OpenCores
URL https://opencores.org/ocsvn/next186/next186/trunk

Subversion Repositories next186

[/] [next186/] [trunk/] [Next186_CPU.v] - Rev 20

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////////////////
//
// This file is part of the Next186 project
// http://opencores.org/project,next186
//
// Filename: Next186_CPU.v
// Description: Implementation of 80186 instruction compatible CPU
// Version 1.0
// Creation date: 24Mar2011 - 07Jun2011
//
// Author: Nicolae Dumitrache 
// e-mail: ndumitrache@opencores.org
//
/////////////////////////////////////////////////////////////////////////////////
// 
// Copyright (C) 2011 Nicolae Dumitrache
// 
// This source file may be used and distributed without 
// restriction provided that this copyright statement is not 
// removed from the file and that any derivative work contains 
// the original copyright notice and the associated disclaimer.
// 
// This source file is free software; you can redistribute it 
// and/or modify it under the terms of the GNU Lesser General 
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any 
// later version. 
// 
// This source is distributed in the hope that it will be 
// useful, but WITHOUT ANY WARRANTY; without even the implied 
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
// PURPOSE. See the GNU Lesser General Public License for more 
// details. 
// 
// You should have received a copy of the GNU Lesser General 
// Public License along with this source; if not, download it 
// from http://www.opencores.org/lgpl.shtml 
// 
///////////////////////////////////////////////////////////////////////////////////
//
// Comments:
// This project was developed and tested on a XILINX Spartan3AN board.
//
//	Next186 processor features:
//		All 80186 intstructions are implemented according with the 80186 specifications (excepting ENTER instruction, 
//		which uses always 0 as the second parameter - level).
//		Designed with 2 buses: 16bit/20bit data/data_address and 48bit/20bit instruction/instruction_address.
//		This allows most instructions to be executed in one clock cycle.
//		In order to couple the CPU unit with a single bus, these sepparate data/instruction buses must be multiplexed by
//		a dedicated bus interface unit (BIU).
//		It is able to execute up to 40Mips on Spartan XC3S700AN speed grade -4, performances comparable with a 486 CPU.
//		Small size, the CPU + BIU requires ~25%  or 1500 slices - on Spartan XC3S700AN
// 
//	16May2012 - fixed REP CMPS/SCAS bug when interrupted on the <equal> item
// 23Dec2012 - fixed DIV bug (exception on sign bit)
// 27Feb2013 - fixed MUL/IMUL 8bit flags bug
// 03Apr2013 - fix RET n alignment bug
// 04Apr2013 - fix TRAP interrupt acknowledge
// 12Apr2013 - fix IDIV when Q=0
// 16May2013 - fix PUSHA SP pushed stack value, which should be the one before PUSHA
// 25May2013 - generate invalid opcode exception for MOV FS and GS 
// 08Sep2016 - separate port address (PORT_ADDR)
// 15Sep2017 - implemented SALC undocumented instruction
///////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
 
module Next186_CPU(
    output [20:0]ADDR,			// mem address
	 output [15:0]PORT_ADDR,	// port address
    input [15:0]DIN,		// mem/port data in
    output [15:0]DOUT,	// mem data out
    output [15:0]POUT,	// port data out
	 input CLK,
	 input CE,
	 input INTR,
	 input NMI,
	 input RST,
	 output reg MREQ,
	 output reg IORQ,
	 output reg INTA,
	 output reg WR,
	 output reg WORD,
	 output LOCK,
	 output [20:0]IADDR,
	 input [47:0]INSTR,
	 output reg IFETCH,
	 output FLUSH,
	 output reg [2:0]ISIZE,
	 output reg HALT
    );
 
// connections	
	wire [15:0]RA;
	wire [15:0]RB;
	wire [15:0]TMP16;
	wire [15:0]SP;
	wire [15:0]IP;
	wire [15:0]AX;
	wire [15:0]BX;
	wire [15:0]BP;
	wire [15:0]SI;
	wire [15:0]DI;
	wire [15:0]DX;
	wire [15:0]FLAGS;
	wire [15:0]FIN;
	wire [15:0]ALUOUT;
	wire [15:0]ALUOUTA;
	wire [15:0]AIMM1;
	reg [15:0]DIMM1;
	wire [15:0]RS;
	wire [15:0]ADDR16;
	wire [15:0]CS;
	wire ALUCONT;
	wire NULLSHIFT;
	wire [1:0]CXZ;
	wire COUT; // adder carry out
	wire DIVEXC; // exit carry for unsigned DIV 
 
// Registers
	reg [7:0]FETCH[5:0];
	reg [6:0]STAGE = 0;
	reg [5:0]CPUStatus = 0;	//1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=LOCK
	reg TZF = 0, TLF = 0;
	reg SRST = 0;
	reg SNMI = 0, FNMI = 0;
	reg SINTR = 0;
	reg [15:0]CRTIP;	// current instruction ptr (used by interrupts)
	reg DIVQSGN;
	reg RDIVEXC;
 
// control	
	reg [2:0]RASEL;
	reg [2:0]RBSEL;
	reg BASEL;
	reg [1:0]BBSEL;
	reg [1:0]RSSEL;
	reg [4:0]WE; // 4=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
	reg [4:0]ALUOP;
	reg [3:0]EAC;
	reg [1:0]DISEL;
	reg [1:0]ISEL;
	reg ASEL;
	reg AEXT;
	reg DEXT;
	reg [1:0]DOSEL;
	reg IPWSEL;
	reg [5:0]status;	//1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=lock
	reg NOBP;
	reg ALUSTAGE;	// inc STAGE with 2
	reg DIVSTAGE;  // inc STAGE with 4
	reg DISP16;
	reg DECCX;
	reg IRQ;
	reg [2:0]IRQL;
	reg REPINT;
	reg [5:0]ICODE1 = 23;
	reg NULLSEG;
	reg DIVOP;
	reg DIVIRQ;
	reg AAMIRQ;
	reg RCOUT;
 
// signals
//	assign IORQ = &EAC;
	assign LOCK = CPUStatus[5];
	assign FLUSH = ~IPWSEL || (ISIZE == 3'b000);
	assign PORT_ADDR = FETCH[0][3] ? DX : {8'h00, FETCH[1]};
	wire [15:0]IPADD = ISIZE == 3'b000 ? CRTIP : IP + ISIZE;
	wire [15:0]IPIN = IPWSEL ? IPADD : ALUOUTA;
	wire [1:0]MOD = FETCH[1][7:6];
	wire [2:0]REG = FETCH[1][5:3];
	wire [2:0]RM  = FETCH[1][2:0];
	wire USEBP = RM[1] && ~&RM;
	wire POP = {EAC[3], EAC[1:0]} == 3'b101;
	wire [15:0]ADDR16_SP = POP ? SP : ADDR16;
	wire [1:0]WBIT = {WORD | RASEL[2], WORD | !RASEL[2]};
	wire [1:0]ISELS = {DISP16 | AEXT, DISP16 | ~AEXT};
	wire [2:0]ISIZES = DISP16 ? 4 : AEXT ? 3 : 2;
	reg  [2:0]ISIZEW;
	reg  [2:0]ISIZEI;	// ise imm
	wire [1:0]WRBIT = WR ? 2'b00 : WBIT;
	wire RCXZ = CPUStatus[4] && ~|CXZ;
	wire NRORCXLE1 = ~CPUStatus[4] || ~CXZ[1];
	wire [7:0]JMPC = {(FLAGS[7] ^ FLAGS[11]) | FLAGS[6], FLAGS[7] ^ FLAGS[11], FLAGS[2], FLAGS[7], FLAGS[0] | FLAGS[6], FLAGS[6], FLAGS[0], FLAGS[11]};
	wire [3:0]LOOPC = {CXZ != 2'b00, CXZ == 2'b01, CXZ == 2'b01 || !FLAGS[6], CXZ == 2'b01 || FLAGS[6]};
	wire IDIV = FETCH[0][1] & FETCH[1][3];
	wire DIVRSGN = (WORD ? FETCH[3][7] : FETCH[2][7]) & IDIV;
	wire DIVSGN = DIVQSGN ^ DIVRSGN;
	wire DIVEND = FETCH[0][0] ? STAGE[6] : STAGE[5];
	wire DIVC = ((COUT & ~RDIVEXC) ^ ~DIVRSGN);
	wire QSGN = (WORD ? DX[15] : AX[15]) & IDIV;
// interrupts
	wire SAMPLEINT = ~(WE[2] & RASEL[1:0] == 2'b10) & ~status[2] & ~status[4] & ~status[5]; // not load SS, no prefix
	wire NMIACK = SNMI & ~FNMI;	// NMI acknowledged
	wire INTRACK = FLAGS[9] & (~WE[4] | FIN[9]) & SINTR;			// INTR acknowledged (IF and not CLI in progress)
	wire IACK = IRQ | (SAMPLEINT & (NMIACK | INTRACK | (~HALT & FLAGS[8]))); // interrupt acknowledged (fixed 04Apr2013)
	reg CMPS;	// early EQ test for CMPS
	reg SCAS;   // early EQ test for SCAS
 
	Next186_Regs REGS (
    .RASEL(RASEL),
    .RBSEL(RBSEL), 
    .BASEL(BASEL), 
    .BBSEL(BBSEL), 
    .RSSEL(RSSEL), 
    .DIN(DIN),
	 .ALUOUT(ALUOUT),
	 .ADDR16(ADDR16),
	 .DIMM(DEXT ? {{8{DIMM1[7]}}, DIMM1[7:0]} : DIMM1),
    .WE(WE), 
	 .IFETCH(IFETCH),
    .RA(RA), 
    .RB(RB), 
    .TMP16(TMP16), 
    .SP(SP), 
    .IP(IP),
	 .AX(AX),
	 .BX(BX),
	 .BP(BP),
	 .SI(SI),
	 .DI(DI),
	 .DX(DX),
	 .RS(RS),
	 .FIN(FIN),
	 .FOUT(FLAGS),
	 .DISEL(DISEL),
	 .WORD(WORD | &DISEL),
	 .IPIN(IPIN),
	 .CLK(CLK),
	 .CLKEN(CE),
	 .CS(CS),
	 .INCSP(POP),
	 .CXZ(CXZ),
	 .DECCX(DECCX),
	 .DIVOP(DIVOP),
	 .DIVEND(DIVEND),
	 .DIVSGN(DIVSGN),
	 .DIVC(DIVC),
	 .DIVEXC(DIVEXC)
    );
 
	Next186_ALU ALU16 (
	 .RA(DOSEL == 2'b01 ? IPADD : RA), 
	 .RB(RB),
	 .TMP16(TMP16),
	 .FETCH23({FETCH[3], FETCH[2]}),
	 .FIN(FLAGS), 
	 .FOUT(FIN),
	 .ALUOP(ALUOP),
	 .EXOP(FETCH[1][5:3]),
	 .FLAGOP(FETCH[0][3:0]),
	 .ALUOUT(ALUOUT),
	 .ALUOUTA(ALUOUTA),
	 .WORD(WORD),
	 .ALUCONT(ALUCONT),
	 .NULLSHIFT(NULLSHIFT),
	 .STAGE(STAGE[2:0]),
	 .INC2(&DISEL),	// when DISEL == 2'b11, inc/dec value is 2 if WORD and 1 if ~WORD
	 .COUT(COUT),
	 .CLK(CLK)
	 );
 
	Next186_EA EA (
    .SP(SP), 
    .BX(BX), 
    .BP(NOBP ? 16'h0000 : BP), 
    .SI(SI), 
    .DI(DI), 
	 .TMP16(TMP16),
	 .AL(AX[7:0]),
    .AIMM(AEXT ? {{8{AIMM1[7]}}, AIMM1[7:0]} : (DISP16 ? AIMM1 : 16'h0000)), 
    .ADDR16(ADDR16),
	 .EAC(EAC)
    );
 
	 assign POUT = DOSEL[0] ? AX : TMP16;
	 assign DOUT = DOSEL[1] ? POUT : DOSEL[0] ? IPADD : ALUOUT;
	 assign ADDR = {{NULLSEG ? 16'h0000 : RS} + {5'b00000, ADDR16_SP[15:4]}, ADDR16_SP[3:0]};
	 assign IADDR = {CS + {5'b00000, IPIN[15:4]}, IPIN[3:0]};
	 assign AIMM1 = ASEL ? {FETCH[3], FETCH[2]} : {FETCH[2], FETCH[1]};
 
	 always @(posedge CLK)
		if(CE) begin
			if(SRST) begin		// reset
//				FETCH[0] <= 8'h0f;
				FETCH[0][0] <= 1'b1; // for word=1
				ICODE1 <= 54;
				FETCH[5][1:0] <= 2'b01;	// RESET
				STAGE <= 4'b1000;
			end else begin
				if(IACK & (IFETCH | HALT | REPINT)) begin // interrupt sampled and acknowledged
					FETCH[0][1:0] <= 2'b11;	
					ICODE1 <= 54;
					STAGE <= 4'b1000;
					FETCH[5][2:0] <= {HALT, 2'b00};
					if(IRQ) FETCH[2] <= IRQL != 3'b010 ? {5'b00000, IRQL} : FETCH[1];
					else if(NMIACK) begin
						FETCH[2] <= 8'h02;
						FNMI <= 1'b1;
					end else if(INTRACK) FETCH[5][1:0] <= 2'b10;
					else FETCH[2] <= 8'h01;	// trap
				end else if(IFETCH) begin		// no interrupt, fetch
					FETCH[5] <= INSTR[47:40];
					FETCH[4] <= INSTR[39:32];
					FETCH[3] <= INSTR[31:24];
					FETCH[2] <= INSTR[23:16];
					FETCH[1] <= INSTR[15:8];
					FETCH[0] <= INSTR[7:0];
					STAGE <= 0;
					CPUStatus[5:0] <= status[5:0];
					ICODE1 <= ICODE(INSTR[7:0]);
				end else begin		// no interrupt, no fetch
					STAGE <= STAGE + {DIVSTAGE, ALUSTAGE} + 1'b1; 
					if(&DOSEL) {FETCH[3], FETCH[2]} <= |DISEL ? DIN : RB;
					TZF <= FIN[6];		// zero flag for BOUND
					TLF <= FIN[7] != FIN[11];	// less flag for BOUND
				end
			end
			if(IFETCH & ~status[2] & ~status[4] & ~status[5]) CRTIP <= IPIN; // no prefix
			SRST <= RST;				// level detection RST
			SINTR <= INTR;				// level detection INTR
			if(NMI) SNMI <= 1'b1;	// edge detection NMI
			else if(FNMI) begin
				SNMI <= 1'b0;
				FNMI <= 1'b0;
			end
			if(~|STAGE[1:0]) DIVQSGN <= QSGN;
			RDIVEXC <= DIVOP & DIVEXC & ~IDIV; // bit 8/16 for unsigned DIV
			CMPS <= (~FETCH[0][0] | (FETCH[3] == DIN[15:8])) & (FETCH[2] == DIN[7:0]);	// early EQ test for CMPS
			SCAS <= (~FETCH[0][0] | (AX[15:8] == DIN[15:8])) & (AX[7:0] == DIN[7:0]);  // early EQ test for SCAS
			RCOUT <= COUT;
			DIVIRQ <= ~|STAGE[6:3] & DIVC & (~STAGE[2] | (~DIVSGN & IDIV)) & (&STAGE[1:0]); // DIV stage4, div loop
			AAMIRQ <= ~|STAGE[6:2] & DIVC & (STAGE[1:0] == 2'b01); // AAM stage2, div
		end
 
	always @(ISEL, FETCH[0], FETCH[1], FETCH[2], FETCH[3], FETCH[4], FETCH[5])
		case(ISEL)
			2'b00: DIMM1 = {FETCH[2], FETCH[1]};
			2'b01: DIMM1 = {FETCH[3], FETCH[2]};
			2'b10: DIMM1 = {FETCH[4], FETCH[3]};
			2'b11: DIMM1 = {FETCH[5], FETCH[4]};
		endcase
 
	always @(FETCH[0], WORD, DISP16, AEXT) begin
		case({WORD, DISP16, AEXT})
			3'b000: ISIZEW = 3;
			3'b001, 3'b100: ISIZEW = 4;
			3'b010, 3'b101: ISIZEW = 5;
			default: ISIZEW = 6;
		endcase
		case({FETCH[0][1:0] == 2'b01, DISP16, AEXT})
			3'b000: ISIZEI = 3;
			3'b001, 3'b100: ISIZEI = 4;
			3'b110: ISIZEI = 6;
			default: ISIZEI = 5;
		endcase
	end
 
	 always @(FETCH[0], FETCH[1], FETCH[2], FETCH[3], FETCH[4], FETCH[5], MOD, REG, RM, CPUStatus, USEBP, NOBP, RASEL, ISIZEI, TLF, EAC, RCOUT, DIVEND, DIVIRQ, AAMIRQ, QSGN, CMPS, SCAS,
				 WBIT, ISIZES, ISELS, WRBIT, ISIZEW, STAGE, NULLSHIFT, ALUCONT, FLAGS, CXZ, RCXZ, NRORCXLE1, TZF, JMPC, LOOPC, ICODE1, DIVQSGN, DIVSGN, DIVRSGN, FIN, IDIV, AX) begin
		WORD = FETCH[0][0];
		BASEL = FETCH[0][1] | &MOD;
		RASEL = FETCH[0][1] ? REG : RM; // destination
		BBSEL = {1'b0, !FETCH[0][1] | &MOD};
		RBSEL = FETCH[0][1] ? RM : REG; // source
		RSSEL = CPUStatus[2] ? CPUStatus[1:0] : (USEBP && !NOBP ? 2'b10 : 2'b11);
		WE = 5'b00000;		// 5=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
		ALUOP = 5'bxxxxx;
		EAC = {1'b0, RM};
		DISEL = 2'b01;		// ALU
		ISEL = 2'bxx;
		ASEL = 1'bx;
		AEXT = MOD == 2'b01;
		DEXT = 1'b0;
		DOSEL = 2'b00;	// ALU	 
		MREQ = 1'b1;
		WR = 1'b0;
		ISIZE = 3'bxxx;
		IPWSEL = 1'b1;		// IP + ISIZE
		IFETCH = 1'b1;
		IORQ = 1'b0;
		status = 6'b00x0xx;
 
		DISP16 = MOD == 2'b10 || NOBP;
		NOBP = {MOD, RM} == 5'b00110;
		HALT = 1'b0;
		INTA = 1'b0;
		ALUSTAGE = 1'b0;
		DIVSTAGE = 1'b0;
		DECCX = 1'b0;
		IRQ = 1'b0;
		IRQL = 3'b110;	// unused opcode
		REPINT = 1'b0;
		NULLSEG = 1'b0;
		DIVOP = 1'b0;
 
		case(ICODE1) // one hot synthesis
// --------------------------------  mov R/M to/from R/SR  --------------------------------
			0: begin				
				if(FETCH[0][2]) WORD = 1'b1;
				if(FETCH[0][2:1] == 2'b10) BBSEL = 2'b11; // RB = SR
				ALUOP = 31;	// PASS B
				DISEL = {1'b0, &MOD};
				ASEL = 1'b1;
				IRQ = FETCH[0][2] & FETCH[1][5];	// 25May2013 - generate invalid opcode exception for MOV FS and GS						
				MREQ = ~&MOD & ~IRQ;
				WR = MREQ & !FETCH[0][1];
				WE = WR | IRQ ? 5'b00000 : &FETCH[0][2:1] ? {2'b00, FETCH[1][4:3] != 2'b01, 2'b00} : {3'b000, WBIT};		// RSSEL, RASEL_HI/RASEL_LO
				ISIZE = IRQ ? 0 : ISIZES;
			end
// --------------------------------  mov IMM to R/M  --------------------------------
			1: begin	
				RASEL = RM; // destination
				BBSEL = 2'b10;
				ALUOP = 31;	// PASS B
				ISEL = ISELS;
				ASEL = 1'b1;
				MREQ = ~&MOD;
				WR = MREQ;
				WE[1:0] = WRBIT;		// RASEL_HI/RASEL_LO
				ISIZE = ISIZEW;
			end
// --------------------------------  mov IMM to R --------------------------------
			2: begin	
				WORD = FETCH[0][3];
				RASEL = FETCH[0][2:0]; // destination
				BBSEL = 2'b10;				// imm
				WE[1:0] = WBIT;		// RASEL_HI/RASEL_LO
				ALUOP = 31;	// PASS B
				ISEL = 2'b00;
				MREQ = 1'b0;
				ISIZE = WORD ? 3 : 2;
			end
// --------------------------------  mov mem to/from ACC --------------------------------
			3: begin
				RASEL = 0; // ACC
				BBSEL = 2'b01;		// reg
				RBSEL = 0; // ACC
				ALUOP = 31;	// PASS B
				EAC = 4'b0110;
				DISEL = 2'b00;
				ASEL = 1'b0;
				AEXT = 1'b0;
				WR = FETCH[0][1];
				WE[1:0] = WRBIT;		// IP, RASEL_HI/RASEL_LO
				ISIZE = 3;
				NOBP = 1'b1;
			end
// --------------------------------  segment override prefix --------------------------------
			4: begin	
				status = {CPUStatus[5:3], 1'b1, FETCH[0][4:3]};
				MREQ = 1'b0;
				ISIZE = 1;
			end
// --------------------------------  rep prefix --------------------------------
			5: begin
				status = {CPUStatus[5], 1'b1, FETCH[0][0], CPUStatus[2:0]};
				MREQ = 1'b0;
				ISIZE = 1;
			end
// --------------------------------  lock prefix --------------------------------
			6: begin
				status = {1'b1, CPUStatus[4:0]};
				MREQ = 1'b0;
				ISIZE = 1;
			end
// --------------------------------  FF block --------------------------------
			7:	begin
				ISIZE = ISIZES;
				case({FETCH[0][0], REG})
		// --------------------------------  push R/M --------------------------------
					4'b1110:
						if(!(&MOD || STAGE[0])) begin	// stage1, read data in TMP16
							WE[3] = 1'b1;		// TMP16
							DISEL = 2'b00;
							ASEL = 1'b1;
							IFETCH = 1'b0;
						end else begin		// stage2, push R/TMP16
							RASEL = 3'b100;		// write SP
							RSSEL = 2'b10;			// SS
							ALUOP = 31;	// PASS B
							WE[1:0] = 2'b11;		// RASEL_HI/RASEL_LO
							EAC = 4'b1000;			// SP - 2
							DISEL = 2'b10;			// ADDR
							WR = 1'b1;
						end
		// --------------------------------  inc/dec R/M --------------------------------
					4'b0000, 4'b1000, 4'b0001, 4'b1001: begin	
						ASEL = 1'b1;
						if(!(&MOD || STAGE[0])) begin	// stage1, load op from memory in TMP16
							WE[3] = 1'b1;		// TMP16
							DISEL = 2'b00;			// DIN
							IFETCH = 1'b0;
						end else begin						// stage2, execute and write		
							BASEL = &MOD;
							RASEL = RM; 			// destination
							ALUOP = {2'b01, FETCH[1][5:3]};
							MREQ = ~BASEL;
							WR = MREQ;
							WE = {3'b100, WRBIT};		// flags, IP, RASEL_HI, RASEL_LO
						end
					end
		// --------------------------------  call/jmp near R/M --------------------------------
					4'b1010, 4'b1100: begin
						if(!STAGE[0] && ~&MOD) begin	// stage1, load op in TMP16
							ASEL = 1'b1;
							WE[3] = 1'b1;		// TMP16
							DISEL = 2'b00;			// DIN
							IFETCH = 1'b0;
						end else begin 		// stage2, push IP, jump
							RASEL = 3'b100; 	// write SP
							RSSEL = 2'b10;		// SS
							ALUOP = 31;	// PASS B
							EAC = 4'b1000;		// SP - 2
							DISEL = 2'b10;		// ADDR
							DOSEL = 2'b01;	// IP	 
							MREQ = REG[1];
							WR = MREQ;
							WE[1:0] = {WR, WR};
							IPWSEL = 1'b0;		// ALU
						end
					end
		// --------------------------------  call/jmp far R/M --------------------------------
					4'b1011, 4'b1101: begin
						ALUOP = 31;				// PASS B
						IRQ = &MOD;
						case({STAGE[1:0], REG[1]})
							3'b001: begin	// stage1, push CS
								RASEL = 3'b100;		// write SP
								BBSEL = 2'b11;
								RBSEL = 3'b001; 		// CS
								RSSEL = 2'b10;			// SS
								EAC = 4'b1000;			// SP - 2
								DISEL = 2'b10;			// ADDR
								MREQ = ~IRQ;
								WR = MREQ;
								IFETCH = IRQ;
								WE[1:0] = IRQ ? 2'b00 : 2'b11;			// RASEL_HI/RASEL_LO
								ISIZE = 0;
							end
							3'b011, 3'b000: begin	// stage2, read offset in FETCH, ADDR16 in TMP16
								RASEL = 3'b100; 		// SP	- write SP to SP for getting ADDR16 to TMP16
								BBSEL = 2'b01;
								RBSEL = 3'b100; 		// SP
								WE[3:0] = IRQ ? 4'b0000 : 4'b1011;			// TMP16, RASEL_HI, RASEL_LO
								ASEL = 1'b1;
								DOSEL = 2'b11;			// load FETCH with DIN
								IFETCH = IRQ;
								MREQ = ~IRQ;
								ISIZE = 0;
							end 
							3'b101, 3'b010: begin 	// stage3, read CS
								RASEL = 3'b001; 		// CS
								WE[2] = 1'b1;			// RSSEL
								EAC = 4'b1011;			// TMP16 + 2
								DISEL = 2'b00;			// DIN
								IFETCH = 1'b0;
							end
							3'b111, 3'b100: begin	// stage4, push IP, jump
								RASEL = 3'b100; 	// write SP
								BBSEL = 2'b10;		// imm
								RSSEL = 2'b10;		// SS
								EAC = 4'b1000;		// SP - 2
								DISEL = 2'b10;		// ADDR
								DOSEL = 2'b01;		// IP	 
								ISEL = 2'b01;
								MREQ = REG[1];
								WR = MREQ;
								WE[1:0] = {WR, WR};
								IPWSEL = 1'b0;		// ALU
							end
						endcase
					end
		// --------------------------------  bad opcode --------------------------------
					default: begin		
						MREQ = 1'b0;
						IRQ = 1'b1;
						ISIZE = 0;
					end
				endcase
			end
// --------------------------------  push R/SR --------------------------------
			8: begin
				WORD = 1'b1;
				RASEL = 3'b100;		// write SP
				BBSEL = {~FETCH[0][6], 1'b1};
				RBSEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // source
				RSSEL = 2'b10;			// SS
				EAC = 4'b1000;			// SP - 2
				DISEL = 2'b10;			// ADDR
				WE[1:0] = 2'b11;		// RASEL_HI/RASEL_LO
				ALUOP = 31;				// PASS B
				WR = 1'b1;
				ISIZE = 1;
			end
// --------------------------------  push Imm --------------------------------
			9: begin		
				WORD = 1'b1;
				RASEL = 3'b100;		// write SP
				BBSEL = 2'b10;			// imm
				RSSEL = 2'b10;			// SS
				WE[1:0] = 2'b11;		// RASEL_HI/RASEL_LO
				ALUOP = 31;				// PASS B
				EAC = 4'b1000;			// SP - 2
				DISEL = 2'b10;			// ADDR
				ISEL = 2'b00;
				DEXT = FETCH[0][1];
				WR = 1'b1;
				ISIZE = FETCH[0][1] ? 2 : 3;
			end
// --------------------------------  pusha --------------------------------
			10: begin
				WORD = 1'b1;
				RASEL = 3'b100;		// write SP
				RBSEL = STAGE[2:0];  // source
				RSSEL = 2'b10;			// SS
				ALUOP = 31;				// PASS B
				EAC = 4'b1000;			// SP - 2
				DISEL = 2'b10;			// ADDR
				WR = 1'b1;
				ISIZE = 1;
				IFETCH = STAGE[2:0] == 3'b111;
				WE[1:0] = 2'b11;					// RASEL_HI, RASEL_LO
				BASEL = STAGE[1:0] == 2'b00;	// 16May2013 - fix PUSHA SP pushed stack value, which should be the one before PUSHA
				BBSEL[0] = STAGE[2:0] != 3'b100;	// SP stage
			end
// --------------------------------  pop R/M --------------------------------
			11: 			
				case(REG)
					3'b000: begin
						ISIZE = ISIZES;
						if(!STAGE[0]) begin	// pop TMP16/REG
							RASEL = RM; 		// destination
							RSSEL = 2'b10;			// SS
							EAC = 4'b1001;			// SP
							DISEL = 2'b00;			// DIN
							IFETCH = &MOD;
							WE[3:0] = IFETCH ? 4'b0011 : 4'b1000;		// TMP16, RASEL_HI, RASEL_LO
						end else begin			// R/M <- TMP16
							RASEL = RM; // destination
							BBSEL = 2'b00;			// TMP
							ALUOP = 31;				// PASS B
							ASEL = 1'b1;
							MREQ = ~&MOD;
							WR = MREQ;
							WE[1:0] = WR ? 2'b00 : 2'b11;		// RASEL_HI, RASEL_LO
						end
					end
					default:	begin		// bad opcode
						MREQ = 1'b0;
						ISIZE = 0;
						IRQ = 1'b1;						
					end
				endcase
// --------------------------------  pop R / SR --------------------------------
			12: begin	
				WORD = 1'b1;
				RASEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // destination
				RSSEL = 2'b10;			// SS
				WE[2:0] = FETCH[0][6] ? 3'b011 : 3'b100;		// RSSEL, RASEL_HI, RASEL_LO
				EAC = 4'b1001;			// SP
				DISEL = 2'b00;			// DIN
				ISIZE = 1;
			end
// --------------------------------  popa --------------------------------
			13: begin
				RASEL = ~STAGE[2:0]; // destination
				RSSEL = 2'b10;			// SS
				EAC = 4'b1001;			// SP
				DISEL = 2'b00;			// DIN
				ISIZE = 1;
				IFETCH = &STAGE[2:0];
				WE[1:0] = {STAGE[2:0] == 3'b011 ? 2'b00 : 2'b11};		// IP, RASEL_HI, RASEL_LO (skip SP)
			end
// --------------------------------  xchg R with R/M/Acc --------------------------------
			14: begin
				WORD = FETCH[0][0] | FETCH[0][4];
				ASEL = 1'b1;
				MREQ = ~&MOD && !FETCH[0][4];
				ALUOP = 31;				// PASS B
				ISIZE = FETCH[0][4] ? 1 : ISIZES;
				if(!STAGE[0]) begin		// stage1, R/M/Acc -> REG -> TMP16
					BASEL = 1'b1;
					RASEL = FETCH[0][4] ? FETCH[0][2:0] : REG; // destination
					BBSEL = 2'b01;		// reg
					RBSEL = FETCH[0][4] ? 3'b000 : RM; // source
					DISEL = {1'b0, !MREQ};		
					WE[1:0] = WBIT;		// RASEL_HI, RASEL_LO
					IFETCH = ~|FETCH[0][2:0]; // nop
				end else begin 		// stage2, TMP16 -> R/M/Acc
					RASEL = FETCH[0][4] ? 3'b000 : RM; // destination
					BBSEL = 2'b00;		// TMP16
					WR = MREQ;
					WE[1:0] = WRBIT;		// RASEL_HI, RASEL_LO
				end
			end
// --------------------------------  in --------------------------------
			15:	begin
				RASEL = 3'b000; // AX/AL
				WE[1:0] = {WORD, 1'b1};		// RASEL_HI, RASEL_LO
				DISEL = 2'b00;	//DIN
				MREQ = 1'b0;
				ISIZE = FETCH[0][3] ? 1 : 2;
				IORQ = 1'b1;
//				EAC = 4'b1111;
//				NULLSEG = 1'b1;
			end
// --------------------------------  out --------------------------------
			16:	begin
				DOSEL = 2'b11;	// AX
				MREQ = 1'b0;
				WR = 1'b1;
				ISIZE = FETCH[0][3] ? 1 : 2;
				IORQ = 1'b1;
//				EAC = 4'b1111;
//				NULLSEG = 1'b1;
			end
// --------------------------------  xlat --------------------------------
			17: begin
				WORD = 1'b0;
				RASEL = 3'b000; 	// AL
				WE[0] = 1'b1;		// RASEL_LO
				EAC = 4'b1010;		// XLAT
				DISEL = 2'b00;		// DIN 
				ISIZE = 1;
				NOBP = 1'b1;	// for RSSEL
			end
// --------------------------------  lea --------------------------------
			18: begin
				RASEL = REG; 			// destination
				WE[1:0] = {&MOD ? 2'b00 : 2'b11};		// RASEL_HI, RASEL_LO
				DISEL = 2'b10;			// EA
				ASEL = 1'b1;
				MREQ = 1'b0;
				ISIZE = ISIZES;
			end
// --------------------------------  lds, les --------------------------------
			19: begin
				WORD = 1'b1;
				DISEL = 2'b00;			// DIN
				ASEL = 1'b1;
				if(!STAGE[0]) begin		// stage1, load offset
					RASEL = REG; 			// destination
					IFETCH = &MOD;			// bad opcode
					IRQ = IFETCH;
					ISIZE = 0;
					WE[3:0] = {2'b10, IFETCH ? 2'b00 : 2'b11};		// TMP16, RASEL_HI, RASEL_LO
				end else begin				// stage2, load segment
					RASEL = FETCH[0][0] ? 3'b011 : 3'b000; // ds/es
					WE[2] = 1'b1;			// RSSEL
					EAC = 4'b1011;			// TMP16 + 2
					ISIZE = ISIZES;
				end
			end
// --------------------------------  lahf, sahf --------------------------------
			20: begin
				WORD = 1'b0;
				RASEL = 3'b100; 		// AH
				WE = {!FETCH[0][0], 2'b00, FETCH[0][0], 1'b0};		// FLAGS, IP, RASEL_HI
				ALUOP = FETCH[0][0] ? 30 : 31;			// PASS/STORE FLAGS
				MREQ = 1'b0;
				ISIZE = 1;
			end
// --------------------------------  pushf --------------------------------
			21: begin
				WORD = 1'b1;
				RASEL = 3'b100;		// write SP
				RSSEL = 2'b10;			// SS
				WE[1:0] = 2'b11;			
				ALUOP = 30;				// pass flags
				EAC = 4'b1000;			// SP - 2
				DISEL = 2'b10;			// ADDR
				WR = 1'b1;
				ISIZE = 1;
			end
// --------------------------------  popf --------------------------------
			22: begin
				ISIZE = 1;
				IFETCH = STAGE[0];
				if(!STAGE[0]) begin	// stage1, pop TMP16
					RSSEL = 2'b10;			// SS
					WE[3] = 1'b1;			// TMP16
					EAC = 4'b1001;			// SP
					DISEL = 2'b00;
				end else begin			// stage2, TMP16 to FLAGS
					BASEL = 1'b0;
					WE[4] = 1'b1;			// flags
					ALUOP = 31;				// store flags
					MREQ = 1'b0;
				end
			end
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
			23: begin									
				ASEL = 1'b1;
				if(!(&MOD || STAGE[0])) begin	// stage1, load op from memory in TMP16
					WE[3] = 1'b1;		// TMP16
					DISEL = 2'b00;			// DIN
					IFETCH = 1'b0;
				end else begin						// stage2, execute and write			
					ALUOP = {2'b00, FETCH[0][2] ? 3'b100 : FETCH[0][5:3]};	// test = and
					MREQ = ~&MOD & ~|FETCH[0][2:1] & ~&FETCH[0][5:3];		// no cmp or test
					WR = MREQ;
					WE = {3'b100, WR | &FETCH[0][5:3] | FETCH[0][2] ? 2'b00 : WBIT};		// flags, RASEL_HI, RASEL_LO
					ISIZE = ISIZES;
				end
			end
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
			24: begin
				ASEL = 1'b1;
				if(!(&MOD || STAGE[0])) begin	// stage1, load op from memory in TMP16
					WE[3] = 1'b1;			// TMP16
					DISEL = 2'b00;			// DIN
					IFETCH = 1'b0;
				end else begin						// stage2, execute and write		
					BASEL = &MOD;
					RASEL = RM;
					BBSEL = 2'b10;			// imm
					ALUOP = {2'b00, FETCH[1][5:3]};
					ISEL = ISELS;
					DEXT = FETCH[0][1];
					MREQ = ~BASEL & ~&FETCH[1][5:3];
					WR = MREQ;
					WE = {3'b100, WR  | &FETCH[1][5:3]? 2'b00 : WBIT};		// flags, RASEL_HI, RASEL_LO
					ISIZE = ISIZEI;
				end
			end
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
			25: begin // test
				BASEL = 1'b1;
				RASEL = 3'b000; 	// acc
				BBSEL = 2'b10;					// imm
				WE = {3'b100, &FETCH[0][5:3] | FETCH[0][7] ? 2'b00 : WBIT};		// flags, RASEL_HI, RASEL_LO
				ALUOP = {2'b00, FETCH[0][7] ? 3'b100 : FETCH[0][5:3]};
				ISEL = 2'b00;
				MREQ = 1'b0;
				ISIZE = WORD ? 3 : 2;
			end
// --------------------------------  inc/dec R16 --------------------------------
			26: begin
				WORD = 1'b1;
				BASEL = 1'b1;
				RASEL = FETCH[0][2:0]; // destination
				WE = 5'b10011;		// flags, RASEL_HI, RASEL_LO
				ALUOP = {2'b01, FETCH[0][5:3]};
				MREQ = 1'b0;
				ISIZE = 1;
			end
// --------------------------------  test/???/not/neg/mul/imul/div/idiv --------------------------------
			27: begin
				ASEL = 1'b1;
				case(REG)					
					3'b000: begin		// TEST R/M with Imm
						if(!(&MOD || |STAGE[1:0])) begin	// stage1, load op from memory in TMP16
							DISEL = 2'b00;		
							WE[3] = 1'b1;					// mem in TMP16
							IFETCH = 1'b0;
						end else begin
							BASEL = &MOD;
							RASEL = RM; 	// destination
							BBSEL = 2'b10;			// imm
							ALUOP = 5'b00100;		// AND
							ISEL = ISELS;
							MREQ = 1'b0;
							WE[4] = 1'b1;			// flags
							ISIZE = ISIZEW;
						end
					end
					3'b010, 3'b011: begin	// NOT/NEG R/M
						if(!(&MOD || |STAGE[1:0])) begin	// stage1, load op from memory in TMP16
							DISEL = 2'b00;		
							WE[3] = 1'b1;					// mem in TMP16
							IFETCH = 1'b0;
						end else begin
							BASEL = &MOD;
							RASEL = RM; 	// destination
							ALUOP = {2'b01, REG};
							MREQ = ~&MOD;
							WR = MREQ;
							WE = {REG[0], 2'b00, WRBIT};		// flags, RASEL_HI, RASEL_LO
							ISIZE = ISIZES;
						end
					end
					3'b100, 3'b101: begin	// MUL, IMUL
						ISIZE = ISIZES;
						ALUOP = {4'b1000, REG[0]};		// BASEL = FETCH[0][1] = 1
						WE[4] = 1'b1;			// fix MUL/IMUL 8bit flags bug
						case(STAGE[1:0])
							2'b00: begin		// stage1, RA -> TMP16, RB (mem) -> FETCH
								MREQ = ~&MOD;
								DISEL = {1'b0, MREQ};
								RASEL = 3'b000; // AX
								DOSEL = 2'b11;	 
								IFETCH = 1'b0;
							end
							2'b01: begin			// stage2, write AX
								WE[1:0] = 2'b11;	// flags, RASEL_HI, RASEL_LO 
								RASEL = 3'b000;	// AX
								MREQ = 1'b0;
								IFETCH = ~FETCH[0][0];
							end
							2'b10: begin			// stage 2, write DX
								WE[1:0] = 2'b11;	// flags, RASEL_HI, RASEL_LO	
								RASEL = 3'b010;	// DX
								MREQ = 1'b0;
							end
						endcase
					end
					3'b110, 3'b111: begin	// div, idiv
						ISIZE = ISIZES;
						IRQL = 3'b000;	// divide overflow
						MREQ = 1'b0;
						case({DIVEND, STAGE[1:0]})
							3'b000: begin		// stage1, RB (mem) -> FETCH
								MREQ = ~&MOD;
								DISEL = {1'b0, MREQ};
								DOSEL = 2'b11;	 
								IFETCH = 1'b0;
								DIVSTAGE = ~QSGN;
								RASEL = 3'b000; // AX
								ALUOP = 5'b01001;		// DEC
							end
							3'b001: begin	// stage2, pre dec AX
//								WORD = 1'b1;
								RASEL = 3'b000; // AX
								WE[1:0] = 2'b11;		// RASEL_HI, RASEL_LO
								ALUOP = 5'b01001;		// DEC
								IFETCH = 1'b0;
								ALUSTAGE = ~(DIVQSGN && FETCH[0][0] && RCOUT);
							end
							3'b010: begin // stage3, pre dec DX
								RASEL = 3'b010; 	// DX
								WE[1:0] = 2'b11;		// RASEL_HI, RASEL_LO
								ALUOP = 5'b01001;		// DEC
								IFETCH = 1'b0;
							end
							3'b011, 3'b111: begin	// stage4, div loop
								RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
								BBSEL = 2'b10;		// imm
								WE[1:0] = {1'b1, WORD};		// RASEL_HI, RASEL_LO
								ALUOP = {2'b00, DIVSGN ? 3'b000 : 3'b101};	// add/sub
								ISEL = 2'b01;
								DIVSTAGE = ~DIVEND;
								ALUSTAGE = ~DIVEND | ~DIVQSGN;
								DIVOP = 1'b1;
								IRQ = DIVIRQ; //~|STAGE[6:3] & DIVC & (~STAGE[2] | (~DIVSGN & IDIV)); // early overflow for positive quotient
								IFETCH = (DIVEND && ~DIVQSGN && ~DIVRSGN) || DIVIRQ;
							end
							3'b100: begin		// stage5, post inc R
								RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
								WE[1:0] = {1'b1, WORD};		// RASEL_HI, RASEL_LO
								ALUOP = 5'b01000;	// inc
								IFETCH = ~DIVSGN;
							end
							default: begin	// stage6, post inc Q
								RASEL = 3'b000; // AX/AL
								WE[1:0] = {WORD, 1'b1};		// RASEL_HI, RASEL_LO
								ALUOP = 5'b01000;	// inc
//								IRQ = SOUT ^ DIVSGN;	// overflow for negative quotient - fixed 12Apr2013 - IDIV bug when Q=0
								IRQ = ~(FIN[7] | (FETCH[0][0] ? AX[15] : AX[7])); // overflow for negative quotient
							end
						endcase
					end
					default: begin		// bad opcode
						MREQ = 1'b0;
						ISIZE = 0;
						IRQ = 1'b1;
					end
				endcase
			end
// --------------------------------  imul imm --------------------------------
			28: begin
				ASEL = 1'b1;
				if(!STAGE[0]) begin	// stage1, load op from memory (or RA) in TMP16
					RASEL = RM;
					DISEL = 2'b00;			// DIN
					DOSEL = 2'b11;
					ISEL = ISELS;
					DEXT = FETCH[0][1];
					BBSEL = 2'b10;			// imm
					MREQ = ~&MOD;
					WE[3] = MREQ;			// TMP16
					IFETCH = 1'b0;
				end else begin						// stage2, execute and write		
					RASEL = REG;
					ALUOP = 5'b10001;		// imul
					MREQ = 1'b0;
					WE = 5'b10011;		// flags, RASEL_HI, RASEL_LO
					ISIZE = ISIZEI;
				end
			end
// --------------------------------  aad --------------------------------
			29: begin
				MREQ = 1'b0;
				WORD = 1'b0;
				BASEL = 1'b1;
				IFETCH = &STAGE[1:0];
				case(STAGE[1:0])
					2'b00: begin	// stage1, load AH in TMP16, move imm in FETCH
						RASEL = 3'b100;		// AH
						DISEL = 2'b00;			// DIN
						DOSEL = 2'b11;			// write FETCH
						ISEL = 2'b00;			// RB -> FETCH
						BBSEL = 2'b10;			// imm
					end
					2'b01: begin				// stage2, TMP16 <- TMP16 * 10
						ALUOP = 5'b10000;		// mul
						WE[3] = 1'b1;			// TMP16
					end
					2'b10: begin			// stage3, AL <- TMP16 + AL
						RASEL = 3'b000; 	// AL
						BBSEL = 2'b00;		// TMP16
						WE = 5'b10001;		// flags, RASEL_LO
						ALUOP = 5'b00000;	// ADD
					end
					2'b11: begin			// stage4, AH <- 0
						RASEL = 3'b100; 	// AH
						RBSEL = 3'b100; 	// AH
						WE[1] = 1'b1;		// RASEL_HI
						ALUOP = 5'b00101;	// SUB
						ISIZE = 2;
					end
				endcase
			end
// --------------------------------  daa, das, aaa, aas --------------------------------
			30: begin
				WORD = FETCH[0][4];
				RASEL = 3'b000; 	// AX,AL
				WE = {3'b100, FETCH[0][4], 1'b1};		// flags, RASEL_HI, RASEL_LO
				ALUOP = {2'b01, FETCH[0][5:3]};
				MREQ = 1'b0;
				ISIZE = 1;
			end
// --------------------------------  shift/rot --------------------------------
			31: begin	// imm
				ALUOP = {4'b1110, FETCH[0][4:1] != 4'b1000};
				ASEL = 1'b1;
				if(!(&MOD || STAGE[0])) begin	// stage1, load op from memory in TMP16
					WE[3] = 1'b1;			// TMP16
					DISEL = 2'b00;			// DIN
					IFETCH = 1'b0;
				end else begin						// stage2, execute and write		
					BASEL = &MOD && ~|STAGE[2:1];
					RASEL = RM;
					BBSEL = FETCH[0][1] ? 2'b01 : 2'b10; // imm/reg
					RBSEL = 3'b001;		// CL
					ISEL = ISELS;
					IRQ = REG == 3'b110;					
					MREQ = ~&MOD && ~NULLSHIFT && ~ALUCONT && ~IRQ;
					WR = MREQ;
					WE = NULLSHIFT || IRQ ? 5'b00000 : ALUCONT ? 5'b11000 : {3'b100, WRBIT};		// flags, TMP16, RASEL_HI, RASEL_LO
					IFETCH = ~ALUCONT || IRQ;
					ALUSTAGE = 1'b1;
					if(IRQ) ISIZE = 0;
					else case({|FETCH[0][4:1], DISP16, AEXT})
						3'b100:	ISIZE = 2;
						3'b000, 3'b101: ISIZE = 3;
						3'b001, 3'b110: ISIZE = 4;
						default: ISIZE = 5;
					endcase
				end
			end
// --------------------------------  (rep)movs --------------------------------
			32: begin
				BASEL = 1'b1;
				AEXT = 1'b0;
				DISP16 = 1'b0;
				NOBP = 1'b1;	// for RSSEL
				if(!STAGE[0]) begin		// stage1, read DS:[SI] in TMP16, inc/dec SI
					RASEL = 3'b110; 	// SI
					ALUOP = {4'b0100, FLAGS[10]};	
					EAC = 4'b0100;		// SI+DISP
					DISEL = 2'b11;		// ALU 16bit
					IFETCH = RCXZ;	// REP & CX==0
					MREQ = ~RCXZ;
					WE = IFETCH ? 5'b00000 : 5'b01011;		// TMP16, RASEL_HI, RASEL_LO
				end else begin			// stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
					RASEL = 3'b111; 	// DI
					RSSEL = 2'b00;		// ES
					WE[1:0] = 2'b11;		// RASEL_HI, RASEL_LO
					ALUOP = {4'b0100, FLAGS[10]};	
					EAC = 4'b0101;		// DI + DISP
					DISEL = 2'b11;		// ALU 16bit
					DOSEL = 2'b10;		// TMP16	 	
					WR = 1'b1;
					IFETCH = NRORCXLE1;  // not REP or CX<=1
					DECCX = CPUStatus[4];
					REPINT = 1'b1;
				end
				ISIZE = IFETCH ? 1 : 0;
			end
// --------------------------------  (rep)cmps --------------------------------
			33: begin
				DISP16 = 1'b0;
				AEXT = 1'b0;
				NOBP = 1'b1;	// for RSSEL
				case(STAGE[1:0])
					2'b00: begin		// stage1, read ES:[DI] in FETCH[3:2], inc/dec DI
						RASEL = 3'b111; 	// SI
						RSSEL = 2'b00;		// ES
						ALUOP = {4'b0100, FLAGS[10]};	
						EAC = 4'b0101;		// DI+DISP
						DISEL = 2'b11;		// ALU 16bit
						DOSEL = 2'b11;		// read data to FETCH
						IFETCH = RCXZ;//(~|CXZ || (CPUStatus[3] ^ TZF));	// REP & CX==0
						MREQ = ~RCXZ;
						WE[1:0] = IFETCH ? 2'b00 : 2'b11;		// RASEL_HI, RASEL_LO
					end
					2'b01: begin		// stage2, read DS:[SI] in TMP16, inc/dec SI
						RASEL = 3'b110; 	// DI
						ALUOP = {4'b0100, FLAGS[10]};	
						EAC = 4'b0100;		// SI+DISP
						DISEL = 2'b11;		// ALU 16bit
						IFETCH = 1'b0;
						WE[3:0] = 4'b1011;		// RASEL_HI, RASEL_LO
					end
					2'b10: begin		// stage3, compare TMP16 with imm, set flags, dec CX
						BASEL = 1'b0;			// TMP16
						BBSEL = 2'b10;			// imm
						ISEL = 2'b01;
						WE[4] = 1'b1;			// flags
						ALUOP = 5'b00111;		// cmp
						MREQ = 1'b0;
						IFETCH = NRORCXLE1 | (CPUStatus[3] ^ CMPS);
						DECCX = CPUStatus[4];
						ALUSTAGE = 1'b1;
						REPINT = 1'b1;
					end
				endcase
				ISIZE = IFETCH ? 1 : 0;
			end
// --------------------------------  (rep)scas --------------------------------
			34: begin
				DISP16 = 1'b0;
				AEXT = 1'b0;
				if(!STAGE[0]) begin	// stage1, read ES:[DI] in TMP16, inc/dec DI
					RASEL = 3'b111; 	// DI
					RSSEL = 2'b00;		// ES
					ALUOP = {4'b0100, FLAGS[10]};	
					EAC = 4'b0101;		// DI+DISP
					DISEL = 2'b11;		// ALU 16bit
					IFETCH = RCXZ;//(~|CXZ || (CPUStatus[3] ^ TZF));	// REP & CX==0
					MREQ = ~RCXZ;
					WE[3:0] = IFETCH ? 4'b0000 : 4'b1011;		// TMP16, RASEL_HI, RASEL_LO
				end else begin	//stage2, compare AL/AX with TMP16, set flags, dec CX
					RASEL = 3'b000;		// AL/AX
					BBSEL = 2'b00;			// TMP16
					WE[4] = 1'b1;			// flags
					ALUOP = 5'b00111;		// cmp
					MREQ = 1'b0;
					IFETCH = NRORCXLE1 | (CPUStatus[3] ^ SCAS);
					DECCX = CPUStatus[4];
					REPINT = 1'b1;
				end
				ISIZE = IFETCH ? 1 : 0;
			end
// --------------------------------  (rep)lods --------------------------------
			35: begin
				BASEL = 1'b1;
				DISP16 = 1'b0;
				AEXT = 1'b0;
				NOBP = 1'b1;	// for RSSEL
				if(!STAGE[0]) begin		// stage1, read DS:[SI] in AL/AX
					RASEL = 3'b000; 	// AX
					EAC = 4'b0100;		// SI+DISP
					DISEL = 2'b00;		// DIN
					IFETCH = RCXZ;	// REP & CX==0
					MREQ = ~RCXZ;
					WE[1:0] = IFETCH ? 2'b00 : {WORD, 1'b1};		// RASEL_HI, RASEL_LO
				end else begin 		// stage2, inc/dec SI, dec CX
					RASEL = 3'b110; 	// SI
					ALUOP = {4'b0100, FLAGS[10]};	
					DISEL = 2'b11;		// ALU 16bit
					IFETCH = NRORCXLE1;  // nor REP or CX<=1
					MREQ = 1'b0;
					WE[1:0] = 2'b11;		// RASEL_HI, RASEL_LO
					DECCX = CPUStatus[4];
					REPINT = 1'b1;
				end
				ISIZE = IFETCH ? 1 : 0;
			end
// --------------------------------  (rep)stos --------------------------------
			36: begin  // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
				BASEL = 1'b1;
				DISP16 = 1'b0;
				AEXT = 1'b0;
				RASEL = 3'b111; 	// DI
				RSSEL = 2'b00;		// ES
				ALUOP = {4'b0100, FLAGS[10]};	
				EAC = 4'b0101;		// DI + DISP
				DISEL = 2'b11;		// ALU 16bit
				DOSEL = 2'b11;		// AX
				IFETCH = NRORCXLE1;  // not REP or CX<=1
				MREQ = ~RCXZ;
				WR = ~RCXZ;
				WE[1:0] = {MREQ, MREQ};		// RASEL_HI, RASEL_LO
				DECCX = CPUStatus[4] && |CXZ;
				REPINT = 1'b1;
				ISIZE = IFETCH ? 1 : 0;
			end
// --------------------------------  (rep)ins --------------------------------
			37: begin
				BASEL = 1'b1;
				DISP16 = 1'b0;
				AEXT = 1'b0;
				if(!STAGE[0]) begin	// stage1, input in TMP16
					WE[3] = 1'b1;		// TMP16
					DISEL = 2'b00;		//DIN
					IFETCH = RCXZ;		// REP & CX==0
					MREQ = 1'b0;
					IORQ = ~RCXZ;
//					EAC = {~RCXZ, 3'b111};
//					NULLSEG = 1'b1;
				end else begin			// stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
					RASEL = 3'b111; 	// DI
					RSSEL = 2'b00;		// ES
					WE[1:0] = 2'b11;		// RASEL_HI, RASEL_LO
					ALUOP = {4'b0100, FLAGS[10]};	
					EAC = 4'b0101;		// DI + DISP
					DISEL = 2'b11;		// ALU 16bit
					DOSEL = 2'b10;		// TMP16	 	
					WR = 1'b1;
					IFETCH = NRORCXLE1;  // not REP or CX<=1
					DECCX = CPUStatus[4];
					REPINT = 1'b1;
				end
				ISIZE = IFETCH ? 1 : 0;
			end
// --------------------------------  (rep)outs --------------------------------
			38: begin
				BASEL = 1'b1;
				DISP16 = 1'b0;
				NOBP = 1'b1;	// for RSSEL
				if(!STAGE[0]) begin		// stage1, read DS:[SI] in TMP16, inc/dec SI
					AEXT = 1'b0;		// tweak for speed (can be moved outside <if>)
					RASEL = 3'b110; 	// SI
					ALUOP = {4'b0100, FLAGS[10]};	
					EAC = 4'b0100;		// SI+DISP
					DISEL = 2'b11;		// ALU 16bit
					IFETCH = RCXZ;	// REP & CX==0
					MREQ = ~RCXZ;
					WE[3:0] = IFETCH ? 4'b0000 : 4'b1011;		// TMP16, RASEL_HI, RASEL_LO
				end else begin			// stage2, out TMP16 at port DX, dec CX
					DOSEL = 2'b10;		// TMP16	 	
					MREQ = 1'b0;
					IORQ = 1'b1;
//					EAC = 4'b1111;
					WR = 1'b1;
					IFETCH = NRORCXLE1;  // not REP or CX<=1
					DECCX = CPUStatus[4];
					REPINT = 1'b1;
//					NULLSEG = 1'b1;
				end
				ISIZE = IFETCH ? 1 : 0;
			end
// --------------------------------  call/jmp direct near --------------------------------
			39: begin	// jump long
				WORD = 1'b1;
				ALUOP = 0;			// ADD
				DISEL = 2'b10;		// ADDR
				ISIZE = FETCH[0][1] ? 2 : 3;
				RASEL = 3'b100;	// write SP
				RSSEL = 2'b10;		// SS
				DOSEL = 2'b01;		// IP
				EAC = 4'b1000;		// SP - 2
				BBSEL = 2'b10;		// imm
				ISEL = 2'b00;
				DEXT = FETCH[0][1];
				MREQ = !FETCH[0][0];
				WR = MREQ;
				WE[1:0] = FETCH[0][0] ? 2'b00 : 2'b11;		// RASEL_HI/RASEL_LO
				IPWSEL = 1'b0;		// ALU
			end
// --------------------------------  call/jmp far imm --------------------------------
			40: begin
				WORD = 1'b1;
				ALUOP = 31;				// PASS B
				case({STAGE[1:0], FETCH[0][6]})
					3'b000: begin	// stage1, push CS
						RASEL = 3'b100;		// write SP
						BBSEL = 2'b11;
						RBSEL = 3'b001; 		// CS
						RSSEL = 2'b10;			// SS
						EAC = 4'b1000;			// SP - 2
						DISEL = 2'b10;			// ADDR
						WR = 1'b1;
						IFETCH = 1'b0;
						WE[1:0] = 2'b11;			// RASEL_HI/RASEL_LO
					end 
					3'b010, 3'b001: begin	// stage2, load CS
						RASEL = 3'b001; 	// CS
						BBSEL = 2'b10;		// imm
						WE[2] = 1'b1;		// RSSEL
						ISEL = 2'b10;
						MREQ = 1'b0;
						IFETCH = 1'b0;
					end
					3'b100, 3'b011: begin	// stage3, push IP, load IP
						RASEL = 3'b100; 	// write SP
						BBSEL = 2'b10;		// imm
						RSSEL = 2'b10;		// SS
						EAC = 4'b1000;		// SP - 2
						DISEL = 2'b10;		// ADDR
						DOSEL = 2'b01;		// IP	 
						ISEL = 2'b00;
						MREQ = FETCH[0][4];
						WR = MREQ;
						WE[1:0] = {WR, WR};
						IPWSEL = 1'b0;		// ALU
						ISIZE = 5;
					end
				endcase
			end
// --------------------------------  ret near --------------------------------
			41: begin
				WORD = 1'b1;		// fix RET n alignment bug - 03Apr2013
				ISIZE = FETCH[0][0] ? 1 : 3;
				IFETCH = STAGE[0];
				ALUOP = 31;			// PASS B
				if(!STAGE[0]) begin	// stage1, pop TMP16
					RSSEL = 2'b10;			// SS
					WE[3] = 1'b1;			// TMP16
					ASEL = 1'b0;
					AEXT = 1'b0;
					DISP16 = 1'b1;
					EAC = {1'b1, !FETCH[0][0], 2'b01};			// SP + 2 (+ imm) 
					DISEL = 2'b00;
				end else begin			// stage2, TMP16 to IP
					BBSEL = 2'b00;		// TMP16	
					IPWSEL = 1'b0;		// ALU
					MREQ = 1'b0;
				end
			end
// --------------------------------  ret far --------------------------------
			42: begin
				WORD = 1'b1;		// fix RET n alignment bug - 03Apr2013
				ALUOP = 31;			// PASS B
				RSSEL = 2'b10;			// SS
				IFETCH = STAGE[1];
				DISEL = 2'b00;			// DIN
				case(STAGE[1:0])
					2'b00: begin	// stage1, pop IP in TMP16
						WE[3] = 1'b1;			// TMP16
						EAC = 4'b1001;			// SP + 2
					end
					2'b01: begin		// stage2, pop CS, TMP16 <- RA
						RASEL = 3'b001;	// CS
						WE[2] = 1'b1;	
						EAC = {1'b1, !FETCH[0][0], 2'b01};
						ASEL = 1'b0;
						AEXT = 1'b0;
						DISP16 = 1'b1;
						BASEL = 1'b0;		// RA <- TMP16
					end
					2'b10: begin		// stage3, IP <- TMP16
						BBSEL = 2'b00;		// TMP16
						IPWSEL = 1'b0;		// ALU
						MREQ = 1'b0;
						ISIZE = FETCH[0][0] ? 1 : 3;
					end
				endcase
			end
// --------------------------------  iret --------------------------------
			43: begin  
				ALUOP = 31;			// PASS B
				RSSEL = 2'b10;			// SS
				ISIZE = 1;
				IFETCH = &STAGE[1:0];
				case(STAGE[1:0])
					2'b00: begin	// stage1, pop IP in FETCH
						EAC = 4'b1001;			// SP + 2
						DOSEL = 2'b11;			// write FETCH
					end
					2'b01: begin		// stage2, pop CS
						RASEL = 3'b001;	// CS
						WE[2] = 1'b1;	
						EAC = {1'b1, !FETCH[0][0], 2'b01};
						DISEL = 2'b00;
						ASEL = 1'b0;
						AEXT = 1'b0;
						DISP16 = 1'b1;
					end
					2'b10: begin		// stage3, pop flags in TMP16
						WE[3] = 1'b1;			// TMP16
						EAC = 4'b1001;			// SP
						DISEL = 2'b00;
					end 
					2'b11: begin		// stage4, IP <- FETCH, FLAGS <- TM
						BASEL = 1'b0;
						BBSEL = 2'b10;		// imm
						WE[4] = 1'b1;		// flags
						ISEL = 2'b01;
						DEXT = 1'b0;
						IPWSEL = 1'b0;		// ALU
						MREQ = 1'b0;
					end
				endcase
			end
// --------------------------------  cbw/cwd --------------------------------
			44: begin
				RASEL = FETCH[0][0] ? 3'b010 : 3'b100; // AH/DX
				RBSEL = 3'b000; // AX
				WE[1:0] = {1'b1, FETCH[0][0]};		// RASEL_HI, RASEL_LO
				ALUOP = {4'b1101, FETCH[0][0]};	// cbw/cwd
				MREQ = 1'b0;
				ISIZE = 1;
			end
// --------------------------------  JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
			45: begin  // loop/loopz/loopnz/jcxz
				ALUOP = 0;			// add
				ISIZE = 2;
				DOSEL = 2'b01;		// IP
				BBSEL = 2'b10;		// imm
				ISEL = 2'b00;
				DEXT = 1'b1;
				MREQ = 1'b0;
				IPWSEL = FETCH[0][7] ? LOOPC[FETCH[0][1:0]] : (JMPC[FETCH[0][3:1]] ~^ FETCH[0][0]);
				DECCX = FETCH[0][7] && (FETCH[0][1:0] != 2'b11);
			end
// --------------------------------  CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
			46: begin
				WE[4] = 1'b1;		// flags
				ALUOP = 5'b11001;	// flag op
				ISIZE = 1;
				MREQ = 1'b0;
			end
// --------------------------------  enter --------------------------------
			47: begin
				WORD = 1'b1;
				WE[1:0] = 2'b11;			// RASEL_HI/RASEL_LO
				case(STAGE[1:0])
					2'b00: begin		// push BP
						RASEL = 3'b100;		// write SP
						RBSEL = 3'b101; 		// BP
						RSSEL = 2'b10;			// SS
						EAC = 4'b1000;			// SP - 2
						DISEL = 2'b10;			// ADDR
						ALUOP = 31;				// PASS B
						WR = 1'b1;
						IFETCH = 1'b0;
					end
					2'b01: begin		// mov BP, SP
						RASEL = 3'b101; // BP
						RBSEL = 3'b100; // SP
						ALUOP = 31;				// PASS B
						MREQ = 1'b0;
						IFETCH = 1'b0;
					end
					2'b10: begin		// sub SP, imm
						BASEL = 1'b1;
						RASEL = 3'b100; // SP
						BBSEL = 2'b10;
						ALUOP = 5'b00101;	// sub
						ISEL = 2'b00;
						MREQ = 1'b0;
						ISIZE = 4;
					end
				endcase
			end	
// --------------------------------  leave --------------------------------
			48: begin
				WE[1:0] = 2'b11;			// RASEL_HI/RASEL_LO
				if(!STAGE[0]) begin	// stage1, mov sp, bp
					RASEL = 3'b100; // BP
					RBSEL = 3'b101; // SP
					ALUOP = 31;				// PASS B
					MREQ = 1'b0;
					IFETCH = 1'b0;
				end else begin			// stage2, pop bp
					RASEL = 3'b101; 	// BP
					RSSEL = 2'b10;			// SS
					EAC = 4'b1001;			// SP
					DISEL = 2'b00;			// DIN
					ISIZE = 1;
				end
			end
// --------------------------------  int, int 3, into --------------------------------
			49: begin
				MREQ = 1'b0;
				ISIZE = FETCH[0][1:0] == 2'b01 ? 2 : 1;
				IRQ = ~FETCH[0][1] | FLAGS[11];
				IRQL = FETCH[0][1] ? 3'b100 : {1'b0, ~FETCH[0][1:0]};	// 4, 2, 3
			end
// --------------------------------  bound --------------------------------
			50: begin
				WORD = 1'b1;
				DOSEL = 2'b11;			// load FETCH with DIN
				case(STAGE[1:0])
					2'b00: begin // stage1,  read min in FETCH, ADDR16 in TMP16
						RASEL = 3'b100; 		// SP	- write SP to SP for getting ADDR16 to TMP16
						BBSEL = 2'b01;
						RBSEL = 3'b100; 		// SP
						ALUOP = 31;				// PASS B
						WE[3:0] = 4'b1011;			// TMP16, RASEL_HI, RASEL_LO
						ASEL = 1'b1;
						IRQ = &MOD;		// illegal instruction
						ISIZE = 0;
						IFETCH = IRQ;
					end
					2'b01, 2'b10, 2'b11: begin	// stage2,3,4 load min/max in TMP16, compare reg with imm
						BBSEL = 2'b10;			// imm
						ALUOP = 5'b00111;		// cmp
						EAC = 4'b1011;			// TMP16 + 2
						ISEL = 2'b01;
						IRQ = STAGE[1] & (STAGE[0] ? ~TLF & ~TZF : TLF);
						MREQ = ~&STAGE[1:0];
						IFETCH = IRQ | ~MREQ;
						IRQL = 3'b101;
						ISIZE = IRQ ? 0 : ISIZES;	// return address is BOUND
					end
				endcase
			end
// --------------------------------  hlt --------------------------------
			51: begin
				IFETCH = 1'b0;
				HALT = 1'b1;
				MREQ = 1'b0;
			end
// --------------------------------  wait --------------------------------
			52: begin	// do nothing
				ISIZE = 1;
				MREQ = 1'b0;
			end
// --------------------------------  aam --------------------------------
			53: begin
				MREQ = 1'b0;
				IRQL = 3'b000;	// divide overflow
				ISIZE = 2;
				case({DIVEND, STAGE[1:0]})
					3'b000: begin	// stage1, clear AH
						BASEL = 1'b0;	 // TMP16
						RASEL = 3'b100; // AH
						BBSEL = 2'b00;	 // TMP16
						WE[1] = 1'b1;	 // RASEL_HI
						ALUOP = 5'b00101;	// sub
						IFETCH = 1'b0;
					end
					3'b001, 3'b101: begin	// stage2, div
						RASEL = 3'b100; // AH
						BASEL = 1'b1;
						BBSEL = 2'b10;	 // imm
						WE[1] = 1'b1;	 // RASEL_HI
						ALUOP = 5'b00101;	// sub
						ISEL = 2'b00;
						DIVSTAGE = ~DIVEND;
						ALUSTAGE = ~DIVEND;
						DIVOP = 1'b1;
						IRQ = AAMIRQ;//~|STAGE[6:2] & DIVC;
						IFETCH = AAMIRQ;
					end
					3'b110: begin	// stage 3, AH <- AL, TMP16 <- AH
						RASEL = 3'b100; // AH
						BASEL = 1'b1;
						RBSEL = 3'b000; // AL
						WE[1] = 1'b1;	// RASEL_HI
						ALUOP = 31;			// PASS B
						IFETCH = 1'b0;
					end
					3'b111: begin // stage4, AL <- TMP16 | TMP16, set flags
						RASEL = 3'b000; // dest = AL
						BASEL = 1'b0;	 // TMP16
						BBSEL = 2'b00;	 // TMP16
						WE = 5'b10001;	 // FLAGS, RASEL_LO
						ALUOP = 5'b00001;		// OR
					end
				endcase
			end
// --------------------------------  reset, irq, nmi, intr --------------------------------
			54:
				if(STAGE[3]) begin
					if(FETCH[5][0]) begin	// reset
						RASEL = {1'b0, STAGE[1:0]}; 	// ES, CS, SS, DS
						WE = 5'b11100;		// FLAGS, TMP16, RSSEL
						BASEL = 1'b0;		// TMP16
						BBSEL = 2'b00;		// TMP16
						ALUOP = STAGE[0] ? STAGE[1] ? 31 : 5'b01001 : 5'b00101;	// pass, dec, sub
						MREQ = 1'b0;
						IPWSEL = 1'b0;		// ALU16
						IFETCH = &STAGE[1:0];
					end else case({FETCH[5][1], STAGE[2:0]}) 
						4'b1000: begin		// stage1 intr
							DOSEL = 2'b11;	// read FETCH[2]	 
							MREQ = 1'b0;
							IFETCH = 1'b0;
							INTA = 1'b1;
						end 
						4'b1001, 4'b0000: begin // stage1 irq, nmi, tf, stage2 intr - push flags, clear TF, IF
							RASEL = 3'b100;		// write SP
							RSSEL = 2'b10;			// SS
							WE = 5'b10011;			// flags, SP	
							ALUOP = 30;				// pass flags
							EAC = 4'b1000;			// SP - 2
							DISEL = 2'b10;			// ADDR
							WR = 1'b1;
							IFETCH = 1'b0;
						end
						4'b1010, 4'b0001: begin // stage2 irq, nmi, tf, stage3 intr - push CS
							RASEL = 3'b100;		// write SP
							BBSEL = 2'b11;
							RBSEL = 3'b001; 		// CS
							RSSEL = 2'b10;			// SS
							ALUOP = 31;				// PASS B
							EAC = 4'b1000;			// SP - 2
							DISEL = 2'b10;			// ADDR
							WR = 1'b1;
							IFETCH = 1'b0;
							WE[1:0] = 2'b11;			// RASEL_HI/RASEL_LO
						end
						4'b1011, 4'b0010: begin // stage3 irq, nmi, tf, stage4 intr - read offset in FETCH, ADDR16 in TMP16
							RASEL = 3'b100; 		// SP	- write SP to SP for getting ADDR16 to TMP16
							BBSEL = 2'b01;
							RBSEL = 3'b100; 		// SP
							ALUOP = 31;				// PASS B
							EAC = 4'b1110;			// int vector
							WE[3:0] = 4'b1011;	// TMP16, RASEL_HI, RASEL_LO
							ASEL = 1'b1;
							DISP16 = 1'b1;
							DOSEL = 2'b11;			// load FETCH with DIN
							IFETCH = 1'b0;
							NULLSEG = 1'b1;
						end
						4'b1100, 4'b0011: begin // stage4 irq, nmi, tf, stage5 intr - read CS
							RASEL = 3'b001; 		// CS
							WE[2] = 1'b1;			// RSSEL
							EAC = 4'b1011;			// TMP16 + 2
							DISEL = 2'b00;			// DIN
							IFETCH = 1'b0;
							NULLSEG = 1'b1;
						end
						4'b1101, 4'b0100: begin // stage5 irq, nmi, tf, stage6 intr - push IP, jump
							RASEL = 3'b100; 	// write SP
							BBSEL = 2'b10;		// imm
							RSSEL = 2'b10;		// SS
							ALUOP = 31;			// PASS B
							EAC = 4'b1000;		// SP - 2
							DISEL = 2'b10;		// ADDR
							DOSEL = 2'b01;		// IP	 
							ISEL = 2'b01;
							WR = 1'b1;
							WE[1:0] = 2'b11;
							ISIZE = FETCH[5][2] ? 1 : 0;
							IPWSEL = 1'b0;		// ALU
						end
					endcase
				end else begin
					MREQ = 1'b0;
					ISIZE = 0;
					IRQ = 1'b1;
				end
// --------------------------------  SALC --------------------------------
			55: begin
				RASEL = 3'b000;	// dest AL (WORD is default 0)
				BASEL = 1'b0;
				BBSEL = 2'b00;
				ALUOP = 3;	// sbb
				MREQ = 1'b0;
				WE[0] = 1'b1;	// RASEL_LO
				ISIZE = 1;
			end
// --------------------------------  bad opcode/esc --------------------------------
			default: begin
				MREQ = 1'b0;
				ISIZE = 0;
				IRQ = 1'b1;
				if(FETCH[0][7:3] == 5'b11011) IRQL = 3'b111; // esc
			end
		endcase
	 end
 
 
 
// instruction pre-decoder
function [5:0]ICODE;
	input [7:0]INSTR;
	begin
		case(INSTR[7:0])
// --------------------------------  mov R/M to/from R/SR  --------------------------------
			8'b10001000, 8'b10001001, 8'b10001010, 8'b10001011, 
			8'b10001110, 8'b10001100: ICODE = 0;
// --------------------------------  mov IMM to R/M  --------------------------------
			8'b11000110, 8'b11000111: ICODE = 1;	
// --------------------------------  mov IMM to R --------------------------------
			8'b10110_000, 8'b10110_001, 8'b10110_010, 8'b10110_011, 8'b10110_100, 8'b10110_101, 8'b10110_110, 8'b10110_111,
			8'b10111_000, 8'b10111_001, 8'b10111_010, 8'b10111_011, 8'b10111_100, 8'b10111_101, 8'b10111_110, 8'b10111_111: ICODE = 2;
// --------------------------------  mov mem to/from ACC --------------------------------
			8'b10100000, 8'b10100001,
			8'b10100010, 8'b10100011: ICODE = 3;
// --------------------------------  segment override prefix --------------------------------
			8'b001_00_110, 8'b001_01_110, 8'b001_10_110, 8'b001_11_110: ICODE = 4;
// --------------------------------  rep prefix --------------------------------
			8'b11110010, 8'b11110011: ICODE = 5;
// --------------------------------  lock prefix --------------------------------
			8'b11110000: ICODE = 6;
// --------------------------------  FF block --------------------------------
			8'b11111111, 8'b11111110:	ICODE = 7;
// --------------------------------  push R/SR --------------------------------
			8'b01010_000, 8'b01010_001, 8'b01010_010, 8'b01010_011, 8'b01010_100, 8'b01010_101, 8'b01010_110, 8'b01010_111,
			8'b000_00_110, 8'b000_01_110, 8'b000_10_110, 8'b000_11_110: ICODE = 8;
// --------------------------------  push Imm --------------------------------
			8'b01101000, 8'b01101010: ICODE = 9;		
// --------------------------------  pusha --------------------------------
			8'b01100000: ICODE = 10;
// --------------------------------  pop R/M --------------------------------
			8'b10001111: ICODE = 11;			
// --------------------------------  pop R / SR --------------------------------
			8'b01011_000, 8'b01011_001, 8'b01011_010, 8'b01011_011, 8'b01011_100, 8'b01011_101, 8'b01011_110, 8'b01011_111,
			8'b000_00_111, 8'b000_10_111, 8'b000_11_111: ICODE = 12;
// --------------------------------  popa --------------------------------
			8'b01100001: ICODE = 13;
// --------------------------------  xchg R with R/M/Acc --------------------------------
			8'b10000110, 8'b10000111,
			8'b10010000, 8'b10010001, 8'b10010010, 8'b10010011, 8'b10010100, 8'b10010101, 8'b10010110, 8'b10010111: ICODE = 14;
// --------------------------------  in --------------------------------
			8'b11100100, 8'b11100101,
			8'b11101100, 8'b11101101:	ICODE = 15;
// --------------------------------  out --------------------------------
			8'b11100110, 8'b11100111,
			8'b11101110, 8'b11101111:	ICODE = 16;
// --------------------------------  xlat --------------------------------
			8'b11010111: ICODE = 17;
// --------------------------------  lea --------------------------------
			8'b10001101: ICODE = 18;
// --------------------------------  lds, les --------------------------------
			8'b11000101, 8'b11000100: ICODE = 19;
// --------------------------------  lahf, sahf --------------------------------
			8'b10011111, 8'b10011110: ICODE = 20;
// --------------------------------  pushf --------------------------------
			8'b10011100: ICODE = 21;
// --------------------------------  popf --------------------------------
			8'b10011101: ICODE = 22;
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
			8'b00000000, 8'b00000001, 8'b00000010, 8'b00000011,		// add
			8'b00001000, 8'b00001001, 8'b00001010, 8'b00001011,		// or
			8'b00010000, 8'b00010001, 8'b00010010, 8'b00010011,		// adc
			8'b00011000, 8'b00011001, 8'b00011010, 8'b00011011,		// sbb
			8'b00100000, 8'b00100001, 8'b00100010, 8'b00100011,		// and
			8'b00101000, 8'b00101001, 8'b00101010, 8'b00101011,		// sub
			8'b00110000, 8'b00110001, 8'b00110010, 8'b00110011,		// xor
			8'b00111000, 8'b00111001, 8'b00111010, 8'b00111011,		// cmp
			8'b10000100, 8'b10000101: ICODE = 23;									// test 
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
			8'b10000000, 8'b10000001, 8'b10000010, 8'b10000011: ICODE = 24;
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
			8'b00000100, 8'b00000101, 		// add
			8'b00001100, 8'b00001101, 		// or
			8'b00010100, 8'b00010101, 		// adc
			8'b00011100, 8'b00011101, 		// sbb
			8'b00100100, 8'b00100101, 		// and
			8'b00101100, 8'b00101101, 		// sub
			8'b00110100, 8'b00110101, 		// xor
			8'b00111100, 8'b00111101,  	// cmp
			8'b10101000, 8'b10101001: ICODE = 25; // test
// --------------------------------  inc/dec R16 --------------------------------
			8'b01000000, 8'b01000001, 8'b01000010, 8'b01000011, 8'b01000100, 8'b01000101, 8'b01000110, 8'b01000111,
			8'b01001000, 8'b01001001, 8'b01001010, 8'b01001011, 8'b01001100, 8'b01001101, 8'b01001110, 8'b01001111: ICODE = 26;
// --------------------------------  test/???/not/neg/mul/imul/div/idiv --------------------------------
			8'b11110110, 8'b11110111: ICODE = 27;
// --------------------------------  imul imm --------------------------------
			8'b01101001, 8'b01101011: ICODE = 28;
// --------------------------------  aad --------------------------------
			8'b11010101: ICODE = 29;
// --------------------------------  daa, das, aaa, aas --------------------------------
			8'b00_100_111, 8'b00_101_111, 8'b00_110_111, 8'b00_111_111: ICODE = 30;
// --------------------------------  shift/rot --------------------------------
			8'b11010000, 8'b11010001,			// 1
			8'b11010010, 8'b11010011,			// CL
			8'b11000000, 8'b11000001: ICODE = 31;	// imm
// --------------------------------  (rep)movs --------------------------------
			8'b10100100, 8'b10100101: ICODE = 32;
// --------------------------------  (rep)cmps --------------------------------
			8'b10100110, 8'b10100111: ICODE = 33;
// --------------------------------  (rep)scas --------------------------------
			8'b10101110, 8'b10101111: ICODE = 34;
// --------------------------------  (rep)lods --------------------------------
			8'b10101100, 8'b10101101: ICODE = 35;
// --------------------------------  (rep)stos --------------------------------
			8'b10101010, 8'b10101011: ICODE = 36;  // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
// --------------------------------  (rep)ins --------------------------------
			8'b01101100, 8'b01101101: ICODE = 37;
// --------------------------------  (rep)outs --------------------------------
			8'b01101110, 8'b01101111: ICODE = 38;
// --------------------------------  call/jmp direct near --------------------------------
			8'b11101000, 			// call long
			8'b11101011,			// jump short
			8'b11101001: ICODE = 39;	// jump long
// --------------------------------  call/jmp far imm --------------------------------
			8'b10011010, 8'b11101010: ICODE = 40;
// --------------------------------  ret near --------------------------------
			8'b11000011, 8'b11000010: ICODE = 41;
// --------------------------------  ret far --------------------------------
			8'b11001011, 8'b11001010: ICODE = 42;
// --------------------------------  iret --------------------------------
			8'b11001111: ICODE = 43;  
// --------------------------------  cbw/cwd --------------------------------
			8'b10011000, 8'b10011001: ICODE = 44;
// --------------------------------  JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
			8'b01110000, 8'b01110001,	// JO/JNO
			8'b01110010, 8'b01110011,	// JB/JNB
			8'b01110100, 8'b01110101,	// JE/JNE
			8'b01110110, 8'b01110111,	// JBE/JA
			8'b01111000, 8'b01111001,	// JS/JNS
			8'b01111010, 8'b01111011,	// JP/JNP
			8'b01111100, 8'b01111101,	// JL/JNL
			8'b01111110, 8'b01111111,	// JLE/JG
			8'b11100010, 8'b11100001, 8'b11100000, 8'b11100011: ICODE = 45;  // loop/loopz/loopnz/jcxz
// --------------------------------  CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
			8'b11111000, 8'b11110101, 8'b11111001, 8'b11111100, 8'b11111101, 8'b11111010, 8'b11111011: ICODE = 46;
// --------------------------------  enter --------------------------------
			8'b11001000: ICODE = 47;
// --------------------------------  leave --------------------------------
			8'b11001001: ICODE = 48;
// --------------------------------  int, int 3, into --------------------------------
			8'b11001101, 8'b11001100, 8'b11001110: ICODE = 49;
// --------------------------------  bound --------------------------------
			8'b01100010: ICODE = 50;
// --------------------------------  hlt --------------------------------
			8'b11110100: ICODE = 51;
// --------------------------------  wait --------------------------------
			8'b10011011: ICODE = 52;	// do nothing
// --------------------------------  aam --------------------------------
			8'b11010100: ICODE = 53;	
// --------------------------------  reset, irq, nmi, intr --------------------------------
			8'b00001111: ICODE = 54;		
// --------------------------------  SALC --------------------------------
			8'b11010110: ICODE = 55;
// --------------------------------  bad opcode/esc --------------------------------
			default: ICODE = 56;
		endcase
	end
endfunction
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.