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

Subversion Repositories next186

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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