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

Subversion Repositories next186

[/] [next186/] [trunk/] [Next186_CPU.v] - Blame information for rev 20

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
2
//
3
// This file is part of the Next186 project
4
// http://opencores.org/project,next186
5
//
6
// Filename: Next186_CPU.v
7
// Description: Implementation of 80186 instruction compatible CPU
8
// Version 1.0
9
// Creation date: 24Mar2011 - 07Jun2011
10
//
11
// Author: Nicolae Dumitrache 
12
// e-mail: ndumitrache@opencores.org
13
//
14
/////////////////////////////////////////////////////////////////////////////////
15
// 
16
// Copyright (C) 2011 Nicolae Dumitrache
17
// 
18
// This source file may be used and distributed without 
19
// restriction provided that this copyright statement is not 
20
// removed from the file and that any derivative work contains 
21
// the original copyright notice and the associated disclaimer.
22
// 
23
// This source file is free software; you can redistribute it 
24
// and/or modify it under the terms of the GNU Lesser General 
25
// Public License as published by the Free Software Foundation;
26
// either version 2.1 of the License, or (at your option) any 
27
// later version. 
28
// 
29
// This source is distributed in the hope that it will be 
30
// useful, but WITHOUT ANY WARRANTY; without even the implied 
31
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
32
// PURPOSE. See the GNU Lesser General Public License for more 
33
// details. 
34
// 
35
// You should have received a copy of the GNU Lesser General 
36
// Public License along with this source; if not, download it 
37
// from http://www.opencores.org/lgpl.shtml 
38
// 
39
///////////////////////////////////////////////////////////////////////////////////
40
//
41
// Comments:
42
// This project was developed and tested on a XILINX Spartan3AN board.
43
//
44
//      Next186 processor features:
45 3 ndumitrach
//              All 80186 intstructions are implemented according with the 80186 specifications (excepting ENTER instruction, 
46 11 ndumitrach
//              which uses always 0 as the second parameter - level).
47 2 ndumitrach
//              Designed with 2 buses: 16bit/20bit data/data_address and 48bit/20bit instruction/instruction_address.
48
//              This allows most instructions to be executed in one clock cycle.
49
//              In order to couple the CPU unit with a single bus, these sepparate data/instruction buses must be multiplexed by
50 3 ndumitrach
//              a dedicated bus interface unit (BIU).
51 11 ndumitrach
//              It is able to execute up to 40Mips on Spartan XC3S700AN speed grade -4, performances comparable with a 486 CPU.
52
//              Small size, the CPU + BIU requires ~25%  or 1500 slices - on Spartan XC3S700AN
53 5 ndumitrach
// 
54 8 ndumitrach
//      16May2012 - fixed REP CMPS/SCAS bug when interrupted on the <equal> item
55 10 ndumitrach
// 23Dec2012 - fixed DIV bug (exception on sign bit)
56 11 ndumitrach
// 27Feb2013 - fixed MUL/IMUL 8bit flags bug
57
// 03Apr2013 - fix RET n alignment bug
58
// 04Apr2013 - fix TRAP interrupt acknowledge
59 12 ndumitrach
// 12Apr2013 - fix IDIV when Q=0
60 13 ndumitrach
// 16May2013 - fix PUSHA SP pushed stack value, which should be the one before PUSHA
61 14 ndumitrach
// 25May2013 - generate invalid opcode exception for MOV FS and GS 
62 20 ndumitrach
// 08Sep2016 - separate port address (PORT_ADDR)
63
// 15Sep2017 - implemented SALC undocumented instruction
64 11 ndumitrach
///////////////////////////////////////////////////////////////////////////////////
65 2 ndumitrach
`timescale 1ns / 1ps
66
 
67
module Next186_CPU(
68 20 ndumitrach
    output [20:0]ADDR,                   // mem address
69
         output [15:0]PORT_ADDR, // port address
70
    input [15:0]DIN,             // mem/port data in
71
    output [15:0]DOUT,   // mem data out
72
    output [15:0]POUT,   // port data out
73 2 ndumitrach
         input CLK,
74
         input CE,
75
         input INTR,
76
         input NMI,
77
         input RST,
78
         output reg MREQ,
79 20 ndumitrach
         output reg IORQ,
80 2 ndumitrach
         output reg INTA,
81
         output reg WR,
82
         output reg WORD,
83
         output LOCK,
84 19 ndumitrach
         output [20:0]IADDR,
85 2 ndumitrach
         input [47:0]INSTR,
86
         output reg IFETCH,
87
         output FLUSH,
88
         output reg [2:0]ISIZE,
89
         output reg HALT
90
    );
91
 
92
// connections  
93
        wire [15:0]RA;
94
        wire [15:0]RB;
95
        wire [15:0]TMP16;
96
        wire [15:0]SP;
97
        wire [15:0]IP;
98
        wire [15:0]AX;
99
        wire [15:0]BX;
100
        wire [15:0]BP;
101
        wire [15:0]SI;
102
        wire [15:0]DI;
103
        wire [15:0]DX;
104
        wire [15:0]FLAGS;
105
        wire [15:0]FIN;
106
        wire [15:0]ALUOUT;
107 20 ndumitrach
        wire [15:0]ALUOUTA;
108 2 ndumitrach
        wire [15:0]AIMM1;
109
        reg [15:0]DIMM1;
110
        wire [15:0]RS;
111
        wire [15:0]ADDR16;
112
        wire [15:0]CS;
113
        wire ALUCONT;
114
        wire NULLSHIFT;
115
        wire [1:0]CXZ;
116
        wire COUT; // adder carry out
117
        wire DIVEXC; // exit carry for unsigned DIV 
118
 
119
// Registers
120
        reg [7:0]FETCH[5:0];
121
        reg [6:0]STAGE = 0;
122
        reg [5:0]CPUStatus = 0;   //1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=LOCK
123
        reg TZF = 0, TLF = 0;
124
        reg SRST = 0;
125
        reg SNMI = 0, FNMI = 0;
126
        reg SINTR = 0;
127
        reg [15:0]CRTIP; // current instruction ptr (used by interrupts)
128
        reg DIVQSGN;
129
        reg RDIVEXC;
130
 
131
// control      
132
        reg [2:0]RASEL;
133
        reg [2:0]RBSEL;
134
        reg BASEL;
135
        reg [1:0]BBSEL;
136
        reg [1:0]RSSEL;
137
        reg [4:0]WE; // 4=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
138
        reg [4:0]ALUOP;
139
        reg [3:0]EAC;
140
        reg [1:0]DISEL;
141
        reg [1:0]ISEL;
142
        reg ASEL;
143
        reg AEXT;
144
        reg DEXT;
145
        reg [1:0]DOSEL;
146
        reg IPWSEL;
147
        reg [5:0]status; //1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=lock
148
        reg NOBP;
149
        reg ALUSTAGE;   // inc STAGE with 2
150
        reg DIVSTAGE;  // inc STAGE with 4
151
        reg DISP16;
152
        reg DECCX;
153
        reg IRQ;
154
        reg [2:0]IRQL;
155
        reg REPINT;
156
        reg [5:0]ICODE1 = 23;
157
        reg NULLSEG;
158
        reg DIVOP;
159 20 ndumitrach
        reg DIVIRQ;
160
        reg AAMIRQ;
161
        reg RCOUT;
162 2 ndumitrach
 
163
// signals
164 20 ndumitrach
//      assign IORQ = &EAC;
165 2 ndumitrach
        assign LOCK = CPUStatus[5];
166
        assign FLUSH = ~IPWSEL || (ISIZE == 3'b000);
167 20 ndumitrach
        assign PORT_ADDR = FETCH[0][3] ? DX : {8'h00, FETCH[1]};
168 2 ndumitrach
        wire [15:0]IPADD = ISIZE == 3'b000 ? CRTIP : IP + ISIZE;
169 20 ndumitrach
        wire [15:0]IPIN = IPWSEL ? IPADD : ALUOUTA;
170 2 ndumitrach
        wire [1:0]MOD = FETCH[1][7:6];
171
        wire [2:0]REG = FETCH[1][5:3];
172
        wire [2:0]RM  = FETCH[1][2:0];
173
        wire USEBP = RM[1] && ~&RM;
174
        wire POP = {EAC[3], EAC[1:0]} == 3'b101;
175
        wire [15:0]ADDR16_SP = POP ? SP : ADDR16;
176
        wire [1:0]WBIT = {WORD | RASEL[2], WORD | !RASEL[2]};
177
        wire [1:0]ISELS = {DISP16 | AEXT, DISP16 | ~AEXT};
178
        wire [2:0]ISIZES = DISP16 ? 4 : AEXT ? 3 : 2;
179
        reg  [2:0]ISIZEW;
180
        reg  [2:0]ISIZEI;        // ise imm
181
        wire [1:0]WRBIT = WR ? 2'b00 : WBIT;
182
        wire RCXZ = CPUStatus[4] && ~|CXZ;
183
        wire NRORCXLE1 = ~CPUStatus[4] || ~CXZ[1];
184
        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]};
185
        wire [3:0]LOOPC = {CXZ != 2'b00, CXZ == 2'b01, CXZ == 2'b01 || !FLAGS[6], CXZ == 2'b01 || FLAGS[6]};
186
        wire IDIV = FETCH[0][1] & FETCH[1][3];
187
        wire DIVRSGN = (WORD ? FETCH[3][7] : FETCH[2][7]) & IDIV;
188
        wire DIVSGN = DIVQSGN ^ DIVRSGN;
189
        wire DIVEND = FETCH[0][0] ? STAGE[6] : STAGE[5];
190
        wire DIVC = ((COUT & ~RDIVEXC) ^ ~DIVRSGN);
191
        wire QSGN = (WORD ? DX[15] : AX[15]) & IDIV;
192
// interrupts
193
        wire SAMPLEINT = ~(WE[2] & RASEL[1:0] == 2'b10) & ~status[2] & ~status[4] & ~status[5]; // not load SS, no prefix
194
        wire NMIACK = SNMI & ~FNMI;     // NMI acknowledged
195
        wire INTRACK = FLAGS[9] & (~WE[4] | FIN[9]) & SINTR;                    // INTR acknowledged (IF and not CLI in progress)
196 11 ndumitrach
        wire IACK = IRQ | (SAMPLEINT & (NMIACK | INTRACK | (~HALT & FLAGS[8]))); // interrupt acknowledged (fixed 04Apr2013)
197 5 ndumitrach
        reg CMPS;       // early EQ test for CMPS
198
        reg SCAS;   // early EQ test for SCAS
199 2 ndumitrach
 
200
        Next186_Regs REGS (
201
    .RASEL(RASEL),
202
    .RBSEL(RBSEL),
203
    .BASEL(BASEL),
204
    .BBSEL(BBSEL),
205
    .RSSEL(RSSEL),
206
    .DIN(DIN),
207
         .ALUOUT(ALUOUT),
208
         .ADDR16(ADDR16),
209
         .DIMM(DEXT ? {{8{DIMM1[7]}}, DIMM1[7:0]} : DIMM1),
210
    .WE(WE),
211
         .IFETCH(IFETCH),
212
    .RA(RA),
213
    .RB(RB),
214
    .TMP16(TMP16),
215
    .SP(SP),
216
    .IP(IP),
217
         .AX(AX),
218
         .BX(BX),
219
         .BP(BP),
220
         .SI(SI),
221
         .DI(DI),
222
         .DX(DX),
223
         .RS(RS),
224
         .FIN(FIN),
225
         .FOUT(FLAGS),
226
         .DISEL(DISEL),
227
         .WORD(WORD | &DISEL),
228
         .IPIN(IPIN),
229
         .CLK(CLK),
230
         .CLKEN(CE),
231
         .CS(CS),
232
         .INCSP(POP),
233
         .CXZ(CXZ),
234
         .DECCX(DECCX),
235
         .DIVOP(DIVOP),
236
         .DIVEND(DIVEND),
237
         .DIVSGN(DIVSGN),
238
         .DIVC(DIVC),
239
         .DIVEXC(DIVEXC)
240
    );
241
 
242
        Next186_ALU ALU16 (
243
         .RA(DOSEL == 2'b01 ? IPADD : RA),
244
         .RB(RB),
245
         .TMP16(TMP16),
246
         .FETCH23({FETCH[3], FETCH[2]}),
247
         .FIN(FLAGS),
248
         .FOUT(FIN),
249
         .ALUOP(ALUOP),
250
         .EXOP(FETCH[1][5:3]),
251
         .FLAGOP(FETCH[0][3:0]),
252
         .ALUOUT(ALUOUT),
253 20 ndumitrach
         .ALUOUTA(ALUOUTA),
254 2 ndumitrach
         .WORD(WORD),
255
         .ALUCONT(ALUCONT),
256
         .NULLSHIFT(NULLSHIFT),
257
         .STAGE(STAGE[2:0]),
258
         .INC2(&DISEL), // when DISEL == 2'b11, inc/dec value is 2 if WORD and 1 if ~WORD
259
         .COUT(COUT),
260
         .CLK(CLK)
261
         );
262
 
263
        Next186_EA EA (
264
    .SP(SP),
265
    .BX(BX),
266
    .BP(NOBP ? 16'h0000 : BP),
267
    .SI(SI),
268
    .DI(DI),
269
         .TMP16(TMP16),
270
         .AL(AX[7:0]),
271
    .AIMM(AEXT ? {{8{AIMM1[7]}}, AIMM1[7:0]} : (DISP16 ? AIMM1 : 16'h0000)),
272
    .ADDR16(ADDR16),
273
         .EAC(EAC)
274
    );
275
 
276 20 ndumitrach
         assign POUT = DOSEL[0] ? AX : TMP16;
277
         assign DOUT = DOSEL[1] ? POUT : DOSEL[0] ? IPADD : ALUOUT;
278 19 ndumitrach
         assign ADDR = {{NULLSEG ? 16'h0000 : RS} + {5'b00000, ADDR16_SP[15:4]}, ADDR16_SP[3:0]};
279
         assign IADDR = {CS + {5'b00000, IPIN[15:4]}, IPIN[3:0]};
280 2 ndumitrach
         assign AIMM1 = ASEL ? {FETCH[3], FETCH[2]} : {FETCH[2], FETCH[1]};
281
 
282
         always @(posedge CLK)
283
                if(CE) begin
284
                        if(SRST) begin          // reset
285
//                              FETCH[0] <= 8'h0f;
286
                                FETCH[0][0] <= 1'b1; // for word=1
287
                                ICODE1 <= 54;
288
                                FETCH[5][1:0] <= 2'b01;  // RESET
289
                                STAGE <= 4'b1000;
290
                        end else begin
291
                                if(IACK & (IFETCH | HALT | REPINT)) begin // interrupt sampled and acknowledged
292
                                        FETCH[0][1:0] <= 2'b11;
293
                                        ICODE1 <= 54;
294
                                        STAGE <= 4'b1000;
295
                                        FETCH[5][2:0] <= {HALT, 2'b00};
296
                                        if(IRQ) FETCH[2] <= IRQL != 3'b010 ? {5'b00000, IRQL} : FETCH[1];
297
                                        else if(NMIACK) begin
298
                                                FETCH[2] <= 8'h02;
299
                                                FNMI <= 1'b1;
300
                                        end else if(INTRACK) FETCH[5][1:0] <= 2'b10;
301
                                        else FETCH[2] <= 8'h01; // trap
302
                                end else if(IFETCH) begin               // no interrupt, fetch
303
                                        FETCH[5] <= INSTR[47:40];
304
                                        FETCH[4] <= INSTR[39:32];
305
                                        FETCH[3] <= INSTR[31:24];
306
                                        FETCH[2] <= INSTR[23:16];
307
                                        FETCH[1] <= INSTR[15:8];
308
                                        FETCH[0] <= INSTR[7:0];
309
                                        STAGE <= 0;
310
                                        CPUStatus[5:0] <= status[5:0];
311
                                        ICODE1 <= ICODE(INSTR[7:0]);
312
                                end else begin          // no interrupt, no fetch
313 20 ndumitrach
                                        STAGE <= STAGE + {DIVSTAGE, ALUSTAGE} + 1'b1;
314 2 ndumitrach
                                        if(&DOSEL) {FETCH[3], FETCH[2]} <= |DISEL ? DIN : RB;
315 5 ndumitrach
                                        TZF <= FIN[6];          // zero flag for BOUND
316 2 ndumitrach
                                        TLF <= FIN[7] != FIN[11];       // less flag for BOUND
317
                                end
318
                        end
319
                        if(IFETCH & ~status[2] & ~status[4] & ~status[5]) CRTIP <= IPIN; // no prefix
320
                        SRST <= RST;                            // level detection RST
321
                        SINTR <= INTR;                          // level detection INTR
322
                        if(NMI) SNMI <= 1'b1;   // edge detection NMI
323
                        else if(FNMI) begin
324
                                SNMI <= 1'b0;
325
                                FNMI <= 1'b0;
326
                        end
327
                        if(~|STAGE[1:0]) DIVQSGN <= QSGN;
328
                        RDIVEXC <= DIVOP & DIVEXC & ~IDIV; // bit 8/16 for unsigned DIV
329 5 ndumitrach
                        CMPS <= (~FETCH[0][0] | (FETCH[3] == DIN[15:8])) & (FETCH[2] == DIN[7:0]); // early EQ test for CMPS
330
                        SCAS <= (~FETCH[0][0] | (AX[15:8] == DIN[15:8])) & (AX[7:0] == DIN[7:0]);  // early EQ test for SCAS
331 20 ndumitrach
                        RCOUT <= COUT;
332
                        DIVIRQ <= ~|STAGE[6:3] & DIVC & (~STAGE[2] | (~DIVSGN & IDIV)) & (&STAGE[1:0]); // DIV stage4, div loop
333
                        AAMIRQ <= ~|STAGE[6:2] & DIVC & (STAGE[1:0] == 2'b01); // AAM stage2, div
334 2 ndumitrach
                end
335
 
336
        always @(ISEL, FETCH[0], FETCH[1], FETCH[2], FETCH[3], FETCH[4], FETCH[5])
337
                case(ISEL)
338
                        2'b00: DIMM1 = {FETCH[2], FETCH[1]};
339
                        2'b01: DIMM1 = {FETCH[3], FETCH[2]};
340
                        2'b10: DIMM1 = {FETCH[4], FETCH[3]};
341
                        2'b11: DIMM1 = {FETCH[5], FETCH[4]};
342
                endcase
343
 
344
        always @(FETCH[0], WORD, DISP16, AEXT) begin
345
                case({WORD, DISP16, AEXT})
346
                        3'b000: ISIZEW = 3;
347
                        3'b001, 3'b100: ISIZEW = 4;
348
                        3'b010, 3'b101: ISIZEW = 5;
349
                        default: ISIZEW = 6;
350
                endcase
351
                case({FETCH[0][1:0] == 2'b01, DISP16, AEXT})
352
                        3'b000: ISIZEI = 3;
353
                        3'b001, 3'b100: ISIZEI = 4;
354
                        3'b110: ISIZEI = 6;
355
                        default: ISIZEI = 5;
356
                endcase
357
        end
358
 
359 20 ndumitrach
         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,
360 12 ndumitrach
                                 WBIT, ISIZES, ISELS, WRBIT, ISIZEW, STAGE, NULLSHIFT, ALUCONT, FLAGS, CXZ, RCXZ, NRORCXLE1, TZF, JMPC, LOOPC, ICODE1, DIVQSGN, DIVSGN, DIVRSGN, FIN, IDIV, AX) begin
361 2 ndumitrach
                WORD = FETCH[0][0];
362
                BASEL = FETCH[0][1] | &MOD;
363
                RASEL = FETCH[0][1] ? REG : RM; // destination
364
                BBSEL = {1'b0, !FETCH[0][1] | &MOD};
365
                RBSEL = FETCH[0][1] ? RM : REG; // source
366
                RSSEL = CPUStatus[2] ? CPUStatus[1:0] : (USEBP && !NOBP ? 2'b10 : 2'b11);
367
                WE = 5'b00000;          // 5=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
368
                ALUOP = 5'bxxxxx;
369
                EAC = {1'b0, RM};
370
                DISEL = 2'b01;          // ALU
371
                ISEL = 2'bxx;
372
                ASEL = 1'bx;
373
                AEXT = MOD == 2'b01;
374
                DEXT = 1'b0;
375
                DOSEL = 2'b00;  // ALU   
376
                MREQ = 1'b1;
377
                WR = 1'b0;
378
                ISIZE = 3'bxxx;
379
                IPWSEL = 1'b1;          // IP + ISIZE
380
                IFETCH = 1'b1;
381 20 ndumitrach
                IORQ = 1'b0;
382 2 ndumitrach
                status = 6'b00x0xx;
383
 
384
                DISP16 = MOD == 2'b10 || NOBP;
385
                NOBP = {MOD, RM} == 5'b00110;
386
                HALT = 1'b0;
387
                INTA = 1'b0;
388
                ALUSTAGE = 1'b0;
389
                DIVSTAGE = 1'b0;
390
                DECCX = 1'b0;
391
                IRQ = 1'b0;
392
                IRQL = 3'b110;  // unused opcode
393
                REPINT = 1'b0;
394
                NULLSEG = 1'b0;
395
                DIVOP = 1'b0;
396
 
397
                case(ICODE1) // one hot synthesis
398
// --------------------------------  mov R/M to/from R/SR  --------------------------------
399
                        0: begin
400
                                if(FETCH[0][2]) WORD = 1'b1;
401
                                if(FETCH[0][2:1] == 2'b10) BBSEL = 2'b11; // RB = SR
402
                                ALUOP = 31;     // PASS B
403
                                DISEL = {1'b0, &MOD};
404
                                ASEL = 1'b1;
405 14 ndumitrach
                                IRQ = FETCH[0][2] & FETCH[1][5]; // 25May2013 - generate invalid opcode exception for MOV FS and GS                                              
406
                                MREQ = ~&MOD & ~IRQ;
407 2 ndumitrach
                                WR = MREQ & !FETCH[0][1];
408 14 ndumitrach
                                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
409
                                ISIZE = IRQ ? 0 : ISIZES;
410 2 ndumitrach
                        end
411
// --------------------------------  mov IMM to R/M  --------------------------------
412
                        1: begin
413
                                RASEL = RM; // destination
414
                                BBSEL = 2'b10;
415
                                ALUOP = 31;     // PASS B
416
                                ISEL = ISELS;
417
                                ASEL = 1'b1;
418
                                MREQ = ~&MOD;
419
                                WR = MREQ;
420
                                WE[1:0] = WRBIT;         // RASEL_HI/RASEL_LO
421
                                ISIZE = ISIZEW;
422
                        end
423
// --------------------------------  mov IMM to R --------------------------------
424
                        2: begin
425
                                WORD = FETCH[0][3];
426
                                RASEL = FETCH[0][2:0]; // destination
427
                                BBSEL = 2'b10;                          // imm
428
                                WE[1:0] = WBIT;          // RASEL_HI/RASEL_LO
429
                                ALUOP = 31;     // PASS B
430
                                ISEL = 2'b00;
431
                                MREQ = 1'b0;
432
                                ISIZE = WORD ? 3 : 2;
433
                        end
434
// --------------------------------  mov mem to/from ACC --------------------------------
435
                        3: begin
436
                                RASEL = 0; // ACC
437
                                BBSEL = 2'b01;          // reg
438
                                RBSEL = 0; // ACC
439
                                ALUOP = 31;     // PASS B
440
                                EAC = 4'b0110;
441
                                DISEL = 2'b00;
442
                                ASEL = 1'b0;
443
                                AEXT = 1'b0;
444
                                WR = FETCH[0][1];
445
                                WE[1:0] = WRBIT;         // IP, RASEL_HI/RASEL_LO
446
                                ISIZE = 3;
447
                                NOBP = 1'b1;
448
                        end
449
// --------------------------------  segment override prefix --------------------------------
450
                        4: begin
451
                                status = {CPUStatus[5:3], 1'b1, FETCH[0][4:3]};
452
                                MREQ = 1'b0;
453
                                ISIZE = 1;
454
                        end
455
// --------------------------------  rep prefix --------------------------------
456
                        5: begin
457
                                status = {CPUStatus[5], 1'b1, FETCH[0][0], CPUStatus[2:0]};
458
                                MREQ = 1'b0;
459
                                ISIZE = 1;
460
                        end
461
// --------------------------------  lock prefix --------------------------------
462
                        6: begin
463
                                status = {1'b1, CPUStatus[4:0]};
464
                                MREQ = 1'b0;
465
                                ISIZE = 1;
466
                        end
467
// --------------------------------  FF block --------------------------------
468
                        7:      begin
469
                                ISIZE = ISIZES;
470
                                case({FETCH[0][0], REG})
471
                // --------------------------------  push R/M --------------------------------
472
                                        4'b1110:
473
                                                if(!(&MOD || STAGE[0])) begin    // stage1, read data in TMP16
474
                                                        WE[3] = 1'b1;           // TMP16
475
                                                        DISEL = 2'b00;
476
                                                        ASEL = 1'b1;
477
                                                        IFETCH = 1'b0;
478
                                                end else begin          // stage2, push R/TMP16
479
                                                        RASEL = 3'b100;         // write SP
480
                                                        RSSEL = 2'b10;                  // SS
481
                                                        ALUOP = 31;     // PASS B
482
                                                        WE[1:0] = 2'b11;         // RASEL_HI/RASEL_LO
483
                                                        EAC = 4'b1000;                  // SP - 2
484
                                                        DISEL = 2'b10;                  // ADDR
485
                                                        WR = 1'b1;
486
                                                end
487
                // --------------------------------  inc/dec R/M --------------------------------
488
                                        4'b0000, 4'b1000, 4'b0001, 4'b1001: begin
489
                                                ASEL = 1'b1;
490
                                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
491
                                                        WE[3] = 1'b1;           // TMP16
492
                                                        DISEL = 2'b00;                  // DIN
493
                                                        IFETCH = 1'b0;
494
                                                end else begin                                          // stage2, execute and write            
495
                                                        BASEL = &MOD;
496
                                                        RASEL = RM;                     // destination
497
                                                        ALUOP = {2'b01, FETCH[1][5:3]};
498
                                                        MREQ = ~BASEL;
499
                                                        WR = MREQ;
500
                                                        WE = {3'b100, WRBIT};           // flags, IP, RASEL_HI, RASEL_LO
501
                                                end
502
                                        end
503
                // --------------------------------  call/jmp near R/M --------------------------------
504
                                        4'b1010, 4'b1100: begin
505
                                                if(!STAGE[0] && ~&MOD) begin     // stage1, load op in TMP16
506
                                                        ASEL = 1'b1;
507
                                                        WE[3] = 1'b1;           // TMP16
508
                                                        DISEL = 2'b00;                  // DIN
509
                                                        IFETCH = 1'b0;
510
                                                end else begin          // stage2, push IP, jump
511
                                                        RASEL = 3'b100;         // write SP
512
                                                        RSSEL = 2'b10;          // SS
513
                                                        ALUOP = 31;     // PASS B
514
                                                        EAC = 4'b1000;          // SP - 2
515
                                                        DISEL = 2'b10;          // ADDR
516
                                                        DOSEL = 2'b01;  // IP    
517
                                                        MREQ = REG[1];
518
                                                        WR = MREQ;
519
                                                        WE[1:0] = {WR, WR};
520
                                                        IPWSEL = 1'b0;          // ALU
521
                                                end
522
                                        end
523
                // --------------------------------  call/jmp far R/M --------------------------------
524
                                        4'b1011, 4'b1101: begin
525
                                                ALUOP = 31;                             // PASS B
526
                                                IRQ = &MOD;
527
                                                case({STAGE[1:0], REG[1]})
528
                                                        3'b001: begin   // stage1, push CS
529
                                                                RASEL = 3'b100;         // write SP
530
                                                                BBSEL = 2'b11;
531
                                                                RBSEL = 3'b001;                 // CS
532
                                                                RSSEL = 2'b10;                  // SS
533
                                                                EAC = 4'b1000;                  // SP - 2
534
                                                                DISEL = 2'b10;                  // ADDR
535
                                                                MREQ = ~IRQ;
536
                                                                WR = MREQ;
537
                                                                IFETCH = IRQ;
538
                                                                WE[1:0] = IRQ ? 2'b00 : 2'b11;                   // RASEL_HI/RASEL_LO
539
                                                                ISIZE = 0;
540
                                                        end
541
                                                        3'b011, 3'b000: begin   // stage2, read offset in FETCH, ADDR16 in TMP16
542
                                                                RASEL = 3'b100;                 // SP   - write SP to SP for getting ADDR16 to TMP16
543
                                                                BBSEL = 2'b01;
544
                                                                RBSEL = 3'b100;                 // SP
545
                                                                WE[3:0] = IRQ ? 4'b0000 : 4'b1011;                       // TMP16, RASEL_HI, RASEL_LO
546
                                                                ASEL = 1'b1;
547
                                                                DOSEL = 2'b11;                  // load FETCH with DIN
548
                                                                IFETCH = IRQ;
549
                                                                MREQ = ~IRQ;
550
                                                                ISIZE = 0;
551
                                                        end
552
                                                        3'b101, 3'b010: begin   // stage3, read CS
553
                                                                RASEL = 3'b001;                 // CS
554
                                                                WE[2] = 1'b1;                   // RSSEL
555
                                                                EAC = 4'b1011;                  // TMP16 + 2
556
                                                                DISEL = 2'b00;                  // DIN
557
                                                                IFETCH = 1'b0;
558
                                                        end
559
                                                        3'b111, 3'b100: begin   // stage4, push IP, jump
560
                                                                RASEL = 3'b100;         // write SP
561
                                                                BBSEL = 2'b10;          // imm
562
                                                                RSSEL = 2'b10;          // SS
563
                                                                EAC = 4'b1000;          // SP - 2
564
                                                                DISEL = 2'b10;          // ADDR
565
                                                                DOSEL = 2'b01;          // IP    
566
                                                                ISEL = 2'b01;
567
                                                                MREQ = REG[1];
568
                                                                WR = MREQ;
569
                                                                WE[1:0] = {WR, WR};
570
                                                                IPWSEL = 1'b0;          // ALU
571
                                                        end
572
                                                endcase
573
                                        end
574
                // --------------------------------  bad opcode --------------------------------
575
                                        default: begin
576
                                                MREQ = 1'b0;
577
                                                IRQ = 1'b1;
578
                                                ISIZE = 0;
579
                                        end
580
                                endcase
581
                        end
582
// --------------------------------  push R/SR --------------------------------
583
                        8: begin
584
                                WORD = 1'b1;
585
                                RASEL = 3'b100;         // write SP
586
                                BBSEL = {~FETCH[0][6], 1'b1};
587
                                RBSEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // source
588
                                RSSEL = 2'b10;                  // SS
589
                                EAC = 4'b1000;                  // SP - 2
590
                                DISEL = 2'b10;                  // ADDR
591
                                WE[1:0] = 2'b11;         // RASEL_HI/RASEL_LO
592
                                ALUOP = 31;                             // PASS B
593
                                WR = 1'b1;
594
                                ISIZE = 1;
595
                        end
596
// --------------------------------  push Imm --------------------------------
597
                        9: begin
598
                                WORD = 1'b1;
599
                                RASEL = 3'b100;         // write SP
600
                                BBSEL = 2'b10;                  // imm
601
                                RSSEL = 2'b10;                  // SS
602
                                WE[1:0] = 2'b11;         // RASEL_HI/RASEL_LO
603
                                ALUOP = 31;                             // PASS B
604
                                EAC = 4'b1000;                  // SP - 2
605
                                DISEL = 2'b10;                  // ADDR
606
                                ISEL = 2'b00;
607
                                DEXT = FETCH[0][1];
608
                                WR = 1'b1;
609
                                ISIZE = FETCH[0][1] ? 2 : 3;
610
                        end
611
// --------------------------------  pusha --------------------------------
612
                        10: begin
613
                                WORD = 1'b1;
614
                                RASEL = 3'b100;         // write SP
615
                                RBSEL = STAGE[2:0];  // source
616
                                RSSEL = 2'b10;                  // SS
617
                                ALUOP = 31;                             // PASS B
618
                                EAC = 4'b1000;                  // SP - 2
619
                                DISEL = 2'b10;                  // ADDR
620
                                WR = 1'b1;
621
                                ISIZE = 1;
622 13 ndumitrach
                                IFETCH = STAGE[2:0] == 3'b111;
623
                                WE[1:0] = 2'b11;                                 // RASEL_HI, RASEL_LO
624
                                BASEL = STAGE[1:0] == 2'b00;     // 16May2013 - fix PUSHA SP pushed stack value, which should be the one before PUSHA
625
                                BBSEL[0] = STAGE[2:0] != 3'b100;  // SP stage
626 2 ndumitrach
                        end
627
// --------------------------------  pop R/M --------------------------------
628
                        11:
629
                                case(REG)
630
                                        3'b000: begin
631
                                                ISIZE = ISIZES;
632
                                                if(!STAGE[0]) begin      // pop TMP16/REG
633
                                                        RASEL = RM;             // destination
634
                                                        RSSEL = 2'b10;                  // SS
635
                                                        EAC = 4'b1001;                  // SP
636
                                                        DISEL = 2'b00;                  // DIN
637
                                                        IFETCH = &MOD;
638
                                                        WE[3:0] = IFETCH ? 4'b0011 : 4'b1000;            // TMP16, RASEL_HI, RASEL_LO
639
                                                end else begin                  // R/M <- TMP16
640
                                                        RASEL = RM; // destination
641
                                                        BBSEL = 2'b00;                  // TMP
642
                                                        ALUOP = 31;                             // PASS B
643
                                                        ASEL = 1'b1;
644
                                                        MREQ = ~&MOD;
645
                                                        WR = MREQ;
646
                                                        WE[1:0] = WR ? 2'b00 : 2'b11;            // RASEL_HI, RASEL_LO
647
                                                end
648
                                        end
649
                                        default:        begin           // bad opcode
650
                                                MREQ = 1'b0;
651
                                                ISIZE = 0;
652
                                                IRQ = 1'b1;
653
                                        end
654
                                endcase
655
// --------------------------------  pop R / SR --------------------------------
656
                        12: begin
657
                                WORD = 1'b1;
658
                                RASEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // destination
659
                                RSSEL = 2'b10;                  // SS
660
                                WE[2:0] = FETCH[0][6] ? 3'b011 : 3'b100;          // RSSEL, RASEL_HI, RASEL_LO
661
                                EAC = 4'b1001;                  // SP
662
                                DISEL = 2'b00;                  // DIN
663
                                ISIZE = 1;
664
                        end
665
// --------------------------------  popa --------------------------------
666
                        13: begin
667
                                RASEL = ~STAGE[2:0]; // destination
668
                                RSSEL = 2'b10;                  // SS
669
                                EAC = 4'b1001;                  // SP
670
                                DISEL = 2'b00;                  // DIN
671
                                ISIZE = 1;
672
                                IFETCH = &STAGE[2:0];
673
                                WE[1:0] = {STAGE[2:0] == 3'b011 ? 2'b00 : 2'b11};         // IP, RASEL_HI, RASEL_LO (skip SP)
674
                        end
675
// --------------------------------  xchg R with R/M/Acc --------------------------------
676
                        14: begin
677
                                WORD = FETCH[0][0] | FETCH[0][4];
678
                                ASEL = 1'b1;
679
                                MREQ = ~&MOD && !FETCH[0][4];
680
                                ALUOP = 31;                             // PASS B
681
                                ISIZE = FETCH[0][4] ? 1 : ISIZES;
682
                                if(!STAGE[0]) begin              // stage1, R/M/Acc -> REG -> TMP16
683
                                        BASEL = 1'b1;
684
                                        RASEL = FETCH[0][4] ? FETCH[0][2:0] : REG; // destination
685
                                        BBSEL = 2'b01;          // reg
686
                                        RBSEL = FETCH[0][4] ? 3'b000 : RM; // source
687
                                        DISEL = {1'b0, !MREQ};
688
                                        WE[1:0] = WBIT;          // RASEL_HI, RASEL_LO
689
                                        IFETCH = ~|FETCH[0][2:0]; // nop
690
                                end else begin          // stage2, TMP16 -> R/M/Acc
691
                                        RASEL = FETCH[0][4] ? 3'b000 : RM; // destination
692
                                        BBSEL = 2'b00;          // TMP16
693
                                        WR = MREQ;
694
                                        WE[1:0] = WRBIT;         // RASEL_HI, RASEL_LO
695
                                end
696
                        end
697
// --------------------------------  in --------------------------------
698
                        15:     begin
699
                                RASEL = 3'b000; // AX/AL
700
                                WE[1:0] = {WORD, 1'b1};          // RASEL_HI, RASEL_LO
701
                                DISEL = 2'b00;  //DIN
702
                                MREQ = 1'b0;
703
                                ISIZE = FETCH[0][3] ? 1 : 2;
704 20 ndumitrach
                                IORQ = 1'b1;
705
//                              EAC = 4'b1111;
706
//                              NULLSEG = 1'b1;
707 2 ndumitrach
                        end
708
// --------------------------------  out --------------------------------
709
                        16:     begin
710
                                DOSEL = 2'b11;  // AX
711
                                MREQ = 1'b0;
712
                                WR = 1'b1;
713
                                ISIZE = FETCH[0][3] ? 1 : 2;
714 20 ndumitrach
                                IORQ = 1'b1;
715
//                              EAC = 4'b1111;
716
//                              NULLSEG = 1'b1;
717 2 ndumitrach
                        end
718
// --------------------------------  xlat --------------------------------
719
                        17: begin
720
                                WORD = 1'b0;
721
                                RASEL = 3'b000;         // AL
722
                                WE[0] = 1'b1;            // RASEL_LO
723
                                EAC = 4'b1010;          // XLAT
724
                                DISEL = 2'b00;          // DIN 
725
                                ISIZE = 1;
726
                                NOBP = 1'b1;    // for RSSEL
727
                        end
728
// --------------------------------  lea --------------------------------
729
                        18: begin
730
                                RASEL = REG;                    // destination
731
                                WE[1:0] = {&MOD ? 2'b00 : 2'b11};                // RASEL_HI, RASEL_LO
732
                                DISEL = 2'b10;                  // EA
733
                                ASEL = 1'b1;
734
                                MREQ = 1'b0;
735
                                ISIZE = ISIZES;
736
                        end
737
// --------------------------------  lds, les --------------------------------
738
                        19: begin
739
                                WORD = 1'b1;
740
                                DISEL = 2'b00;                  // DIN
741
                                ASEL = 1'b1;
742
                                if(!STAGE[0]) begin              // stage1, load offset
743
                                        RASEL = REG;                    // destination
744
                                        IFETCH = &MOD;                  // bad opcode
745
                                        IRQ = IFETCH;
746
                                        ISIZE = 0;
747
                                        WE[3:0] = {2'b10, IFETCH ? 2'b00 : 2'b11};               // TMP16, RASEL_HI, RASEL_LO
748
                                end else begin                          // stage2, load segment
749
                                        RASEL = FETCH[0][0] ? 3'b011 : 3'b000; // ds/es
750
                                        WE[2] = 1'b1;                   // RSSEL
751
                                        EAC = 4'b1011;                  // TMP16 + 2
752
                                        ISIZE = ISIZES;
753
                                end
754
                        end
755
// --------------------------------  lahf, sahf --------------------------------
756
                        20: begin
757
                                WORD = 1'b0;
758
                                RASEL = 3'b100;                 // AH
759
                                WE = {!FETCH[0][0], 2'b00, FETCH[0][0], 1'b0};              // FLAGS, IP, RASEL_HI
760
                                ALUOP = FETCH[0][0] ? 30 : 31;                    // PASS/STORE FLAGS
761
                                MREQ = 1'b0;
762
                                ISIZE = 1;
763
                        end
764
// --------------------------------  pushf --------------------------------
765
                        21: begin
766
                                WORD = 1'b1;
767
                                RASEL = 3'b100;         // write SP
768
                                RSSEL = 2'b10;                  // SS
769
                                WE[1:0] = 2'b11;
770
                                ALUOP = 30;                             // pass flags
771
                                EAC = 4'b1000;                  // SP - 2
772
                                DISEL = 2'b10;                  // ADDR
773
                                WR = 1'b1;
774
                                ISIZE = 1;
775
                        end
776
// --------------------------------  popf --------------------------------
777
                        22: begin
778
                                ISIZE = 1;
779
                                IFETCH = STAGE[0];
780
                                if(!STAGE[0]) begin      // stage1, pop TMP16
781
                                        RSSEL = 2'b10;                  // SS
782
                                        WE[3] = 1'b1;                   // TMP16
783
                                        EAC = 4'b1001;                  // SP
784
                                        DISEL = 2'b00;
785
                                end else begin                  // stage2, TMP16 to FLAGS
786
                                        BASEL = 1'b0;
787
                                        WE[4] = 1'b1;                   // flags
788
                                        ALUOP = 31;                             // store flags
789
                                        MREQ = 1'b0;
790
                                end
791
                        end
792
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
793
                        23: begin
794
                                ASEL = 1'b1;
795
                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
796
                                        WE[3] = 1'b1;           // TMP16
797
                                        DISEL = 2'b00;                  // DIN
798
                                        IFETCH = 1'b0;
799
                                end else begin                                          // stage2, execute and write                    
800
                                        ALUOP = {2'b00, FETCH[0][2] ? 3'b100 : FETCH[0][5:3]};    // test = and
801
                                        MREQ = ~&MOD & ~|FETCH[0][2:1] & ~&FETCH[0][5:3];         // no cmp or test
802
                                        WR = MREQ;
803
                                        WE = {3'b100, WR | &FETCH[0][5:3] | FETCH[0][2] ? 2'b00 : WBIT};          // flags, RASEL_HI, RASEL_LO
804
                                        ISIZE = ISIZES;
805
                                end
806
                        end
807
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
808
                        24: begin
809
                                ASEL = 1'b1;
810
                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
811
                                        WE[3] = 1'b1;                   // TMP16
812
                                        DISEL = 2'b00;                  // DIN
813
                                        IFETCH = 1'b0;
814
                                end else begin                                          // stage2, execute and write            
815
                                        BASEL = &MOD;
816
                                        RASEL = RM;
817
                                        BBSEL = 2'b10;                  // imm
818
                                        ALUOP = {2'b00, FETCH[1][5:3]};
819
                                        ISEL = ISELS;
820
                                        DEXT = FETCH[0][1];
821
                                        MREQ = ~BASEL & ~&FETCH[1][5:3];
822
                                        WR = MREQ;
823
                                        WE = {3'b100, WR  | &FETCH[1][5:3]? 2'b00 : WBIT};              // flags, RASEL_HI, RASEL_LO
824
                                        ISIZE = ISIZEI;
825
                                end
826
                        end
827
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
828
                        25: begin // test
829
                                BASEL = 1'b1;
830
                                RASEL = 3'b000;         // acc
831
                                BBSEL = 2'b10;                                  // imm
832
                                WE = {3'b100, &FETCH[0][5:3] | FETCH[0][7] ? 2'b00 : WBIT};               // flags, RASEL_HI, RASEL_LO
833
                                ALUOP = {2'b00, FETCH[0][7] ? 3'b100 : FETCH[0][5:3]};
834
                                ISEL = 2'b00;
835
                                MREQ = 1'b0;
836
                                ISIZE = WORD ? 3 : 2;
837
                        end
838
// --------------------------------  inc/dec R16 --------------------------------
839
                        26: begin
840
                                WORD = 1'b1;
841
                                BASEL = 1'b1;
842
                                RASEL = FETCH[0][2:0]; // destination
843
                                WE = 5'b10011;          // flags, RASEL_HI, RASEL_LO
844
                                ALUOP = {2'b01, FETCH[0][5:3]};
845
                                MREQ = 1'b0;
846
                                ISIZE = 1;
847
                        end
848
// --------------------------------  test/???/not/neg/mul/imul/div/idiv --------------------------------
849
                        27: begin
850
                                ASEL = 1'b1;
851
                                case(REG)
852
                                        3'b000: begin           // TEST R/M with Imm
853
                                                if(!(&MOD || |STAGE[1:0])) begin // stage1, load op from memory in TMP16
854
                                                        DISEL = 2'b00;
855
                                                        WE[3] = 1'b1;                                   // mem in TMP16
856
                                                        IFETCH = 1'b0;
857
                                                end else begin
858
                                                        BASEL = &MOD;
859
                                                        RASEL = RM;     // destination
860
                                                        BBSEL = 2'b10;                  // imm
861
                                                        ALUOP = 5'b00100;               // AND
862
                                                        ISEL = ISELS;
863
                                                        MREQ = 1'b0;
864
                                                        WE[4] = 1'b1;                   // flags
865
                                                        ISIZE = ISIZEW;
866
                                                end
867
                                        end
868
                                        3'b010, 3'b011: begin   // NOT/NEG R/M
869
                                                if(!(&MOD || |STAGE[1:0])) begin // stage1, load op from memory in TMP16
870
                                                        DISEL = 2'b00;
871
                                                        WE[3] = 1'b1;                                   // mem in TMP16
872
                                                        IFETCH = 1'b0;
873
                                                end else begin
874
                                                        BASEL = &MOD;
875
                                                        RASEL = RM;     // destination
876
                                                        ALUOP = {2'b01, REG};
877
                                                        MREQ = ~&MOD;
878
                                                        WR = MREQ;
879
                                                        WE = {REG[0], 2'b00, WRBIT};             // flags, RASEL_HI, RASEL_LO
880
                                                        ISIZE = ISIZES;
881
                                                end
882
                                        end
883
                                        3'b100, 3'b101: begin   // MUL, IMUL
884
                                                ISIZE = ISIZES;
885
                                                ALUOP = {4'b1000, REG[0]};               // BASEL = FETCH[0][1] = 1
886 10 ndumitrach
                                                WE[4] = 1'b1;                   // fix MUL/IMUL 8bit flags bug
887 2 ndumitrach
                                                case(STAGE[1:0])
888
                                                        2'b00: begin            // stage1, RA -> TMP16, RB (mem) -> FETCH
889
                                                                MREQ = ~&MOD;
890
                                                                DISEL = {1'b0, MREQ};
891
                                                                RASEL = 3'b000; // AX
892
                                                                DOSEL = 2'b11;
893
                                                                IFETCH = 1'b0;
894
                                                        end
895 10 ndumitrach
                                                        2'b01: begin                    // stage2, write AX
896
                                                                WE[1:0] = 2'b11; // flags, RASEL_HI, RASEL_LO 
897 2 ndumitrach
                                                                RASEL = 3'b000; // AX
898
                                                                MREQ = 1'b0;
899
                                                                IFETCH = ~FETCH[0][0];
900
                                                        end
901
                                                        2'b10: begin                    // stage 2, write DX
902 10 ndumitrach
                                                                WE[1:0] = 2'b11; // flags, RASEL_HI, RASEL_LO    
903 2 ndumitrach
                                                                RASEL = 3'b010; // DX
904
                                                                MREQ = 1'b0;
905
                                                        end
906
                                                endcase
907
                                        end
908
                                        3'b110, 3'b111: begin   // div, idiv
909
                                                ISIZE = ISIZES;
910
                                                IRQL = 3'b000;  // divide overflow
911
                                                MREQ = 1'b0;
912
                                                case({DIVEND, STAGE[1:0]})
913
                                                        3'b000: begin           // stage1, RB (mem) -> FETCH
914
                                                                MREQ = ~&MOD;
915
                                                                DISEL = {1'b0, MREQ};
916
                                                                DOSEL = 2'b11;
917
                                                                IFETCH = 1'b0;
918
                                                                DIVSTAGE = ~QSGN;
919 20 ndumitrach
                                                                RASEL = 3'b000; // AX
920
                                                                ALUOP = 5'b01001;               // DEC
921 2 ndumitrach
                                                        end
922
                                                        3'b001: begin   // stage2, pre dec AX
923
//                                                              WORD = 1'b1;
924
                                                                RASEL = 3'b000; // AX
925
                                                                WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
926
                                                                ALUOP = 5'b01001;               // DEC
927
                                                                IFETCH = 1'b0;
928 20 ndumitrach
                                                                ALUSTAGE = ~(DIVQSGN && FETCH[0][0] && RCOUT);
929 2 ndumitrach
                                                        end
930
                                                        3'b010: begin // stage3, pre dec DX
931
                                                                RASEL = 3'b010;         // DX
932
                                                                WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
933
                                                                ALUOP = 5'b01001;               // DEC
934
                                                                IFETCH = 1'b0;
935
                                                        end
936
                                                        3'b011, 3'b111: begin   // stage4, div loop
937
                                                                RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
938
                                                                BBSEL = 2'b10;          // imm
939
                                                                WE[1:0] = {1'b1, WORD};          // RASEL_HI, RASEL_LO
940
                                                                ALUOP = {2'b00, DIVSGN ? 3'b000 : 3'b101};      // add/sub
941
                                                                ISEL = 2'b01;
942
                                                                DIVSTAGE = ~DIVEND;
943
                                                                ALUSTAGE = ~DIVEND | ~DIVQSGN;
944
                                                                DIVOP = 1'b1;
945 20 ndumitrach
                                                                IRQ = DIVIRQ; //~|STAGE[6:3] & DIVC & (~STAGE[2] | (~DIVSGN & IDIV)); // early overflow for positive quotient
946
                                                                IFETCH = (DIVEND && ~DIVQSGN && ~DIVRSGN) || DIVIRQ;
947 2 ndumitrach
                                                        end
948
                                                        3'b100: begin           // stage5, post inc R
949
                                                                RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
950
                                                                WE[1:0] = {1'b1, WORD};          // RASEL_HI, RASEL_LO
951
                                                                ALUOP = 5'b01000;       // inc
952
                                                                IFETCH = ~DIVSGN;
953
                                                        end
954
                                                        default: begin  // stage6, post inc Q
955
                                                                RASEL = 3'b000; // AX/AL
956
                                                                WE[1:0] = {WORD, 1'b1};          // RASEL_HI, RASEL_LO
957
                                                                ALUOP = 5'b01000;       // inc
958 12 ndumitrach
//                                                              IRQ = SOUT ^ DIVSGN;    // overflow for negative quotient - fixed 12Apr2013 - IDIV bug when Q=0
959
                                                                IRQ = ~(FIN[7] | (FETCH[0][0] ? AX[15] : AX[7])); // overflow for negative quotient
960 2 ndumitrach
                                                        end
961
                                                endcase
962
                                        end
963
                                        default: begin          // bad opcode
964
                                                MREQ = 1'b0;
965
                                                ISIZE = 0;
966
                                                IRQ = 1'b1;
967
                                        end
968
                                endcase
969
                        end
970
// --------------------------------  imul imm --------------------------------
971
                        28: begin
972
                                ASEL = 1'b1;
973
                                if(!STAGE[0]) begin      // stage1, load op from memory (or RA) in TMP16
974
                                        RASEL = RM;
975
                                        DISEL = 2'b00;                  // DIN
976
                                        DOSEL = 2'b11;
977
                                        ISEL = ISELS;
978
                                        DEXT = FETCH[0][1];
979
                                        BBSEL = 2'b10;                  // imm
980
                                        MREQ = ~&MOD;
981
                                        WE[3] = MREQ;                   // TMP16
982
                                        IFETCH = 1'b0;
983
                                end else begin                                          // stage2, execute and write            
984
                                        RASEL = REG;
985
                                        ALUOP = 5'b10001;               // imul
986
                                        MREQ = 1'b0;
987
                                        WE = 5'b10011;          // flags, RASEL_HI, RASEL_LO
988
                                        ISIZE = ISIZEI;
989
                                end
990
                        end
991
// --------------------------------  aad --------------------------------
992
                        29: begin
993
                                MREQ = 1'b0;
994
                                WORD = 1'b0;
995
                                BASEL = 1'b1;
996
                                IFETCH = &STAGE[1:0];
997
                                case(STAGE[1:0])
998
                                        2'b00: begin    // stage1, load AH in TMP16, move imm in FETCH
999
                                                RASEL = 3'b100;         // AH
1000
                                                DISEL = 2'b00;                  // DIN
1001
                                                DOSEL = 2'b11;                  // write FETCH
1002
                                                ISEL = 2'b00;                   // RB -> FETCH
1003
                                                BBSEL = 2'b10;                  // imm
1004
                                        end
1005
                                        2'b01: begin                            // stage2, TMP16 <- TMP16 * 10
1006
                                                ALUOP = 5'b10000;               // mul
1007
                                                WE[3] = 1'b1;                   // TMP16
1008
                                        end
1009
                                        2'b10: begin                    // stage3, AL <- TMP16 + AL
1010
                                                RASEL = 3'b000;         // AL
1011
                                                BBSEL = 2'b00;          // TMP16
1012
                                                WE = 5'b10001;          // flags, RASEL_LO
1013
                                                ALUOP = 5'b00000;       // ADD
1014
                                        end
1015
                                        2'b11: begin                    // stage4, AH <- 0
1016
                                                RASEL = 3'b100;         // AH
1017
                                                RBSEL = 3'b100;         // AH
1018
                                                WE[1] = 1'b1;           // RASEL_HI
1019
                                                ALUOP = 5'b00101;       // SUB
1020
                                                ISIZE = 2;
1021
                                        end
1022
                                endcase
1023
                        end
1024
// --------------------------------  daa, das, aaa, aas --------------------------------
1025
                        30: begin
1026
                                WORD = FETCH[0][4];
1027
                                RASEL = 3'b000;         // AX,AL
1028
                                WE = {3'b100, FETCH[0][4], 1'b1};                // flags, RASEL_HI, RASEL_LO
1029
                                ALUOP = {2'b01, FETCH[0][5:3]};
1030
                                MREQ = 1'b0;
1031
                                ISIZE = 1;
1032
                        end
1033
// --------------------------------  shift/rot --------------------------------
1034
                        31: begin       // imm
1035
                                ALUOP = {4'b1110, FETCH[0][4:1] != 4'b1000};
1036
                                ASEL = 1'b1;
1037
                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
1038
                                        WE[3] = 1'b1;                   // TMP16
1039
                                        DISEL = 2'b00;                  // DIN
1040
                                        IFETCH = 1'b0;
1041
                                end else begin                                          // stage2, execute and write            
1042
                                        BASEL = &MOD && ~|STAGE[2:1];
1043
                                        RASEL = RM;
1044
                                        BBSEL = FETCH[0][1] ? 2'b01 : 2'b10; // imm/reg
1045
                                        RBSEL = 3'b001;         // CL
1046
                                        ISEL = ISELS;
1047
                                        IRQ = REG == 3'b110;
1048
                                        MREQ = ~&MOD && ~NULLSHIFT && ~ALUCONT && ~IRQ;
1049
                                        WR = MREQ;
1050
                                        WE = NULLSHIFT || IRQ ? 5'b00000 : ALUCONT ? 5'b11000 : {3'b100, WRBIT};                // flags, TMP16, RASEL_HI, RASEL_LO
1051
                                        IFETCH = ~ALUCONT || IRQ;
1052
                                        ALUSTAGE = 1'b1;
1053
                                        if(IRQ) ISIZE = 0;
1054
                                        else case({|FETCH[0][4:1], DISP16, AEXT})
1055
                                                3'b100: ISIZE = 2;
1056
                                                3'b000, 3'b101: ISIZE = 3;
1057
                                                3'b001, 3'b110: ISIZE = 4;
1058
                                                default: ISIZE = 5;
1059
                                        endcase
1060
                                end
1061
                        end
1062
// --------------------------------  (rep)movs --------------------------------
1063
                        32: begin
1064
                                BASEL = 1'b1;
1065
                                AEXT = 1'b0;
1066
                                DISP16 = 1'b0;
1067
                                NOBP = 1'b1;    // for RSSEL
1068
                                if(!STAGE[0]) begin              // stage1, read DS:[SI] in TMP16, inc/dec SI
1069
                                        RASEL = 3'b110;         // SI
1070
                                        ALUOP = {4'b0100, FLAGS[10]};
1071
                                        EAC = 4'b0100;          // SI+DISP
1072
                                        DISEL = 2'b11;          // ALU 16bit
1073
                                        IFETCH = RCXZ;  // REP & CX==0
1074
                                        MREQ = ~RCXZ;
1075
                                        WE = IFETCH ? 5'b00000 : 5'b01011;              // TMP16, RASEL_HI, RASEL_LO
1076
                                end else begin                  // stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
1077
                                        RASEL = 3'b111;         // DI
1078
                                        RSSEL = 2'b00;          // ES
1079
                                        WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
1080
                                        ALUOP = {4'b0100, FLAGS[10]};
1081
                                        EAC = 4'b0101;          // DI + DISP
1082
                                        DISEL = 2'b11;          // ALU 16bit
1083
                                        DOSEL = 2'b10;          // TMP16                
1084
                                        WR = 1'b1;
1085
                                        IFETCH = NRORCXLE1;  // not REP or CX<=1
1086
                                        DECCX = CPUStatus[4];
1087
                                        REPINT = 1'b1;
1088
                                end
1089
                                ISIZE = IFETCH ? 1 : 0;
1090
                        end
1091
// --------------------------------  (rep)cmps --------------------------------
1092
                        33: begin
1093
                                DISP16 = 1'b0;
1094
                                AEXT = 1'b0;
1095
                                NOBP = 1'b1;    // for RSSEL
1096
                                case(STAGE[1:0])
1097 5 ndumitrach
                                        2'b00: begin            // stage1, read ES:[DI] in FETCH[3:2], inc/dec DI
1098 2 ndumitrach
                                                RASEL = 3'b111;         // SI
1099
                                                RSSEL = 2'b00;          // ES
1100
                                                ALUOP = {4'b0100, FLAGS[10]};
1101
                                                EAC = 4'b0101;          // DI+DISP
1102
                                                DISEL = 2'b11;          // ALU 16bit
1103
                                                DOSEL = 2'b11;          // read data to FETCH
1104 5 ndumitrach
                                                IFETCH = RCXZ;//(~|CXZ || (CPUStatus[3] ^ TZF));        // REP & CX==0
1105
                                                MREQ = ~RCXZ;
1106 2 ndumitrach
                                                WE[1:0] = IFETCH ? 2'b00 : 2'b11;                // RASEL_HI, RASEL_LO
1107
                                        end
1108
                                        2'b01: begin            // stage2, read DS:[SI] in TMP16, inc/dec SI
1109
                                                RASEL = 3'b110;         // DI
1110
                                                ALUOP = {4'b0100, FLAGS[10]};
1111
                                                EAC = 4'b0100;          // SI+DISP
1112
                                                DISEL = 2'b11;          // ALU 16bit
1113
                                                IFETCH = 1'b0;
1114
                                                WE[3:0] = 4'b1011;               // RASEL_HI, RASEL_LO
1115
                                        end
1116 5 ndumitrach
                                        2'b10: begin            // stage3, compare TMP16 with imm, set flags, dec CX
1117 2 ndumitrach
                                                BASEL = 1'b0;                   // TMP16
1118
                                                BBSEL = 2'b10;                  // imm
1119
                                                ISEL = 2'b01;
1120
                                                WE[4] = 1'b1;                   // flags
1121
                                                ALUOP = 5'b00111;               // cmp
1122
                                                MREQ = 1'b0;
1123 5 ndumitrach
                                                IFETCH = NRORCXLE1 | (CPUStatus[3] ^ CMPS);
1124 2 ndumitrach
                                                DECCX = CPUStatus[4];
1125
                                                ALUSTAGE = 1'b1;
1126
                                                REPINT = 1'b1;
1127
                                        end
1128
                                endcase
1129
                                ISIZE = IFETCH ? 1 : 0;
1130
                        end
1131
// --------------------------------  (rep)scas --------------------------------
1132
                        34: begin
1133
                                DISP16 = 1'b0;
1134
                                AEXT = 1'b0;
1135
                                if(!STAGE[0]) begin      // stage1, read ES:[DI] in TMP16, inc/dec DI
1136
                                        RASEL = 3'b111;         // DI
1137
                                        RSSEL = 2'b00;          // ES
1138
                                        ALUOP = {4'b0100, FLAGS[10]};
1139
                                        EAC = 4'b0101;          // DI+DISP
1140
                                        DISEL = 2'b11;          // ALU 16bit
1141 5 ndumitrach
                                        IFETCH = RCXZ;//(~|CXZ || (CPUStatus[3] ^ TZF));        // REP & CX==0
1142
                                        MREQ = ~RCXZ;
1143 2 ndumitrach
                                        WE[3:0] = IFETCH ? 4'b0000 : 4'b1011;            // TMP16, RASEL_HI, RASEL_LO
1144
                                end else begin  //stage2, compare AL/AX with TMP16, set flags, dec CX
1145
                                        RASEL = 3'b000;         // AL/AX
1146
                                        BBSEL = 2'b00;                  // TMP16
1147
                                        WE[4] = 1'b1;                   // flags
1148
                                        ALUOP = 5'b00111;               // cmp
1149
                                        MREQ = 1'b0;
1150 5 ndumitrach
                                        IFETCH = NRORCXLE1 | (CPUStatus[3] ^ SCAS);
1151 2 ndumitrach
                                        DECCX = CPUStatus[4];
1152
                                        REPINT = 1'b1;
1153
                                end
1154
                                ISIZE = IFETCH ? 1 : 0;
1155
                        end
1156
// --------------------------------  (rep)lods --------------------------------
1157
                        35: begin
1158
                                BASEL = 1'b1;
1159
                                DISP16 = 1'b0;
1160
                                AEXT = 1'b0;
1161
                                NOBP = 1'b1;    // for RSSEL
1162
                                if(!STAGE[0]) begin              // stage1, read DS:[SI] in AL/AX
1163
                                        RASEL = 3'b000;         // AX
1164
                                        EAC = 4'b0100;          // SI+DISP
1165
                                        DISEL = 2'b00;          // DIN
1166
                                        IFETCH = RCXZ;  // REP & CX==0
1167
                                        MREQ = ~RCXZ;
1168
                                        WE[1:0] = IFETCH ? 2'b00 : {WORD, 1'b1};         // RASEL_HI, RASEL_LO
1169
                                end else begin          // stage2, inc/dec SI, dec CX
1170
                                        RASEL = 3'b110;         // SI
1171
                                        ALUOP = {4'b0100, FLAGS[10]};
1172
                                        DISEL = 2'b11;          // ALU 16bit
1173
                                        IFETCH = NRORCXLE1;  // nor REP or CX<=1
1174
                                        MREQ = 1'b0;
1175
                                        WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
1176
                                        DECCX = CPUStatus[4];
1177
                                        REPINT = 1'b1;
1178
                                end
1179
                                ISIZE = IFETCH ? 1 : 0;
1180
                        end
1181
// --------------------------------  (rep)stos --------------------------------
1182
                        36: begin  // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
1183
                                BASEL = 1'b1;
1184
                                DISP16 = 1'b0;
1185
                                AEXT = 1'b0;
1186
                                RASEL = 3'b111;         // DI
1187
                                RSSEL = 2'b00;          // ES
1188
                                ALUOP = {4'b0100, FLAGS[10]};
1189
                                EAC = 4'b0101;          // DI + DISP
1190
                                DISEL = 2'b11;          // ALU 16bit
1191
                                DOSEL = 2'b11;          // AX
1192
                                IFETCH = NRORCXLE1;  // not REP or CX<=1
1193
                                MREQ = ~RCXZ;
1194
                                WR = ~RCXZ;
1195
                                WE[1:0] = {MREQ, MREQ};          // RASEL_HI, RASEL_LO
1196
                                DECCX = CPUStatus[4] && |CXZ;
1197
                                REPINT = 1'b1;
1198
                                ISIZE = IFETCH ? 1 : 0;
1199
                        end
1200
// --------------------------------  (rep)ins --------------------------------
1201
                        37: begin
1202
                                BASEL = 1'b1;
1203
                                DISP16 = 1'b0;
1204
                                AEXT = 1'b0;
1205
                                if(!STAGE[0]) begin      // stage1, input in TMP16
1206
                                        WE[3] = 1'b1;           // TMP16
1207
                                        DISEL = 2'b00;          //DIN
1208
                                        IFETCH = RCXZ;          // REP & CX==0
1209
                                        MREQ = 1'b0;
1210 20 ndumitrach
                                        IORQ = ~RCXZ;
1211
//                                      EAC = {~RCXZ, 3'b111};
1212
//                                      NULLSEG = 1'b1;
1213 2 ndumitrach
                                end else begin                  // stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
1214
                                        RASEL = 3'b111;         // DI
1215
                                        RSSEL = 2'b00;          // ES
1216
                                        WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
1217
                                        ALUOP = {4'b0100, FLAGS[10]};
1218
                                        EAC = 4'b0101;          // DI + DISP
1219
                                        DISEL = 2'b11;          // ALU 16bit
1220
                                        DOSEL = 2'b10;          // TMP16                
1221
                                        WR = 1'b1;
1222
                                        IFETCH = NRORCXLE1;  // not REP or CX<=1
1223
                                        DECCX = CPUStatus[4];
1224
                                        REPINT = 1'b1;
1225
                                end
1226
                                ISIZE = IFETCH ? 1 : 0;
1227
                        end
1228
// --------------------------------  (rep)outs --------------------------------
1229
                        38: begin
1230
                                BASEL = 1'b1;
1231
                                DISP16 = 1'b0;
1232
                                NOBP = 1'b1;    // for RSSEL
1233
                                if(!STAGE[0]) begin              // stage1, read DS:[SI] in TMP16, inc/dec SI
1234
                                        AEXT = 1'b0;            // tweak for speed (can be moved outside <if>)
1235
                                        RASEL = 3'b110;         // SI
1236
                                        ALUOP = {4'b0100, FLAGS[10]};
1237
                                        EAC = 4'b0100;          // SI+DISP
1238
                                        DISEL = 2'b11;          // ALU 16bit
1239
                                        IFETCH = RCXZ;  // REP & CX==0
1240
                                        MREQ = ~RCXZ;
1241
                                        WE[3:0] = IFETCH ? 4'b0000 : 4'b1011;            // TMP16, RASEL_HI, RASEL_LO
1242
                                end else begin                  // stage2, out TMP16 at port DX, dec CX
1243
                                        DOSEL = 2'b10;          // TMP16                
1244
                                        MREQ = 1'b0;
1245 20 ndumitrach
                                        IORQ = 1'b1;
1246
//                                      EAC = 4'b1111;
1247 2 ndumitrach
                                        WR = 1'b1;
1248
                                        IFETCH = NRORCXLE1;  // not REP or CX<=1
1249
                                        DECCX = CPUStatus[4];
1250
                                        REPINT = 1'b1;
1251 20 ndumitrach
//                                      NULLSEG = 1'b1;
1252 2 ndumitrach
                                end
1253
                                ISIZE = IFETCH ? 1 : 0;
1254
                        end
1255
// --------------------------------  call/jmp direct near --------------------------------
1256
                        39: begin       // jump long
1257
                                WORD = 1'b1;
1258
                                ALUOP = 0;                       // ADD
1259
                                DISEL = 2'b10;          // ADDR
1260
                                ISIZE = FETCH[0][1] ? 2 : 3;
1261
                                RASEL = 3'b100; // write SP
1262
                                RSSEL = 2'b10;          // SS
1263
                                DOSEL = 2'b01;          // IP
1264
                                EAC = 4'b1000;          // SP - 2
1265
                                BBSEL = 2'b10;          // imm
1266
                                ISEL = 2'b00;
1267
                                DEXT = FETCH[0][1];
1268
                                MREQ = !FETCH[0][0];
1269
                                WR = MREQ;
1270
                                WE[1:0] = FETCH[0][0] ? 2'b00 : 2'b11;             // RASEL_HI/RASEL_LO
1271
                                IPWSEL = 1'b0;          // ALU
1272
                        end
1273
// --------------------------------  call/jmp far imm --------------------------------
1274
                        40: begin
1275
                                WORD = 1'b1;
1276
                                ALUOP = 31;                             // PASS B
1277
                                case({STAGE[1:0], FETCH[0][6]})
1278
                                        3'b000: begin   // stage1, push CS
1279
                                                RASEL = 3'b100;         // write SP
1280
                                                BBSEL = 2'b11;
1281
                                                RBSEL = 3'b001;                 // CS
1282
                                                RSSEL = 2'b10;                  // SS
1283
                                                EAC = 4'b1000;                  // SP - 2
1284
                                                DISEL = 2'b10;                  // ADDR
1285
                                                WR = 1'b1;
1286
                                                IFETCH = 1'b0;
1287
                                                WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1288
                                        end
1289
                                        3'b010, 3'b001: begin   // stage2, load CS
1290
                                                RASEL = 3'b001;         // CS
1291
                                                BBSEL = 2'b10;          // imm
1292
                                                WE[2] = 1'b1;           // RSSEL
1293
                                                ISEL = 2'b10;
1294
                                                MREQ = 1'b0;
1295
                                                IFETCH = 1'b0;
1296
                                        end
1297
                                        3'b100, 3'b011: begin   // stage3, push IP, load IP
1298
                                                RASEL = 3'b100;         // write SP
1299
                                                BBSEL = 2'b10;          // imm
1300
                                                RSSEL = 2'b10;          // SS
1301
                                                EAC = 4'b1000;          // SP - 2
1302
                                                DISEL = 2'b10;          // ADDR
1303
                                                DOSEL = 2'b01;          // IP    
1304
                                                ISEL = 2'b00;
1305
                                                MREQ = FETCH[0][4];
1306
                                                WR = MREQ;
1307
                                                WE[1:0] = {WR, WR};
1308
                                                IPWSEL = 1'b0;          // ALU
1309
                                                ISIZE = 5;
1310
                                        end
1311
                                endcase
1312
                        end
1313
// --------------------------------  ret near --------------------------------
1314
                        41: begin
1315 11 ndumitrach
                                WORD = 1'b1;            // fix RET n alignment bug - 03Apr2013
1316 2 ndumitrach
                                ISIZE = FETCH[0][0] ? 1 : 3;
1317
                                IFETCH = STAGE[0];
1318
                                ALUOP = 31;                     // PASS B
1319
                                if(!STAGE[0]) begin      // stage1, pop TMP16
1320
                                        RSSEL = 2'b10;                  // SS
1321
                                        WE[3] = 1'b1;                   // TMP16
1322
                                        ASEL = 1'b0;
1323
                                        AEXT = 1'b0;
1324
                                        DISP16 = 1'b1;
1325
                                        EAC = {1'b1, !FETCH[0][0], 2'b01};                        // SP + 2 (+ imm) 
1326
                                        DISEL = 2'b00;
1327
                                end else begin                  // stage2, TMP16 to IP
1328
                                        BBSEL = 2'b00;          // TMP16        
1329
                                        IPWSEL = 1'b0;          // ALU
1330
                                        MREQ = 1'b0;
1331
                                end
1332
                        end
1333
// --------------------------------  ret far --------------------------------
1334
                        42: begin
1335 11 ndumitrach
                                WORD = 1'b1;            // fix RET n alignment bug - 03Apr2013
1336 2 ndumitrach
                                ALUOP = 31;                     // PASS B
1337
                                RSSEL = 2'b10;                  // SS
1338
                                IFETCH = STAGE[1];
1339
                                DISEL = 2'b00;                  // DIN
1340
                                case(STAGE[1:0])
1341
                                        2'b00: begin    // stage1, pop IP in TMP16
1342
                                                WE[3] = 1'b1;                   // TMP16
1343
                                                EAC = 4'b1001;                  // SP + 2
1344
                                        end
1345
                                        2'b01: begin            // stage2, pop CS, TMP16 <- RA
1346
                                                RASEL = 3'b001; // CS
1347
                                                WE[2] = 1'b1;
1348
                                                EAC = {1'b1, !FETCH[0][0], 2'b01};
1349
                                                ASEL = 1'b0;
1350
                                                AEXT = 1'b0;
1351
                                                DISP16 = 1'b1;
1352
                                                BASEL = 1'b0;           // RA <- TMP16
1353
                                        end
1354
                                        2'b10: begin            // stage3, IP <- TMP16
1355
                                                BBSEL = 2'b00;          // TMP16
1356
                                                IPWSEL = 1'b0;          // ALU
1357
                                                MREQ = 1'b0;
1358
                                                ISIZE = FETCH[0][0] ? 1 : 3;
1359
                                        end
1360
                                endcase
1361
                        end
1362
// --------------------------------  iret --------------------------------
1363
                        43: begin
1364
                                ALUOP = 31;                     // PASS B
1365
                                RSSEL = 2'b10;                  // SS
1366
                                ISIZE = 1;
1367
                                IFETCH = &STAGE[1:0];
1368
                                case(STAGE[1:0])
1369
                                        2'b00: begin    // stage1, pop IP in FETCH
1370
                                                EAC = 4'b1001;                  // SP + 2
1371
                                                DOSEL = 2'b11;                  // write FETCH
1372
                                        end
1373
                                        2'b01: begin            // stage2, pop CS
1374
                                                RASEL = 3'b001; // CS
1375
                                                WE[2] = 1'b1;
1376
                                                EAC = {1'b1, !FETCH[0][0], 2'b01};
1377
                                                DISEL = 2'b00;
1378
                                                ASEL = 1'b0;
1379
                                                AEXT = 1'b0;
1380
                                                DISP16 = 1'b1;
1381
                                        end
1382
                                        2'b10: begin            // stage3, pop flags in TMP16
1383
                                                WE[3] = 1'b1;                   // TMP16
1384
                                                EAC = 4'b1001;                  // SP
1385
                                                DISEL = 2'b00;
1386
                                        end
1387
                                        2'b11: begin            // stage4, IP <- FETCH, FLAGS <- TM
1388
                                                BASEL = 1'b0;
1389
                                                BBSEL = 2'b10;          // imm
1390
                                                WE[4] = 1'b1;           // flags
1391
                                                ISEL = 2'b01;
1392
                                                DEXT = 1'b0;
1393
                                                IPWSEL = 1'b0;          // ALU
1394
                                                MREQ = 1'b0;
1395
                                        end
1396
                                endcase
1397
                        end
1398
// --------------------------------  cbw/cwd --------------------------------
1399
                        44: begin
1400
                                RASEL = FETCH[0][0] ? 3'b010 : 3'b100; // AH/DX
1401
                                RBSEL = 3'b000; // AX
1402
                                WE[1:0] = {1'b1, FETCH[0][0]};             // RASEL_HI, RASEL_LO
1403
                                ALUOP = {4'b1101, FETCH[0][0]};   // cbw/cwd
1404
                                MREQ = 1'b0;
1405
                                ISIZE = 1;
1406
                        end
1407
// --------------------------------  JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
1408
                        45: begin  // loop/loopz/loopnz/jcxz
1409
                                ALUOP = 0;                       // add
1410
                                ISIZE = 2;
1411
                                DOSEL = 2'b01;          // IP
1412
                                BBSEL = 2'b10;          // imm
1413
                                ISEL = 2'b00;
1414
                                DEXT = 1'b1;
1415
                                MREQ = 1'b0;
1416
                                IPWSEL = FETCH[0][7] ? LOOPC[FETCH[0][1:0]] : (JMPC[FETCH[0][3:1]] ~^ FETCH[0][0]);
1417
                                DECCX = FETCH[0][7] && (FETCH[0][1:0] != 2'b11);
1418
                        end
1419
// --------------------------------  CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
1420
                        46: begin
1421
                                WE[4] = 1'b1;           // flags
1422
                                ALUOP = 5'b11001;       // flag op
1423
                                ISIZE = 1;
1424
                                MREQ = 1'b0;
1425
                        end
1426
// --------------------------------  enter --------------------------------
1427
                        47: begin
1428
                                WORD = 1'b1;
1429
                                WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1430
                                case(STAGE[1:0])
1431
                                        2'b00: begin            // push BP
1432
                                                RASEL = 3'b100;         // write SP
1433
                                                RBSEL = 3'b101;                 // BP
1434
                                                RSSEL = 2'b10;                  // SS
1435
                                                EAC = 4'b1000;                  // SP - 2
1436
                                                DISEL = 2'b10;                  // ADDR
1437
                                                ALUOP = 31;                             // PASS B
1438
                                                WR = 1'b1;
1439
                                                IFETCH = 1'b0;
1440
                                        end
1441
                                        2'b01: begin            // mov BP, SP
1442
                                                RASEL = 3'b101; // BP
1443
                                                RBSEL = 3'b100; // SP
1444
                                                ALUOP = 31;                             // PASS B
1445
                                                MREQ = 1'b0;
1446
                                                IFETCH = 1'b0;
1447
                                        end
1448
                                        2'b10: begin            // sub SP, imm
1449
                                                BASEL = 1'b1;
1450
                                                RASEL = 3'b100; // SP
1451
                                                BBSEL = 2'b10;
1452
                                                ALUOP = 5'b00101;       // sub
1453
                                                ISEL = 2'b00;
1454
                                                MREQ = 1'b0;
1455
                                                ISIZE = 4;
1456
                                        end
1457
                                endcase
1458
                        end
1459
// --------------------------------  leave --------------------------------
1460
                        48: begin
1461
                                WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1462
                                if(!STAGE[0]) begin      // stage1, mov sp, bp
1463
                                        RASEL = 3'b100; // BP
1464
                                        RBSEL = 3'b101; // SP
1465
                                        ALUOP = 31;                             // PASS B
1466
                                        MREQ = 1'b0;
1467
                                        IFETCH = 1'b0;
1468
                                end else begin                  // stage2, pop bp
1469
                                        RASEL = 3'b101;         // BP
1470
                                        RSSEL = 2'b10;                  // SS
1471
                                        EAC = 4'b1001;                  // SP
1472
                                        DISEL = 2'b00;                  // DIN
1473
                                        ISIZE = 1;
1474
                                end
1475
                        end
1476
// --------------------------------  int, int 3, into --------------------------------
1477
                        49: begin
1478
                                MREQ = 1'b0;
1479
                                ISIZE = FETCH[0][1:0] == 2'b01 ? 2 : 1;
1480
                                IRQ = ~FETCH[0][1] | FLAGS[11];
1481
                                IRQL = FETCH[0][1] ? 3'b100 : {1'b0, ~FETCH[0][1:0]};      // 4, 2, 3
1482
                        end
1483
// --------------------------------  bound --------------------------------
1484
                        50: begin
1485
                                WORD = 1'b1;
1486
                                DOSEL = 2'b11;                  // load FETCH with DIN
1487
                                case(STAGE[1:0])
1488
                                        2'b00: begin // stage1,  read min in FETCH, ADDR16 in TMP16
1489
                                                RASEL = 3'b100;                 // SP   - write SP to SP for getting ADDR16 to TMP16
1490
                                                BBSEL = 2'b01;
1491
                                                RBSEL = 3'b100;                 // SP
1492
                                                ALUOP = 31;                             // PASS B
1493
                                                WE[3:0] = 4'b1011;                       // TMP16, RASEL_HI, RASEL_LO
1494
                                                ASEL = 1'b1;
1495
                                                IRQ = &MOD;             // illegal instruction
1496
                                                ISIZE = 0;
1497
                                                IFETCH = IRQ;
1498
                                        end
1499
                                        2'b01, 2'b10, 2'b11: begin      // stage2,3,4 load min/max in TMP16, compare reg with imm
1500
                                                BBSEL = 2'b10;                  // imm
1501
                                                ALUOP = 5'b00111;               // cmp
1502
                                                EAC = 4'b1011;                  // TMP16 + 2
1503
                                                ISEL = 2'b01;
1504
                                                IRQ = STAGE[1] & (STAGE[0] ? ~TLF & ~TZF : TLF);
1505
                                                MREQ = ~&STAGE[1:0];
1506
                                                IFETCH = IRQ | ~MREQ;
1507
                                                IRQL = 3'b101;
1508
                                                ISIZE = IRQ ? 0 : ISIZES;        // return address is BOUND
1509
                                        end
1510
                                endcase
1511
                        end
1512
// --------------------------------  hlt --------------------------------
1513
                        51: begin
1514
                                IFETCH = 1'b0;
1515
                                HALT = 1'b1;
1516
                                MREQ = 1'b0;
1517
                        end
1518
// --------------------------------  wait --------------------------------
1519
                        52: begin       // do nothing
1520
                                ISIZE = 1;
1521
                                MREQ = 1'b0;
1522
                        end
1523
// --------------------------------  aam --------------------------------
1524
                        53: begin
1525
                                MREQ = 1'b0;
1526
                                IRQL = 3'b000;  // divide overflow
1527
                                ISIZE = 2;
1528
                                case({DIVEND, STAGE[1:0]})
1529
                                        3'b000: begin   // stage1, clear AH
1530
                                                BASEL = 1'b0;    // TMP16
1531
                                                RASEL = 3'b100; // AH
1532
                                                BBSEL = 2'b00;   // TMP16
1533
                                                WE[1] = 1'b1;    // RASEL_HI
1534
                                                ALUOP = 5'b00101;       // sub
1535
                                                IFETCH = 1'b0;
1536
                                        end
1537
                                        3'b001, 3'b101: begin   // stage2, div
1538
                                                RASEL = 3'b100; // AH
1539
                                                BASEL = 1'b1;
1540
                                                BBSEL = 2'b10;   // imm
1541
                                                WE[1] = 1'b1;    // RASEL_HI
1542
                                                ALUOP = 5'b00101;       // sub
1543
                                                ISEL = 2'b00;
1544
                                                DIVSTAGE = ~DIVEND;
1545
                                                ALUSTAGE = ~DIVEND;
1546
                                                DIVOP = 1'b1;
1547 20 ndumitrach
                                                IRQ = AAMIRQ;//~|STAGE[6:2] & DIVC;
1548
                                                IFETCH = AAMIRQ;
1549 2 ndumitrach
                                        end
1550
                                        3'b110: begin   // stage 3, AH <- AL, TMP16 <- AH
1551
                                                RASEL = 3'b100; // AH
1552
                                                BASEL = 1'b1;
1553
                                                RBSEL = 3'b000; // AL
1554
                                                WE[1] = 1'b1;   // RASEL_HI
1555
                                                ALUOP = 31;                     // PASS B
1556
                                                IFETCH = 1'b0;
1557
                                        end
1558
                                        3'b111: begin // stage4, AL <- TMP16 | TMP16, set flags
1559
                                                RASEL = 3'b000; // dest = AL
1560
                                                BASEL = 1'b0;    // TMP16
1561
                                                BBSEL = 2'b00;   // TMP16
1562
                                                WE = 5'b10001;   // FLAGS, RASEL_LO
1563
                                                ALUOP = 5'b00001;               // OR
1564
                                        end
1565
                                endcase
1566
                        end
1567
// --------------------------------  reset, irq, nmi, intr --------------------------------
1568
                        54:
1569
                                if(STAGE[3]) begin
1570
                                        if(FETCH[5][0]) begin    // reset
1571
                                                RASEL = {1'b0, STAGE[1:0]};      // ES, CS, SS, DS
1572
                                                WE = 5'b11100;          // FLAGS, TMP16, RSSEL
1573
                                                BASEL = 1'b0;           // TMP16
1574
                                                BBSEL = 2'b00;          // TMP16
1575
                                                ALUOP = STAGE[0] ? STAGE[1] ? 31 : 5'b01001 : 5'b00101;  // pass, dec, sub
1576
                                                MREQ = 1'b0;
1577
                                                IPWSEL = 1'b0;          // ALU16
1578
                                                IFETCH = &STAGE[1:0];
1579
                                        end else case({FETCH[5][1], STAGE[2:0]})
1580
                                                4'b1000: begin          // stage1 intr
1581
                                                        DOSEL = 2'b11;  // read FETCH[2]         
1582
                                                        MREQ = 1'b0;
1583
                                                        IFETCH = 1'b0;
1584
                                                        INTA = 1'b1;
1585
                                                end
1586
                                                4'b1001, 4'b0000: begin // stage1 irq, nmi, tf, stage2 intr - push flags, clear TF, IF
1587
                                                        RASEL = 3'b100;         // write SP
1588
                                                        RSSEL = 2'b10;                  // SS
1589
                                                        WE = 5'b10011;                  // flags, SP    
1590
                                                        ALUOP = 30;                             // pass flags
1591
                                                        EAC = 4'b1000;                  // SP - 2
1592
                                                        DISEL = 2'b10;                  // ADDR
1593
                                                        WR = 1'b1;
1594
                                                        IFETCH = 1'b0;
1595
                                                end
1596
                                                4'b1010, 4'b0001: begin // stage2 irq, nmi, tf, stage3 intr - push CS
1597
                                                        RASEL = 3'b100;         // write SP
1598
                                                        BBSEL = 2'b11;
1599
                                                        RBSEL = 3'b001;                 // CS
1600
                                                        RSSEL = 2'b10;                  // SS
1601
                                                        ALUOP = 31;                             // PASS B
1602
                                                        EAC = 4'b1000;                  // SP - 2
1603
                                                        DISEL = 2'b10;                  // ADDR
1604
                                                        WR = 1'b1;
1605
                                                        IFETCH = 1'b0;
1606
                                                        WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1607
                                                end
1608
                                                4'b1011, 4'b0010: begin // stage3 irq, nmi, tf, stage4 intr - read offset in FETCH, ADDR16 in TMP16
1609
                                                        RASEL = 3'b100;                 // SP   - write SP to SP for getting ADDR16 to TMP16
1610
                                                        BBSEL = 2'b01;
1611
                                                        RBSEL = 3'b100;                 // SP
1612
                                                        ALUOP = 31;                             // PASS B
1613
                                                        EAC = 4'b1110;                  // int vector
1614
                                                        WE[3:0] = 4'b1011;       // TMP16, RASEL_HI, RASEL_LO
1615
                                                        ASEL = 1'b1;
1616
                                                        DISP16 = 1'b1;
1617
                                                        DOSEL = 2'b11;                  // load FETCH with DIN
1618
                                                        IFETCH = 1'b0;
1619
                                                        NULLSEG = 1'b1;
1620
                                                end
1621
                                                4'b1100, 4'b0011: begin // stage4 irq, nmi, tf, stage5 intr - read CS
1622
                                                        RASEL = 3'b001;                 // CS
1623
                                                        WE[2] = 1'b1;                   // RSSEL
1624
                                                        EAC = 4'b1011;                  // TMP16 + 2
1625
                                                        DISEL = 2'b00;                  // DIN
1626
                                                        IFETCH = 1'b0;
1627
                                                        NULLSEG = 1'b1;
1628
                                                end
1629
                                                4'b1101, 4'b0100: begin // stage5 irq, nmi, tf, stage6 intr - push IP, jump
1630
                                                        RASEL = 3'b100;         // write SP
1631
                                                        BBSEL = 2'b10;          // imm
1632
                                                        RSSEL = 2'b10;          // SS
1633
                                                        ALUOP = 31;                     // PASS B
1634
                                                        EAC = 4'b1000;          // SP - 2
1635
                                                        DISEL = 2'b10;          // ADDR
1636
                                                        DOSEL = 2'b01;          // IP    
1637
                                                        ISEL = 2'b01;
1638
                                                        WR = 1'b1;
1639
                                                        WE[1:0] = 2'b11;
1640
                                                        ISIZE = FETCH[5][2] ? 1 : 0;
1641
                                                        IPWSEL = 1'b0;          // ALU
1642
                                                end
1643
                                        endcase
1644
                                end else begin
1645
                                        MREQ = 1'b0;
1646
                                        ISIZE = 0;
1647
                                        IRQ = 1'b1;
1648 20 ndumitrach
                                end
1649
// --------------------------------  SALC --------------------------------
1650
                        55: begin
1651
                                RASEL = 3'b000; // dest AL (WORD is default 0)
1652
                                BASEL = 1'b0;
1653
                                BBSEL = 2'b00;
1654
                                ALUOP = 3;      // sbb
1655
                                MREQ = 1'b0;
1656
                                WE[0] = 1'b1;    // RASEL_LO
1657
                                ISIZE = 1;
1658
                        end
1659 2 ndumitrach
// --------------------------------  bad opcode/esc --------------------------------
1660
                        default: begin
1661
                                MREQ = 1'b0;
1662
                                ISIZE = 0;
1663
                                IRQ = 1'b1;
1664
                                if(FETCH[0][7:3] == 5'b11011) IRQL = 3'b111; // esc
1665
                        end
1666
                endcase
1667
         end
1668
 
1669
 
1670
 
1671
// instruction pre-decoder
1672
function [5:0]ICODE;
1673
        input [7:0]INSTR;
1674
        begin
1675
                case(INSTR[7:0])
1676
// --------------------------------  mov R/M to/from R/SR  --------------------------------
1677
                        8'b10001000, 8'b10001001, 8'b10001010, 8'b10001011,
1678
                        8'b10001110, 8'b10001100: ICODE = 0;
1679
// --------------------------------  mov IMM to R/M  --------------------------------
1680
                        8'b11000110, 8'b11000111: ICODE = 1;
1681
// --------------------------------  mov IMM to R --------------------------------
1682
                        8'b10110_000, 8'b10110_001, 8'b10110_010, 8'b10110_011, 8'b10110_100, 8'b10110_101, 8'b10110_110, 8'b10110_111,
1683
                        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;
1684
// --------------------------------  mov mem to/from ACC --------------------------------
1685
                        8'b10100000, 8'b10100001,
1686
                        8'b10100010, 8'b10100011: ICODE = 3;
1687
// --------------------------------  segment override prefix --------------------------------
1688
                        8'b001_00_110, 8'b001_01_110, 8'b001_10_110, 8'b001_11_110: ICODE = 4;
1689
// --------------------------------  rep prefix --------------------------------
1690
                        8'b11110010, 8'b11110011: ICODE = 5;
1691
// --------------------------------  lock prefix --------------------------------
1692
                        8'b11110000: ICODE = 6;
1693
// --------------------------------  FF block --------------------------------
1694
                        8'b11111111, 8'b11111110:       ICODE = 7;
1695
// --------------------------------  push R/SR --------------------------------
1696
                        8'b01010_000, 8'b01010_001, 8'b01010_010, 8'b01010_011, 8'b01010_100, 8'b01010_101, 8'b01010_110, 8'b01010_111,
1697
                        8'b000_00_110, 8'b000_01_110, 8'b000_10_110, 8'b000_11_110: ICODE = 8;
1698
// --------------------------------  push Imm --------------------------------
1699
                        8'b01101000, 8'b01101010: ICODE = 9;
1700
// --------------------------------  pusha --------------------------------
1701
                        8'b01100000: ICODE = 10;
1702
// --------------------------------  pop R/M --------------------------------
1703
                        8'b10001111: ICODE = 11;
1704
// --------------------------------  pop R / SR --------------------------------
1705
                        8'b01011_000, 8'b01011_001, 8'b01011_010, 8'b01011_011, 8'b01011_100, 8'b01011_101, 8'b01011_110, 8'b01011_111,
1706
                        8'b000_00_111, 8'b000_10_111, 8'b000_11_111: ICODE = 12;
1707
// --------------------------------  popa --------------------------------
1708
                        8'b01100001: ICODE = 13;
1709
// --------------------------------  xchg R with R/M/Acc --------------------------------
1710
                        8'b10000110, 8'b10000111,
1711
                        8'b10010000, 8'b10010001, 8'b10010010, 8'b10010011, 8'b10010100, 8'b10010101, 8'b10010110, 8'b10010111: ICODE = 14;
1712
// --------------------------------  in --------------------------------
1713
                        8'b11100100, 8'b11100101,
1714
                        8'b11101100, 8'b11101101:       ICODE = 15;
1715
// --------------------------------  out --------------------------------
1716
                        8'b11100110, 8'b11100111,
1717
                        8'b11101110, 8'b11101111:       ICODE = 16;
1718
// --------------------------------  xlat --------------------------------
1719
                        8'b11010111: ICODE = 17;
1720
// --------------------------------  lea --------------------------------
1721
                        8'b10001101: ICODE = 18;
1722
// --------------------------------  lds, les --------------------------------
1723
                        8'b11000101, 8'b11000100: ICODE = 19;
1724
// --------------------------------  lahf, sahf --------------------------------
1725
                        8'b10011111, 8'b10011110: ICODE = 20;
1726
// --------------------------------  pushf --------------------------------
1727
                        8'b10011100: ICODE = 21;
1728
// --------------------------------  popf --------------------------------
1729
                        8'b10011101: ICODE = 22;
1730
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
1731
                        8'b00000000, 8'b00000001, 8'b00000010, 8'b00000011,             // add
1732
                        8'b00001000, 8'b00001001, 8'b00001010, 8'b00001011,             // or
1733
                        8'b00010000, 8'b00010001, 8'b00010010, 8'b00010011,             // adc
1734
                        8'b00011000, 8'b00011001, 8'b00011010, 8'b00011011,             // sbb
1735
                        8'b00100000, 8'b00100001, 8'b00100010, 8'b00100011,             // and
1736
                        8'b00101000, 8'b00101001, 8'b00101010, 8'b00101011,             // sub
1737
                        8'b00110000, 8'b00110001, 8'b00110010, 8'b00110011,             // xor
1738
                        8'b00111000, 8'b00111001, 8'b00111010, 8'b00111011,             // cmp
1739
                        8'b10000100, 8'b10000101: ICODE = 23;                                                                   // test 
1740
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
1741
                        8'b10000000, 8'b10000001, 8'b10000010, 8'b10000011: ICODE = 24;
1742
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
1743
                        8'b00000100, 8'b00000101,               // add
1744
                        8'b00001100, 8'b00001101,               // or
1745
                        8'b00010100, 8'b00010101,               // adc
1746
                        8'b00011100, 8'b00011101,               // sbb
1747
                        8'b00100100, 8'b00100101,               // and
1748
                        8'b00101100, 8'b00101101,               // sub
1749
                        8'b00110100, 8'b00110101,               // xor
1750
                        8'b00111100, 8'b00111101,       // cmp
1751
                        8'b10101000, 8'b10101001: ICODE = 25; // test
1752
// --------------------------------  inc/dec R16 --------------------------------
1753
                        8'b01000000, 8'b01000001, 8'b01000010, 8'b01000011, 8'b01000100, 8'b01000101, 8'b01000110, 8'b01000111,
1754
                        8'b01001000, 8'b01001001, 8'b01001010, 8'b01001011, 8'b01001100, 8'b01001101, 8'b01001110, 8'b01001111: ICODE = 26;
1755
// --------------------------------  test/???/not/neg/mul/imul/div/idiv --------------------------------
1756
                        8'b11110110, 8'b11110111: ICODE = 27;
1757
// --------------------------------  imul imm --------------------------------
1758
                        8'b01101001, 8'b01101011: ICODE = 28;
1759
// --------------------------------  aad --------------------------------
1760
                        8'b11010101: ICODE = 29;
1761
// --------------------------------  daa, das, aaa, aas --------------------------------
1762
                        8'b00_100_111, 8'b00_101_111, 8'b00_110_111, 8'b00_111_111: ICODE = 30;
1763
// --------------------------------  shift/rot --------------------------------
1764
                        8'b11010000, 8'b11010001,                       // 1
1765
                        8'b11010010, 8'b11010011,                       // CL
1766
                        8'b11000000, 8'b11000001: ICODE = 31;   // imm
1767
// --------------------------------  (rep)movs --------------------------------
1768
                        8'b10100100, 8'b10100101: ICODE = 32;
1769
// --------------------------------  (rep)cmps --------------------------------
1770
                        8'b10100110, 8'b10100111: ICODE = 33;
1771
// --------------------------------  (rep)scas --------------------------------
1772
                        8'b10101110, 8'b10101111: ICODE = 34;
1773
// --------------------------------  (rep)lods --------------------------------
1774
                        8'b10101100, 8'b10101101: ICODE = 35;
1775
// --------------------------------  (rep)stos --------------------------------
1776
                        8'b10101010, 8'b10101011: ICODE = 36;  // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
1777
// --------------------------------  (rep)ins --------------------------------
1778
                        8'b01101100, 8'b01101101: ICODE = 37;
1779
// --------------------------------  (rep)outs --------------------------------
1780
                        8'b01101110, 8'b01101111: ICODE = 38;
1781
// --------------------------------  call/jmp direct near --------------------------------
1782
                        8'b11101000,                    // call long
1783
                        8'b11101011,                    // jump short
1784
                        8'b11101001: ICODE = 39;        // jump long
1785
// --------------------------------  call/jmp far imm --------------------------------
1786
                        8'b10011010, 8'b11101010: ICODE = 40;
1787
// --------------------------------  ret near --------------------------------
1788
                        8'b11000011, 8'b11000010: ICODE = 41;
1789
// --------------------------------  ret far --------------------------------
1790
                        8'b11001011, 8'b11001010: ICODE = 42;
1791
// --------------------------------  iret --------------------------------
1792
                        8'b11001111: ICODE = 43;
1793
// --------------------------------  cbw/cwd --------------------------------
1794
                        8'b10011000, 8'b10011001: ICODE = 44;
1795
// --------------------------------  JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
1796
                        8'b01110000, 8'b01110001,       // JO/JNO
1797
                        8'b01110010, 8'b01110011,       // JB/JNB
1798
                        8'b01110100, 8'b01110101,       // JE/JNE
1799
                        8'b01110110, 8'b01110111,       // JBE/JA
1800
                        8'b01111000, 8'b01111001,       // JS/JNS
1801
                        8'b01111010, 8'b01111011,       // JP/JNP
1802
                        8'b01111100, 8'b01111101,       // JL/JNL
1803
                        8'b01111110, 8'b01111111,       // JLE/JG
1804
                        8'b11100010, 8'b11100001, 8'b11100000, 8'b11100011: ICODE = 45;  // loop/loopz/loopnz/jcxz
1805
// --------------------------------  CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
1806
                        8'b11111000, 8'b11110101, 8'b11111001, 8'b11111100, 8'b11111101, 8'b11111010, 8'b11111011: ICODE = 46;
1807
// --------------------------------  enter --------------------------------
1808
                        8'b11001000: ICODE = 47;
1809
// --------------------------------  leave --------------------------------
1810
                        8'b11001001: ICODE = 48;
1811
// --------------------------------  int, int 3, into --------------------------------
1812
                        8'b11001101, 8'b11001100, 8'b11001110: ICODE = 49;
1813
// --------------------------------  bound --------------------------------
1814
                        8'b01100010: ICODE = 50;
1815
// --------------------------------  hlt --------------------------------
1816
                        8'b11110100: ICODE = 51;
1817
// --------------------------------  wait --------------------------------
1818
                        8'b10011011: ICODE = 52;        // do nothing
1819
// --------------------------------  aam --------------------------------
1820
                        8'b11010100: ICODE = 53;
1821
// --------------------------------  reset, irq, nmi, intr --------------------------------
1822
                        8'b00001111: ICODE = 54;
1823 20 ndumitrach
// --------------------------------  SALC --------------------------------
1824
                        8'b11010110: ICODE = 55;
1825
// --------------------------------  bad opcode/esc --------------------------------
1826
                        default: ICODE = 56;
1827 2 ndumitrach
                endcase
1828
        end
1829
endfunction
1830
 
1831
endmodule
1832
 

powered by: WebSVN 2.1.0

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