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

Subversion Repositories next186

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

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

powered by: WebSVN 2.1.0

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