cpu.c (19069B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "interconnect.h" 5 #include "cpu.h" 6 #include "types.h" 7 #include "util.h" 8 #include "log.h" 9 10 CPU* 11 new_cpu(Interconnect* inter) { 12 CPU* cpu = (CPU*)malloc(sizeof(CPU)); 13 14 cpu->pc = 0xBFC00000; 15 cpu->next_pc = cpu->pc + 4; 16 cpu->current_pc = 0; 17 cpu->cause = 0x0; cpu->epc = 0x0; cpu->sr = 0x0; 18 cpu->hi = 0xdeaddead; 19 cpu->lo = 0xdeaddead; 20 cpu->branch = 0; 21 cpu->delay_slot = 0; 22 cpu->inter = inter; 23 cpu->load._0 = 0; cpu->load._1 = 0; 24 cpu->next_instruction = new_instr(0); /* NOP */ 25 memset(cpu->regs, 0, sizeof(cpu->regs)); 26 memset(cpu->out_regs, 0, sizeof(cpu->out_regs)); 27 return cpu; 28 } 29 30 u32 CPU_load32(CPU* cpu, u32 addr) { return INTER_load32(cpu->inter, addr); } 31 u16 CPU_load16(CPU* cpu, u32 addr) { return INTER_load16(cpu->inter, addr); } 32 u8 CPU_load8(CPU* cpu, u32 addr) { return INTER_load8(cpu->inter, addr); } 33 34 void CPU_store32(CPU* cpu, u32 addr, u32 val) { INTER_store32(cpu->inter, addr, val); } 35 void CPU_store16(CPU* cpu, u32 addr, u16 val) { INTER_store16(cpu->inter, addr, val); } 36 void CPU_store8(CPU* cpu, u32 addr, u8 val) { INTER_store8(cpu->inter, addr, val); } 37 void set_reg(CPU* cpu, u32 reg, u32 val) { cpu->out_regs[reg] = val; cpu->out_regs[0] = 0; } 38 u32 reg(CPU* cpu, u32 reg) { return cpu->out_regs[reg]; } 39 40 void 41 exception(CPU* cpu, EXCEPTION cause) 42 { 43 u32 handler, mode; 44 45 handler = ((cpu->sr & (1 << 22)) != 0) ? 0xBFC00180 : 0x80000080; 46 mode = cpu->sr & 0x3f; 47 cpu->sr &= ~0x3f; 48 cpu->sr |= (mode << 2) & 0x3f; 49 cpu->cause = (u32)cause << 2; 50 cpu->epc = cpu->current_pc; 51 52 if (cpu->delay_slot) 53 { 54 cpu->epc -= 4; 55 cpu->cause |= 1 << 31; 56 } 57 58 cpu->pc = handler; 59 cpu->next_pc = cpu->pc + 4; 60 61 return; 62 } 63 64 65 void 66 op_lui(CPU* cpu, instruction* i) 67 { 68 u32 v = i->imm << 16; 69 set_reg(cpu, i->t, v); 70 } 71 72 void 73 op_or(CPU* cpu, instruction* i) 74 { 75 u32 v; 76 v = reg(cpu, i->s) | reg(cpu, i->t); 77 set_reg(cpu, i->d, v); 78 } 79 80 void 81 op_xor(CPU* cpu, instruction* i) 82 { 83 u32 v; 84 v = reg(cpu, i->s) ^ reg(cpu, i->t); 85 set_reg(cpu, i->d, v); 86 } 87 88 void 89 op_nor(CPU* cpu, instruction* i) 90 { 91 u32 v; 92 v = !(reg(cpu, i->s) | reg(cpu, i->t)); 93 set_reg(cpu, i->d, v); 94 } 95 96 void 97 op_and(CPU* cpu, instruction* i) 98 { 99 u32 v; 100 v = reg(cpu, i->s) & reg(cpu, i->t); 101 set_reg(cpu, i->d, v); 102 } 103 104 void 105 op_ori(CPU* cpu, instruction* i) 106 { 107 u32 v; 108 v = reg(cpu, i->s) | i->imm; 109 set_reg(cpu, i->t, v); 110 } 111 112 void 113 op_xori(CPU* cpu, instruction* i) 114 { 115 u32 v; 116 v = reg(cpu, i->s) ^ i->imm; 117 set_reg(cpu, i->t, v); 118 } 119 120 void 121 op_sw(CPU* cpu, instruction* i) 122 { 123 u32 imm_se, t, s, addr, v; 124 125 if ((cpu->sr & 0x10000) != 0) 126 { 127 log_debug("ignoring store while cache is isolated!"); 128 return; 129 } 130 131 imm_se = i->imm_se; 132 t = i->t; 133 s = i->s; 134 135 addr = reg(cpu, s) + imm_se; 136 v = reg(cpu, t); 137 if ((addr % 4) == 0) 138 { 139 CPU_store32(cpu, addr, v); 140 } 141 else 142 { 143 exception(cpu, E_STORE_ADRESS_ERROR); 144 } 145 } 146 147 void 148 op_swl(CPU* cpu, instruction* i) 149 { 150 u32 addr, v, aligned_addr, cur_mem, mem; 151 152 addr = reg(cpu, i->s) + i->imm_se; 153 v = reg(cpu, i->t); 154 aligned_addr = addr & ~3; 155 cur_mem = CPU_load32(cpu, aligned_addr); 156 157 switch(addr & 3) 158 { 159 case 0: mem = (cur_mem & 0xffffff00) | (v >> 24); break; 160 case 1: mem = (cur_mem & 0xffff0000) | (v >> 16); break; 161 case 2: mem = (cur_mem & 0xff000000) | (v >> 8); break; 162 case 3: mem = (cur_mem & 0x00000000) | (v >> 0); break; 163 default: log_fatal("* STORE WORD LEFT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE); 164 } 165 166 CPU_store32(cpu, addr, mem); 167 } 168 169 void 170 op_swr(CPU* cpu, instruction* i) 171 { 172 u32 addr, v, aligned_addr, cur_mem, mem; 173 174 addr = reg(cpu, i->s) + i->imm_se; 175 v = reg(cpu, i->t); 176 aligned_addr = addr & ~3; 177 cur_mem = CPU_load32(cpu, aligned_addr); 178 179 switch(addr & 3) 180 { 181 case 0: mem = (cur_mem & 0x00000000) | (v << 0); break; 182 case 1: mem = (cur_mem & 0x000000ff) | (v << 8); break; 183 case 2: mem = (cur_mem & 0x0000ffff) | (v << 16); break; 184 case 3: mem = (cur_mem & 0x00ffffff) | (v << 24); break; 185 default: log_fatal("* STORE WORD RIGHT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE); 186 } 187 188 CPU_store32(cpu, addr, mem); 189 } 190 191 void 192 op_sh(CPU* cpu, instruction* i) 193 { 194 u32 imm_se, t, s, addr, v; 195 196 if ((cpu->sr & 0x10000) != 0) 197 { 198 log_info("ignoring store while cache is isolated!"); 199 return; 200 } 201 202 imm_se = i->imm_se; 203 t = i->t; 204 s = i->s; 205 206 addr = reg(cpu, s) + imm_se; 207 v = reg(cpu, t); 208 209 if ((addr % 2) == 0) 210 { 211 CPU_store16(cpu, addr, (u16)v); 212 } 213 else 214 { 215 exception(cpu, E_STORE_ADRESS_ERROR); 216 } 217 } 218 219 void 220 op_sb(CPU* cpu, instruction* i) 221 { 222 u32 imm_se, t, s, addr, v; 223 224 if ((cpu->sr & 0x10000) != 0) 225 { 226 log_info("ignoring store while cache is isolated!"); 227 return; 228 } 229 230 imm_se = i->imm_se; 231 t = i->t; 232 s = i->s; 233 234 addr = reg(cpu, s) + imm_se; 235 v = reg(cpu, t); 236 CPU_store8(cpu, addr, (u8)v); 237 } 238 239 void 240 op_sll(CPU* cpu, instruction* i) 241 { 242 u32 shift, t, d, v; 243 244 shift = i->shift; 245 t = i->t; 246 d = i->d; 247 248 v = reg(cpu, t) << shift; 249 set_reg(cpu, d, v); 250 251 } 252 253 void 254 op_srlv(CPU* cpu, instruction* i) 255 { 256 u32 v; 257 258 v = reg(cpu, i->t) >> (reg(cpu, i->s) & 0x1f); 259 set_reg(cpu, i->d, v); 260 } 261 262 void 263 op_sllv(CPU* cpu, instruction* i) 264 { 265 u32 v; 266 267 v = reg(cpu, i->t) << (reg(cpu, i->s) & 0x1f); 268 set_reg(cpu, i->d, v); 269 } 270 271 void 272 op_addiu(CPU* cpu, instruction* i) 273 { 274 u32 v; 275 v = reg(cpu, i->s) + i->imm_se; 276 set_reg(cpu, i->t, v); 277 } 278 279 void 280 op_addi(CPU* cpu, instruction* i) 281 { 282 i32 v; 283 i32 imm_se; 284 i32 res; 285 286 imm_se = (i32)i->imm_se; 287 v = (i32)reg(cpu, i->s); 288 289 if(checked_addi32(v, imm_se, &res)) 290 set_reg(cpu, i->t, res); 291 else 292 exception(cpu, E_OVERFLOW); 293 } 294 295 void 296 op_j(CPU* cpu, instruction* i) 297 { 298 cpu->next_pc = (cpu->next_pc & 0xf0000000) | (i->imm_jump << 2); 299 cpu->branch = 1; 300 } 301 302 void 303 op_jal(CPU* cpu, instruction* i) 304 { 305 set_reg(cpu, 31, cpu->next_pc); 306 op_j(cpu, i); 307 } 308 309 void 310 op_jr(CPU* cpu, instruction* i) 311 { 312 cpu->next_pc = reg(cpu, i->s); 313 cpu->branch = 1; 314 } 315 316 void op_jalr(CPU* cpu, instruction* i) 317 { 318 set_reg(cpu, i->d, cpu->next_pc); 319 cpu->next_pc = reg(cpu, i->s); 320 cpu->branch = 1; 321 } 322 323 void 324 op_mtc0(CPU* cpu, instruction* i) 325 { 326 u32 cop_r, v; 327 328 cop_r = i->d; 329 v = reg(cpu, i->t); 330 331 switch(cop_r) { 332 case 3: case 5: case 6: case 7: case 9: case 11: 333 if (v != 0) 334 { 335 log_fatal("Unhandled cop0r%d", cop_r); 336 exit(EXIT_FAILURE); 337 } 338 break; 339 case 12: 340 cpu->sr = v; 341 break; 342 case 13: 343 if (v != 0) 344 { 345 log_fatal("Unhandled write to CAUSE register"); 346 exit(EXIT_FAILURE); 347 } 348 break; 349 default: 350 log_fatal("Unhandled cop0 register %d", cop_r); 351 exit(EXIT_FAILURE); 352 } 353 } 354 355 void 356 op_mfc0(CPU* cpu, instruction* i) 357 { 358 u32 cop_r; 359 360 cop_r = i->d; 361 362 switch(cop_r) { 363 case 12: 364 cpu->load._0 = i->t; 365 cpu->load._1 = cpu->sr; 366 break; 367 case 13: 368 cpu->load._0 = i->t; 369 cpu->load._1 = cpu->cause; 370 break; 371 case 14: 372 cpu->load._0 = i->t; 373 cpu->load._1 = cpu->epc; 374 break; 375 default: 376 log_fatal("Unhandled read from cop0r%d", cop_r); 377 exit(EXIT_FAILURE); 378 } 379 } 380 381 void 382 op_rfe(CPU* cpu, instruction* i) 383 { 384 u32 mode; 385 386 if ((i->_0 & 0x3f) != 0x10) 387 { 388 log_fatal("Invalid cop0 instruction %08X", i->_0); 389 exit(EXIT_FAILURE); 390 } 391 392 mode = cpu->sr & 0x3f; 393 cpu->sr &= ~0x3f; 394 cpu->sr |= mode >> 2; 395 } 396 397 void 398 op_cop0(CPU* cpu, instruction* i) 399 { 400 switch (i->cop_opcode) { 401 case 0x00: op_mfc0(cpu, i); break; 402 case 0x04: op_mtc0(cpu, i); break; 403 case 0x10: op_rfe(cpu, i); break; 404 default: log_fatal("Unhandled cop0 instruction %08X", i->_0); exit(EXIT_FAILURE); 405 } 406 } 407 408 void 409 op_cop1(CPU* cpu, instruction* i) 410 { 411 (void)i; 412 exception(cpu, E_COPROCESSOR_ERROR); 413 } 414 415 /* GTE */ 416 void 417 op_cop2(CPU* cpu, instruction* i) 418 { 419 (void)i;(void)cpu; 420 log_fatal("Unhandle GTE Instruction: %08X", i->_0); 421 exit(EXIT_FAILURE); 422 /* exception(cpu, E_COPROCESSOR_ERROR); */ 423 } 424 425 void 426 op_cop3(CPU* cpu, instruction* i) 427 { 428 (void)i; 429 exception(cpu, E_COPROCESSOR_ERROR); 430 } 431 432 void 433 branch(CPU* cpu, u32 offset) 434 { 435 cpu->next_pc += (offset << 2) - 4; 436 cpu->branch = 1; 437 } 438 439 void 440 op_bne(CPU* cpu, instruction* i) 441 { 442 if (reg(cpu, i->s) != reg(cpu, i->t)) branch(cpu, i->imm_se); 443 } 444 445 void 446 op_beq(CPU* cpu, instruction* i) 447 { 448 if (reg(cpu, i->s) == reg(cpu, i->t)) branch(cpu, i->imm_se); 449 } 450 451 void 452 op_bgtz(CPU* cpu, instruction* i) 453 { 454 i32 v; 455 456 v = (i32)reg(cpu, i->s); 457 458 if (v > 0) 459 branch(cpu, i->imm_se); 460 } 461 462 void 463 op_blez(CPU* cpu, instruction* i) 464 { 465 i32 v; 466 467 v = (i32)reg(cpu, i->s); 468 469 if (v <= 0) 470 branch(cpu, i->imm_se); 471 } 472 473 void 474 op_bxx(CPU* cpu, instruction* i) 475 { 476 u8 is_bgez, is_link; 477 u32 test; 478 i32 v; 479 480 is_bgez = (i->_0 >> 16) & 1; 481 is_link = ((i->_0 >> 20) & 1) != 0; 482 483 v = (i32)reg(cpu, i->s); 484 485 test = v < 0; 486 487 test = test ^ is_bgez; 488 489 if (test != 0) 490 { 491 if (is_link) 492 set_reg(cpu, 31, cpu->pc); 493 494 branch(cpu, i->imm_se); 495 } 496 } 497 498 void 499 op_lw(CPU* cpu, instruction* i) 500 { 501 u32 v, addr; 502 503 addr = reg(cpu, i->s) + i->imm_se; 504 505 if ((addr % 4) == 0) 506 { 507 v = CPU_load32(cpu, addr); 508 509 cpu->load._0 = i->t; 510 cpu->load._1 = v; 511 } 512 else 513 { 514 exception(cpu, E_STORE_ADRESS_ERROR); 515 } 516 } 517 518 void 519 op_lwl(CPU* cpu, instruction* i) 520 { 521 u32 v, addr, cur_v, aligned_addr, aligned_word; 522 523 addr = reg(cpu, i->s) + i->imm_se; 524 525 cur_v = cpu->out_regs[i->t]; 526 527 aligned_addr = addr & ~3; 528 aligned_word = CPU_load32(cpu, aligned_addr); 529 530 switch(addr & 3) 531 { 532 case 0: v = (cur_v & 0x00ffffff) | (aligned_word << 24); break; 533 case 1: v = (cur_v & 0x0000ffff) | (aligned_word << 16); break; 534 case 2: v = (cur_v & 0x000000ff) | (aligned_word << 8); break; 535 case 3: v = (cur_v & 0x00000000) | (aligned_word << 0); break; 536 default: log_fatal("* LOAD WORD LEFT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE); 537 } 538 539 cpu->load._0 = i->t; 540 cpu->load._1 = v; 541 } 542 543 void 544 op_lwr(CPU* cpu, instruction* i) 545 { 546 u32 v, addr, cur_v, aligned_addr, aligned_word; 547 548 addr = reg(cpu, i->s) + i->imm_se; 549 550 cur_v = cpu->out_regs[i->t]; 551 552 aligned_addr = addr & ~3; 553 aligned_word = CPU_load32(cpu, aligned_addr); 554 555 switch(addr & 3) 556 { 557 case 0: v = (cur_v & 0x00000000) | (aligned_word >> 0); break; 558 case 1: v = (cur_v & 0xff000000) | (aligned_word >> 8); break; 559 case 2: v = (cur_v & 0xffff0000) | (aligned_word >> 16); break; 560 case 3: v = (cur_v & 0xffffff00) | (aligned_word >> 24); break; 561 default: log_fatal("* LOAD WORD RIGHT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE); 562 } 563 564 cpu->load._0 = i->t; 565 cpu->load._1 = v; 566 } 567 568 void 569 op_lb(CPU* cpu, instruction* i) 570 { 571 i8 v; 572 u32 addr; 573 574 addr = reg(cpu, i->s) + i->imm_se; 575 v = (i8)CPU_load8(cpu, addr); 576 577 cpu->load._0 = i->t; 578 cpu->load._1 = (u32)v; 579 } 580 581 void 582 op_lbu(CPU* cpu, instruction* i) 583 { 584 u32 v, addr; 585 586 addr = reg(cpu, i->s) + i->imm_se; 587 v = CPU_load8(cpu, addr); 588 589 cpu->load._0 = i->t; 590 cpu->load._1 = (u32)v; 591 } 592 593 void 594 op_lh(CPU* cpu, instruction* i) 595 { 596 u32 addr; 597 i16 v; 598 599 addr = reg(cpu, i->s) + i->imm_se; 600 601 if (addr % 2 == 0) 602 { 603 v = (i16)CPU_load16(cpu, addr); 604 605 cpu->load._0 = i->t; 606 cpu->load._1 = (u32)v; 607 } 608 else 609 { 610 exception(cpu, E_LOAD_ADRESS_ERROR); 611 } 612 } 613 614 void 615 op_lhu(CPU* cpu, instruction* i) 616 { 617 u32 v, addr; 618 619 addr = reg(cpu, i->s) + i->imm_se; 620 621 if (addr % 2 == 0) 622 { 623 v = CPU_load16(cpu, addr); 624 625 cpu->load._0 = i->t; 626 cpu->load._1 = (u32)v; 627 } 628 else 629 { 630 exception(cpu, E_LOAD_ADRESS_ERROR); 631 } 632 } 633 634 void 635 op_slt(CPU* cpu, instruction* i) 636 { 637 u32 v; 638 639 v = (i32)reg(cpu, i->s) < (i32)reg(cpu, i->t); 640 set_reg(cpu, i->d, (u32)v); 641 } 642 643 void 644 op_sltu(CPU* cpu, instruction* i) 645 { 646 u32 v; 647 648 v = reg(cpu, i->s) < reg(cpu, i->t); 649 set_reg(cpu, i->d, v); 650 } 651 652 void 653 op_slti(CPU* cpu, instruction* i) 654 { 655 u32 v; 656 v = (i32)reg(cpu, i->s) < (i32)i->imm_se; 657 set_reg(cpu, i->t, v); 658 } 659 660 void 661 op_sltiu(CPU* cpu, instruction* i) 662 { 663 u32 v; 664 v = reg(cpu, i->s) < i->imm_se; 665 set_reg(cpu, i->t, v); 666 } 667 668 void 669 op_add(CPU* cpu, instruction* i) 670 { 671 i32 s, t; 672 i32 res; 673 674 s = (i32)reg(cpu, i->s); 675 t = (i32)reg(cpu, i->t); 676 677 if(checked_addi32(s, t, &res)) 678 set_reg(cpu, i->d, (u32)res); 679 else 680 exception(cpu, E_OVERFLOW); 681 } 682 683 void 684 op_addu(CPU* cpu, instruction* i) 685 { 686 u32 v; 687 688 v = reg(cpu, i->t) + reg(cpu, i->s); 689 set_reg(cpu, i->d, v); 690 691 } 692 693 void 694 op_sub(CPU* cpu, instruction* i) 695 { 696 i32 s, t; 697 i32 res; 698 699 s = (i32)reg(cpu, i->s); 700 t = (i32)reg(cpu, i->t); 701 702 if(checked_subi32(s, t, &res)) 703 set_reg(cpu, i->d, (u32)res); 704 else 705 exception(cpu, E_OVERFLOW); 706 707 } 708 709 void 710 op_subu(CPU* cpu, instruction* i) 711 { 712 u32 v; 713 714 v = reg(cpu, i->s) - reg(cpu, i->t); 715 set_reg(cpu, i->d, v); 716 717 } 718 719 void 720 op_andi(CPU* cpu, instruction *i) 721 { 722 u32 v; 723 v = reg(cpu, i->s) & i->imm; 724 set_reg(cpu, i->t, v); 725 } 726 727 void 728 op_sra(CPU* cpu, instruction* i) 729 { 730 i32 v; 731 v = (i32)reg(cpu, i->t) >> i->shift; 732 set_reg(cpu, i->d, (u32)v); 733 } 734 735 void 736 op_srav(CPU* cpu, instruction* i) 737 { 738 i32 v; 739 740 v = (i32)reg(cpu, i->t) >> (reg(cpu, i->s) & 0x1f); 741 set_reg(cpu, i->d, (u32)v); 742 } 743 744 void 745 op_srl(CPU* cpu, instruction* i) 746 { 747 u32 v; 748 v = reg(cpu, i->t) >> i->shift; 749 set_reg(cpu, i->d, v); 750 } 751 752 void 753 op_div(CPU* cpu, instruction* i) 754 { 755 i32 n, d; 756 757 n = (i32)reg(cpu, i->s); 758 d = (i32)reg(cpu, i->t); 759 760 if (d == 0) 761 { 762 cpu->hi = (u32)n; 763 if (n >= 0) 764 cpu->lo = 0xffffffff; 765 else 766 cpu->lo = 1; 767 } 768 else if ((u32)n == 0x80000000 && d == -1) 769 { 770 cpu->hi = 0; 771 cpu->lo = 0x80000000; 772 } 773 else 774 { 775 cpu->hi = (u32)(n % d); 776 cpu->lo = (u32)(n / d); 777 } 778 } 779 780 void 781 op_divu(CPU* cpu, instruction* i) 782 { 783 u32 n, d; 784 785 n = reg(cpu, i->s); 786 d = reg(cpu, i->t); 787 788 if (d == 0) 789 { 790 cpu->hi = (u32)n; 791 cpu->lo = 0xffffffff; 792 } 793 else 794 { 795 cpu->hi = (n % d); 796 cpu->lo = (n / d); 797 } 798 } 799 800 void 801 op_mult(CPU* cpu, instruction* i) 802 { 803 i64 a, b; 804 u64 v; 805 806 a = (i64)((i32)reg(cpu, i->s)); 807 b = (i64)((i32)reg(cpu, i->t)); 808 809 v = (u64)(a * b); 810 811 cpu->hi = (u32)(v >> 32); 812 cpu->lo = (u32)v; 813 } 814 815 void 816 op_multu(CPU* cpu, instruction* i) 817 { 818 u64 a, b, v; 819 820 a = (u64)reg(cpu, i->s); 821 b = (u64)reg(cpu, i->t); 822 823 v = a * b; 824 825 cpu->hi = (u32)(v >> 32); 826 cpu->lo = (u32)v; 827 } 828 829 830 void 831 op_mflo(CPU* cpu, instruction* i) 832 { 833 set_reg(cpu, i->d, cpu->lo); 834 } 835 836 void 837 op_mtlo(CPU* cpu, instruction* i) 838 { 839 cpu->lo = reg(cpu, i->s); 840 } 841 842 void 843 op_mfhi(CPU* cpu, instruction* i) 844 { 845 set_reg(cpu, i->d, cpu->hi); 846 } 847 848 void 849 op_mthi(CPU* cpu, instruction* i) 850 { 851 cpu->hi = reg(cpu, i->s); 852 } 853 854 void op_syscall(CPU* cpu, instruction* i) 855 { 856 (void)i; 857 exception(cpu, E_SYSCALL); 858 } 859 860 void 861 op_break(CPU* cpu, instruction* i) 862 { 863 (void)i; 864 exception(cpu, E_BREAK); 865 } 866 867 void op_lwc0(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); } 868 void op_lwc1(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); } 869 void op_lwc2(CPU* cpu, instruction* i) { (void)i; (void)cpu; log_fatal("Unhandled GTE LWC: %08X", i->_0); exit(EXIT_FAILURE); } 870 void op_lwc3(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); } 871 872 void op_swc0(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); } 873 void op_swc1(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); } 874 void op_swc2(CPU* cpu, instruction* i) { (void)i; (void)cpu; log_fatal("Unhandled GTE SWC: %08X", i->_0); exit(EXIT_FAILURE); } 875 void op_swc3(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); } 876 877 void 878 op_illegal(CPU* cpu, instruction* i) 879 { 880 (void)i; 881 log_warn("Illegal instruction %08X", i->_0); 882 exception(cpu, E_ILLEGAL_INSTRUCTION); 883 } 884 885 886 void 887 CPU_decode_and_execute(CPU* cpu, instruction* i) 888 { 889 890 switch(i->fn) { 891 case 0x0: 892 switch(i->sub) { 893 case 0x0: op_sll(cpu, i); break; 894 case 0x02: op_srl(cpu, i); break; 895 case 0x03: op_sra(cpu, i); break; 896 case 0x0d: op_break(cpu, i); break; 897 case 0x07: op_srav(cpu, i); break; 898 case 0x04: op_sllv(cpu, i); break; 899 case 0x06: op_srlv(cpu, i); break; 900 case 0x08: op_jr(cpu, i); break; 901 case 0x09: op_jalr(cpu, i); break; 902 case 0x24: op_and(cpu, i); break; 903 case 0x25: op_or(cpu, i); break; 904 case 0x26: op_xor(cpu, i); break; 905 case 0x27: op_nor(cpu, i); break; 906 case 0x2a: op_slt(cpu, i); break; 907 case 0x2B: op_sltu(cpu, i); break; 908 case 0x20: op_add(cpu, i); break; 909 case 0x21: op_addu(cpu, i); break; 910 case 0x22: op_sub(cpu, i); break; 911 case 0x23: op_subu(cpu, i); break; 912 case 0x1a: op_div(cpu, i); break; 913 case 0x1b: op_divu(cpu, i); break; 914 case 0x10: op_mfhi(cpu, i); break; 915 case 0x11: op_mthi(cpu, i); break; 916 case 0x12: op_mflo(cpu, i); break; 917 case 0x13: op_mtlo(cpu, i); break; 918 case 0x18: op_mult(cpu, i); break; 919 case 0x19: op_multu(cpu, i); break; 920 case 0x0C: op_syscall(cpu, i); break; 921 default: op_illegal(cpu, i); break; 922 } 923 break; 924 case 0x01: op_bxx(cpu, i); break; 925 case 0x02: op_j(cpu, i); break; 926 case 0x03: op_jal(cpu, i); break; 927 case 0x04: op_beq(cpu, i); break; 928 case 0x05: op_bne(cpu, i); break; 929 case 0x06: op_blez(cpu, i); break; 930 case 0x07: op_bgtz(cpu, i); break; 931 case 0x08: op_addi(cpu, i); break; 932 case 0x09: op_addiu(cpu, i); break; 933 case 0x0a: op_slti(cpu, i); break; 934 case 0x0b: op_sltiu(cpu, i); break; 935 case 0x0c: op_andi(cpu, i); break; 936 case 0x0d: op_ori(cpu, i); break; 937 case 0x0e: op_xori(cpu, i); break; 938 case 0x0f: op_lui(cpu, i); break; 939 case 0x10: op_cop0(cpu, i); break; 940 case 0x11: op_cop1(cpu, i); break; 941 case 0x12: op_cop2(cpu, i); break; 942 case 0x13: op_cop3(cpu, i); break; 943 case 0x20: op_lb(cpu, i); break; 944 case 0x21: op_lh(cpu, i); break; 945 case 0x22: op_lwl(cpu, i); break; 946 case 0x23: op_lw(cpu, i); break; 947 case 0x24: op_lbu(cpu, i); break; 948 case 0x25: op_lhu(cpu, i); break; 949 case 0x26: op_lwr(cpu, i); break; 950 case 0x2a: op_swl(cpu, i); break; 951 case 0x2e: op_swr(cpu, i); break; 952 case 0x2b: op_sw(cpu, i); break; 953 case 0x28: op_sb(cpu, i); break; 954 case 0x29: op_sh(cpu, i); break; 955 case 0x30: op_lwc0(cpu, i); break; 956 case 0x31: op_lwc1(cpu, i); break; 957 case 0x32: op_lwc2(cpu, i); break; 958 case 0x33: op_lwc3(cpu, i); break; 959 case 0x38: op_swc0(cpu, i); break; 960 case 0x39: op_swc1(cpu, i); break; 961 case 0x3a: op_swc2(cpu, i); break; 962 case 0x3b: op_swc3(cpu, i); break; 963 default: op_illegal(cpu, i); break; 964 } 965 966 } 967 968 void 969 CPU_run_next_instruction(CPU* cpu) 970 { 971 instruction i = new_instr(CPU_load32(cpu, cpu->pc)); 972 973 cpu->delay_slot = cpu->branch; 974 cpu->branch = 0; 975 976 cpu->current_pc = cpu->pc; 977 978 if ((cpu->current_pc % 4) != 0) 979 { 980 exception(cpu, E_LOAD_ADRESS_ERROR); 981 return; 982 } 983 if (cpu->pc == 0x80058498) { 984 //puts("Hey"); 985 //printf("cpu->pc: %08x\n", cpu->pc); 986 //printf("Target: %08x\n", i.t); 987 //printf("IMM: %08x\n", i.imm); 988 //printf("FN: %08x\n", i.fn); 989 //exit(1); 990 } 991 992 cpu->pc = cpu->next_pc; 993 cpu->next_pc = cpu->next_pc + 4; 994 995 set_reg(cpu, cpu->load._0, cpu->load._1); 996 997 cpu->load._0 = 0; 998 cpu->load._1 = 0; 999 1000 CPU_decode_and_execute(cpu, &i); 1001 1002 memcpy(cpu->regs, cpu->out_regs, sizeof(u32) * 32); 1003 } 1004 1005 instruction 1006 new_instr(u32 i) 1007 { 1008 instruction ins; 1009 ins._0 = i; 1010 ins.fn = i >> 26; 1011 ins.sub = i & 0x3f; 1012 ins.s = (i >> 21) & 0x1f; 1013 ins.t = (i >> 16) & 0x1f; 1014 ins.d = (i >> 11) & 0x1f; 1015 ins.shift = (i >> 6) & 0x1f; 1016 ins.imm = i & 0xffff; 1017 ins.imm_se = (u32)((i16)(i & 0xffff)); 1018 ins.imm_jump = i & 0x3ffffff; 1019 ins.cop_opcode = (i >> 21) & 0x1f; 1020 return ins; 1021 }