using System; using System.Diagnostics; namespace BizHawk.Emulation.CPUs.ARM { partial class ARM { uint ExecuteThumb() { uint opcode = instruction >> 10; _currentCondVal = 14; //TODO - this one could really be turned into a table switch (opcode) { case _.b000000: case _.b000001: case _.b000010: case _.b000011: case _.b000100: case _.b000101: case _.b000110: case _.b000111: case _.b001000: case _.b001001: case _.b001010: case _.b001011: case _.b001100: case _.b001101: case _.b001110: case _.b001111: return ExecuteThumb_AluMisc(); case _.b010000: return ExecuteThumb_DataProcessing(); case _.b010001: return ExecuteThumb_SpecialBX(); case _.b010010: case _.b010011: return Execute_LDR_literal_T1(); case _.b010100: case _.b010101: case _.b010110: case _.b010111: case _.b011000: case _.b011001: case _.b011010: case _.b011011: case _.b011100: case _.b011101: case _.b011110: case _.b011111: case _.b100000: case _.b100001: case _.b100010: case _.b100011: case _.b100100: case _.b100101: case _.b100110: case _.b100111: return ExecuteThumb_LoadStore(); case _.b101000: case _.b101001: return Execute_ADR_T1(); case _.b101010: case _.b101011: return Execute_ADD_SP_plus_immediate_T1(); case _.b101100: case _.b101101: case _.b101110: case _.b101111: return ExecuteThumb_Misc16(); case _.b110000: case _.b110001: return Execute_STM_STMIA_STMEA_T1(); case _.b110010: case _.b110011: return Execute_LDM_LDMIA_LDMFD_T1(); case _.b110100: case _.b110101: case _.b110110: case _.b110111: return ExecuteThumb_CondBr_And_SVC(); case _.b111000: case _.b111001: return Execute_B_T2(); case _.b111010: case _.b111011: case _.b111100: case _.b111101: case _.b111110: case _.b111111: return ExecuteThumb_32(); default: throw new InvalidOperationException("unhandled case in ExecuteThumb"); } } uint Execute_LDR_literal_T1() { //A8.6.59 uint t = Reg8(8); uint imm8 = instruction & 0xFF; uint imm32 = imm8 << 2; const bool add = true; return ExecuteCore_LDR_literal(Encoding.T1, t, imm32, add); } uint ExecuteThumb_LoadStore() { //A6.2.4 uint opA = (instruction >> 12) & 0xF; uint opB = (instruction >> 9) & 0x7; switch (opA) { case _.b0101: switch (opB) { case _.b000: return Execute_Unhandled("STR (register) on page A8-386"); case _.b001: return Execute_Unhandled("STRH (register) on page A8-412"); case _.b010: return Execute_STRB_register_T1(); case _.b011: return Execute_Unhandled("LDRSB (register) on page A8-164"); case _.b100: return Execute_LDR_register_T1(); case _.b101: return Execute_Unhandled("LDRH (register)"); case _.b110: return Execute_LDRB_register_T1(); case _.b111: return Execute_Unhandled("LDRSH (register) on page A8-172"); default: throw new InvalidOperationException("decoder fail"); } case _.b0110: switch (opB) { case _.b000: case _.b001: case _.b010: case _.b011: return Execute_STR_immediate_thumb_T1(); case _.b100: case _.b101: case _.b110: case _.b111: return Execute_LDR_immediate_thumb_T1(); default: throw new InvalidOperationException("decoder fail"); } case _.b0111: switch (opB) { case _.b000: case _.b001: case _.b010: case _.b011: return Execute_STRB_immediate_thumb_T1(); case _.b100: case _.b101: case _.b110: case _.b111: return Execute_LDRB_immediate_thumb_T1(); default: throw new InvalidOperationException("decoder fail"); } case _.b1000: switch (opB) { case _.b000: case _.b001: case _.b010: case _.b011: return Execute_STRH_immediate_thumb_T1(); case _.b100: case _.b101: case _.b110: case _.b111: return Execute_LDRH_immediate_thumb_T1(); default: throw new InvalidOperationException("decoder fail"); } case _.b1001: switch (opB) { case _.b000: case _.b001: case _.b010: case _.b011: return Execute_STR_immediate_thumb_T2(); case _.b100: case _.b101: case _.b110: case _.b111: return Execute_LDR_immediate_thumb_T2(); default: throw new InvalidOperationException("decoder fail"); } default: throw new InvalidOperationException("decoder fail"); } //switch(opA) } uint Execute_STRB_register_T1() { //A8.6.198 uint t = Reg8(0); uint n = Reg8(3); uint m = Reg8(6); const bool index = true; const bool add = true; const bool wback = false; const SRType shift_t = SRType.LSL; const int shift_n = 0; return ExecuteCore_STRB_register(Encoding.T1, t, n, m, shift_t, shift_n, index, add, wback); } uint Execute_LDR_register_T1() { //A8.6.60 if (_CurrentInstrSet() == EInstrSet.THUMBEE) throw new NotSupportedException("Modified operatoin in ThumbEE"); uint t = Reg8(0); uint n = Reg8(3); uint m = Reg8(6); const bool index = true; const bool add = true; const bool wback = false; const SRType shift_t = SRType.LSL; const int shift_n = 0; return ExecuteCore_LDR_register(Encoding.T1, t, n, m, shift_t, shift_n, index, add, wback); } uint Execute_LDRB_register_T1() { //A8.6.64 uint t = Reg8(0); uint n = Reg8(3); uint m = Reg8(6); const bool index = true; const bool add = true; const bool wback = false; const SRType shift_t = SRType.LSL; const int shift_n = 0; return ExecuteCore_LDRB_register(Encoding.T1, t, n, m, shift_t, shift_n, index, add, wback); } uint Execute_LDRB_immediate_thumb_T1() { //A8.6.61 uint t = Reg8(0); uint n = Reg8(3); uint imm5 = (instruction >> 6) & 0x1F; uint imm32 = _ZeroExtend_32(imm5); const bool index = true; const bool add = true; const bool wback = false; return ExecuteCore_LDRB_immediate_thumb(Encoding.T1, t, n, imm32, index, add, wback); } uint Execute_STRB_immediate_thumb_T1() { //A8.6.196 uint t = Reg8(0); uint n = Reg8(3); uint imm5 = (instruction >> 6) & 0x1F; uint imm32 = _ZeroExtend_32(imm5); const bool index = true; const bool add = true; const bool wback = false; return ExecuteCore_STRB_immediate_thumb(Encoding.T1, t, n, imm32, index, add, wback); } uint Execute_LDRH_immediate_thumb_T1() { //A8.6.73 uint t = Reg8(0); uint n = Reg8(3); uint imm5 = (instruction >> 6) & 0x1F; uint imm32 = _ZeroExtend_32(imm5 << 1); const bool index = true; const bool add = true; const bool wback = false; return ExecuteCore_LDRH_immediate_thumb(Encoding.T1, t, n, imm32, index, add, wback); } uint Execute_STRH_immediate_thumb_T1() { //A8.6.206 STRH uint t = Reg8(0); uint n = Reg8(3); uint imm5 = (instruction >> 6) & 0x1F; uint imm32 = _ZeroExtend_32(imm5 << 1); const bool index = true; const bool add = true; const bool wback = false; return ExecuteCore_STRH_immediate_thumb(Encoding.T1, t, n, imm32, index, add, wback); } uint Execute_LDR_immediate_thumb_T1() { //A8.6.57 LDR (immediate,thumb) uint t = Reg8(0); uint n = Reg8(3); uint imm5 = (instruction >> 6) & 0x1F; uint imm32 = _ZeroExtend_32(imm5 << 2); bool index = true; bool add = true; bool wback = false; return ExecuteCore_LDR_immediate_thumb(Encoding.T1, t, imm32, n, index, add, wback); } uint Execute_STR_immediate_thumb_T1() { //A8.6.193 STR (immediate,thumb) uint t = Reg8(0); uint n = Reg8(3); uint imm5 = (instruction >> 6) & 0x1F; uint imm32 = _ZeroExtend_32(imm5 << 2); bool index = true; bool add = true; bool wback = false; return ExecuteCore_STR_immediate_thumb(Encoding.T1, t, imm32, n, index, add, wback); } uint Execute_LDR_immediate_thumb_T2() { //A8.6.57 LDR (immediate, thumb) uint t = Reg8(8); uint imm8 = instruction & 0xFF; const uint n = 13; uint imm32 = _ZeroExtend_32(imm8 << 2); const bool index = true; const bool add = true; const bool wback = false; return ExecuteCore_LDR_immediate_thumb(Encoding.T2, t, imm32, n, index, add, wback); } uint Execute_STR_immediate_thumb_T2() { //A8.6.193 STR (immediate,thumb) uint Rt = Reg8(8); uint imm8 = instruction & 0xFF; const uint n = 13; uint imm32 = _ZeroExtend_32(imm8 << 2); const bool index = true; const bool add = true; const bool wback = false; return ExecuteCore_STR_immediate_thumb(Encoding.T2, Rt, imm32, n, index, add, wback); } uint ExecuteThumb_32() { uint op1 = (instruction >> 11) & 3; uint op2 = (instruction >> 4) & 0x7F; ThumbFetchExtra(); uint op = _.BIT15(thumb_32bit_extra); switch (op1) { case _.b00: throw new InvalidOperationException("decode error"); case _.b01: return Execute_Unhandled("thumb-32bit"); case _.b10: if (op == 0) return Execute_Unhandled("thumb-32bit"); else return ExecuteThumb_32_BranchAndMiscControl(op2); case _.b11: return Execute_Unhandled("thumb-32bit"); default: throw new InvalidOperationException(); } } uint ExecuteThumb_32_BranchAndMiscControl(uint op) { uint op1 = (thumb_32bit_extra >> 12) & 7; switch (op1) { case _.b000: case _.b010: return Execute_Unhandled("thumb-32bit"); case _.b001: case _.b011: return Execute_Unhandled("thumb-32bit 6T2 branch"); case _.b100: case _.b110: return Execute_BL_BLX_immediate_T2(); case _.b101: case _.b111: return Execute_BL_BLX_immediate_T1(); default: throw new InvalidOperationException(); } } uint Execute_BL_BLX_immediate_T1() { //A8.6.23 uint S = _.BIT10(instruction); uint J1 = _.BIT13(thumb_32bit_extra); uint J2 = _.BIT11(thumb_32bit_extra); uint imm11 = thumb_32bit_extra & _.b11111111111; uint imm10 = instruction & _.b1111111111; uint I1 = (~(J1 ^ S)) & 1; uint I2 = (~(J2 ^ S)) & 1; int imm32 = _SignExtend_32(25, (imm11 << 1) | (imm10 << 12) | (I2 << 22) | (I1 << 23) | (S << 24)); if (_InITBlock() && !_LastInITBlock()) _UNPREDICTABLE(); return ExecuteCore_BL_BLX_immediate(Encoding.T1, _CurrentInstrSet(), imm32, false); } uint Execute_BL_BLX_immediate_T2() { //A8.6.23 uint S = _.BIT10(instruction); uint J1 = _.BIT13(thumb_32bit_extra); uint J2 = _.BIT11(thumb_32bit_extra); uint H = _.BIT0(thumb_32bit_extra); uint imm10L = (thumb_32bit_extra >> 1) & 0x3FF; uint imm10H = instruction & 0x3FF; uint I1 = (~(J1 ^ S)) & 1; uint I2 = (~(J2 ^ S)) & 1; int imm32 = _SignExtend_32(25, (imm10L << 2) | (imm10H << 12) | (I2 << 22) | (I1 << 23) | (S << 24)); return ExecuteCore_BL_BLX_immediate(Encoding.T2, EInstrSet.ARM, imm32, true); } uint ExecuteThumb_AluMisc() { //A6.2.1 uint opcode = (instruction >> 9) & 0x1F; switch (opcode) { case _.b00000: case _.b00001: case _.b00010: case _.b00011: return Execute_LSL_immediate_T1(); case _.b00100: case _.b00101: case _.b00110: case _.b00111: return Execute_LSR_immediate_T1(); case _.b01000: case _.b01001: case _.b01010: case _.b01011: return Execute_ASR_immediate_T1(); case _.b01100: return Execute_ADD_Register_T1(); case _.b01101: return Execute_SUB_Register_T1(); case _.b01110: return Execute_ADD_immediate_thumb_T1(); case _.b01111: return Execute_SUB_immediate_thumb_T1(); case _.b10000: case _.b10001: case _.b10010: case _.b10011: return Execute_MOV_immediate_T1(); case _.b10100: case _.b10101: case _.b10110: case _.b10111: return Execute_CMP_immediate_T1(); case _.b11000: case _.b11001: case _.b11010: case _.b11011: return Execute_ADD_immediate_thumb_T2(); case _.b11100: case _.b11101: case _.b11110: case _.b11111: return Execute_SUB_immediate_thumb_T2(); } return Execute_Unhandled("ExecuteThumb_AluMisc"); } uint Execute_CMP_immediate_T1() { //A8.6.35 CMP immediate //A8-80 uint n = Reg8(8); uint imm8 = instruction & 0xFF; uint imm32 = _ZeroExtend_32(imm8); return ExecuteCore_CMP_immediate(Encoding.T1, n, imm32); } uint Execute_MOV_immediate_T1() { //A8.6.96 MOV immediate uint d = Reg8(8); uint imm8 = instruction & 0xFF; bool setflags = !_InITBlock(); uint imm32 = _ZeroExtend_32(imm8); Bit carry = APSR.C; return ExecuteCore_MOV_immediate(Encoding.T1, d, setflags, imm32, carry); } uint Execute_SUB_Register_T1() { //A8.6.213 SUB (register) uint d = Reg8(0); uint n = Reg8(3); uint m = Reg8(6); bool setflags = !_InITBlock(); const SRType shift_t = SRType.LSL; const int shift_n = 0; return ExecuteCore_SUB_register(Encoding.T1, setflags, m, n, d, shift_t, shift_n); } uint Execute_ADD_Register_T1() { //A8.6.6 ADD (register) uint d = Reg8(0); uint n = Reg8(3); uint m = Reg8(6); bool setflags = !_InITBlock(); const SRType shift_t = SRType.LSL; const int shift_n = 0; return ExecuteCore_ADD_register(Encoding.T1, m, d, n, setflags, shift_t, shift_n); } uint Execute_ADD_register_T2() { //A8.6.6 ADD (register) Bit DN = _.BIT7(instruction); uint rdn = Reg8(0); uint m = Reg16(3); Debug.Assert(!(DN == 1 && rdn == _.b101 || m == _.b1101), "see ADD (SP plus register)"); uint d = rdn; uint n = rdn; bool setflags = false; const SRType shift_t = SRType.LSL; const int shift_n = 0; if (n == 15 && m == 15) _FlagUnpredictable(); if (d == 15 && _InITBlock() && !_LastInITBlock()) _FlagUnpredictable(); return ExecuteCore_ADD_register(Encoding.T2, m, d, n, setflags, shift_t, shift_n); } uint Execute_SUB_immediate_thumb_T1() { //A7.6.211 uint d = Reg8(0); uint n = Reg8(3); uint imm3 = (instruction >> 6) & 7; bool setflags = !_InITBlock(); uint imm32 = _ZeroExtend_32(imm3); return ExecuteCore_SUB_immediate_thumb(Encoding.T1, n, d, setflags, imm32); } uint Execute_ADD_immediate_thumb_T1() { uint d = Reg8(0); uint n = Reg8(3); uint imm3 = (instruction >> 6) & 7; bool setflags = !_InITBlock(); uint imm32 = _ZeroExtend_32(imm3); return ExecuteCore_ADD_immediate_thumb(Encoding.T1, n, d, setflags, imm32); } uint Execute_SUB_immediate_thumb_T2() { //A8.6.211 uint d = Reg8(8); uint n = d; bool setflags = !_InITBlock(); uint imm8 = (instruction & 0xFF); uint imm32 = _ZeroExtend_32(imm8); return ExecuteCore_SUB_immediate_thumb(Encoding.T2, n, d, setflags, imm32); } uint Execute_ADD_immediate_thumb_T2() { uint Rdn = Reg8(8); uint imm8 = instruction & _.b11111111; uint d = Rdn; uint n = Rdn; bool setflags = !_InITBlock(); uint imm32 = imm8; return ExecuteCore_ADD_immediate_thumb(Encoding.T2, n, d, setflags, imm32); } uint Execute_LSL_immediate_T1() { //A8.6.14 uint imm5 = (instruction >> 6) & 0x1F; if (imm5 == 0 && procopt.Thumb_LSL_immediate_T1_0_is_MOV_register_T2) return Execute_MOV_register_T2(); uint d = Reg8(0); uint m = Reg8(3); bool setflags = !_InITBlock(); _DecodeImmShift(0, imm5); return ExecuteCore_LSL_immediate(Encoding.T1, d, m, setflags, shift_n); } uint Execute_ASR_immediate_T1() { //A8.6.14 ASR (immediate) uint d = Reg8(0); uint m = Reg8(3); uint imm5 = (instruction >> 6) & 0x1F; bool setflags = !_InITBlock(); _DecodeImmShift(_.b10, imm5); return ExecuteCore_ASR_immediate(Encoding.T1, d, m, setflags, shift_n); } uint Execute_LSR_immediate_T1() { uint imm5 = (instruction >> 6) & 0x1F; uint m = Reg8(3); uint d = Reg8(0); bool setflags = !_InITBlock(); _DecodeImmShift(_.b01, imm5); return ExecuteCore_LSR_immediate(Encoding.T1, d, m, setflags, shift_n); } uint Execute_MOV_register_T1() { //A8.6.97 MOV (register) uint D = _.BIT7(instruction); uint d = Reg8(0) + 8 * D; uint m = Reg16(3); bool setflags = false; if (d == 15 && _InITBlock() && !_LastInITBlock()) unpredictable = true; //my own sanity check: if (m >= 8 && _ArchVersion() < 6) throw new InvalidOperationException("thumb mov register invalid for your architecture version. need to think about this."); return ExecuteCore_MOV_register(Encoding.T1, d, m, setflags); } uint Execute_MOV_register_T2() { uint D = _.BIT7(instruction); uint d = Reg8(0); uint m = Reg8(3); bool setflags = true; if (_InITBlock()) unpredictable = true; return ExecuteCore_MOV_register(Encoding.T2, d, m, setflags); } uint ExecuteThumb_DataProcessing() { //A6.2.2 uint opcode = (instruction >> 6) & 0xF; switch (opcode) { case _.b0000: return Execute_Unhandled("thumb AND reg"); case _.b0001: return Execute_EOR_register_T1(); case _.b0010: return Execute_Unhandled("thumb LSL reg"); case _.b0011: return Execute_Unhandled("thumb LSR reg"); case _.b0100: return Execute_Unhandled("thumb ASR reg"); case _.b0101: return Execute_Unhandled("thumb ADC reg"); case _.b0110: return Execute_Unhandled("thumb SBC reg"); case _.b0111: return Execute_Unhandled("thumb ROR reg"); case _.b1000: return Execute_Unhandled("thumb TST reg"); case _.b1001: return Execute_RSB_immediate_T1(); case _.b1010: return Execute_CMP_register_T1(); case _.b1011: return Execute_Unhandled("thumb CMN reg"); case _.b1100: return Execute_ORR_register_T1(); case _.b1101: return Execute_Unhandled("thumb MUL"); case _.b1110: return Execute_Unhandled("thumb BIC reg"); case _.b1111: return Execute_Unhandled("thumb MVN reg"); default: throw new InvalidOperationException(); } } uint Execute_RSB_immediate_T1() { //A8.6.142 uint d = Reg8(0); uint n = Reg8(3); bool setflags = !_InITBlock(); uint imm32 = 0; return ExecuteCore_RSB_immediate(Encoding.T1, d, n, setflags, imm32); } uint Execute_EOR_register_T1() { //A8.6.45 uint d = Reg8(0); uint n = d; uint m = Reg8(3); bool setflags = !_InITBlock(); const SRType shift_t = SRType.LSL; const int shift_n = 0; return ExecuteCore_EOR_register(Encoding.T1, m, d, n, setflags, shift_t, shift_n); } uint Execute_ORR_register_T1() { //A7.6.114 uint d = Reg8(0); uint n = d; uint m = Reg8(3); bool setflags = !_InITBlock(); const SRType shift_t = SRType.LSL; const int shift_n = 0; return ExecuteCore_ORR_register(Encoding.T1, m, d, n, setflags, shift_t, shift_n); } uint Execute_CMP_register_T1() { //A8.6.36 uint n = Reg8(0); uint m = Reg8(3); SRType shift_t = SRType.LSL; int shift_n = 0; return ExecuteCore_CMP_register(Encoding.T1, n, m, shift_t, shift_n); } uint ExecuteThumb_SpecialBX() { uint opcode = (instruction >> 6) & _.b1111; switch (opcode) { case _.b0000: return Execute_Unhandled("ADD (low register) on page A8-24 [v6T2*] *unpredictable in earlier variants"); case _.b0001: case _.b0010: case _.b0011: return Execute_ADD_register_T2(); case _.b0100: return _UNPREDICTABLE(); case _.b0101: case _.b0110: case _.b0111: return Execute_Unhandled("CMP (high register) on page A8-82 [v4t]"); case _.b1000: return Execute_MOV_register_T1(); case _.b1001: case _.b1010: case _.b1011: return Execute_MOV_register_T1(); case _.b1100: case _.b1101: return Execute_BX_T1(); case _.b1110: case _.b1111: return Execute_BLX_register_T1(); default: throw new InvalidOperationException("decode fail"); } } uint Execute_BLX_register_T1() { //A8.6.24 uint m = Reg16(3); if (m == 15) _FlagUnpredictable(); if (_InITBlock() && !_LastInITBlock()) _FlagUnpredictable(); return ExecuteCore_BLX_register(Encoding.T1, m); } uint Execute_BX_T1() { //A8.6.25 uint m = Reg16(3); if (_InITBlock() && !_LastInITBlock()) return _UNPREDICTABLE(); if (disassemble) return DISNEW("BX", "", m); _BXWritePC(r[m]); return 1; } uint Execute_ADR_T1() { //A8.6.10 uint d = Reg8(8); uint imm8 = instruction & 0xFF; uint imm32 = _ZeroExtend_32(imm8 << 2); const bool add = true; return ExecuteCore_ADR(Encoding.T1, d, imm32, add); } uint Execute_ADD_SP_plus_immediate_T2() { //A8.6.8 uint d = 13; uint imm7 = (instruction & 0xFF); bool setflags = false; uint imm32 = _ZeroExtend_32(imm7 << 2); return ExecuteCore_ADD_SP_plus_immedate(Encoding.T2, d, setflags, imm32); } uint Execute_ADD_SP_plus_immediate_T1() { //A8.6.8 ADD SP plus immediate //A8-28 uint d = Reg8(8); uint imm8 = (instruction & 0xFF); bool setflags = false; uint imm32 = _ZeroExtend_32(imm8 << 2); return ExecuteCore_ADD_SP_plus_immedate(Encoding.T1, d, setflags, imm32); } uint ExecuteThumb_Misc16() { uint opcode = (instruction >> 5) & 0x7F; //ThumbMisc switch((opcode<<0)) { //opcode == #0110010 case 50: Execute_Unhandled("SETEND on page A8-314"); break; //opcode == #0110011 case 51: Execute_Unhandled("CPS on page B6-3"); break; //opcode == #00000xx case 0: case 1: case 2: case 3: Execute_ADD_SP_plus_immediate_T2(); break; //opcode == #00001xx case 4: case 5: case 6: case 7: Execute_SUB_SP_minus_immediate_T1(); break; //opcode == #0001xxx //opcode == #0011xxx //opcode == #1001xxx case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79: Execute_Unhandled("CBNZ,CBZ on page A8-66 [v6T2]"); break; //opcode == #001000x case 16: case 17: Execute_Unhandled("SXTH on page A8-444"); break; //opcode == #001001x case 18: case 19: Execute_Unhandled("SXTB on page A8-440"); break; //opcode == #001010x case 20: case 21: Execute_UXTH_T1(); break; //opcode == #001011x case 22: case 23: Execute_UXTB_T1(); break; //opcode == #010xxxx case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: Execute_PUSH_T1(); break; //opcode == #101000x case 80: case 81: Execute_Unhandled("REV on page A8-272"); break; //opcode == #101001x case 82: case 83: Execute_Unhandled("REV16 on page A8-274"); break; //opcode == #101011x case 86: case 87: Execute_Unhandled("REVSH on page A8-276"); break; //opcode == #110xxxx case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: Execute_POP_T1(); break; //opcode == #1110xxx case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: Execute_Unhandled("BKPT on page A8-56"); break; //opcode == #1111xxx case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: Execute_Unhandled("If-Then and hints on page A6-12"); break; default: throw new InvalidOperationException("unhandled case for switch ThumbMisc"); } return 1; } uint Execute_POP_T1() { //A8.6.122 uint P = _.BIT8(instruction); uint registers = (P << 15) | (instruction & 0xFF); bool UnalignedAllowed = false; if (registers == 0) { _UNPREDICTABLE(); return 1; } if (P == 1 && _InITBlock() && !_LastInITBlock()) { _UNPREDICTABLE(); return 1; } if (disassemble) return DISNEW("pop", "", registers); return ExecuteCore_POP(Encoding.T1, registers, UnalignedAllowed); } uint Execute_SUB_SP_minus_immediate_T1() { //A8.6.215 SUB (SP minus immediate) const uint d = 13; uint imm7 = instruction & 0x7F; bool setflags = false; uint imm32 = _ZeroExtend_32(imm7 << 2); return ExecuteCore_SUB_SP_minus_immediate(Encoding.T1, d, setflags, imm32); } uint Execute_UXTH_T1() { //A8.6.265 uint d = Reg8(0); uint m = Reg8(3); const uint rotation = 0; return ExecuteCore_UXTH(Encoding.T1, d, m, rotation); } uint Execute_UXTB_T1() { //A8.6.263 uint d = Reg8(0); uint m = Reg8(3); const uint rotation = 0; return ExecuteCore_UXTB(Encoding.T1, d, m, rotation); } uint Execute_PUSH_T1() { //A8.6.123 uint M = _.BIT8(instruction); uint regs = (M << 14) | (instruction & 0xFF); if (_.BitCount(regs) < 1) unpredictable = true; return ExecuteCore_PUSH(Encoding.T1, regs, false); } uint Execute_LDM_LDMIA_LDMFD_T1() { //A8.6.53 LDM/LDMIA/LDMFD if (_CurrentInstrSet() == EInstrSet.THUMBEE) throw new NotImplementedException(); uint n = Reg8(8); uint registers = instruction & 0xFF; bool wback = (_.BITN((int)n, registers) == 0); if (registers == 0) _FlagUnpredictable(); return ExecuteCore_LDM_LDMIA_LDMFD(Encoding.T1, wback, n, registers); } uint Execute_STM_STMIA_STMEA_T1() { //A8.6.189 STM/STMIA/STMEA if (_CurrentInstrSet() == EInstrSet.THUMBEE) throw new NotImplementedException(); uint n = Reg8(8); uint registers = instruction & 0xFF; bool wback = true; if (registers == 0) unpredictable = true; return ExecuteCore_STM_STMIA_STMEA(Encoding.T1, wback, n, registers); } uint ExecuteThumb_CondBr_And_SVC() { uint opcode = (instruction >> 8) & 0xF; switch (opcode) { case _.b0000: case _.b0001: case _.b0010: case _.b0011: case _.b0100: case _.b0101: case _.b0110: case _.b0111: case _.b1000: case _.b1001: case _.b1010: case _.b1011: case _.b1100: case _.b1101: return Execute_B_T1(); case _.b1110: return _PERMANENTLY_UNDEFINED(); case _.b1111: return Execute_SVC_T1(); default: throw new InvalidOperationException("decode fail"); } } uint ExecuteThumb_UnCondBr() { return Execute_Unhandled("ExecuteThumb_UnCondBr"); } uint Execute_B_T2() { //A8.6.16 B uint imm11 = instruction & 0x7FF; int imm32 = _SignExtend_32(11, imm11 << 1); if (_InITBlock() && !_LastInITBlock()) unpredictable = true; return ExecuteCore_B(Encoding.T2, imm32); } uint Execute_B_T1() { //A8.6.16 B uint imm8 = (instruction & 0xFF); int imm32 = _SignExtend_32(9, imm8 << 1); _currentCondVal = (instruction >> 8) & 0xF; if (_InITBlock()) return _UNPREDICTABLE(); return ExecuteCore_B(Encoding.T1, imm32); } uint Execute_SVC_T1() { return Execute_Unhandled("Execute_SVC_T1"); } } }