§ Описание
Здесь лишь только часть процессора, то есть, только его ядро: core88.Основные пины
-
clock
— 25 мгц -
resetn
— если 0, то процессор сбрасывается -
locked
— если 1, процессор работает -
address
— адрес -
bus
— входящие данные -
data
— исходящие данные -
wreq
— сигнал записи
-
port_clk
- тактовый импульс для защелкивания -
port
- номер порта -
port_i
- входящие данные из порта -
port_o
- исходящие данные -
port_w
- сигнал записи в порт
- intr - Запрос прерывания
- irq - Номер прерывания
- intr_latch - Защелка что прерывание обработано
§ Ядро процессора на Verilog
Ревизия процессора: 09/05/221// verilator lint_off CASEX 2// verilator lint_off CASEOVERLAP 3 4module core88 5( 6 input wire clock, 7 input wire reset_n, 8 input wire locked, 9 10 // Данные 11 output wire [19:0] address, 12 input wire [ 7:0] bus, 13 output reg [ 7:0] data, 14 output reg wreq, 15 16 // Порты 17 output reg port_clk, 18 output reg [15:0] port, 19 input wire [ 7:0] port_i, 20 output reg [ 7:0] port_o, 21 output reg port_w, 22 23 // Прерывания 24 input wire intr, // Запрос прерывания 25 input wire [ 7:0] irq, // Номер прерывания 26 output reg intr_latch, // ACCEPT прерывания 27 28 // Отладочные LED 29 output wire [ 3:0] iload 30); 31 32assign iload = mode; 33 34// --------------------------------------------------------------------- 35// ОБЪЯВЛЕНИЕ РЕГИСТРОВ 36// --------------------------------------------------------------------- 37 38// Сегментные регистры 39reg [15:0] seg_cs = 16'hF000; 40reg [15:0] seg_ss = 16'h0000; 41reg [15:0] seg_es = 16'h0000; 42reg [15:0] seg_ds = 16'h0000; 43reg [15:0] seg_fs = 16'h0000; 44reg [15:0] seg_gs = 16'h0000; 45 46// Регистры 47reg [31:0] eax = 32'h4321_e21B; 48reg [31:0] ebx = 32'hefd0_0001; 49reg [31:0] ecx = 32'ha1ac_0005; 50reg [31:0] edx = 32'h0b21_8001; 51reg [31:0] esp = 32'haaa3_5432; 52reg [31:0] ebp = 32'ha940_5678; 53reg [31:0] esi = 32'ha580_0002; 54reg [31:0] edi = 32'ha670_0004; 55 56// Системные 57reg [15:0] ip = 16'h0000; 58reg [15:0] ipstart = 16'h0000; 59reg [15:0] seg_ea = 16'h0000; 60reg [31:0] ea = 32'h0000_0000; 61 62// ODIT SZ A P C 63reg [11:0] flags = 12'b0000_00000010; 64 65// --------------------------------------------------------------------- 66// Состояние процессора 67// --------------------------------------------------------------------- 68 69// Выбранная шина адреса (sel=1) seg:ea (sel=0) cs:ip 70reg [3:0] mode = 1'b0; 71reg sel = 1'b0; 72reg sel_seg = 1'b0; 73reg [1:0] sel_rep = 1'b0; 74reg [3:0] tstate = 1'b0; 75reg [4:0] estate = 1'b0; 76reg [8:0] opcode = 1'b0; 77reg [7:0] modrm = 1'b0; 78reg skip_op = 1'b0; // Не считывать операнды 79reg stack32 = 1'b0; // 16/32 80reg isize = 1'b0; // 8/16 81reg opsize = 1'b0; // 16/32 82reg opsizet = 1'b0; 83reg adsize = 1'b0; // 16/32 84reg idir = 1'b0; // rm,r | r,rm 85reg [ 2:0] regn = 1'b0; // regv = register[regn] 86reg [ 2:0] alumode = 1'b0; 87reg [31:0] op1 = 1'b0; 88reg [31:0] op2 = 1'b0; 89reg [31:0] wb = 1'b0; // Для записи в reg/rm 90reg [15:0] tmp16 = 1'b0; 91reg is_intr = 1'b0; 92reg [63:0] rdtsc = 1'b0; 93 94// Модуль деления op1 / op2 -> divres | divrem 95reg [63:0] diva = 1'b0; 96reg [63:0] divb = 1'b0; 97reg [ 6:0] divcnt = 1'b0; 98reg [63:0] divrem = 1'b0; 99reg [63:0] divres = 1'b0; 100reg signa = 1'b0; 101reg signb = 1'b0; 102 103// --------------------------------------------------------------------- 104// Константы и initial 105// --------------------------------------------------------------------- 106 107localparam 108 CF = 0, PF = 2, AF = 4, ZF = 6, SF = 7, 109 TF = 8, IF = 9, DF = 10, OF = 11; 110 111localparam 112 113 PREPARE = 0, // Эта подготовки инструкции к исполнению 114 MAIN = 1, // Обработка микрокода 115 FETCHEA = 2, // Считывание ModRM/EA 116 SETEA = 3, // Запись в память или регистр 117 PUSH = 4, // Запись в стек 118 POP = 5, // Извлечь из стека 119 INTERRUPT = 6, // Вызов прерывания 120 LOADSEG = 7, // Загрузка сегмента 121 IMMEDIATE = 8, // Непосредственное значение 122 SHIFT = 9, // Сдвиги 123 DIVIDE = 10, // Деление 8/16/32 битного 124 EXTENDED0 = 11, 125 EXTENDED = 12; // Расширенный опкод 126 127initial begin 128 129 data = 8'hFF; 130 wreq = 0; 131 port_w = 0; 132 port_o = 0; 133 port_clk = 0; 134 port = 0; 135 intr_latch = 0; 136 137end 138 139// --------------------------------------------------------------------- 140// Предвычисления 141// --------------------------------------------------------------------- 142 143// Выбор регистра 144wire [31:0] regv = 145 regn == 0 ? (isize ? (opsize ? eax : eax[15:0]) : eax[ 7:0]) : 146 regn == 1 ? (isize ? (opsize ? ecx : ecx[15:0]) : ecx[ 7:0]) : 147 regn == 2 ? (isize ? (opsize ? edx : edx[15:0]) : edx[ 7:0]) : 148 regn == 3 ? (isize ? (opsize ? ebx : ebx[15:0]) : ebx[ 7:0]) : 149 regn == 4 ? (isize ? (opsize ? esp : esp[15:0]) : eax[15:8]) : 150 regn == 5 ? (isize ? (opsize ? ebp : ebp[15:0]) : ecx[15:8]) : 151 regn == 6 ? (isize ? (opsize ? esi : esi[15:0]) : edx[15:8]) : 152 (isize ? (opsize ? edi : edi[15:0]) : ebx[15:8]); 153 154// Вычисление условий 155wire [7:0] branches = { 156 157 (flags[SF] ^ flags[OF]) | flags[ZF], // 7: (ZF=1) OR (SF!=OF) 158 (flags[SF] ^ flags[OF]), // 6: SF!=OF 159 flags[PF], // 5: PF 160 flags[SF], // 4: SF 161 flags[CF] | flags[ZF], // 3: CF or ZF 162 flags[ZF], // 2: ZF 163 flags[CF], // 1: CF 164 flags[OF] // 0: OF 165}; 166 167// Модуль умножения 168wire [63:0] mult = op1 * op2; 169wire signd = signa ^ signb; 170 171// Выбор источника памяти 172assign address = sel ? {seg_ea, 4'h0} + ea : {seg_cs, 4'h0} + ip; 173 174// ===================================================================== 175// Основная работа процессорного микрокода, так сказать 176// ===================================================================== 177 178// Считать такты процессора 179always @(posedge clock) rdtsc <= rdtsc + 1; 180 181always @(posedge clock) 182// Сброс 183if (reset_n == 0) begin seg_cs <= 16'hF000; ip <= 0; mode <= PREPARE; end 184// Исполнение 185else if (locked) case (mode) 186 187 // Считывание опкода, сброс, прерывания 188 PREPARE: begin 189 190 opcode <= bus; 191 idir <= 0; 192 isize <= 0; 193 modrm <= 0; 194 opsize <= 0; 195 adsize <= 0; 196 sel_seg <= 0; 197 sel_rep <= 0; 198 stack32 <= 0; 199 skip_op <= 0; 200 seg_ea <= seg_ds; 201 tstate <= 0; 202 estate <= 0; 203 ipstart <= ip; 204 205 // Есть наличие IRQ из контроллера прерываний 206 if (flags[IF] & (intr ^ intr_latch)) begin 207 208 is_intr <= 1; 209 mode <= INTERRUPT; 210 wb <= irq; 211 intr_latch <= intr; 212 213 // Разблокировка HLT 214 if (bus == 8'hF4) ip <= ip + 1; 215 216 end 217 else begin 218 219 is_intr <= 0; 220 ip <= ip + 1; 221 mode <= MAIN; 222 223 end 224 225 end 226 227 // Исполнение инструкции 228 MAIN: casex (opcode) 229 230 // Сегментные префиксы 231 8'h26: begin opcode <= bus; ip <= ip + 1; sel_seg <= 1; seg_ea <= seg_es; end 232 8'h2E: begin opcode <= bus; ip <= ip + 1; sel_seg <= 1; seg_ea <= seg_cs; end 233 8'h36: begin opcode <= bus; ip <= ip + 1; sel_seg <= 1; seg_ea <= seg_ss; end 234 8'h3E: begin opcode <= bus; ip <= ip + 1; sel_seg <= 1; seg_ea <= seg_ds; end 235 8'h64: begin opcode <= bus; ip <= ip + 1; sel_seg <= 1; seg_ea <= seg_fs; end 236 8'h65: begin opcode <= bus; ip <= ip + 1; sel_seg <= 1; seg_ea <= seg_gs; end 237 // Расширения операнда и адреса 238 8'h66: begin opcode <= bus; ip <= ip + 1; opsize <= ~opsize; end 239 8'h67: begin opcode <= bus; ip <= ip + 1; adsize <= ~adsize; end 240 // REP: 241 8'hF2: begin opcode <= bus; ip <= ip + 1; sel_rep <= 2'b10; end // REPNZ 242 8'hF3: begin opcode <= bus; ip <= ip + 1; sel_rep <= 2'b11; end // REPZ 243 // Расширение опкода 244 8'h0F: begin opcode <= {1'b1, bus}; ip <= ip + 1; end 245 // Неиспользуемые коды операции LOCK: FWAIT 246 8'hF0, 8'h9B: begin opcode <= bus; ip <= ip + 1; end 247 248 // ==== Групповые инструкции должны идти первыми ==== 249 250 // Групповые инструкции F6/F7 251 8'b1111_011x: case (tstate) 252 253 0: begin tstate <= 1; {idir, isize} <= opcode[0]; mode <= FETCHEA; end 254 1: begin tstate <= 2; case (modrm[5:3]) 255 256 // TEST 257 0, 1: begin sel <= 0; mode <= IMMEDIATE; end 258 // NOT 259 2: begin wb <= ~op1; mode <= SETEA; end 260 // NEG 261 3: begin op1 <= 0; op2 <= op1; alumode <= 5; end 262 // MUL 263 4: begin op2 <= isize ? (opsize ? eax : eax[15:0]) : eax[7:0]; end 264 // IMUL 265 5: begin 266 267 op1 <= isize ? (opsize ? op1 : {{16{op1[15]}},op1[15:0]}) : {{24{op1[7]}},op1[7:0]}; 268 op2 <= isize ? (opsize ? eax : {{16{eax[15]}},eax[15:0]}) : {{24{eax[7]}},eax[7:0]}; 269 270 end 271 // DIV, IDIV 272 6, 7: begin 273 274 divcnt <= isize ? (opsize ? 64 : 32) : 16; 275 diva <= isize ? (opsize ? {edx, eax} : {edx[15:0],eax[15:0],32'h0}) : {eax[15:0],48'h0}; 276 divb <= isize ? (opsize ? op1 : op1[15:0]) : op1[7:0]; 277 divrem <= 0; 278 divres <= 0; 279 signa <= 0; 280 signb <= 0; 281 282 // Переход к IDIV вместо DIV 283 if (modrm[3]) tstate <= 4; else mode <= DIVIDE; 284 285 end 286 287 endcase end 288 2: begin tstate <= 3; case (modrm[5:3]) 289 290 0, 1: begin op2 <= wb; alumode <= 4; end 291 2: begin sel <= 0; mode <= PREPARE; end 292 3: begin wb <= result; flags <= flags_o; mode <= SETEA; end 293 4, 5: begin 294 295 sel <= 0; 296 mode <= PREPARE; 297 298 // CF,OF устанавливаются при переполнении 299 // ZF при нулевом результате 300 if (opsize && isize) begin // 32 bit 301 302 eax <= mult[31:0]; 303 edx <= mult[63:32]; 304 flags[ZF] <= mult[63:0] == 0; 305 flags[CF] <= edx != 0; 306 flags[OF] <= edx != 0; 307 308 end else if (isize) begin // 16 bit 309 310 eax[15:0] <= mult[15:0]; 311 edx[15:0] <= mult[31:16]; 312 flags[ZF] <= mult[31:0] == 0; 313 flags[CF] <= edx[15:0] != 0; 314 flags[OF] <= edx[15:0] != 0; 315 316 end else begin // 8 bit 317 318 eax[15:0] <= mult[15:0]; 319 flags[ZF] <= mult[15:0] == 0; 320 flags[CF] <= eax[15:8] != 0; 321 flags[OF] <= eax[15:8] != 0; 322 323 end 324 325 end 326 6, 7: begin 327 328 sel <= 0; 329 wb <= 0; 330 mode <= PREPARE; 331 332 if (isize && opsize) begin 333 334 eax <= signd ? -divres[31:0] : divres[31:0]; 335 edx <= divrem[31:0]; 336 337 if (|divres[63:32] || divb[31:0] == 0) mode <= INTERRUPT; 338 339 end else if (isize) begin 340 341 eax[15:0] <= signd ? -divres[15:0] : divres[15:0]; 342 edx[15:0] <= divrem[15:0]; 343 344 if (|divres[31:16] || divb[15:0] == 0) mode <= INTERRUPT; 345 346 end else begin 347 348 eax[ 7:0] <= signd ? -divres[7:0] : divres[7:0]; 349 eax[15:8] <= divrem[7:0]; 350 351 if (|divres[15:8] || divb[7:0] == 0) mode <= INTERRUPT; 352 353 end 354 355 end 356 357 endcase end 358 3: case (modrm[5:3]) 359 360 0, 1: begin flags <= flags_o; mode <= PREPARE; end 361 3, 6: begin sel <= 0; mode <= PREPARE; end 362 363 endcase 364 365 // Коррекция IDIV 366 4: begin 367 368 signa <= diva[63]; 369 370 // Определение знака A 371 if (diva[63]) begin 372 373 if (isize && opsize) diva <= -diva; 374 else if (isize) diva[63:32] <= -diva[63:32]; 375 else diva[63:48] <= -diva[63:48]; 376 377 end 378 379 // Определение знака A 380 if (isize && opsize && divb[31]) begin signb <= 1; divb[31:0] <= -divb[31:0]; end 381 else if (isize && divb[15]) begin signb <= 1; divb[15:0] <= -divb[15:0]; end 382 else if (divb[7]) begin signb <= 1; divb[ 7:0] <= -divb[ 7:0]; end 383 384 tstate <= 2; 385 mode <= DIVIDE; 386 387 end 388 389 endcase 390 391 // Групповые инструкции #2 INC/DEC r8 392 8'b1111_1110: case (tstate) 393 394 0: begin tstate <= 1; mode <= FETCHEA; {idir, isize} <= 2'b00; end 395 1: begin tstate <= 2; op2 <= 1; alumode <= modrm[3] ? 5 : 0; end 396 2: begin tstate <= 3; wb <= result; flags <= {flags_o[11:1], 1'b0}; mode <= SETEA; end 397 3: begin sel <= 0; mode <= PREPARE; end 398 399 endcase 400 401 // Групповые инструкции #3 Word/DWord 402 8'b1111_1111: case (tstate) 403 404 0: begin tstate <= 1; {idir, isize} <= 2'b01; mode <= FETCHEA; end 405 1: begin tstate <= 2; case (modrm[5:3]) 406 407 // INC|DEC 408 0, 1: begin op2 <= 1; alumode <= modrm[3] ? 5 : 0; end 409 // CALL rm16 410 2: begin wb <= ip; ip <= op1; mode <= PUSH; end 411 // CALL far: Запись CS 412 3: begin wb <= seg_cs; mode <= PUSH; op2 <= ea; tmp16 <= seg_ea; end 413 // JMP rm16 414 4: begin ip <= op1; sel <= 0; mode <= PREPARE; end 415 // JMP far 416 5: begin ip <= op1; ea <= ea + (opsize ? 4 : 2); sel <= 1; end 417 // PUSH rm16 418 6: begin wb <= op1; mode <= PUSH; end 419 420 endcase end 421 2: begin tstate <= 3; case (modrm[5:3]) 422 423 // INC|DEC 424 0, 1: begin mode <= SETEA; wb <= result; flags <= {flags_o[11:1], 1'b0}; {idir, isize} <= 2'b01; end 425 // CALL far: запись IP 426 3: begin wb <= ip; ip <= op1; mode <= PUSH; end 427 // JMP far 428 5: begin wb <= bus; ea <= ea + 1; end 429 2, 6: mode <= PREPARE; 430 431 endcase end 432 3: begin tstate <= 4; case (modrm[5:3]) 433 434 // INC|DEC 435 0, 1: begin sel <= 0; mode <= PREPARE; end 436 // CALL far 437 3: begin sel <= 1; seg_ea <= op2; ea <= tmp16 + (opsize ? 4 : 2); end 438 // JMP far 439 5: begin wb[15:8] <= bus; mode <= LOADSEG; regn <= 1; end 440 441 endcase end 442 4: begin tstate <= 5; case (modrm[5:3]) 443 444 3: begin wb <= bus; ea <= ea + 1; end 445 5: begin sel <= 0; mode <= PREPARE; end 446 447 endcase end 448 5: begin tstate <= 6; case (modrm[5:3]) 449 450 3: begin wb[15:8] <= bus; mode <= LOADSEG; regn <= 1; end 451 452 endcase end 453 5: case (modrm[5:3]) 454 455 3: begin sel <= 0; mode <= PREPARE; end 456 457 endcase 458 459 endcase 460 461 // Arithmetic Grp 462 8'b1000_00xx: case (tstate) 463 464 // Прочесть байт modrm, найти ссылку на память 465 0: begin tstate <= 1; mode <= FETCHEA; isize <= opcode[0]; idir <= 0; end 466 467 // Запрос на получение второго операнда 468 1: begin tstate <= 2; mode <= IMMEDIATE; 469 470 alumode <= modrm[5:3]; 471 sel <= 0; 472 if (opcode[1:0] == 2'b11) isize <= 0; 473 474 end 475 // Распознание второго операнда 476 2: begin 477 478 tstate <= 3; 479 op2 <= opcode[1:0] == 2'b11 ? (opsize ? {{24{wb[7]}},wb[7:0]} : {{8{wb[7]}},wb[7:0]}) : wb; 480 isize <= opcode[0]; 481 482 end 483 // Запись результата 484 3: begin 485 486 tstate <= 4; 487 mode <= alumode == 7 ? PREPARE : SETEA; 488 sel <= alumode == 7 ? 0 : 1; 489 wb <= result; 490 flags <= flags_o; 491 if (alumode == 7) sel <= 0; 492 493 end 494 4: begin sel <= 0; mode <= PREPARE; end 495 496 endcase 497 498 // ALU modrm 499 8'b00_xxx_0xx: case (tstate) 500 501 0: begin tstate <= 1; mode <= FETCHEA; {idir, isize} <= opcode[1:0]; alumode <= opcode[5:3]; end 502 1: begin tstate <= 2; flags <= flags_o; if (alumode < 7) begin mode <= SETEA; wb <= result; end end 503 2: begin mode <= PREPARE; sel <= 0; end 504 505 endcase 506 507 // ALU ac, # 508 8'b00_xxx_10x: case (tstate) 509 510 0: begin 511 512 tstate <= 1; 513 mode <= IMMEDIATE; 514 alumode <= opcode[5:3]; 515 isize <= opcode[0]; 516 op1 <= opcode[0] ? (opsize ? eax : eax[15:0]) : eax[7:0]; 517 518 end 519 1: begin tstate <= 2; op2 <= wb; end 520 2: begin tstate <= 3; flags <= flags_o; 521 522 idir <= 1; 523 mode <= alumode == 7 ? PREPARE : SETEA; 524 wb <= result; 525 modrm[5:3] <= 0; 526 527 end 528 3: mode <= PREPARE; 529 530 endcase 531 532 // IMUL r16, rm, i16/i8 533 8'b0110_10x1: case (tstate) 534 535 0: begin tstate <= 1; mode <= FETCHEA; {idir, isize} <= 2'b11; end 536 1: begin tstate <= 2; mode <= IMMEDIATE; isize <= ~opcode[1]; op1 <= op2; sel <= 0; end 537 2: begin tstate <= 3; 538 539 isize <= 1'b1; 540 op1 <= opsize ? op2 : {{16{op2[15]}}, op2[15:0]}; 541 op2 <= isize ? (opsize ? wb : {{16{wb[15]}}, wb[15:0]}) : {{24{wb[7]}}, wb[7:0]}; 542 543 end 544 3: begin tstate <= 4; 545 546 if (opsize) begin 547 548 wb <= mult[31:0]; 549 flags[CF] <= mult[63:32] ? 1 : 0; 550 flags[OF] <= mult[63:32] ? 1 : 0; 551 552 end 553 else begin 554 555 wb <= mult[15:0]; 556 flags[CF] <= mult[31:16] ? 1 : 0; 557 flags[OF] <= mult[31:16] ? 1 : 0; 558 559 end 560 561 mode <= SETEA; 562 563 end 564 4: begin mode <= PREPARE; sel <= 0; end 565 566 endcase 567 568 // PUSH i16/i8 569 8'b0110_10x0: case (tstate) 570 571 0: begin tstate <= 1; isize <= !opcode[1]; mode <= IMMEDIATE; end 572 1: begin tstate <= 2; isize <= 1; mode <= PUSH; if (isize == 0) wb <= {{24{wb[7]}}, wb[7:0]}; end 573 2: begin mode <= PREPARE; sel <= 0; end 574 575 endcase 576 577 // ==== Строковые инструкции ==== 578 579 // MOVSx 580 8'b1010_010x: case (tstate) 581 582 0: begin // Читать 583 584 tstate <= 1; 585 isize <= opcode[0]; 586 ea <= esi[15:0]; 587 op1 <= 0; 588 op2 <= opcode[0] ? (opsize ? 4 : 2) : 1; 589 590 // Если REP и CX=0, то пропуск инструкции 591 if (sel_rep && ecx[15:0] == 0) begin sel <= 0; mode <= PREPARE; end 592 else begin sel <= 1; estate <= 4; mode <= FETCHEA; end 593 594 end 595 1: begin // Писать 596 597 tstate <= 2; 598 estate <= 0; 599 seg_ea <= seg_es; 600 ea <= edi[15:0]; 601 wb <= op1; 602 mode <= SETEA; 603 604 end 605 2: begin // Инкременты 606 607 sel <= 0; 608 mode <= PREPARE; 609 610 esi[15:0] <= flags[DF] ? esi[15:0] - op2 : esi[15:0] + op2; 611 edi[15:0] <= flags[DF] ? edi[15:0] - op2 : edi[15:0] + op2; 612 613 if (sel_rep) begin ecx[15:0] <= ecx[15:0] - 1; ip <= ipstart; end 614 615 end 616 617 endcase 618 619 // CMPSx 620 8'b1010_011x: case (tstate) 621 622 0: begin // Читать DS:SI 623 624 tstate <= 1; 625 isize <= opcode[0]; 626 ea <= esi[15:0]; 627 op1 <= 0; 628 tmp16 <= opcode[0] ? (opsize ? 4 : 2) : 1; 629 alumode <= 7; // alu=CMP 630 631 // Если REP и CX=0, то пропуск инструкции 632 if (sel_rep && ecx[15:0] == 0) 633 begin sel <= 0; mode <= PREPARE; end 634 else begin sel <= 1; mode <= FETCHEA; estate <= 4; end 635 636 end 637 1: begin // Читать ES:DI 638 639 tstate <= 2; 640 estate <= 4; 641 idir <= 1; 642 seg_ea <= seg_es; 643 ea <= edi[15:0]; 644 mode <= FETCHEA; 645 646 end 647 2: begin // Инкременты 648 649 sel <= 0; 650 mode <= PREPARE; 651 flags <= flags_o; 652 653 esi[15:0] <= flags[DF] ? esi[15:0] - tmp16 : esi[15:0] + tmp16; 654 edi[15:0] <= flags[DF] ? edi[15:0] - tmp16 : edi[15:0] + tmp16; 655 656 // При CMPSx всегда проверяется REPZ/REPNZ 657 // При любом REP должен быть декрементирован CX 658 if (sel_rep) ecx[15:0] <= ecx[15:0] - 1; 659 if (sel_rep && sel_rep[0] == flags_o[ZF]) ip <= ipstart; 660 661 end 662 663 endcase 664 665 // STOSx 666 8'b1010_101x: case (tstate) 667 668 0: begin 669 670 tstate <= 1; 671 isize <= opcode[0]; 672 seg_ea <= seg_es; 673 ea <= edi[15:0]; 674 wb <= eax; 675 op2 <= opcode[0] ? (opsize ? 4 : 2) : 1; 676 677 // Если REP и CX=0, то пропуск инструкции 678 if (sel_rep && ecx[15:0] == 0) mode <= PREPARE; 679 else begin sel <= 1; mode <= SETEA; end 680 681 end 682 1: begin 683 684 sel <= 0; 685 mode <= PREPARE; 686 687 // Увеличить/Уменьшить DI 688 edi[15:0] <= flags[DF] ? edi[15:0] - op2 : edi[15:0] + op2; 689 690 // Если есть префикс REP: то повторить инструкцию 691 if (sel_rep) begin ecx[15:0] <= ecx[15:0] - 1; ip <= ipstart; end 692 693 end 694 695 endcase 696 697 // LODSx 698 8'b1010_110x: case (tstate) 699 700 0: begin 701 702 tstate <= 1; 703 estate <= 4; 704 isize <= opcode[0]; 705 ea <= esi[15:0]; 706 op1 <= 0; 707 op2 <= opcode[0] ? (opsize ? 4 : 2) : 1; 708 709 // Если REP и CX=0, то пропуск инструкции 710 if (sel_rep && ecx[15:0] == 0) mode <= PREPARE; 711 else begin sel <= 1; mode <= FETCHEA; end 712 713 end 714 1: begin 715 716 sel <= 0; 717 mode <= PREPARE; 718 719 // Загрузка в Acc 720 if (isize && opsize) eax <= op1; 721 else if (isize) eax[15:0] <= op1[15:0]; 722 else eax[7:0] <= op1[7:0]; 723 724 esi[15:0] <= flags[DF] ? esi[15:0] - op2 : esi[15:0] + op2; 725 if (sel_rep) begin ecx[15:0] <= ecx[15:0] - 1; ip <= ipstart; end 726 727 end 728 729 endcase 730 731 // SCASx 732 8'b1010_111x: case (tstate) 733 734 0: begin // Читать ES:DI 735 736 tstate <= 1; 737 idir <= 1; 738 isize <= opcode[0]; 739 seg_ea <= seg_es; 740 ea <= edi[15:0]; 741 op1 <= eax; 742 tmp16 <= opcode[0] ? (opsize ? 4 : 2) : 1; 743 alumode <= 7; // alu=CMP 744 745 // Если REP и CX=0, то пропуск инструкции 746 if (sel_rep && ecx[15:0] == 0) 747 begin sel <= 0; mode <= PREPARE; end 748 else begin sel <= 1; mode <= FETCHEA; estate <= 4; end 749 750 end 751 1: begin // Инкременты 752 753 sel <= 0; 754 mode <= PREPARE; 755 flags <= flags_o; 756 757 edi[15:0] <= flags[DF] ? edi[15:0] - tmp16 : edi[15:0] + tmp16; 758 759 // Учет префикса REP: 760 if (sel_rep) ecx[15:0] <= ecx[15:0] - 1; 761 if (sel_rep && sel_rep[0] == flags_o[ZF]) ip <= ipstart; 762 763 end 764 765 endcase 766 767 // ==== Все инструкции ==== 768 769 // PUSH sr 770 8'b00_0xx_110: case (tstate) 771 772 0: begin tstate <= 1; 773 774 mode <= PUSH; 775 case (opcode[4:3]) 776 2'b00: wb <= seg_es; 777 2'b01: wb <= seg_cs; 778 2'b10: wb <= seg_ss; 779 2'b11: wb <= seg_ds; 780 endcase 781 782 end 783 784 1: mode <= PREPARE; 785 786 endcase 787 788 // POP sr 789 8'b00_0xx_111: case (tstate) 790 791 0: begin tstate <= 1; mode <= POP; end 792 1: begin tstate <= 2; mode <= LOADSEG; regn <= opcode[4:3]; end 793 2: mode <= PREPARE; 794 795 endcase 796 797 // DAA|DAS|AAA|AAS 798 8'b00_1xx_111: case (tstate) 799 800 0: begin tstate <= 1; op1 <= eax[15:0]; alumode <= opcode[4:3]; end 801 1: begin mode <= PREPARE; 802 803 flags <= flags_d; 804 if (opcode[4]) 805 eax[15:0] <= daa_r; 806 else eax[ 7:0] <= daa_r[7:0]; 807 808 end 809 810 endcase 811 812 // INC|DEC r 813 8'b01_00x_xxx: case (tstate) 814 815 0: begin tstate <= 1; op2 <= 1; regn <= opcode[2:0]; isize <= 1'b1; end 816 1: begin tstate <= 2; op1 <= regv; alumode <= opcode[3] ? /*SUB*/ 5 : /*ADD*/ 0; end 817 2: begin tstate <= 3; 818 819 mode <= SETEA; 820 idir <= 1'b1; 821 wb <= result; 822 flags <= {flags_o[11:1], flags[0]}; 823 modrm[5:3] <= regn; 824 825 end 826 3: mode <= PREPARE; 827 828 endcase 829 830 // PUSH r 831 8'b01_010_xxx: case (tstate) 832 833 0: begin tstate <= 1; regn <= opcode[2:0]; isize <= 1'b1; end 834 1: begin tstate <= 2; wb <= regv; mode <= PUSH; end 835 2: mode <= PREPARE; 836 837 endcase 838 839 // POP r 840 8'b01_011_xxx: case (tstate) 841 842 0: begin tstate <= 1; mode <= POP; {idir, isize} <= 2'b11; end 843 1: begin tstate <= 2; mode <= SETEA; modrm[5:3] <= opcode[2:0]; end 844 2: begin mode <= PREPARE; end 845 846 endcase 847 848 // Jccc b8 849 8'b0111_xxxx: begin 850 851 // Проверка на выполнение условия в branches 852 if (branches[ opcode[3:1] ] ^ opcode[0]) 853 ip <= ip + 1 + {{8{bus[7]}}, bus[7:0]}; 854 else 855 ip <= ip + 1; 856 857 mode <= PREPARE; 858 859 end 860 861 // TEST rm, r 862 8'b1000_010x: case (tstate) 863 864 0: begin tstate <= 1; {idir, isize} <= opcode[1:0]; mode <= FETCHEA; alumode <= 4; end 865 1: begin flags <= flags_o; sel <= 0; mode <= PREPARE; end 866 867 endcase 868 869 // XCHG rm, r 870 8'b1000_011x: case (tstate) 871 872 0: begin tstate <= 1; {idir, isize} <= opcode[1:0]; mode <= FETCHEA; alumode <= 4; end 873 1: begin tstate <= 2; wb <= op2; mode <= SETEA; end 874 2: begin tstate <= 3; wb <= op1; mode <= SETEA; idir <= 0; end 875 3: begin sel <= 0; mode <= PREPARE; end 876 877 endcase 878 879 // MOV rmr 880 8'b1000_10xx: case (tstate) 881 882 0: begin tstate <= 1; {idir, isize} <= opcode[1:0]; mode <= FETCHEA; end 883 1: begin tstate <= 2; wb <= op2; mode <= SETEA; end 884 2: begin sel <= 0; mode <= PREPARE; end 885 886 endcase 887 888 // LEA r16, ea 889 8'b1000_1101: case (tstate) 890 891 0: begin tstate <= 1; {idir, isize} <= 2'b11; mode <= FETCHEA; skip_op <= 1; end 892 1: begin tstate <= 2; wb <= ea; mode <= SETEA; end 893 2: begin sel <= 0; mode <= PREPARE; end 894 895 endcase 896 897 // MOV sreg|rm 898 8'b1000_11x0: case (tstate) 899 900 0: begin tstate <= 1; {isize, idir} <= opcode[2:1]; skip_op <= ~opcode[1]; mode <= FETCHEA; end 901 1: begin 902 903 tstate <= 2; 904 905 // MOV sr, r16 906 if (opcode[1]) begin 907 908 mode <= LOADSEG; 909 regn <= modrm[5:3]; 910 wb <= op2; 911 912 end 913 // MOV rm, sr 914 else begin 915 916 mode <= SETEA; 917 case (modrm[5:3]) 918 0: wb <= seg_es; 919 1: wb <= seg_cs; 920 2: wb <= seg_ss; 921 3: wb <= seg_ds; 922 4: wb <= seg_fs; 923 5: wb <= seg_gs; 924 endcase 925 926 end 927 928 end 929 2: begin sel <= 0; mode <= PREPARE; end 930 931 endcase 932 933 // POP rm 934 8'b1000_1111: case (tstate) 935 936 0: begin tstate <= 1; mode <= POP; {idir, isize} <= 2'b01; op1 <= seg_ea; end 937 1: begin tstate <= 2; mode <= FETCHEA; skip_op <= 1; seg_ea <= op1; end 938 2: begin tstate <= 3; mode <= SETEA; end 939 3: begin sel <= 0; mode <= PREPARE; end 940 941 endcase 942 943 // XCHG ax, r 944 8'b1001_0000: mode <= PREPARE; 945 8'b1001_0xxx: case (tstate) 946 947 0: begin tstate <= 1; regn <= opcode[2:0]; modrm[5:3] <= opcode[2:0]; {isize, idir} <= 2'b11; end 948 1: begin tstate <= 2; mode <= SETEA; wb <= eax; if (opsize) eax <= regv; else eax[15:0] <= regv; end 949 2: begin sel <= 0; mode <= PREPARE; end 950 951 endcase 952 953 // CBW, CWDE 954 8'b1001_1000: begin 955 956 if (opsize) eax[31:16] <= {16{eax[15]}}; 957 else eax[15:8] <= {8{eax[7]}}; 958 959 mode <= PREPARE; 960 961 end 962 963 // CWD, CDQ 964 8'b1001_1001: begin 965 966 if (opsize) edx <= {32{eax[31]}}; 967 else edx[15:0] <= {16{eax[15]}}; 968 969 mode <= PREPARE; 970 971 end 972 973 // CALL far 974 8'b1001_1010: case (tstate) 975 976 0: begin tstate <= 1; isize <= 1; mode <= IMMEDIATE; end 977 1: begin tstate <= 2; opsize <= 0; mode <= IMMEDIATE; op1 <= wb; end 978 2: begin tstate <= 3; mode <= PUSH; wb <= seg_cs; op2 <= wb; end 979 3: begin tstate <= 4; mode <= PUSH; wb <= ip; end 980 4: begin tstate <= 5; mode <= LOADSEG; wb <= op2; regn <= 1; ip <= op1; end 981 5: begin mode <= PREPARE; end 982 983 endcase 984 985 // PUSHF 986 8'b1001_1100: case (tstate) 987 988 0: begin tstate <= 1; mode <= PUSH; wb <= {flags[11:6],1'b0,flags[4],1'b0,flags[2],1'b1,flags[0]}; end 989 1: begin sel <= 0; mode <= PREPARE; end 990 991 endcase 992 993 // POPF 994 8'b1001_1101: case (tstate) 995 996 0: begin tstate <= 1; mode <= POP; end 997 1: begin flags <= wb[11:0]; sel <= 0; mode <= PREPARE; end 998 999 endcase 1000 1001 // SAHF, LAHF 1002 8'b1001_1110: begin flags[7:0] <= eax[15:8]; mode <= PREPARE; end 1003 8'b1001_1111: begin eax[15:8] <= flags[7:0]; mode <= PREPARE; end 1004 1005 // MOV r,# 1006 8'b1011_xxxx: case (tstate) 1007 1008 0: begin 1009 1010 tstate <= 1; 1011 idir <= 1; 1012 isize <= opcode[3]; 1013 modrm[5:3] <= opcode[2:0]; 1014 mode <= IMMEDIATE; 1015 1016 end 1017 1: begin tstate <= 2; mode <= SETEA; end 1018 2: mode <= PREPARE; 1019 1020 endcase 1021 1022 // MOV ac, [m16] 1023 8'b1010_00xx: case (tstate) 1024 1025 0: begin // Чтение imm8/16/32 1026 1027 tstate <= 1; 1028 opsizet <= opsize; 1029 opsize <= adsize; 1030 isize <= 1; 1031 mode <= IMMEDIATE; 1032 1033 end 1034 1: begin // Запрос на чтение из памяти или запись в память 1035 1036 tstate <= 2; 1037 sel <= 1; 1038 modrm <= 0; 1039 idir <= 0; 1040 isize <= opcode[0]; 1041 opsize <= opsizet; 1042 ea <= wb; 1043 1044 // acc -> mem 1045 if (opcode[1]) begin mode <= SETEA; wb <= eax; end else 1046 // mem -> acc 1047 begin mode <= FETCHEA; sel <= 1; estate <= 4; end 1048 1049 end 1050 2: begin // Запись в регистр ACC или выход 1051 1052 sel <= 0; 1053 mode <= PREPARE; 1054 1055 // Запись в регистр AL, AX, EAX 1056 if (opcode[1] == 0) begin 1057 1058 if (isize && opsize) eax <= op1; 1059 else if (isize) eax[15:0] <= op1[15:0]; 1060 else eax[7:0] <= op1[7:0]; 1061 1062 end 1063 1064 end 1065 1066 endcase 1067 1068 // TEST eax, # 1069 8'b1010_100x: case (tstate) 1070 1071 0: begin tstate <= 1; isize <= opcode[0]; mode <= IMMEDIATE; end 1072 1: begin tstate <= 2; alumode <= 4; op1 <= eax; op2 <= wb; end 1073 2: begin flags <= flags_o; sel <= 0; mode <= PREPARE; end 1074 1075 endcase 1076 1077 // RET [i16] 1078 8'b1100_001x: case (tstate) 1079 1080 // Если opcode[0]=0, imm16 1081 0: begin tstate <= 1; isize <= 1; mode <= POP; end 1082 1: begin tstate <= 2; op1 <= wb; if (opcode[0] == 0) mode <= IMMEDIATE; end 1083 2: begin 1084 1085 ip <= op1; 1086 sel <= 0; 1087 mode <= PREPARE; 1088 1089 // Если RET imm, то добавить к стеку 1090 if (opcode[0] == 0) begin 1091 if (stack32) esp <= esp + wb; else esp[15:0] <= esp[15:0] + wb; 1092 end 1093 1094 end 1095 1096 endcase 1097 1098 // LES|LDS r16, [m] 1099 8'b1100_010x: case (tstate) 1100 1101 0: begin tstate <= 1; {idir, isize} <= 2'b11; mode <= FETCHEA; end 1102 1: begin tstate <= 2; mode <= SETEA; wb <= op2; end 1103 2: begin tstate <= 3; ea <= ea + opsize ? 4 : 2; end 1104 3: begin tstate <= 4; wb[7:0] <= bus; ea <= ea + 1; end 1105 4: begin tstate <= 5; wb[15:8] <= bus; regn <= opcode[0] ? 3 : 0; mode <= LOADSEG; sel <= 0; end 1106 5: begin mode <= PREPARE; end 1107 1108 endcase 1109 1110 // MOV rm, # 1111 8'b1100_011x: case (tstate) 1112 1113 0: begin tstate <= 1; {idir, isize} <= {1'b0, opcode[0]}; skip_op <= 1; mode <= FETCHEA; end 1114 1: begin tstate <= 2; sel <= 0; mode <= IMMEDIATE; end 1115 2: begin tstate <= 3; sel <= 1; mode <= SETEA; end 1116 3: begin sel <= 0; mode <= PREPARE; end 1117 1118 endcase 1119 1120 // RETF 1121 8'b1100_101x: case (tstate) 1122 1123 0: begin tstate <= 1; isize <= 1; mode <= POP; end 1124 1: begin tstate <= 2; op1 <= wb; mode <= POP; end 1125 2: begin tstate <= 3; op2 <= wb; if (opcode[0] == 0) mode <= IMMEDIATE; end 1126 3: begin tstate <= 4; 1127 1128 ip <= op1; 1129 wb <= op2; 1130 regn <= 1; 1131 sel <= 0; 1132 mode <= LOADSEG; 1133 1134 if (opcode[0] == 0) begin 1135 if (stack32) esp <= esp + wb; else esp[15:0] <= esp[15:0] + wb; 1136 end 1137 1138 end 1139 4: mode <= PREPARE; 1140 1141 endcase 1142 1143 // INT 1/3 1144 8'b1111_0001, 1145 8'b1100_1100: case (tstate) 1146 1147 0: begin tstate <= 1; wb <= opcode[0] ? 1 : 3; mode <= INTERRUPT; end 1148 1: begin mode <= PREPARE; end 1149 1150 endcase 1151 1152 // INT i8 1153 8'b1100_1101: case (tstate) 1154 1155 0: begin tstate <= 1; isize <= 0; mode <= IMMEDIATE; end 1156 1: begin tstate <= 2; mode <= INTERRUPT; end 1157 2: begin mode <= PREPARE; end 1158 1159 endcase 1160 1161 // INTO: Вызов INT4 если OF=1 1162 8'b1100_1110: case (tstate) 1163 1164 0: begin 1165 1166 tstate <= 1; 1167 wb <= 4; 1168 mode <= flags[OF] ? INTERRUPT : PREPARE; 1169 1170 end 1171 1: mode <= PREPARE; 1172 1173 endcase 1174 1175 // IRET 1176 8'b1100_1111: case (tstate) 1177 1178 0: begin tstate <= 1; mode <= POP; end 1179 1: begin tstate <= 2; mode <= POP; op1 <= wb; end 1180 2: begin tstate <= 3; mode <= POP; op2 <= wb; end 1181 3: begin tstate <= 4; mode <= LOADSEG; regn <= 1; ip <= op1; wb <= op2; flags <= wb; end 1182 4: mode <= PREPARE; 1183 1184 endcase 1185 1186 // Сдвиговые инструкции (IMM) 1187 8'b1100_000x: case (tstate) 1188 1189 0: begin tstate <= 1; mode <= FETCHEA; {idir, isize} <= opcode[1:0]; end 1190 1: begin tstate <= 2; mode <= IMMEDIATE; sel <= 0; isize <= 0; opsizet <= isize; end 1191 2: begin tstate <= 3; mode <= SHIFT; alumode <= modrm[5:3]; op2 <= wb; isize <= opsizet; end 1192 3: begin tstate <= 4; mode <= SETEA; sel <= 1; wb <= op1; end 1193 4: begin sel <= 0; mode <= PREPARE; end 1194 1195 endcase 1196 1197 // Сдвиговые инструкции (CL,N) 1198 8'b1101_00xx: case (tstate) 1199 1200 0: begin tstate <= 1; mode <= FETCHEA; {idir, isize} <= {1'b0, opcode[0]}; end 1201 1: begin tstate <= 2; mode <= SHIFT; alumode <= modrm[5:3]; op2 <= opcode[1] ? ecx[4:0] : 1; end 1202 2: begin tstate <= 3; mode <= SETEA; wb <= op1; end 1203 3: begin sel <= 0; mode <= PREPARE; end 1204 1205 endcase 1206 1207 // AAM 1208 8'b1101_0100: case (tstate) 1209 1210 0: begin tstate <= 1; 1211 1212 divcnt <= 8; 1213 diva <= {eax[7:0], 56'b0}; 1214 divb <= bus; 1215 wb <= 0; 1216 mode <= bus ? DIVIDE : INTERRUPT; 1217 ip <= ip + 1; 1218 1219 end 1220 1: begin 1221 1222 sel <= 0; 1223 mode <= PREPARE; 1224 1225 if (divb) begin 1226 1227 eax[15:0] <= {divres[7:0], divrem[7:0]}; 1228 flags[ZF] <= eax[15:0] == 0; 1229 flags[SF] <= eax[15]; 1230 flags[PF] <= ~^eax[15]; 1231 1232 end 1233 1234 end 1235 1236 endcase 1237 1238 // AAD 1239 8'b1101_0101: case (tstate) 1240 1241 0: begin tstate <= 1; eax[15:0] <= eax[15:8]*bus + eax[7:0]; ip <= ip + 1; end 1242 1: begin mode <= PREPARE; 1243 1244 flags[ZF] <= eax[15:0] == 0; 1245 flags[SF] <= eax[15]; 1246 flags[PF] <= ~^eax[15]; 1247 1248 end 1249 1250 endcase 1251 1252 // SALC 1253 8'b1101_0110: begin eax[7:0] <= {8{flags[CF]}}; mode <= PREPARE; end 1254 1255 // XLATB 1256 8'b1101_0111: case (tstate) 1257 1258 0: begin sel <= 1; tstate <= 1; ea <= ebx[15:0] + eax[7:0]; end 1259 1: begin sel <= 0; eax[7:0] <= bus; mode <= PREPARE; end 1260 1261 endcase 1262 1263 // JCXZ 1264 8'b1110_0011: begin 1265 1266 mode <= PREPARE; 1267 if ((opsize && ecx == 0) || (!adsize && ecx[15:0] == 0)) 1268 ip <= ip + 1 + {{24{bus[7]}}, bus[7:0]}; 1269 else 1270 ip <= ip + 1; 1271 1272 end 1273 1274 // LOOPNZ, LOOPZ, LOOP 1275 8'b1110_00xx: begin 1276 1277 if (adsize) ecx <= ecx - 1; 1278 else ecx[15:0] <= ecx[15:0] - 1; 1279 1280 // ZF=0/1 и CX != 0 (после декремента) 1281 if (((flags[ZF] == opcode[0]) || opcode[1]) && (adsize ? ecx : ecx[15:0]) != 1) 1282 ip <= ip + 1 + {{24{bus[7]}}, bus[7:0]}; 1283 else 1284 ip <= ip + 1; 1285 1286 mode <= PREPARE; 1287 1288 end 1289 1290 // IN eAX, dx/i8 1291 8'b1110_x10x: case (tstate) 1292 1293 0: begin tstate <= 1; 1294 1295 if (opcode[3] == 0) ip <= ip + 1; 1296 port <= opcode[3] ? edx[15:0] : bus; 1297 op1 <= opcode[0] ? (opsize ? 3 : 1) : 0; 1298 op2 <= 0; 1299 1300 end 1301 1: begin tstate <= 2; port_clk <= 1; end 1302 2: begin tstate <= 3; port_clk <= 0; end 1303 3: begin tstate <= 1; 1304 1305 case (op2[1:0]) 1306 1307 0: eax[7:0] <= port_i; 1308 1: eax[15:8] <= port_i; 1309 2: eax[23:16] <= port_i; 1310 3: eax[31:24] <= port_i; 1311 1312 endcase 1313 1314 port <= port + 1; 1315 op2[1:0] <= op2[1:0] + 1; 1316 1317 if (op1[1:0] == op2[1:0]) mode <= PREPARE; 1318 1319 end 1320 1321 endcase 1322 1323 // OUT dx/i8, eAX 1324 8'b1110_x11x: case (tstate) 1325 1326 0: begin tstate <= 1; 1327 1328 if (opcode[3] == 0) ip <= ip + 1; 1329 port <= opcode[3] ? edx[15:0] : bus; 1330 op1 <= opcode[0] ? (opsize ? 3 : 1) : 0; 1331 op2 <= 0; 1332 1333 end 1334 1: begin tstate <= 2; 1335 1336 case (op2[1:0]) 1337 1338 0: port_o <= eax[7:0]; 1339 1: port_o <= eax[15:8]; 1340 2: port_o <= eax[23:16]; 1341 3: port_o <= eax[31:24]; 1342 1343 endcase 1344 1345 port_w <= 1; 1346 port_clk <= 1; 1347 1348 end 1349 2: begin tstate <= 3; port_w <= 0; port_clk <= 0; end 1350 3: begin tstate <= 1; 1351 1352 port <= port + 1; 1353 op2[1:0] <= op2[1:0] + 1; 1354 1355 if (op1[1:0] == op2[1:0]) mode <= PREPARE; 1356 1357 end 1358 1359 endcase 1360 1361 // CALL b16 1362 8'b1110_1000: case (tstate) 1363 1364 0: begin tstate <= 1; isize <= 1; mode <= IMMEDIATE; end 1365 1: begin tstate <= 2; wb <= ip; ip <= ip + wb; mode <= PUSH; end 1366 2: begin mode <= PREPARE; end 1367 1368 endcase 1369 1370 // JMP b16 1371 8'b1110_1001: case (tstate) 1372 1373 0: begin tstate <= 1; isize <= 1; mode <= IMMEDIATE; end 1374 1: begin mode <= PREPARE; ip <= ip + wb; end 1375 1376 endcase 1377 1378 // JMP b16:c16 1379 8'b1110_1010: case (tstate) 1380 1381 0: begin tstate <= 1; isize <= 1; mode <= IMMEDIATE; end 1382 1: begin tstate <= 2; op1 <= wb; opsize <= 0; mode <= IMMEDIATE; end 1383 2: begin tstate <= 3; mode <= LOADSEG; regn <= 1; ip <= op1; end 1384 3: begin mode <= PREPARE; end 1385 1386 endcase 1387 1388 // JMP b8 1389 8'b1110_1011: begin ip <= ip + 1 + {{8{bus[7]}}, bus[7:0]}; mode <= PREPARE; end 1390 1391 // HLT 1392 8'b1111_0100: begin ip <= ip - 1; mode <= PREPARE; end 1393 1394 // CMC, CLC, STC, CLI, STI, CLD, STD 1395 8'b1111_0101: begin flags[CF] <= ~flags[CF]; mode <= PREPARE; end 1396 8'b1111_100x: begin flags[CF] <= opcode[0]; mode <= PREPARE; end 1397 8'b1111_101x: begin flags[IF] <= opcode[0]; mode <= PREPARE; end 1398 8'b1111_110x: begin flags[DF] <= opcode[0]; mode <= PREPARE; end 1399 1400 // Коды расширенных инструкции 1401 // ============================================================= 1402 1403 // Jccc NEAR b16 1404 9'b1_1000_xxxx: case (tstate) 1405 1406 0: begin tstate <= 1; wb <= bus; ip <= ip + 1; end 1407 1: begin 1408 1409 if (branches[opcode[3:1]] ^ opcode[0]) 1410 ip <= ip + (adsize ? 3 : 1) + {bus, wb[7:0]}; 1411 else 1412 ip <= ip + (adsize ? 3 : 1); 1413 1414 mode <= PREPARE; 1415 1416 end 1417 1418 endcase 1419 1420 // RDTSC 1421 9'b1_0011_0001: begin eax <= rdtsc[31:0]; edx <= rdtsc[63:32]; mode <= PREPARE; end 1422 1423 endcase 1424 1425 // Считывание эффективного адреса и регистров 1426 FETCHEA: case (estate) 1427 1428 0: begin 1429 1430 modrm <= bus; 1431 ip <= ip + 1; 1432 1433 // Операнд 1 1434 case (idir ? bus[5:3] : bus[2:0]) 1435 1436 0: op1 <= isize ? (opsize ? eax : eax[15:0]) : eax[ 7:0]; 1437 1: op1 <= isize ? (opsize ? ecx : ecx[15:0]) : ecx[ 7:0]; 1438 2: op1 <= isize ? (opsize ? edx : edx[15:0]) : edx[ 7:0]; 1439 3: op1 <= isize ? (opsize ? ebx : ebx[15:0]) : ebx[ 7:0]; 1440 4: op1 <= isize ? (opsize ? esp : esp[15:0]) : eax[15:8]; 1441 5: op1 <= isize ? (opsize ? ebp : ebp[15:0]) : ecx[15:8]; 1442 6: op1 <= isize ? (opsize ? esi : esi[15:0]) : edx[15:8]; 1443 7: op1 <= isize ? (opsize ? edi : edi[15:0]) : ebx[15:8]; 1444 1445 endcase 1446 1447 // Операнд 2 1448 case (idir ? bus[2:0] : bus[5:3]) 1449 1450 0: op2 <= isize ? (opsize ? eax : eax[15:0]) : eax[ 7:0]; 1451 1: op2 <= isize ? (opsize ? ecx : ecx[15:0]) : ecx[ 7:0]; 1452 2: op2 <= isize ? (opsize ? edx : edx[15:0]) : edx[ 7:0]; 1453 3: op2 <= isize ? (opsize ? ebx : ebx[15:0]) : ebx[ 7:0]; 1454 4: op2 <= isize ? (opsize ? esp : esp[15:0]) : eax[15:8]; 1455 5: op2 <= isize ? (opsize ? ebp : ebp[15:0]) : ecx[15:8]; 1456 6: op2 <= isize ? (opsize ? esi : esi[15:0]) : edx[15:8]; 1457 7: op2 <= isize ? (opsize ? edi : edi[15:0]) : ebx[15:8]; 1458 1459 endcase 1460 1461 // Вычисление эффективного адреса 32 bit 1462 if (adsize) 1463 case (bus[2:0]) 1464 0: ea <= eax; 1465 1: ea <= ecx; 1466 2: ea <= edx; 1467 3: ea <= ebx; 1468 // 4: SIB 1469 5: ea <= ebp; 1470 6: ea <= esi; 1471 7: ea <= edi; 1472 endcase 1473 else 1474 // Вычисление эффективного адреса 16 bit 1475 case (bus[2:0]) 1476 1477 0: ea[15:0] <= ebx[15:0] + esi[15:0]; 1478 1: ea[15:0] <= ebx[15:0] + edi[15:0]; 1479 2: ea[15:0] <= ebp[15:0] + esi[15:0]; 1480 3: ea[15:0] <= ebp[15:0] + edi[15:0]; 1481 4: ea[15:0] <= esi[15:0]; 1482 5: ea[15:0] <= edi[15:0]; 1483 6: ea[15:0] <= ebp[15:0]; 1484 7: ea[15:0] <= ebx[15:0]; 1485 1486 endcase 1487 1488 // Выбор SS: по умолчанию 1489 if (!sel_seg) begin 1490 1491 // 32 bit 1492 if (adsize) begin if (bus[2:0] == 5 && ^bus[7:6]) seg_ea <= seg_ss; end 1493 // 16 bit 1494 else if ((bus[2:0] == 3'h6 && ^bus[7:6]) || (bus[2:1] == 2'b01)) 1495 seg_ea <= seg_ss; 1496 end 1497 1498 // 32 bit 1499 if (adsize) 1500 casex (bus) 1501 1502 8'b11_xxx_xxx: begin estate <= 0; mode <= MAIN; end // reg 1503 8'b00_xxx_101: begin estate <= 8; ea <= 0; end // disp32 1504 8'bxx_xxx_100: begin estate <= 12; end // sib 1505 8'b00_xxx_xxx: begin estate <= 4; sel <= 1; end // без disp 1506 8'b01_xxx_xxx: begin estate <= 3; end // disp8 1507 8'b10_xxx_xxx: begin estate <= 8; end // disp32 1508 1509 endcase 1510 // 16 bit 1511 else casex (bus) 1512 1513 8'b00_xxx_110: begin estate <= 1; ea <= 0; end // disp16 1514 8'b00_xxx_xxx: begin estate <= 4; sel <= 1; end // без disp 1515 8'b01_xxx_xxx: begin estate <= 3; end // disp8 1516 8'b10_xxx_xxx: begin estate <= 1; end // disp16 1517 8'b11_xxx_xxx: begin estate <= 0; mode <= MAIN; end 1518 1519 endcase 1520 1521 end 1522 1523 // Считывание 16-бит displacement 1524 1: begin estate <= 2; ip <= ip + 1; ea <= ea + bus; end 1525 2: begin estate <= 4; ip <= ip + 1; ea[15:8] <= ea[15:8] + bus; ea[31:16] <= 0; sel <= 1; end 1526 1527 // Считывание 8-бит displacement 1528 3: begin estate <= 4; 1529 1530 ip <= ip + 1; 1531 sel <= 1; 1532 1533 if (adsize) 1534 ea <= ea + {{24{bus[7]}}, bus[7:0]}; 1535 else ea[15:0] <= ea[15:0] + {{8{bus[7]}}, bus[7:0]}; 1536 1537 end 1538 1539 // Чтение операнда 8bit из памяти 1540 4: begin 1541 1542 if (skip_op) begin estate <= 0; mode <= MAIN; end 1543 else begin 1544 1545 if (idir) op2 <= bus; else op1 <= bus; 1546 if (isize) begin estate <= 5; ea <= ea + 1; end 1547 else begin estate <= 0; mode <= MAIN; end 1548 end 1549 1550 end 1551 1552 // Чтение операнда 16 бит (память) 1553 5: begin 1554 1555 if (idir) op2[15:8] <= bus; else op1[15:8] <= bus; 1556 if (opsize) begin estate <= 6; ea <= ea + 1; end 1557 else begin estate <= 0; ea <= ea - 1; mode <= MAIN; end 1558 1559 end 1560 1561 // Чтение операнда 32 бит (память) 1562 6: begin estate <= 7; if (idir) op2[23:16] <= bus; else op1[23:16] <= bus; ea <= ea + 1; end 1563 7: begin estate <= 0; if (idir) op2[31:24] <= bus; else op1[31:24] <= bus; ea <= ea - 3; mode <= MAIN; end 1564 1565 // Чтение +disp32 и переход к чтение операнда из памяти 1566 8: begin tstate <= 9; ip <= ip + 1; ea <= ea + bus; end 1567 9: begin tstate <= 10; ip <= ip + 1; ea[31:8] <= ea[31:8] + bus; end 1568 10: begin tstate <= 11; ip <= ip + 1; ea[31:16] <= ea[31:16] + bus; end 1569 11: begin tstate <= 4; ip <= ip + 1; ea[31:24] <= ea[31:24] + bus; sel <= 1; end 1570 1571 // Разбор байта SIB: Считывание SS*INDEX 1572 12: begin 1573 1574 estate <= 13; 1575 1576 casex (bus) 1577 1578 8'bxx_000_xxx: ea <= eax << bus[7:6]; 1579 8'bxx_001_xxx: ea <= ecx << bus[7:6]; 1580 8'bxx_010_xxx: ea <= edx << bus[7:6]; 1581 8'bxx_011_xxx: ea <= ebx << bus[7:6]; 1582 8'bxx_100_xxx: ea <= 0; 1583 8'bxx_101_xxx: ea <= ebp << bus[7:6]; 1584 8'bxx_110_xxx: ea <= esi << bus[7:6]; 1585 8'bxx_111_xxx: ea <= edi << bus[7:6]; 1586 1587 endcase 1588 1589 // Выбор сегмента SS: по умолчанию 1590 if (!sel_seg && bus[5:3] == 5) seg_ea <= seg_ss; 1591 1592 end 1593 1594 // Считывание BASE 1595 13: begin 1596 1597 estate <= 4; 1598 sel <= 1; 1599 ip <= ip + 1; 1600 1601 case (bus[2:0]) 1602 1603 // disp32 1604 3'b000: ea <= ea + eax; 1605 3'b001: ea <= ea + ecx; 1606 3'b010: ea <= ea + edx; 1607 3'b011: ea <= ea + ebx; 1608 3'b100: ea <= ea + esp; 1609 3'b101: 1610 if (^modrm[7:6]) begin 1611 ea <= ea + ebp; 1612 if (!sel_seg) seg_ea <= seg_ss; 1613 end 1614 3'b110: ea <= ea + esi; 1615 3'b111: ea <= ea + edi; 1616 1617 endcase 1618 1619 // +disp8/32 1620 if (modrm[7:6] == 2'b00 && bus[2:0] == 5) begin sel <= 0; estate <= 8; end 1621 else if (modrm[7:6] == 2'b01) begin sel <= 0; estate <= 3; end 1622 else if (modrm[7:6] == 2'b10) begin sel <= 0; estate <= 8; end 1623 1624 end 1625 1626 endcase 1627 1628 // Запись обратно в память или регистр [idir, isize, modrm, wb] 1629 // * idir (1 запись `wb` в регистр modrm[5:3]) 1630 // (0 запись в память ea) 1631 // * isize (0/1) 1632 // * wb (8/16) 1633 SETEA: case (estate) 1634 1635 0: begin 1636 1637 // Запись результата в регистр 1638 if (idir || (modrm[7:6] == 2'b11)) begin 1639 1640 case (idir ? modrm[5:3] : modrm[2:0]) 1641 1642 0: if (isize && opsize) eax <= wb; else if (isize) eax[15:0] <= wb; else eax[ 7:0] <= wb[7:0]; 1643 1: if (isize && opsize) ecx <= wb; else if (isize) ecx[15:0] <= wb; else ecx[ 7:0] <= wb[7:0]; 1644 2: if (isize && opsize) edx <= wb; else if (isize) edx[15:0] <= wb; else edx[ 7:0] <= wb[7:0]; 1645 3: if (isize && opsize) ebx <= wb; else if (isize) ebx[15:0] <= wb; else ebx[ 7:0] <= wb[7:0]; 1646 4: if (isize && opsize) esp <= wb; else if (isize) esp[15:0] <= wb; else eax[15:8] <= wb[7:0]; 1647 5: if (isize && opsize) ebp <= wb; else if (isize) ebp[15:0] <= wb; else ecx[15:8] <= wb[7:0]; 1648 6: if (isize && opsize) esi <= wb; else if (isize) esi[15:0] <= wb; else edx[15:8] <= wb[7:0]; 1649 7: if (isize && opsize) edi <= wb; else if (isize) edi[15:0] <= wb; else ebx[15:8] <= wb[7:0]; 1650 1651 endcase 1652 1653 mode <= MAIN; 1654 1655 end 1656 // Запись [7:0] в память 1657 else begin 1658 1659 estate <= 1; 1660 wreq <= 1; 1661 data <= wb[7:0]; 1662 1663 end 1664 1665 end 1666 1667 // Запись [15:8] или завершение 1668 1: begin 1669 1670 if (isize) 1671 begin estate <= 2; data <= wb[15:8]; ea <= ea + 1; end 1672 else begin estate <= 0; wreq <= 0; mode <= MAIN; end 1673 1674 end 1675 1676 // Завершение записи 16 bit 1677 2: begin 1678 1679 if (opsize) begin estate <= 3; data <= wb[23:16]; ea <= ea + 1; end 1680 else begin estate <= 0; wreq <= 0; mode <= MAIN; ea <= ea - 1; end 1681 1682 end 1683 1684 // Завершение записи 32 bit 1685 3: begin estate <= 4; data <= wb[31:24]; ea <= ea + 1; end 1686 4: begin estate <= 0; wreq <= 0; mode <= MAIN; ea <= ea - 3; end 1687 1688 endcase 1689 1690 // Получение imm8/16/32 [isize] 1691 IMMEDIATE: case (estate) 1692 1693 0: begin ip <= ip + 1; wb <= bus; if (isize == 0) mode <= MAIN; else begin estate <= 1; end end 1694 1: begin ip <= ip + 1; wb[ 15:8] <= bus; if (opsize) estate <= 2; else begin estate <= 0; mode <= MAIN; end end 1695 2: begin ip <= ip + 1; wb[23:16] <= bus; estate <= 3; end 1696 3: begin ip <= ip + 1; wb[31:24] <= bus; estate <= 0; mode <= MAIN; end 1697 1698 endcase 1699 1700 // Сохранение данных в стек [wb] 1701 // Если стек 32-х разрядный, используются 4 байта 1702 PUSH: case (estate) 1703 1704 0: begin 1705 1706 estate <= 1; 1707 sel <= 1; 1708 wreq <= 1; 1709 seg_ea <= seg_ss; 1710 data <= wb[7:0]; 1711 1712 if (stack32) begin 1713 ea <= esp - 4; 1714 esp <= esp - 4; 1715 end 1716 else begin 1717 ea <= esp[15:0] - (opsize ? 4 : 2); 1718 esp[15:0] <= esp[15:0] - (opsize ? 4 : 2); 1719 end 1720 1721 end 1722 1: begin estate <= 2; ea <= ea + 1; data <= wb[15:8]; end 1723 2: begin 1724 1725 if (opsize) begin ea <= ea + 1; data <= wb[23:16]; estate <= 3; end 1726 else begin 1727 1728 estate <= 0; 1729 sel <= 0; 1730 wreq <= 0; 1731 mode <= MAIN; 1732 1733 end 1734 1735 end 1736 3: begin estate <= 4; ea <= ea + 1; data <= wb[31:24]; end 1737 4: begin estate <= 0; sel <= 0; wreq <= 0; mode <= MAIN; end 1738 1739 endcase 1740 1741 // Извлечение данных из стека -> wb 1742 POP: case (estate) 1743 1744 0: begin 1745 1746 estate <= 1; 1747 sel <= 1; 1748 seg_ea <= seg_ss; 1749 1750 if (stack32) begin 1751 ea <= esp; 1752 esp <= esp - 4; 1753 end 1754 else begin 1755 ea <= esp[15:0]; 1756 esp[15:0] <= esp[15:0] + (opsize ? 4 : 2); 1757 end 1758 1759 end 1760 1: begin estate <= 2; wb <= bus; ea <= ea + 1; end 1761 2: begin 1762 1763 wb[15:8] <= bus; 1764 1765 if (opsize) begin estate <= 3; ea <= ea + 1; end 1766 else begin estate <= 0; sel <= 0; mode <= MAIN; end 1767 1768 end 1769 3: begin estate <= 4; wb[23:16] <= bus; ea <= ea + 1; end 1770 4: begin estate <= 0; wb[31:24] <= bus; sel <= 0; mode <= MAIN; end 1771 1772 endcase 1773 1774 // Загрузка и проверка нового сегментного регистра [regn, wb] 1775 LOADSEG: case (estate) 1776 1777 0: begin 1778 1779 // Если это было прерывание 1780 if (is_intr) begin mode <= PREPARE; end 1781 else mode <= MAIN; 1782 1783 case (regn) 1784 1785 3'b000: seg_es <= wb; 1786 3'b001: seg_cs <= wb; 1787 3'b010: seg_ss <= wb; 1788 3'b011: seg_ds <= wb; 1789 3'b100: seg_fs <= wb; 1790 3'b101: seg_gs <= wb; 1791 1792 endcase 1793 1794 end 1795 1796 endcase 1797 1798 // Вызов прерывания [wb] 1799 INTERRUPT: case (estate) 1800 1801 // Запись в стек CS:IP:FLAGS 1802 0: begin 1803 1804 estate <= 1; 1805 sel <= 1; 1806 wreq <= 1; 1807 seg_ea <= seg_ss; 1808 data <= ip[7:0]; 1809 1810 if (stack32) begin 1811 ea <= esp - 4*3; 1812 esp <= esp - 4*3; 1813 end 1814 else begin 1815 ea <= esp[15:0] - 2*3; 1816 esp[15:0] <= esp[15:0] - 2*3; 1817 end 1818 1819 end 1820 1: begin data <= ip[15:8]; estate <= stack32 ? 2 : 4; ea <= ea + 1; end 1821 // 2, 3 1822 4: begin data <= seg_cs[ 7:0]; estate <= 5; ea <= ea + 1; end 1823 5: begin data <= seg_cs[15:8]; estate <= stack32 ? 6 : 8; ea <= ea + 1; end 1824 // 6, 7 1825 8: begin data <= flags[7:0]; estate <= 9; ea <= ea + 1; end 1826 9: begin data <= flags[11:8]; estate <= stack32 ? 10 : 12; ea <= ea + 1; end 1827 // 10, 11 1828 12: begin estate <= 13; 1829 1830 wreq <= 0; 1831 flags[IF] <= 1'b0; 1832 flags[TF] <= 1'b0; 1833 seg_ea <= 0; 1834 ea <= {wb, 2'b00}; 1835 1836 end 1837 // Загрузка нового CS:IP из IVT 1838 13: begin estate <= 14; ip[7:0] <= bus; ea <= ea + 1; end 1839 14: begin estate <= 15; ip[15:8] <= bus; ea <= ea + 1; end 1840 15: begin estate <= 16; wb[7:0] <= bus; ea <= ea + 1; end 1841 16: begin estate <= 0; wb[15:8] <= bus; sel <= 0; regn <= 1; mode <= LOADSEG; end 1842 1843 // 32-х битный 1844 default: begin estate <= estate + 1; data <= 0; ea <= ea + 1; end 1845 1846 endcase 1847 1848 // Сдвиги: 1849 // * alumode=операция 1850 // * isize, opsize 1851 // * op1 1852 // * op2 1853 SHIFT: case (estate) 1854 1855 // Вычисление ограничения количества сдвигов 1856 // Если сдвиг не задан (0), то не срабатывает 1857 0: begin 1858 1859 estate <= 1; 1860 1861 if (isize && opsize) 1862 begin wb <= 31; op2 <= op2[4:0]; if (op2[4:0] == 0) begin estate <= 0; mode <= MAIN; end end 1863 else if (isize) 1864 // DosBox так обрабатывает (4:0) 1865 begin wb <= 15; op2 <= op2[4:0]; if (op2[4:0] == 0) begin estate <= 0; mode <= MAIN; end end 1866 else 1867 begin wb <= 7; op2 <= op2[2:0]; if (op2[2:0] == 0) begin estate <= 0; mode <= MAIN; end end 1868 1869 end 1870 1871 // Вычисление 1872 1: begin 1873 1874 // Сдвиги 1875 if (op2) begin 1876 1877 op2 <= op2 - 1; 1878 case (alumode) 1879 1880 /* ROL */ 0: 1881 begin op1 <= isize ? (opsize ? {op1[30:0],op1[31]} : {op1[14:0],op1[15]}) : {op1[6:0],op1[7]}; end 1882 1883 /* ROR */ 1: 1884 begin op1 <= isize ? (opsize ? {op1[0],op1[31:1]} : {op1[0],op1[15:1]}) : {op1[0],op1[7:1]}; end 1885 1886 /* RCL */ 2: 1887 begin 1888 1889 op1 <= isize ? (opsize ? {op1[30:0],flags[CF]} : {op1[14:0],flags[CF]}) : {op1[6:0],flags[CF]}; 1890 flags[CF] <= op1[wb]; 1891 1892 end 1893 1894 /* RCR */ 3: 1895 begin 1896 1897 op1 <= isize ? (opsize ? {flags[CF],op1[31:1]} : {flags[CF],op1[15:1]}) : {flags[CF],op1[7:1]}; 1898 flags[CF] <= op1[0]; 1899 1900 end 1901 1902 /* SHL */ 4, 6: 1903 begin 1904 1905 flags[CF] <= op1[wb-op2+1]; 1906 op1 <= op1 << op2; 1907 op2 <= 0; 1908 1909 end 1910 1911 /* SHR */ 5: 1912 begin 1913 1914 flags[CF] <= op1[op2-1]; 1915 op1 <= op1 >> op2; 1916 op2 <= 0; 1917 1918 end 1919 1920 /* SAR */ 7: 1921 begin 1922 op1 <= isize ? (opsize ? {op1[31],op1[31:1]} : {op1[15],op1[15:1]}) : {op1[7],op1[7:1]}; 1923 flags[CF] <= op1[0]; 1924 end 1925 1926 endcase 1927 1928 end 1929 // Расчет флагов 1930 else begin 1931 1932 estate <= 0; 1933 mode <= MAIN; 1934 1935 case (alumode) 1936 1937 0: begin flags[CF] <= op1[0]; flags[OF] <= op1[0] ^ op1[wb]; end 1938 1: begin flags[CF] <= op1[wb]; flags[OF] <= op1[wb] ^ op1[wb-1]; end 1939 2: begin flags[OF] <= flags[CF] ^ op1[wb]; end 1940 3: begin flags[OF] <= op1[wb] ^ op1[wb-1]; end 1941 default: begin 1942 1943 flags[ZF] <= !op1; 1944 flags[SF] <= op1[wb]; 1945 flags[PF] <= ~^op1[7:0]; 1946 flags[AF] <= 1; 1947 1948 end 1949 1950 endcase 1951 1952 end 1953 end 1954 1955 endcase 1956 1957 // Процедура деления [diva, divb, divcnt] 1958 DIVIDE: begin 1959 1960 if (divcnt) begin 1961 1962 divrem <= {divrem,diva[63]} >= divb ? {divrem,diva[63]} - divb : {divrem,diva[63]}; 1963 divres <= {divres[62:0], {divrem,diva[63]} >= divb}; 1964 diva <= {diva[62:0], 1'b0}; 1965 divcnt <= divcnt - 1; 1966 1967 end 1968 else mode <= MAIN; 1969 1970 end 1971 1972endcase 1973 1974// --------------------------------------------------------------------- 1975// АРИФМЕТИКО-ЛОГИКА 1976// --------------------------------------------------------------------- 1977 1978wire [31:0] result = isize ? (opsize ? res[31:0] : res[15:0]) : res[7:0]; 1979reg [15:0] daa_r; 1980reg [11:0] flags_o; 1981reg [11:0] flags_d; 1982reg [32:0] res; 1983 1984// Десятичная коррекция 1985reg daa_a; 1986reg daa_c; 1987reg daa_x; 1988reg [8:0] daa_i; 1989reg [7:0] daa_h; 1990 1991// Верхний бит 7, 15 или 31 1992wire [3:0] signx = isize ? (opsize ? 31 : 15) : 7; 1993 1994wire parity = ~^res[7:0]; 1995wire zerof = isize ? (opsize ? ~|res : ~|res[15:0]) : ~|res[7:0]; 1996wire carryf = res[signx + 1]; 1997wire signf = res[signx]; 1998wire auxf = op1[4]^op2[4]^res[4]; 1999 2000// Самая хитрая логика из всего тут 2001wire add_o = (op1[isize] ^ op2[isize] ^ 1) & (op1[isize] ^ res[isize]); 2002wire sub_o = (op1[isize] ^ op2[isize] ^ 0) & (op1[isize] ^ res[isize]); 2003 2004// Общие АЛУ 2005always @* begin 2006 2007 case (alumode) 2008 2009 /* ADD */ 0: res = op1 + op2; 2010 /* OR */ 1: res = op1 | op2; 2011 /* ADC */ 2: res = op1 + op2 + flags[0]; 2012 /* SBB */ 3: res = op1 - op2 - flags[0]; 2013 /* AND */ 4: res = op1 & op2; 2014 /* SUB */ 5, 2015 /* CMP */ 7: res = op1 - op2; 2016 /* XOR */ 6: res = op1 ^ op2; 2017 2018 endcase 2019 2020 case (alumode) 2021 2022 // ADD | ADC 2023 0, 2: flags_o = { 2024 2025 /* O */ add_o, 2026 /* D */ flags[10], 2027 /* I */ flags[9], 2028 /* T */ flags[8], 2029 /* S */ signf, 2030 /* Z */ zerof, 2031 /* 0 */ 1'b0, 2032 /* A */ auxf, 2033 /* 0 */ 1'b0, 2034 /* P */ parity, 2035 /* 1 */ 1'b1, 2036 /* C */ carryf 2037 }; 2038 2039 // SBB | SUB | CMP 2040 3, 5, 7: flags_o = { 2041 2042 /* O */ sub_o, 2043 /* D */ flags[10], 2044 /* I */ flags[9], 2045 /* T */ flags[8], 2046 /* S */ signf, 2047 /* Z */ zerof, 2048 /* 0 */ 1'b0, 2049 /* A */ auxf, 2050 /* 0 */ 1'b0, 2051 /* P */ parity, 2052 /* 1 */ 1'b1, 2053 /* C */ carryf 2054 }; 2055 2056 // OR, AND, XOR одинаковые флаги 2057 1, 4, 6: flags_o = { 2058 2059 /* O */ 1'b0, 2060 /* D */ flags[10], 2061 /* I */ flags[9], 2062 /* T */ flags[8], 2063 /* S */ signf, 2064 /* Z */ zerof, 2065 /* 0 */ 1'b0, 2066 /* A */ 1'b0, 2067 /* 0 */ 1'b0, 2068 /* P */ parity, 2069 /* 1 */ 1'b1, 2070 /* C */ 1'b0 2071 }; 2072 2073 endcase 2074 2075end 2076 2077// Десятичная коррекция 2078always @* begin 2079 2080 daa_r = op1[7:0]; 2081 flags_d = flags; 2082 2083 case (alumode) 2084 2085 // DAA, DAS 2086 0, 1: begin 2087 2088 daa_c = flags[0]; 2089 daa_a = flags[4]; 2090 daa_i = op1[7:0]; 2091 2092 // Младший ниббл 2093 if (op1[3:0] > 9 || flags[4]) begin 2094 daa_i = alumode[0] ? op1[7:0]-6 : op1[7:0]+6; 2095 daa_c = daa_i[8]; 2096 daa_a = 1; 2097 end 2098 2099 daa_r = daa_i[7:0]; 2100 daa_x = daa_c; 2101 2102 // Старший ниббл 2103 if (daa_c || daa_i[7:0] > 8'h9F) begin 2104 daa_r = alumode[0] ? daa_i[7:0]-8'h60 : daa_i[7:0]+8'h60; 2105 daa_x = 1; 2106 end 2107 2108 flags_d[7] = daa_r[7]; // S 2109 flags_d[6] = ~|daa_r[7:0]; // Z 2110 flags_d[4] = daa_a; // A 2111 flags_d[2] = ~^daa_r[7:0]; // P 2112 flags_d[0] = daa_x; // C 2113 2114 end 2115 2116 // AAA, AAS 2117 2, 3: begin 2118 2119 daa_i = op1[ 7:0]; 2120 daa_r = op1[15:0]; 2121 2122 if (flags[4] || op1[3:0] > 9) begin 2123 2124 daa_i = alumode[0] ? op1[ 7:0] - 6 : op1[ 7:0] + 6; 2125 daa_h = alumode[0] ? op1[15:8] - 1 : op1[15:8] + 1; 2126 daa_r = {daa_h, 4'h0, daa_i[3:0]}; 2127 2128 flags_d[4] = 1; // AF=1 2129 flags_d[0] = 1; // CF=1 2130 2131 end 2132 else begin flags_d[4] = 0; flags_d[0] = 0; end 2133 2134 end 2135 2136 endcase 2137 2138end 2139 2140endmodule