|
20 | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | 21 | */ |
22 | 22 |
|
23 | | -#include "cstring" |
| 23 | +#include <algorithm> |
| 24 | +#include <cstring> |
24 | 25 |
|
25 | 26 | #include "system/types.h" |
26 | 27 | #include "cpu/debug.h" |
@@ -94,7 +95,7 @@ static void ppc_opc_invalid(uint32 opc) |
94 | 95 | } |
95 | 96 | fprintf(stderr, "[PPC/DEC] Bad opcode: %08x (%u:%u)\n", |
96 | 97 | opc, PPC_OPC_MAIN(opc), |
97 | | - PPC_OPC_EXT(opc)); |
| 98 | + PPC_OPC_MOD(opc)); |
98 | 99 |
|
99 | 100 | SINGLESTEP("unknown instruction\n"); |
100 | 101 |
|
@@ -534,84 +535,86 @@ static void ppc_opc_group_v(uint32 opc) |
534 | 535 | return ppc_opc_table_groupv[ext](opc); |
535 | 536 | } |
536 | 537 |
|
537 | | -static ppc_opc_function ppc_opc_table_main[64] = { |
538 | | - &ppc_opc_invalid, // 0 |
539 | | - &ppc_opc_invalid, // 1 |
540 | | - &ppc_opc_invalid, // 2 (tdi on 64 bit platforms) |
541 | | - &ppc_opc_twi, // 3 |
542 | | - &ppc_opc_invalid, // 4 (altivec group 1) |
543 | | - &ppc_opc_invalid, // 5 |
544 | | - &ppc_opc_invalid, // 6 |
545 | | - &ppc_opc_mulli, // 7 |
546 | | - &ppc_opc_subfic, // 8 |
547 | | - &ppc_opc_invalid, // 9 |
548 | | - &ppc_opc_cmpli, // 10 |
549 | | - &ppc_opc_cmpi, // 11 |
550 | | - &ppc_opc_addic, // 12 |
551 | | - &ppc_opc_addic_, // 13 |
552 | | - &ppc_opc_addi, // 14 |
553 | | - &ppc_opc_addis, // 15 |
554 | | - &ppc_opc_bcx, // 16 |
555 | | - &ppc_opc_sc, // 17 |
556 | | - &ppc_opc_bx, // 18 |
557 | | - &ppc_opc_group_1, // 19 |
558 | | - &ppc_opc_rlwimix, // 20 |
559 | | - &ppc_opc_rlwinmx, // 21 |
560 | | - &ppc_opc_invalid, // 22 |
561 | | - &ppc_opc_rlwnmx, // 23 |
562 | | - &ppc_opc_ori, // 24 |
563 | | - &ppc_opc_oris, // 25 |
564 | | - &ppc_opc_xori, // 26 |
565 | | - &ppc_opc_xoris, // 27 |
566 | | - &ppc_opc_andi_, // 28 |
567 | | - &ppc_opc_andis_, // 29 |
568 | | - &ppc_opc_invalid, // 30 (group_rld on 64 bit platforms) |
569 | | - &ppc_opc_group_2, // 31 |
570 | | - &ppc_opc_lwz, // 32 |
571 | | - &ppc_opc_lwzu, // 33 |
572 | | - &ppc_opc_lbz, // 34 |
573 | | - &ppc_opc_lbzu, // 35 |
574 | | - &ppc_opc_stw, // 36 |
575 | | - &ppc_opc_stwu, // 37 |
576 | | - &ppc_opc_stb, // 38 |
577 | | - &ppc_opc_stbu, // 39 |
578 | | - &ppc_opc_lhz, // 40 |
579 | | - &ppc_opc_lhzu, // 41 |
580 | | - &ppc_opc_lha, // 42 |
581 | | - &ppc_opc_lhau, // 43 |
582 | | - &ppc_opc_sth, // 44 |
583 | | - &ppc_opc_sthu, // 45 |
584 | | - &ppc_opc_lmw, // 46 |
585 | | - &ppc_opc_stmw, // 47 |
586 | | - &ppc_opc_lfs, // 48 |
587 | | - &ppc_opc_lfsu, // 49 |
588 | | - &ppc_opc_lfd, // 50 |
589 | | - &ppc_opc_lfdu, // 51 |
590 | | - &ppc_opc_stfs, // 52 |
591 | | - &ppc_opc_stfsu, // 53 |
592 | | - &ppc_opc_stfd, // 54 |
593 | | - &ppc_opc_stfdu, // 55 |
594 | | - &ppc_opc_invalid, // 56 |
595 | | - &ppc_opc_invalid, // 57 |
596 | | - &ppc_opc_invalid, // 58 (ld on 64 bit platforms) |
597 | | - &ppc_opc_group_f1, // 59 |
598 | | - &ppc_opc_invalid, // 60 |
599 | | - &ppc_opc_invalid, // 61 |
600 | | - &ppc_opc_invalid, // 62 |
601 | | - &ppc_opc_group_f2, // 63 |
602 | | -}; |
| 538 | +// Opcode lookup table, indexed by primary opcode (bits 0...5) and modifier (bits 21...31). |
| 539 | +static ppc_opc_function ppc_opc_table[64 * 2048]; |
| 540 | + |
| 541 | +#define OP(opcode, fn) \ |
| 542 | +do { \ |
| 543 | +for (uint32_t mod = 0; mod < 2048; mod++) { \ |
| 544 | + ppc_opc_table[((opcode) << 11) | mod] = fn; \ |
| 545 | +} \ |
| 546 | +} while (0) |
603 | 547 |
|
604 | 548 | void FASTCALL ppc_exec_opc(uint32 opc) |
605 | 549 | { |
606 | | - uint32 mainopc = PPC_OPC_MAIN(opc); |
607 | | - ppc_opc_table_main[mainopc](opc); |
| 550 | + ppc_opc_table[PPC_OPC_MAIN(opc) | PPC_OPC_MOD(opc)](opc); |
608 | 551 | } |
609 | 552 |
|
610 | 553 | void ppc_dec_init() |
611 | 554 | { |
| 555 | + auto ppc_opc_table_size = sizeof(ppc_opc_table) / sizeof(ppc_opc_table[0]); |
| 556 | + std::fill_n(ppc_opc_table, ppc_opc_table_size, ppc_opc_invalid); |
| 557 | + |
| 558 | + OP(3, ppc_opc_twi); |
| 559 | + OP(7, ppc_opc_mulli); |
| 560 | + OP(8, ppc_opc_subfic); |
| 561 | + OP(10, ppc_opc_cmpli); |
| 562 | + OP(11, ppc_opc_cmpi); |
| 563 | + OP(12, ppc_opc_addic); |
| 564 | + OP(13, ppc_opc_addic_); |
| 565 | + OP(14, ppc_opc_addi); |
| 566 | + OP(15, ppc_opc_addis); |
| 567 | + OP(16, ppc_opc_bcx); |
| 568 | + OP(17, ppc_opc_sc); |
| 569 | + OP(18, ppc_opc_bx); |
| 570 | + OP(19, ppc_opc_group_1); |
| 571 | + OP(20, ppc_opc_rlwimix); |
| 572 | + OP(21, ppc_opc_rlwinmx); |
| 573 | + OP(23, ppc_opc_rlwnmx); |
| 574 | + OP(24, ppc_opc_ori); |
| 575 | + OP(25, ppc_opc_oris); |
| 576 | + OP(26, ppc_opc_xori); |
| 577 | + OP(27, ppc_opc_xoris); |
| 578 | + OP(28, ppc_opc_andi_); |
| 579 | + OP(29, ppc_opc_andis_); |
| 580 | + OP(31, ppc_opc_group_2); |
| 581 | + OP(32, ppc_opc_lwz); |
| 582 | + OP(33, ppc_opc_lwzu); |
| 583 | + OP(34, ppc_opc_lbz); |
| 584 | + OP(35, ppc_opc_lbzu); |
| 585 | + OP(36, ppc_opc_stw); |
| 586 | + OP(37, ppc_opc_stwu); |
| 587 | + OP(38, ppc_opc_stb); |
| 588 | + OP(39, ppc_opc_stbu); |
| 589 | + OP(40, ppc_opc_lhz); |
| 590 | + OP(41, ppc_opc_lhzu); |
| 591 | + OP(42, ppc_opc_lha); |
| 592 | + OP(43, ppc_opc_lhau); |
| 593 | + OP(44, ppc_opc_sth); |
| 594 | + OP(45, ppc_opc_sthu); |
| 595 | + OP(46, ppc_opc_lmw); |
| 596 | + OP(47, ppc_opc_stmw); |
| 597 | + OP(48, ppc_opc_lfs); |
| 598 | + OP(49, ppc_opc_lfsu); |
| 599 | + OP(50, ppc_opc_lfd); |
| 600 | + OP(51, ppc_opc_lfdu); |
| 601 | + OP(52, ppc_opc_stfs); |
| 602 | + OP(53, ppc_opc_stfsu); |
| 603 | + OP(54, ppc_opc_stfd); |
| 604 | + OP(55, ppc_opc_stfdu); |
| 605 | + OP(59, ppc_opc_group_f1); |
| 606 | + OP(63, ppc_opc_group_f2); |
| 607 | + |
612 | 608 | ppc_opc_init_group2(); |
| 609 | + |
| 610 | + // G4 CPU |
613 | 611 | if ((ppc_cpu_get_pvr(0) & 0xffff0000) == 0x000c0000) { |
614 | | - ppc_opc_table_main[4] = ppc_opc_group_v; |
| 612 | + OP(4, ppc_opc_group_v); |
615 | 613 | ppc_opc_init_groupv(); |
616 | 614 | } |
| 615 | + |
| 616 | + // 64-bit CPU |
| 617 | + // OP(2, ppc_opc_tdi); |
| 618 | + // OP(30, ppc_opc_group_rld); |
| 619 | + // OP(58, ppc_opc_ld); |
617 | 620 | } |
0 commit comments