diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx index 316270705..0ec27ea3b 100644 --- a/src/emucore/Thumbulator.cxx +++ b/src/emucore/Thumbulator.cxx @@ -19,7 +19,6 @@ // This class provides Thumb emulation code ("Thumbulator") // by David Welch (dwelch@dwelch.com) // Modified by Fred Quimby -// Optimized by Christina Speckner and Thomas Jentzsch // Code is public domain and used with the author's consent //============================================================================ @@ -58,7 +57,7 @@ Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 romSize, Thumbulator::ConfigureFor configurefor, Cartridge* cartridge) : rom(rom_ptr), romSize(romSize), - decodedInstruction(new Instruction[romSize / 2]), + decodedRom(new Op[romSize / 2]), ram(ram_ptr), T1TCR(0), T1TC(0), @@ -66,7 +65,7 @@ Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 romSize, myCartridge(cartridge) { for (uint32_t i = 0; i < romSize / 2; i++) - decodeInstructionWord(CONV_RAMROM(rom[i]), decodedInstruction[i]); + decodedRom[i] = decodeInstructionWord(CONV_RAMROM(rom[i])); setConsoleTiming(ConsoleTiming::ntsc); trapFatalErrors(traponfatal); @@ -535,572 +534,227 @@ void Thumbulator::do_vflag_bit(uInt32 x) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Thumbulator::decodeInstructionWord(uint16_t inst, Instruction& instr) -{ +Thumbulator::Op Thumbulator::decodeInstructionWord(uint16_t inst) { //ADC - if((inst & 0xFFC0) == 0x4140) - { - instr.op = Op::adc; - instr.rd = (inst >> 0) & 0x07; - instr.rm = (inst >> 3) & 0x07; - } - //ADD(1) small immediate two registers - else if((inst & 0xFE00) == 0x1C00 && (inst >> 6) & 0x7) - { - instr.op = Op::add1; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rb = (inst >> 6) & 0x7; - } - //ADD(2) big immediate one register - else if((inst & 0xF800) == 0x3000) - { - instr.op = Op::add2; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x7; - } - //ADD(3) three registers - else if((inst & 0xFE00) == 0x1800) - { - instr.op = Op::add3; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } - //ADD(4) two registers one or both high no flags - else if((inst & 0xFF00) == 0x4400) - { - instr.op = Op::add4; - if((inst >> 6) & 3) - { - //UNPREDICTABLE - } - instr.rd = (inst >> 0) & 0x7; - instr.rd |= (inst >> 4) & 0x8; - instr.rm = (inst >> 3) & 0xF; - } - //ADD(5) rd = pc plus immediate - else if((inst & 0xF800) == 0xA000) - { - instr.op = Op::add5; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x7; - instr.rb <<= 2; - } - //ADD(6) rd = sp plus immediate - else if((inst & 0xF800) == 0xA800) - { - instr.op = Op::add6; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x7; - instr.rb <<= 2; - } - //ADD(7) sp plus immediate - else if((inst & 0xFF80) == 0xB000) - { - instr.op = Op::add7; - instr.rb = (inst >> 0) & 0x7F; - instr.rb <<= 2; - } - //AND - else if((inst & 0xFFC0) == 0x4000) - { - instr.op = Op::and_; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } - //ASR(1) two register immediate - else if((inst & 0xF800) == 0x1000) - { - instr.op = Op::asr1; - instr.rd = (inst >> 0) & 0x07; - instr.rm = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - } - //ASR(2) two register - else if((inst & 0xFFC0) == 0x4100) - { - instr.op = Op::asr2; - instr.rd = (inst >> 0) & 0x07; - instr.rs = (inst >> 3) & 0x07; - } - //B(1) conditional branch - else if((inst & 0xF000) == 0xD000) - { - instr.op = Op::b1; - instr.rb = (inst >> 0) & 0xFF; - if(instr.rb & 0x80) - instr.rb |= (~0u) << 8; - instr.rb <<= 1; - instr.rb += 2; - } - //B(2) unconditional branch - else if((inst & 0xF800) == 0xE000) - { - instr.op = Op::b2; - instr.rb = (inst >> 0) & 0x7FF; - if(instr.rb & (1 << 10)) - instr.rb |= (~0u) << 11; - instr.rb <<= 1; - instr.rb += 2; - } - //BIC - else if((inst & 0xFFC0) == 0x4380) - { - instr.op = Op::bic; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } - //BKPT - else if((inst & 0xFF00) == 0xBE00) - { - instr.op = Op::bkpt; - instr.rb = (inst >> 0) & 0xFF; - } - //BL/BLX(1) - else if((inst & 0xE000) == 0xE000) - { - instr.op = Op::blx1; - if((inst & 0x1800) == 0x1000) //H=b10 - { - instr.rb = inst & ((1 << 11) - 1); - if(instr.rb & 1 << 10) - instr.rb |= (~((1 << 11) - 1)); //sign extend - instr.rb <<= 12; - } - else if((inst & 0x1800) == 0x1800) //H=b11 - { - instr.rb = (inst & ((1 << 11) - 1)) << 1; - instr.rb += 2; - } - else if((inst & 0x1800) == 0x0800) //H=b01 - { - instr.rb = (inst & ((1 << 11) - 1)) << 1; - } - } - //BLX(2) - else if((inst & 0xFF87) == 0x4780) - { - instr.op = Op::blx2; - instr.rm = (inst >> 3) & 0xF; - } - //BX - else if((inst & 0xFF87) == 0x4700) - { - instr.op = Op::bx; - instr.rm = (inst >> 3) & 0xF; - } - //CMN - else if((inst & 0xFFC0) == 0x42C0) - { - instr.op = Op::cmn; - instr.rn = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } - //CMP(1) compare immediate - else if((inst & 0xF800) == 0x2800) - { - instr.op = Op::cmp1; - instr.rb = (inst >> 0) & 0xFF; - instr.rn = (inst >> 8) & 0x07; - } - //CMP(2) compare register - else if((inst & 0xFFC0) == 0x4280) - { - instr.op = Op::cmp2; - instr.rn = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } - //CMP(3) compare high register - else if((inst & 0xFF00) == 0x4500) - { - instr.op = Op::cmp3; - if(((inst >> 6) & 3) == 0x0) - { - //UNPREDICTABLE - } - instr.rn = (inst >> 0) & 0x7; - instr.rn |= (inst >> 4) & 0x8; - if(instr.rn == 0xF) - { - //UNPREDICTABLE - } - instr.rm = (inst >> 3) & 0xF; - } - //CPS - else if((inst & 0xFFE8) == 0xB660) - { - instr.op = Op::cps; - } - //CPY copy high register - else if((inst & 0xFFC0) == 0x4600) - { - instr.op = Op::cpy; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } - //EOR - else if((inst & 0xFFC0) == 0x4040) - { - instr.op = Op::eor; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } - //LDMIA - else if((inst & 0xF800) == 0xC800) - { - instr.op = Op::ldmia; - instr.rn = (inst >> 8) & 0x7; - } - //LDR(1) two register immediate - else if((inst & 0xF800) == 0x6800) - { - instr.op = Op::ldr1; - instr.rd = (inst >> 0) & 0x07; - instr.rn = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - instr.rb <<= 2; - } - //LDR(2) three register - else if((inst & 0xFE00) == 0x5800) - { - instr.op = Op::ldr2; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } - //LDR(3) - else if((inst & 0xF800) == 0x4800) - { - instr.op = Op::ldr3; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x07; - instr.rb <<= 2; + if((inst & 0xFFC0) == 0x4140) return Op::adc; + + //ADD(1) small immediate two registers + if((inst & 0xFE00) == 0x1C00 && (inst >> 6) & 0x7) return Op::add1; + + //ADD(2) big immediate one register + if((inst & 0xF800) == 0x3000) return Op::add2; + + //ADD(3) three registers + if((inst & 0xFE00) == 0x1800) return Op::add3; + + //ADD(4) two registers one or both high no flags + if((inst & 0xFF00) == 0x4400) return Op::add4; + + //ADD(5) rd = pc plus immediate + if((inst & 0xF800) == 0xA000) return Op::add5; + + //ADD(6) rd = sp plus immediate + if((inst & 0xF800) == 0xA800) return Op::add6; + + //ADD(7) sp plus immediate + if((inst & 0xFF80) == 0xB000) return Op::add7; + + //AND + if((inst & 0xFFC0) == 0x4000) return Op::and_; + + //ASR(1) two register immediate + if((inst & 0xF800) == 0x1000) return Op::asr1; + + //ASR(2) two register + if((inst & 0xFFC0) == 0x4100) return Op::asr2; + + //B(1) conditional branch + if((inst & 0xF000) == 0xD000) return Op::b1; + + //B(2) unconditional branch + if((inst & 0xF800) == 0xE000) return Op::b2; + + //BIC + if((inst & 0xFFC0) == 0x4380) return Op::bic; + + //BKPT + if((inst & 0xFF00) == 0xBE00) return Op::bkpt; + + //BL/BLX(1) + if((inst & 0xE000) == 0xE000) return Op::blx1; + + //BLX(2) + if((inst & 0xFF87) == 0x4780) return Op::blx2; + + //BX + if((inst & 0xFF87) == 0x4700) return Op::bx; + + //CMN + if((inst & 0xFFC0) == 0x42C0) return Op::cmn; + + //CMP(1) compare immediate + if((inst & 0xF800) == 0x2800) return Op::cmp1; + + //CMP(2) compare register + if((inst & 0xFFC0) == 0x4280) return Op::cmp2; + + //CMP(3) compare high register + if((inst & 0xFF00) == 0x4500) return Op::cmp3; + + //CPS + if((inst & 0xFFE8) == 0xB660) return Op::cps; + + //CPY copy high register + if((inst & 0xFFC0) == 0x4600) return Op::cpy; + + //EOR + if((inst & 0xFFC0) == 0x4040) return Op::eor; + + //LDMIA + if((inst & 0xF800) == 0xC800) return Op::ldmia; + + //LDR(1) two register immediate + if((inst & 0xF800) == 0x6800) return Op::ldr1; + + //LDR(2) three register + if((inst & 0xFE00) == 0x5800) return Op::ldr2; + + //LDR(3) + if((inst & 0xF800) == 0x4800) return Op::ldr3; + + //LDR(4) + if((inst & 0xF800) == 0x9800) return Op::ldr4; - } //LDR(4) - else if((inst & 0xF800) == 0x9800) - { - instr.op = Op::ldr4; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x07; - instr.rb <<= 2; - } //LDRB(1) - else if((inst & 0xF800) == 0x7800) - { - instr.op = Op::ldrb1; - instr.rd = (inst >> 0) & 0x07; - instr.rn = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - } + if((inst & 0xF800) == 0x7800) return Op::ldrb1; + //LDRB(2) - else if((inst & 0xFE00) == 0x5C00) - { - instr.op = Op::ldrb2; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x5C00) return Op::ldrb2; + //LDRH(1) - else if((inst & 0xF800) == 0x8800) - { - instr.op = Op::ldrh1; - instr.rd = (inst >> 0) & 0x07; - instr.rn = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - instr.rb <<= 1; - } + if((inst & 0xF800) == 0x8800) return Op::ldrh1; + //LDRH(2) - else if((inst & 0xFE00) == 0x5A00) - { - instr.op = Op::ldrh2; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x5A00) return Op::ldrh2; + //LDRSB - else if((inst & 0xFE00) == 0x5600) - { - instr.op = Op::ldrsb; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x5600) return Op::ldrsb; + //LDRSH - else if((inst & 0xFE00) == 0x5E00) - { - instr.op = Op::ldrsh; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x5E00) return Op::ldrsh; + //LSL(1) - else if((inst & 0xF800) == 0x0000) - { - instr.op = Op::lsl1; - instr.rd = (inst >> 0) & 0x07; - instr.rm = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - } + if((inst & 0xF800) == 0x0000) return Op::lsl1; + //LSL(2) two register - else if((inst & 0xFFC0) == 0x4080) - { - instr.op = Op::lsl2; - instr.rd = (inst >> 0) & 0x07; - instr.rs = (inst >> 3) & 0x07; - } + if((inst & 0xFFC0) == 0x4080) return Op::lsl2; + //LSR(1) two register immediate - else if((inst & 0xF800) == 0x0800) - { - instr.op = Op::lsr1; - instr.rd = (inst >> 0) & 0x07; - instr.rm = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - } + if((inst & 0xF800) == 0x0800) return Op::lsr1; + //LSR(2) two register - else if((inst & 0xFFC0) == 0x40C0) - { - instr.op = Op::lsr2; - instr.rd = (inst >> 0) & 0x07; - instr.rs = (inst >> 3) & 0x07; - } + if((inst & 0xFFC0) == 0x40C0) return Op::lsr2; + //MOV(1) immediate - else if((inst & 0xF800) == 0x2000) - { - instr.op = Op::mov1; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x07; - } + if((inst & 0xF800) == 0x2000) return Op::mov1; + //MOV(2) two low registers - else if((inst & 0xFFC0) == 0x1C00) - { - instr.op = Op::mov2; - instr.rd = (inst >> 0) & 7; - instr.rn = (inst >> 3) & 7; - } + if((inst & 0xFFC0) == 0x1C00) return Op::mov2; + //MOV(3) - else if((inst & 0xFF00) == 0x4600) - { - instr.op = Op::mov3; - instr.rd = (inst >> 0) & 0x7; - instr.rd |= (inst >> 4) & 0x8; - instr.rm = (inst >> 3) & 0xF; - } + if((inst & 0xFF00) == 0x4600) return Op::mov3; + //MUL - else if((inst & 0xFFC0) == 0x4340) - { - instr.op = Op::mul; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0x4340) return Op::mul; + //MVN - else if((inst & 0xFFC0) == 0x43C0) - { - instr.op = Op::mvn; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0x43C0) return Op::mvn; + //NEG - else if((inst & 0xFFC0) == 0x4240) - { - instr.op = Op::neg; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0x4240) return Op::neg; + //ORR - else if((inst & 0xFFC0) == 0x4300) - { - instr.op = Op::orr; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0x4300) return Op::orr; + //POP - else if((inst & 0xFE00) == 0xBC00) - { - instr.op = Op::pop; - } + if((inst & 0xFE00) == 0xBC00) return Op::pop; + //PUSH - else if((inst & 0xFE00) == 0xB400) - { - instr.op = Op::push; - } + if((inst & 0xFE00) == 0xB400) return Op::push; + //REV - else if((inst & 0xFFC0) == 0xBA00) - { - instr.op = Op::rev; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0xBA00) return Op::rev; + //REV16 - else if((inst & 0xFFC0) == 0xBA40) - { - instr.op = Op::rev16; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0xBA40) return Op::rev16; + //REVSH - else if((inst & 0xFFC0) == 0xBAC0) - { - instr.op = Op::revsh; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0xBAC0) return Op::revsh; + //ROR - else if((inst & 0xFFC0) == 0x41C0) - { - instr.op = Op::ror; - instr.rd = (inst >> 0) & 0x7; - instr.rs = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0x41C0) return Op::ror; + //SBC - else if((inst & 0xFFC0) == 0x4180) - { - instr.op = Op::sbc; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0x4180) return Op::sbc; + //SETEND - else if((inst & 0xFFF7) == 0xB650) - { - instr.op = Op::setend; - } + if((inst & 0xFFF7) == 0xB650) return Op::setend; + //STMIA - else if((inst & 0xF800) == 0xC000) - { - instr.op = Op::stmia; - instr.rn = (inst >> 8) & 0x7; - } + if((inst & 0xF800) == 0xC000) return Op::stmia; + //STR(1) - else if((inst & 0xF800) == 0x6000) - { - instr.op = Op::str1; - instr.rd = (inst >> 0) & 0x07; - instr.rn = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - instr.rb <<= 2; - } + if((inst & 0xF800) == 0x6000) return Op::str1; + //STR(2) - else if((inst & 0xFE00) == 0x5000) - { - instr.op = Op::str2; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x5000) return Op::str2; + //STR(3) - else if((inst & 0xF800) == 0x9000) - { - instr.op = Op::str3; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x07; - instr.rb <<= 2; - } + if((inst & 0xF800) == 0x9000) return Op::str3; + //STRB(1) - else if((inst & 0xF800) == 0x7000) - { - instr.op = Op::strb1; - instr.rd = (inst >> 0) & 0x07; - instr.rn = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - } + if((inst & 0xF800) == 0x7000) return Op::strb1; + //STRB(2) - else if((inst & 0xFE00) == 0x5400) - { - instr.op = Op::strb2; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x5400) return Op::strb2; + //STRH(1) - else if((inst & 0xF800) == 0x8000) - { - instr.op = Op::strh1; - instr.rd = (inst >> 0) & 0x07; - instr.rn = (inst >> 3) & 0x07; - instr.rb = (inst >> 6) & 0x1F; - instr.rb <<= 1; - } + if((inst & 0xF800) == 0x8000) return Op::strh1; + //STRH(2) - else if((inst & 0xFE00) == 0x5200) - { - instr.op = Op::strh2; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x5200) return Op::strh2; + //SUB(1) - else if((inst & 0xFE00) == 0x1E00) - { - instr.op = Op::sub1; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rb = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x1E00) return Op::sub1; + //SUB(2) - else if((inst & 0xF800) == 0x3800) - { - instr.op = Op::sub2; - instr.rb = (inst >> 0) & 0xFF; - instr.rd = (inst >> 8) & 0x07; - } + if((inst & 0xF800) == 0x3800) return Op::sub2; + //SUB(3) - else if((inst & 0xFE00) == 0x1A00) - { - instr.op = Op::sub3; - instr.rd = (inst >> 0) & 0x7; - instr.rn = (inst >> 3) & 0x7; - instr.rm = (inst >> 6) & 0x7; - } + if((inst & 0xFE00) == 0x1A00) return Op::sub3; + //SUB(4) - else if((inst & 0xFF80) == 0xB080) - { - instr.op = Op::sub4; - instr.rb = inst & 0x7F; - instr.rb <<= 2; - } + if((inst & 0xFF80) == 0xB080) return Op::sub4; + //SWI - else if((inst & 0xFF00) == 0xDF00) - { - instr.op = Op::swi; - instr.rb = inst & 0xFF; - } + if((inst & 0xFF00) == 0xDF00) return Op::swi; + //SXTB - else if((inst & 0xFFC0) == 0xB240) - { - instr.op = Op::sxtb; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0xB240) return Op::sxtb; + //SXTH - else if((inst & 0xFFC0) == 0xB200) - { - instr.op = Op::sxth; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0xB200) return Op::sxth; + //TST - else if((inst & 0xFFC0) == 0x4200) - { - instr.op = Op::tst; - instr.rn = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0x4200) return Op::tst; + //UXTB - else if((inst & 0xFFC0) == 0xB2C0) - { - instr.op = Op::uxtb; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } + if((inst & 0xFFC0) == 0xB2C0) return Op::uxtb; + //UXTH - else if((inst & 0xFFC0) == 0xB280) - { - instr.op = Op::uxth; - instr.rd = (inst >> 0) & 0x7; - instr.rm = (inst >> 3) & 0x7; - } - else - instr.op = Op::invalid; + if((inst & 0xFFC0) == 0xB280) return Op::uxth; + + return Op::invalid; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1119,19 +773,15 @@ int Thumbulator::execute() ++instructions; - Instruction decodedInstr; - if ((instructionPtr & 0xF0000000) == 0 && instructionPtr < romSize) - decodedInstr = decodedInstruction[instructionPtr / 2]; - else - decodeInstructionWord(inst, decodedInstr); + Op decodedOp; + if ((instructionPtr & 0xF0000000) == 0 && instructionPtr < romSize) decodedOp = decodedRom[instructionPtr / 2]; + else decodedOp = decodeInstructionWord(inst); - switch (decodedInstr.op) { + switch (decodedOp) { //ADC case Op::adc: { - //rd = (inst >> 0) & 0x07; - //rm = (inst >> 3) & 0x07; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x07; + rm = (inst >> 3) & 0x07; DO_DISS(statusMsg << "adc r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); @@ -1148,12 +798,9 @@ int Thumbulator::execute() //ADD(1) small immediate two registers case Op::add1: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rb = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rb = (inst >> 6) & 0x7; if(rb) { DO_DISS(statusMsg << "adds r" << dec << rd << ",r" << dec << rn << "," @@ -1178,10 +825,8 @@ int Thumbulator::execute() //ADD(2) big immediate one register case Op::add2: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x7; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x7; DO_DISS(statusMsg << "adds r" << dec << rd << ",#0x" << Base::HEX2 << rb << endl); ra = read_register(rd); rc = ra + rb; @@ -1195,12 +840,9 @@ int Thumbulator::execute() //ADD(3) three registers case Op::add3: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "adds r" << dec << rd << ",r" << dec << rn << ",r" << rm << endl); ra = read_register(rn); rb = read_register(rm); @@ -1215,15 +857,14 @@ int Thumbulator::execute() //ADD(4) two registers one or both high no flags case Op::add4: { - //if((inst >> 6) & 3) - //{ - // //UNPREDICTABLE - //} - //rd = (inst >> 0) & 0x7; - //rd |= (inst >> 4) & 0x8; - //rm = (inst >> 3) & 0xF; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + if((inst >> 6) & 3) + { + //UNPREDICTABLE + } + rd = (inst >> 0) & 0x7; + rd |= (inst >> 4) & 0x8; + rm = (inst >> 3) & 0xF; + DO_DISS(statusMsg << "add r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); rc = ra + rb; @@ -1242,11 +883,9 @@ int Thumbulator::execute() //ADD(5) rd = pc plus immediate case Op::add5: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x7; - //rb <<= 2; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x7; + rb <<= 2; DO_DISS(statusMsg << "add r" << dec << rd << ",PC,#0x" << Base::HEX2 << rb << endl); ra = read_register(15); rc = (ra & (~3u)) + rb; @@ -1256,11 +895,9 @@ int Thumbulator::execute() //ADD(6) rd = sp plus immediate case Op::add6: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x7; - //rb <<= 2; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x7; + rb <<= 2; DO_DISS(statusMsg << "add r" << dec << rd << ",SP,#0x" << Base::HEX2 << rb << endl); ra = read_register(13); rc = ra + rb; @@ -1270,9 +907,8 @@ int Thumbulator::execute() //ADD(7) sp plus immediate case Op::add7: { - //rb = (inst >> 0) & 0x7F; - //rb <<= 2; - rb = decodedInstr.rb; + rb = (inst >> 0) & 0x7F; + rb <<= 2; DO_DISS(statusMsg << "add SP,#0x" << Base::HEX2 << rb << endl); ra = read_register(13); rc = ra + rb; @@ -1282,10 +918,8 @@ int Thumbulator::execute() //AND case Op::and_: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "ands r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); @@ -1298,12 +932,9 @@ int Thumbulator::execute() //ASR(1) two register immediate case Op::asr1: { - //rd = (inst >> 0) & 0x07; - //rm = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - rd = decodedInstr.rd; - rm = decodedInstr.rm; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rm = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; DO_DISS(statusMsg << "asrs r" << dec << rd << ",r" << dec << rm << ",#0x" << Base::HEX2 << rb << endl); rc = read_register(rm); if(rb == 0) @@ -1335,10 +966,8 @@ int Thumbulator::execute() //ASR(2) two register case Op::asr2: { - //rd = (inst >> 0) & 0x07; - //rs = (inst >> 3) & 0x07; - rd = decodedInstr.rd; - rs = decodedInstr.rs; + rd = (inst >> 0) & 0x07; + rs = (inst >> 3) & 0x07; DO_DISS(statusMsg << "asrs r" << dec << rd << ",r" << dec << rs << endl); rc = read_register(rd); rb = read_register(rs); @@ -1377,14 +1006,13 @@ int Thumbulator::execute() //B(1) conditional branch case Op::b1: { - //rb = (inst >> 0) & 0xFF; - //if(rb & 0x80) - // rb |= (~0u) << 8; - op = (inst >> 8) & 0xF; - //rb <<= 1; - rb = decodedInstr.rb; + rb = (inst >> 0) & 0xFF; + if(rb & 0x80) + rb |= (~0u) << 8; + op=(inst >> 8) & 0xF; + rb <<= 1; rb += pc; - //rb += 2; + rb += 2; switch(op) { case 0x0: //b eq z set @@ -1515,13 +1143,12 @@ int Thumbulator::execute() //B(2) unconditional branch case Op::b2: { - //rb = (inst >> 0) & 0x7FF; - //if(rb & (1 << 10)) - // rb |= (~0u) << 11; - //rb <<= 1; - rb = decodedInstr.rb; + rb = (inst >> 0) & 0x7FF; + if(rb & (1 << 10)) + rb |= (~0u) << 11; + rb <<= 1; rb += pc; - //rb += 2; + rb += 2; DO_DISS(statusMsg << "B 0x" << Base::HEX8 << (rb-3) << endl); write_register(15, rb); return 0; @@ -1529,10 +1156,8 @@ int Thumbulator::execute() //BIC case Op::bic: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "bics r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); @@ -1545,8 +1170,7 @@ int Thumbulator::execute() //BKPT case Op::bkpt: { - //rb = (inst >> 0) & 0xFF; - rb = decodedInstr.rb; + rb = (inst >> 0) & 0xFF; statusMsg << "bkpt 0x" << Base::HEX2 << rb << endl; return 1; } @@ -1556,10 +1180,9 @@ int Thumbulator::execute() if((inst & 0x1800) == 0x1000) //H=b10 { DO_DISS(statusMsg << endl); - //rb = inst & ((1 << 11) - 1); - //if(rb & 1<<10) rb |= (~((1 << 11) - 1)); //sign extend - //rb <<= 12; - rb = decodedInstr.rb; + rb = inst & ((1 << 11) - 1); + if(rb & 1<<10) rb |= (~((1 << 11) - 1)); //sign extend + rb <<= 12; rb += pc; write_register(14, rb); return 0; @@ -1567,10 +1190,9 @@ int Thumbulator::execute() else if((inst & 0x1800) == 0x1800) //H=b11 { //branch to thumb - //rb = (inst & ((1 << 11) - 1)) << 1;; - rb = decodedInstr.rb; - rb += read_register(14); - //rb += 2; + rb = read_register(14); + rb += (inst & ((1 << 11) - 1)) << 1;; + rb += 2; DO_DISS(statusMsg << "bl 0x" << Base::HEX8 << (rb-3) << endl); write_register(14, (pc-2) | 1); write_register(15, rb); @@ -1580,9 +1202,8 @@ int Thumbulator::execute() { //fprintf(stderr,"cannot branch to arm 0x%08X 0x%04X\n",pc,inst); // fxq: this should exit the code without having to detect it - //rb = (inst & ((1 << 11) - 1)) << 1; - rb = decodedInstr.rb; - rb += read_register(14); + rb = read_register(14); + rb += (inst & ((1 << 11) - 1)) << 1;; rb &= 0xFFFFFFFC; rb += 2; DO_DISS(statusMsg << "bl 0x" << Base::HEX8 << (rb-3) << endl); @@ -1596,8 +1217,7 @@ int Thumbulator::execute() //BLX(2) case Op::blx2: { - //rm = (inst >> 3) & 0xF; - rm = decodedInstr.rm; + rm = (inst >> 3) & 0xF; DO_DISS(statusMsg << "blx r" << dec << rm << endl); rc = read_register(rm); //fprintf(stderr,"blx r%u 0x%X 0x%X\n",rm,rc,pc); @@ -1619,8 +1239,7 @@ int Thumbulator::execute() //BX case Op::bx: { - //rm = (inst >> 3) & 0xF; - rm = decodedInstr.rm; + rm = (inst >> 3) & 0xF; DO_DISS(statusMsg << "bx r" << dec << rm << endl); rc = read_register(rm); rc += 2; @@ -1847,10 +1466,8 @@ int Thumbulator::execute() //CMN case Op::cmn: { - //rn = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rn = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "cmns r" << dec << rn << ",r" << dec << rm << endl); ra = read_register(rn); rb = read_register(rm); @@ -1864,10 +1481,8 @@ int Thumbulator::execute() //CMP(1) compare immediate case Op::cmp1: { - //rb = (inst >> 0) & 0xFF; - //rn = (inst >> 8) & 0x07; - rb = decodedInstr.rb; - rn = decodedInstr.rn; + rb = (inst >> 0) & 0xFF; + rn = (inst >> 8) & 0x07; DO_DISS(statusMsg << "cmp r" << dec << rn << ",#0x" << Base::HEX2 << rb << endl); ra = read_register(rn); rc = ra - rb; @@ -1881,10 +1496,8 @@ int Thumbulator::execute() //CMP(2) compare register case Op::cmp2: { - //rn = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rn = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "cmps r" << dec << rn << ",r" << dec << rm << endl); ra = read_register(rn); rb = read_register(rm); @@ -1899,19 +1512,17 @@ int Thumbulator::execute() //CMP(3) compare high register case Op::cmp3: { - //if(((inst >> 6) & 3) == 0x0) - //{ - // //UNPREDICTABLE - //} - //rn = (inst >> 0) & 0x7; - //rn |= (inst >> 4) & 0x8; - //if(rn == 0xF) - //{ - // //UNPREDICTABLE - //} - //rm = (inst >> 3) & 0xF; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + if(((inst >> 6) & 3) == 0x0) + { + //UNPREDICTABLE + } + rn = (inst >> 0) & 0x7; + rn |= (inst >> 4) & 0x8; + if(rn == 0xF) + { + //UNPREDICTABLE + } + rm = (inst >> 3) & 0xF; DO_DISS(statusMsg << "cmps r" << dec << rn << ",r" << dec << rm << endl); ra = read_register(rn); rb = read_register(rm); @@ -1933,10 +1544,8 @@ int Thumbulator::execute() case Op::cpy: { //same as mov except you can use both low registers //going to let mov handle high registers - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "cpy r" << dec << rd << ",r" << dec << rm << endl); rc = read_register(rm); write_register(rd, rc); @@ -1945,10 +1554,8 @@ int Thumbulator::execute() //EOR case Op::eor: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "eors r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); @@ -1961,8 +1568,7 @@ int Thumbulator::execute() //LDMIA case Op::ldmia: { - //rn = (inst >> 8) & 0x7; - rn = decodedInstr.rn; + rn = (inst >> 8) & 0x7; #if defined(THUMB_DISS) statusMsg << "ldmia r" << dec << rn << "!,{"; for(ra=0,rb=0x01,rc=0;rb;rb=(rb<<1)&0xFF,++ra) @@ -1994,13 +1600,10 @@ int Thumbulator::execute() //LDR(1) two register immediate case Op::ldr1: { - //rd = (inst >> 0) & 0x07; - //rn = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - //rb <<= 2; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rn = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; + rb <<= 2; DO_DISS(statusMsg << "ldr r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl); rb = read_register(rn) + rb; rc = read32(rb); @@ -2010,12 +1613,9 @@ int Thumbulator::execute() //LDR(2) three register case Op::ldr2: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "ldr r" << dec << rd << ",[r" << dec << rn << ",r" << dec << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read32(rb); @@ -2025,11 +1625,9 @@ int Thumbulator::execute() //LDR(3) case Op::ldr3: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x07; - //rb <<= 2; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x07; + rb <<= 2; DO_DISS(statusMsg << "ldr r" << dec << rd << ",[PC+#0x" << Base::HEX2 << rb << "] "); ra = read_register(15); ra &= ~3; @@ -2042,11 +1640,9 @@ int Thumbulator::execute() //LDR(4) case Op::ldr4: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x07; - //rb <<= 2; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x07; + rb <<= 2; DO_DISS(statusMsg << "ldr r" << dec << rd << ",[SP+#0x" << Base::HEX2 << rb << "]" << endl); ra = read_register(13); //ra&=~3; @@ -2058,12 +1654,9 @@ int Thumbulator::execute() //LDRB(1) case Op::ldrb1: { - //rd = (inst >> 0) & 0x07; - //rn = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rn = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl); rb = read_register(rn) + rb; rc = read16(rb & (~1u)); @@ -2080,12 +1673,9 @@ int Thumbulator::execute() //LDRB(2) case Op::ldrb2: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read16(rb & (~1u)); @@ -2102,13 +1692,10 @@ int Thumbulator::execute() //LDRH(1) case Op::ldrh1: { - //rd = (inst >> 0) & 0x07; - //rn = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - //rb <<= 1; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rn = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; + rb <<= 1; DO_DISS(statusMsg << "ldrh r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl); rb=read_register(rn) + rb; rc = read16(rb); @@ -2118,12 +1705,9 @@ int Thumbulator::execute() //LDRH(2) case Op::ldrh2: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "ldrh r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read16(rb); @@ -2133,12 +1717,9 @@ int Thumbulator::execute() //LDRSB case Op::ldrsb: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "ldrsb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read16(rb & (~1u)); @@ -2158,12 +1739,9 @@ int Thumbulator::execute() //LDRSH case Op::ldrsh: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "ldrsh r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read16(rb); @@ -2176,12 +1754,9 @@ int Thumbulator::execute() //LSL(1) case Op::lsl1: { - //rd = (inst >> 0) & 0x07; - //rm = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - rd = decodedInstr.rd; - rm = decodedInstr.rm; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rm = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; DO_DISS(statusMsg << "lsls r" << dec << rd << ",r" << dec << rm << ",#0x" << Base::HEX2 << rb << endl); rc = read_register(rm); if(rb == 0) @@ -2204,10 +1779,8 @@ int Thumbulator::execute() //LSL(2) two register case Op::lsl2: { - //rd = (inst >> 0) & 0x07; - //rs = (inst >> 3) & 0x07; - rd = decodedInstr.rd; - rs = decodedInstr.rs; + rd = (inst >> 0) & 0x07; + rs = (inst >> 3) & 0x07; DO_DISS(statusMsg << "lsls r" << dec << rd << ",r" << dec << rs << endl); rc = read_register(rd); rb = read_register(rs); @@ -2238,12 +1811,9 @@ int Thumbulator::execute() //LSR(1) two register immediate case Op::lsr1: { - //rd = (inst >> 0) & 0x07; - //rm = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - rd = decodedInstr.rd; - rm = decodedInstr.rm; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rm = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; DO_DISS(statusMsg << "lsrs r" << dec << rd << ",r" << dec << rm << ",#0x" << Base::HEX2 << rb << endl); rc = read_register(rm); if(rb == 0) @@ -2264,10 +1834,8 @@ int Thumbulator::execute() //LSR(2) two register case Op::lsr2: { - //rd = (inst >> 0) & 0x07; - //rs = (inst >> 3) & 0x07; - rd = decodedInstr.rd; - rs = decodedInstr.rs; + rd = (inst >> 0) & 0x07; + rs = (inst >> 3) & 0x07; DO_DISS(statusMsg << "lsrs r" << dec << rd << ",r" << dec << rs << endl); rc = read_register(rd); rb = read_register(rs); @@ -2298,10 +1866,8 @@ int Thumbulator::execute() //MOV(1) immediate case Op::mov1: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x07; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x07; DO_DISS(statusMsg << "movs r" << dec << rd << ",#0x" << Base::HEX2 << rb << endl); write_register(rd, rb); do_nflag(rb); @@ -2311,10 +1877,8 @@ int Thumbulator::execute() //MOV(2) two low registers case Op::mov2: { - //rd = (inst >> 0) & 7; - //rn = (inst >> 3) & 7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; + rd = (inst >> 0) & 7; + rn = (inst >> 3) & 7; DO_DISS(statusMsg << "movs r" << dec << rd << ",r" << dec << rn << endl); rc = read_register(rn); //fprintf(stderr,"0x%08X\n",rc); @@ -2328,11 +1892,9 @@ int Thumbulator::execute() //MOV(3) case Op::mov3: { - //rd = (inst >> 0) & 0x7; - //rd |= (inst >> 4) & 0x8; - //rm = (inst >> 3) & 0xF; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rd |= (inst >> 4) & 0x8; + rm = (inst >> 3) & 0xF; DO_DISS(statusMsg << "mov r" << dec << rd << ",r" << dec << rm << endl); rc = read_register(rm); if((rd == 14) && (rm == 15)) @@ -2351,10 +1913,8 @@ int Thumbulator::execute() //MUL case Op::mul: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "muls r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); @@ -2367,10 +1927,8 @@ int Thumbulator::execute() //MVN case Op::mvn: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "mvns r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rm); rc = (~ra); @@ -2382,10 +1940,8 @@ int Thumbulator::execute() //NEG case Op::neg: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "negs r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rm); rc = 0 - ra; @@ -2399,10 +1955,8 @@ int Thumbulator::execute() //ORR case Op::orr: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "orrs r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); @@ -2511,10 +2065,8 @@ int Thumbulator::execute() //REV case Op::rev: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; DO_DISS(statusMsg << "rev r" << dec << rd << ",r" << dec << rn << endl); ra = read_register(rn); rc = ((ra >> 0) & 0xFF) << 24; @@ -2527,10 +2079,8 @@ int Thumbulator::execute() //REV16 case Op::rev16: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; DO_DISS(statusMsg << "rev16 r" << dec << rd << ",r" << dec << rn << endl); ra = read_register(rn); rc = ((ra >> 0) & 0xFF) << 8; @@ -2543,10 +2093,8 @@ int Thumbulator::execute() //REVSH case Op::revsh: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; DO_DISS(statusMsg << "revsh r" << dec << rd << ",r" << dec << rn << endl); ra = read_register(rn); rc = ((ra >> 0) & 0xFF) << 8; @@ -2559,10 +2107,8 @@ int Thumbulator::execute() //ROR case Op::ror: { - //rd = (inst >> 0) & 0x7; - //rs = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rs = decodedInstr.rs; + rd = (inst >> 0) & 0x7; + rs = (inst >> 3) & 0x7; DO_DISS(statusMsg << "rors r" << dec << rd << ",r" << dec << rs << endl); rc = read_register(rd); ra = read_register(rs); @@ -2593,10 +2139,8 @@ int Thumbulator::execute() //SBC case Op::sbc: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "sbc r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rd); rb = read_register(rm); @@ -2626,8 +2170,7 @@ int Thumbulator::execute() //STMIA case Op::stmia: { - /*rn = (inst >> 8) & 0x7;*/ - rn = decodedInstr.rn; + rn = (inst >> 8) & 0x7; #if defined(THUMB_DISS) statusMsg << "stmia r" << dec << rn << "!,{"; for(ra=0,rb=0x01,rc=0;rb;rb=(rb<<1)&0xFF,++ra) @@ -2657,13 +2200,10 @@ int Thumbulator::execute() //STR(1) case Op::str1: { - //rd = (inst >> 0) & 0x07; - //rn = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - //rb <<= 2; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rn = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; + rb <<= 2; DO_DISS(statusMsg << "str r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl); rb = read_register(rn) + rb; rc = read_register(rd); @@ -2673,12 +2213,9 @@ int Thumbulator::execute() //STR(2) case Op::str2: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "str r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read_register(rd); @@ -2688,11 +2225,9 @@ int Thumbulator::execute() //STR(3) case Op::str3: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x07; - //rb <<= 2; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x07; + rb <<= 2; DO_DISS(statusMsg << "str r" << dec << rd << ",[SP,#0x" << Base::HEX2 << rb << "]" << endl); rb = read_register(13) + rb; //fprintf(stderr,"0x%08X\n",rb); @@ -2703,12 +2238,9 @@ int Thumbulator::execute() //STRB(1) case Op::strb1: { - //rd = (inst >> 0) & 0x07; - //rn = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rn = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX8 << rb << "]" << endl); rb = read_register(rn) + rb; rc = read_register(rd); @@ -2729,12 +2261,9 @@ int Thumbulator::execute() //STRB(2) case Op::strb2: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",r" << rm << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read_register(rd); @@ -2755,13 +2284,10 @@ int Thumbulator::execute() //STRH(1) case Op::strh1: { - //rd = (inst >> 0) & 0x07; - //rn = (inst >> 3) & 0x07; - //rb = (inst >> 6) & 0x1F; - //rb <<= 1; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x07; + rn = (inst >> 3) & 0x07; + rb = (inst >> 6) & 0x1F; + rb <<= 1; DO_DISS(statusMsg << "strh r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]" << endl); rb = read_register(rn) + rb; rc= read_register(rd); @@ -2771,12 +2297,9 @@ int Thumbulator::execute() //STRH(2) case Op::strh2: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "strh r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]" << endl); rb = read_register(rn) + read_register(rm); rc = read_register(rd); @@ -2786,12 +2309,9 @@ int Thumbulator::execute() //SUB(1) case Op::sub1: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rb = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rb = decodedInstr.rb; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rb = (inst >> 6) & 0x7; DO_DISS(statusMsg << "subs r" << dec << rd << ",r" << dec << rn << ",#0x" << Base::HEX2 << rb << endl); ra = read_register(rn); rc = ra - rb; @@ -2805,10 +2325,8 @@ int Thumbulator::execute() //SUB(2) case Op::sub2: { - //rb = (inst >> 0) & 0xFF; - //rd = (inst >> 8) & 0x07; - rb = decodedInstr.rb; - rd = decodedInstr.rd; + rb = (inst >> 0) & 0xFF; + rd = (inst >> 8) & 0x07; DO_DISS(statusMsg << "subs r" << dec << rd << ",#0x" << Base::HEX2 << rb << endl); ra = read_register(rd); rc = ra - rb; @@ -2822,12 +2340,9 @@ int Thumbulator::execute() //SUB(3) case Op::sub3: { - //rd = (inst >> 0) & 0x7; - //rn = (inst >> 3) & 0x7; - //rm = (inst >> 6) & 0x7; - rd = decodedInstr.rd; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rn = (inst >> 3) & 0x7; + rm = (inst >> 6) & 0x7; DO_DISS(statusMsg << "subs r" << dec << rd << ",r" << dec << rn << ",r" << dec << rm << endl); ra = read_register(rn); rb = read_register(rm); @@ -2842,9 +2357,8 @@ int Thumbulator::execute() //SUB(4) case Op::sub4: { - //rb = inst & 0x7F; - //rb <<= 2; - rb = decodedInstr.rb; + rb = inst & 0x7F; + rb <<= 2; DO_DISS(statusMsg << "sub SP,#0x" << Base::HEX2 << rb << endl); ra = read_register(13); ra -= rb; @@ -2854,8 +2368,7 @@ int Thumbulator::execute() //SWI case Op::swi: { - //rb = inst & 0xFF; - rb = decodedInstr.rb; + rb = inst & 0xFF; DO_DISS(statusMsg << "swi 0x" << Base::HEX2 << rb << endl); if((inst & 0xFF) == 0xCC) @@ -2872,10 +2385,8 @@ int Thumbulator::execute() //SXTB case Op::sxtb: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "sxtb r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rm); rc = ra & 0xFF; @@ -2887,10 +2398,8 @@ int Thumbulator::execute() //SXTH case Op::sxth: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "sxth r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rm); rc = ra & 0xFFFF; @@ -2902,10 +2411,8 @@ int Thumbulator::execute() //TST case Op::tst: { - //rn = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rn = decodedInstr.rn; - rm = decodedInstr.rm; + rn = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "tst r" << dec << rn << ",r" << dec << rm << endl); ra = read_register(rn); rb = read_register(rm); @@ -2917,10 +2424,8 @@ int Thumbulator::execute() //UXTB case Op::uxtb: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "uxtb r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rm); rc = ra & 0xFF; @@ -2930,10 +2435,8 @@ int Thumbulator::execute() //UXTH case Op::uxth: { - //rd = (inst >> 0) & 0x7; - //rm = (inst >> 3) & 0x7; - rd = decodedInstr.rd; - rm = decodedInstr.rm; + rd = (inst >> 0) & 0x7; + rm = (inst >> 3) & 0x7; DO_DISS(statusMsg << "uxth r" << dec << rd << ",r" << dec << rm << endl); ra = read_register(rm); rc = ra & 0xFFFF; diff --git a/src/emucore/Thumbulator.hxx b/src/emucore/Thumbulator.hxx index bb9d50dd7..a4562d8ff 100644 --- a/src/emucore/Thumbulator.hxx +++ b/src/emucore/Thumbulator.hxx @@ -19,7 +19,6 @@ // This class provides Thumb emulation code ("Thumbulator") // by David Welch (dwelch@dwelch.com) // Modified by Fred Quimby -// Optimized by Christina Speckner and Thomas Jentzsch // Code is public domain and used with the author's consent //============================================================================ @@ -141,12 +140,6 @@ class Thumbulator uxth }; - struct Instruction - { - Op op; - uInt32 rb, rd, rm, rn, rs; - }; - private: uInt32 read_register(uInt32 reg); void write_register(uInt32 reg, uInt32 data); @@ -159,7 +152,7 @@ class Thumbulator void write32(uInt32 addr, uInt32 data); void updateTimer(uInt32 cycles); - void decodeInstructionWord(uint16_t inst, Instruction& instr); + static Op decodeInstructionWord(uint16_t inst); void do_zflag(uInt32 x); void do_nflag(uInt32 x); @@ -182,7 +175,7 @@ class Thumbulator private: const uInt16* rom; uInt16 romSize; - const unique_ptr decodedInstruction; + const unique_ptr decodedRom; uInt16* ram; uInt32 reg_norm[16]; // normal execution mode, do not have a thread mode