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

Subversion Repositories next186

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

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

powered by: WebSVN 2.1.0

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