§ Описание портов
Пины
-
clock
— 25 мгц -
reset_n
— если 0, то процессор сбрасывается -
locked
— если 1, процессор работает -
address
— адрес -
in
— входящие данные -
out
— исходящие данные -
we
— сигнал записи
Порты
-
port_clk
— тактовый импульс для защелкивания -
port
— номер порта -
port_i
— входящие данные из порта -
port_o
— исходящие данные -
port_w
— сигнал записи в порт
Прерывания
-
irq
— Номер прерывания -
intr
— Запрос прерывания -
intl
— Защелка что прерывание обработано
§ Код ядра
1
2
3
4
5module core
6(
7
8 input clock,
9 input reset_n,
10 input locked,
11
12 output [31:0] address,
13 input [ 7:0] in,
14 output reg [ 7:0] out,
15 output reg we,
16
17 output reg [15:0] port,
18 output reg port_clk,
19 input [ 7:0] port_i,
20 output reg [ 7:0] port_o,
21 output reg port_w,
22
23 input [ 7:0] irq,
24 input intr,
25 output reg intl,
26
27 output [ 3:0] instr
28);
29
30assign instr = t; wire m0 = (t == 1'b0 && clock == 1'b0);
31always @(posedge clock)
32if (locked) begin
33if (reset_n == 1'b0) begin
34 t <= fetch;
35 cs <= 16'h000;
36 ds <= 16'h000;
37 es <= 16'h000;
38 ss <= 16'h000;
39 esp <= 20'h00800;
40 eip <= 20'hF8000;
41 eflags <= 2'h2;
42 adsize <= defsize;
43 __adsize <= defsize;
44 __opsize <= defsize;
45 __segment <= 16'h0000;
46 __override <= 1'b0;
47 __rep <= 1'b0;
48 __opext <= 1'b0;
49 src <= 1'b0;
50 prot <= 1'b0;
51 psize <= 1'b0;
52 trace_ff <= 1'b0;
53end
54else case (t)
55
56 fetch: begin
57 eip <= eip_next;
58 opcode <= in;
59 size <= in[0];
60 dir <= in[1];
61 alu <= in[5:3];
62 regn <= in[2:0];
63 fn <= 1'b0;
64 fn2 <= 1'b0;
65 ignoreo <= 1'b0;
66 t_next <= fetch;
67 src_next <= 1'b1;
68 case (in)
69
70 8'h26: begin psize <= psize + 1'b1; __segment <= es; __override <= 1'b1; end
71 8'h2E: begin psize <= psize + 1'b1; __segment <= cs; __override <= 1'b1; end
72 8'h36: begin psize <= psize + 1'b1; __segment <= ss; __override <= 1'b1; end
73 8'h3E: begin psize <= psize + 1'b1; __segment <= ds; __override <= 1'b1; end
74 8'h64: begin psize <= psize + 1'b1; __segment <= fs; __override <= 1'b1; end
75 8'h65: begin psize <= psize + 1'b1; __segment <= gs; __override <= 1'b1; end
76
77 8'h66: begin psize <= psize + 1'b1; __opsize <= ~__opsize; end
78 8'h67: begin psize <= psize + 1'b1; __adsize <= ~__adsize; end
79
80 8'h0F: begin psize <= psize + 1'b1; __opext <= 1'b1; end
81
82 8'hF0: begin psize <= psize + 1'b1; end
83 8'hF2, 8'hF3: begin psize <= psize + 1'b1; __rep <= in[1:0]; end
84
85 default: begin
86 t <= exec;
87 eip_rep <= eip-psize;
88 psize <= 0;
89
90 rep <= __rep; __rep <= 2'b00;
91 override <= __override; __override <= 1'b0;
92 opsize <= __opsize; __opsize <= defsize;
93 adsize <= __adsize; __adsize <= defsize;
94 segment <= __segment; __segment <= ds;
95 opcode[8] <= __opext; __opext <= 1'b0;
96
97 if (eflags[IF] && intr ^ intl) begin
98 t <= interrupt;
99 intl <= intr;
100 eip <= eip - psize;
101 wb <= irq;
102 end
103
104 else if (eflags[TF] && trace_ff) begin
105 t <= interrupt;
106 trace_ff <= ~trace_ff;
107 eip <= eip - psize;
108 wb <= 1;
109 end
110
111 else casex ({__opext, in})
112
113 8'h9B, 8'h90: begin t <= fetch; end
114
115 8'b00xx_x0xx,
116 8'b1000_011x,
117 8'b1101_1xxx: begin t <= fetch_modrm; end
118 8'b00xx_x101,
119 8'b1001_1010,
120 8'b1110_1010: begin t <= fetch_imm16; end
121
122 8'b1100_x010: begin t <= fetch_imm16; t_next <= exec; size <= 1'b1; end
123
124 8'b000x_x111,
125 8'b0101_1xxx,
126 8'b1000_1111,
127 8'b1001_1101,
128 8'b1100_1111,
129 8'b1100_x011: begin t <= pop; t_next <= exec; op1 <= 0; fn <= 1; end
130
131 8'b0010_x111: begin t <= fetch; eflags <= eflags_d; eax[7:0] <= daa_r[ 7:0]; end
132
133 9'b0_0111_xxxx,
134 9'b1_1000_xxxx: begin
135 size <= 1'b1;
136
137 if (branches[ in[3:1] ] == in[0]) begin
138 t <= fetch;
139 eip <= __opext ? (__opsize ? eip_next5 : eip_next3) : eip_next2;
140 end
141
142 else if (__opext) begin size <= 1'b1; t <= fetch_imm16; end
143 end
144
145 8'b0011_x111: begin t <= fetch; eflags <= eflags_d; eax[15:0] <= daa_r[15:0]; end
146
147 8'b000x_x110: begin
148 t <= push;
149 opsize <= 1'b0;
150 case (in[4:3])
151 2'b00: wb <= es[15:0];
152 2'b01: wb <= cs[15:0];
153 2'b10: wb <= ss[15:0];
154 2'b11: wb <= ds[15:0];
155 endcase
156 end
157
158 8'b0110_1000: begin t <= fetch_imm16; size <= 1'b1; t_next <= exec; end
159
160 8'b0100_xxxx,
161 8'b0101_0xxx,
162 8'b1001_0xxx: begin size <= 1'b1; end
163
164 8'b0110_0000: begin frametemp <= esp; t_next <= exec; size <= 1'b1; regn <= 0; end
165
166 8'b0110_0001: begin t_next <= exec; regn <= 7; t <= pop; end
167
168 8'b0110_10x1: begin t <= fetch_modrm; {size, dir} <= 2'b11; src_next <= 1'b0; end
169
170
171 8'b1000_00xx,
172 8'b1100_000x,
173 8'b1101_00xx: begin
174 t <= fetch_modrm;
175 dir <= 1'b0;
176 src_next <= 1'b0;
177 end
178
179 8'b1001_1100: begin
180 t <= push;
181 wb <= {eflags[17:6], 1'b0, eflags[4], 1'b0, eflags[2], 1'b1, eflags[0]};
182 end
183
184 8'b1010_00xx: begin
185 t <= fetch_imm16;
186 size <= 1'b1;
187 opsize <= __adsize;
188 adsize <= __opsize;
189 end
190
191 8'b1010_x10x: if (__rep[1] == 1'b0 || str_zcx) begin
192 t <= fetch_modrm;
193 t_next <= exec;
194 fn2 <= 4;
195 src <= 1'b1;
196 ea <= defsize ? esi : esi[15:0];
197 end else t <= fetch;
198
199 8'b1010_101x: if (__rep[1] == 1'b0 || str_zcx) begin
200 t <= modrm_wb;
201 segment <= es;
202 ea <= defsize ? edi : edi[15:0];
203 wb <= eax;
204 edi <= str_edi;
205 dir <= 1'b0;
206 src <= 1'b1;
207 modrm <= 1'b0;
208
209 if (__rep[1]) begin ecx <= str_ecx; eip <= eip-psize; end
210 end else t <= fetch;
211
212 8'b1010_011x: if (__rep[1] == 1'b0 || str_zcx) begin
213 t <= fetch_modrm;
214 t_next <= exec;
215 fn2 <= 4;
216 dir <= 1'b0;
217 src <= 1'b1;
218 ea <= defsize ? esi : esi[15:0];
219 op1 <= 0;
220 alu <= alu_cmp;
221 end else t <= fetch;
222
223 8'b1010_111x: if (__rep[1] == 1'b0 || str_zcx) begin
224 t <= fetch_modrm;
225 t_next <= exec;
226 fn2 <= 4;
227 src <= 1'b1;
228 ea <= defsize ? edi : edi[15:0];
229 segment <= es;
230 op1 <= eax;
231 alu <= alu_cmp;
232 end else t <= fetch;
233
234 8'b1000_010x: begin t <= fetch_modrm; alu <= alu_and; end
235
236 8'b1000_1100: begin t <= fetch_modrm; {size, dir, ignoreo} <= 3'b101; end
237
238 8'b1000_1101: begin t <= fetch_modrm; {size, dir, ignoreo} <= 3'b111; end
239
240
241 8'b1100_010x,
242 8'b1000_1110: begin t <= fetch_modrm; {size, dir} <= 2'b11; end
243
244 8'b1000_10xx: begin t <= fetch_modrm; ignoreo <= ~in[1]; end
245
246 8'b1011_1xxx: begin t <= fetch_imm16; end
247
248 8'b1001_1110: begin eflags[7:0] <= eax[15:8]; t <= fetch; end
249
250 8'b1001_1111: begin eax[15:8] <= eflags[7:0]; t <= fetch; end
251
252 8'b1001_1000: begin
253 t <= fetch;
254 if (__opsize)
255 eax[31:16] <= {16{eax[15]}};
256 else eax[15:8] <= { 8{eax[7]}};
257 end
258
259 8'b1001_1001: begin
260 t <= fetch;
261 if (__opsize)
262 edx[31:0] <= {32{eax[31]}};
263 else edx[15:0] <= {16{eax[15]}};
264 end
265
266 8'b1010_1001: begin t <= fetch_imm16; end
267
268 8'b1100_011x: begin t <= fetch_modrm; {dir, ignoreo} <= 2'b01; end
269
270 8'b1100_1000: begin t <= fetch_imm16; t_next <= exec; size <= 1'b1; end
271
272 8'b1100_1001: begin esp <= ebp; t <= pop; t_next <= exec; end
273
274 8'b1101_0110: begin t <= fetch; eax[7:0] <= {8{eflags[CF]}}; end
275
276 8'b1101_0111: begin t <= exec; ea <= ebx[15:0] + eax[7:0]; src <= 1'b1; end
277
278 8'b1110_0011: begin
279 t <= fetch;
280 if ((__opsize && ecx == 0) || (!__opsize && ecx[15:0] == 0))
281 t <= exec;
282 else
283 eip <= eip_next2;
284 end
285
286 8'b1110_000x,
287 8'b1110_0010: begin
288 t <= fetch;
289
290 if (__adsize) ecx <= ecx - 1'b1; else ecx[15:0] <= ecx[15:0] - 1'b1;
291
292 if (((eflags[ZF] == in[0]) || in[1]) && (__adsize ? ecx : ecx[15:0]) != 1'b1)
293 t <= exec;
294 else
295 eip <= eip_next2;
296 end
297
298 8'b1110_x1xx: begin
299 fn <= in[3] ? 1 : 0;
300 op1 <= in[0] ? (__opsize ? 3 : 1) : 0;
301 op2 <= 0;
302 port <= edx[15:0];
303 port_clk <= 1'b0;
304 end
305
306 8'b1110_100x: begin t <= fetch_imm16; size <= 1'b1; end
307
308 8'b1100_1100: begin t <= interrupt; wb <= 3; end
309 8'b1111_0001: begin t <= interrupt; wb <= 1; end
310
311 8'b1100_1110: begin if (eflags[OF]) begin t <= interrupt; wb <= 4; end else t <= fetch; end
312
313 8'b1111_0100: begin t <= fetch; eip <= eip; end
314
315 8'b1111_0101: begin t <= fetch; eflags[CF] <= ~eflags[CF]; end
316 8'b1111_100x: begin t <= fetch; eflags[CF] <= in[0]; end
317 8'b1111_101x: begin t <= fetch; eflags[IF] <= in[0]; end
318 8'b1111_110x: begin t <= fetch; eflags[DF] <= in[0]; end
319
320 8'b1111_x11x: begin t <= fetch_modrm; t_next <= exec; dir <= 1'b0; end
321
322
323 9'b1_0100_xxxx,
324 9'b1_1011_x11x: begin t <= fetch_modrm; dir <= 1'b1; size <= 1'b1; end
325
326 9'b1_1001_xxxx: begin t <= fetch_modrm; dir <= 1'b0; size <= 1'b0; ignoreo <= 1'b1; end
327
328 default: t <= exec;
329 endcase
330 end
331 endcase
332 end
333
334 fetch_modrm: case (fn2)
335
336 0: begin
337 modrm <= in;
338 eip <= eip_next;
339 ea <= 1'b0;
340
341 case (dir ? in[5:3] : in[2:0])
342 0: op1 <= size ? (opsize ? eax : eax[15:0]) : eax[ 7:0];
343 1: op1 <= size ? (opsize ? ecx : ecx[15:0]) : ecx[ 7:0];
344 2: op1 <= size ? (opsize ? edx : edx[15:0]) : edx[ 7:0];
345 3: op1 <= size ? (opsize ? ebx : ebx[15:0]) : ebx[ 7:0];
346 4: op1 <= size ? (opsize ? esp : esp[15:0]) : eax[15:8];
347 5: op1 <= size ? (opsize ? ebp : ebp[15:0]) : ecx[15:8];
348 6: op1 <= size ? (opsize ? esi : esi[15:0]) : edx[15:8];
349 7: op1 <= size ? (opsize ? edi : edi[15:0]) : ebx[15:8];
350 endcase
351
352 case (dir ? in[2:0] : in[5:3])
353 0: op2 <= size ? (opsize ? eax : eax[15:0]) : eax[ 7:0];
354 1: op2 <= size ? (opsize ? ecx : ecx[15:0]) : ecx[ 7:0];
355 2: op2 <= size ? (opsize ? edx : edx[15:0]) : edx[ 7:0];
356 3: op2 <= size ? (opsize ? ebx : ebx[15:0]) : ebx[ 7:0];
357 4: op2 <= size ? (opsize ? esp : esp[15:0]) : eax[15:8];
358 5: op2 <= size ? (opsize ? ebp : ebp[15:0]) : ecx[15:8];
359 6: op2 <= size ? (opsize ? esi : esi[15:0]) : edx[15:8];
360 7: op2 <= size ? (opsize ? edi : edi[15:0]) : ebx[15:8];
361 endcase
362
363 if (adsize) begin
364 case (in[2:0])
365 3'b000: ea <= eax;
366 3'b001: ea <= ecx;
367 3'b010: ea <= edx;
368 3'b011: ea <= ebx;
369 3'b100: ea <= 0;
370 3'b101: ea <= ^in[7:6] ? ebp : 0;
371 3'b110: ea <= esi;
372 3'b111: ea <= edi;
373 endcase
374
375 case (in[7:6])
376 2'b00: begin
377 if (in[2:0] == 3'b101) fn2 <= 1;
378 else if (in[2:0] == 3'b100) fn2 <= 10;
379 else begin
380 fn2 <= 4;
381 src <= 1'b1;
382 if (ignoreo) begin t <= exec; fn2 <= 0; end
383 end
384 end
385 2'b01: fn2 <= in[2:0] == 3'b100 ? 10 : 3;
386 2'b10: fn2 <= in[2:0] == 3'b100 ? 10 : 1;
387 2'b11: begin fn2 <= 0; t <= exec; end
388 endcase
389
390 if (!override && (^in[7:6] && in[2:0] == 3'b101))
391 segment <= ss;
392 end
393
394 else begin
395 case (in[2:0])
396 3'b000: ea[15:0] <= ebx + esi;
397 3'b001: ea[15:0] <= ebx + edi;
398 3'b010: ea[15:0] <= ebp + esi;
399 3'b011: ea[15:0] <= ebp + edi;
400 3'b100: ea[15:0] <= esi;
401 3'b101: ea[15:0] <= edi;
402 3'b110: ea[15:0] <= ^in[7:6] ? ebp : 1'b0;
403 3'b111: ea[15:0] <= ebx;
404 endcase
405
406 if (!override && (in[2:1] == 2'b01 || (^in[7:6] && in[2:0] == 3'b110)))
407 segment <= ss;
408
409 case (in[7:6])
410 2'b00: begin
411
412 if (in[2:0] == 3'b110) fn2 <= 1;
413
414 else begin
415 fn2 <= 4;
416 src <= 1'b1;
417 if (ignoreo) begin t <= exec; fn2 <= 0; end
418 end
419 end
420 2'b01: fn2 <= 3;
421 2'b10: fn2 <= 1;
422 2'b11: begin fn2 <= 0; t <= exec; end
423 endcase
424 end
425 end
426
427 1: begin fn2 <= 2; ea <= ea + in; eip <= eip_next; end
428 2: begin
429 fn2 <= adsize ? 8 : 4;
430 src <= !adsize;
431 ea[31:8] <= ea[31:8] + in;
432 eip <= eip_next;
433 if (ignoreo && !adsize) begin t <= exec; fn2 <= 0; end
434 end
435
436 3: begin
437 fn2 <= 4;
438 ea <= ea + {{24{in[7]}}, in};
439 src <= 1'b1;
440 eip <= eip_next;
441 if (ignoreo) begin t <= exec; fn2 <= 0; end
442 end
443
444 4: begin
445 if (dir) op2 <= in; else op1 <= in;
446 if (size) begin fn2 <= 5; ea <= ea + 1; end
447 else begin fn2 <= 0; t <= exec; src <= src_next; end
448 end
449
450 5: begin
451 if (dir) op2[15:8] <= in; else op1[15:8] <= in;
452 if (opsize) begin fn2 <= 6; ea <= ea + 1; end
453 else begin fn2 <= 0; ea <= ea - 1; t <= exec; src <= src_next; end
454 end
455
456 6: begin
457 fn2 <= 7; ea <= ea + 1;
458 if (dir) op2[23:16] <= in; else op1[23:16] <= in;
459 end
460
461 7: begin
462 t <= exec;
463 fn2 <= 0;
464 ea <= ea - 3;
465 src <= src_next;
466 if (dir) op2[31:24] <= in; else op1[31:24] <= in;
467 end
468
469 8: begin fn2 <= 9; ea[31:16] <= ea[31:16] + in; eip <= eip_next; end
470 9: begin
471 fn2 <= 4;
472 ea[31:24] <= ea[31:24] + in;
473 src <= 1'b1;
474 eip <= eip_next;
475 if (ignoreo) begin t <= exec; fn2 <= 0; end
476 end
477
478 10: begin
479 eip <= eip_next;
480
481 case (in[5:3])
482 3'b000: ea <= sib_base + (eax << in[7:6]);
483 3'b001: ea <= sib_base + (ecx << in[7:6]);
484 3'b010: ea <= sib_base + (edx << in[7:6]);
485 3'b011: ea <= sib_base + (ebx << in[7:6]);
486 3'b100: ea <= sib_base;
487 3'b101: ea <= sib_base + (ebp << in[7:6]);
488 3'b110: ea <= sib_base + (esi << in[7:6]);
489 3'b111: ea <= sib_base + (edi << in[7:6]);
490 endcase
491
492 case (modrm[7:6])
493 2'b00: if (in[2:0] == 3'b101)
494 begin fn2 <= 1; end
495 else begin fn2 <= 4; src <= 1'b1; end
496 2'b01: begin fn2 <= 3; end
497 2'b10: begin fn2 <= 1; end
498 2'b11: begin fn2 <= 0; t <= exec; end
499 endcase
500
501 if (!override && ((^modrm[7:6] && in[2:0] == 3'b101) || (in[5:3] == 3'b101)))
502 segment <= ss;
503
504 if (ignoreo && modrm[7:6] == 2'b00 && in[2:0] != 3'b101) begin t <= exec; fn2 <= 0; end
505 end
506 endcase
507
508 modrm_wb: case (fn2)
509 0: begin
510
511 if (dir || modrm[7:6] == 2'b11) begin
512 case (dir ? modrm[5:3] : modrm[2:0])
513 3'b000: if (size && opsize) eax <= wb; else if (size) eax[15:0] <= wb[15:0]; else eax[ 7:0] <= wb[7:0];
514 3'b001: if (size && opsize) ecx <= wb; else if (size) ecx[15:0] <= wb[15:0]; else ecx[ 7:0] <= wb[7:0];
515 3'b010: if (size && opsize) edx <= wb; else if (size) edx[15:0] <= wb[15:0]; else edx[ 7:0] <= wb[7:0];
516 3'b011: if (size && opsize) ebx <= wb; else if (size) ebx[15:0] <= wb[15:0]; else ebx[ 7:0] <= wb[7:0];
517 3'b100: if (size && opsize) esp <= wb; else if (size) esp[15:0] <= wb[15:0]; else eax[15:8] <= wb[7:0];
518 3'b101: if (size && opsize) ebp <= wb; else if (size) ebp[15:0] <= wb[15:0]; else ecx[15:8] <= wb[7:0];
519 3'b110: if (size && opsize) esi <= wb; else if (size) esi[15:0] <= wb[15:0]; else edx[15:8] <= wb[7:0];
520 3'b111: if (size && opsize) edi <= wb; else if (size) edi[15:0] <= wb[15:0]; else ebx[15:8] <= wb[7:0];
521 endcase
522 t <= t_next;
523 src <= 1'b0;
524 end
525
526 else begin
527 out <= wb[7:0];
528 we <= 1'b1;
529 src <= 1'b1;
530 fn2 <= 1;
531 end
532 end
533
534 1: begin
535 if (size) begin out <= wb[15:8]; ea <= ea + 1; fn2 <= 2; end
536 else begin fn2 <= 0; t <= t_next; {src, we} <= 2'b00; end
537 end
538
539 2: begin
540 if (opsize) begin out <= wb[23:16]; ea <= ea + 1; fn2 <= 3; end
541 else begin fn2 <= 0; t <= t_next; {src, we} <= 2'b00; end
542 end
543
544 3: begin out <= wb[31:24]; ea <= ea + 1; fn2 <= 4; end
545 4: begin fn2 <= 0; t <= t_next; {src, we} <= 2'b00; end
546 endcase
547
548 fetch_imm16: case (fn2)
549 0: begin eip <= eip_next; wb <= in; fn2 <= 1; end
550 1: begin eip <= eip_next; wb[15:8] <= in; fn2 <= opsize ? 2 : 0; if (!opsize) t <= exec; end
551 2: begin eip <= eip_next; wb[23:16] <= in; fn2 <= 3; end
552 3: begin eip <= eip_next; wb[31:24] <= in; fn2 <= 0; t <= exec; end
553 endcase
554
555 loadseg: case (fn2)
556
557 0: begin
558 t <= t_next;
559 src <= 1'b0;
560
561 case (regn)
562 3'b000: begin es[15:0] <= wb; end
563 3'b001: begin cs[15:0] <= wb; end
564 3'b010: begin ss[15:0] <= wb; end
565
566 3'b011: begin ds[15:0] <= wb; __segment[15:0] <= wb; end
567 3'b100: begin fs[15:0] <= wb; end
568 3'b101: begin gs[15:0] <= wb; end
569 default: t <= exception;
570 endcase
571 end
572 endcase
573
574 push: case (fn2)
575
576 0: begin
577 fn2 <= 1;
578 segment <= ss;
579 ea <= esp_dec;
580 esp <= esp_dec;
581 src <= 1'b1;
582 we <= 1'b1;
583 out <= wb[7:0];
584 end
585
586 1: begin ea <= ea + 1; out <= wb[ 15:8]; fn2 <= stacksize | opsize ? 2 : 4; end
587 2: begin ea <= ea + 1; out <= wb[24:16]; fn2 <= 3; end
588 3: begin ea <= ea + 1; out <= wb[31:24]; fn2 <= 4; end
589 4: begin {we, src} <= 2'b00; fn2 <= 0; t <= t_next; end
590 endcase
591
592 pop: case (fn2)
593
594 0: begin
595 fn2 <= 1;
596 segment <= ss;
597 ea <= esp;
598 esp <= esp_inc;
599 src <= 1'b1;
600 end
601
602 1: begin fn2 <= 2; wb <= in; ea <= ea + 1; end
603 2: begin
604 wb[15:8] <= in;
605 fn2 <= stacksize | opsize ? 3 : 0;
606 ea <= ea + 1;
607 if (opsize == 0) begin src <= 1'b0; t <= t_next; end
608 end
609
610 3: begin wb[23:16] <= in; fn2 <= 4; ea <= ea + 1; end
611 4: begin wb[31:24] <= in; fn2 <= 0; src <= 1'b0; t <= t_next; end
612 endcase
613
614
615
616
617 shift: case (fn2)
618
619
620 0: begin
621 fn2 <= 1;
622
623 if (size && opsize) begin
624 wb <= 31;
625 op2 <= op2[4:0];
626 if (op2[4:0] == 0) begin fn2 <= 0; src <= 1'b0; t <= fetch; end
627 end
628
629 else if (size) begin
630
631 wb <= 15;
632 op2 <= op2[4:0];
633 if (op2[4:0] == 0) begin fn2 <= 0; src <= 1'b0; t <= fetch; end
634 end
635
636 else begin
637 wb <= 7;
638 op2 <= op2[2:0];
639 if (op2[2:0] == 0) begin fn2 <= 0; src <= 1'b0; t <= fetch; end
640 end
641 end
642
643 1: begin
644
645 if (op2) begin
646 op2 <= op2 - 1;
647 case (alu)
648 0:
649 begin op1 <= size ? (opsize ? {op1[30:0],op1[31]} : {op1[14:0],op1[15]}) : {op1[6:0],op1[7]}; end
650 1:
651 begin op1 <= size ? (opsize ? {op1[0],op1[31:1]} : {op1[0],op1[15:1]}) : {op1[0],op1[7:1]}; end
652 2:
653 begin
654 op1 <= size ? (opsize ? {op1[30:0],eflags[CF]} : {op1[14:0],eflags[CF]}) : {op1[6:0],eflags[CF]};
655 eflags[CF] <= op1[wb];
656 end
657 3:
658 begin
659 op1 <= size ? (opsize ? {eflags[CF],op1[31:1]} : {eflags[CF],op1[15:1]}) : {eflags[CF],op1[7:1]};
660 eflags[CF] <= op1[0];
661 end
662 4, 6:
663 begin
664 eflags[CF] <= op1[wb-op2+1];
665 op1 <= op1 << op2;
666 op2 <= 0;
667 end
668 5:
669 begin
670 eflags[CF] <= op1[op2-1];
671 op1 <= op1 >> op2;
672 op2 <= 0;
673 end
674 7:
675 begin
676 op1 <= size ? (opsize ? {op1[31],op1[31:1]} : {op1[15],op1[15:1]}) : {op1[7],op1[7:1]};
677 eflags[CF] <= op1[0];
678 end
679 endcase
680 end
681
682 else begin
683 fn2 <= 0;
684 t <= modrm_wb;
685 wb <= op1;
686 case (alu)
687 0: begin eflags[CF] <= op1[0]; eflags[OF] <= op1[0] ^ op1[wb]; end
688 1: begin eflags[CF] <= op1[wb]; eflags[OF] <= op1[wb] ^ op1[wb-1]; end
689 2: begin eflags[OF] <= eflags[CF] ^ op1[wb]; end
690 3: begin eflags[OF] <= op1[wb] ^ op1[wb-1]; end
691 default: begin
692 eflags[ZF] <= !op1;
693 eflags[SF] <= op1[wb];
694 eflags[PF] <= ~^op1[7:0];
695 eflags[AF] <= 1'b1;
696 end
697 endcase
698 end
699 end
700 endcase
701
702 divide: begin
703 if (divcnt) begin
704
705 divrem <= _divr >= divb ? _divr - divb : _divr;
706
707 divres <= {divres[62:0], _divr >= divb};
708
709 diva <= {diva[62:0], 1'b0};
710
711 divcnt <= divcnt - 1'b1;
712 end
713 else t <= t_next;
714 end
715
716
717
718 interrupt: case (fn)
719
720 0: begin
721 fn <= 1;
722 t <= push;
723 t_next <= interrupt;
724 wb <= eflags;
725 eflags[IF] <= 1'b0;
726 eflags[TF] <= 1'b0;
727 op1 <= wb;
728 end
729 1: begin fn <= 2; t <= push; wb <= cs[15:0]; end
730 2: begin fn <= 3; t <= push; wb <= eip[15:0]; end
731
732 3: begin fn <= 4; ea <= {op1[7:0], 2'b00}; src <= 1'b1; segment[15:0] <= 16'h0000; end
733 4: begin fn <= 5; eip[ 7:0] <= in; ea <= ea + 1; end
734 5: begin fn <= 6; eip[15:8] <= in; ea <= ea + 1; end
735 6: begin fn <= 7; wb [ 7:0] <= in; ea <= ea + 1; end
736 7: begin
737 t <= loadseg;
738 t_next <= fetch;
739 fn <= 0;
740 fn2 <= 0;
741 wb[15:8] <= in;
742 regn <= 1;
743 end
744 endcase
745 exec: casex (opcode)
746
747
748 9'b0_1110_1001,
749 9'b1_1000_xxxx: begin
750 t <= fetch;
751 if (opsize) eip <= eip + wb;
752 else eip[15:0] <= eip[15:0] + wb[15:0];
753 end
754
755 9'b1_0100_xxxx: begin
756 if (branches[ opcode[3:1] ] != opcode[0]) begin
757 t <= modrm_wb;
758 wb <= op2;
759 end else begin src <= 0; t <= fetch; end
760 end
761
762 9'b1_1001_xxxx: begin
763 t <= modrm_wb;
764 wb <= branches[ opcode[3:1] ] != opcode[0] ? 1'b1 : 1'b0;
765 end
766
767 9'b1_1011_x11x: begin
768 t <= modrm_wb;
769 if (opcode[2])
770 wb <= opcode[0] ? {{16{op2[15]}}, op2[15:0]} : {{24{op2[7]}}, op2[7:0]};
771 else wb <= opcode[0] ? op2[15:0] : op2[7:0];
772 end
773
774 8'b00xx_x0xx: begin
775 t <= modrm_wb;
776 wb <= alu_r;
777 eflags <= alu_f;
778 if (alu == alu_cmp) begin t <= fetch; src <= 1'b0; end
779 end
780
781 8'b00xx_x10x: case (fn)
782
783 0: begin
784 fn <= 1;
785 op1 <= size ? (opsize ? eax : eax[15:0]) : eax[7:0];
786 op2 <= size ? (opsize ? wb : wb[15:0]) : in;
787 if (size == 0) eip <= eip_next;
788 end
789
790 1: begin
791 t <= fetch;
792 eflags <= alu_f;
793 if (alu != alu_cmp) begin
794 if (opsize && size) eax <= alu_r;
795 else if (size) eax[15:0] <= alu_r[15:0];
796 else eax[7:0] <= alu_r[7:0];
797 end
798 end
799 endcase
800
801 8'b000x_x111: begin
802 t <= loadseg;
803 t_next <= fetch;
804 regn <= opcode[4:3];
805 end
806
807 8'b0100_xxxx: case (fn)
808
809 0: begin
810 fn <= 1;
811 op1 <= reg32;
812 op2 <= 1;
813 alu <= opcode[3] ? alu_sub : alu_add;
814 end
815
816 1: begin
817 t <= modrm_wb;
818 wb <= alu_r;
819 eflags <= {alu_f[17:1], eflags[CF]};
820 dir <= 1'b1;
821 modrm[5:3] <= opcode[2:0];
822 end
823 endcase
824
825 8'b0101_0xxx: begin
826 t <= push;
827 wb <= reg32;
828 end
829
830 8'b0101_1xxx: begin
831 t <= modrm_wb;
832 t_next <= fetch;
833 size <= 1'b1;
834 dir <= 1'b1;
835 modrm[5:3] <= opcode[2:0];
836 end
837
838 8'b0110_0000: begin
839 if (regn == 7) t_next <= fetch;
840 wb <= regn == 4 ? frametemp : reg32;
841 t <= push;
842 regn <= regn + 1;
843 end
844
845 8'b0110_0001: begin
846 t <= regn == 0 ? fetch : pop;
847 regn <= regn - 1;
848 case (regn)
849 0: if (opsize) eax <= wb; else eax[15:0] <= wb[15:0];
850 1: if (opsize) ecx <= wb; else ecx[15:0] <= wb[15:0];
851 2: if (opsize) edx <= wb; else edx[15:0] <= wb[15:0];
852 3: if (opsize) ebx <= wb; else ebx[15:0] <= wb[15:0];
853
854 5: if (opsize) ebp <= wb; else ebp[15:0] <= wb[15:0];
855 6: if (opsize) esi <= wb; else esi[15:0] <= wb[15:0];
856 7: if (opsize) edi <= wb; else edi[15:0] <= wb[15:0];
857 endcase
858 end
859
860 8'b0110_10x0: begin
861 t <= push;
862 t_next <= fetch;
863 if (opcode[1]) begin wb <= {{24{in[7]}}, in}; eip <= eip_next; end
864 end
865
866 8'b0110_10x1: case (fn)
867 0: begin
868 fn <= 1;
869 t <= opcode[1] ? exec : fetch_imm16;
870 t_next <= exec;
871 op1 <= op2;
872 wb <= in;
873 if (opcode[1]) eip <= eip_next;
874 end
875 1: begin
876 fn <= 2;
877 op1 <= opsize ? op2 : {{16{op2[15]}}, op2[15:0]};
878 op2 <= opcode[1] ? {{24{wb[7]}}, wb[7:0]} : (opsize ? wb : {{16{wb[15]}}, wb[15:0]});
879 end
880 2: begin
881 if (opsize) begin
882 wb <= mult[31:0];
883 eflags[CF] <= mult[63:32] ? 1 : 0;
884 eflags[OF] <= mult[63:32] ? 1 : 0;
885 end
886 else begin
887 wb <= mult[15:0];
888 eflags[CF] <= mult[31:16] ? 1 : 0;
889 eflags[OF] <= mult[31:16] ? 1 : 0;
890 end
891 t <= modrm_wb;
892 t_next <= fetch;
893 end
894 endcase
895
896 8'b1000_00xx: case (fn)
897
898 0: begin
899 fn <= 2;
900 alu <= modrm[5:3];
901 case (opcode[1:0])
902 0, 2: begin eip <= eip_next; op2 <= in; end
903 1: begin t <= fetch_imm16; fn <= 1; end
904 3: begin eip <= eip_next; op2 <= opsize ? {{24{in[7]}}, in} : {{8{in[7]}}, in}; end
905 endcase
906 end
907
908 1: begin fn <= 2; op2 <= wb; end
909
910 2: begin
911 t <= modrm_wb;
912 wb <= alu_r;
913 eflags <= alu_f;
914 src <= 1'b1;
915 if (alu == alu_cmp) begin t <= fetch; src <= 1'b0; end
916 end
917 endcase
918
919 8'b1000_010x: begin
920 eflags <= alu_f;
921 fn <= 1'b0;
922 t <= fetch;
923 src <= 1'b0;
924 end
925
926 8'b1000_011x: case (fn)
927 0: begin t <= modrm_wb; wb <= op2; t_next <= exec; fn <= 1; end
928 1: begin t <= modrm_wb; wb <= op1; t_next <= fetch; dir <= 0; end
929 endcase
930
931
932 8'b1000_10xx,
933 8'b1000_1101: begin
934 t <= modrm_wb;
935 wb <= opcode[2] ? ea : op2;
936 end
937
938 8'b1000_110x: begin
939 t <= modrm_wb;
940 case (modrm[5:3])
941 3'h0: wb <= es[15:0];
942 3'h1: wb <= cs[15:0];
943 3'h2: wb <= ss[15:0];
944 3'h3: wb <= ds[15:0];
945 3'h4: wb <= fs[15:0];
946 3'h5: wb <= gs[15:0];
947 default: t <= exception;
948 endcase
949 end
950
951 8'b1000_1110: begin
952 wb <= op2;
953 t <= modrm[5:3] == 3'b001 ? exception : loadseg;
954 regn <= modrm[5:3];
955 end
956
957 8'b1000_1111: case (fn)
958 1: begin t <= fetch_modrm; fn <= 2; {dir, ignoreo} <= 2'b01; end
959 2: begin t <= modrm_wb; t_next <= fetch; end
960 endcase
961
962 8'b1001_0xxx: begin
963 t <= modrm_wb;
964 wb <= eax;
965 dir <= 1'b1;
966 modrm[5:3] <= regn;
967 if (opsize) eax <= reg32; else eax[15:0] <= reg32[15:0];
968 end
969
970 8'b1001_1010,
971 8'b1110_1010: case (fn)
972 0: begin fn <= 1; opsize <= 1'b0; op1 <= wb; t <= fetch_imm16; end
973 1: begin
974 fn <= 2;
975 t <= loadseg;
976 t_next <= opcode[4] ? exec : fetch;
977 regn <= 3'h1;
978 if (opsize) eip <= op1; else eip[15:0] <= op1;
979
980 op1 <= eip;
981 op2 <= cs[15:0];
982 end
983 2: begin fn <= 3; t <= push; wb <= op2; end
984 3: begin fn <= 0; t <= push; wb <= op1; t_next <= fetch; end
985 endcase
986
987 8'b1001_1101: begin
988 t <= fetch;
989 if (opsize)
990 eflags[17:0] <= {wb[17:6], 1'b0, wb[4], 1'b0, wb[2], 1'b1, wb[0]};
991 else
992 eflags[15:0] <= {wb[15:6], 1'b0, wb[4], 1'b0, wb[2], 1'b1, wb[0]};
993 end
994
995 8'b1010_00xx: case (fn)
996
997 0: begin
998 fn <= 1;
999 src <= 1'b1;
1000 ea <= wb;
1001 adsize <= opsize;
1002 opsize <= adsize;
1003 size <= opcode[0];
1004 if (opcode[1]) begin
1005 t <= modrm_wb;
1006 wb <= eax;
1007 dir <= 1'b0;
1008 modrm <= 1'b0;
1009 end
1010 end
1011
1012 1: begin
1013 fn <= 2;
1014 ea <= ea + 1;
1015 eax[7:0] <= in;
1016 if (opcode[0] == 1'b0) begin fn <= 0; src <= 1'b0; t <= fetch; end
1017 end
1018 2: begin
1019 fn <= 3;
1020 ea <= ea + 1;
1021 eax[15:8] <= in;
1022 if (opsize == 1'b0) begin fn <= 0; src <= 1'b0; t <= fetch; end
1023 end
1024 3: begin eax[23:16] <= in; fn <= 4; ea <= ea + 1; end
1025 4: begin eax[31:24] <= in; t <= fetch; src <= 1'b0; end
1026 endcase
1027
1028 8'b1010_010x: begin
1029 t <= modrm_wb;
1030 t_next <= fetch;
1031 segment <= es;
1032 ea <= defsize ? edi : edi[15:0];
1033 wb <= op1;
1034 modrm <= 1'b0;
1035 esi <= str_esi;
1036 edi <= str_edi;
1037 if (rep[1]) begin ecx <= str_ecx; eip <= eip_rep; end
1038 end
1039
1040 8'b1010_011x: case (fn)
1041 0: begin
1042 fn <= 1;
1043 fn2 <= 4;
1044 dir <= 1'b1;
1045 segment <= es;
1046 ea <= defsize ? edi : edi[15:0];
1047 t <= fetch_modrm;
1048 end
1049 1: begin
1050 t <= fetch;
1051 src <= 1'b0;
1052 eflags <= alu_f;
1053 esi <= str_esi;
1054 edi <= str_edi;
1055 if (rep[1]) ecx <= str_ecx;
1056 if (rep[1] && rep[0] == alu_f[ZF]) eip <= eip_rep;
1057 end
1058 endcase
1059
1060 8'b1010_100x: case (fn)
1061 0: begin
1062 fn <= 1;
1063 op1 <= eax;
1064 op2 <= opcode[0] ? wb : in;
1065 alu <= alu_and;
1066 if (opcode[0] == 1'b0) eip <= eip_next;
1067 end
1068 1: begin eflags <= alu_f; fn <= 1'b0; t <= fetch; end
1069 endcase
1070
1071 8'b1010_110x: begin
1072 t <= fetch;
1073 src <= 1'b0;
1074 esi <= str_esi;
1075
1076 if (size && opsize) eax <= op1[31:0];
1077 else if (size) eax[15:0] <= op1[15:0];
1078 else eax[7:0] <= op1[ 7:0];
1079 if (rep[1]) begin ecx <= str_ecx; eip <= eip_rep; end
1080 end
1081
1082 8'b1010_111x: begin
1083 src <= 1'b0;
1084 t <= fetch;
1085 eflags <= alu_f;
1086 edi <= str_edi;
1087 if (rep[1]) ecx <= str_ecx;
1088 if (rep[1] && rep[0] == alu_f[ZF]) eip <= eip_rep;
1089 end
1090
1091 8'b1011_xxxx: begin
1092 t <= modrm_wb;
1093 dir <= 1'b1;
1094 size <= opcode[3];
1095 modrm[5:3] <= opcode[2:0];
1096
1097 if (!opcode[3]) begin eip <= eip_next; wb <= in; end
1098 end
1099
1100 8'b1100_011x: case (fn)
1101
1102 0: begin
1103 fn <= size ? 2 : 1;
1104 src <= 1'b0;
1105 if (size) t <= fetch_imm16;
1106 end
1107 1: begin fn <= 2; wb <= in; eip <= eip_next; end
1108 2: begin src <= 1'b1; t <= modrm_wb; t_next <= fetch; end
1109 endcase
1110
1111 8'b1100_000x,
1112 8'b1101_00xx: begin
1113 t <= shift;
1114 t_next <= fetch;
1115 alu <= modrm[5:3];
1116 src <= 1'b1;
1117 if (opcode[4])
1118 op2 <= opcode[1] ? ecx[5:0] : 1'b1;
1119 else begin
1120 eip <= eip_next;
1121 op2 <= in;
1122 end
1123 end
1124
1125 8'b1100_010x: case (fn)
1126 0: begin fn <= 1; t <= modrm_wb; t_next <= exec; wb <= op2; end
1127 1: begin fn <= 2; src <= 1'b1; ea <= ea + (opsize ? 4 : 2); end
1128 2: begin wb[7:0] <= in; fn <= 3; ea <= ea + 1; end
1129 3: begin
1130 t <= loadseg;
1131 t_next <= fetch;
1132 regn <= opcode[0] ? 3 : 0;
1133 wb[15:8] <= in;
1134 end
1135 endcase
1136
1137 8'b1100_001x: case (fn)
1138 0: begin fn <= 1; t <= pop; op1 <= wb; end
1139 1: begin
1140 t <= fetch;
1141 if (defsize) eip <= wb; else eip[15:0] <= wb[15:0];
1142 if (stacksize) esp <= esp + op1; else esp[15:0] <= esp[15:0] + op1[15:0];
1143 end
1144 endcase
1145
1146 8'b1100_1000: case (fn)
1147 0: begin
1148 fn <= in ? 1 : 2;
1149 op1 <= wb;
1150 op2 <= in;
1151 eip <= eip_next;
1152 t <= push;
1153 wb <= ebp;
1154 frametemp <= esp_dec;
1155 end
1156 1: begin
1157 t <= push;
1158 wb <= op2 > 1 ? ebp-2 : frametemp;
1159 ebp <= op2 > 1 ? ebp-2 : ebp;
1160 fn <= op2 == 1 ? 2 : 1;
1161 op2 <= op2 - 1;
1162 end
1163 2: begin
1164 t <= fetch;
1165 ebp <= frametemp;
1166 esp <= ebp - op1;
1167 end
1168 endcase
1169
1170 8'b1100_1001: begin ebp <= wb; t <= fetch; end
1171
1172 8'b1100_101x: case (fn)
1173 0: begin fn <= 1; t <= pop; op1 <= wb; end
1174 1: begin
1175 fn <= 2;
1176 t <= pop;
1177 if (defsize) eip <= wb; else eip[15:0] <= wb[15:0];
1178 end
1179 2: begin
1180 t <= loadseg;
1181 t_next <= fetch;
1182 regn <= 3'h1;
1183 if (stacksize) esp <= esp + op1; else esp[15:0] <= esp[15:0] + op1[15:0];
1184 end
1185 endcase
1186
1187 8'b1100_1101: begin t <= interrupt; eip <= eip_next; wb <= in; end
1188
1189 8'b1100_1111: case (fn)
1190 1: begin fn <= 2; t <= pop; op1 <= wb; end
1191 2: begin fn <= 3; t <= pop; op2 <= wb; end
1192 3: begin
1193 t <= loadseg;
1194 t_next <= fetch;
1195 regn <= 1;
1196 eflags <= wb;
1197 wb <= op2;
1198 if (defsize) eip <= op1; else eip[15:0] <= op1[15:0];
1199 end
1200 endcase
1201
1202 8'b1110_x10x: case (fn)
1203 0: begin
1204 fn <= 1;
1205 eip <= eip_next;
1206 port <= in;
1207 port_clk <= 1'b0;
1208 end
1209 1: begin fn <= 2; port_clk <= 1; end
1210 2: begin fn <= 3; port_clk <= 0; end
1211 3: begin fn <= 1;
1212 case (op2[1:0])
1213 0: eax[7:0] <= port_i;
1214 1: eax[15:8] <= port_i;
1215 2: eax[23:16] <= port_i;
1216 3: eax[31:24] <= port_i;
1217 endcase
1218 port <= port + 1'b1;
1219 op2[1:0] <= op2[1:0] + 1'b1;
1220 if (op1[1:0] == op2[1:0]) t <= fetch;
1221 end
1222 endcase
1223
1224 8'b1110_1000: begin
1225 t <= push;
1226 t_next <= fetch;
1227 wb <= eip;
1228 if (opsize) eip <= eip + wb;
1229 else eip[15:0] <= eip[15:0] + wb[15:0];
1230 end
1231
1232 8'b1101_0100: case (fn)
1233 0: begin
1234 fn <= 1;
1235 t <= in ? divide : interrupt;
1236 t_next <= exec;
1237 diva <= {eax[7:0], 56'b0};
1238 divb <= in;
1239 divcnt <= 8;
1240 wb <= 0;
1241 eip <= eip_next;
1242 end
1243 1: begin
1244 src <= 1'b0;
1245 t <= fetch;
1246 if (divb) begin
1247 eax[15:0] <= {divres[7:0], divrem[7:0]};
1248 eflags[ZF] <= eax[15:0] == 0;
1249 eflags[SF] <= eax[15];
1250 eflags[PF] <= ~^eax[15];
1251 end
1252 end
1253 endcase
1254
1255 8'b1101_0101: begin
1256 t <= fetch;
1257 eip <= eip_next;
1258 eax[15:0] <= aam;
1259 eflags[ZF] <= aam[15:0] == 0;
1260 eflags[SF] <= aam[15];
1261 eflags[PF] <= ~^aam[15];
1262 end
1263
1264 8'b1101_0111: begin eax[7:0] <= in; src <= 1'b0; t <= fetch; end
1265
1266 8'b1110_00xx,
1267 8'b1110_1011,
1268 8'b0111_xxxx: begin
1269 t <= fetch;
1270 eip <= eip + 1'b1 + {{24{in[7]}}, in};
1271 end
1272
1273 8'b1110_x11x: case (fn)
1274 0: begin
1275 fn <= 1;
1276 eip <= eip_next;
1277 port <= in;
1278 port_clk <= 1'b0;
1279 end
1280 1: begin
1281 fn <= 2;
1282 port_w <= 1;
1283 port_clk <= 1;
1284 case (op2[1:0])
1285 0: port_o <= eax[ 7:0];
1286 1: port_o <= eax[ 15:8];
1287 2: port_o <= eax[23:16];
1288 3: port_o <= eax[31:24];
1289 endcase
1290 end
1291 2: begin fn <= 3; port_w <= 0; port_clk <= 0; end
1292 3: begin fn <= 1;
1293 port <= port + 1'b1;
1294 op2[1:0] <= op2[1:0] + 1'b1;
1295 if (op1[1:0] == op2[1:0]) t <= fetch;
1296 end
1297 endcase
1298
1299 8'b1111_011x: casex (modrm[5:3])
1300
1301 3'b00x: case (fn)
1302
1303 0: if (src) src <= 1'b0;
1304 else begin
1305 fn <= opcode[0] ? 1 : 2;
1306 t <= opcode[0] ? fetch_imm16 : exec;
1307 op2 <= in;
1308 alu <= alu_and;
1309 src <= 1'b0;
1310 if (opcode[0] == 1'b0) eip <= eip_next;
1311 end
1312 1: begin fn <= 2; op2 <= wb; end
1313 2: begin eflags <= alu_f; t <= fetch; end
1314 endcase
1315
1316 3'b010: begin
1317 wb <= ~op1;
1318 t <= modrm_wb;
1319 t_next <= fetch;
1320 end
1321
1322 3'b011: case (fn)
1323 0: begin fn <= 1; op1 <= 0; op2 <= op1; alu <= alu_sub; end
1324 1: begin wb <= alu_r; eflags <= alu_f; t <= modrm_wb; t_next <= fetch; end
1325 endcase
1326
1327 3'b10x: case (fn)
1328
1329 0: begin
1330 fn <= 1;
1331 if (modrm[3]) begin
1332 op1 <= size ? (opsize ? op1 : {{16{op1[15]}}, op1[15:0]}) : {{24{op1[7]}}, op1[7:0]};
1333 op2 <= size ? (opsize ? eax : {{16{eax[15]}}, eax[15:0]}) : {{24{eax[7]}}, eax[7:0]};
1334 end else begin
1335 op2 <= size ? (opsize ? eax : eax[15:0]) : eax[7:0];
1336 end
1337 end
1338
1339 1: begin
1340 src <= 1'b0;
1341 t <= fetch;
1342
1343
1344 if (opsize && size) begin
1345 eax <= mult[31:0];
1346 edx <= mult[63:32];
1347 eflags[ZF] <= mult[63:0] == 64'b0;
1348 eflags[CF] <= edx[31:0] != 32'b0;
1349 eflags[OF] <= edx[31:0] != 32'b0;
1350 end else if (size) begin
1351 eax[15:0] <= mult[15:0];
1352 edx[15:0] <= mult[31:16];
1353 eflags[ZF] <= mult[31:0] == 32'b0;
1354 eflags[CF] <= edx[15:0] != 16'b0;
1355 eflags[OF] <= edx[15:0] != 16'b0;
1356 end else begin
1357 eax[15:0] <= mult[15:0];
1358 eflags[ZF] <= mult[15:0] == 16'b0;
1359 eflags[CF] <= eax[15:8] != 8'b0;
1360 eflags[OF] <= eax[15:8] != 8'b0;
1361 end
1362 end
1363 endcase
1364
1365 3'b11x: case (fn)
1366
1367 0: begin
1368 fn <= 1;
1369 t <= divide;
1370 diva <= _diva;
1371 divb <= _divb;
1372 divcnt <= size ? (opsize ? 64 : 32) : 16;
1373 divrem <= 1'b0;
1374 divres <= 1'b0;
1375 signa <= 1'b0;
1376 signb <= 1'b0;
1377
1378 if (modrm[3]) begin
1379
1380 signa <= _diva[63];
1381 signb <= _divb[alu_top];
1382
1383 if (_diva[63]) begin
1384 if (size && opsize) diva <= -_diva;
1385 else if (size) diva[63:32] <= -_diva[63:32];
1386 else diva[63:48] <= -_diva[63:48];
1387 end
1388
1389 if (size && opsize && _divb[31]) divb[31:0] <= -_divb[31:0];
1390 else if (size && _divb[15]) divb[15:0] <= -_divb[15:0];
1391 else if (_divb[7]) divb[ 7:0] <= -_divb[ 7:0];
1392 end
1393 end
1394
1395 1: begin
1396 t <= fetch;
1397 src <= 1'b0;
1398 wb <= 1'b0;
1399 if (size && opsize) begin
1400 eax <= signd ? -divres[31:0] : divres[31:0];
1401 edx <= divrem[31:0];
1402 if (|divres[63:32] || divb[31:0] == 0) t <= interrupt;
1403 end else if (size) begin
1404 eax[15:0] <= signd ? -divres[15:0] : divres[15:0];
1405 edx[15:0] <= divrem[15:0];
1406 if (|divres[31:16] || divb[15:0] == 0) t <= interrupt;
1407 end else begin
1408 eax[ 7:0] <= signd ? -divres[7:0] : divres[7:0];
1409 eax[15:8] <= divrem[7:0];
1410 if (|divres[15:8] || divb[7:0] == 0) t <= interrupt;
1411 end
1412 end
1413 endcase
1414 endcase
1415
1416 8'b1111_111x: case (modrm[5:3])
1417
1418 3'b000,
1419 3'b001: case (fn)
1420 0: begin fn <= 1; op2 <= 1; alu <= modrm[3] ? 5 : 0; end
1421 1: begin wb <= alu_r; t <= modrm_wb; t_next <= fetch; eflags <= {alu_f[11:1], eflags[CF]}; end
1422 endcase
1423
1424 3'b010,
1425 3'b100: if (size) begin
1426 t <= modrm[4] ? push : fetch;
1427 t_next <= fetch;
1428 src <= modrm[4];
1429 wb <= eip;
1430 if (opsize) eip <= op1; else eip[15:0] <= op1[15:0];
1431 end else t <= exception;
1432
1433 3'b011,
1434 3'b101: if (size) case (fn)
1435 0: begin
1436
1437 op1 <= cs[15:0];
1438 op2 <= eip;
1439
1440 if (defsize | opsize) eip <= op1; else eip[15:0] <= op1[15:0];
1441 fn <= 1;
1442 ea <= ea + (opsize? 4 : 2);
1443 end
1444
1445 1: begin fn <= 2; wb[7:0] <= in; ea <= ea + 1; end
1446
1447 2: begin
1448 t <= loadseg;
1449 t_next <= modrm[5] ? fetch : exec;
1450 fn <= 3;
1451 regn <= 1;
1452 wb[15:8] <= in;
1453 end
1454
1455 3: begin fn <= 4; t <= push; wb <= op1; end
1456 4: begin fn <= 5; t <= push; wb <= op2; t_next <= fetch; end
1457 endcase else t <= exception;
1458
1459 3'b110: if (size) begin
1460 t <= push;
1461 t_next <= fetch;
1462 wb <= op1;
1463 end else t <= exception;
1464
1465 3'b111: t <= exception;
1466 endcase
1467
1468 default: begin end
1469 endcase
1470endcase
1471end
1472
1473
1474
1475localparam
1476 fetch = 0,
1477 fetch_modrm = 1,
1478 exec = 2,
1479 modrm_wb = 3,
1480 fetch_imm16 = 4,
1481 loadseg = 5,
1482 exception = 6,
1483 push = 7,
1484 pop = 8,
1485 shift = 9,
1486 interrupt = 10,
1487 divide = 11,
1488 portin = 12,
1489 portout = 13;
1490localparam
1491 CF = 0, PF = 2, AF = 4, ZF = 6, SF = 7,
1492 TF = 8, IF = 9, DF = 10, OF = 11,
1493 IOPL0 = 12,
1494 IOPL1 = 13,
1495 NT = 14,
1496 RF = 16,
1497 VM = 17;
1498localparam
1499 alu_add = 3'h0, alu_or = 3'h1,
1500 alu_adc = 3'h2, alu_sbb = 3'h3,
1501 alu_and = 3'h4, alu_sub = 3'h5,
1502 alu_xor = 3'h6, alu_cmp = 3'h7;
1503
1504
1505
1506
1507assign address =
1508 src ? {segment, 4'h0} + (adsize ? ea : ea[15:0]) :
1509 { cs, 4'h0} + (adsize ? eip : eip[15:0]);
1510initial begin
1511 we = 1'b0;
1512 out = 1'b0;
1513 port = 1'b0;
1514 port_clk = 1'b0;
1515 port_o = 1'b0;
1516 port_w = 1'b0;
1517end
1518
1519
1520
1521
1522reg [31:0] eax = 32'hDAEE_707F;
1523reg [31:0] ebx = 32'h0177_AABC;
1524reg [31:0] ecx = 32'h0000_0002;
1525reg [31:0] edx = 32'h0000_0000;
1526reg [31:0] esp = 32'h0000_FFFE;
1527reg [31:0] ebp = 32'h0000_0000;
1528reg [31:0] esi = 32'h0000_0000;
1529reg [31:0] edi = 32'h0000_0004;
1530
1531reg [17:0] eflags = 18'b00_0000_0000_0000_0010;
1532reg [31:0] eip = 32'h0000_0000;
1533reg [31:0] eip_rep = 32'h0000_0000;
1534
1535reg [15:0] es = 80'hF000;
1536reg [15:0] cs = 80'hF000;
1537reg [15:0] ss = 80'h0000;
1538reg [15:0] ds = 80'hF800;
1539reg [15:0] fs = 80'h0000;
1540reg [15:0] gs = 80'h0000;
1541
1542reg [3:0] t = 1'b0;
1543reg [3:0] t_next = 1'b0;
1544reg [4:0] fn = 1'b0;
1545reg [3:0] fn2 = 1'b0;
1546reg [8:0] opcode = 1'b0;
1547reg [2:0] psize = 1'b0;
1548reg [7:0] modrm = 1'b0;
1549reg src = 1'b0;
1550reg src_next = 1'b1;
1551reg trace_ff = 1'b0;
1552reg [79:0] segment = 1'b0;
1553reg [31:0] ea = 1'b0;
1554reg prot = 1'b0;
1555reg adsize = 1'b0;
1556reg opsize = 1'b0;
1557reg override = 1'b0;
1558reg ignoreo = 1'b0;
1559reg [1:0] rep = 1'b0;
1560reg [2:0] alu = 3'h0;
1561reg size = 1'b0;
1562reg dir = 1'b0;
1563reg [ 2:0] regn = 3'b0;
1564reg [31:0] op1 = 32'h0;
1565reg [31:0] op2 = 32'h0;
1566reg [31:0] wb = 32'h0;
1567reg [31:0] frametemp = 32'h0;
1568reg __opext = 1'b0;
1569reg __adsize = 1'b0;
1570reg __opsize = 1'b0;
1571reg __override = 1'b0;
1572reg [1:0] __rep = 2'b00;
1573reg [15:0] __segment = 16'h0000;
1574
1575
1576
1577reg [63:0] diva = 1'b0;
1578reg [63:0] divb = 1'b0;
1579reg [ 6:0] divcnt = 1'b0;
1580reg [63:0] divrem = 1'b0;
1581reg [63:0] divres = 1'b0;
1582reg signa = 1'b0;
1583reg signb = 1'b0;
1584
1585wire signd = signa ^ signb;
1586wire [63:0] mult = op1 * op2;
1587wire [15:0] aam = eax[15:8]*in + eax[7:0];
1588wire [63:0] _diva = size ? (opsize ? {edx, eax} : {edx[15:0], eax[15:0], 32'h0}) : {eax[15:0], 48'h0};
1589wire [63:0] _divb = size ? (opsize ? op1 : op1[15:0]) : op1[7:0];
1590wire [63:0] _divr = {divrem, diva[63]};
1591
1592
1593
1594
1595wire defsize = 1'b1;
1596wire stacksize = 1'b1;
1597wire [15:0] sp_dec = esp[15:0] - (opsize ? 3'h4 : 2'h2);
1598wire [15:0] sp_inc = esp[15:0] + (opsize ? 3'h4 : 2'h2);
1599wire [15:0] ipnext1 = eip[15:0] + 1'b1;
1600wire [15:0] ipnext2 = eip[15:0] + 2'h2;
1601wire [15:0] ipnext3 = eip[15:0] + 2'h3;
1602wire [15:0] ipnext5 = eip[15:0] + 3'h5;
1603
1604wire [31:0] eip_next = defsize ? eip + 1'b1 : {eip[31:16], ipnext1};
1605wire [31:0] eip_next2 = defsize ? eip + 2'h2 : {eip[31:16], ipnext2};
1606wire [31:0] eip_next3 = defsize ? eip + 2'h3 : {eip[31:16], ipnext3};
1607wire [31:0] eip_next5 = defsize ? eip + 3'h5 : {eip[31:16], ipnext5};
1608wire [31:0] esp_dec = defsize ? esp - 4'h4 : {esp[31:16], sp_dec};
1609wire [31:0] esp_inc = defsize ? esp + 4'h4 : {esp[31:16], sp_inc};
1610
1611
1612
1613
1614wire [ 2:0] str_inc = t == fetch ?
1615 (( in[0] ? (__opsize ? 3'h4 : 3'h2) : 3'h1)) :
1616 ((opcode[0] ? ( opsize ? 3'h4 : 3'h2) : 3'h1));
1617wire [31:0] str_ncx = ecx - 1'b1;
1618wire [31:0] str_zcx = defsize ? ecx : ecx[15:0];
1619wire [31:0] str_nsi = eflags[DF] ? esi - str_inc : esi + str_inc;
1620wire [31:0] str_ndi = eflags[DF] ? edi - str_inc : edi + str_inc;
1621
1622wire [31:0] str_esi = defsize ? str_nsi : {esi[31:16], str_nsi[15:0]};
1623wire [31:0] str_edi = defsize ? str_ndi : {edi[31:16], str_ndi[15:0]};
1624wire [31:0] str_ecx = defsize ? str_ncx : {ecx[31:16], str_ncx[15:0]};
1625
1626
1627
1628
1629wire [31:0] sib_base =
1630 in[2:0] == 3'b000 ? eax :
1631 in[2:0] == 3'b001 ? ecx :
1632 in[2:0] == 3'b010 ? edx :
1633 in[2:0] == 3'b011 ? ebx :
1634 in[2:0] == 3'b100 ? esp :
1635 in[2:0] == 3'b101 ? (^modrm[7:6] ? ebp : 1'b0) :
1636 in[2:0] == 3'b110 ? esi :
1637 edi;
1638
1639wire [31:0] reg32 =
1640 regn == 3'd0 ? (opsize & size ? eax : (size ? eax[15:0] : eax[ 7:0])) :
1641 regn == 3'd1 ? (opsize & size ? ecx : (size ? ecx[15:0] : ecx[ 7:0])) :
1642 regn == 3'd2 ? (opsize & size ? edx : (size ? edx[15:0] : edx[ 7:0])) :
1643 regn == 3'd3 ? (opsize & size ? ebx : (size ? ebx[15:0] : ebx[ 7:0])) :
1644 regn == 3'd4 ? (opsize & size ? esp : (size ? esp[15:0] : eax[15:8])) :
1645 regn == 3'd5 ? (opsize & size ? ebp : (size ? ebp[15:0] : ecx[15:8])) :
1646 regn == 3'd6 ? (opsize & size ? esi : (size ? esi[15:0] : edx[15:8])) :
1647 (opsize & size ? edi : (size ? edi[15:0] : ebx[15:8]));
1648
1649
1650
1651wire [7:0] branches = {
1652 (eflags[SF] ^ eflags[OF]) | eflags[ZF],
1653 (eflags[SF] ^ eflags[OF]),
1654 eflags[PF],
1655 eflags[SF],
1656 eflags[CF] | eflags[ZF],
1657 eflags[ZF],
1658 eflags[CF],
1659 eflags[OF]
1660};
1661
1662
1663
1664wire [32:0] alu_r =
1665 alu == alu_add ? op1 + op2 :
1666 alu == alu_or ? op1 | op2 :
1667 alu == alu_adc ? op1 + op2 + eflags[CF] :
1668 alu == alu_sbb ? op1 - op2 - eflags[CF] :
1669 alu == alu_and ? op1 & op2:
1670 alu == alu_xor ? op1 ^ op2:
1671 op1 - op2;
1672wire [ 4:0] alu_top = size ? (opsize ? 31 : 15) : 7;
1673wire [ 5:0] alu_up = alu_top + 1'b1;
1674wire is_add = alu == alu_add || alu == alu_adc;
1675wire is_lgc = alu == alu_xor || alu == alu_and || alu == alu_or;
1676wire alu_cf = alu_r[alu_up];
1677wire alu_af = op1[4] ^ op2[4] ^ alu_r[4];
1678wire alu_sf = alu_r[alu_top];
1679wire alu_zf = size ? (opsize ? ~|alu_r[31:0] : ~|alu_r[15:0]) : ~|alu_r[7:0];
1680wire alu_pf = ~^alu_r[7:0];
1681wire alu_of = (op1[alu_top] ^ op2[alu_top] ^ is_add) & (op1[alu_top] ^ alu_r[alu_top]);
1682wire [17:0] alu_f = {
1683 eflags[17:12],
1684 alu_of & ~is_lgc,
1685 eflags[10:8],
1686 alu_sf,
1687 alu_zf,
1688 1'b0,
1689 alu_af & ~is_lgc,
1690 1'b0,
1691 alu_pf,
1692 1'b1,
1693 alu_cf & ~is_lgc
1694};
1695
1696
1697
1698reg daa_a;
1699reg daa_c;
1700reg daa_x;
1701reg [8:0] daa_i;
1702reg [7:0] daa_h;
1703reg [15:0] daa_r;
1704reg [11:0] eflags_o;
1705reg [11:0] eflags_d;
1706always @* begin
1707 daa_r = eax[15:0];
1708 eflags_d = eflags;
1709 case (in[4:3])
1710
1711 0, 1: begin
1712 daa_c = eflags[CF];
1713 daa_a = eflags[AF];
1714 daa_i = eax[7:0];
1715
1716 if (eax[3:0] > 4'h9 || eflags[AF]) begin
1717 daa_i = in[3] ? eax[7:0] - 3'h6 : eax[7:0] + 3'h6;
1718 daa_c = daa_i[8];
1719 daa_a = 1'b1;
1720 end
1721 daa_r = daa_i[7:0];
1722 daa_x = daa_c;
1723
1724 if (daa_c || daa_i[7:0] > 8'h9F) begin
1725 daa_r = in[3] ? daa_i[7:0] - 8'h60 : daa_i[7:0] + 8'h60;
1726 daa_x = 1'b1;
1727 end
1728 eflags_d[SF] = daa_r[7];
1729 eflags_d[ZF] = ~|daa_r[7:0];
1730 eflags_d[AF] = daa_a;
1731 eflags_d[PF] = ~^daa_r[7:0];
1732 eflags_d[OF] = daa_x;
1733 end
1734
1735 2, 3: begin
1736 daa_i = eax[ 7:0];
1737 daa_r = eax[15:0];
1738 if (eflags[4] || eax[3:0] > 4'h9) begin
1739 daa_i = alu[0] ? eax[ 7:0] - 3'h6 : eax[ 7:0] + 3'h6;
1740 daa_h = alu[0] ? eax[15:8] - 1'b1 : eax[15:8] + 1'b1;
1741 daa_r = {daa_h, 4'h0, daa_i[3:0]};
1742 eflags_d[AF] = 1'b1;
1743 eflags_d[CF] = 1'b1;
1744 end
1745 else begin
1746 eflags_d[AF] = 1'b0;
1747 eflags_d[CF] = 1'b0;
1748 end
1749 end
1750 endcase
1751end
1752endmodule