§ Исходный код ядра
1
4
5module c8086
6(
7
8 input clock,
9 input ce,
10 input reset_n,
11 output [19:0] address,
12 input [ 7:0] in,
13 output reg [ 7:0] out,
14 output reg we,
15 output m0,
16
17
18 output reg [15:0] port_a,
19 output reg port_w,
20 output reg port_r,
21 input [ 7:0] port_i,
22 output reg [ 7:0] port_o,
23
24
25 input irq,
26 input [ 7:0] irq_in
27);
28
29
30assign address = cp ? {segment, 4'h0} + ea : {cs, 4'h0} + ip;
31assign m0 = (fn == START);
32
33localparam
34
35 ALU_ROL = 0, ALU_ROR = 1,
36 ALU_RCL = 2, ALU_RCR = 3,
37 ALU_SHL = 4, ALU_SHR = 5,
38 ALU_SAL = 6, ALU_SAR = 7;
39
40localparam
41 ALU_ADD = 0, ALU_OR = 1, ALU_ADC = 2, ALU_SBB = 3,
42 ALU_AND = 4, ALU_SUB = 5, ALU_XOR = 6, ALU_CMP = 7;
43
44localparam
45 CF = 0, PF = 2, AF = 4, ZF = 6, SF = 7, TF = 8, IF = 9, DF = 10, OF = 11;
46
47localparam
48 REG_AX = 0, REG_CX = 1, REG_DX = 2, REG_BX = 3,
49 REG_SP = 4, REG_BP = 5, REG_SI = 6, REG_DI = 7;
50
51localparam
52 START = 0, LOAD = 1, MODRM = 2, INSTR = 3, INTR = 4,
53 WBACK = 5, PUSH = 6, POP = 7, REPF = 8, UNDEF = 9;
54
55
56wire [15:0] signex = {{8{in[7]}}, in};
57wire [15:0] rin =
58 in[2:0] == REG_AX ? ax : in[2:0] == REG_CX ? cx :
59 in[2:0] == REG_DX ? dx : in[2:0] == REG_BX ? bx :
60 in[2:0] == REG_SP ? sp : in[2:0] == REG_BP ? bp :
61 in[2:0] == REG_SI ? si : di;
62
63
64wire [7:0] branches =
65{
66 (flags[SF] ^ flags[OF]) | flags[ZF],
67 (flags[SF] ^ flags[OF]),
68 flags[PF],
69 flags[SF],
70 flags[CF] | flags[OF],
71 flags[ZF],
72 flags[CF],
73 flags[OF]
74};
75
76
77
78reg cp, size, dir, cpen, over, rep_ft, iack, trace_ff;
79reg [15:0] ax, bx, cx, dx, sp, bp, si, di;
80reg [15:0] es, cs, ss, ds;
81reg [ 1:0] rep;
82reg [ 3:0] fn, fnext, s1, s2;
83reg [ 7:0] opcode, modrm;
84reg [15:0] segment, ea, wb, ip, ip_start;
85reg [ 7:0] intr;
86reg [ 2:0] alu;
87reg [15:0] op1, op2;
88reg [11:0] flags;
89
90
91
92always @(posedge clock)
93if (reset_n == 1'b0) begin
94
95 fn <= START;
96 cs <= 16'hF000;
97 es <= 16'h0000;
98 ds <= 16'h0000;
99 ss <= 16'h0000;
100 sp <= 16'h0000;
101 ip <= 16'hFFF0;
102 iack <= 1'b0;
103
104 flags <= 12'b0010_0000_0010;
105
106end
107else if (ce) begin
108
109 port_r <= 0;
110 port_w <= 0;
111
112 case (fn)
113
114
115
116 START: begin
117
118 fn <= LOAD;
119 fnext <= START;
120 s1 <= 0;
121 s2 <= 0;
122 cp <= 0;
123 cpen <= 1;
124 modrm <= 0;
125 segment <= ds;
126 over <= 1'b0;
127 rep <= 2'b0;
128 ea <= 0;
129 we <= 0;
130 rep_ft <= 0;
131 wb <= 0;
132 ip_start <= ip;
133
134
135 if ((iack ^ irq) && flags[IF]) begin
136
137 fn <= irq ? INTR : LOAD;
138 intr <= irq_in;
139 iack <= irq;
140
141 end
142
143 else if (flags[IF] && flags[TF] && trace_ff) begin
144
145 fn <= INTR;
146 intr <= 1;
147
148 end
149
150
151 if (flags[IF] && flags[TF]) trace_ff <= ~trace_ff;
152
153 end
154
155
156
157 LOAD: begin
158
159
160 fn <= LOAD;
161 ip <= ip + 1;
162 size <= in[0];
163 dir <= in[1];
164 alu <= in[5:3];
165 opcode <= in;
166
167
168 casex (in)
169
170
171 8'b00100110: begin segment <= es; over <= 1; end
172 8'b00101110: begin segment <= cs; over <= 1; end
173 8'b00110110: begin segment <= ss; over <= 1; end
174 8'b00111110: begin segment <= ds; over <= 1; end
175
176 8'b1111001x: begin rep <= in[1:0]; end
177
178 8'b00001111,
179 8'b0110010x,
180 8'b0110011x,
181
182 8'b10010000,
183 8'b10011011,
184 8'b11110000: begin end
185
186 8'b00xxx0xx: begin fn <= MODRM; end
187 8'b00xxx10x: begin fn <= INSTR; end
188
189 8'b1100011x,
190 8'b10001101: begin fn <= MODRM; cpen <= 0; end
191
192 8'b0100xxxx: begin
193
194 fn <= INSTR;
195 alu <= in[3] ? ALU_SUB : ALU_ADD;
196 op1 <= rin;
197 op2 <= 1;
198 size <= 1;
199
200 end
201
202 8'b10010xxx: begin
203
204 fn <= WBACK;
205 ax <= rin;
206 wb <= ax;
207 dir <= 1;
208 size <= 1;
209 modrm[5:3] <= in[2:0];
210
211 end
212
213 8'b01010xxx: begin fn <= PUSH; wb <= rin; end
214
215 8'b01011xxx,
216 8'b000xx111,
217 8'b10011101,
218 8'b1100101x,
219 8'b1x001111,
220 8'b1100001x: begin fn <= POP; fnext <= INSTR; end
221
222 8'b00000110: begin fn <= PUSH; wb <= es; end
223 8'b00001110: begin fn <= PUSH; wb <= cs; end
224 8'b00010110: begin fn <= PUSH; wb <= ss; end
225 8'b00011110: begin fn <= PUSH; wb <= ds; end
226
227 8'b10011100: begin fn <= PUSH; wb <= flags; end
228
229 8'b1111100x: begin fn <= START; flags[CF] <= in[0]; end
230 8'b1111101x: begin fn <= START; flags[IF] <= in[0]; end
231 8'b1111110x: begin fn <= START; flags[DF] <= in[0]; end
232 8'b11110101: begin fn <= START; flags[CF] <= ~flags[CF]; end
233
234 8'b10011110: begin fn <= START; flags <= ax[15:8]; end
235 8'b10011111: begin fn <= START; ax[15:8] <= flags[7:0] | 2; end
236
237 8'b11010110: begin fn <= START; ax[ 7:0] <= {8{flags[CF]}}; end
238
239 8'b11110100: begin fn <= START; ip <= ip; end
240
241 8'b100000xx,
242 8'b1000011x: begin fn <= MODRM; dir <= 0; end
243
244 8'b1000010x: begin fn <= MODRM; alu <= ALU_AND; end
245
246 8'b10011000: begin fn <= START; ax[15:8] <= {8{ax[7]}}; end
247 8'b10011001: begin fn <= START; dx <= {16{ax[15]}}; end
248
249 8'b10001110: begin fn <= MODRM; size <= 1; end
250
251 8'b11010111: begin fn <= INSTR; ea <= bx + ax[7:0]; cp <= 1; end
252
253 8'b1100010x: begin fn <= MODRM; size <= 1; dir <= 1; end
254
255 8'b11110001: begin intr <= 1; fn <= INTR; end
256 8'b11001100: begin intr <= 3; fn <= INTR; end
257 8'b11001110: begin intr <= 4; fn <= flags[OF] ? INTR : START; end
258
259 8'b1111x11x,
260 8'b1100000x,
261 8'b110100xx: begin fn <= MODRM; dir <= 0; end
262
263 8'b0111xxxx,
264 8'b11100011: begin
265
266 if ((branches[ in[3:1] ] == in[0] && !in[7]) || (in[7] && cx))
267 begin fn <= START; ip <= ip + 2; end
268 else begin fn <= INSTR; end
269
270 end
271
272 8'b111000xx: begin
273
274
275 if ((cx != 1) && (in[1] || flags[ZF] == in[0]))
276 begin fn <= INSTR; end
277 else begin fn <= START; ip <= ip + 2; end
278
279 cx <= cx - 1;
280
281 end
282
283 default: casex (in)
284
285 8'b1000xxxx, 8'b1100000x, 8'b110001xx, 8'b011010x1,
286 8'b110100xx, 8'b11011xxx, 8'b1111x11x, 8'b0110001x:
287 fn <= MODRM;
288 default: fn <= INSTR;
289
290 endcase
291
292 endcase
293
294 end
295
296
297
298 MODRM: case (s1)
299
300
301 0: begin
302
303 modrm <= in;
304 ip <= ip + 1;
305
306
307 case (dir ? in[5:3] : in[2:0])
308 REG_AX: op1 <= size ? ax : ax[ 7:0];
309 REG_CX: op1 <= size ? cx : cx[ 7:0];
310 REG_DX: op1 <= size ? dx : dx[ 7:0];
311 REG_BX: op1 <= size ? bx : bx[ 7:0];
312 REG_SP: op1 <= size ? sp : ax[15:8];
313 REG_BP: op1 <= size ? bp : cx[15:8];
314 REG_SI: op1 <= size ? si : dx[15:8];
315 REG_DI: op1 <= size ? di : bx[15:8];
316 endcase
317
318
319 case (dir ? in[2:0] : in[5:3])
320 REG_AX: op2 <= size ? ax : ax[ 7:0];
321 REG_CX: op2 <= size ? cx : cx[ 7:0];
322 REG_DX: op2 <= size ? dx : dx[ 7:0];
323 REG_BX: op2 <= size ? bx : bx[ 7:0];
324 REG_SP: op2 <= size ? sp : ax[15:8];
325 REG_BP: op2 <= size ? bp : cx[15:8];
326 REG_SI: op2 <= size ? si : dx[15:8];
327 REG_DI: op2 <= size ? di : bx[15:8];
328 endcase
329
330
331 case (in[2:0])
332 3'b000: ea <= bx + si;
333 3'b001: ea <= bx + di;
334 3'b010: ea <= bp + si;
335 3'b011: ea <= bp + di;
336 3'b100: ea <= si;
337 3'b101: ea <= di;
338 3'b110: ea <= in[7:6] == 2'b00 ? 0 : bp;
339 3'b111: ea <= bx;
340 endcase
341
342
343 if (!over)
344 casex (in)
345 8'bxx_xxx_01x,
346 8'b01_xxx_110,
347 8'b10_xxx_110: segment <= ss;
348 endcase
349
350
351 casex (in)
352 8'b00_xxx_110: begin s1 <= 2; end
353
354 8'b00_xxx_xxx: begin s1 <= cpen ? 4 : 0; cp <= cpen; if (!cpen) fn <= INSTR; end
355 8'b01_xxx_xxx: begin s1 <= 1; end
356 8'b10_xxx_xxx: begin s1 <= 2; end
357 8'b11_xxx_xxx: begin s1 <= 0; fn <= INSTR; end
358 default: begin s1 <= 1; end
359 endcase
360
361 end
362
363
364 1: begin
365
366 s1 <= 4;
367 ip <= ip + 1;
368 ea <= ea + signex;
369 cp <= cpen;
370
371 if (!cpen) begin s1 <= 0; fn <= INSTR; end
372
373 end
374
375
376 2: begin s1 <= 3; ip <= ip + 1; ea <= ea + in; end
377 3: begin
378
379 s1 <= 4;
380 ip <= ip + 1;
381 cp <= cpen;
382 ea <= ea + {in, 8'h00};
383
384 if (!cpen) begin s1 <= 0; fn <= INSTR; end
385
386 end
387
388
389 4: begin
390
391 if (dir) op2 <= in; else op1 <= in;
392 if (size)
393 begin s1 <= 5; ea <= ea + 1; end
394 else begin s1 <= 0; fn <= INSTR; end
395
396 end
397
398
399 5: begin
400
401 if (dir) op2[15:8] <= in; else op1[15:8] <= in;
402
403 s1 <= 0;
404 fn <= INSTR;
405 ea <= ea - 1;
406
407 end
408
409 endcase
410
411
412
413 INSTR: casex (opcode)
414
415 8'b00xxx0xx: begin
416
417 wb <= alu_r;
418 flags <= alu_f;
419
420 fn <= (alu != ALU_CMP) ? WBACK : START;
421
422 end
423 8'b00xxx10x: case (s2)
424
425
426 0: begin
427
428 op1 <= size ? ax : ax[7:0];
429 op2 <= in;
430 s2 <= size ? 1 : 2;
431 ip <= ip + 1;
432
433 end
434
435
436 1: begin s2 <= 2; op2[15:8] <= in; ip <= ip + 1; end
437
438
439 2: begin
440
441 fn <= START;
442 flags <= alu_f;
443
444 if (alu != ALU_CMP) begin
445
446 if (size) ax <= alu_r;
447 else ax[7:0] <= alu_r[7:0];
448
449 end
450
451 end
452
453 endcase
454 8'b1011xxxx: case (s2)
455
456
457 0: begin
458
459 s2 <= 1;
460 dir <= 1;
461 size <= opcode[3];
462 modrm[5:3] <= opcode[2:0];
463 wb <= in;
464 ip <= ip + 1;
465
466 if (opcode[3] == 0) fn <= WBACK;
467
468 end
469
470
471 1: begin
472
473 wb[15:8] <= in;
474
475 fn <= WBACK;
476 ip <= ip + 1;
477
478 end
479
480 endcase
481 8'b100010xx: begin
482
483 wb <= op2;
484 fn <= WBACK;
485
486 end
487 8'b1100011x: case (s2)
488
489
490 0: begin
491
492 s2 <= 1; wb <= in; dir <= 0; ip <= ip + 1;
493 if (size == 0) begin fn <= WBACK; cp <= 1; end
494
495 end
496
497
498 1: begin fn <= WBACK; cp <= 1; ip <= ip + 1; wb[15:8] <= in; end
499
500 endcase
501 8'b10001101: begin
502
503 wb <= ea;
504 size <= 1;
505 dir <= 1;
506 fn <= WBACK;
507
508 end
509 8'b0100xxxx: begin
510
511 fn <= WBACK;
512 modrm[5:3] <= opcode[2:0];
513 dir <= 1;
514 wb <= alu_r;
515 flags <= {alu_f[11:1], flags[CF]};
516
517 end
518 8'b01011xxx: begin
519
520 fn <= WBACK;
521 size <= 1;
522 dir <= 1;
523 modrm[5:3] <= opcode[2:0];
524
525 end
526 8'b000xx111: begin
527
528 fn <= START;
529
530 case (opcode[4:3])
531 2'b00: es <= wb;
532 2'b01: cs <= wb;
533 2'b10: ss <= wb;
534 2'b11: ds <= wb;
535 endcase
536
537 end
538 8'b100000xx: case (s2)
539
540
541 0: begin s2 <= 1; alu <= modrm[5:3]; cpen <= cp; cp <= 0; end
542 1: begin s2 <= 2; op2 <= in; ip <= ip + 1; end
543 2: begin s2 <= 3;
544
545 case (opcode[1:0])
546 2'b01: begin op2[15:8] <= in; ip <= ip + 1; end
547 2'b11: begin op2[15:8] <= {8{op2[7]}}; end
548 endcase
549
550 end
551
552 3: begin
553
554 cp <= cpen;
555 wb <= alu_r;
556 flags <= alu_f;
557 fn <= (alu != ALU_CMP) ? WBACK : START;
558
559 end
560
561 endcase
562 8'b101000xx: case (s2)
563
564
565 0: begin ea[ 7:0] <= in; ip <= ip + 1; s2 <= 1; end
566 1: begin ea[15:8] <= in; ip <= ip + 1; cp <= 1; s2 <= dir ? 2 : 5; end
567
568
569 2: begin we <= 1; out <= ax[ 7:0]; s2 <= size ? 3 : 4; end
570 3: begin we <= 1; out <= ax[15:8]; s2 <= 4; ea <= ea + 1; end
571 4: begin fn <= START; we <= 0; end
572
573
574 5: begin s2 <= 6; ax[ 7:0] <= in; ea <= ea + 1; if (!size) fn <= START; end
575 6: begin fn <= START; ax[15:8] <= in; end
576
577 endcase
578 8'b1000010x: begin
579
580 flags <= alu_f;
581 fn <= START;
582
583 end
584 8'b100001xx: case (s2)
585
586 0: begin
587
588 fn <= WBACK;
589 fnext <= INSTR;
590 s2 <= 1;
591 dir <= 1;
592 wb <= op1;
593
594 end
595 1: begin
596
597 fn <= WBACK;
598 fnext <= START;
599 dir <= 0;
600 wb <= op2;
601
602 end
603
604 endcase
605 8'b10011101: begin
606
607 fn <= START;
608 flags <= wb | 2;
609
610 end
611 8'b1010100x: case (s2)
612
613
614 0: begin s2 <= size ? 1 : 2; alu <= ALU_AND; op1 <= ax; op2 <= in; ip <= ip + 1; end
615
616
617 1: begin s2 <= 2; op2[15:8] <= in; ip <= ip + 1; end
618
619
620 2: begin flags <= alu_f; fn <= START; end
621
622 endcase
623 8'b0111xxxx,
624 8'b111000xx,
625 8'b11101011: begin
626
627 fn <= START;
628 ip <= ip + 1 + signex;
629
630 end
631 8'b11101001: case (s2)
632
633 0: begin s2 <= 1; ip <= ip + 1; ea[7:0] <= in; end
634 1: begin fn <= START; ip <= ip + 1 + {in, ea[7:0]}; end
635
636 endcase
637 8'b11101010: case (s2)
638
639
640 0: begin ip <= ip + 1; s2 <= 1; ea <= in; end
641 1: begin ip <= ip + 1; s2 <= 2; ea[15:8] <= in; end
642 2: begin ip <= ip + 1; s2 <= 3; op1 <= in; end
643 3: begin ip <= ea; cs <= {in, op1[7:0]}; fn <= START; end
644
645 endcase
646 8'b11101000: case (s2)
647
648 0: begin s2 <= 1; ea <= in; ip <= ip + 1; end
649 1: begin fn <= PUSH; wb <= ip + 1; ip <= ip + 1 + {in, ea[7:0]}; end
650
651 endcase
652 8'b11000011: begin
653
654 fn <= START;
655 ip <= wb;
656
657 end
658 8'b11000010: case (s2)
659
660 0: begin s2 <= 1; ea <= in; ip <= ip + 1; end
661 1: begin fn <= START; ip <= wb; sp <= sp + {in, ea[7:0]}; end
662
663 endcase
664 8'b1100101x: case (s2)
665
666 0: begin fn <= POP; s2 <= 1; op1 <= wb; op2 <= in; ip <= ip + 1; end
667 1: begin fn <= START; cs <= wb; ip <= op1; if (!opcode[0]) sp <= sp + {in, op2[7:0]}; end
668
669 endcase
670 8'b11001111: case (s2)
671
672 0: begin s2 <= 1; fn <= POP; ip <= wb; end
673 1: begin s2 <= 2; fn <= POP; cs <= wb; end
674 2: begin fn <= START; flags <= wb[11:0] | 2; end
675
676 endcase
677 8'b10001100: begin
678
679 fn <= WBACK;
680 size <= 1;
681
682 case (modrm[4:3])
683 2'b00: wb <= es;
684 2'b01: wb <= cs;
685 2'b10: wb <= ss;
686 2'b11: wb <= ds;
687 endcase
688
689 end
690 8'b10001110: begin
691
692 fn <= START;
693 case (modrm[4:3])
694 0: es <= op2;
695 1: cs <= op2;
696 2: ss <= op2;
697 3: ds <= op2;
698 endcase
699
700 end
701 8'b10011010: case (s2)
702
703 0: begin s2 <= 1; ip <= ip + 1; op1[ 7:0] <= in; end
704 1: begin s2 <= 2; ip <= ip + 1; op1[15:8] <= in; end
705 2: begin s2 <= 3; ip <= ip + 1; op2[ 7:0] <= in; end
706 3: begin s2 <= 4; ip <= ip + 1; op2[15:8] <= in; fn <= PUSH; wb <= cs; fnext <= INSTR; end
707 4: begin s2 <= 5; fn <= PUSH; wb <= ip; fnext <= INSTR; end
708 5: begin ip <= op1; fn <= START; cs <= op2; end
709
710 endcase
711 8'b1100010x: case (s2)
712
713 0: begin
714
715 s2 <= 1;
716 ea <= ea + 2;
717
718 end
719 1: begin s2 <= 2; wb[7:0] <= in; ea <= ea + 1; end
720 2: begin
721
722 fn <= WBACK;
723 wb <= op2;
724
725 if (opcode[0])
726 ds <= {in, wb[7:0]};
727 else es <= {in, wb[7:0]};
728
729 end
730
731 endcase
732 8'b10001111: case (s2)
733
734 0: begin s2 <= 1; cpen <= 0; fn <= MODRM; dir <= 0; end
735 1: begin cp <= 1; fn <= WBACK; fnext <= START; end
736
737 endcase
738 8'b011010x0: case (s2)
739
740 0: begin s2 <= opcode[1] ? 2 : 1; wb <= signex; ip <= ip + 1; end
741 1: begin s2 <= 2; wb[15:8] <= in; ip <= ip + 1; end
742 2: begin fn <= PUSH; fnext <= START; end
743
744 endcase
745 8'b11010111: begin
746
747 fn <= START;
748 ax[7:0] <= in;
749
750 end
751 8'b11001101: begin
752
753 fn <= INTR;
754 intr <= in;
755 ip <= ip + 1;
756
757 end
758 8'b1100000x,
759 8'b110100xx: case (s2)
760
761
762
763 0: if (cp) cp <= 0; else
764 begin
765
766 s2 <= 1;
767 alu <= modrm[5:3];
768
769 if (opcode[4])
770 begin op2 <= (opcode[1] ? cx[3:0] : 1); end
771 else begin op2 <= in[3:0]; ip <= ip + 1; end
772
773 end
774
775
776 1: begin
777
778
779 if (op2) begin op1 <= rot_r; flags <= rot_f; end
780
781 else begin wb <= op1; cp <= 1; fn <= WBACK; end
782
783 op2 <= op2 - 1;
784
785 end
786
787 endcase
788 8'b1110x10x: case (s2)
789
790
791 0: begin
792
793 s2 <= 1;
794 cpen <= 0;
795 port_a <= opcode[3] ? dx : in;
796 if (!opcode[3]) ip <= ip + 1;
797
798 end
799
800
801 1: begin s2 <= 2; port_r <= 1; end
802 2: begin s2 <= 3; end
803
804
805 3: begin
806
807 if (size) begin s2 <= 1; cpen <= 1; end
808 else fn <= START;
809
810 if (cpen)
811 ax[15:8] <= port_i;
812 else ax[ 7:0] <= port_i;
813
814 port_a <= port_a + 1;
815 size <= 0;
816
817 end
818
819 endcase
820 8'b1110x11x: case (s2)
821
822 0: begin
823
824 s2 <= 1;
825
826 port_a <= opcode[3] ? dx : in;
827 port_o <= ax[7:0];
828 port_w <= 1;
829
830 if (!opcode[3]) ip <= ip + 1;
831 if (!size) fn <= START;
832
833 end
834 1: begin
835
836 port_a <= port_a + 1;
837 port_o <= ax[15:8];
838 port_w <= 1;
839 fn <= START;
840
841 end
842
843 endcase
844 8'b1111011x: case (modrm[5:3])
845
846
847 0, 1: case (s2)
848
849 0: begin s2 <= 1; cp <= 0; alu <= ALU_AND; end
850 1: begin s2 <= size ? 2 : 3; op2 <= in; ip <= ip + 1; end
851 2: begin s2 <= 3; op2[15:8] <= in; ip <= ip + 1; end
852 3: begin fn <= START; flags <= alu_f; end
853
854 endcase
855
856
857 2: begin wb <= ~op1; fn <= WBACK; end
858
859
860 3: case (s2)
861
862 0: begin s2 <= 1; alu <= ALU_SUB; op2 <= op1; op1 <= 0; end
863 1: begin fn <= WBACK; wb <= alu_r; flags <= alu_f; end
864
865 endcase
866
867 endcase
868 8'b1111111x: case (modrm[5:3])
869
870
871 0,
872 1: case (s2)
873
874 0: begin s2 <= 1; op2 <= 1; alu <= modrm[3] ? ALU_SUB : ALU_ADD; end
875 1: begin fn <= WBACK; wb <= alu_r; flags <= alu_f; end
876
877 endcase
878
879
880 2: begin
881
882 ip <= op1;
883 wb <= ip;
884 fn <= size ? PUSH : UNDEF;
885
886 end
887
888
889 3: case (s2)
890
891 0: begin s2 <= 1; ea <= ea + 2; ip <= op1; op1 <= ip; op2 <= cs; if (size == 0) fn <= UNDEF; end
892 1: begin s2 <= 2; ea <= ea + 1; wb <= in; fnext <= INSTR; end
893 2: begin s2 <= 3; fn <= PUSH; cs <= {in, wb[7:0]}; wb <= op2; end
894 3: begin s2 <= 4; fn <= PUSH; wb <= op1; end
895 4: begin fn <= START; end
896
897 endcase
898
899
900 4: begin ip <= op1; fn <= size ? START : UNDEF; end
901
902
903 5: case (s2)
904
905 0: begin s2 <= 1; ea <= ea + 2; ip <= op1; if (size == 0) fn <= UNDEF; end
906 1: begin s2 <= 2; ea <= ea + 1; wb <= in; end
907 2: begin fn <= START; cs <= {in, wb[7:0]}; end
908
909 endcase
910
911
912 6: begin wb <= op1; fn <= PUSH; end
913 7: begin fn <= UNDEF; end
914
915 endcase
916 8'b1010101x: case (s2)
917
918 0: begin
919
920 s2 <= size ? 1 : 2;
921 cp <= 1;
922 we <= 1;
923 ea <= di;
924 out <= ax[7:0];
925 segment <= es;
926
927 end
928 1: begin
929
930 s2 <= 2;
931 we <= 1;
932 ea <= ea + 1;
933 out <= ax[15:8];
934
935 end
936 2: begin
937
938 we <= 0;
939 fn <= rep[1] ? REPF : START;
940 cp <= 0;
941 di <= flags[DF] ? di - (size + 1) : di + (size + 1);
942 size <= 1;
943
944 end
945
946 endcase
947 8'b1010110x: case (s2)
948
949 0: begin s2 <= 1; cp <= 1; ea <= si; end
950 1: begin s2 <= size ? 2 : 3; ea <= ea + 1; ax[7:0] <= in; end
951 2: begin s2 <= 3; ax[15:8] <= in; end
952 3: begin
953
954 fn <= rep[1] ? REPF : START;
955 cp <= 0;
956 si <= flags[DF] ? si - (opcode[0] + 1) : si + (opcode[0] + 1);
957 size <= 1;
958
959 end
960
961 endcase
962 8'b1010010x: case (s2)
963
964
965 0: begin s2 <= 1; ea <= si; cp <= 1; end
966 1: begin s2 <= size ? 2 : 3; wb <= in; ea <= ea + 1; end
967 2: begin s2 <= 3; wb[15:8] <= in; end
968
969
970 3: begin
971
972 s2 <= size ? 4 : 5;
973 we <= 1;
974 ea <= di;
975 segment <= es;
976 out <= wb[7:0];
977
978 end
979 4: begin s2 <= 5; we <= 1; ea <= ea + 1; out <= wb[15:8]; end
980
981
982 5: begin
983
984 s2 <= 6;
985 we <= 0;
986 cp <= 0;
987 si <= flags[DF] ? si - (opcode[0] + 1) : si + (opcode[0] + 1);
988 size <= 1;
989
990 end
991
992
993 6: begin s2 <= 6;
994
995 di <= flags[DF] ? di - (opcode[0] + 1) : di + (opcode[0] + 1);
996
997
998 fn <= rep[1] ? REPF : START;
999
1000 end
1001
1002 endcase
1003 8'b1010011x: case (s2)
1004
1005 0: begin s2 <= 1; cp <= 1; ea <= si; alu <= ALU_SUB; end
1006 1: begin s2 <= size ? 2 : 3; op1 <= in; ea <= ea + 1; end
1007 2: begin s2 <= 3; op1[15:8] <= in; end
1008 3: begin s2 <= 4; segment <= es; ea <= di; end
1009 4: begin s2 <= size ? 5 : 6; op2 <= in; ea <= ea + 1; end
1010 5: begin s2 <= 6; op2[15:8] <= in; end
1011
1012
1013 6: begin
1014
1015 s2 <= 7;
1016 flags <= alu_f;
1017 cp <= 0;
1018 si <= flags[DF] ? si - (opcode[0] + 1) : si + (opcode[0] + 1);
1019 size <= 1;
1020
1021 end
1022
1023
1024 7: begin
1025
1026 rep_ft <= 1;
1027
1028
1029 di <= flags[DF] ? di - (opcode[0] + 1) : di + (opcode[0] + 1);
1030
1031
1032 fn <= rep[1] ? REPF : START;
1033
1034 end
1035
1036 endcase
1037 8'b1010111x: case (s2)
1038
1039 0: begin
1040
1041 s2 <= 1;
1042 cp <= 1;
1043 alu <= ALU_SUB;
1044 op1 <= ax;
1045 ea <= di;
1046 segment <= es;
1047
1048 end
1049 1: begin s2 <= size ? 2 : 3; op2 <= in; ea <= ea + 1; end
1050 2: begin s2 <= 3; op2[15:8] <= in; end
1051
1052
1053 3: begin
1054
1055 flags <= alu_f;
1056 cp <= 0;
1057 rep_ft <= 1;
1058 di <= flags[DF] ? di - (opcode[0] + 1) : di + (opcode[0] + 1);
1059 fn <= rep[1] ? REPF : START;
1060
1061 end
1062
1063 endcase
1064
1065 endcase
1066
1067
1068
1069 INTR: case (s2)
1070
1071 0: begin s2 <= 1; fn <= PUSH; wb <= flags; fnext <= INTR; end
1072 1: begin s2 <= 2; fn <= PUSH; wb <= cs; end
1073 2: begin s2 <= 3; fn <= PUSH; wb <= ip; end
1074 3: begin s2 <= 4; ea <= {intr, 2'b00}; segment <= 0; cp <= 1; end
1075 4: begin s2 <= 5; ea <= ea + 1; ip[ 7:0] <= in; end
1076 5: begin s2 <= 6; ea <= ea + 1; ip[15:8] <= in; end
1077 6: begin s2 <= 7; ea <= ea + 1; cs[ 7:0] <= in; end
1078 7: begin cp <= 0; ea <= ea + 1; cs[15:8] <= in; fn <= START; flags[IF] <= 1'b0; end
1079
1080 endcase
1081
1082
1083
1084 WBACK: case (s1)
1085
1086
1087 0: begin
1088
1089
1090 if (dir || modrm[7:6] == 2'b11) begin
1091
1092 cp <= 0;
1093 s1 <= 0;
1094 fn <= fnext;
1095
1096 case (dir ? modrm[5:3] : modrm[2:0])
1097 REG_AX: if (size) ax <= wb; else ax[ 7:0] <= wb[7:0];
1098 REG_CX: if (size) cx <= wb; else cx[ 7:0] <= wb[7:0];
1099 REG_DX: if (size) dx <= wb; else dx[ 7:0] <= wb[7:0];
1100 REG_BX: if (size) bx <= wb; else bx[ 7:0] <= wb[7:0];
1101 REG_SP: if (size) sp <= wb; else ax[15:8] <= wb[7:0];
1102 REG_BP: if (size) bp <= wb; else cx[15:8] <= wb[7:0];
1103 REG_SI: if (size) si <= wb; else dx[15:8] <= wb[7:0];
1104 REG_DI: if (size) di <= wb; else bx[15:8] <= wb[7:0];
1105 endcase
1106
1107 end
1108
1109 else begin out <= wb[7:0]; we <= 1; s1 <= 1; end
1110
1111 end
1112
1113
1114 1: if (size) begin size <= 0; ea <= ea + 1; out <= wb[15:8]; end
1115 else begin s1 <= 0; cp <= 0; we <= 0; fn <= fnext; end
1116
1117 endcase
1118
1119
1120
1121 PUSH: case (s1)
1122
1123 0: begin s1 <= 1; out <= wb[ 7:0]; ea <= sp - 2; we <= 1; cp <= 1; segment <= ss; end
1124 1: begin s1 <= 2; out <= wb[15:8]; ea <= ea + 1; end
1125 2: begin s1 <= 0; we <= 0; cp <= 0; sp <= sp - 2; fn <= fnext; end
1126
1127 endcase
1128
1129
1130
1131 POP: case (s1)
1132
1133 0: begin s1 <= 1; segment <= ss; ea <= sp; cp <= 1; end
1134 1: begin s1 <= 2; wb[ 7:0] <= in; ea <= ea + 1; end
1135 2: begin s1 <= 0; wb[15:8] <= in; cp <= 0; sp <= sp + 2; fn <= fnext; end
1136
1137 endcase
1138
1139
1140 REPF: case (s1)
1141
1142
1143 0: begin s1 <= 1; cx <= cx - 1; end
1144 1: begin
1145
1146 s1 <= 0;
1147 fn <= START;
1148
1149
1150 if (cx) begin
1151
1152
1153 if (rep_ft) begin if (rep[0] == flags[ZF]) ip <= ip_start; end
1154
1155 else ip <= ip_start;
1156
1157 end
1158
1159 end
1160
1161 endcase
1162
1163
1164
1165
1166
1167 endcase
1168
1169end
1170
1171
1172
1173
1174wire [16:0] alu_r =
1175
1176 alu == ALU_ADD ? op1 + op2 :
1177 alu == ALU_OR ? op1 | op2 :
1178 alu == ALU_ADC ? op1 + op2 + flags[CF] :
1179 alu == ALU_SBB ? op1 - op2 - flags[CF] :
1180 alu == ALU_AND ? op1 & op2:
1181 alu == ALU_XOR ? op1 ^ op2:
1182 op1 - op2;
1183
1184wire [ 3:0] alu_top = size ? 15 : 7;
1185wire [ 4:0] alu_up = alu_top + 1'b1;
1186
1187wire is_add = alu == ALU_ADD || alu == ALU_ADC;
1188wire is_lgc = alu == ALU_XOR || alu == ALU_AND || alu == ALU_OR;
1189wire alu_cf = alu_r[alu_up];
1190wire alu_af = op1[4] ^ op2[4] ^ alu_r[4];
1191wire alu_sf = alu_r[alu_top];
1192wire alu_zf = (size ? alu_r[15:0] : alu_r[7:0]) == 0;
1193wire alu_pf = ~^alu_r[7:0];
1194wire alu_of = (op1[alu_top] ^ op2[alu_top] ^ is_add) & (op1[alu_top] ^ alu_r[alu_top]);
1195
1196wire [11:0] alu_f = {
1197 alu_of & ~is_lgc,
1198 flags[10:8],
1199 alu_sf,
1200 alu_zf,
1201 1'b0,
1202 alu_af & ~is_lgc,
1203 1'b0,
1204 alu_pf,
1205 1'b1,
1206 alu_cf & ~is_lgc
1207};
1208
1209
1210
1211
1212reg [15:0] rot_r;
1213reg [11:0] rot_f;
1214
1215always @* begin
1216
1217 rot_f = flags;
1218
1219 case (alu)
1220 ALU_ROL: rot_r = size ? {op1[14:0], op1[15]} : {op1[6:0], op1[7]};
1221 ALU_ROR: rot_r = size ? {op1[0], op1[15:1]} : {op1[0], op1[7:1]};
1222 ALU_RCL: rot_r = size ? {op1[14:0], flags[CF]} : {op1[6:0], flags[CF]};
1223 ALU_RCR: rot_r = size ? {flags[CF], op1[15:1]} : {flags[CF], op1[7:1]};
1224 ALU_SHL,
1225 ALU_SAL: rot_r = size ? {op1[14:0], 1'b0} : {op1[6:0], 1'b0};
1226 ALU_SHR: rot_r = size ? {1'b0, op1[15:1]} : {1'b0, op1[7:1]};
1227 ALU_SHR: rot_r = size ? {op1[15], op1[15:1]} : {op1[7], op1[7:1]};
1228 endcase
1229
1230
1231 rot_f[CF] = alu[0] ? op1[0] : op1[alu_top];
1232
1233
1234 case (alu)
1235 ALU_ROL,
1236 ALU_RCL,
1237 ALU_SAL,
1238 ALU_SHL: rot_f[OF] = op1[alu_top] ^ op1[alu_top - 1];
1239 ALU_ROR,
1240 ALU_RCR: rot_f[OF] = rot_r[alu_top] ^ rot_r[alu_top - 1];
1241 ALU_SHR: rot_f[OF] = op1[alu_top];
1242 ALU_SAR: rot_f[OF] = 1'b0;
1243 endcase
1244
1245
1246 if (alu == ALU_SHL || alu == ALU_SHR || alu == ALU_SAL || alu == ALU_SHR) begin
1247
1248 rot_f[SF] = rot_r[alu_top];
1249 rot_f[ZF] = (size ? rot_r[15:0] : rot_r[7:0]) == 0;
1250 rot_f[PF] = ~^rot_r[7:0];
1251
1252 end
1253
1254end
1255
1256endmodule