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

Subversion Repositories next186

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

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

powered by: WebSVN 2.1.0

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