trunk/src/emu/cpu/arm7/arm7drc.c
| r20737 | r20738 | |
| 61 | 61 | CONSTANTS |
| 62 | 62 | ***************************************************************************/ |
| 63 | 63 | |
| 64 | typedef const void (*arm7thumb_drcophandler)(arm_state*, drcuml_block*, compiler_state*, opcode_desc*); |
| 65 | |
| 66 | #include "arm7tdrc.c" |
| 67 | |
| 64 | 68 | /* map variables */ |
| 65 | 69 | #define MAPVAR_PC M0 |
| 66 | 70 | #define MAPVAR_CYCLES M1 |
| r20737 | r20738 | |
| 137 | 141 | code_handle * entry; /* entry point */ |
| 138 | 142 | code_handle * nocode; /* nocode exception handler */ |
| 139 | 143 | code_handle * out_of_cycles; /* out of cycles exception handler */ |
| 144 | code_handle * tlb_translate; /* tlb translation handler */ |
| 145 | code_handle * detect_fault; /* tlb fault detection handler */ |
| 146 | code_handle * check_irq; /* irq check handler */ |
| 140 | 147 | code_handle * read8; /* read byte */ |
| 141 | 148 | code_handle * write8; /* write byte */ |
| 142 | 149 | code_handle * read16; /* read half */ |
| r20737 | r20738 | |
| 146 | 153 | |
| 147 | 154 | /* fast RAM */ |
| 148 | 155 | UINT32 fastram_select; |
| 149 | | fast_ram_info fastram[MIPS3_MAX_FASTRAM]; |
| 156 | fast_ram_info fastram[ARM7_MAX_FASTRAM]; |
| 150 | 157 | }; |
| 151 | 158 | |
| 152 | 159 | |
| r20737 | r20738 | |
| 165 | 172 | static void static_generate_nocode_handler(arm_state *arm); |
| 166 | 173 | static void static_generate_out_of_cycles(arm_state *arm); |
| 167 | 174 | static void static_generate_tlb_translate(arm_state *arm); |
| 175 | static void static_generate_detect_fault(arm_state *arm); |
| 176 | static void static_generate_check_irq(arm_state *arm); |
| 168 | 177 | |
| 169 | 178 | static void generate_update_cycles(arm_state *arm, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception); |
| 170 | 179 | static void generate_checksum_block(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); |
| r20737 | r20738 | |
| 296 | 305 | arm->impstate->drcuml = auto_alloc(device->machine(), drcuml_state(*device, *cache, flags, 1, 32, 1)); |
| 297 | 306 | |
| 298 | 307 | /* add symbols for our stuff */ |
| 299 | | arm->impstate->drcuml->symbol_add(&arm->pc, sizeof(mips3->pc), "pc"); |
| 300 | | arm->impstate->drcuml->symbol_add(&arm->icount, sizeof(mips3->icount), "icount"); |
| 308 | arm->impstate->drcuml->symbol_add(&arm->icount, sizeof(arm->icount), "icount"); |
| 301 | 309 | for (int regnum = 0; regnum < 37; regnum++) |
| 302 | 310 | { |
| 303 | 311 | char buf[10]; |
| r20737 | r20738 | |
| 476 | 484 | } |
| 477 | 485 | |
| 478 | 486 | /*------------------------------------------------- |
| 479 | | mips3_exit - cleanup from execution |
| 487 | arm7_exit - cleanup from execution |
| 480 | 488 | -------------------------------------------------*/ |
| 481 | 489 | |
| 482 | | static CPU_EXIT( mips3 ) |
| 490 | static CPU_EXIT( arm7 ) |
| 483 | 491 | { |
| 484 | 492 | arm_state *arm = get_safe_token(device); |
| 485 | 493 | |
| r20737 | r20738 | |
| 491 | 499 | |
| 492 | 500 | |
| 493 | 501 | /*------------------------------------------------- |
| 494 | | mips3_translate - perform virtual-to-physical |
| 502 | arm7_translate - perform virtual-to-physical |
| 495 | 503 | address translation |
| 496 | 504 | -------------------------------------------------*/ |
| 497 | 505 | |
| r20737 | r20738 | |
| 1224 | 1232 | static_generate_nocode_handler(arm); |
| 1225 | 1233 | static_generate_out_of_cycles(arm); |
| 1226 | 1234 | static_generate_tlb_translate(arm); |
| 1235 | static_generate_detect_fault(arm); |
| 1227 | 1236 | //static_generate_tlb_mismatch(arm); |
| 1228 | 1237 | |
| 1229 | | /* append exception handlers for various types */ |
| 1230 | | /*static_generate_exception(mips3, EXCEPTION_INTERRUPT, TRUE, "exception_interrupt"); |
| 1231 | | static_generate_exception(mips3, EXCEPTION_INTERRUPT, FALSE, "exception_interrupt_norecover"); |
| 1232 | | static_generate_exception(mips3, EXCEPTION_TLBMOD, TRUE, "exception_tlbmod"); |
| 1233 | | static_generate_exception(mips3, EXCEPTION_TLBLOAD, TRUE, "exception_tlbload"); |
| 1234 | | static_generate_exception(mips3, EXCEPTION_TLBSTORE, TRUE, "exception_tlbstore"); |
| 1235 | | static_generate_exception(mips3, EXCEPTION_TLBLOAD_FILL, TRUE, "exception_tlbload_fill"); |
| 1236 | | static_generate_exception(mips3, EXCEPTION_TLBSTORE_FILL, TRUE, "exception_tlbstore_fill"); |
| 1237 | | static_generate_exception(mips3, EXCEPTION_ADDRLOAD, TRUE, "exception_addrload"); |
| 1238 | | static_generate_exception(mips3, EXCEPTION_ADDRSTORE, TRUE, "exception_addrstore"); |
| 1239 | | static_generate_exception(mips3, EXCEPTION_SYSCALL, TRUE, "exception_syscall"); |
| 1240 | | static_generate_exception(mips3, EXCEPTION_BREAK, TRUE, "exception_break"); |
| 1241 | | static_generate_exception(mips3, EXCEPTION_INVALIDOP, TRUE, "exception_invalidop"); |
| 1242 | | static_generate_exception(mips3, EXCEPTION_BADCOP, TRUE, "exception_badcop"); |
| 1243 | | static_generate_exception(mips3, EXCEPTION_OVERFLOW, TRUE, "exception_overflow"); |
| 1244 | | static_generate_exception(mips3, EXCEPTION_TRAP, TRUE, "exception_trap");*/ |
| 1245 | | |
| 1246 | 1238 | /* add subroutines for memory accesses */ |
| 1247 | | //for (mode = 0; mode < 3; mode++) |
| 1248 | | //{ |
| 1249 | | static_generate_memory_accessor(mips3, mode, 1, FALSE, FALSE, "read8", &mips3->impstate->read8[mode]); |
| 1250 | | static_generate_memory_accessor(mips3, mode, 1, TRUE, FALSE, "write8", &mips3->impstate->write8[mode]); |
| 1251 | | static_generate_memory_accessor(mips3, mode, 2, FALSE, FALSE, "read16", &mips3->impstate->read16[mode]); |
| 1252 | | static_generate_memory_accessor(mips3, mode, 2, TRUE, FALSE, "write16", &mips3->impstate->write16[mode]); |
| 1253 | | static_generate_memory_accessor(mips3, mode, 4, FALSE, FALSE, "read32", &mips3->impstate->read32[mode]); |
| 1254 | | static_generate_memory_accessor(mips3, mode, 4, FALSE, TRUE, "read32mask", &mips3->impstate->read32mask[mode]); |
| 1255 | | static_generate_memory_accessor(mips3, mode, 4, TRUE, FALSE, "write32", &mips3->impstate->write32[mode]); |
| 1256 | | static_generate_memory_accessor(mips3, mode, 4, TRUE, TRUE, "write32mask", &mips3->impstate->write32mask[mode]); |
| 1257 | | static_generate_memory_accessor(mips3, mode, 8, FALSE, FALSE, "read64", &mips3->impstate->read64[mode]); |
| 1258 | | static_generate_memory_accessor(mips3, mode, 8, FALSE, TRUE, "read64mask", &mips3->impstate->read64mask[mode]); |
| 1259 | | static_generate_memory_accessor(mips3, mode, 8, TRUE, FALSE, "write64", &mips3->impstate->write64[mode]); |
| 1260 | | static_generate_memory_accessor(mips3, mode, 8, TRUE, TRUE, "write64mask", &mips3->impstate->write64mask[mode]); |
| 1261 | | //} |
| 1239 | static_generate_memory_accessor(arm, mode, 1, FALSE, FALSE, "read8", &arm->impstate->read8); |
| 1240 | static_generate_memory_accessor(arm, mode, 1, TRUE, FALSE, "write8", &arm->impstate->write8); |
| 1241 | static_generate_memory_accessor(arm, mode, 2, FALSE, FALSE, "read16", &arm->impstate->read16); |
| 1242 | static_generate_memory_accessor(arm, mode, 2, TRUE, FALSE, "write16", &arm->impstate->write16); |
| 1243 | static_generate_memory_accessor(arm, mode, 4, FALSE, FALSE, "read32", &arm->impstate->read32); |
| 1244 | static_generate_memory_accessor(arm, mode, 4, TRUE, FALSE, "write32", &arm->impstate->write32); |
| 1262 | 1245 | } |
| 1263 | 1246 | catch (drcuml_block::abort_compilation &) |
| 1264 | 1247 | { |
| r20737 | r20738 | |
| 1435 | 1418 | /* forward references */ |
| 1436 | 1419 | alloc_handle(drcuml, &arm->impstate->exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover"); |
| 1437 | 1420 | alloc_handle(drcuml, &arm->impstate->nocode, "nocode"); |
| 1421 | alloc_handle(drcuml, &arm->impstate->detect_fault, "detect_fault"); |
| 1422 | alloc_handle(drcuml, &arm->impstate->tlb_translate, "tlb_translate"); |
| 1438 | 1423 | |
| 1439 | 1424 | alloc_handle(drcuml, &arm->impstate->entry, "entry"); |
| 1440 | | UML_HANDLE(block, *arm->impstate->entry); // handle entry |
| 1425 | UML_HANDLE(block, *arm->impstate->entry); // handle entry |
| 1441 | 1426 | |
| 1442 | 1427 | /* load fast integer registers */ |
| 1443 | 1428 | load_fast_iregs(arm, block); |
| 1444 | 1429 | |
| 1430 | UML_CALLH(block, *arm->impstate->check_irq); |
| 1431 | |
| 1432 | /* generate a hash jump via the current mode and PC */ |
| 1433 | UML_HASHJMP(block, 0, mem(&arm->pc), *arm->impstate->nocode); // hashjmp 0,<pc>,nocode |
| 1434 | block->end(); |
| 1435 | } |
| 1436 | |
| 1437 | |
| 1438 | /*------------------------------------------------- |
| 1439 | static_generate_check_irq - generate a handler |
| 1440 | to check IRQs |
| 1441 | -------------------------------------------------*/ |
| 1442 | |
| 1443 | static void static_generate_check_irq(arm_state *arm) |
| 1444 | { |
| 1445 | drcuml_state *drcuml = arm->impstate->drcuml; |
| 1446 | drcuml_block *block; |
| 1447 | int nodabt = 0; |
| 1448 | int nopabt = 0; |
| 1449 | int irqadjust = 0; |
| 1450 | int nofiq = 0; |
| 1451 | int irq32 = 0; |
| 1452 | int swi32 = 0; |
| 1453 | int done = 0; |
| 1454 | int label = 1; |
| 1455 | |
| 1456 | /* begin generating */ |
| 1457 | block = drcuml->begin_block(120); |
| 1458 | |
| 1459 | /* generate a hash jump via the current mode and PC */ |
| 1460 | alloc_handle(drcuml, &arm->impstate->check_irq, "check_irq"); |
| 1461 | UML_HANDLE(block, *arm->impstate->check_irq); // handle check_irq |
| 1445 | 1462 | /* Exception priorities: |
| 1446 | 1463 | |
| 1447 | 1464 | Reset |
| r20737 | r20738 | |
| 1544 | 1561 | UML_MOV(block, mem(&arm->pendingUnd, 0); // mov pendingUnd, 0 |
| 1545 | 1562 | UML_JMP(block, irqadjust); // jmp irqadjust |
| 1546 | 1563 | |
| 1547 | | UML_LABEL(block, nound); // nound: |
| 1564 | UML_LABEL(block, nopabt); // nopabt: |
| 1548 | 1565 | |
| 1549 | 1566 | // Software Interrupt |
| 1550 | 1567 | UML_TEST(block, mem(&arm->pendingSwi, 1); // test pendingSwi, 1 |
| r20737 | r20738 | |
| 1583 | 1600 | |
| 1584 | 1601 | UML_LABEL(block, done); // done: |
| 1585 | 1602 | |
| 1586 | | /* generate a hash jump via the current mode and PC */ |
| 1587 | | UML_HASHJMP(block, mem(&arm->impstate->mode), mem(&arm->pc), *arm->impstate->nocode); |
| 1588 | | // hashjmp <mode>,<pc>,nocode |
| 1589 | 1603 | block->end(); |
| 1590 | | } |
| 1604 | }; |
| 1591 | 1605 | |
| 1592 | | |
| 1593 | 1606 | /*------------------------------------------------- |
| 1594 | 1607 | static_generate_nocode_handler - generate an |
| 1595 | 1608 | exception handler for "out of code" |
| r20737 | r20738 | |
| 1658 | 1671 | block = drcuml->begin_block(1024); |
| 1659 | 1672 | |
| 1660 | 1673 | /* add a global entry for this */ |
| 1661 | | alloc_handle(drcuml, handleptr, name); |
| 1662 | | UML_HANDLE(block, **handleptr); // handle *handleptr |
| 1674 | alloc_handle(drcuml, &arm->impstate->detect_fault, "detect_fault"); |
| 1675 | UML_HANDLE(block, *arm->impstate->detect_fault); // handle detect_fault |
| 1663 | 1676 | |
| 1664 | 1677 | UML_ROLAND(block, I6, I4, 32-4, 0x0f<<1); // roland i6, i4, 32-4, 0xf<<1 |
| 1665 | 1678 | UML_ROLAND(block, I6, mem(&COPRO_DOMAIN_ACCESS_CONTROL), I6, 3);// roland i6, COPRO_DOMAIN_ACCESS_CONTROL, i6, 3 |
| r20737 | r20738 | |
| 1747 | 1760 | /* begin generating */ |
| 1748 | 1761 | block = drcuml->begin_block(170); |
| 1749 | 1762 | |
| 1750 | | /* add a global entry for this */ |
| 1751 | | alloc_handle(drcuml, handleptr, name); |
| 1752 | | UML_HANDLE(block, **handleptr); // handle *handleptr |
| 1763 | alloc_handle(drcuml, &arm->impstate->tlb_translate, "tlb_translate"); |
| 1764 | UML_HANDLE(block, *arm->impstate->tlb_translate); // handle tlb_translate |
| 1753 | 1765 | |
| 1754 | 1766 | // I3: vaddr |
| 1755 | 1767 | UML_CMP(block, I0, 32 * 1024 * 1024); // cmp i0, 32*1024*1024 |
| r20737 | r20738 | |
| 1932 | 1944 | |
| 1933 | 1945 | static void static_generate_memory_accessor(arm_state *arm, int size, bool istlb, bool iswrite, const char *name, code_handle **handleptr) |
| 1934 | 1946 | { |
| 1935 | | /* on entry, address is in I0; data for writes is in I1 */ |
| 1947 | /* on entry, address is in I0; data for writes is in I1, fetch type in I2 */ |
| 1936 | 1948 | /* on exit, read result is in I0 */ |
| 1937 | 1949 | /* routine trashes I0-I3 */ |
| 1938 | | //code_handle &exception_tlb = *mips3->impstate->exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD]; |
| 1939 | | //code_handle &exception_tlbfill = *mips3->impstate->exception[iswrite ? EXCEPTION_TLBSTORE_FILL : EXCEPTION_TLBLOAD_FILL]; |
| 1940 | | //code_handle &exception_addrerr = *mips3->impstate->exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD]; |
| 1941 | 1950 | drcuml_state *drcuml = arm->impstate->drcuml; |
| 1942 | 1951 | drcuml_block *block; |
| 1943 | 1952 | int tlbmiss = 0; |
| r20737 | r20738 | |
| 1955 | 1964 | UML_TEST(block, mem(&COPRO_CTRL), COPRO_CTRL_MMU_EN); // test COPRO_CTRL, COPRO_CTRL_MMU_EN |
| 1956 | 1965 | if (iswrite) |
| 1957 | 1966 | { |
| 1958 | | UML_MOVc(block, COND_NZ, I2, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE);// movnz i2, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE |
| 1967 | UML_MOVc(block, COND_NZ, I3, ARM7_TLB_WRITE); // movnz i3, ARM7_TLB_WRITE |
| 1959 | 1968 | } |
| 1960 | 1969 | else |
| 1961 | 1970 | { |
| 1962 | | UML_MOVc(block, COND_NZ, I2, ARM7_TLB_ABORT_D | ARM7_TLB_READ); // movnz i2, ARM7_TLB_ABORT_D | ARM7_TLB_READ |
| 1971 | UML_MOVc(block, COND_NZ, I3, ARM7_TLB_READ); // movnz i3, ARM7_TLB_READ |
| 1963 | 1972 | } |
| 1973 | UML_OR(block, I2, I2, I3); // or i2, i2, i3 |
| 1964 | 1974 | UML_CALLHc(block, COND_NZ, *arm->impstate->tlb_translate); // callhnz tlb_translate |
| 1965 | 1975 | } |
| 1966 | 1976 | |
| r20737 | r20738 | |
| 2014 | 2024 | } |
| 2015 | 2025 | else if (size == 2) |
| 2016 | 2026 | { |
| 2017 | | UML_XOR(block, I0, I0, mips3->bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)); |
| 2027 | UML_XOR(block, I0, I0, arm->bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)); |
| 2018 | 2028 | // xor i0, i0, wordxor |
| 2019 | 2029 | UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1); // store fastbase, i0, i1, word_x1 |
| 2020 | 2030 | } |
| r20737 | r20738 | |
| 2070 | 2080 | block->end(); |
| 2071 | 2081 | } |
| 2072 | 2082 | |
| 2083 | /*************************************************************************** |
| 2084 | CODE GENERATION |
| 2085 | ***************************************************************************/ |
| 2086 | |
| 2087 | /*------------------------------------------------- |
| 2088 | generate_update_cycles - generate code to |
| 2089 | subtract cycles from the icount and generate |
| 2090 | an exception if out |
| 2091 | -------------------------------------------------*/ |
| 2092 | |
| 2093 | static void generate_update_cycles(arm_state *arm, drcuml_block *block, compiler_state *compiler, parameter param) |
| 2094 | { |
| 2095 | /* check full interrupts if pending */ |
| 2096 | if (compiler->checkints) |
| 2097 | { |
| 2098 | code_label skip; |
| 2099 | |
| 2100 | compiler->checkints = FALSE; |
| 2101 | UML_CALLH(block, *arm->impstate->check_irq); |
| 2102 | } |
| 2103 | |
| 2104 | /* account for cycles */ |
| 2105 | if (compiler->cycles > 0) |
| 2106 | { |
| 2107 | UML_SUB(block, mem(&arm->icount), mem(&arm->icount), MAPVAR_CYCLES); // sub icount,icount,cycles |
| 2108 | UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 |
| 2109 | UML_EXHc(block, COND_S, *arm->impstate->out_of_cycles, param); // exh out_of_cycles,nextpc |
| 2110 | } |
| 2111 | compiler->cycles = 0; |
| 2112 | } |
| 2113 | |
| 2114 | |
| 2115 | /*------------------------------------------------- |
| 2116 | generate_checksum_block - generate code to |
| 2117 | validate a sequence of opcodes |
| 2118 | -------------------------------------------------*/ |
| 2119 | |
| 2120 | static void generate_checksum_block(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) |
| 2121 | { |
| 2122 | const opcode_desc *curdesc; |
| 2123 | if (LOG_UML) |
| 2124 | { |
| 2125 | block->append_comment("[Validation for %08X]", seqhead->pc); // comment |
| 2126 | } |
| 2127 | |
| 2128 | /* loose verify or single instruction: just compare and fail */ |
| 2129 | if (!(arm->impstate->drcoptions & ARM7DRC_STRICT_VERIFY) || seqhead->next() == NULL) |
| 2130 | { |
| 2131 | if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) |
| 2132 | { |
| 2133 | UINT32 sum = seqhead->opptr.l[0]; |
| 2134 | void *base = arm->direct->read_decrypted_ptr(seqhead->physpc); |
| 2135 | UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword |
| 2136 | |
| 2137 | if (seqhead->delay.first() != NULL && seqhead->physpc != seqhead->delay.first()->physpc) |
| 2138 | { |
| 2139 | base = arm->direct->read_decrypted_ptr(seqhead->delay.first()->physpc); |
| 2140 | UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword |
| 2141 | UML_ADD(block, I0, I0, I1); // add i0,i0,i1 |
| 2142 | |
| 2143 | sum += seqhead->delay.first()->opptr.l[0]; |
| 2144 | } |
| 2145 | |
| 2146 | UML_CMP(block, I0, sum); // cmp i0,opptr[0] |
| 2147 | UML_EXHc(block, COND_NE, *arm->impstate->nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 2148 | } |
| 2149 | } |
| 2150 | |
| 2151 | /* full verification; sum up everything */ |
| 2152 | else |
| 2153 | { |
| 2154 | UINT32 sum = 0; |
| 2155 | void *base = arm->direct->read_decrypted_ptr(seqhead->physpc); |
| 2156 | UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword |
| 2157 | sum += seqhead->opptr.l[0]; |
| 2158 | for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) |
| 2159 | if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) |
| 2160 | { |
| 2161 | base = arm->direct->read_decrypted_ptr(curdesc->physpc); |
| 2162 | UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword |
| 2163 | UML_ADD(block, I0, I0, I1); // add i0,i0,i1 |
| 2164 | sum += curdesc->opptr.l[0]; |
| 2165 | |
| 2166 | if (curdesc->delay.first() != NULL && (curdesc == seqlast || (curdesc->next() != NULL && curdesc->next()->physpc != curdesc->delay.first()->physpc))) |
| 2167 | { |
| 2168 | base = arm->direct->read_decrypted_ptr(curdesc->delay.first()->physpc); |
| 2169 | UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword |
| 2170 | UML_ADD(block, I0, I0, I1); // add i0,i0,i1 |
| 2171 | sum += curdesc->delay.first()->opptr.l[0]; |
| 2172 | } |
| 2173 | } |
| 2174 | UML_CMP(block, I0, sum); // cmp i0,sum |
| 2175 | UML_EXHc(block, COND_NE, *arm->impstate->nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 2176 | } |
| 2177 | } |
| 2178 | |
| 2179 | |
| 2180 | /*------------------------------------------------- |
| 2181 | generate_sequence_instruction - generate code |
| 2182 | for a single instruction in a sequence |
| 2183 | -------------------------------------------------*/ |
| 2184 | |
| 2185 | static void generate_sequence_instruction(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 2186 | { |
| 2187 | offs_t expc; |
| 2188 | int hotnum; |
| 2189 | |
| 2190 | /* add an entry for the log */ |
| 2191 | if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) |
| 2192 | log_add_disasm_comment(arm, block, desc->pc, desc->opptr.l[0]); |
| 2193 | |
| 2194 | /* set the PC map variable */ |
| 2195 | expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 3 : desc->pc; |
| 2196 | UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc |
| 2197 | |
| 2198 | /* accumulate total cycles */ |
| 2199 | compiler->cycles += desc->cycles; |
| 2200 | |
| 2201 | /* is this a hotspot? */ |
| 2202 | for (hotnum = 0; hotnum < MIPS3_MAX_HOTSPOTS; hotnum++) |
| 2203 | { |
| 2204 | if (arm->impstate->hotspot[hotnum].pc != 0 && desc->pc == arm->impstate->hotspot[hotnum].pc && desc->opptr.l[0] == arm->impstate->hotspot[hotnum].opcode) |
| 2205 | { |
| 2206 | compiler->cycles += arm->impstate->hotspot[hotnum].cycles; |
| 2207 | break; |
| 2208 | } |
| 2209 | } |
| 2210 | |
| 2211 | /* update the icount map variable */ |
| 2212 | UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles |
| 2213 | |
| 2214 | /* if we are debugging, call the debugger */ |
| 2215 | if ((arm->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 2216 | { |
| 2217 | UML_MOV(block, mem(&R15), desc->pc); // mov [pc],desc->pc |
| 2218 | save_fast_iregs(arm, block); |
| 2219 | UML_DEBUG(block, desc->pc); // debug desc->pc |
| 2220 | } |
| 2221 | |
| 2222 | /* if we hit an unmapped address, fatal error */ |
| 2223 | if (desc->flags & OPFLAG_COMPILER_UNMAPPED) |
| 2224 | { |
| 2225 | UML_MOV(block, mem(&R15), desc->pc); // mov R15,desc->pc |
| 2226 | save_fast_iregs(arm, block); |
| 2227 | UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE |
| 2228 | } |
| 2229 | |
| 2230 | /* otherwise, unless this is a virtual no-op, it's a regular instruction */ |
| 2231 | else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) |
| 2232 | { |
| 2233 | /* compile the instruction */ |
| 2234 | if (!generate_opcode(arm, block, compiler, desc)) |
| 2235 | { |
| 2236 | UML_MOV(block, mem(&R15), desc->pc); // mov R15,desc->pc |
| 2237 | UML_MOV(block, mem(&arm->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l |
| 2238 | UML_CALLC(block, cfunc_unimplemented, arm); // callc cfunc_unimplemented |
| 2239 | } |
| 2240 | } |
| 2241 | } |
| 2242 | |
| 2243 | |
| 2244 | /*------------------------------------------------------------------ |
| 2245 | generate_delay_slot_and_branch |
| 2246 | ------------------------------------------------------------------*/ |
| 2247 | |
| 2248 | static void generate_delay_slot_and_branch(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 linkreg) |
| 2249 | { |
| 2250 | compiler_state compiler_temp = *compiler; |
| 2251 | UINT32 op = desc->opptr.l[0]; |
| 2252 | |
| 2253 | /* update the cycles and jump through the hash table to the target */ |
| 2254 | if (desc->targetpc != BRANCH_TARGET_DYNAMIC) |
| 2255 | { |
| 2256 | generate_update_cycles(arm, block, &compiler_temp, desc->targetpc, TRUE); // <subtract cycles> |
| 2257 | UML_HASHJMP(block, 0, desc->targetpc, *arm->impstate->nocode); |
| 2258 | // hashjmp 0,desc->targetpc,nocode |
| 2259 | } |
| 2260 | else |
| 2261 | { |
| 2262 | generate_update_cycles(arm, block, &compiler_temp, mem(&arm->impstate->jmpdest), TRUE); |
| 2263 | // <subtract cycles> |
| 2264 | UML_HASHJMP(block, 0, mem(&arm->impstate->jmpdest), *arm->impstate->nocode);// hashjmp 0,<rsreg>,nocode |
| 2265 | } |
| 2266 | |
| 2267 | /* update the label */ |
| 2268 | compiler->labelnum = compiler_temp.labelnum; |
| 2269 | |
| 2270 | /* reset the mapvar to the current cycles and account for skipped slots */ |
| 2271 | compiler->cycles += desc->skipslots; |
| 2272 | UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles |
| 2273 | } |
| 2274 | |
| 2275 | |
| 2276 | /*------------------------------------------------- |
| 2277 | generate_opcode - generate code for a specific |
| 2278 | opcode |
| 2279 | -------------------------------------------------*/ |
| 2280 | |
| 2281 | static int generate_opcode(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 2282 | { |
| 2283 | int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); |
| 2284 | UINT32 op = desc->opptr.l[0]; |
| 2285 | UINT8 opswitch = op >> 26; |
| 2286 | code_label skip; |
| 2287 | |
| 2288 | if (T_IS_SET(GET_CPSR)) |
| 2289 | { |
| 2290 | |
| 2291 | } |
| 2292 | |
| 2293 | switch (opswitch) |
| 2294 | { |
| 2295 | /* ----- sub-groups ----- */ |
| 2296 | |
| 2297 | case 0x00: /* SPECIAL - MIPS I */ |
| 2298 | UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg> |
| 2299 | UML_JMPc(block, COND_NE, skip = compiler->labelnum++); // jmp skip,NE |
| 2300 | generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp> |
| 2301 | UML_LABEL(block, skip); // skip: |
| 2302 | return TRUE; |
| 2303 | |
| 2073 | 2304 | DEFINE_LEGACY_CPU_DEVICE(ARM7, arm7); |
| 2074 | 2305 | DEFINE_LEGACY_CPU_DEVICE(ARM7_BE, arm7_be); |
| 2075 | 2306 | DEFINE_LEGACY_CPU_DEVICE(ARM7500, arm7500); |
trunk/src/emu/cpu/arm7/arm7thmb.c
| r20737 | r20738 | |
| 3 | 3 | #include "arm7thmb.h" |
| 4 | 4 | #include "arm7help.h" |
| 5 | 5 | |
| 6 | | // this is our master dispatch jump table for THUMB mode, representing [(insn & 0xffc0) >> 6] bits of the 16-bit decoded instruction |
| 6 | // this is our master dispatch jump table for THUMB mode, representing [(INSN & 0xffc0) >> 6] bits of the 16-bit decoded instruction |
| 7 | 7 | arm7thumb_ophandler thumb_handler[0x40*0x10] = |
| 8 | 8 | { |
| 9 | 9 | // #define THUMB_SHIFT_R ((UINT16)0x0800) |
| 10 | | tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, |
| 10 | tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, tg00_0, |
| 11 | tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, tg00_1, |
| 11 | 12 | // #define THUMB_INSN_ADDSUB ((UINT16)0x0800) // #define THUMB_ADDSUB_TYPE ((UINT16)0x0600) |
| 12 | | tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, |
| 13 | tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, tg01_0, |
| 14 | tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_10, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_11, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_12, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, tg01_13, |
| 13 | 15 | // #define THUMB_INSN_CMP ((UINT16)0x0800) |
| 14 | | tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, |
| 16 | tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, tg02_0, |
| 17 | tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, tg02_1, |
| 15 | 18 | // #define THUMB_INSN_SUB ((UINT16)0x0800) |
| 16 | | tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, |
| 19 | tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, tg03_0, |
| 20 | tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, tg03_1, |
| 17 | 21 | //#define THUMB_GROUP4_TYPE ((UINT16)0x0c00) //#define THUMB_ALUOP_TYPE ((UINT16)0x03c0) // #define THUMB_HIREG_OP ((UINT16)0x0300) // #define THUMB_HIREG_H ((UINT16)0x00c0) |
| 18 | | tg04_00_00, tg04_00_01, tg04_00_02, tg04_00_03, tg04_00_04, tg04_00_05, tg04_00_06, tg04_00_07, tg04_00_08, tg04_00_09, tg04_00_0a, tg04_00_0b, tg04_00_0c, tg04_00_0d, tg04_00_0e, tg04_00_0f, tg04_01_00, tg04_01_01, tg04_01_02, tg04_01_03, tg04_01_10, tg04_01_11, tg04_01_12, tg04_01_13, tg04_01_20, tg04_01_21, tg04_01_22, tg04_01_23, tg04_01_30, tg04_01_31, tg04_01_32, tg04_01_33, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, |
| 22 | tg04_00_00, tg04_00_01, tg04_00_02, tg04_00_03, tg04_00_04, tg04_00_05, tg04_00_06, tg04_00_07, tg04_00_08, tg04_00_09, tg04_00_0a, tg04_00_0b, tg04_00_0c, tg04_00_0d, tg04_00_0e, tg04_00_0f, tg04_01_00, tg04_01_01, tg04_01_02, tg04_01_03, tg04_01_10, tg04_01_11, tg04_01_12, tg04_01_13, tg04_01_20, tg04_01_21, tg04_01_22, tg04_01_23, tg04_01_30, tg04_01_31, tg04_01_32, tg04_01_33, |
| 23 | tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, tg04_0203, |
| 19 | 24 | //#define THUMB_GROUP5_TYPE ((UINT16)0x0e00) |
| 20 | | tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, |
| 25 | tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_0, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_1, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_2, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, tg05_3, |
| 26 | tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_4, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_5, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_6, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, tg05_7, |
| 21 | 27 | //#define THUMB_LSOP_L ((UINT16)0x0800) |
| 22 | | tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, |
| 28 | tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, tg06_0, |
| 29 | tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, tg06_1, |
| 23 | 30 | //#define THUMB_LSOP_L ((UINT16)0x0800) |
| 24 | | tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, |
| 31 | tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, tg07_0, |
| 32 | tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, tg07_1, |
| 25 | 33 | // #define THUMB_HALFOP_L ((UINT16)0x0800) |
| 26 | | tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, |
| 34 | tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, tg08_0, |
| 35 | tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, tg08_1, |
| 27 | 36 | // #define THUMB_STACKOP_L ((UINT16)0x0800) |
| 28 | | tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, |
| 37 | tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, tg09_0, |
| 38 | tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, tg09_1, |
| 29 | 39 | // #define THUMB_RELADDR_SP ((UINT16)0x0800) |
| 30 | | tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, |
| 40 | tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, tg0a_0, |
| 41 | tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, tg0a_1, |
| 31 | 42 | // #define THUMB_STACKOP_TYPE ((UINT16)0x0f00) |
| 32 | | tg0b_0, tg0b_0, tg0b_0, tg0b_0, tg0b_1, tg0b_1, tg0b_1, tg0b_1, tg0b_2, tg0b_2, tg0b_2, tg0b_2, tg0b_3, tg0b_3, tg0b_3, tg0b_3, tg0b_4, tg0b_4, tg0b_4, tg0b_4, tg0b_5, tg0b_5, tg0b_5, tg0b_5, tg0b_6, tg0b_6, tg0b_6, tg0b_6, tg0b_7, tg0b_7, tg0b_7, tg0b_7, tg0b_8, tg0b_8, tg0b_8, tg0b_8, tg0b_9, tg0b_9, tg0b_9, tg0b_9, tg0b_a, tg0b_a, tg0b_a, tg0b_a, tg0b_b, tg0b_b, tg0b_b, tg0b_b, tg0b_c, tg0b_c, tg0b_c, tg0b_c, tg0b_d, tg0b_d, tg0b_d, tg0b_d, tg0b_e, tg0b_e, tg0b_e, tg0b_e, tg0b_f, tg0b_f, tg0b_f, tg0b_f, |
| 43 | tg0b_0, tg0b_0, tg0b_0, tg0b_0, tg0b_1, tg0b_1, tg0b_1, tg0b_1, tg0b_2, tg0b_2, tg0b_2, tg0b_2, tg0b_3, tg0b_3, tg0b_3, tg0b_3, tg0b_4, tg0b_4, tg0b_4, tg0b_4, tg0b_5, tg0b_5, tg0b_5, tg0b_5, tg0b_6, tg0b_6, tg0b_6, tg0b_6, tg0b_7, tg0b_7, tg0b_7, tg0b_7, |
| 44 | tg0b_8, tg0b_8, tg0b_8, tg0b_8, tg0b_9, tg0b_9, tg0b_9, tg0b_9, tg0b_a, tg0b_a, tg0b_a, tg0b_a, tg0b_b, tg0b_b, tg0b_b, tg0b_b, tg0b_c, tg0b_c, tg0b_c, tg0b_c, tg0b_d, tg0b_d, tg0b_d, tg0b_d, tg0b_e, tg0b_e, tg0b_e, tg0b_e, tg0b_f, tg0b_f, tg0b_f, tg0b_f, |
| 33 | 45 | // #define THUMB_MULTLS ((UINT16)0x0800) |
| 34 | | tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, |
| 46 | tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, tg0c_0, |
| 47 | tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, tg0c_1, |
| 35 | 48 | // #define THUMB_COND_TYPE ((UINT16)0x0f00) |
| 36 | | tg0d_0, tg0d_0, tg0d_0, tg0d_0, tg0d_1, tg0d_1, tg0d_1, tg0d_1, tg0d_2, tg0d_2, tg0d_2, tg0d_2, tg0d_3, tg0d_3, tg0d_3, tg0d_3, tg0d_4, tg0d_4, tg0d_4, tg0d_4, tg0d_5, tg0d_5, tg0d_5, tg0d_5, tg0d_6, tg0d_6, tg0d_6, tg0d_6, tg0d_7, tg0d_7, tg0d_7, tg0d_7, tg0d_8, tg0d_8, tg0d_8, tg0d_8, tg0d_9, tg0d_9, tg0d_9, tg0d_9, tg0d_a, tg0d_a, tg0d_a, tg0d_a, tg0d_b, tg0d_b, tg0d_b, tg0d_b, tg0d_c, tg0d_c, tg0d_c, tg0d_c, tg0d_d, tg0d_d, tg0d_d, tg0d_d, tg0d_e, tg0d_e, tg0d_e, tg0d_e, tg0d_f, tg0d_f, tg0d_f, tg0d_f, |
| 49 | tg0d_0, tg0d_0, tg0d_0, tg0d_0, tg0d_1, tg0d_1, tg0d_1, tg0d_1, tg0d_2, tg0d_2, tg0d_2, tg0d_2, tg0d_3, tg0d_3, tg0d_3, tg0d_3, tg0d_4, tg0d_4, tg0d_4, tg0d_4, tg0d_5, tg0d_5, tg0d_5, tg0d_5, tg0d_6, tg0d_6, tg0d_6, tg0d_6, tg0d_7, tg0d_7, tg0d_7, tg0d_7, |
| 50 | tg0d_8, tg0d_8, tg0d_8, tg0d_8, tg0d_9, tg0d_9, tg0d_9, tg0d_9, tg0d_a, tg0d_a, tg0d_a, tg0d_a, tg0d_b, tg0d_b, tg0d_b, tg0d_b, tg0d_c, tg0d_c, tg0d_c, tg0d_c, tg0d_d, tg0d_d, tg0d_d, tg0d_d, tg0d_e, tg0d_e, tg0d_e, tg0d_e, tg0d_f, tg0d_f, tg0d_f, tg0d_f, |
| 37 | 51 | // #define THUMB_BLOP_LO ((UINT16)0x0800) |
| 38 | | tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, |
| 52 | tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, tg0e_0, |
| 53 | tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, tg0e_1, |
| 39 | 54 | // #define THUMB_BLOP_LO ((UINT16)0x0800) |
| 40 | | tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, |
| 55 | tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, tg0f_0, |
| 56 | tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, tg0f_1, |
| 41 | 57 | }; |
| 42 | 58 | |
| 43 | 59 | /* Shift operations */ |
| 44 | 60 | |
| 45 | | const void tg00_0(arm_state *arm, UINT32 pc, UINT32 insn) /* Shift left */ |
| 61 | const void tg00_0(arm_state *arm, UINT32 pc, UINT32 op) /* Shift left */ |
| 46 | 62 | { |
| 47 | 63 | UINT32 rs, rd, rrs; |
| 48 | 64 | INT32 offs; |
| 49 | 65 | |
| 50 | 66 | SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK)); |
| 51 | 67 | |
| 52 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 53 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 68 | rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 69 | rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 54 | 70 | rrs = GET_REGISTER(arm, rs); |
| 55 | | offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 71 | offs = (op & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 56 | 72 | if (offs != 0) |
| 57 | 73 | { |
| 58 | 74 | SET_REGISTER(arm, rd, rrs << offs); |
| r20737 | r20738 | |
| 74 | 90 | R15 += 2; |
| 75 | 91 | } |
| 76 | 92 | |
| 77 | | const void tg00_1(arm_state *arm, UINT32 pc, UINT32 insn) /* Shift right */ |
| 93 | const void tg00_1(arm_state *arm, UINT32 pc, UINT32 op) /* Shift right */ |
| 78 | 94 | { |
| 79 | 95 | UINT32 rs, rd, rrs; |
| 80 | 96 | INT32 offs; |
| 81 | 97 | |
| 82 | | SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK)); |
| 83 | | |
| 84 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 85 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 98 | rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 99 | rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 86 | 100 | rrs = GET_REGISTER(arm, rs); |
| 87 | | offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 101 | offs = (op & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 88 | 102 | if (offs != 0) |
| 89 | 103 | { |
| 90 | 104 | SET_REGISTER(arm, rd, rrs >> offs); |
| r20737 | r20738 | |
| 114 | 128 | R15 += 2; |
| 115 | 129 | } |
| 116 | 130 | |
| 117 | | /* Arithmetic */ |
| 131 | /* Arithmetic */ |
| 118 | 132 | |
| 119 | | const void tg01_0(arm_state *arm, UINT32 pc, UINT32 insn) |
| 133 | const void tg01_0(arm_state *arm, UINT32 pc, UINT32 op) |
| 120 | 134 | { |
| 121 | 135 | UINT32 rs, rd, rrs; |
| 122 | 136 | INT32 offs; |
| 123 | 137 | /* ASR.. */ |
| 124 | | //if (insn & THUMB_SHIFT_R) /* Shift right */ |
| 138 | //if (op & THUMB_SHIFT_R) /* Shift right */ |
| 125 | 139 | { |
| 126 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 127 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 140 | rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 141 | rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 128 | 142 | rrs = GET_REGISTER(arm, rs); |
| 129 | | offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 143 | offs = (op & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 130 | 144 | if (offs == 0) |
| 131 | 145 | { |
| 132 | 146 | offs = 32; |
| r20737 | r20738 | |
| 164 | 178 | } |
| 165 | 179 | } |
| 166 | 180 | |
| 167 | | const void tg01_10(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD Rd, Rs, Rn */ |
| 181 | const void tg01_10(arm_state *arm, UINT32 pc, UINT32 op) /* ADD Rd, Rs, Rn */ |
| 168 | 182 | { |
| 169 | | UINT32 rn, rs, rd; |
| 170 | | |
| 171 | | |
| 172 | | rn = GET_REGISTER(arm, (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT); |
| 173 | | rs = GET_REGISTER(arm, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 174 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 183 | UINT32 rn = GET_REGISTER(arm, (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT); |
| 184 | UINT32 rs = GET_REGISTER(arm, (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 185 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 175 | 186 | SET_REGISTER(arm, rd, rs + rn); |
| 176 | 187 | HandleThumbALUAddFlags(GET_REGISTER(arm, rd), rs, rn); |
| 177 | 188 | |
| 178 | 189 | } |
| 179 | 190 | |
| 180 | | const void tg01_11(arm_state *arm, UINT32 pc, UINT32 insn) /* SUB Rd, Rs, Rn */ |
| 191 | const void tg01_11(arm_state *arm, UINT32 pc, UINT32 op) /* SUB Rd, Rs, Rn */ |
| 181 | 192 | { |
| 182 | | UINT32 rn, rs, rd; |
| 183 | | |
| 184 | | rn = GET_REGISTER(arm, (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT); |
| 185 | | rs = GET_REGISTER(arm, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 186 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 193 | UINT32 rn = GET_REGISTER(arm, (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT); |
| 194 | UINT32 rs = GET_REGISTER(arm, (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 195 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 187 | 196 | SET_REGISTER(arm, rd, rs - rn); |
| 188 | 197 | HandleThumbALUSubFlags(GET_REGISTER(arm, rd), rs, rn); |
| 189 | 198 | |
| 190 | 199 | } |
| 191 | 200 | |
| 192 | | const void tg01_12(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD Rd, Rs, #imm */ |
| 201 | const void tg01_12(arm_state *arm, UINT32 pc, UINT32 op) /* ADD Rd, Rs, #imm */ |
| 193 | 202 | { |
| 194 | | UINT32 rs, rd, imm; |
| 195 | | |
| 196 | | imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 197 | | rs = GET_REGISTER(arm, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 198 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 203 | UINT32 imm = (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 204 | UINT32 rs = GET_REGISTER(arm, (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 205 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 199 | 206 | SET_REGISTER(arm, rd, rs + imm); |
| 200 | 207 | HandleThumbALUAddFlags(GET_REGISTER(arm, rd), rs, imm); |
| 201 | 208 | |
| 202 | 209 | } |
| 203 | 210 | |
| 204 | | const void tg01_13(arm_state *arm, UINT32 pc, UINT32 insn) /* SUB Rd, Rs, #imm */ |
| 211 | const void tg01_13(arm_state *arm, UINT32 pc, UINT32 op) /* SUB Rd, Rs, #imm */ |
| 205 | 212 | { |
| 206 | | UINT32 rs, rd, imm; |
| 207 | | |
| 208 | | imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 209 | | rs = GET_REGISTER(arm, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 210 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 213 | UINT32 imm = (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 214 | UINT32 rs = GET_REGISTER(arm, (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); |
| 215 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 211 | 216 | SET_REGISTER(arm, rd, rs - imm); |
| 212 | 217 | HandleThumbALUSubFlags(GET_REGISTER(arm, rd), rs,imm); |
| 213 | 218 | |
| 214 | 219 | } |
| 215 | 220 | |
| 216 | | /* CMP / MOV */ |
| 221 | /* CMP / MOV */ |
| 217 | 222 | |
| 218 | | const void tg02_0(arm_state *arm, UINT32 pc, UINT32 insn) |
| 223 | const void tg02_0(arm_state *arm, UINT32 pc, UINT32 op) |
| 219 | 224 | { |
| 220 | | UINT32 rd, op2; |
| 221 | | |
| 222 | | rd = (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 223 | | op2 = (insn & THUMB_INSN_IMM); |
| 225 | UINT32 rd = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 226 | UINT32 op2 = (op & THUMB_INSN_IMM); |
| 224 | 227 | SET_REGISTER(arm, rd, op2); |
| 225 | 228 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 226 | 229 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 227 | 230 | R15 += 2; |
| 228 | 231 | } |
| 229 | 232 | |
| 230 | | const void tg02_1(arm_state *arm, UINT32 pc, UINT32 insn) |
| 233 | const void tg02_1(arm_state *arm, UINT32 pc, UINT32 op) |
| 231 | 234 | { |
| 232 | | UINT32 rn, rd, op2; |
| 233 | | |
| 234 | | rn = GET_REGISTER(arm, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); |
| 235 | | op2 = insn & THUMB_INSN_IMM; |
| 236 | | rd = rn - op2; |
| 235 | UINT32 rn = GET_REGISTER(arm, (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); |
| 236 | UINT32 op2 = op & THUMB_INSN_IMM; |
| 237 | UINT32 rd = rn - op2; |
| 237 | 238 | HandleThumbALUSubFlags(rd, rn, op2); |
| 238 | | //mame_printf_debug("%08x: xxx Thumb instruction: CMP R%d (%08x), %02x (N=%d, Z=%d, C=%d, V=%d)\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, GET_REGISTER(arm, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT), op2, N_IS_SET(GET_CPSR) ? 1 : 0, Z_IS_SET(GET_CPSR) ? 1 : 0, C_IS_SET(GET_CPSR) ? 1 : 0, V_IS_SET(GET_CPSR) ? 1 : 0); |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | /* ADD/SUB immediate */ |
| 241 | 242 | |
| 242 | | |
| 243 | | /* ADD/SUB immediate */ |
| 244 | | |
| 245 | | const void tg03_0(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD Rd, #Offset8 */ |
| 243 | const void tg03_0(arm_state *arm, UINT32 pc, UINT32 op) /* ADD Rd, #Offset8 */ |
| 246 | 244 | { |
| 247 | | UINT32 rn, rd, op2; |
| 248 | | |
| 249 | | rn = GET_REGISTER(arm, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); |
| 250 | | op2 = insn & THUMB_INSN_IMM; |
| 251 | | rd = rn + op2; |
| 252 | | //mame_printf_debug("%08x: Thumb instruction: ADD R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2); |
| 253 | | SET_REGISTER(arm, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd); |
| 245 | UINT32 rn = GET_REGISTER(arm, (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); |
| 246 | UINT32 op2 = op & THUMB_INSN_IMM; |
| 247 | UINT32 rd = rn + op2; |
| 248 | SET_REGISTER(arm, (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd); |
| 254 | 249 | HandleThumbALUAddFlags(rd, rn, op2); |
| 255 | 250 | } |
| 256 | 251 | |
| 257 | | const void tg03_1(arm_state *arm, UINT32 pc, UINT32 insn) /* SUB Rd, #Offset8 */ |
| 252 | const void tg03_1(arm_state *arm, UINT32 pc, UINT32 op) /* SUB Rd, #Offset8 */ |
| 258 | 253 | { |
| 259 | | UINT32 rn, rd, op2; |
| 260 | | |
| 261 | | rn = GET_REGISTER(arm, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); |
| 262 | | op2 = insn & THUMB_INSN_IMM; |
| 263 | | //mame_printf_debug("%08x: Thumb instruction: SUB R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2); |
| 264 | | rd = rn - op2; |
| 265 | | SET_REGISTER(arm, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd); |
| 254 | UINT32 rn = GET_REGISTER(arm, (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); |
| 255 | UINT32 op2 = op & THUMB_INSN_IMM; |
| 256 | UINT32 rd = rn - op2; |
| 257 | SET_REGISTER(arm, (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd); |
| 266 | 258 | HandleThumbALUSubFlags(rd, rn, op2); |
| 267 | 259 | } |
| 268 | 260 | |
| 261 | /* Rd & Rm instructions */ |
| 269 | 262 | |
| 270 | | |
| 271 | | /* Rd & Rm instructions */ |
| 272 | | |
| 273 | | const void tg04_00_00(arm_state *arm, UINT32 pc, UINT32 insn) /* AND Rd, Rs */ |
| 263 | const void tg04_00_00(arm_state *arm, UINT32 pc, UINT32 op) /* AND Rd, Rs */ |
| 274 | 264 | { |
| 275 | | UINT32 rs, rd; |
| 276 | | |
| 277 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 278 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 265 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 266 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 279 | 267 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rd) & GET_REGISTER(arm, rs)); |
| 280 | 268 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 281 | 269 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 282 | 270 | R15 += 2; |
| 283 | | |
| 284 | 271 | } |
| 285 | 272 | |
| 286 | | const void tg04_00_01(arm_state *arm, UINT32 pc, UINT32 insn) /* EOR Rd, Rs */ |
| 273 | const void tg04_00_01(arm_state *arm, UINT32 pc, UINT32 op) /* EOR Rd, Rs */ |
| 287 | 274 | { |
| 288 | | UINT32 rs, rd; |
| 289 | | |
| 290 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 291 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 275 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 276 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 292 | 277 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rd) ^ GET_REGISTER(arm, rs)); |
| 293 | 278 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 294 | 279 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 295 | 280 | R15 += 2; |
| 296 | | |
| 297 | 281 | } |
| 298 | 282 | |
| 299 | | const void tg04_00_02(arm_state *arm, UINT32 pc, UINT32 insn) /* LSL Rd, Rs */ |
| 283 | const void tg04_00_02(arm_state *arm, UINT32 pc, UINT32 op) /* LSL Rd, Rs */ |
| 300 | 284 | { |
| 301 | | UINT32 rs, rd, rrd; |
| 302 | | INT32 offs; |
| 303 | | |
| 304 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 305 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 306 | | rrd = GET_REGISTER(arm, rd); |
| 307 | | offs = GET_REGISTER(arm, rs) & 0x000000ff; |
| 285 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 286 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 287 | UINT32 rrd = GET_REGISTER(arm, rd); |
| 288 | INT32 offs = GET_REGISTER(arm, rs) & 0x000000ff; |
| 308 | 289 | if (offs > 0) |
| 309 | 290 | { |
| 310 | 291 | if (offs < 32) |
| r20737 | r20738 | |
| 340 | 321 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 341 | 322 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 342 | 323 | R15 += 2; |
| 343 | | |
| 344 | 324 | } |
| 345 | 325 | |
| 346 | | const void tg04_00_03(arm_state *arm, UINT32 pc, UINT32 insn) /* LSR Rd, Rs */ |
| 326 | const void tg04_00_03(arm_state *arm, UINT32 pc, UINT32 op) /* LSR Rd, Rs */ |
| 347 | 327 | { |
| 348 | | UINT32 rs, rd, rrd; |
| 349 | | INT32 offs; |
| 350 | | |
| 351 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 352 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 353 | | rrd = GET_REGISTER(arm, rd); |
| 354 | | offs = GET_REGISTER(arm, rs) & 0x000000ff; |
| 328 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 329 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 330 | UINT32 rrd = GET_REGISTER(arm, rd); |
| 331 | INT32 offs = GET_REGISTER(arm, rs) & 0x000000ff; |
| 355 | 332 | if (offs > 0) |
| 356 | 333 | { |
| 357 | 334 | if (offs < 32) |
| r20737 | r20738 | |
| 387 | 364 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 388 | 365 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 389 | 366 | R15 += 2; |
| 390 | | |
| 391 | 367 | } |
| 392 | 368 | |
| 393 | | const void tg04_00_04(arm_state *arm, UINT32 pc, UINT32 insn) /* ASR Rd, Rs */ |
| 369 | const void tg04_00_04(arm_state *arm, UINT32 pc, UINT32 op) /* ASR Rd, Rs */ |
| 394 | 370 | { |
| 395 | | UINT32 rs, rd, rrs, rrd; |
| 396 | | |
| 397 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 398 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 399 | | rrs = GET_REGISTER(arm, rs)&0xff; |
| 400 | | rrd = GET_REGISTER(arm, rd); |
| 371 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 372 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 373 | UINT32 rrs = GET_REGISTER(arm, rs)&0xff; |
| 374 | UINT32 rrd = GET_REGISTER(arm, rd); |
| 401 | 375 | if (rrs != 0) |
| 402 | 376 | { |
| 403 | 377 | if (rrs >= 32) |
| r20737 | r20738 | |
| 430 | 404 | SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK)); |
| 431 | 405 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 432 | 406 | R15 += 2; |
| 433 | | |
| 434 | 407 | } |
| 435 | 408 | |
| 436 | | const void tg04_00_05(arm_state *arm, UINT32 pc, UINT32 insn) /* ADC Rd, Rs */ |
| 409 | const void tg04_00_05(arm_state *arm, UINT32 pc, UINT32 op) /* ADC Rd, Rs */ |
| 437 | 410 | { |
| 438 | | UINT32 rn, rs, rd, op2; |
| 439 | | |
| 440 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 441 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 442 | | op2=(GET_CPSR & C_MASK) ? 1 : 0; |
| 443 | | rn=GET_REGISTER(arm, rd) + GET_REGISTER(arm, rs) + op2; |
| 411 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 412 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 413 | UINT32 op2 = (GET_CPSR & C_MASK) ? 1 : 0; |
| 414 | UINT32 rn = GET_REGISTER(arm, rd) + GET_REGISTER(arm, rs) + op2; |
| 444 | 415 | HandleThumbALUAddFlags(rn, GET_REGISTER(arm, rd), (GET_REGISTER(arm, rs))); // ? |
| 445 | 416 | SET_REGISTER(arm, rd, rn); |
| 446 | | |
| 447 | 417 | } |
| 448 | 418 | |
| 449 | | const void tg04_00_06(arm_state *arm, UINT32 pc, UINT32 insn) /* SBC Rd, Rs */ |
| 419 | const void tg04_00_06(arm_state *arm, UINT32 pc, UINT32 op) /* SBC Rd, Rs */ |
| 450 | 420 | { |
| 451 | | UINT32 rn, rs, rd, op2; |
| 452 | | |
| 453 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 454 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 455 | | op2=(GET_CPSR & C_MASK) ? 0 : 1; |
| 456 | | rn=GET_REGISTER(arm, rd) - GET_REGISTER(arm, rs) - op2; |
| 421 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 422 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 423 | UINT32 op2 = (GET_CPSR & C_MASK) ? 0 : 1; |
| 424 | UINT32 rn = GET_REGISTER(arm, rd) - GET_REGISTER(arm, rs) - op2; |
| 457 | 425 | HandleThumbALUSubFlags(rn, GET_REGISTER(arm, rd), (GET_REGISTER(arm, rs))); //? |
| 458 | 426 | SET_REGISTER(arm, rd, rn); |
| 459 | | |
| 460 | 427 | } |
| 461 | 428 | |
| 462 | | const void tg04_00_07(arm_state *arm, UINT32 pc, UINT32 insn) /* ROR Rd, Rs */ |
| 429 | const void tg04_00_07(arm_state *arm, UINT32 pc, UINT32 op) /* ROR Rd, Rs */ |
| 463 | 430 | { |
| 464 | | UINT32 rs, rd, imm, rrd; |
| 465 | | |
| 466 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 467 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 468 | | rrd = GET_REGISTER(arm, rd); |
| 469 | | imm = GET_REGISTER(arm, rs) & 0x0000001f; |
| 431 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 432 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 433 | UINT32 rrd = GET_REGISTER(arm, rd); |
| 434 | UINT32 imm = GET_REGISTER(arm, rs) & 0x0000001f; |
| 470 | 435 | SET_REGISTER(arm, rd, (rrd >> imm) | (rrd << (32 - imm))); |
| 471 | 436 | if (rrd & (1 << (imm - 1))) |
| 472 | 437 | { |
| r20737 | r20738 | |
| 479 | 444 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 480 | 445 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 481 | 446 | R15 += 2; |
| 482 | | |
| 483 | 447 | } |
| 484 | 448 | |
| 485 | | const void tg04_00_08(arm_state *arm, UINT32 pc, UINT32 insn) /* TST Rd, Rs */ |
| 449 | const void tg04_00_08(arm_state *arm, UINT32 pc, UINT32 op) /* TST Rd, Rs */ |
| 486 | 450 | { |
| 487 | | UINT32 rs, rd; |
| 488 | | |
| 489 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 490 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 451 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 452 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 491 | 453 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 492 | 454 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd) & GET_REGISTER(arm, rs))); |
| 493 | 455 | R15 += 2; |
| 494 | | |
| 495 | 456 | } |
| 496 | 457 | |
| 497 | | const void tg04_00_09(arm_state *arm, UINT32 pc, UINT32 insn) /* NEG Rd, Rs */ |
| 458 | const void tg04_00_09(arm_state *arm, UINT32 pc, UINT32 op) /* NEG Rd, Rs */ |
| 498 | 459 | { |
| 499 | | UINT32 rn, rs, rd, rrs; |
| 500 | | |
| 501 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 502 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 503 | | rrs = GET_REGISTER(arm, rs); |
| 504 | | rn = 0 - rrs; |
| 505 | | SET_REGISTER(arm, rd, rn); |
| 460 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 461 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 462 | UINT32 rrs = GET_REGISTER(arm, rs); |
| 463 | SET_REGISTER(arm, rd, 0 - rrs); |
| 506 | 464 | HandleThumbALUSubFlags(GET_REGISTER(arm, rd), 0, rrs); |
| 507 | | |
| 508 | 465 | } |
| 509 | 466 | |
| 510 | | const void tg04_00_0a(arm_state *arm, UINT32 pc, UINT32 insn) /* CMP Rd, Rs */ |
| 467 | const void tg04_00_0a(arm_state *arm, UINT32 pc, UINT32 op) /* CMP Rd, Rs */ |
| 511 | 468 | { |
| 512 | | UINT32 rn, rs, rd; |
| 513 | | |
| 514 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 515 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 516 | | rn = GET_REGISTER(arm, rd) - GET_REGISTER(arm, rs); |
| 469 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 470 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 471 | UINT32 rn = GET_REGISTER(arm, rd) - GET_REGISTER(arm, rs); |
| 517 | 472 | HandleThumbALUSubFlags(rn, GET_REGISTER(arm, rd), GET_REGISTER(arm, rs)); |
| 518 | | |
| 519 | 473 | } |
| 520 | 474 | |
| 521 | | |
| 522 | | const void tg04_00_0b(arm_state *arm, UINT32 pc, UINT32 insn) /* CMN Rd, Rs - check flags, add dasm */ |
| 475 | const void tg04_00_0b(arm_state *arm, UINT32 pc, UINT32 op) /* CMN Rd, Rs - check flags, add dasm */ |
| 523 | 476 | { |
| 524 | | UINT32 rn, rs, rd; |
| 525 | | |
| 526 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 527 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 528 | | rn = GET_REGISTER(arm, rd) + GET_REGISTER(arm, rs); |
| 477 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 478 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 479 | UINT32 rn = GET_REGISTER(arm, rd) + GET_REGISTER(arm, rs); |
| 529 | 480 | HandleThumbALUAddFlags(rn, GET_REGISTER(arm, rd), GET_REGISTER(arm, rs)); |
| 530 | | |
| 531 | 481 | } |
| 532 | 482 | |
| 533 | | const void tg04_00_0c(arm_state *arm, UINT32 pc, UINT32 insn) /* ORR Rd, Rs */ |
| 483 | const void tg04_00_0c(arm_state *arm, UINT32 pc, UINT32 op) /* ORR Rd, Rs */ |
| 534 | 484 | { |
| 535 | | UINT32 rs, rd; |
| 536 | | |
| 537 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 538 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 485 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 486 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 539 | 487 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rd) | GET_REGISTER(arm, rs)); |
| 540 | 488 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 541 | 489 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 542 | 490 | R15 += 2; |
| 543 | | |
| 544 | 491 | } |
| 545 | 492 | |
| 546 | | const void tg04_00_0d(arm_state *arm, UINT32 pc, UINT32 insn) /* MUL Rd, Rs */ |
| 493 | const void tg04_00_0d(arm_state *arm, UINT32 pc, UINT32 op) /* MUL Rd, Rs */ |
| 547 | 494 | { |
| 548 | | UINT32 rn, rs, rd; |
| 549 | | |
| 550 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 551 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 552 | | rn = GET_REGISTER(arm, rd) * GET_REGISTER(arm, rs); |
| 495 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 496 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 497 | UINT32 rn = GET_REGISTER(arm, rd) * GET_REGISTER(arm, rs); |
| 553 | 498 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 554 | 499 | SET_REGISTER(arm, rd, rn); |
| 555 | 500 | SET_CPSR(GET_CPSR | HandleALUNZFlags(rn)); |
| 556 | 501 | R15 += 2; |
| 557 | | |
| 558 | 502 | } |
| 559 | 503 | |
| 560 | | const void tg04_00_0e(arm_state *arm, UINT32 pc, UINT32 insn) /* BIC Rd, Rs */ |
| 504 | const void tg04_00_0e(arm_state *arm, UINT32 pc, UINT32 op) /* BIC Rd, Rs */ |
| 561 | 505 | { |
| 562 | | UINT32 rs, rd; |
| 563 | | |
| 564 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 565 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 506 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 507 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 566 | 508 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rd) & (~GET_REGISTER(arm, rs))); |
| 567 | 509 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 568 | 510 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 569 | 511 | R15 += 2; |
| 570 | | |
| 571 | 512 | } |
| 572 | | const void tg04_00_0f(arm_state *arm, UINT32 pc, UINT32 insn) /* MVN Rd, Rs */ |
| 573 | | { |
| 574 | | UINT32 rs, rd, op2; |
| 575 | 513 | |
| 576 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 577 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 578 | | op2 = GET_REGISTER(arm, rs); |
| 514 | const void tg04_00_0f(arm_state *arm, UINT32 pc, UINT32 op) /* MVN Rd, Rs */ |
| 515 | { |
| 516 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 517 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 518 | UINT32 op2 = GET_REGISTER(arm, rs); |
| 579 | 519 | SET_REGISTER(arm, rd, ~op2); |
| 580 | 520 | SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); |
| 581 | 521 | SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(arm, rd))); |
| 582 | 522 | R15 += 2; |
| 583 | | |
| 584 | 523 | } |
| 585 | 524 | |
| 586 | 525 | /* ADD Rd, Rs group */ |
| 587 | 526 | |
| 588 | | const void tg04_01_00(arm_state *arm, UINT32 pc, UINT32 insn) |
| 527 | const void tg04_01_00(arm_state *arm, UINT32 pc, UINT32 op) |
| 589 | 528 | { |
| 590 | | // UINT32 rs, rd; |
| 591 | | // rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 592 | | // rd = insn & THUMB_HIREG_RD; |
| 593 | | |
| 594 | | |
| 595 | | fatalerror("%08x: G4-1-0 Undefined Thumb instruction: %04x %x\n", pc, insn, (insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT); |
| 596 | | |
| 597 | | R15 += 2; |
| 598 | | |
| 529 | fatalerror("%08x: G4-1-0 Undefined Thumb instruction: %04x %x\n", pc, op, (op & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT); |
| 599 | 530 | } |
| 600 | 531 | |
| 601 | | const void tg04_01_01(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD Rd, HRs */ |
| 532 | const void tg04_01_01(arm_state *arm, UINT32 pc, UINT32 op) /* ADD Rd, HRs */ |
| 602 | 533 | { |
| 603 | | UINT32 rs, rd; |
| 604 | | rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 605 | | rd = insn & THUMB_HIREG_RD; |
| 606 | | |
| 607 | | |
| 534 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 535 | UINT32 rd = op & THUMB_HIREG_RD; |
| 608 | 536 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rd) + GET_REGISTER(arm, rs+8)); |
| 609 | 537 | // emulate the effects of pre-fetch |
| 610 | 538 | if (rs == 7) |
| r20737 | r20738 | |
| 615 | 543 | R15 += 2; |
| 616 | 544 | } |
| 617 | 545 | |
| 618 | | const void tg04_01_02(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD HRd, Rs */ |
| 546 | const void tg04_01_02(arm_state *arm, UINT32 pc, UINT32 op) /* ADD HRd, Rs */ |
| 619 | 547 | { |
| 620 | | UINT32 rs, rd; |
| 621 | | rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 622 | | rd = insn & THUMB_HIREG_RD; |
| 623 | | |
| 624 | | |
| 548 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 549 | UINT32 rd = op & THUMB_HIREG_RD; |
| 625 | 550 | SET_REGISTER(arm, rd+8, GET_REGISTER(arm, rd+8) + GET_REGISTER(arm, rs)); |
| 626 | 551 | if (rd == 7) |
| 627 | 552 | { |
| r20737 | r20738 | |
| 631 | 556 | R15 += 2; |
| 632 | 557 | } |
| 633 | 558 | |
| 634 | | const void tg04_01_03(arm_state *arm, UINT32 pc, UINT32 insn) /* Add HRd, HRs */ |
| 559 | const void tg04_01_03(arm_state *arm, UINT32 pc, UINT32 op) /* Add HRd, HRs */ |
| 635 | 560 | { |
| 636 | | UINT32 rs, rd; |
| 637 | | rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 638 | | rd = insn & THUMB_HIREG_RD; |
| 639 | | |
| 640 | | |
| 561 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 562 | UINT32 rd = op & THUMB_HIREG_RD; |
| 641 | 563 | SET_REGISTER(arm, rd+8, GET_REGISTER(arm, rd+8) + GET_REGISTER(arm, rs+8)); |
| 642 | 564 | // emulate the effects of pre-fetch |
| 643 | 565 | if (rs == 7) |
| r20737 | r20738 | |
| 652 | 574 | R15 += 2; |
| 653 | 575 | } |
| 654 | 576 | |
| 655 | | |
| 656 | | const void tg04_01_10(arm_state *arm, UINT32 pc, UINT32 insn) /* CMP Rd, Rs */ |
| 577 | const void tg04_01_10(arm_state *arm, UINT32 pc, UINT32 op) /* CMP Rd, Rs */ |
| 657 | 578 | { |
| 658 | | UINT32 rn, rs, rd; |
| 659 | | |
| 660 | | rs = GET_REGISTER(arm, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); |
| 661 | | rd = GET_REGISTER(arm, insn & THUMB_HIREG_RD); |
| 662 | | rn = rd - rs; |
| 579 | UINT32 rs = GET_REGISTER(arm, ((op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); |
| 580 | UINT32 rd = GET_REGISTER(arm, op & THUMB_HIREG_RD); |
| 581 | UINT32 rn = rd - rs; |
| 663 | 582 | HandleThumbALUSubFlags(rn, rd, rs); |
| 664 | | |
| 665 | 583 | } |
| 666 | 584 | |
| 667 | | const void tg04_01_11(arm_state *arm, UINT32 pc, UINT32 insn) /* CMP Rd, Hs */ |
| 585 | const void tg04_01_11(arm_state *arm, UINT32 pc, UINT32 op) /* CMP Rd, Hs */ |
| 668 | 586 | { |
| 669 | | UINT32 rn, rs, rd; |
| 670 | | |
| 671 | | rs = GET_REGISTER(arm, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); |
| 672 | | rd = GET_REGISTER(arm, insn & THUMB_HIREG_RD); |
| 673 | | rn = rd - rs; |
| 587 | UINT32 rs = GET_REGISTER(arm, ((op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); |
| 588 | UINT32 rd = GET_REGISTER(arm, op & THUMB_HIREG_RD); |
| 589 | UINT32 rn = rd - rs; |
| 674 | 590 | HandleThumbALUSubFlags(rn, rd, rs); |
| 675 | | |
| 676 | 591 | } |
| 677 | 592 | |
| 678 | | const void tg04_01_12(arm_state *arm, UINT32 pc, UINT32 insn) /* CMP Hd, Rs */ |
| 593 | const void tg04_01_12(arm_state *arm, UINT32 pc, UINT32 op) /* CMP Hd, Rs */ |
| 679 | 594 | { |
| 680 | | UINT32 rn, rs, rd; |
| 681 | | |
| 682 | | rs = GET_REGISTER(arm, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); |
| 683 | | rd = GET_REGISTER(arm, (insn & THUMB_HIREG_RD) + 8); |
| 684 | | rn = rd - rs; |
| 595 | UINT32 rs = GET_REGISTER(arm, ((op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); |
| 596 | UINT32 rd = GET_REGISTER(arm, (op & THUMB_HIREG_RD) + 8); |
| 597 | UINT32 rn = rd - rs; |
| 685 | 598 | HandleThumbALUSubFlags(rn, rd, rs); |
| 686 | | |
| 687 | 599 | } |
| 688 | 600 | |
| 689 | | const void tg04_01_13(arm_state *arm, UINT32 pc, UINT32 insn) /* CMP Hd, Hs */ |
| 601 | const void tg04_01_13(arm_state *arm, UINT32 pc, UINT32 op) /* CMP Hd, Hs */ |
| 690 | 602 | { |
| 691 | | UINT32 rn, rs, rd; |
| 692 | | |
| 693 | | rs = GET_REGISTER(arm, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); |
| 694 | | rd = GET_REGISTER(arm, (insn & THUMB_HIREG_RD) + 8); |
| 695 | | rn = rd - rs; |
| 603 | UINT32 rs = GET_REGISTER(arm, ((op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); |
| 604 | UINT32 rd = GET_REGISTER(arm, (op & THUMB_HIREG_RD) + 8); |
| 605 | UINT32 rn = rd - rs; |
| 696 | 606 | HandleThumbALUSubFlags(rn, rd, rs); |
| 697 | | |
| 698 | 607 | } |
| 699 | 608 | |
| 700 | | /* MOV group */ |
| 609 | /* MOV group */ |
| 701 | 610 | |
| 702 | 611 | // "The action of H1 = 0, H2 = 0 for Op = 00 (ADD), Op = 01 (CMP) and Op = 10 (MOV) is undefined, and should not be used." |
| 703 | | const void tg04_01_20(arm_state *arm, UINT32 pc, UINT32 insn) /* MOV Rd, Rs (undefined) */ |
| 612 | const void tg04_01_20(arm_state *arm, UINT32 pc, UINT32 op) /* MOV Rd, Rs (undefined) */ |
| 704 | 613 | { |
| 705 | | UINT32 rs, rd; |
| 706 | | |
| 707 | | |
| 708 | | rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 709 | | rd = insn & THUMB_HIREG_RD; |
| 614 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 615 | UINT32 rd = op & THUMB_HIREG_RD; |
| 710 | 616 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rs)); |
| 711 | 617 | R15 += 2; |
| 712 | | |
| 713 | 618 | } |
| 714 | 619 | |
| 715 | | const void tg04_01_21(arm_state *arm, UINT32 pc, UINT32 insn) /* MOV Rd, Hs */ |
| 620 | const void tg04_01_21(arm_state *arm, UINT32 pc, UINT32 op) /* MOV Rd, Hs */ |
| 716 | 621 | { |
| 717 | | UINT32 rs, rd; |
| 718 | | |
| 719 | | rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 720 | | rd = insn & THUMB_HIREG_RD; |
| 622 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 623 | UINT32 rd = op & THUMB_HIREG_RD; |
| 624 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rs + 8)); |
| 721 | 625 | if (rs == 7) |
| 722 | 626 | { |
| 723 | | SET_REGISTER(arm, rd, GET_REGISTER(arm, rs + 8) + 4); |
| 627 | SET_REGISTER(arm, rd, GET_REGISTER(arm, rd) + 4); |
| 724 | 628 | } |
| 725 | | else |
| 726 | | { |
| 727 | | SET_REGISTER(arm, rd, GET_REGISTER(arm, rs + 8)); |
| 728 | | } |
| 729 | 629 | R15 += 2; |
| 730 | | |
| 731 | 630 | } |
| 732 | 631 | |
| 733 | | const void tg04_01_22(arm_state *arm, UINT32 pc, UINT32 insn) /* MOV Hd, Rs */ |
| 632 | const void tg04_01_22(arm_state *arm, UINT32 pc, UINT32 op) /* MOV Hd, Rs */ |
| 734 | 633 | { |
| 735 | | UINT32 rs, rd; |
| 736 | | |
| 737 | | rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 738 | | rd = insn & THUMB_HIREG_RD; |
| 634 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 635 | UINT32 rd = op & THUMB_HIREG_RD; |
| 739 | 636 | SET_REGISTER(arm, rd + 8, GET_REGISTER(arm, rs)); |
| 740 | 637 | if (rd != 7) |
| 741 | 638 | { |
| r20737 | r20738 | |
| 745 | 642 | { |
| 746 | 643 | R15 &= ~1; |
| 747 | 644 | } |
| 748 | | |
| 749 | 645 | } |
| 750 | 646 | |
| 751 | | const void tg04_01_23(arm_state *arm, UINT32 pc, UINT32 insn) /* MOV Hd, Hs */ |
| 647 | const void tg04_01_23(arm_state *arm, UINT32 pc, UINT32 op) /* MOV Hd, Hs */ |
| 752 | 648 | { |
| 753 | | UINT32 rs, rd; |
| 754 | | |
| 755 | | rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 756 | | rd = insn & THUMB_HIREG_RD; |
| 649 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 650 | UINT32 rd = op & THUMB_HIREG_RD; |
| 757 | 651 | if (rs == 7) |
| 758 | 652 | { |
| 759 | 653 | SET_REGISTER(arm, rd + 8, GET_REGISTER(arm, rs+8)+4); |
| r20737 | r20738 | |
| 766 | 660 | { |
| 767 | 661 | R15 += 2; |
| 768 | 662 | } |
| 769 | | if (rd == 7) |
| 663 | else |
| 770 | 664 | { |
| 771 | 665 | R15 &= ~1; |
| 772 | 666 | } |
| 773 | | |
| 774 | 667 | } |
| 775 | 668 | |
| 776 | | |
| 777 | | const void tg04_01_30(arm_state *arm, UINT32 pc, UINT32 insn) |
| 669 | const void tg04_01_30(arm_state *arm, UINT32 pc, UINT32 op) |
| 778 | 670 | { |
| 779 | | UINT32 addr; |
| 780 | | UINT32 rd; |
| 781 | | |
| 782 | | |
| 783 | | rd = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 784 | | addr = GET_REGISTER(arm, rd); |
| 671 | UINT32 rd = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 672 | UINT32 addr = GET_REGISTER(arm, rd); |
| 785 | 673 | if (addr & 1) |
| 786 | 674 | { |
| 787 | 675 | addr &= ~1; |
| r20737 | r20738 | |
| 795 | 683 | } |
| 796 | 684 | } |
| 797 | 685 | R15 = addr; |
| 798 | | |
| 799 | 686 | } |
| 800 | 687 | |
| 801 | | const void tg04_01_31(arm_state *arm, UINT32 pc, UINT32 insn) |
| 688 | const void tg04_01_31(arm_state *arm, UINT32 pc, UINT32 op) |
| 802 | 689 | { |
| 803 | | UINT32 addr; |
| 804 | | |
| 805 | | |
| 806 | | addr = GET_REGISTER(arm, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); |
| 807 | | if ((((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8) == 15) |
| 690 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 691 | UINT32 addr = GET_REGISTER(arm, rs+8); |
| 692 | if (rs == 7) |
| 808 | 693 | { |
| 809 | 694 | addr += 2; |
| 810 | 695 | } |
| r20737 | r20738 | |
| 821 | 706 | } |
| 822 | 707 | } |
| 823 | 708 | R15 = addr; |
| 824 | | |
| 825 | 709 | } |
| 826 | 710 | |
| 827 | | const void tg04_01_32(arm_state *arm, UINT32 pc, UINT32 insn) |
| 711 | const void tg04_01_32(arm_state *arm, UINT32 pc, UINT32 op) |
| 828 | 712 | { |
| 829 | | // UINT32 addr; |
| 830 | | // UINT32 rd; |
| 831 | | |
| 832 | | |
| 833 | | fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, insn); |
| 834 | | R15 += 2; |
| 835 | | |
| 713 | fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, op); |
| 836 | 714 | } |
| 837 | 715 | |
| 838 | | const void tg04_01_33(arm_state *arm, UINT32 pc, UINT32 insn) |
| 716 | const void tg04_01_33(arm_state *arm, UINT32 pc, UINT32 op) |
| 839 | 717 | { |
| 840 | | // UINT32 addr; |
| 841 | | // UINT32 rd; |
| 842 | | |
| 843 | | |
| 844 | | fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, insn); |
| 845 | | R15 += 2; |
| 846 | | |
| 718 | fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, op); |
| 847 | 719 | } |
| 848 | 720 | |
| 849 | | |
| 850 | | |
| 851 | | |
| 852 | | |
| 853 | | |
| 854 | | const void tg04_0203(arm_state *arm, UINT32 pc, UINT32 insn) |
| 721 | const void tg04_0203(arm_state *arm, UINT32 pc, UINT32 op) |
| 855 | 722 | { |
| 856 | | UINT32 readword; |
| 857 | | |
| 858 | | readword = READ32((R15 & ~2) + 4 + ((insn & THUMB_INSN_IMM) << 2)); |
| 859 | | SET_REGISTER(arm, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, readword); |
| 723 | UINT32 readword = READ32((R15 & ~2) + 4 + ((op & THUMB_INSN_IMM) << 2)); |
| 724 | SET_REGISTER(arm, (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, readword); |
| 860 | 725 | R15 += 2; |
| 861 | 726 | } |
| 862 | 727 | |
| 863 | 728 | /* LDR* STR* group */ |
| 864 | 729 | |
| 865 | | const void tg05_0(arm_state *arm, UINT32 pc, UINT32 insn) /* STR Rd, [Rn, Rm] */ |
| 730 | const void tg05_0(arm_state *arm, UINT32 pc, UINT32 op) /* STR Rd, [Rn, Rm] */ |
| 866 | 731 | { |
| 867 | | UINT32 addr; |
| 868 | | UINT32 rm, rn, rd; |
| 869 | | |
| 870 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 871 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 872 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 873 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 732 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 733 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 734 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 735 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 874 | 736 | WRITE32(addr, GET_REGISTER(arm, rd)); |
| 875 | 737 | R15 += 2; |
| 876 | | |
| 877 | 738 | } |
| 878 | 739 | |
| 879 | | const void tg05_1(arm_state *arm, UINT32 pc, UINT32 insn) /* STRH Rd, [Rn, Rm] */ |
| 740 | const void tg05_1(arm_state *arm, UINT32 pc, UINT32 op) /* STRH Rd, [Rn, Rm] */ |
| 880 | 741 | { |
| 881 | | UINT32 addr; |
| 882 | | UINT32 rm, rn, rd; |
| 883 | | |
| 884 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 885 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 886 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 887 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 742 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 743 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 744 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 745 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 888 | 746 | WRITE16(addr, GET_REGISTER(arm, rd)); |
| 889 | 747 | R15 += 2; |
| 890 | | |
| 891 | 748 | } |
| 892 | 749 | |
| 893 | | const void tg05_2(arm_state *arm, UINT32 pc, UINT32 insn) /* STRB Rd, [Rn, Rm] */ |
| 750 | const void tg05_2(arm_state *arm, UINT32 pc, UINT32 op) /* STRB Rd, [Rn, Rm] */ |
| 894 | 751 | { |
| 895 | | UINT32 addr; |
| 896 | | UINT32 rm, rn, rd; |
| 897 | | |
| 898 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 899 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 900 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 901 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 752 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 753 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 754 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 755 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 902 | 756 | WRITE8(addr, GET_REGISTER(arm, rd)); |
| 903 | 757 | R15 += 2; |
| 904 | | |
| 905 | 758 | } |
| 906 | 759 | |
| 907 | | const void tg05_3(arm_state *arm, UINT32 pc, UINT32 insn) /* LDSB Rd, [Rn, Rm] todo, add dasm */ |
| 760 | const void tg05_3(arm_state *arm, UINT32 pc, UINT32 op) /* LDSB Rd, [Rn, Rm] todo, add dasm */ |
| 908 | 761 | { |
| 909 | | UINT32 addr; |
| 910 | | UINT32 rm, rn, rd, op2; |
| 911 | | |
| 912 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 913 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 914 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 915 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 916 | | op2 = READ8(addr); |
| 762 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 763 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 764 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 765 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 766 | UINT32 op2 = READ8(addr); |
| 917 | 767 | if (op2 & 0x00000080) |
| 918 | 768 | { |
| 919 | 769 | op2 |= 0xffffff00; |
| 920 | 770 | } |
| 921 | 771 | SET_REGISTER(arm, rd, op2); |
| 922 | 772 | R15 += 2; |
| 923 | | |
| 924 | 773 | } |
| 925 | 774 | |
| 926 | | const void tg05_4(arm_state *arm, UINT32 pc, UINT32 insn) /* LDR Rd, [Rn, Rm] */ |
| 775 | const void tg05_4(arm_state *arm, UINT32 pc, UINT32 op) /* LDR Rd, [Rn, Rm] */ |
| 927 | 776 | { |
| 928 | | UINT32 addr; |
| 929 | | UINT32 rm, rn, rd, op2; |
| 930 | | |
| 931 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 932 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 933 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 934 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 935 | | op2 = READ32(addr); |
| 777 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 778 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 779 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 780 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 781 | UINT32 op2 = READ32(addr); |
| 936 | 782 | SET_REGISTER(arm, rd, op2); |
| 937 | 783 | R15 += 2; |
| 938 | | |
| 939 | 784 | } |
| 940 | 785 | |
| 941 | | const void tg05_5(arm_state *arm, UINT32 pc, UINT32 insn) /* LDRH Rd, [Rn, Rm] */ |
| 786 | const void tg05_5(arm_state *arm, UINT32 pc, UINT32 op) /* LDRH Rd, [Rn, Rm] */ |
| 942 | 787 | { |
| 943 | | UINT32 addr; |
| 944 | | UINT32 rm, rn, rd, op2; |
| 945 | | |
| 946 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 947 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 948 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 949 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 950 | | op2 = READ16(addr); |
| 788 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 789 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 790 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 791 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 792 | UINT32 op2 = READ16(addr); |
| 951 | 793 | SET_REGISTER(arm, rd, op2); |
| 952 | 794 | R15 += 2; |
| 953 | | |
| 954 | 795 | } |
| 955 | 796 | |
| 956 | | const void tg05_6(arm_state *arm, UINT32 pc, UINT32 insn) /* LDRB Rd, [Rn, Rm] */ |
| 797 | const void tg05_6(arm_state *arm, UINT32 pc, UINT32 op) /* LDRB Rd, [Rn, Rm] */ |
| 957 | 798 | { |
| 958 | | UINT32 addr; |
| 959 | | UINT32 rm, rn, rd, op2; |
| 960 | | |
| 961 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 962 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 963 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 964 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 965 | | op2 = READ8(addr); |
| 799 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 800 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 801 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 802 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 803 | UINT32 op2 = READ8(addr); |
| 966 | 804 | SET_REGISTER(arm, rd, op2); |
| 967 | 805 | R15 += 2; |
| 968 | | |
| 969 | 806 | } |
| 970 | 807 | |
| 971 | | const void tg05_7(arm_state *arm, UINT32 pc, UINT32 insn) /* LDSH Rd, [Rn, Rm] */ |
| 808 | const void tg05_7(arm_state *arm, UINT32 pc, UINT32 op) /* LDSH Rd, [Rn, Rm] */ |
| 972 | 809 | { |
| 973 | | UINT32 addr; |
| 974 | | UINT32 rm, rn, rd, op2; |
| 975 | | |
| 976 | | rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 977 | | rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 978 | | rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 979 | | addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 980 | | op2 = READ16(addr); |
| 810 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 811 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 812 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 813 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 814 | UINT32 op2 = READ16(addr); |
| 981 | 815 | if (op2 & 0x00008000) |
| 982 | 816 | { |
| 983 | 817 | op2 |= 0xffff0000; |
| 984 | 818 | } |
| 985 | 819 | SET_REGISTER(arm, rd, op2); |
| 986 | 820 | R15 += 2; |
| 987 | | |
| 988 | 821 | } |
| 989 | 822 | |
| 990 | 823 | /* Word Store w/ Immediate Offset */ |
| 991 | 824 | |
| 992 | | const void tg06_0(arm_state *arm, UINT32 pc, UINT32 insn) /* Store */ |
| 825 | const void tg06_0(arm_state *arm, UINT32 pc, UINT32 op) /* Store */ |
| 993 | 826 | { |
| 994 | | UINT32 rn, rd; |
| 995 | | INT32 offs; |
| 996 | | |
| 997 | | rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 998 | | rd = insn & THUMB_ADDSUB_RD; |
| 999 | | offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; |
| 827 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 828 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 829 | INT32 offs = ((op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; |
| 1000 | 830 | WRITE32(GET_REGISTER(arm, rn) + offs, GET_REGISTER(arm, rd)); |
| 1001 | 831 | R15 += 2; |
| 1002 | 832 | } |
| 1003 | 833 | |
| 1004 | | const void tg06_1(arm_state *arm, UINT32 pc, UINT32 insn) /* Load */ |
| 834 | const void tg06_1(arm_state *arm, UINT32 pc, UINT32 op) /* Load */ |
| 1005 | 835 | { |
| 1006 | | UINT32 rn, rd; |
| 1007 | | INT32 offs; |
| 1008 | | |
| 1009 | | rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1010 | | rd = insn & THUMB_ADDSUB_RD; |
| 1011 | | offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; |
| 836 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 837 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 838 | INT32 offs = ((op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; |
| 1012 | 839 | SET_REGISTER(arm, rd, READ32(GET_REGISTER(arm, rn) + offs)); // fix |
| 1013 | 840 | R15 += 2; |
| 1014 | 841 | } |
| 1015 | 842 | |
| 1016 | 843 | /* Byte Store w/ Immeidate Offset */ |
| 1017 | 844 | |
| 1018 | | const void tg07_0(arm_state *arm, UINT32 pc, UINT32 insn) /* Store */ |
| 845 | const void tg07_0(arm_state *arm, UINT32 pc, UINT32 op) /* Store */ |
| 1019 | 846 | { |
| 1020 | | UINT32 rn, rd; |
| 1021 | | INT32 offs; |
| 1022 | | |
| 1023 | | rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1024 | | rd = insn & THUMB_ADDSUB_RD; |
| 1025 | | offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; |
| 847 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 848 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 849 | INT32 offs = (op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; |
| 1026 | 850 | WRITE8(GET_REGISTER(arm, rn) + offs, GET_REGISTER(arm, rd)); |
| 1027 | 851 | R15 += 2; |
| 1028 | 852 | } |
| 1029 | 853 | |
| 1030 | | const void tg07_1(arm_state *arm, UINT32 pc, UINT32 insn) /* Load */ |
| 854 | const void tg07_1(arm_state *arm, UINT32 pc, UINT32 op) /* Load */ |
| 1031 | 855 | { |
| 1032 | | UINT32 rn, rd; |
| 1033 | | INT32 offs; |
| 1034 | | |
| 1035 | | rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1036 | | rd = insn & THUMB_ADDSUB_RD; |
| 1037 | | offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; |
| 856 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 857 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 858 | INT32 offs = (op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; |
| 1038 | 859 | SET_REGISTER(arm, rd, READ8(GET_REGISTER(arm, rn) + offs)); |
| 1039 | 860 | R15 += 2; |
| 1040 | 861 | } |
| 1041 | 862 | |
| 1042 | 863 | /* Load/Store Halfword */ |
| 1043 | 864 | |
| 1044 | | const void tg08_0(arm_state *arm, UINT32 pc, UINT32 insn) /* Store */ |
| 865 | const void tg08_0(arm_state *arm, UINT32 pc, UINT32 op) /* Store */ |
| 1045 | 866 | { |
| 1046 | | UINT32 rs, rd, imm; |
| 1047 | | |
| 1048 | | imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; |
| 1049 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1050 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 867 | UINT32 imm = (op & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; |
| 868 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 869 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 1051 | 870 | WRITE16(GET_REGISTER(arm, rs) + (imm << 1), GET_REGISTER(arm, rd)); |
| 1052 | 871 | R15 += 2; |
| 1053 | 872 | } |
| 1054 | 873 | |
| 1055 | | const void tg08_1(arm_state *arm, UINT32 pc, UINT32 insn) /* Load */ |
| 874 | const void tg08_1(arm_state *arm, UINT32 pc, UINT32 op) /* Load */ |
| 1056 | 875 | { |
| 1057 | | UINT32 rs, rd, imm; |
| 1058 | | |
| 1059 | | imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; |
| 1060 | | rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1061 | | rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 876 | UINT32 imm = (op & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; |
| 877 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 878 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 1062 | 879 | SET_REGISTER(arm, rd, READ16(GET_REGISTER(arm, rs) + (imm << 1))); |
| 1063 | 880 | R15 += 2; |
| 1064 | 881 | } |
| 1065 | 882 | |
| 1066 | | /* Stack-Relative Load/Store */ |
| 883 | /* Stack-Relative Load/Store */ |
| 1067 | 884 | |
| 1068 | | const void tg09_0(arm_state *arm, UINT32 pc, UINT32 insn) /* Store */ |
| 885 | const void tg09_0(arm_state *arm, UINT32 pc, UINT32 op) /* Store */ |
| 1069 | 886 | { |
| 1070 | | UINT32 rd; |
| 1071 | | INT32 offs; |
| 1072 | | |
| 1073 | | rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; |
| 1074 | | offs = (UINT8)(insn & THUMB_INSN_IMM); |
| 887 | UINT32 rd = (op & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; |
| 888 | INT32 offs = (UINT8)(op & THUMB_INSN_IMM); |
| 1075 | 889 | WRITE32(GET_REGISTER(arm, 13) + ((UINT32)offs << 2), GET_REGISTER(arm, rd)); |
| 1076 | 890 | R15 += 2; |
| 1077 | 891 | } |
| 1078 | 892 | |
| 1079 | | const void tg09_1(arm_state *arm, UINT32 pc, UINT32 insn) /* Load */ |
| 893 | const void tg09_1(arm_state *arm, UINT32 pc, UINT32 op) /* Load */ |
| 1080 | 894 | { |
| 1081 | | UINT32 readword; |
| 1082 | | UINT32 rd; |
| 1083 | | INT32 offs; |
| 1084 | | |
| 1085 | | rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; |
| 1086 | | offs = (UINT8)(insn & THUMB_INSN_IMM); |
| 1087 | | readword = READ32(GET_REGISTER(arm, 13) + ((UINT32)offs << 2)); |
| 895 | UINT32 rd = (op & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; |
| 896 | INT32 offs = (UINT8)(op & THUMB_INSN_IMM); |
| 897 | UINT32 readword = READ32(GET_REGISTER(arm, 13) + ((UINT32)offs << 2)); |
| 1088 | 898 | SET_REGISTER(arm, rd, readword); |
| 1089 | 899 | R15 += 2; |
| 1090 | 900 | } |
| 1091 | 901 | |
| 1092 | | /* Get relative address */ |
| 902 | /* Get relative address */ |
| 1093 | 903 | |
| 1094 | | const void tg0a_0(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD Rd, PC, #nn */ |
| 904 | const void tg0a_0(arm_state *arm, UINT32 pc, UINT32 op) /* ADD Rd, PC, #nn */ |
| 1095 | 905 | { |
| 1096 | | UINT32 rd; |
| 1097 | | INT32 offs; |
| 1098 | | |
| 1099 | | rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; |
| 1100 | | offs = (UINT8)(insn & THUMB_INSN_IMM) << 2; |
| 906 | UINT32 rd = (op & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; |
| 907 | INT32 offs = (UINT8)(op & THUMB_INSN_IMM) << 2; |
| 1101 | 908 | SET_REGISTER(arm, rd, ((R15 + 4) & ~2) + offs); |
| 1102 | 909 | R15 += 2; |
| 1103 | 910 | } |
| 1104 | 911 | |
| 1105 | | const void tg0a_1(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD Rd, SP, #nn */ |
| 912 | const void tg0a_1(arm_state *arm, UINT32 pc, UINT32 op) /* ADD Rd, SP, #nn */ |
| 1106 | 913 | { |
| 1107 | | UINT32 rd; |
| 1108 | | INT32 offs; |
| 1109 | | |
| 1110 | | rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; |
| 1111 | | offs = (UINT8)(insn & THUMB_INSN_IMM) << 2; |
| 914 | UINT32 rd = (op & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; |
| 915 | INT32 offs = (UINT8)(op & THUMB_INSN_IMM) << 2; |
| 1112 | 916 | SET_REGISTER(arm, rd, GET_REGISTER(arm, 13) + offs); |
| 1113 | 917 | R15 += 2; |
| 1114 | 918 | } |
| 1115 | 919 | |
| 1116 | 920 | /* Stack-Related Opcodes */ |
| 1117 | 921 | |
| 1118 | | const void tg0b_0(arm_state *arm, UINT32 pc, UINT32 insn) /* ADD SP, #imm */ |
| 922 | const void tg0b_0(arm_state *arm, UINT32 pc, UINT32 op) /* ADD SP, #imm */ |
| 1119 | 923 | { |
| 1120 | | UINT32 addr; |
| 1121 | | |
| 1122 | | |
| 1123 | | addr = (insn & THUMB_INSN_IMM); |
| 924 | UINT32 addr = (op & THUMB_INSN_IMM); |
| 1124 | 925 | addr &= ~THUMB_INSN_IMM_S; |
| 1125 | | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) + ((insn & THUMB_INSN_IMM_S) ? -(addr << 2) : (addr << 2))); |
| 926 | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) + ((op & THUMB_INSN_IMM_S) ? -(addr << 2) : (addr << 2))); |
| 1126 | 927 | R15 += 2; |
| 1127 | | |
| 1128 | 928 | } |
| 1129 | 929 | |
| 1130 | | const void tg0b_1(arm_state *arm, UINT32 pc, UINT32 insn) |
| 930 | const void tg0b_1(arm_state *arm, UINT32 pc, UINT32 op) |
| 1131 | 931 | { |
| 1132 | | // UINT32 addr; |
| 1133 | | // INT32 offs; |
| 1134 | | |
| 1135 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1136 | | R15 += 2; |
| 1137 | | |
| 932 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1138 | 933 | } |
| 1139 | 934 | |
| 1140 | | const void tg0b_2(arm_state *arm, UINT32 pc, UINT32 insn) |
| 935 | const void tg0b_2(arm_state *arm, UINT32 pc, UINT32 op) |
| 1141 | 936 | { |
| 1142 | | // UINT32 addr; |
| 1143 | | // INT32 offs; |
| 1144 | | |
| 1145 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1146 | | R15 += 2; |
| 1147 | | |
| 937 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1148 | 938 | } |
| 1149 | 939 | |
| 1150 | | const void tg0b_3(arm_state *arm, UINT32 pc, UINT32 insn) |
| 940 | const void tg0b_3(arm_state *arm, UINT32 pc, UINT32 op) |
| 1151 | 941 | { |
| 1152 | | // UINT32 addr; |
| 1153 | | // INT32 offs; |
| 1154 | | |
| 1155 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1156 | | R15 += 2; |
| 1157 | | |
| 942 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1158 | 943 | } |
| 1159 | 944 | |
| 1160 | | const void tg0b_4(arm_state *arm, UINT32 pc, UINT32 insn) /* PUSH {Rlist} */ |
| 945 | const void tg0b_4(arm_state *arm, UINT32 pc, UINT32 op) /* PUSH {Rlist} */ |
| 1161 | 946 | { |
| 1162 | | INT32 offs; |
| 1163 | | |
| 1164 | | for (offs = 7; offs >= 0; offs--) |
| 947 | for (INT32 offs = 7; offs >= 0; offs--) |
| 1165 | 948 | { |
| 1166 | | if (insn & (1 << offs)) |
| 949 | if (op & (1 << offs)) |
| 1167 | 950 | { |
| 1168 | 951 | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) - 4); |
| 1169 | 952 | WRITE32(GET_REGISTER(arm, 13), GET_REGISTER(arm, offs)); |
| 1170 | 953 | } |
| 1171 | 954 | } |
| 1172 | 955 | R15 += 2; |
| 1173 | | |
| 1174 | 956 | } |
| 1175 | 957 | |
| 1176 | | const void tg0b_5(arm_state *arm, UINT32 pc, UINT32 insn) /* PUSH {Rlist}{LR} */ |
| 958 | const void tg0b_5(arm_state *arm, UINT32 pc, UINT32 op) /* PUSH {Rlist}{LR} */ |
| 1177 | 959 | { |
| 1178 | | INT32 offs; |
| 1179 | | |
| 1180 | 960 | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) - 4); |
| 1181 | 961 | WRITE32(GET_REGISTER(arm, 13), GET_REGISTER(arm, 14)); |
| 1182 | | for (offs = 7; offs >= 0; offs--) |
| 962 | for (INT32 offs = 7; offs >= 0; offs--) |
| 1183 | 963 | { |
| 1184 | | if (insn & (1 << offs)) |
| 964 | if (op & (1 << offs)) |
| 1185 | 965 | { |
| 1186 | 966 | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) - 4); |
| 1187 | 967 | WRITE32(GET_REGISTER(arm, 13), GET_REGISTER(arm, offs)); |
| 1188 | 968 | } |
| 1189 | 969 | } |
| 1190 | 970 | R15 += 2; |
| 1191 | | |
| 1192 | 971 | } |
| 1193 | 972 | |
| 1194 | | const void tg0b_6(arm_state *arm, UINT32 pc, UINT32 insn) |
| 973 | const void tg0b_6(arm_state *arm, UINT32 pc, UINT32 op) |
| 1195 | 974 | { |
| 1196 | | // UINT32 addr; |
| 1197 | | // INT32 offs; |
| 1198 | | |
| 1199 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1200 | | R15 += 2; |
| 1201 | | |
| 975 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1202 | 976 | } |
| 1203 | 977 | |
| 1204 | | const void tg0b_7(arm_state *arm, UINT32 pc, UINT32 insn) |
| 978 | const void tg0b_7(arm_state *arm, UINT32 pc, UINT32 op) |
| 1205 | 979 | { |
| 1206 | | // UINT32 addr; |
| 1207 | | // INT32 offs; |
| 1208 | | |
| 1209 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1210 | | R15 += 2; |
| 1211 | | |
| 980 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1212 | 981 | } |
| 1213 | 982 | |
| 1214 | | const void tg0b_8(arm_state *arm, UINT32 pc, UINT32 insn) |
| 983 | const void tg0b_8(arm_state *arm, UINT32 pc, UINT32 op) |
| 1215 | 984 | { |
| 1216 | | // UINT32 addr; |
| 1217 | | // INT32 offs; |
| 1218 | | |
| 1219 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1220 | | R15 += 2; |
| 1221 | | |
| 985 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1222 | 986 | } |
| 1223 | 987 | |
| 1224 | | const void tg0b_9(arm_state *arm, UINT32 pc, UINT32 insn) |
| 988 | const void tg0b_9(arm_state *arm, UINT32 pc, UINT32 op) |
| 1225 | 989 | { |
| 1226 | | // UINT32 addr; |
| 1227 | | // INT32 offs; |
| 1228 | | |
| 1229 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1230 | | R15 += 2; |
| 1231 | | |
| 990 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1232 | 991 | } |
| 1233 | 992 | |
| 1234 | | const void tg0b_a(arm_state *arm, UINT32 pc, UINT32 insn) |
| 993 | const void tg0b_a(arm_state *arm, UINT32 pc, UINT32 op) |
| 1235 | 994 | { |
| 1236 | | // UINT32 addr; |
| 1237 | | // INT32 offs; |
| 1238 | | |
| 1239 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1240 | | R15 += 2; |
| 1241 | | |
| 995 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1242 | 996 | } |
| 1243 | 997 | |
| 1244 | | const void tg0b_b(arm_state *arm, UINT32 pc, UINT32 insn) |
| 998 | const void tg0b_b(arm_state *arm, UINT32 pc, UINT32 op) |
| 1245 | 999 | { |
| 1246 | | // UINT32 addr; |
| 1247 | | // INT32 offs; |
| 1248 | | |
| 1249 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1250 | | R15 += 2; |
| 1251 | | |
| 1000 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1252 | 1001 | } |
| 1253 | 1002 | |
| 1254 | | const void tg0b_c(arm_state *arm, UINT32 pc, UINT32 insn) /* POP {Rlist} */ |
| 1003 | const void tg0b_c(arm_state *arm, UINT32 pc, UINT32 op) /* POP {Rlist} */ |
| 1255 | 1004 | { |
| 1256 | | INT32 offs; |
| 1257 | | |
| 1258 | | for (offs = 0; offs < 8; offs++) |
| 1005 | for (INT32 offs = 0; offs < 8; offs++) |
| 1259 | 1006 | { |
| 1260 | | if (insn & (1 << offs)) |
| 1007 | if (op & (1 << offs)) |
| 1261 | 1008 | { |
| 1262 | 1009 | SET_REGISTER(arm, offs, READ32(GET_REGISTER(arm, 13))); |
| 1263 | 1010 | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) + 4); |
| 1264 | 1011 | } |
| 1265 | 1012 | } |
| 1266 | 1013 | R15 += 2; |
| 1267 | | |
| 1268 | 1014 | } |
| 1269 | 1015 | |
| 1270 | | const void tg0b_d(arm_state *arm, UINT32 pc, UINT32 insn) /* POP {Rlist}{PC} */ |
| 1016 | const void tg0b_d(arm_state *arm, UINT32 pc, UINT32 op) /* POP {Rlist}{PC} */ |
| 1271 | 1017 | { |
| 1272 | | INT32 offs; |
| 1273 | | |
| 1274 | | for (offs = 0; offs < 8; offs++) |
| 1018 | for (INT32 offs = 0; offs < 8; offs++) |
| 1275 | 1019 | { |
| 1276 | | if (insn & (1 << offs)) |
| 1020 | if (op & (1 << offs)) |
| 1277 | 1021 | { |
| 1278 | 1022 | SET_REGISTER(arm, offs, READ32(GET_REGISTER(arm, 13))); |
| 1279 | 1023 | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) + 4); |
| 1280 | 1024 | } |
| 1281 | 1025 | } |
| 1282 | 1026 | UINT32 addr = READ32(GET_REGISTER(arm, 13)); |
| 1283 | | // in v4T, bit 0 is ignored. v5 and later, it's an ARM/Thumb flag like the BX instruction |
| 1284 | 1027 | if (arm->archRev < 5) |
| 1285 | 1028 | { |
| 1286 | 1029 | R15 = addr & ~1; |
| r20737 | r20738 | |
| 1303 | 1046 | R15 = addr; |
| 1304 | 1047 | } |
| 1305 | 1048 | SET_REGISTER(arm, 13, GET_REGISTER(arm, 13) + 4); |
| 1306 | | |
| 1307 | 1049 | } |
| 1308 | 1050 | |
| 1309 | | const void tg0b_e(arm_state *arm, UINT32 pc, UINT32 insn) |
| 1051 | const void tg0b_e(arm_state *arm, UINT32 pc, UINT32 op) |
| 1310 | 1052 | { |
| 1311 | | // UINT32 addr; |
| 1312 | | // INT32 offs; |
| 1313 | | |
| 1314 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1315 | | R15 += 2; |
| 1316 | | |
| 1053 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1317 | 1054 | } |
| 1318 | 1055 | |
| 1319 | | const void tg0b_f(arm_state *arm, UINT32 pc, UINT32 insn) |
| 1056 | const void tg0b_f(arm_state *arm, UINT32 pc, UINT32 op) |
| 1320 | 1057 | { |
| 1321 | | // UINT32 addr; |
| 1322 | | // INT32 offs; |
| 1323 | | |
| 1324 | | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); |
| 1325 | | R15 += 2; |
| 1326 | | |
| 1058 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1327 | 1059 | } |
| 1328 | 1060 | |
| 1329 | 1061 | /* Multiple Load/Store */ |
| r20737 | r20738 | |
| 1334 | 1066 | // GBA "BB Ball" performs an unaligned read with A[1:0] = 2 and expects A[1] not to be ignored [BP 800B90A,(R4&3)!=0] |
| 1335 | 1067 | // GBA "Gadget Racers" performs an unaligned read with A[1:0] = 1 and expects A[0] to be ignored [BP B72,(R0&3)!=0] |
| 1336 | 1068 | |
| 1337 | | const void tg0c_0(arm_state *arm, UINT32 pc, UINT32 insn) /* Store */ |
| 1069 | const void tg0c_0(arm_state *arm, UINT32 pc, UINT32 op) /* Store */ |
| 1338 | 1070 | { |
| 1339 | | UINT32 rd; |
| 1340 | | INT32 offs; |
| 1341 | | |
| 1342 | | UINT32 ld_st_address; |
| 1343 | | |
| 1344 | | rd = (insn & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT; |
| 1345 | | |
| 1346 | | |
| 1347 | | ld_st_address = GET_REGISTER(arm, rd); |
| 1348 | | |
| 1349 | | for (offs = 0; offs < 8; offs++) |
| 1071 | UINT32 rd = (op & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT; |
| 1072 | UINT32 ld_st_address = GET_REGISTER(arm, rd); |
| 1073 | for (INT32 offs = 0; offs < 8; offs++) |
| 1350 | 1074 | { |
| 1351 | | if (insn & (1 << offs)) |
| 1075 | if (op & (1 << offs)) |
| 1352 | 1076 | { |
| 1353 | 1077 | WRITE32(ld_st_address & ~3, GET_REGISTER(arm, offs)); |
| 1354 | 1078 | ld_st_address += 4; |
| r20737 | r20738 | |
| 1358 | 1082 | R15 += 2; |
| 1359 | 1083 | } |
| 1360 | 1084 | |
| 1361 | | |
| 1362 | | const void tg0c_1(arm_state *arm, UINT32 pc, UINT32 insn) /* Load */ |
| 1085 | const void tg0c_1(arm_state *arm, UINT32 pc, UINT32 op) /* Load */ |
| 1363 | 1086 | { |
| 1364 | | UINT32 rd; |
| 1365 | | INT32 offs; |
| 1366 | | |
| 1367 | | UINT32 ld_st_address; |
| 1368 | | |
| 1369 | | rd = (insn & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT; |
| 1370 | | |
| 1371 | | |
| 1372 | | ld_st_address = GET_REGISTER(arm, rd); |
| 1373 | | |
| 1374 | | |
| 1375 | | int rd_in_list; |
| 1376 | | |
| 1377 | | rd_in_list = insn & (1 << rd); |
| 1378 | | for (offs = 0; offs < 8; offs++) |
| 1087 | UINT32 rd = (op & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT; |
| 1088 | int rd_in_list = op & (1 << rd); |
| 1089 | UINT32 ld_st_address = GET_REGISTER(arm, rd); |
| 1090 | for (INT32 offs = 0; offs < 8; offs++) |
| 1379 | 1091 | { |
| 1380 | | if (insn & (1 << offs)) |
| 1092 | if (op & (1 << offs)) |
| 1381 | 1093 | { |
| 1382 | 1094 | SET_REGISTER(arm, offs, READ32(ld_st_address & ~1)); |
| 1383 | 1095 | ld_st_address += 4; |
| 1384 | 1096 | } |
| 1385 | 1097 | } |
| 1386 | | |
| 1387 | 1098 | if (!rd_in_list) |
| 1099 | { |
| 1388 | 1100 | SET_REGISTER(arm, rd, ld_st_address); |
| 1389 | | |
| 1101 | } |
| 1390 | 1102 | R15 += 2; |
| 1391 | 1103 | } |
| 1392 | 1104 | |
| 1393 | 1105 | /* Conditional Branch */ |
| 1394 | 1106 | |
| 1395 | | const void tg0d_0(arm_state *arm, UINT32 pc, UINT32 insn) // COND_EQ: |
| 1107 | const void tg0d_0(arm_state *arm, UINT32 pc, UINT32 op) // COND_EQ: |
| 1396 | 1108 | { |
| 1397 | | INT32 offs; |
| 1398 | | |
| 1399 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1400 | | //case |
| 1109 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1401 | 1110 | if (Z_IS_SET(GET_CPSR)) |
| 1402 | 1111 | { |
| 1403 | 1112 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1409 | 1118 | |
| 1410 | 1119 | } |
| 1411 | 1120 | |
| 1412 | | const void tg0d_1(arm_state *arm, UINT32 pc, UINT32 insn) // COND_NE: |
| 1121 | const void tg0d_1(arm_state *arm, UINT32 pc, UINT32 op) // COND_NE: |
| 1413 | 1122 | { |
| 1414 | | INT32 offs; |
| 1415 | | |
| 1416 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1417 | | //case |
| 1123 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1418 | 1124 | if (Z_IS_CLEAR(GET_CPSR)) |
| 1419 | 1125 | { |
| 1420 | 1126 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1423 | 1129 | { |
| 1424 | 1130 | R15 += 2; |
| 1425 | 1131 | } |
| 1426 | | |
| 1427 | 1132 | } |
| 1428 | 1133 | |
| 1429 | | const void tg0d_2(arm_state *arm, UINT32 pc, UINT32 insn) // COND_CS: |
| 1134 | const void tg0d_2(arm_state *arm, UINT32 pc, UINT32 op) // COND_CS: |
| 1430 | 1135 | { |
| 1431 | | INT32 offs; |
| 1432 | | |
| 1433 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1434 | | //case |
| 1136 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1435 | 1137 | if (C_IS_SET(GET_CPSR)) |
| 1436 | 1138 | { |
| 1437 | 1139 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1440 | 1142 | { |
| 1441 | 1143 | R15 += 2; |
| 1442 | 1144 | } |
| 1443 | | |
| 1444 | 1145 | } |
| 1445 | 1146 | |
| 1446 | | const void tg0d_3(arm_state *arm, UINT32 pc, UINT32 insn) // COND_CC: |
| 1147 | const void tg0d_3(arm_state *arm, UINT32 pc, UINT32 op) // COND_CC: |
| 1447 | 1148 | { |
| 1448 | | INT32 offs; |
| 1449 | | |
| 1450 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1451 | | //case |
| 1149 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1452 | 1150 | if (C_IS_CLEAR(GET_CPSR)) |
| 1453 | 1151 | { |
| 1454 | 1152 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1457 | 1155 | { |
| 1458 | 1156 | R15 += 2; |
| 1459 | 1157 | } |
| 1460 | | |
| 1461 | 1158 | } |
| 1462 | 1159 | |
| 1463 | | const void tg0d_4(arm_state *arm, UINT32 pc, UINT32 insn) // COND_MI: |
| 1160 | const void tg0d_4(arm_state *arm, UINT32 pc, UINT32 op) // COND_MI: |
| 1464 | 1161 | { |
| 1465 | | INT32 offs; |
| 1466 | | |
| 1467 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1468 | | //case |
| 1162 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1469 | 1163 | if (N_IS_SET(GET_CPSR)) |
| 1470 | 1164 | { |
| 1471 | 1165 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1474 | 1168 | { |
| 1475 | 1169 | R15 += 2; |
| 1476 | 1170 | } |
| 1477 | | |
| 1478 | 1171 | } |
| 1479 | 1172 | |
| 1480 | | const void tg0d_5(arm_state *arm, UINT32 pc, UINT32 insn) // COND_PL: |
| 1173 | const void tg0d_5(arm_state *arm, UINT32 pc, UINT32 op) // COND_PL: |
| 1481 | 1174 | { |
| 1482 | | INT32 offs; |
| 1483 | | |
| 1484 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1485 | | //case |
| 1175 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1486 | 1176 | if (N_IS_CLEAR(GET_CPSR)) |
| 1487 | 1177 | { |
| 1488 | 1178 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1491 | 1181 | { |
| 1492 | 1182 | R15 += 2; |
| 1493 | 1183 | } |
| 1494 | | |
| 1495 | 1184 | } |
| 1496 | 1185 | |
| 1497 | | const void tg0d_6(arm_state *arm, UINT32 pc, UINT32 insn) // COND_VS: |
| 1186 | const void tg0d_6(arm_state *arm, UINT32 pc, UINT32 op) // COND_VS: |
| 1498 | 1187 | { |
| 1499 | | INT32 offs; |
| 1500 | | |
| 1501 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1502 | | //case |
| 1188 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1503 | 1189 | if (V_IS_SET(GET_CPSR)) |
| 1504 | 1190 | { |
| 1505 | 1191 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1508 | 1194 | { |
| 1509 | 1195 | R15 += 2; |
| 1510 | 1196 | } |
| 1511 | | |
| 1512 | 1197 | } |
| 1513 | 1198 | |
| 1514 | | const void tg0d_7(arm_state *arm, UINT32 pc, UINT32 insn) // COND_VC: |
| 1199 | const void tg0d_7(arm_state *arm, UINT32 pc, UINT32 op) // COND_VC: |
| 1515 | 1200 | { |
| 1516 | | INT32 offs; |
| 1517 | | |
| 1518 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1519 | | //case |
| 1201 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1520 | 1202 | if (V_IS_CLEAR(GET_CPSR)) |
| 1521 | 1203 | { |
| 1522 | 1204 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1525 | 1207 | { |
| 1526 | 1208 | R15 += 2; |
| 1527 | 1209 | } |
| 1528 | | |
| 1529 | 1210 | } |
| 1530 | 1211 | |
| 1531 | | const void tg0d_8(arm_state *arm, UINT32 pc, UINT32 insn) // COND_HI: |
| 1212 | const void tg0d_8(arm_state *arm, UINT32 pc, UINT32 op) // COND_HI: |
| 1532 | 1213 | { |
| 1533 | | INT32 offs; |
| 1534 | | |
| 1535 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1536 | | //case |
| 1214 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1537 | 1215 | if (C_IS_SET(GET_CPSR) && Z_IS_CLEAR(GET_CPSR)) |
| 1538 | 1216 | { |
| 1539 | 1217 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1542 | 1220 | { |
| 1543 | 1221 | R15 += 2; |
| 1544 | 1222 | } |
| 1545 | | |
| 1546 | 1223 | } |
| 1547 | 1224 | |
| 1548 | | const void tg0d_9(arm_state *arm, UINT32 pc, UINT32 insn) // COND_LS: |
| 1225 | const void tg0d_9(arm_state *arm, UINT32 pc, UINT32 op) // COND_LS: |
| 1549 | 1226 | { |
| 1550 | | INT32 offs; |
| 1551 | | |
| 1552 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1553 | | //case |
| 1227 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1554 | 1228 | if (C_IS_CLEAR(GET_CPSR) || Z_IS_SET(GET_CPSR)) |
| 1555 | 1229 | { |
| 1556 | 1230 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1559 | 1233 | { |
| 1560 | 1234 | R15 += 2; |
| 1561 | 1235 | } |
| 1562 | | |
| 1563 | 1236 | } |
| 1564 | 1237 | |
| 1565 | | const void tg0d_a(arm_state *arm, UINT32 pc, UINT32 insn) // COND_GE: |
| 1238 | const void tg0d_a(arm_state *arm, UINT32 pc, UINT32 op) // COND_GE: |
| 1566 | 1239 | { |
| 1567 | | INT32 offs; |
| 1568 | | |
| 1569 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1570 | | //case |
| 1240 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1571 | 1241 | if (!(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK)) |
| 1572 | 1242 | { |
| 1573 | 1243 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1576 | 1246 | { |
| 1577 | 1247 | R15 += 2; |
| 1578 | 1248 | } |
| 1579 | | |
| 1580 | 1249 | } |
| 1581 | 1250 | |
| 1582 | | const void tg0d_b(arm_state *arm, UINT32 pc, UINT32 insn) // COND_LT: |
| 1251 | const void tg0d_b(arm_state *arm, UINT32 pc, UINT32 op) // COND_LT: |
| 1583 | 1252 | { |
| 1584 | | INT32 offs; |
| 1585 | | |
| 1586 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1587 | | //case |
| 1253 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1588 | 1254 | if (!(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK)) |
| 1589 | 1255 | { |
| 1590 | 1256 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1593 | 1259 | { |
| 1594 | 1260 | R15 += 2; |
| 1595 | 1261 | } |
| 1596 | | |
| 1597 | 1262 | } |
| 1598 | 1263 | |
| 1599 | | const void tg0d_c(arm_state *arm, UINT32 pc, UINT32 insn) // COND_GT: |
| 1264 | const void tg0d_c(arm_state *arm, UINT32 pc, UINT32 op) // COND_GT: |
| 1600 | 1265 | { |
| 1601 | | INT32 offs; |
| 1602 | | |
| 1603 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1604 | | //case |
| 1266 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1605 | 1267 | if (Z_IS_CLEAR(GET_CPSR) && !(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK)) |
| 1606 | 1268 | { |
| 1607 | 1269 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1610 | 1272 | { |
| 1611 | 1273 | R15 += 2; |
| 1612 | 1274 | } |
| 1613 | | |
| 1614 | 1275 | } |
| 1615 | 1276 | |
| 1616 | | const void tg0d_d(arm_state *arm, UINT32 pc, UINT32 insn) // COND_LE: |
| 1277 | const void tg0d_d(arm_state *arm, UINT32 pc, UINT32 op) // COND_LE: |
| 1617 | 1278 | { |
| 1618 | | INT32 offs; |
| 1619 | | |
| 1620 | | offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1621 | | //case |
| 1279 | INT32 offs = (INT8)(op & THUMB_INSN_IMM); |
| 1622 | 1280 | if (Z_IS_SET(GET_CPSR) || !(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK)) |
| 1623 | 1281 | { |
| 1624 | 1282 | R15 += 4 + (offs << 1); |
| r20737 | r20738 | |
| 1627 | 1285 | { |
| 1628 | 1286 | R15 += 2; |
| 1629 | 1287 | } |
| 1630 | | |
| 1631 | 1288 | } |
| 1632 | 1289 | |
| 1633 | | const void tg0d_e(arm_state *arm, UINT32 pc, UINT32 insn) // COND_AL: |
| 1290 | const void tg0d_e(arm_state *arm, UINT32 pc, UINT32 op) // COND_AL: |
| 1634 | 1291 | { |
| 1635 | | // INT32 offs; |
| 1636 | | |
| 1637 | | // offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1638 | | //case |
| 1639 | | fatalerror("%08x: Undefined Thumb instruction: %04x (ARM9 reserved)\n", pc, insn); |
| 1640 | | R15 += 2; |
| 1641 | | |
| 1292 | fatalerror("%08x: Undefined Thumb instruction: %04x (ARM9 reserved)\n", pc, op); |
| 1642 | 1293 | } |
| 1643 | 1294 | |
| 1644 | | const void tg0d_f(arm_state *arm, UINT32 pc, UINT32 insn) // COND_NV: // SWI (this is sort of a "hole" in the opcode encoding) |
| 1295 | const void tg0d_f(arm_state *arm, UINT32 pc, UINT32 op) // COND_NV: // SWI (this is sort of a "hole" in the opcode encoding) |
| 1645 | 1296 | { |
| 1646 | | // INT32 offs; |
| 1647 | | |
| 1648 | | // offs = (INT8)(insn & THUMB_INSN_IMM); |
| 1649 | | |
| 1650 | | //case |
| 1651 | 1297 | arm->pendingSwi = 1; |
| 1652 | 1298 | ARM7_CHECKIRQ; |
| 1653 | | |
| 1654 | 1299 | } |
| 1655 | 1300 | |
| 1656 | | /* B #offs */ |
| 1301 | /* B #offs */ |
| 1657 | 1302 | |
| 1658 | | const void tg0e_0(arm_state *arm, UINT32 pc, UINT32 insn) |
| 1303 | const void tg0e_0(arm_state *arm, UINT32 pc, UINT32 op) |
| 1659 | 1304 | { |
| 1660 | | INT32 offs; |
| 1661 | | |
| 1662 | | offs = (insn & THUMB_BRANCH_OFFS) << 1; |
| 1305 | INT32 offs = (op & THUMB_BRANCH_OFFS) << 1; |
| 1663 | 1306 | if (offs & 0x00000800) |
| 1664 | 1307 | { |
| 1665 | 1308 | offs |= 0xfffff800; |
| r20737 | r20738 | |
| 1667 | 1310 | R15 += 4 + offs; |
| 1668 | 1311 | } |
| 1669 | 1312 | |
| 1670 | | |
| 1671 | | const void tg0e_1(arm_state *arm, UINT32 pc, UINT32 insn) |
| 1313 | const void tg0e_1(arm_state *arm, UINT32 pc, UINT32 op) |
| 1672 | 1314 | { |
| 1673 | | UINT32 addr; |
| 1674 | | |
| 1675 | | addr = GET_REGISTER(arm, 14); |
| 1676 | | addr += (insn & THUMB_BLOP_OFFS) << 1; |
| 1315 | UINT32 addr = GET_REGISTER(arm, 14); |
| 1316 | addr += (op & THUMB_BLOP_OFFS) << 1; |
| 1677 | 1317 | addr &= 0xfffffffc; |
| 1678 | 1318 | SET_REGISTER(arm, 14, (R15 + 4) | 1); |
| 1679 | 1319 | R15 = addr; |
| r20737 | r20738 | |
| 1681 | 1321 | |
| 1682 | 1322 | /* BL */ |
| 1683 | 1323 | |
| 1684 | | const void tg0f_0(arm_state *arm, UINT32 pc, UINT32 insn) |
| 1324 | const void tg0f_0(arm_state *arm, UINT32 pc, UINT32 op) |
| 1685 | 1325 | { |
| 1686 | | UINT32 addr; |
| 1687 | | |
| 1688 | | addr = (insn & THUMB_BLOP_OFFS) << 12; |
| 1326 | UINT32 addr = (op & THUMB_BLOP_OFFS) << 12; |
| 1689 | 1327 | if (addr & (1 << 22)) |
| 1690 | 1328 | { |
| 1691 | 1329 | addr |= 0xff800000; |
| r20737 | r20738 | |
| 1695 | 1333 | R15 += 2; |
| 1696 | 1334 | } |
| 1697 | 1335 | |
| 1698 | | |
| 1699 | | const void tg0f_1(arm_state *arm, UINT32 pc, UINT32 insn) /* BL */ |
| 1336 | const void tg0f_1(arm_state *arm, UINT32 pc, UINT32 op) /* BL */ |
| 1700 | 1337 | { |
| 1701 | | UINT32 addr; |
| 1702 | | |
| 1703 | | addr = GET_REGISTER(arm, 14) & ~1; |
| 1704 | | addr += (insn & THUMB_BLOP_OFFS) << 1; |
| 1338 | UINT32 addr = GET_REGISTER(arm, 14) & ~1; |
| 1339 | addr += (op & THUMB_BLOP_OFFS) << 1; |
| 1705 | 1340 | SET_REGISTER(arm, 14, (R15 + 2) | 1); |
| 1706 | 1341 | R15 = addr; |
| 1707 | 1342 | //R15 += 2; |
trunk/src/emu/cpu/arm7/arm7tdrc.c
| r0 | r20738 | |
| 1 | #include "emu.h" |
| 2 | #include "arm7core.h" |
| 3 | #include "arm7thmb.h" |
| 4 | #include "arm7help.h" |
| 5 | |
| 6 | #ifdef ARM7_USE_DRC |
| 7 | |
| 8 | arm7thumb_drcophandler drcthumb_handler[0x40*0x10] = |
| 9 | { |
| 10 | // #define THUMB_SHIFT_R ((UINT16)0x0800) |
| 11 | drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, |
| 12 | drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, |
| 13 | drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, |
| 14 | drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, drctg00_0, |
| 15 | drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, |
| 16 | drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, |
| 17 | drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, |
| 18 | drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, drctg00_1, |
| 19 | // #define THUMB_INSN_ADDSUB ((UINT16)0x0800) // #define THUMB_ADDSUB_TYPE ((UINT16)0x0600) |
| 20 | drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, |
| 21 | drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, |
| 22 | drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, |
| 23 | drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, drctg01_0, |
| 24 | drctg01_10, drctg01_10, drctg01_10, drctg01_10, drctg01_10, drctg01_10, drctg01_10, drctg01_10, |
| 25 | drctg01_11, drctg01_11, drctg01_11, drctg01_11, drctg01_11, drctg01_11, drctg01_11, drctg01_11, |
| 26 | drctg01_12, drctg01_12, drctg01_12, drctg01_12, drctg01_12, drctg01_12, drctg01_12, drctg01_12, |
| 27 | drctg01_13, drctg01_13, drctg01_13, drctg01_13, drctg01_13, drctg01_13, drctg01_13, drctg01_13, |
| 28 | // #define THUMB_INSN_CMP ((UINT16)0x0800) |
| 29 | drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, |
| 30 | drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, |
| 31 | drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, |
| 32 | drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, drctg02_0, |
| 33 | drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, |
| 34 | drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, |
| 35 | drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, |
| 36 | drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, drctg02_1, |
| 37 | // #define THUMB_INSN_SUB ((UINT16)0x0800) |
| 38 | drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, |
| 39 | drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, |
| 40 | drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, |
| 41 | drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, drctg03_0, |
| 42 | drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, |
| 43 | drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, |
| 44 | drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, |
| 45 | drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, drctg03_1, |
| 46 | //#define THUMB_GROUP4_TYPE ((UINT16)0x0c00) //#define THUMB_ALUOP_TYPE ((UINT16)0x03c0) // #define THUMB_HIREG_OP ((UINT16)0x0300) // #define THUMB_HIREG_H ((UINT16)0x00c0) |
| 47 | drctg04_00_00, drctg04_00_01, drctg04_00_02, drctg04_00_03, drctg04_00_04, drctg04_00_05, drctg04_00_06, drctg04_00_07, |
| 48 | drctg04_00_08, drctg04_00_09, drctg04_00_0a, drctg04_00_0b, drctg04_00_0c, drctg04_00_0d, drctg04_00_0e, drctg04_00_0f, |
| 49 | drctg04_01_00, drctg04_01_01, drctg04_01_02, drctg04_01_03, drctg04_01_10, drctg04_01_11, drctg04_01_12, drctg04_01_13, |
| 50 | drctg04_01_20, drctg04_01_21, drctg04_01_22, drctg04_01_23, drctg04_01_30, drctg04_01_31, drctg04_01_32, drctg04_01_33, |
| 51 | drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, |
| 52 | drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, |
| 53 | drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, |
| 54 | drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, drctg04_0203, |
| 55 | //#define THUMB_GROUP5_TYPE ((UINT16)0x0e00) |
| 56 | drctg05_0, drctg05_0, drctg05_0, drctg05_0, drctg05_0, drctg05_0, drctg05_0, drctg05_0, |
| 57 | drctg05_1, drctg05_1, drctg05_1, drctg05_1, drctg05_1, drctg05_1, drctg05_1, drctg05_1, |
| 58 | drctg05_2, drctg05_2, drctg05_2, drctg05_2, drctg05_2, drctg05_2, drctg05_2, drctg05_2, |
| 59 | drctg05_3, drctg05_3, drctg05_3, drctg05_3, drctg05_3, drctg05_3, drctg05_3, drctg05_3, |
| 60 | drctg05_4, drctg05_4, drctg05_4, drctg05_4, drctg05_4, drctg05_4, drctg05_4, drctg05_4, |
| 61 | drctg05_5, drctg05_5, drctg05_5, drctg05_5, drctg05_5, drctg05_5, drctg05_5, drctg05_5, |
| 62 | drctg05_6, drctg05_6, drctg05_6, drctg05_6, drctg05_6, drctg05_6, drctg05_6, drctg05_6, |
| 63 | drctg05_7, drctg05_7, drctg05_7, drctg05_7, drctg05_7, drctg05_7, drctg05_7, drctg05_7, |
| 64 | //#define THUMB_LSOP_L ((UINT16)0x0800) |
| 65 | drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, |
| 66 | drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, |
| 67 | drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, |
| 68 | drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, drctg06_0, |
| 69 | drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, |
| 70 | drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, |
| 71 | drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, |
| 72 | drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, drctg06_1, |
| 73 | //#define THUMB_LSOP_L ((UINT16)0x0800) |
| 74 | drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, |
| 75 | drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, |
| 76 | drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, |
| 77 | drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, drctg07_0, |
| 78 | drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, |
| 79 | drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, |
| 80 | drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, |
| 81 | drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, drctg07_1, |
| 82 | // #define THUMB_HALFOP_L ((UINT16)0x0800) |
| 83 | drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, |
| 84 | drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, |
| 85 | drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, |
| 86 | drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, drctg08_0, |
| 87 | drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, |
| 88 | drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, |
| 89 | drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, |
| 90 | drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, drctg08_1, |
| 91 | // #define THUMB_STACKOP_L ((UINT16)0x0800) |
| 92 | drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, |
| 93 | drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, |
| 94 | drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, |
| 95 | drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, drctg09_0, |
| 96 | drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, |
| 97 | drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, |
| 98 | drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, |
| 99 | drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, drctg09_1, |
| 100 | // #define THUMB_RELADDR_SP ((UINT16)0x0800) |
| 101 | drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, |
| 102 | drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, |
| 103 | drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, |
| 104 | drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, drctg0a_0, |
| 105 | drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, |
| 106 | drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, |
| 107 | drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, |
| 108 | drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, drctg0a_1, |
| 109 | // #define THUMB_STACKOP_TYPE ((UINT16)0x0f00) |
| 110 | drctg0b_0, drctg0b_0, drctg0b_0, drctg0b_0, drctg0b_1, drctg0b_1, drctg0b_1, drctg0b_1, |
| 111 | drctg0b_2, drctg0b_2, drctg0b_2, drctg0b_2, drctg0b_3, drctg0b_3, drctg0b_3, drctg0b_3, |
| 112 | drctg0b_4, drctg0b_4, drctg0b_4, drctg0b_4, drctg0b_5, drctg0b_5, drctg0b_5, drctg0b_5, |
| 113 | drctg0b_6, drctg0b_6, drctg0b_6, drctg0b_6, drctg0b_7, drctg0b_7, drctg0b_7, drctg0b_7, |
| 114 | drctg0b_8, drctg0b_8, drctg0b_8, drctg0b_8, drctg0b_9, drctg0b_9, drctg0b_9, drctg0b_9, |
| 115 | drctg0b_a, drctg0b_a, drctg0b_a, drctg0b_a, drctg0b_b, drctg0b_b, drctg0b_b, drctg0b_b, |
| 116 | drctg0b_c, drctg0b_c, drctg0b_c, drctg0b_c, drctg0b_d, drctg0b_d, drctg0b_d, drctg0b_d, |
| 117 | drctg0b_e, drctg0b_e, drctg0b_e, drctg0b_e, drctg0b_f, drctg0b_f, drctg0b_f, drctg0b_f, |
| 118 | // #define THUMB_MULTLS ((UINT16)0x0800) |
| 119 | drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, |
| 120 | drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, |
| 121 | drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, |
| 122 | drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, drctg0c_0, |
| 123 | drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, |
| 124 | drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, |
| 125 | drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, |
| 126 | drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, drctg0c_1, |
| 127 | // #define THUMB_COND_TYPE ((UINT16)0x0f00) |
| 128 | drctg0d_0, drctg0d_0, drctg0d_0, drctg0d_0, drctg0d_1, drctg0d_1, drctg0d_1, drctg0d_1, |
| 129 | drctg0d_2, drctg0d_2, drctg0d_2, drctg0d_2, drctg0d_3, drctg0d_3, drctg0d_3, drctg0d_3, |
| 130 | drctg0d_4, drctg0d_4, drctg0d_4, drctg0d_4, drctg0d_5, drctg0d_5, drctg0d_5, drctg0d_5, |
| 131 | drctg0d_6, drctg0d_6, drctg0d_6, drctg0d_6, drctg0d_7, drctg0d_7, drctg0d_7, drctg0d_7, |
| 132 | drctg0d_8, drctg0d_8, drctg0d_8, drctg0d_8, drctg0d_9, drctg0d_9, drctg0d_9, drctg0d_9, |
| 133 | drctg0d_a, drctg0d_a, drctg0d_a, drctg0d_a, drctg0d_b, drctg0d_b, drctg0d_b, drctg0d_b, |
| 134 | drctg0d_c, drctg0d_c, drctg0d_c, drctg0d_c, drctg0d_d, drctg0d_d, drctg0d_d, drctg0d_d, |
| 135 | drctg0d_e, drctg0d_e, drctg0d_e, drctg0d_e, drctg0d_f, drctg0d_f, drctg0d_f, drctg0d_f, |
| 136 | // #define THUMB_BLOP_LO ((UINT16)0x0800) |
| 137 | drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, |
| 138 | drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, |
| 139 | drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, |
| 140 | drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, drctg0e_0, |
| 141 | drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, |
| 142 | drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, |
| 143 | drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, |
| 144 | drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, drctg0e_1, |
| 145 | // #define THUMB_BLOP_LO ((UINT16)0x0800) |
| 146 | drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, |
| 147 | drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, |
| 148 | drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, |
| 149 | drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, drctg0f_0, |
| 150 | drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, |
| 151 | drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, |
| 152 | drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, |
| 153 | drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, drctg0f_1, |
| 154 | }; |
| 155 | |
| 156 | /* Shift operations */ |
| 157 | |
| 158 | const void drctg00_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Shift left */ |
| 159 | { |
| 160 | UINT32 op = desc->opptr.l[0]; |
| 161 | UINT32 pc = desc->pc; |
| 162 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 163 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 164 | INT32 offs = (op & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 165 | |
| 166 | UML_MOV(block, I0, DRC_RS); // rrs |
| 167 | if (offs != 0) |
| 168 | { |
| 169 | UML_SHL(block, DRC_RD, DRC_RS, offs); |
| 170 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~C_MASK); |
| 171 | UML_TEST(block, I0, 1 << (31 - (offs - 1))); |
| 172 | UML_MOVc(block, COND_NZ, I1, C_MASK); |
| 173 | UML_MOVc(block, COND_Z, I1, 0); |
| 174 | UML_OR(block, DRC_CPSR, I1); |
| 175 | } |
| 176 | else |
| 177 | { |
| 178 | UML_MOV(block, DRC_RD, DRC_RS); |
| 179 | } |
| 180 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 181 | DRCHandleALUNZFlags(DRC_RD); |
| 182 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 183 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 184 | } |
| 185 | |
| 186 | const void drctg00_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Shift right */ |
| 187 | { |
| 188 | UINT32 op = desc->opptr.l[0]; |
| 189 | UINT32 pc = desc->pc; |
| 190 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 191 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 192 | INT32 offs = (op & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 193 | |
| 194 | UML_MOV(block, I0, DRC_RS); // rrs |
| 195 | if (offs != 0) |
| 196 | { |
| 197 | UML_SHR(block, DRC_RD, DRC_RS, offs); |
| 198 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~C_MASK); |
| 199 | UML_TEST(block, I0, 1 << (31 - (offs - 1))); |
| 200 | UML_MOVc(block, COND_NZ, I1, C_MASK); |
| 201 | UML_MOVc(block, COND_Z, I1, 0); |
| 202 | UML_OR(block, DRC_CPSR, I1); |
| 203 | } |
| 204 | else |
| 205 | { |
| 206 | UML_MOV(block, DRC_RD, 0); |
| 207 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~C_MASK); |
| 208 | UML_TEST(block, I0, 0x80000000); |
| 209 | UML_MOVc(block, COND_NZ, I1, C_MASK); |
| 210 | UML_MOVc(block, COND_Z, I1, 0); |
| 211 | UML_OR(block, DRC_CPSR, I1); |
| 212 | } |
| 213 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 214 | DRCHandleALUNZFlags(DRC_RD); |
| 215 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 216 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 217 | } |
| 218 | |
| 219 | /* Arithmetic */ |
| 220 | |
| 221 | const void drctg01_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 222 | { |
| 223 | UINT32 op = desc->opptr.l[0]; |
| 224 | UINT32 pc = desc->pc; |
| 225 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 226 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 227 | INT32 offs = (op & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; |
| 228 | |
| 229 | /* ASR.. */ |
| 230 | UML_MOV(block, I0, DRC_RS); |
| 231 | if (offs == 0) |
| 232 | { |
| 233 | offs = 32; |
| 234 | } |
| 235 | if (offs >= 32) |
| 236 | { |
| 237 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~C_MASK); |
| 238 | UML_SHR(block, I1, I0, 31); |
| 239 | UML_TEST(block, I1, ~0); |
| 240 | UML_MOVc(block, COND_NZ, I1, C_MASK); |
| 241 | UML_MOVc(block, COND_Z, I1, 0); |
| 242 | UML_OR(block, DRC_CPSR, DRC_CPSR, I1); |
| 243 | UML_TEST(block, I0, 0x80000000); |
| 244 | UML_MOVc(block, COND_NZ, DRC_RD, ~0); |
| 245 | UML_MOVc(block, COND_Z, DRC_RD, 0); |
| 246 | } |
| 247 | else |
| 248 | { |
| 249 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~C_MASK); |
| 250 | UML_TEST(block, I0, 1 << (offs - 1)); |
| 251 | UML_MOVc(block, COND_NZ, I1, C_MASK); |
| 252 | UML_MOVc(block, COND_Z, I1, 0); |
| 253 | UML_OR(block, DRC_CPSR, DRC_CPSR, I1); |
| 254 | UML_SHR(block, I1, I0, offs); |
| 255 | UML_SHL(block, I2, ~0, 32 - offs); |
| 256 | UML_TEST(block, I0, 0x80000000); |
| 257 | UML_MOVc(block, COND_Z, I2, 0); |
| 258 | UML_OR(block, DRC_RD, I1, I2); |
| 259 | } |
| 260 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 261 | DRCHandleALUNZFlags(DRC_RD); |
| 262 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 263 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 264 | } |
| 265 | |
| 266 | const void drctg01_10(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 267 | { |
| 268 | UINT32 op = desc->opptr.l[0]; |
| 269 | UINT32 rn = (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 270 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 271 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 272 | UML_ADD(block, DRC_REG(rd), DRC_REG(rs), DRC_REG(rn)); |
| 273 | DRCHandleThumbALUAddFlags(DRC_REG(rd), DRC_REG(rs), DRC_REG(rn)); |
| 274 | } |
| 275 | |
| 276 | const void drctg01_11(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* SUB Rd, Rs, Rn */ |
| 277 | { |
| 278 | UINT32 op = desc->opptr.l[0]; |
| 279 | UINT32 rn = (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 280 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 281 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 282 | UML_SUB(block, DRC_REG(rd), DRC_REG(rs), DRC_REG(rn)); |
| 283 | DRCHandleThumbALUSubFlags(DRC_REG(rd), DRC_REG(rs), DRC_REG(rn)); |
| 284 | } |
| 285 | |
| 286 | const void drctg01_12(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADD Rd, Rs, #imm */ |
| 287 | { |
| 288 | UINT32 op = desc->opptr.l[0]; |
| 289 | UINT32 imm = (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 290 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 291 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 292 | UML_ADD(block, DRC_REG(rd), DRC_REG(rs), imm); |
| 293 | DRCHandleThumbALUAddFlags(DRC_REG(rd), DRC_REG(rs), imm); |
| 294 | } |
| 295 | |
| 296 | const void drctg01_13(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* SUB Rd, Rs, #imm */ |
| 297 | { |
| 298 | UINT32 op = desc->opptr.l[0]; |
| 299 | UINT32 imm = (op & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; |
| 300 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 301 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 302 | UML_SUB(block, DRC_REG(rd), DRC_REG(rs), imm); |
| 303 | DRCHandleThumbALUSubFlags(DRC_REG(rd), DRC_REG(rs), imm); |
| 304 | } |
| 305 | |
| 306 | /* CMP / MOV */ |
| 307 | |
| 308 | const void drctg02_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 309 | { |
| 310 | UINT32 op = desc->opptr.l[0]; |
| 311 | UINT32 rd = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 312 | UINT32 op2 = (op & THUMB_INSN_IMM); |
| 313 | UML_MOV(block, DRC_REG(rd), op2); |
| 314 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 315 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 316 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 317 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 318 | } |
| 319 | |
| 320 | const void drctg02_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 321 | { |
| 322 | UINT32 op = desc->opptr.l[0]; |
| 323 | UINT32 rn = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 324 | UINT32 op2 = op & THUMB_INSN_IMM; |
| 325 | |
| 326 | UML_SUB(block, I3, DRC_REG(rn), op2); |
| 327 | DRCHandleThumbALUSubFlags(I3, DRC_REG(rn), op2); |
| 328 | } |
| 329 | |
| 330 | /* ADD/SUB immediate */ |
| 331 | |
| 332 | const void drctg03_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADD Rd, #Offset8 */ |
| 333 | { |
| 334 | UINT32 op = desc->opptr.l[0]; |
| 335 | UINT32 rn = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 336 | UINT32 op2 = op & THUMB_INSN_IMM; |
| 337 | UINT32 rd = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 338 | UML_ADD(block, DRC_REG(rd), DRC_REG(rn), op2); |
| 339 | DRCHandleThumbALUAddFlags(DRC_REG(rd), DRC_REG(rn), op2); |
| 340 | } |
| 341 | |
| 342 | const void drctg03_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* SUB Rd, #Offset8 */ |
| 343 | { |
| 344 | UINT32 op = desc->opptr.l[0]; |
| 345 | UINT32 rn = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 346 | UINT32 op2 = op & THUMB_INSN_IMM; |
| 347 | UINT32 rd = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 348 | UML_SUB(block, DRC_REG(rd), DRC_REG(rn), op2); |
| 349 | DRCHandleThumbALUSubFlags(DRC_REG(rd), DRC_REG(rn), op2); |
| 350 | } |
| 351 | |
| 352 | /* Rd & Rm instructions */ |
| 353 | |
| 354 | const void drctg04_00_00(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* AND Rd, Rs */ |
| 355 | { |
| 356 | UINT32 op = desc->opptr.l[0]; |
| 357 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 358 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 359 | UML_AND(block, DRC_REG(rd), DRC_REG(rd), DRC_REG(rs)); |
| 360 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 361 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 362 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 363 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 364 | } |
| 365 | |
| 366 | const void drctg04_00_01(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* EOR Rd, Rs */ |
| 367 | { |
| 368 | UINT32 op = desc->opptr.l[0]; |
| 369 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 370 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 371 | UML_XOR(block, DRC_REG(rd), DRC_REG(rd), DRC_REG(rs)); |
| 372 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 373 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 374 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 375 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 376 | } |
| 377 | |
| 378 | const void drctg04_00_02(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* LSL Rd, Rs */ |
| 379 | { |
| 380 | UINT32 op = desc->opptr.l[0]; |
| 381 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 382 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 383 | code_label skip; |
| 384 | code_label offsg32; |
| 385 | code_label offs32; |
| 386 | |
| 387 | UML_AND(block, I1, DRC_REG(rs), 0xff); |
| 388 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK | C_MASK)); |
| 389 | |
| 390 | UML_CMP(block, I1, 0); |
| 391 | UML_JMPc(block, COND_E, skip = compiler->labelnum++); |
| 392 | |
| 393 | UML_CMP(block, I1, 32); |
| 394 | UML_JMPc(block, COND_A, offsg32 = compiler->labelnum++); |
| 395 | UML_JMPc(block, COND_E, offs32 = compiler->labelnum++); |
| 396 | |
| 397 | UML_SHL(block, DRC_REG(rd), DRC_REG(rd), I1); |
| 398 | UML_SUB(block, I1, I1, 1); |
| 399 | UML_SUB(block, I1, 31, I1); |
| 400 | UML_SHL(block, I1, 1, I1); |
| 401 | UML_TEST(block, DRC_REG(rd), I1); |
| 402 | UML_MOVc(block, COND_NZ, I0, C_MASK); |
| 403 | UML_MOVc(block, COND_Z, I0, 0); |
| 404 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 405 | UML_JMP(block, skip); |
| 406 | |
| 407 | UML_LABEL(block, offs32); |
| 408 | UML_TEST(block, DRC_REG(rd), 1); |
| 409 | UML_MOVc(block, COND_NZ, I0, C_MASK); |
| 410 | UML_MOVc(block, COND_Z, I0, 0); |
| 411 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 412 | UML_MOV(block, DRC_REG(rd), 0); |
| 413 | UML_JMP(block, skip); |
| 414 | |
| 415 | UML_LABEL(block, offsg32); |
| 416 | UML_MOV(block, DRC_REG(rd), 0); |
| 417 | |
| 418 | UML_LABEL(block, skip); |
| 419 | |
| 420 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 421 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 422 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 423 | } |
| 424 | |
| 425 | const void drctg04_00_03(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* LSR Rd, Rs */ |
| 426 | { |
| 427 | UINT32 op = desc->opptr.l[0]; |
| 428 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 429 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 430 | code_label skip; |
| 431 | code_label offsg32; |
| 432 | code_label offs32; |
| 433 | |
| 434 | UML_AND(block, I1, DRC_REG(rs), 0xff); |
| 435 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK | C_MASK)); |
| 436 | UML_CMP(block, I1, 0); |
| 437 | UML_JMPc(block, COND_E, skip = compiler->labelnum++); |
| 438 | |
| 439 | UML_CMP(block, I1, 32); |
| 440 | UML_JMPc(block, COND_A, offsg32 = compiler->labelnum++); |
| 441 | UML_JMPc(block, COND_E, offs32 = compiler->labelnum++); |
| 442 | |
| 443 | UML_SHR(block, DRC_REG(rd), DRC_REG(rd), I1); |
| 444 | UML_SUB(block, I1, 1); |
| 445 | UML_SHL(block, I1, 1, I1); |
| 446 | UML_TEST(block, DRC_REG(rd), I1); |
| 447 | UML_MOVc(block, COND_NZ, I0, C_MASK); |
| 448 | UML_MOVc(block, COND_Z, I0, 0); |
| 449 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 450 | UML_JMP(block, skip); |
| 451 | |
| 452 | UML_LABEL(block, offs32); |
| 453 | UML_TEST(block, DRC_REG(rd), 0x80000000); |
| 454 | UML_MOVc(block, COND_NZ, I0, C_MASK); |
| 455 | UML_MOVc(block, COND_Z, I0, 0); |
| 456 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 457 | UML_MOV(block, DRC_REG(rd), 0); |
| 458 | UML_JMP(block, skip); |
| 459 | |
| 460 | UML_LABEL(block, offsg32); |
| 461 | UML_MOV(block, DRC_REG(rd), 0); |
| 462 | |
| 463 | UML_LABEL(block, skip); |
| 464 | |
| 465 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 466 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 467 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 468 | } |
| 469 | |
| 470 | const void drctg04_00_04(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ASR Rd, Rs */ |
| 471 | { |
| 472 | UINT32 op = desc->opptr.l[0]; |
| 473 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 474 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 475 | code_label skip; |
| 476 | code_label offsg32; |
| 477 | code_label offs32; |
| 478 | |
| 479 | UML_MOV(block, I0, DRC_REG(rd)); |
| 480 | UML_AND(block, I1, DRC_REG(rs), 0xff); |
| 481 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK | C_MASK)); |
| 482 | UML_CMP(block, I1, 0); |
| 483 | UML_JMPc(block, COND_E, skip = compiler->labelnum++); |
| 484 | |
| 485 | UML_SHR(block, I2, I0, I1); |
| 486 | UML_SUB(block, I1, 32, I1); |
| 487 | UML_SHL(block, I1, ~0, I1); |
| 488 | UML_TEST(block, I0, 0x80000000); |
| 489 | UML_MOVc(block, COND_NZ, DRC_REG(RD), I1); |
| 490 | UML_MOVc(block, COND_Z, DRC_REG(RD), 0); |
| 491 | UML_OR(block, DRC_REG(rd), DRC_REG(RD), I2); |
| 492 | UML_JMPc(block, COND_B, offsl32 = compiler->labelnum++); |
| 493 | |
| 494 | UML_TEST(block, I0, 0x80000000); |
| 495 | UML_MOVc(block, COND_NZ, DRC_REG(rd), ~0); |
| 496 | UML_MOVc(block, COND_Z, DRC_REG(rd), 0); |
| 497 | UML_MOVc(block, COND_NZ, I1, C_MASK); |
| 498 | UML_MOVc(block, COND_Z, I1, 0); |
| 499 | UML_OR(block, DRC_CPSR, DRC_CPSR, I1); |
| 500 | UML_JMP(block, skip); |
| 501 | |
| 502 | UML_LABEL(block, offsl32); |
| 503 | UML_SUB(block, I1, I1, 1); |
| 504 | UML_SHL(block, I1, 1, I1); |
| 505 | UML_TEST(block, I0, I1); |
| 506 | UML_MOVc(block, COND_NZ, I1, C_MASK); |
| 507 | UML_MOVc(block, COND_Z, I1, 0); |
| 508 | UML_OR(block, DRC_CPSR, DRC_CPSR, I1); |
| 509 | UML_JMP(block, skip); |
| 510 | |
| 511 | UML_LABEL(block, skip); |
| 512 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 513 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 514 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 515 | |
| 516 | } |
| 517 | |
| 518 | const void drctg04_00_05(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADC Rd, Rs */ |
| 519 | { |
| 520 | UINT32 op = desc->opptr.l[0]; |
| 521 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 522 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 523 | UML_TEST(block, DRC_CPSR, C_MASK); |
| 524 | UML_MOVc(block, COND_NZ, I3, 1); |
| 525 | UML_MOVc(block, COND_Z, I3, 0); |
| 526 | UML_ADD(block, I3, I3, DRC_REG(rd); |
| 527 | UML_ADD(block, I3, I3, DRC_REG(rs); |
| 528 | DRCHandleThumbALUAddFlags(I3, DRC_REG(rd), DRC_REG(rs)); |
| 529 | UML_MOV(block, DRC_REG(rd), I3); |
| 530 | } |
| 531 | |
| 532 | const void drctg04_00_06(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* SBC Rd, Rs */ |
| 533 | { |
| 534 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 535 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 536 | UML_TEST(block, DRC_CPSR, C_MASK); |
| 537 | UML_MOVc(block, COND_NZ, I3, 0); |
| 538 | UML_MOVc(block, COND_Z, I3, 1); |
| 539 | UML_SUB(block, I3, DRC_REG(rs), I3); |
| 540 | UML_ADD(block, I3, DRC_REG(rd), I3); |
| 541 | DRCHandleThumbALUSubFlags(I3, DRC_REG(rd), DRC_REG(rs)); |
| 542 | UML_MOV(block, DRC_REG(rd), I3); |
| 543 | } |
| 544 | |
| 545 | const void drctg04_00_07(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ROR Rd, Rs */ |
| 546 | { |
| 547 | UINT32 op = desc->opptr.l[0]; |
| 548 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 549 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 550 | UML_MOV(block, I0, DRC_REG(rd)); |
| 551 | UML_AND(block, I1, DRC_REG(rs), 0x1f); |
| 552 | UML_SHR(block, DRC_REG(rd), I0, I1); |
| 553 | UML_SUB(block, I2, 32, I1); |
| 554 | UML_SHL(block( I2, I0, I2); |
| 555 | UML_OR(block, DRC_REG(rd), DRC_REG(rd), I2); |
| 556 | UML_SUB(block, I1, I1, 1); |
| 557 | UML_SHL(block, I1, 1, I1); |
| 558 | UML_TEST(block, I0, I1); |
| 559 | UML_MOVc(block, COND_NZ, I0, C_MASK); |
| 560 | UML_MOVc(block, COND_Z, I0, 0); |
| 561 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK | C_MASK)); |
| 562 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 563 | UML_OR(block, DRC_CSPR, DRC_CPSR, I0); |
| 564 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 565 | } |
| 566 | |
| 567 | const void drctg04_00_08(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* TST Rd, Rs */ |
| 568 | { |
| 569 | UINT32 op = desc->opptr.l[0]; |
| 570 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 571 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 572 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 573 | UML_AND(block, I2, DRC_REG(rd), DRC_REG(rs)); |
| 574 | DRCHandleALUNZFlags(I2); |
| 575 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 576 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 577 | } |
| 578 | |
| 579 | const void drctg04_00_09(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* NEG Rd, Rs */ |
| 580 | { |
| 581 | UINT32 op = desc->opptr.l[0]; |
| 582 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 583 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 584 | UML_MOV(block, I3, DRC_REG(rs)); |
| 585 | UML_SUB(block, DRC_REG(rd), 0, I3); |
| 586 | DRCHandleThumbALUSubFlags(DRC_REG(rd), 0, I3); |
| 587 | } |
| 588 | |
| 589 | const void drctg04_00_0a(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* CMP Rd, Rs */ |
| 590 | { |
| 591 | UINT32 op = desc->opptr.l[0]; |
| 592 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 593 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 594 | UML_SUB(block, I3, DRC_REG(rd), DRC_REG(rs)); |
| 595 | DRCHandleThumbALUSubFlags(I3, DRC_REG(rd), DRC_REG(rs)); |
| 596 | } |
| 597 | |
| 598 | const void drctg04_00_0b(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* CMN Rd, Rs - check flags, add dasm */ |
| 599 | { |
| 600 | UINT32 op = desc->opptr.l[0]; |
| 601 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 602 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 603 | UML_ADD(block, I3, DRC_REG(rd), DRC_REG(rs)); |
| 604 | DRCHandleThumbALUAddFlags(I3, DRC_REG(rd), DRC_REG(rs)); |
| 605 | } |
| 606 | |
| 607 | const void drctg04_00_0c(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ORR Rd, Rs */ |
| 608 | { |
| 609 | UINT32 op = desc->opptr.l[0]; |
| 610 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 611 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 612 | UML_OR(block, DRC_REG(rd), DRC_REG(rd), DRC_REG(rs)); |
| 613 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 614 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 615 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 616 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 617 | } |
| 618 | |
| 619 | const void drctg04_00_0d(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* MUL Rd, Rs */ |
| 620 | { |
| 621 | UINT32 op = desc->opptr.l[0]; |
| 622 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 623 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 624 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 625 | UML_MULU(block, DRC_REG(rd), I1, DRC_REG(rd), DRC_REG(rs)); |
| 626 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 627 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 628 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 629 | } |
| 630 | |
| 631 | const void drctg04_00_0e(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* BIC Rd, Rs */ |
| 632 | { |
| 633 | UINT32 op = desc->opptr.l[0]; |
| 634 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 635 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 636 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 637 | UML_XOR(block, I0, DRC_REG(rs), ~0); |
| 638 | UML_AND(block, DRC_REG(rd), DRC_REG(rd), I0); |
| 639 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 640 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 641 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 642 | } |
| 643 | |
| 644 | const void drctg04_00_0f(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* MVN Rd, Rs */ |
| 645 | { |
| 646 | UINT32 op = desc->opptr.l[0]; |
| 647 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 648 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 649 | UML_XOR(block, I0, DRC_REG(rs), ~0); |
| 650 | UML_MOV(block, DRC_REG(rd), I0); |
| 651 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~(Z_MASK | N_MASK)); |
| 652 | DRCHandleALUNZFlags(DRC_REG(rd)); |
| 653 | UML_OR(block, DRC_CPSR, DRC_CPSR, I0); |
| 654 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 655 | } |
| 656 | |
| 657 | /* ADD Rd, Rs group */ |
| 658 | |
| 659 | const void drctg04_01_00(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 660 | { |
| 661 | UINT32 op = desc->opptr.l[0]; |
| 662 | fatalerror("%08x: G4-1-0 Undefined Thumb instruction: %04x %x\n", pc, op, (op & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT); |
| 663 | } |
| 664 | |
| 665 | const void drctg04_01_01(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADD Rd, HRs */ |
| 666 | { |
| 667 | UINT32 op = desc->opptr.l[0]; |
| 668 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 669 | UINT32 rd = op & THUMB_HIREG_RD; |
| 670 | UML_ADD(block, DRC_REG(rd), DRC_REG(rd), DRC_REG(rs+8)); |
| 671 | if (rs == 7) |
| 672 | { |
| 673 | UML_ADD(block, DRC_REG(rd), DRC_REG(rd), 4); |
| 674 | } |
| 675 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 676 | } |
| 677 | |
| 678 | const void drctg04_01_02(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADD HRd, Rs */ |
| 679 | { |
| 680 | UINT32 op = desc->opptr.l[0]; |
| 681 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 682 | UINT32 rd = op & THUMB_HIREG_RD; |
| 683 | UML_ADD(block, DRC_REG(rd+8), DRC_REG(rd+8), DRC_REG(rs)); |
| 684 | if (rd == 7) |
| 685 | { |
| 686 | UML_ADD(block, DRC_REG(rd), DRC_REG(rd), 4); |
| 687 | } |
| 688 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 689 | } |
| 690 | |
| 691 | const void drctg04_01_03(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Add HRd, HRs */ |
| 692 | { |
| 693 | UINT32 op = desc->opptr.l[0]; |
| 694 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 695 | UINT32 rd = op & THUMB_HIREG_RD; |
| 696 | UML_ADD(block, DRC_REG(rd+8), DRC_REG(rd+8), DRC_REG(rs+8)); |
| 697 | // emulate the effects of pre-fetch |
| 698 | if (rs == 7) |
| 699 | { |
| 700 | UML_ADD(block, DRC_REG(rd+8), DRC_REG(rd+8), 4); |
| 701 | } |
| 702 | if (rd == 7) |
| 703 | { |
| 704 | UML_ADD(block, DRC_REG(rd+8), DRC_REG(rd+8), 2); |
| 705 | } |
| 706 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 707 | } |
| 708 | |
| 709 | const void drctg04_01_10(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* CMP Rd, Rs */ |
| 710 | { |
| 711 | UINT32 op = desc->opptr.l[0]; |
| 712 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 713 | UINT32 rd = op & THUMB_HIREG_RD; |
| 714 | UML_SUB(block, I3, DRC_REG(rd), DRC_REG(rs)); |
| 715 | DRCHandleThumbALUSubFlags(I3, DRC_REG(rd), DRC_REG(rs)); |
| 716 | } |
| 717 | |
| 718 | const void drctg04_01_11(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* CMP Rd, Hs */ |
| 719 | { |
| 720 | UINT32 op = desc->opptr.l[0]; |
| 721 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 722 | UINT32 rd = op & THUMB_HIREG_RD; |
| 723 | UML_SUB(block, I3, DRC_REG(rd), DRC_REG(rs+8)); |
| 724 | DRCHandleThumbALUSubFlags(I3, DRC_REG(rd), DRC_REG(rs+8)); |
| 725 | } |
| 726 | |
| 727 | const void drctg04_01_12(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* CMP Hd, Rs */ |
| 728 | { |
| 729 | UINT32 op = desc->opptr.l[0]; |
| 730 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); |
| 731 | UINT32 rd = op & THUMB_HIREG_RD; |
| 732 | UML_SUB(block, I3, DRC_REG(rd+8), DRC_REG(rs)); |
| 733 | DRCHandleThumbALUSubFlags(I3, DRC_REG(rd+8), DRC_REG(rs)); |
| 734 | } |
| 735 | |
| 736 | const void drctg04_01_13(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* CMP Hd, Hs */ |
| 737 | { |
| 738 | UINT32 op = desc->opptr.l[0]; |
| 739 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); |
| 740 | UINT32 rd = op & THUMB_HIREG_RD; |
| 741 | UML_SUB(block, I3, DRC_REG(rd+8), DRC_REG(rs+8)); |
| 742 | DRCHandleThumbALUSubFlags(I3, DRC_REG(rd+8), DRC_REG(rs+8)); |
| 743 | } |
| 744 | |
| 745 | /* MOV group */ |
| 746 | |
| 747 | const void drctg04_01_20(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* MOV Rd, Rs (undefined) */ |
| 748 | { |
| 749 | UINT32 op = desc->opptr.l[0]; |
| 750 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 751 | UINT32 rd = op & THUMB_HIREG_RD; |
| 752 | UML_MOV(block, DRC_REG(rd), DRC_REG(rs)); |
| 753 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 754 | } |
| 755 | |
| 756 | const void drctg04_01_21(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* MOV Rd, Hs */ |
| 757 | { |
| 758 | UINT32 op = desc->opptr.l[0]; |
| 759 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 760 | UINT32 rd = op & THUMB_HIREG_RD; |
| 761 | UML_MOV(block, DRC_REG(rd), DRC_REG(rs+8)); |
| 762 | if (rs == 7) |
| 763 | { |
| 764 | UML_ADD(block, DRC_REG(rd), DRC_REG(rd), 4); |
| 765 | } |
| 766 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 767 | } |
| 768 | |
| 769 | const void drctg04_01_22(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* MOV Hd, Rs */ |
| 770 | { |
| 771 | UINT32 op = desc->opptr.l[0]; |
| 772 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 773 | UINT32 rd = op & THUMB_HIREG_RD; |
| 774 | UML_MOV(block, DRC_REG(rd+8), DRC_REG(rs)); |
| 775 | // CHECKME |
| 776 | if (rd != 7) |
| 777 | { |
| 778 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 779 | } |
| 780 | else |
| 781 | { |
| 782 | UML_AND(block, DRC_PC, DRC_PC, ~1); |
| 783 | } |
| 784 | } |
| 785 | |
| 786 | const void drctg04_01_23(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* MOV Hd, Hs */ |
| 787 | { |
| 788 | UINT32 op = desc->opptr.l[0]; |
| 789 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 790 | UINT32 rd = op & THUMB_HIREG_RD; |
| 791 | UML_MOV(block, DRC_REG(rd+8), DRC_REG(rs+8)); |
| 792 | if (rs == 7) |
| 793 | { |
| 794 | UML_ADD(block, DRC_REG(rd+8), DRC_REG(rd+8), 4); |
| 795 | } |
| 796 | if (rd != 7) |
| 797 | { |
| 798 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 799 | } |
| 800 | else |
| 801 | { |
| 802 | UML_AND(block, DRC_PC, DRC_PC, ~1); |
| 803 | } |
| 804 | |
| 805 | } |
| 806 | |
| 807 | const void drctg04_01_30(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 808 | { |
| 809 | UINT32 op = desc->opptr.l[0]; |
| 810 | code_label switch_state; |
| 811 | code_label done; |
| 812 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 813 | UML_MOV(block, I0, DRC_REG(rs); |
| 814 | UML_TEST(block, I0, 1); |
| 815 | UML_JMPc(block, COND_Z, switch_state = compiler->labelnum++); |
| 816 | UML_AND(block, I0, I0, ~1); |
| 817 | UML_JMP(block, done = compiler->labelnum++); |
| 818 | |
| 819 | UML_LABEL(block, switch_state); |
| 820 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~T_MASK); |
| 821 | UML_TEST(block, I0, 2); |
| 822 | UML_MOVc(block, COND_NZ, I1, 2); |
| 823 | UML_MOVc(block, COND_Z, I1, 0); |
| 824 | UML_ADD(block, I0, I0, I1); |
| 825 | |
| 826 | UML_LABEL(block, done); |
| 827 | UML_MOV(block, DRC_PC, I0); |
| 828 | } |
| 829 | |
| 830 | const void drctg04_01_31(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 831 | { |
| 832 | UINT32 op = desc->opptr.l[0]; |
| 833 | code_label switch_state; |
| 834 | code_label done; |
| 835 | UINT32 rs = (op & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; |
| 836 | UML_MOV(block, I0, DRC_REG(rs+8); |
| 837 | if(rs == 7) |
| 838 | { |
| 839 | UML_ADD(block, I0, I0, 2); |
| 840 | } |
| 841 | UML_TEST(block, I0, 1); |
| 842 | UML_JMPc(block, COND_Z, switch_state = compiler->labelnum++); |
| 843 | UML_AND(block, I0, I0, ~1); |
| 844 | UML_JMP(block, done = compiler->labelnum++); |
| 845 | |
| 846 | UML_LABEL(block, switch_state); |
| 847 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~T_MASK); |
| 848 | UML_TEST(block, I0, 2); |
| 849 | UML_MOVc(block, COND_NZ, I1, 2); |
| 850 | UML_MOVc(block, COND_Z, I1, 0); |
| 851 | UML_ADD(block, I0, I0, I1); |
| 852 | |
| 853 | UML_LABEL(block, done); |
| 854 | UML_MOV(block, DRC_PC, I0); |
| 855 | } |
| 856 | |
| 857 | const void drctg04_01_32(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 858 | { |
| 859 | UINT32 op = desc->opptr.l[0]; |
| 860 | fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, op); |
| 861 | } |
| 862 | |
| 863 | const void drctg04_01_33(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 864 | { |
| 865 | UINT32 op = desc->opptr.l[0]; |
| 866 | fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, op); |
| 867 | } |
| 868 | |
| 869 | const void drctg04_0203(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 870 | { |
| 871 | UINT32 op = desc->opptr.l[0]; |
| 872 | UINT32 rd = (op & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; |
| 873 | UINT32 imm = 4 + ((op & THUMB_INSN_IMM) << 2); |
| 874 | UML_AND(block, I0, DRC_PC, ~2); |
| 875 | UML_ADD(block, I0, I0, imm); |
| 876 | UML_CALLH(block, *arm->impstate->read32); |
| 877 | UML_MOV(block, DRC_REG(rd), I0); |
| 878 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 879 | } |
| 880 | |
| 881 | /* LDR* STR* group */ |
| 882 | |
| 883 | const void drctg05_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* STR Rd, [Rn, Rm] */ |
| 884 | { |
| 885 | UINT32 op = desc->opptr.l[0]; |
| 886 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 887 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 888 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 889 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 890 | UML_MOV(block, I1, DRC_REG(rd)); |
| 891 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 892 | UML_CALLH(block, *arm->impstate->write32); |
| 893 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 894 | } |
| 895 | |
| 896 | const void drctg05_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* STRH Rd, [Rn, Rm] */ |
| 897 | { |
| 898 | UINT32 op = desc->opptr.l[0]; |
| 899 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 900 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 901 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 902 | UML_MOV(block, I1, DRC_REG(rd)); |
| 903 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 904 | UML_CALLH(block, *arm->impstate->write16); |
| 905 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 906 | } |
| 907 | |
| 908 | const void drctg05_2(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* STRB Rd, [Rn, Rm] */ |
| 909 | { |
| 910 | UINT32 op = desc->opptr.l[0]; |
| 911 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 912 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 913 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 914 | UINT32 addr = GET_REGISTER(arm, rn) + GET_REGISTER(arm, rm); |
| 915 | UML_MOV(block, I1, DRC_REG(rd)); |
| 916 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 917 | UML_CALLH(block, *arm->impstate->write16); |
| 918 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 919 | } |
| 920 | |
| 921 | const void drctg05_3(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* LDSB Rd, [Rn, Rm] todo, add dasm */ |
| 922 | { |
| 923 | UINT32 op = desc->opptr.l[0]; |
| 924 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 925 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 926 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 927 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 928 | UML_CALLH(block, *arm->impstate->read8); |
| 929 | UML_SEXT(block, DRC_REG(rd), I0, SIZE_BYTE); |
| 930 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 931 | } |
| 932 | |
| 933 | const void drctg05_4(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* LDR Rd, [Rn, Rm] */ |
| 934 | { |
| 935 | UINT32 op = desc->opptr.l[0]; |
| 936 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 937 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 938 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 939 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 940 | UML_CALLH(block, *arm->impstate->read32); |
| 941 | UML_MOV(block, DRC_REG(rd), I0); |
| 942 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 943 | } |
| 944 | |
| 945 | const void drctg05_5(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* LDRH Rd, [Rn, Rm] */ |
| 946 | { |
| 947 | UINT32 op = desc->opptr.l[0]; |
| 948 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 949 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 950 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 951 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 952 | UML_CALLH(block, *arm->impstate->read16); |
| 953 | UML_MOV(block, DRC_REG(rd), I0); |
| 954 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 955 | } |
| 956 | |
| 957 | const void drctg05_6(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* LDRB Rd, [Rn, Rm] */ |
| 958 | { |
| 959 | UINT32 op = desc->opptr.l[0]; |
| 960 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 961 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 962 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 963 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 964 | UML_CALLH(block, *arm->impstate->read8); |
| 965 | UML_MOV(block, DRC_REG(rd), I0); |
| 966 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 967 | } |
| 968 | |
| 969 | const void drctg05_7(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* LDSH Rd, [Rn, Rm] */ |
| 970 | { |
| 971 | UINT32 op = desc->opptr.l[0]; |
| 972 | UINT32 rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; |
| 973 | UINT32 rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; |
| 974 | UINT32 rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; |
| 975 | UML_ADD(block, I0, DRC_REG(rn), DRC_REG(rm)); |
| 976 | UML_CALLH(block, *arm->impstate->read16); |
| 977 | UML_SEXT(block, DRC_REG(rd), I0, SIZE_WORD); |
| 978 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 979 | } |
| 980 | |
| 981 | /* Word Store w/ Immediate Offset */ |
| 982 | |
| 983 | const void drctg06_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Store */ |
| 984 | { |
| 985 | UINT32 op = desc->opptr.l[0]; |
| 986 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 987 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 988 | INT32 offs = ((op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; |
| 989 | UML_ADD(block, I0, DRC_REG(rn), offs); |
| 990 | UML_MOV(block, I1, DRC_REG(rd)); |
| 991 | UML_CALLH(block, *arm->impstate->write32); |
| 992 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 993 | } |
| 994 | |
| 995 | const void drctg06_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Load */ |
| 996 | { |
| 997 | UINT32 op = desc->opptr.l[0]; |
| 998 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 999 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 1000 | INT32 offs = ((op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; |
| 1001 | UML_ADD(block, I0, DRC_REG(rn), offs); |
| 1002 | UML_CALLH(block, *arm->impstate->read32); |
| 1003 | UML_MOV(block, DRC_REG(rd), I0); |
| 1004 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1005 | } |
| 1006 | |
| 1007 | /* Byte Store w/ Immeidate Offset */ |
| 1008 | |
| 1009 | const void drctg07_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Store */ |
| 1010 | { |
| 1011 | UINT32 op = desc->opptr.l[0]; |
| 1012 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1013 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 1014 | INT32 offs = (op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; |
| 1015 | UML_ADD(block, I0, DRC_REG(rn), offs); |
| 1016 | UML_MOV(block, I1, DRC_REG(rd)); |
| 1017 | UML_CALLH(block, *arm->impstate->write8); |
| 1018 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1019 | } |
| 1020 | |
| 1021 | const void drctg07_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Load */ |
| 1022 | { |
| 1023 | UINT32 op = desc->opptr.l[0]; |
| 1024 | UINT32 rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1025 | UINT32 rd = op & THUMB_ADDSUB_RD; |
| 1026 | INT32 offs = (op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; |
| 1027 | UML_ADD(block, I0, DRC_REG(rn), offs); |
| 1028 | UML_CALLH(block, *arm->impstate->read8); |
| 1029 | UML_MOV(block, DRC_REG(rd), I0); |
| 1030 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1031 | } |
| 1032 | |
| 1033 | /* Load/Store Halfword */ |
| 1034 | |
| 1035 | const void drctg08_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Store */ |
| 1036 | { |
| 1037 | UINT32 op = desc->opptr.l[0]; |
| 1038 | UINT32 offs = (op & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; |
| 1039 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1040 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 1041 | UML_ADD(block, I0, DRC_REG(rn), offs << 1); |
| 1042 | UML_MOV(block, I1, DRC_REG(rd)); |
| 1043 | UML_CALLH(block, *arm->impstate->write16); |
| 1044 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1045 | } |
| 1046 | |
| 1047 | const void drctg08_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Load */ |
| 1048 | { |
| 1049 | UINT32 op = desc->opptr.l[0]; |
| 1050 | UINT32 offs = (op & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; |
| 1051 | UINT32 rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; |
| 1052 | UINT32 rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; |
| 1053 | UML_ADD(block, I0, DRC_REG(rn), offs << 1); |
| 1054 | UML_CALLH(block, *arm->impstate->read16); |
| 1055 | UML_MOV(block, DRC_REG(rd), I0); |
| 1056 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1057 | } |
| 1058 | |
| 1059 | /* Stack-Relative Load/Store */ |
| 1060 | |
| 1061 | const void drctg09_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Store */ |
| 1062 | { |
| 1063 | UINT32 op = desc->opptr.l[0]; |
| 1064 | UINT32 rd = (op & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; |
| 1065 | INT32 offs = (UINT8)(op & THUMB_INSN_IMM) << 2; |
| 1066 | UML_ADD(block, I0, DRC_REG(13), offs); |
| 1067 | UML_MOV(block, I1, DRC_REG(rd)); |
| 1068 | UML_CALLH(block, *arm->impstate->write32); |
| 1069 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1070 | } |
| 1071 | |
| 1072 | const void drctg09_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Load */ |
| 1073 | { |
| 1074 | UINT32 op = desc->opptr.l[0]; |
| 1075 | UINT32 rd = (op & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; |
| 1076 | UINT32 offs = (UINT8)(op & THUMB_INSN_IMM) << 2; |
| 1077 | UML_ADD(block, I0, DRC_REG(13), offs); |
| 1078 | UML_CALLH(block, *arm->impstate->read32); |
| 1079 | UML_MOV(block, DRC_REG(rd), I0); |
| 1080 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1081 | } |
| 1082 | |
| 1083 | /* Get relative address */ |
| 1084 | |
| 1085 | const void drctg0a_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADD Rd, PC, #nn */ |
| 1086 | { |
| 1087 | UINT32 op = desc->opptr.l[0]; |
| 1088 | UINT32 rd = (op & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; |
| 1089 | INT32 offs = (UINT8)(op & THUMB_INSN_IMM) << 2; |
| 1090 | UML_ADD(block, I0, DRC_PC, 4); |
| 1091 | UML_AND(block, I0, I0, ~2); |
| 1092 | UML_ADD(block, DRC_REG(rd), I0, offs); |
| 1093 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1094 | } |
| 1095 | |
| 1096 | const void drctg0a_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADD Rd, SP, #nn */ |
| 1097 | { |
| 1098 | UINT32 op = desc->opptr.l[0]; |
| 1099 | UINT32 rd = (op & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; |
| 1100 | INT32 offs = (UINT8)(op & THUMB_INSN_IMM) << 2; |
| 1101 | UML_ADD(block, DRC_REG(rd), DRC_REG(13), offs); |
| 1102 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1103 | } |
| 1104 | |
| 1105 | /* Stack-Related Opcodes */ |
| 1106 | |
| 1107 | const void drctg0b_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* ADD SP, #imm */ |
| 1108 | { |
| 1109 | UINT32 op = desc->opptr.l[0]; |
| 1110 | INT32 addr = (op & THUMB_INSN_IMM); |
| 1111 | addr &= ~THUMB_INSN_IMM_S; |
| 1112 | addr = ((op & THUMB_INSN_IMM_S) ? -(addr << 2) : (addr << 2)); |
| 1113 | UML_ADD(block, DRC_REG(13), DRC_REG(13), addr); |
| 1114 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1115 | } |
| 1116 | |
| 1117 | const void drctg0b_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1118 | { |
| 1119 | UINT32 op = desc->opptr.l[0]; |
| 1120 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1121 | } |
| 1122 | |
| 1123 | const void drctg0b_2(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1124 | { |
| 1125 | UINT32 op = desc->opptr.l[0]; |
| 1126 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1127 | } |
| 1128 | |
| 1129 | const void drctg0b_3(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1130 | { |
| 1131 | UINT32 op = desc->opptr.l[0]; |
| 1132 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1133 | } |
| 1134 | |
| 1135 | const void drctg0b_4(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* PUSH {Rlist} */ |
| 1136 | { |
| 1137 | UINT32 op = desc->opptr.l[0]; |
| 1138 | for (INT32 offs = 7; offs >= 0; offs--) |
| 1139 | { |
| 1140 | if (op & (1 << offs)) |
| 1141 | { |
| 1142 | UML_SUB(block, DRC_REG(13), DRC_REG(13), 4); |
| 1143 | UML_MOV(block, I0, DRC_REG(13)); |
| 1144 | UML_MOV(block, I1, DRC_REG(offs)); |
| 1145 | UML_CALLH(block, *arm->impstate->write32); |
| 1146 | } |
| 1147 | } |
| 1148 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1149 | } |
| 1150 | |
| 1151 | const void drctg0b_5(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* PUSH {Rlist}{LR} */ |
| 1152 | { |
| 1153 | UINT32 op = desc->opptr.l[0]; |
| 1154 | UML_SUB(block, DRC_REG(13), DRC_REG(13), 4); |
| 1155 | UML_MOV(block, I0, DRC_REG(13)); |
| 1156 | UML_MOV(block, I1, DRC_REG(14)); |
| 1157 | UML_CALLH(block, *arm->impstate->write32); |
| 1158 | for (INT32 offs = 7; offs >= 0; offs--) |
| 1159 | { |
| 1160 | if (op & (1 << offs)) |
| 1161 | { |
| 1162 | UML_SUB(block, DRC_REG(13), DRC_REG(13), 4); |
| 1163 | UML_MOV(block, I0, DRC_REG(13)); |
| 1164 | UML_MOV(block, I1, DRC_REG(offs)); |
| 1165 | UML_CALLH(block, *arm->impstate->write32); |
| 1166 | } |
| 1167 | } |
| 1168 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1169 | } |
| 1170 | |
| 1171 | const void drctg0b_6(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1172 | { |
| 1173 | UINT32 op = desc->opptr.l[0]; |
| 1174 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1175 | } |
| 1176 | |
| 1177 | const void drctg0b_7(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1178 | { |
| 1179 | UINT32 op = desc->opptr.l[0]; |
| 1180 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1181 | } |
| 1182 | |
| 1183 | const void drctg0b_8(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1184 | { |
| 1185 | UINT32 op = desc->opptr.l[0]; |
| 1186 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1187 | } |
| 1188 | |
| 1189 | const void drctg0b_9(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1190 | { |
| 1191 | UINT32 op = desc->opptr.l[0]; |
| 1192 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1193 | } |
| 1194 | |
| 1195 | const void drctg0b_a(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1196 | { |
| 1197 | UINT32 op = desc->opptr.l[0]; |
| 1198 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1199 | } |
| 1200 | |
| 1201 | const void drctg0b_b(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1202 | { |
| 1203 | UINT32 op = desc->opptr.l[0]; |
| 1204 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1205 | } |
| 1206 | |
| 1207 | const void tg0b_c(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* POP {Rlist} */ |
| 1208 | { |
| 1209 | UINT32 op = desc->opptr.l[0]; |
| 1210 | for (INT32 offs = 0; offs < 8; offs++) |
| 1211 | { |
| 1212 | if (op & (1 << offs)) |
| 1213 | { |
| 1214 | UML_MOV(block, I0, DRC_REG(13)); |
| 1215 | UML_CALLH(block, *arm->impstate->read32); |
| 1216 | UML_MOV(block, DRC_REG(offs), I0); |
| 1217 | UML_ADD(block, DRC_REG(13), DRC_REG(13), 4); |
| 1218 | } |
| 1219 | } |
| 1220 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1221 | } |
| 1222 | |
| 1223 | const void drctg0b_d(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* POP {Rlist}{PC} */ |
| 1224 | { |
| 1225 | UINT32 op = desc->opptr.l[0]; |
| 1226 | code_label arch5up; |
| 1227 | code_label done; |
| 1228 | code_label switch_mode; |
| 1229 | for (INT32 offs = 0; offs < 8; offs++) |
| 1230 | { |
| 1231 | if (op & (1 << offs)) |
| 1232 | { |
| 1233 | UML_MOV(block, I0, DRC_REG(13)); |
| 1234 | UML_CALLH(block, *arm->impstate->read32); |
| 1235 | UML_MOV(block, DRC_REG(offs), I0); |
| 1236 | UML_ADD(block, DRC_REG(13), DRC_REG(13), 4); |
| 1237 | } |
| 1238 | } |
| 1239 | UML_MOV(block, I0, DRC_REG(13)); |
| 1240 | UML_CALLH(block, *arm->impstate->read32); |
| 1241 | UML_CMP(block, mem(&arm->archRev), 4); |
| 1242 | UML_JMPc(block, COND_A, arch5up = compiler->labelnum++); |
| 1243 | UML_AND(block, DRC_PC, I0, ~1); |
| 1244 | |
| 1245 | UML_LABEL(block, arch5up); |
| 1246 | |
| 1247 | UML_TEST(block, I0, 1); |
| 1248 | UML_JMPc(block, COND_Z, switch_mode = compiler->labelnum++); |
| 1249 | |
| 1250 | UML_AND(block, I0, I0, ~1); |
| 1251 | UML_MOV(block, DRC_PC, I0); |
| 1252 | UML_JMP(block done); |
| 1253 | |
| 1254 | UML_LABEL(block, switch_mode); |
| 1255 | UML_AND(block, DRC_CPSR, DRC_CPSR, ~T_MASK); |
| 1256 | UML_TEST(block, I0, 2); |
| 1257 | UML_MOVc(block, COND_NZ, I1, 2); |
| 1258 | UML_MOVc(block, COND_Z, I1, 0); |
| 1259 | UML_ADD(block, I0, I0, I1); |
| 1260 | UML_MOV(block, DRC_PC, I0); |
| 1261 | |
| 1262 | UML_LABEL(block, done); |
| 1263 | UML_ADD(block, DRC_REG(13), DRC_REG(13), 4); |
| 1264 | } |
| 1265 | |
| 1266 | const void drctg0b_e(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1267 | { |
| 1268 | UINT32 op = desc->opptr.l[0]; |
| 1269 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1270 | } |
| 1271 | |
| 1272 | const void drctg0b_f(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1273 | { |
| 1274 | UINT32 op = desc->opptr.l[0]; |
| 1275 | fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, op); |
| 1276 | } |
| 1277 | |
| 1278 | /* Multiple Load/Store */ |
| 1279 | |
| 1280 | // "The address should normally be a word aligned quantity and non-word aligned addresses do not affect the instruction." |
| 1281 | // "However, the bottom 2 bits of the address will appear on A[1:0] and might be interpreted by the memory system." |
| 1282 | |
| 1283 | // GBA "BB Ball" performs an unaligned read with A[1:0] = 2 and expects A[1] not to be ignored [BP 800B90A,(R4&3)!=0] |
| 1284 | // GBA "Gadget Racers" performs an unaligned read with A[1:0] = 1 and expects A[0] to be ignored [BP B72,(R0&3)!=0] |
| 1285 | |
| 1286 | const void drctg0c_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Store */ |
| 1287 | { |
| 1288 | UINT32 op = desc->opptr.l[0]; |
| 1289 | UINT32 rd = (op & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT; |
| 1290 | UML_MOV(block, I2, DRC_REG(rd)); |
| 1291 | for (INT32 offs = 0; offs < 8; offs++) |
| 1292 | { |
| 1293 | if (op & (1 << offs)) |
| 1294 | { |
| 1295 | UML_AND(block, I0, I2, ~3); |
| 1296 | UML_MOV(block, I1, DRC_REG(offs)); |
| 1297 | UML_CALLH(block, *arm->impstate->write32); |
| 1298 | UML_ADD(block, I2, I2, 4); |
| 1299 | } |
| 1300 | } |
| 1301 | UML_MOV(block, DRC_REG(rd), I2); |
| 1302 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1303 | } |
| 1304 | |
| 1305 | const void drctg0c_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* Load */ |
| 1306 | { |
| 1307 | UINT32 op = desc->opptr.l[0]; |
| 1308 | UINT32 rd = (op & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT; |
| 1309 | int rd_in_list = op & (1 << rd); |
| 1310 | UML_MOV(block, I2, DRC_REG(rd)); |
| 1311 | for (INT32 offs = 0; offs < 8; offs++) |
| 1312 | { |
| 1313 | if (op & (1 << offs)) |
| 1314 | { |
| 1315 | UML_AND(block, I0, I2, ~1); |
| 1316 | UML_CALLH(block, *arm->impstate->read32); |
| 1317 | UML_ADD(block, I2, I2, 4); |
| 1318 | } |
| 1319 | } |
| 1320 | if (!rd_in_list) |
| 1321 | { |
| 1322 | UML_MOV(block, DRC_REG(rd), I2); |
| 1323 | } |
| 1324 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1325 | } |
| 1326 | |
| 1327 | /* Conditional Branch */ |
| 1328 | |
| 1329 | const void drctg0d_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_EQ: |
| 1330 | { |
| 1331 | UINT32 op = desc->opptr.l[0]; |
| 1332 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1333 | UML_TEST(block, DRC_CPSR, Z_MASK); |
| 1334 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1335 | UML_MOVc(block, COND_Z, I0, 2); |
| 1336 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1337 | } |
| 1338 | |
| 1339 | const void drctg0d_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_NE: |
| 1340 | { |
| 1341 | UINT32 op = desc->opptr.l[0]; |
| 1342 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1343 | UML_TEST(block, DRC_CPSR, Z_MASK); |
| 1344 | UML_MOVc(block, COND_Z, I0, offs); |
| 1345 | UML_MOVc(block, COND_NZ, I0, 2); |
| 1346 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1347 | } |
| 1348 | |
| 1349 | const void drctg0d_2(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_CS: |
| 1350 | { |
| 1351 | UINT32 op = desc->opptr.l[0]; |
| 1352 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1353 | UML_TEST(block, DRC_CPSR, C_MASK); |
| 1354 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1355 | UML_MOVc(block, COND_Z, I0, 2); |
| 1356 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1357 | } |
| 1358 | |
| 1359 | const void drctg0d_3(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_CC: |
| 1360 | { |
| 1361 | UINT32 op = desc->opptr.l[0]; |
| 1362 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1363 | UML_TEST(block, DRC_CPSR, C_MASK); |
| 1364 | UML_MOVc(block, COND_Z, I0, offs); |
| 1365 | UML_MOVc(block, COND_NZ, I0, 2); |
| 1366 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1367 | } |
| 1368 | |
| 1369 | const void drctg0d_4(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_MI: |
| 1370 | { |
| 1371 | UINT32 op = desc->opptr.l[0]; |
| 1372 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1373 | UML_TEST(block, DRC_CPSR, N_MASK); |
| 1374 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1375 | UML_MOVc(block, COND_Z, I0, 2); |
| 1376 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1377 | } |
| 1378 | |
| 1379 | const void drctg0d_5(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_PL: |
| 1380 | { |
| 1381 | UINT32 op = desc->opptr.l[0]; |
| 1382 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1383 | UML_TEST(block, DRC_CPSR, N_MASK); |
| 1384 | UML_MOVc(block, COND_Z, I0, offs); |
| 1385 | UML_MOVc(block, COND_NZ, I0, 2); |
| 1386 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1387 | } |
| 1388 | |
| 1389 | const void drctg0d_6(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_VS: |
| 1390 | { |
| 1391 | UINT32 op = desc->opptr.l[0]; |
| 1392 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1393 | UML_TEST(block, DRC_CPSR, V_MASK); |
| 1394 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1395 | UML_MOVc(block, COND_Z, I0, 2); |
| 1396 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1397 | } |
| 1398 | |
| 1399 | const void drctg0d_7(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_VC: |
| 1400 | { |
| 1401 | UINT32 op = desc->opptr.l[0]; |
| 1402 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1403 | UML_TEST(block, DRC_CPSR, V_MASK); |
| 1404 | UML_MOVc(block, COND_Z, I0, offs); |
| 1405 | UML_MOVc(block, COND_NZ, I0, 2); |
| 1406 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1407 | } |
| 1408 | |
| 1409 | const void drctg0d_8(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_HI: |
| 1410 | { |
| 1411 | UINT32 op = desc->opptr.l[0]; |
| 1412 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1413 | UML_TEST(block, DRC_CPSR, C_MASK); |
| 1414 | UML_MOVc(block, COND_NZ, I0, 1); |
| 1415 | UML_MOVc(block, COND_Z, I0, 0); |
| 1416 | UML_TEST(block, DRC_CPSR, Z_MASK); |
| 1417 | UML_MOVc(block, COND_NZ, I1, 0); |
| 1418 | UML_MOVc(block, COND_Z, I1, 1); |
| 1419 | UML_AND(block, I0, I0, I1); |
| 1420 | UML_TEST(block, I0, 1); |
| 1421 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1422 | UML_MOVc(block, COND_Z, I0, 2); |
| 1423 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1424 | } |
| 1425 | |
| 1426 | const void drctg0d_9(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_LS: |
| 1427 | { |
| 1428 | UINT32 op = desc->opptr.l[0]; |
| 1429 | INT32 offs = ((INT8)(op & THUMB_INSN_IMM) << 1) + 4; |
| 1430 | UML_TEST(block, DRC_CPSR, C_MASK); |
| 1431 | UML_MOVc(block, COND_Z, I0, 1); |
| 1432 | UML_MOVc(block, COND_NZ, I0, 0); |
| 1433 | UML_TEST(block, DRC_CPSR, Z_MASK); |
| 1434 | UML_MOVc(block, COND_Z, I1, 0); |
| 1435 | UML_MOVc(block, COND_NZ, I1, 1); |
| 1436 | UML_AND(block, I0, I0, I1); |
| 1437 | UML_TEST(block, I0, 1); |
| 1438 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1439 | UML_MOVc(block, COND_Z, I0, 2); |
| 1440 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1441 | } |
| 1442 | |
| 1443 | const void drctg0d_a(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_GE: |
| 1444 | { |
| 1445 | UINT32 op = desc->opptr.l[0]; |
| 1446 | UML_TEST(block, DRC_CPSR, N_MASK); |
| 1447 | UML_MOVc(block, COND_Z, I0, 1); |
| 1448 | UML_MOVc(block, COND_NZ, I0, 0); |
| 1449 | UML_TEST(block, DRC_CPSR, V_MASK); |
| 1450 | UML_MOVc(block, COND_Z, I1, 0); |
| 1451 | UML_MOVc(block, COND_NZ, I1, 1); |
| 1452 | UML_CMP(block, I0, I1); |
| 1453 | UML_MOVc(block, COND_E, I0, offs); |
| 1454 | UML_MOVc(block, COND_NE, I0, 2); |
| 1455 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1456 | } |
| 1457 | |
| 1458 | const void drctg0d_b(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_LT: |
| 1459 | { |
| 1460 | UINT32 op = desc->opptr.l[0]; |
| 1461 | UML_TEST(block, DRC_CPSR, N_MASK); |
| 1462 | UML_MOVc(block, COND_Z, I0, 1); |
| 1463 | UML_MOVc(block, COND_NZ, I0, 0); |
| 1464 | UML_TEST(block, DRC_CPSR, V_MASK); |
| 1465 | UML_MOVc(block, COND_Z, I1, 0); |
| 1466 | UML_MOVc(block, COND_NZ, I1, 1); |
| 1467 | UML_CMP(block, I0, I1); |
| 1468 | UML_MOVc(block, COND_NE, I0, offs); |
| 1469 | UML_MOVc(block, COND_E, I0, 2); |
| 1470 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1471 | } |
| 1472 | |
| 1473 | const void drctg0d_c(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_GT: |
| 1474 | { |
| 1475 | UINT32 op = desc->opptr.l[0]; |
| 1476 | UML_TEST(block, DRC_CPSR, N_MASK); |
| 1477 | UML_MOVc(block, COND_Z, I0, 1); |
| 1478 | UML_MOVc(block, COND_NZ, I0, 0); |
| 1479 | UML_TEST(block, DRC_CPSR, V_MASK); |
| 1480 | UML_MOVc(block, COND_Z, I1, 0); |
| 1481 | UML_MOVc(block, COND_NZ, I1, 1); |
| 1482 | UML_CMP(block, I0, I1); |
| 1483 | UML_MOVc(block, COND_E, I0, 1); |
| 1484 | UML_MOVc(block, COND_NE, I0, 0); |
| 1485 | UML_TEST(block, DRC_CPSR, Z_MASK); |
| 1486 | UML_MOVc(block, COND_NZ, I1, 1); |
| 1487 | UML_MOVc(block, COND_Z, I1, 0); |
| 1488 | UML_AND(block, I0, I0, I1); |
| 1489 | UML_TEST(block, I0, 1); |
| 1490 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1491 | UML_MOVc(block, COND_Z, I0, 2); |
| 1492 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1493 | } |
| 1494 | |
| 1495 | const void drctg0d_d(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_LE: |
| 1496 | { |
| 1497 | UINT32 op = desc->opptr.l[0]; |
| 1498 | UML_TEST(block, DRC_CPSR, N_MASK); |
| 1499 | UML_MOVc(block, COND_Z, I0, 1); |
| 1500 | UML_MOVc(block, COND_NZ, I0, 0); |
| 1501 | UML_TEST(block, DRC_CPSR, V_MASK); |
| 1502 | UML_MOVc(block, COND_Z, I1, 0); |
| 1503 | UML_MOVc(block, COND_NZ, I1, 1); |
| 1504 | UML_CMP(block, I0, I1); |
| 1505 | UML_MOVc(block, COND_NE, I0, 1); |
| 1506 | UML_MOVc(block, COND_E, I0, 0); |
| 1507 | UML_TEST(block, DRC_CPSR, Z_MASK); |
| 1508 | UML_MOVc(block, COND_NZ, I1, 0); |
| 1509 | UML_MOVc(block, COND_Z, I1, 1); |
| 1510 | UML_AND(block, I0, I0, I1); |
| 1511 | UML_TEST(block, I0, 1); |
| 1512 | UML_MOVc(block, COND_NZ, I0, offs); |
| 1513 | UML_MOVc(block, COND_Z, I0, 2); |
| 1514 | UML_ADD(block, COND_PC, COND_PC, I0); |
| 1515 | } |
| 1516 | |
| 1517 | const void drctg0d_e(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // COND_AL: |
| 1518 | { |
| 1519 | UINT32 op = desc->opptr.l[0]; |
| 1520 | fatalerror("%08x: Undefined Thumb instruction: %04x (ARM9 reserved)\n", pc, op); |
| 1521 | } |
| 1522 | |
| 1523 | const void drctg0d_f(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // SWI (this is sort of a "hole" in the opcode encoding) |
| 1524 | { |
| 1525 | UINT32 op = desc->opptr.l[0]; |
| 1526 | UML_MOV(block, mem(&arm->pendingSwi), 1); |
| 1527 | UML_CALLH(block, *arm->impstate->check_irq); |
| 1528 | } |
| 1529 | |
| 1530 | /* B #offs */ |
| 1531 | |
| 1532 | const void drctg0e_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1533 | { |
| 1534 | UINT32 op = desc->opptr.l[0]; |
| 1535 | INT32 offs = (op & THUMB_BRANCH_OFFS) << 1; |
| 1536 | if (offs & 0x00000800) |
| 1537 | { |
| 1538 | offs |= 0xfffff800; |
| 1539 | } |
| 1540 | UML_ADD(block, DRC_PC, DRC_PC, offs + 4); |
| 1541 | } |
| 1542 | |
| 1543 | const void drctg0e_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1544 | { |
| 1545 | UINT32 op = desc->opptr.l[0]; |
| 1546 | UINT32 offs = (op & THUMB_BLOP_OFFS) << 1; |
| 1547 | UML_MOV(block, I0, DRC_REG(14)); |
| 1548 | UML_ADD(block, I0, I0, offs); |
| 1549 | UML_AND(block, I0, I0, ~3); |
| 1550 | UML_ADD(block, DRC_REG(14), DRC_PC, 4); |
| 1551 | UML_OR(block, DRC_REG(14), DRC_REG(14), 1); |
| 1552 | UML_MOV(block, DRC_PC, I0); |
| 1553 | } |
| 1554 | |
| 1555 | /* BL */ |
| 1556 | |
| 1557 | const void drctg0f_0(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| 1558 | { |
| 1559 | UINT32 op = desc->opptr.l[0]; |
| 1560 | UINT32 addr = (op & THUMB_BLOP_OFFS) << 12; |
| 1561 | if (addr & (1 << 22)) |
| 1562 | { |
| 1563 | addr |= 0xff800000; |
| 1564 | } |
| 1565 | addr += 4; |
| 1566 | UML_ADD(block, DRC_REG(14), DRC_PC, addr); |
| 1567 | UML_ADD(block, DRC_PC, DRC_PC, 2); |
| 1568 | } |
| 1569 | |
| 1570 | const void drctg0f_1(arm_state *arm, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) /* BL */ |
| 1571 | { |
| 1572 | UINT32 op = desc->opptr.l[0]; |
| 1573 | UINT32 addr = (op & THUMB_BLOP_OFFS) << 1; |
| 1574 | UML_AND(block, I0, DRC_REG(14), ~1); |
| 1575 | UML_ADD(block, I0, I0, addr); |
| 1576 | UML_ADD(block, DRC_REG(14), DRC_PC, 2); |
| 1577 | UML_OR(block, DRC_REG(14), DRC_REG(14), 1); |
| 1578 | UML_MOV(block, DRC_PC, I0); |
| 1579 | } |
| 1580 | |
| 1581 | #endif // ARM7_USE_DRC |
| | No newline at end of file |