rlm@1: #ifdef BKPT_SUPPORT rlm@1: #define CONSOLE_OUTPUT(a, b) \ rlm@1: extern void (*dbgOutput)(char *, u32); \ rlm@1: if ((opcode == 0xe0000000) && (reg[0].I == 0xC0DED00D)) { \ rlm@1: dbgOutput((a), (b)); \ rlm@1: } rlm@1: #else rlm@1: #define CONSOLE_OUTPUT(a, b) rlm@1: #endif rlm@1: rlm@1: #define OP_AND \ rlm@1: reg[dest].I = reg[(opcode >> 16) & 15].I & value; \ rlm@1: CONSOLE_OUTPUT(NULL, reg[2].I); rlm@1: rlm@1: #define OP_ANDS \ rlm@1: reg[dest].I = reg[(opcode >> 16) & 15].I & value; \ rlm@1: \ rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (reg[dest].I) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: rlm@1: #define OP_EOR \ rlm@1: reg[dest].I = reg[(opcode >> 16) & 15].I ^ value; rlm@1: rlm@1: #define OP_EORS \ rlm@1: reg[dest].I = reg[(opcode >> 16) & 15].I ^ value; \ rlm@1: \ rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (reg[dest].I) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: #ifdef C_CORE rlm@1: #define NEG(i) ((i) >> 31) rlm@1: #define POS(i) ((~(i)) >> 31) rlm@1: #define ADDCARRY(a, b, c) \ rlm@1: C_FLAG = ((NEG(a) & NEG(b)) | \ rlm@1: (NEG(a) & POS(c)) | \ rlm@1: (NEG(b) & POS(c))) ? true : false; rlm@1: #define ADDOVERFLOW(a, b, c) \ rlm@1: V_FLAG = ((NEG(a) & NEG(b) & POS(c)) | \ rlm@1: (POS(a) & POS(b) & NEG(c))) ? true : false; rlm@1: #define SUBCARRY(a, b, c) \ rlm@1: C_FLAG = ((NEG(a) & POS(b)) | \ rlm@1: (NEG(a) & POS(c)) | \ rlm@1: (POS(b) & POS(c))) ? true : false; rlm@1: #define SUBOVERFLOW(a, b, c) \ rlm@1: V_FLAG = ((NEG(a) & POS(b) & POS(c)) | \ rlm@1: (POS(a) & NEG(b) & NEG(c))) ? true : false; rlm@1: #define OP_SUB \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I - value; \ rlm@1: } rlm@1: #define OP_SUBS \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = lhs - rhs; \ rlm@1: reg[dest].I = res; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: SUBCARRY(lhs, rhs, res); \ rlm@1: SUBOVERFLOW(lhs, rhs, res); \ rlm@1: } rlm@1: #define OP_RSB \ rlm@1: { \ rlm@1: reg[dest].I = value - reg[base].I; \ rlm@1: } rlm@1: #define OP_RSBS \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = rhs - lhs; \ rlm@1: reg[dest].I = res; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: SUBCARRY(rhs, lhs, res); \ rlm@1: SUBOVERFLOW(rhs, lhs, res); \ rlm@1: } rlm@1: #define OP_ADD \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I + value; \ rlm@1: } rlm@1: #define OP_ADDS \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = lhs + rhs; \ rlm@1: reg[dest].I = res; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: ADDCARRY(lhs, rhs, res); \ rlm@1: ADDOVERFLOW(lhs, rhs, res); \ rlm@1: } rlm@1: #define OP_ADC \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I + value + (u32)C_FLAG; \ rlm@1: } rlm@1: #define OP_ADCS \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = lhs + rhs + (u32)C_FLAG; \ rlm@1: reg[dest].I = res; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: ADDCARRY(lhs, rhs, res); \ rlm@1: ADDOVERFLOW(lhs, rhs, res); \ rlm@1: } rlm@1: #define OP_SBC \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I - value - !((u32)C_FLAG); \ rlm@1: } rlm@1: #define OP_SBCS \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = lhs - rhs - !((u32)C_FLAG); \ rlm@1: reg[dest].I = res; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: SUBCARRY(lhs, rhs, res); \ rlm@1: SUBOVERFLOW(lhs, rhs, res); \ rlm@1: } rlm@1: #define OP_RSC \ rlm@1: { \ rlm@1: reg[dest].I = value - reg[base].I - !((u32)C_FLAG); \ rlm@1: } rlm@1: #define OP_RSCS \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = rhs - lhs - !((u32)C_FLAG); \ rlm@1: reg[dest].I = res; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: SUBCARRY(rhs, lhs, res); \ rlm@1: SUBOVERFLOW(rhs, lhs, res); \ rlm@1: } rlm@1: #define OP_CMP \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = lhs - rhs; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: SUBCARRY(lhs, rhs, res); \ rlm@1: SUBOVERFLOW(lhs, rhs, res); \ rlm@1: } rlm@1: #define OP_CMN \ rlm@1: { \ rlm@1: u32 lhs = reg[base].I; \ rlm@1: u32 rhs = value; \ rlm@1: u32 res = lhs + rhs; \ rlm@1: Z_FLAG = (res == 0) ? true : false; \ rlm@1: N_FLAG = NEG(res) ? true : false; \ rlm@1: ADDCARRY(lhs, rhs, res); \ rlm@1: ADDOVERFLOW(lhs, rhs, res); \ rlm@1: } rlm@1: rlm@1: #define LOGICAL_LSL_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = (v >> (32 - shift)) & 1 ? true : false; \ rlm@1: value = v << shift; \ rlm@1: } rlm@1: #define LOGICAL_LSR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ rlm@1: value = v >> shift; \ rlm@1: } rlm@1: #define LOGICAL_ASR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false; \ rlm@1: value = (s32)v >> (int)shift; \ rlm@1: } rlm@1: #define LOGICAL_ROR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define LOGICAL_RRX_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: shift = (int)C_FLAG; \ rlm@1: C_OUT = (v & 1) ? true : false; \ rlm@1: value = ((v >> 1) | \ rlm@1: (shift << 31)); \ rlm@1: } rlm@1: #define LOGICAL_ROR_IMM \ rlm@1: { \ rlm@1: u32 v = opcode & 0xff; \ rlm@1: C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ARITHMETIC_LSL_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = v << shift; \ rlm@1: } rlm@1: #define ARITHMETIC_LSR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = v >> shift; \ rlm@1: } rlm@1: #define ARITHMETIC_ASR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = (s32)v >> (int)shift; \ rlm@1: } rlm@1: #define ARITHMETIC_ROR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ARITHMETIC_RRX_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: shift = (int)C_FLAG; \ rlm@1: value = ((v >> 1) | \ rlm@1: (shift << 31)); \ rlm@1: } rlm@1: #define ARITHMETIC_ROR_IMM \ rlm@1: { \ rlm@1: u32 v = opcode & 0xff; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ROR_IMM_MSR \ rlm@1: { \ rlm@1: u32 v = opcode & 0xff; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ROR_VALUE \ rlm@1: { \ rlm@1: value = ((value << (32 - shift)) | \ rlm@1: (value >> shift)); \ rlm@1: } rlm@1: #define RCR_VALUE \ rlm@1: { \ rlm@1: shift = (int)C_FLAG; \ rlm@1: value = ((value >> 1) | \ rlm@1: (shift << 31)); \ rlm@1: } rlm@1: #else rlm@1: #ifdef __GNUC__ rlm@1: #ifdef __POWERPC__ rlm@1: #define OP_SUB \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I - value; \ rlm@1: } rlm@1: #define OP_SUBS \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("subco. %0, %2, %3\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value) \ rlm@1: ); \ rlm@1: reg[dest].I = Result; \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: #define OP_RSB \ rlm@1: { \ rlm@1: reg[dest].I = value - reg[base].I; \ rlm@1: } rlm@1: #define OP_RSBS \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("subfco. %0, %2, %3\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value) \ rlm@1: ); \ rlm@1: reg[dest].I = Result; \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: #define OP_ADD \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I + value; \ rlm@1: } rlm@1: rlm@1: #define OP_ADDS \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("addco. %0, %2, %3\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value) \ rlm@1: ); \ rlm@1: reg[dest].I = Result; \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: #define OP_ADC \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I + value + (u32)C_FLAG; \ rlm@1: } rlm@1: #define OP_ADCS \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("mtspr xer, %4\n" \ rlm@1: "addeo. %0, %2, %3\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value), \ rlm@1: "r" (C_FLAG << 29) \ rlm@1: ); \ rlm@1: reg[dest].I = Result; \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: #define OP_SBC \ rlm@1: { \ rlm@1: reg[dest].I = reg[base].I - value - (C_FLAG ^ 1); \ rlm@1: } rlm@1: #define OP_SBCS \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("mtspr xer, %4\n" \ rlm@1: "subfeo. %0, %3, %2\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value), \ rlm@1: "r" (C_FLAG << 29) \ rlm@1: ); \ rlm@1: reg[dest].I = Result; \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: #define OP_RSC \ rlm@1: { \ rlm@1: reg[dest].I = value - reg[base].I - (C_FLAG ^ 1); \ rlm@1: } rlm@1: #define OP_RSCS \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("mtspr xer, %4\n" \ rlm@1: "subfeo. %0, %2, %3\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value), \ rlm@1: "r" (C_FLAG << 29) \ rlm@1: ); \ rlm@1: reg[dest].I = Result; \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: #define OP_CMP \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("subco. %0, %2, %3\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value) \ rlm@1: ); \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: #define OP_CMN \ rlm@1: { \ rlm@1: register int Flags; \ rlm@1: register int Result; \ rlm@1: asm volatile ("addco. %0, %2, %3\n" \ rlm@1: "mcrxr cr1\n" \ rlm@1: "mfcr %1\n" \ rlm@1: : "=r" (Result), \ rlm@1: "=r" (Flags) \ rlm@1: : "r" (reg[base].I), \ rlm@1: "r" (value) \ rlm@1: ); \ rlm@1: Z_FLAG = (Flags >> 29) & 1; \ rlm@1: N_FLAG = (Flags >> 31) & 1; \ rlm@1: C_FLAG = (Flags >> 25) & 1; \ rlm@1: V_FLAG = (Flags >> 26) & 1; \ rlm@1: } rlm@1: rlm@1: #define LOGICAL_LSL_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = (v >> (32 - shift)) & 1 ? true : false; \ rlm@1: value = v << shift; \ rlm@1: } rlm@1: #define LOGICAL_LSR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ rlm@1: value = v >> shift; \ rlm@1: } rlm@1: #define LOGICAL_ASR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false; \ rlm@1: value = (s32)v >> (int)shift; \ rlm@1: } rlm@1: #define LOGICAL_ROR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define LOGICAL_RRX_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: shift = (int)C_FLAG; \ rlm@1: C_OUT = (v & 1) ? true : false; \ rlm@1: value = ((v >> 1) | \ rlm@1: (shift << 31)); \ rlm@1: } rlm@1: #define LOGICAL_ROR_IMM \ rlm@1: { \ rlm@1: u32 v = opcode & 0xff; \ rlm@1: C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ARITHMETIC_LSL_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = v << shift; \ rlm@1: } rlm@1: #define ARITHMETIC_LSR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = v >> shift; \ rlm@1: } rlm@1: #define ARITHMETIC_ASR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = (s32)v >> (int)shift; \ rlm@1: } rlm@1: #define ARITHMETIC_ROR_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ARITHMETIC_RRX_REG \ rlm@1: { \ rlm@1: u32 v = reg[opcode & 0x0f].I; \ rlm@1: shift = (int)C_FLAG; \ rlm@1: value = ((v >> 1) | \ rlm@1: (shift << 31)); \ rlm@1: } rlm@1: #define ARITHMETIC_ROR_IMM \ rlm@1: { \ rlm@1: u32 v = opcode & 0xff; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ROR_IMM_MSR \ rlm@1: { \ rlm@1: u32 v = opcode & 0xff; \ rlm@1: value = ((v << (32 - shift)) | \ rlm@1: (v >> shift)); \ rlm@1: } rlm@1: #define ROR_VALUE \ rlm@1: { \ rlm@1: value = ((value << (32 - shift)) | \ rlm@1: (value >> shift)); \ rlm@1: } rlm@1: #define RCR_VALUE \ rlm@1: { \ rlm@1: shift = (int)C_FLAG; \ rlm@1: value = ((value >> 1) | \ rlm@1: (shift << 31)); \ rlm@1: } rlm@1: #else rlm@1: #define OP_SUB \ rlm@1: asm ("sub %1, %%ebx;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: rlm@1: #define OP_SUBS \ rlm@1: asm ("sub %1, %%ebx;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setncb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: rlm@1: #define OP_RSB \ rlm@1: asm ("sub %1, %%ebx;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (reg[base].I), "b" (value)); rlm@1: rlm@1: #define OP_RSBS \ rlm@1: asm ("sub %1, %%ebx;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setncb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (reg[base].I), "b" (value)); rlm@1: rlm@1: #define OP_ADD \ rlm@1: asm ("add %1, %%ebx;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: rlm@1: #define OP_ADDS \ rlm@1: asm ("add %1, %%ebx;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setcb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: rlm@1: #define OP_ADC \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "adc %1, %%ebx;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: rlm@1: #define OP_ADCS \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "adc %1, %%ebx;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setcb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: rlm@1: #define OP_SBC \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "cmc;" \ rlm@1: "sbb %1, %%ebx;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: rlm@1: #define OP_SBCS \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "cmc;" \ rlm@1: "sbb %1, %%ebx;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setncb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (value), "b" (reg[base].I)); rlm@1: #define OP_RSC \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "cmc;" \ rlm@1: "sbb %1, %%ebx;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (reg[base].I), "b" (value)); rlm@1: rlm@1: #define OP_RSCS \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "cmc;" \ rlm@1: "sbb %1, %%ebx;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setncb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : "=b" (reg[dest].I) \ rlm@1: : "r" (reg[base].I), "b" (value)); rlm@1: #define OP_CMP \ rlm@1: asm ("sub %0, %1;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setncb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : \ rlm@1: : "r" (value), "r" (reg[base].I)); rlm@1: rlm@1: #define OP_CMN \ rlm@1: asm ("add %0, %1;" \ rlm@1: "setsb N_FLAG;" \ rlm@1: "setzb Z_FLAG;" \ rlm@1: "setcb C_FLAG;" \ rlm@1: "setob V_FLAG;" \ rlm@1: : \ rlm@1: : "r" (value), "r" (reg[base].I)); rlm@1: #define LOGICAL_LSL_REG \ rlm@1: asm ("shl %%cl, %%eax;" \ rlm@1: "setcb %%cl;" \ rlm@1: : "=a" (value), "=c" (C_OUT) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define LOGICAL_LSR_REG \ rlm@1: asm ("shr %%cl, %%eax;" \ rlm@1: "setcb %%cl;" \ rlm@1: : "=a" (value), "=c" (C_OUT) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define LOGICAL_ASR_REG \ rlm@1: asm ("sar %%cl, %%eax;" \ rlm@1: "setcb %%cl;" \ rlm@1: : "=a" (value), "=c" (C_OUT) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define LOGICAL_ROR_REG \ rlm@1: asm ("ror %%cl, %%eax;" \ rlm@1: "setcb %%cl;" \ rlm@1: : "=a" (value), "=c" (C_OUT) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define LOGICAL_RRX_REG \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "rcr $1, %%eax;" \ rlm@1: "setcb %%cl;" \ rlm@1: : "=a" (value), "=c" (C_OUT) \ rlm@1: : "a" (reg[opcode & 0x0f].I)); rlm@1: rlm@1: #define LOGICAL_ROR_IMM \ rlm@1: asm ("ror %%cl, %%eax;" \ rlm@1: "setcb %%cl;" \ rlm@1: : "=a" (value), "=c" (C_OUT) \ rlm@1: : "a" (opcode & 0xff), "c" (shift)); rlm@1: #define ARITHMETIC_LSL_REG \ rlm@1: asm ("\ rlm@1: shl %%cl, %%eax;" \ rlm@1: : "=a" (value) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define ARITHMETIC_LSR_REG \ rlm@1: asm ("\ rlm@1: shr %%cl, %%eax;" \ rlm@1: : "=a" (value) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define ARITHMETIC_ASR_REG \ rlm@1: asm ("\ rlm@1: sar %%cl, %%eax;" \ rlm@1: : "=a" (value) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define ARITHMETIC_ROR_REG \ rlm@1: asm ("\ rlm@1: ror %%cl, %%eax;" \ rlm@1: : "=a" (value) \ rlm@1: : "a" (reg[opcode & 0x0f].I), "c" (shift)); rlm@1: rlm@1: #define ARITHMETIC_RRX_REG \ rlm@1: asm ("\ rlm@1: bt $0, C_FLAG;\ rlm@1: rcr $1, %%eax;" \ rlm@1: : "=a" (value) \ rlm@1: : "a" (reg[opcode & 0x0f].I)); rlm@1: rlm@1: #define ARITHMETIC_ROR_IMM \ rlm@1: asm ("\ rlm@1: ror %%cl, %%eax;" \ rlm@1: : "=a" (value) \ rlm@1: : "a" (opcode & 0xff), "c" (shift)); rlm@1: #define ROR_IMM_MSR \ rlm@1: asm ("ror %%cl, %%eax;" \ rlm@1: : "=a" (value) \ rlm@1: : "a" (opcode & 0xFF), "c" (shift)); rlm@1: #define ROR_VALUE \ rlm@1: asm ("ror %%cl, %0" \ rlm@1: : "=r" (value) \ rlm@1: : "r" (value), "c" (shift)); rlm@1: #define RCR_VALUE \ rlm@1: asm ("bt $0, C_FLAG;" \ rlm@1: "rcr $1, %0" \ rlm@1: : "=r" (value) \ rlm@1: : "r" (value)); rlm@1: #endif rlm@1: #else rlm@1: #define OP_SUB \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm sub ebx, value \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: } rlm@1: rlm@1: #define OP_SUBS \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm sub ebx, value \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setnc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: rlm@1: #define OP_RSB \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm mov eax, value \ rlm@1: __asm sub eax, ebx \ rlm@1: __asm mov ebx, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * ebx], eax \ rlm@1: } rlm@1: rlm@1: #define OP_RSBS \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm mov eax, value \ rlm@1: __asm sub eax, ebx \ rlm@1: __asm mov ebx, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * ebx], eax \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setnc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: rlm@1: #define OP_ADD \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm add ebx, value \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: } rlm@1: rlm@1: #define OP_ADDS \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm add ebx, value \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: rlm@1: #define OP_ADC \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm adc ebx, value \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: } rlm@1: rlm@1: #define OP_ADCS \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm adc ebx, value \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: rlm@1: #define OP_SBC \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm mov eax, value \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm cmc \ rlm@1: __asm sbb ebx, eax \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: } rlm@1: rlm@1: #define OP_SBCS \ rlm@1: { \ rlm@1: __asm mov ebx, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ rlm@1: __asm mov eax, value \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm cmc \ rlm@1: __asm sbb ebx, eax \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setnc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: #define OP_RSC \ rlm@1: { \ rlm@1: __asm mov ebx, value \ rlm@1: __asm mov eax, base \ rlm@1: __asm mov eax, dword ptr[OFFSET reg + 4 * eax] \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm cmc \ rlm@1: __asm sbb ebx, eax \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: } rlm@1: rlm@1: #define OP_RSCS \ rlm@1: { \ rlm@1: __asm mov ebx, value \ rlm@1: __asm mov eax, base \ rlm@1: __asm mov eax, dword ptr[OFFSET reg + 4 * eax] \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm cmc \ rlm@1: __asm sbb ebx, eax \ rlm@1: __asm mov eax, dest \ rlm@1: __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setnc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: #define OP_CMP \ rlm@1: { \ rlm@1: __asm mov eax, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm sub ebx, value \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setnc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: rlm@1: #define OP_CMN \ rlm@1: { \ rlm@1: __asm mov eax, base \ rlm@1: __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm add ebx, value \ rlm@1: __asm sets byte ptr N_FLAG \ rlm@1: __asm setz byte ptr Z_FLAG \ rlm@1: __asm setc byte ptr C_FLAG \ rlm@1: __asm seto byte ptr V_FLAG \ rlm@1: } rlm@1: #define LOGICAL_LSL_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0f \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm shl eax, cl \ rlm@1: __asm mov value, eax \ rlm@1: __asm setc byte ptr C_OUT rlm@1: rlm@1: #define LOGICAL_LSR_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0f \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm shr eax, cl \ rlm@1: __asm mov value, eax \ rlm@1: __asm setc byte ptr C_OUT rlm@1: rlm@1: #define LOGICAL_ASR_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0f \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm sar eax, cl \ rlm@1: __asm mov value, eax \ rlm@1: __asm setc byte ptr C_OUT rlm@1: rlm@1: #define LOGICAL_ROR_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0F \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm ror eax, cl \ rlm@1: __asm mov value, eax \ rlm@1: __asm setc byte ptr C_OUT rlm@1: rlm@1: #define LOGICAL_RRX_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0F \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm bt word ptr C_OUT, 0 \ rlm@1: __asm rcr eax, 1 \ rlm@1: __asm mov value, eax \ rlm@1: __asm setc byte ptr C_OUT rlm@1: rlm@1: #define LOGICAL_ROR_IMM \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0xff \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm ror eax, cl \ rlm@1: __asm mov value, eax \ rlm@1: __asm setc byte ptr C_OUT rlm@1: #define ARITHMETIC_LSL_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0f \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm shl eax, cl \ rlm@1: __asm mov value, eax rlm@1: rlm@1: #define ARITHMETIC_LSR_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0f \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm shr eax, cl \ rlm@1: __asm mov value, eax rlm@1: rlm@1: #define ARITHMETIC_ASR_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0f \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm sar eax, cl \ rlm@1: __asm mov value, eax rlm@1: rlm@1: #define ARITHMETIC_ROR_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0F \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm ror eax, cl \ rlm@1: __asm mov value, eax rlm@1: rlm@1: #define ARITHMETIC_RRX_REG \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0x0F \ rlm@1: __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm rcr eax, 1 \ rlm@1: __asm mov value, eax rlm@1: rlm@1: #define ARITHMETIC_ROR_IMM \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0xff \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm ror eax, cl \ rlm@1: __asm mov value, eax rlm@1: #define ROR_IMM_MSR \ rlm@1: { \ rlm@1: __asm mov eax, opcode \ rlm@1: __asm and eax, 0xff \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm ror eax, CL \ rlm@1: __asm mov value, eax \ rlm@1: } rlm@1: #define ROR_VALUE \ rlm@1: { \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm ror dword ptr value, cl \ rlm@1: } rlm@1: #define RCR_VALUE \ rlm@1: { \ rlm@1: __asm mov cl, byte ptr shift \ rlm@1: __asm bt word ptr C_FLAG, 0 \ rlm@1: __asm rcr dword ptr value, 1 \ rlm@1: } rlm@1: #endif rlm@1: #endif rlm@1: rlm@1: #define OP_TST \ rlm@1: u32 res = reg[base].I & value; \ rlm@1: N_FLAG = (res & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (res) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: rlm@1: #define OP_TEQ \ rlm@1: u32 res = reg[base].I ^ value; \ rlm@1: N_FLAG = (res & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (res) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: rlm@1: #define OP_ORR \ rlm@1: reg[dest].I = reg[base].I | value; rlm@1: rlm@1: #define OP_ORRS \ rlm@1: reg[dest].I = reg[base].I | value; \ rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (reg[dest].I) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: rlm@1: #define OP_MOV \ rlm@1: reg[dest].I = value; rlm@1: rlm@1: #define OP_MOVS \ rlm@1: reg[dest].I = value; \ rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (reg[dest].I) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: rlm@1: #define OP_BIC \ rlm@1: reg[dest].I = reg[base].I & (~value); rlm@1: rlm@1: #define OP_BICS \ rlm@1: reg[dest].I = reg[base].I & (~value); \ rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (reg[dest].I) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: rlm@1: #define OP_MVN \ rlm@1: reg[dest].I = ~value; rlm@1: rlm@1: #define OP_MVNS \ rlm@1: reg[dest].I = ~value; \ rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \ rlm@1: Z_FLAG = (reg[dest].I) ? false : true; \ rlm@1: C_FLAG = C_OUT; rlm@1: rlm@1: #define CASE_16(BASE) \ rlm@1: case BASE: \ rlm@1: case BASE + 1: \ rlm@1: case BASE + 2: \ rlm@1: case BASE + 3: \ rlm@1: case BASE + 4: \ rlm@1: case BASE + 5: \ rlm@1: case BASE + 6: \ rlm@1: case BASE + 7: \ rlm@1: case BASE + 8: \ rlm@1: case BASE + 9: \ rlm@1: case BASE + 10: \ rlm@1: case BASE + 11: \ rlm@1: case BASE + 12: \ rlm@1: case BASE + 13: \ rlm@1: case BASE + 14: \ rlm@1: case BASE + 15: rlm@1: rlm@1: #define CASE_256(BASE) \ rlm@1: CASE_16(BASE) \ rlm@1: CASE_16(BASE + 0x10) \ rlm@1: CASE_16(BASE + 0x20) \ rlm@1: CASE_16(BASE + 0x30) \ rlm@1: CASE_16(BASE + 0x40) \ rlm@1: CASE_16(BASE + 0x50) \ rlm@1: CASE_16(BASE + 0x60) \ rlm@1: CASE_16(BASE + 0x70) \ rlm@1: CASE_16(BASE + 0x80) \ rlm@1: CASE_16(BASE + 0x90) \ rlm@1: CASE_16(BASE + 0xa0) \ rlm@1: CASE_16(BASE + 0xb0) \ rlm@1: CASE_16(BASE + 0xc0) \ rlm@1: CASE_16(BASE + 0xd0) \ rlm@1: CASE_16(BASE + 0xe0) \ rlm@1: CASE_16(BASE + 0xf0) rlm@1: rlm@1: #define LOGICAL_DATA_OPCODE(OPCODE, OPCODE2, BASE) \ rlm@1: case BASE: \ rlm@1: case BASE + 8: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSL # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: \ rlm@1: if (shift) { \ rlm@1: LOGICAL_LSL_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 2: \ rlm@1: case BASE + 10: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSR # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_LSR_REG \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false; \ rlm@1: } \ rlm@1: \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 4: \ rlm@1: case BASE + 12: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ASR # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ASR_REG \ rlm@1: } else { \ rlm@1: if (reg[opcode & 0x0F].I & 0x80000000) { \ rlm@1: value = 0xFFFFFFFF; \ rlm@1: C_OUT = true; \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } \ rlm@1: \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 6: \ rlm@1: case BASE + 14: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ROR # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ROR_REG \ rlm@1: } else { \ rlm@1: LOGICAL_RRX_REG \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 1: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSL Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: if (shift == 32) { \ rlm@1: value = 0; \ rlm@1: C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false); \ rlm@1: } else if (shift < 32) { \ rlm@1: LOGICAL_LSL_REG \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 3: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: if (shift == 32) { \ rlm@1: value = 0; \ rlm@1: C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false); \ rlm@1: } else if (shift < 32) { \ rlm@1: LOGICAL_LSR_REG \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 5: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ASR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift < 32) { \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ASR_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: } else { \ rlm@1: if (reg[opcode & 0x0F].I & 0x80000000) { \ rlm@1: value = 0xFFFFFFFF; \ rlm@1: C_OUT = true; \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 7: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ROR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: shift &= 0x1f; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ROR_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: C_OUT = (value & 0x80000000 ? true : false); \ rlm@1: } \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: C_OUT = (value & 0x80000000 ? true : false); \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 0x200: \ rlm@1: case BASE + 0x201: \ rlm@1: case BASE + 0x202: \ rlm@1: case BASE + 0x203: \ rlm@1: case BASE + 0x204: \ rlm@1: case BASE + 0x205: \ rlm@1: case BASE + 0x206: \ rlm@1: case BASE + 0x207: \ rlm@1: case BASE + 0x208: \ rlm@1: case BASE + 0x209: \ rlm@1: case BASE + 0x20a: \ rlm@1: case BASE + 0x20b: \ rlm@1: case BASE + 0x20c: \ rlm@1: case BASE + 0x20d: \ rlm@1: case BASE + 0x20e: \ rlm@1: case BASE + 0x20f: \ rlm@1: { \ rlm@1: int shift = (opcode & 0xF00) >> 7; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int dest = (opcode >> 12) & 0x0F; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ROR_IMM \ rlm@1: } else { \ rlm@1: value = opcode & 0xff; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; rlm@1: rlm@1: #define LOGICAL_DATA_OPCODE_WITHOUT_base(OPCODE, OPCODE2, BASE) \ rlm@1: case BASE: \ rlm@1: case BASE + 8: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSL # */ \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: \ rlm@1: if (shift) { \ rlm@1: LOGICAL_LSL_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 2: \ rlm@1: case BASE + 10: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSR # */ \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_LSR_REG \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false; \ rlm@1: } \ rlm@1: \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 4: \ rlm@1: case BASE + 12: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ASR # */ \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ASR_REG \ rlm@1: } else { \ rlm@1: if (reg[opcode & 0x0F].I & 0x80000000) { \ rlm@1: value = 0xFFFFFFFF; \ rlm@1: C_OUT = true; \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } \ rlm@1: \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 6: \ rlm@1: case BASE + 14: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ROR # */ \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ROR_REG \ rlm@1: } else { \ rlm@1: LOGICAL_RRX_REG \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 1: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSL Rs */ \ rlm@1: clockTicks++; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: if (shift == 32) { \ rlm@1: value = 0; \ rlm@1: C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false); \ rlm@1: } else if (shift < 32) { \ rlm@1: LOGICAL_LSL_REG \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 3: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: if (shift == 32) { \ rlm@1: value = 0; \ rlm@1: C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false); \ rlm@1: } else if (shift < 32) { \ rlm@1: LOGICAL_LSR_REG \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 5: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ASR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift < 32) { \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ASR_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: } else { \ rlm@1: if (reg[opcode & 0x0F].I & 0x80000000) { \ rlm@1: value = 0xFFFFFFFF; \ rlm@1: C_OUT = true; \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: C_OUT = false; \ rlm@1: } \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 7: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ROR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: shift &= 0x1f; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ROR_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: C_OUT = (value & 0x80000000 ? true : false); \ rlm@1: } \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: C_OUT = (value & 0x80000000 ? true : false); \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 0x200: \ rlm@1: case BASE + 0x201: \ rlm@1: case BASE + 0x202: \ rlm@1: case BASE + 0x203: \ rlm@1: case BASE + 0x204: \ rlm@1: case BASE + 0x205: \ rlm@1: case BASE + 0x206: \ rlm@1: case BASE + 0x207: \ rlm@1: case BASE + 0x208: \ rlm@1: case BASE + 0x209: \ rlm@1: case BASE + 0x20a: \ rlm@1: case BASE + 0x20b: \ rlm@1: case BASE + 0x20c: \ rlm@1: case BASE + 0x20d: \ rlm@1: case BASE + 0x20e: \ rlm@1: case BASE + 0x20f: \ rlm@1: { \ rlm@1: int shift = (opcode & 0xF00) >> 7; \ rlm@1: int dest = (opcode >> 12) & 0x0F; \ rlm@1: bool C_OUT = C_FLAG; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: LOGICAL_ROR_IMM \ rlm@1: } else { \ rlm@1: value = opcode & 0xff; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; rlm@1: rlm@1: #define ARITHMETIC_DATA_OPCODE(OPCODE, OPCODE2, BASE) \ rlm@1: case BASE: \ rlm@1: case BASE + 8: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSL # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: ARITHMETIC_LSL_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 2: \ rlm@1: case BASE + 10: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSR # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: ARITHMETIC_LSR_REG \ rlm@1: } else { \ rlm@1: value = 0; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 4: \ rlm@1: case BASE + 12: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ASR # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: ARITHMETIC_ASR_REG \ rlm@1: } else { \ rlm@1: if (reg[opcode & 0x0F].I & 0x80000000) { \ rlm@1: value = 0xFFFFFFFF; \ rlm@1: } else value = 0; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 6: \ rlm@1: case BASE + 14: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ROR # */ \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = (opcode >> 7) & 0x1F; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: ARITHMETIC_ROR_REG \ rlm@1: } else { \ rlm@1: ARITHMETIC_RRX_REG \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 1: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSL Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: if (shift == 32) { \ rlm@1: value = 0; \ rlm@1: } else if (shift < 32) { \ rlm@1: ARITHMETIC_LSL_REG \ rlm@1: } else value = 0; \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 3: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm LSR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: if (shift == 32) { \ rlm@1: value = 0; \ rlm@1: } else if (shift < 32) { \ rlm@1: ARITHMETIC_LSR_REG \ rlm@1: } else value = 0; \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 5: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ASR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift < 32) { \ rlm@1: if (shift) { \ rlm@1: ARITHMETIC_ASR_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: } else { \ rlm@1: if (reg[opcode & 0x0F].I & 0x80000000) { \ rlm@1: value = 0xFFFFFFFF; \ rlm@1: } else value = 0; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 7: \ rlm@1: { \ rlm@1: /* OP Rd,Rb,Rm ROR Rs */ \ rlm@1: clockTicks++; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int shift = reg[(opcode >> 8) & 15].B.B0; \ rlm@1: int dest = (opcode >> 12) & 15; \ rlm@1: u32 value; \ rlm@1: if (shift) { \ rlm@1: shift &= 0x1f; \ rlm@1: if (shift) { \ rlm@1: ARITHMETIC_ROR_REG \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: } else { \ rlm@1: value = reg[opcode & 0x0F].I; \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; \ rlm@1: case BASE + 0x200: \ rlm@1: case BASE + 0x201: \ rlm@1: case BASE + 0x202: \ rlm@1: case BASE + 0x203: \ rlm@1: case BASE + 0x204: \ rlm@1: case BASE + 0x205: \ rlm@1: case BASE + 0x206: \ rlm@1: case BASE + 0x207: \ rlm@1: case BASE + 0x208: \ rlm@1: case BASE + 0x209: \ rlm@1: case BASE + 0x20a: \ rlm@1: case BASE + 0x20b: \ rlm@1: case BASE + 0x20c: \ rlm@1: case BASE + 0x20d: \ rlm@1: case BASE + 0x20e: \ rlm@1: case BASE + 0x20f: \ rlm@1: { \ rlm@1: int shift = (opcode & 0xF00) >> 7; \ rlm@1: int base = (opcode >> 16) & 0x0F; \ rlm@1: int dest = (opcode >> 12) & 0x0F; \ rlm@1: u32 value; \ rlm@1: { \ rlm@1: ARITHMETIC_ROR_IMM \ rlm@1: } \ rlm@1: if (dest == 15) { \ rlm@1: OPCODE2 \ rlm@1: /* todo */ \ rlm@1: if (opcode & 0x00100000) { \ rlm@1: clockTicks++; \ rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); \ rlm@1: } \ rlm@1: if (armState) { \ rlm@1: reg[15].I &= 0xFFFFFFFC; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 4; \ rlm@1: } else { \ rlm@1: reg[15].I &= 0xFFFFFFFE; \ rlm@1: armNextPC = reg[15].I; \ rlm@1: reg[15].I += 2; \ rlm@1: } \ rlm@1: } else { \ rlm@1: OPCODE \ rlm@1: } \ rlm@1: } \ rlm@1: break; rlm@1: rlm@1: u32 opcode = CPUReadMemoryQuick(armNextPC); rlm@1: rlm@1: clockTicks = memoryWaitFetch32[(armNextPC >> 24) & 15]; rlm@1: rlm@1: #ifndef FINAL_VERSION rlm@1: if (armNextPC == stop) rlm@1: { rlm@1: armNextPC++; rlm@1: } rlm@1: #endif rlm@1: rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: int cond = opcode >> 28; rlm@1: // suggested optimization for frequent cases rlm@1: bool cond_res; rlm@1: if (cond == 0x0e) rlm@1: { rlm@1: cond_res = true; rlm@1: } rlm@1: else rlm@1: { rlm@1: switch (cond) rlm@1: { rlm@1: case 0x00: // EQ rlm@1: cond_res = Z_FLAG; rlm@1: break; rlm@1: case 0x01: // NE rlm@1: cond_res = !Z_FLAG; rlm@1: break; rlm@1: case 0x02: // CS rlm@1: cond_res = C_FLAG; rlm@1: break; rlm@1: case 0x03: // CC rlm@1: cond_res = !C_FLAG; rlm@1: break; rlm@1: case 0x04: // MI rlm@1: cond_res = N_FLAG; rlm@1: break; rlm@1: case 0x05: // PL rlm@1: cond_res = !N_FLAG; rlm@1: break; rlm@1: case 0x06: // VS rlm@1: cond_res = V_FLAG; rlm@1: break; rlm@1: case 0x07: // VC rlm@1: cond_res = !V_FLAG; rlm@1: break; rlm@1: case 0x08: // HI rlm@1: cond_res = C_FLAG && !Z_FLAG; rlm@1: break; rlm@1: case 0x09: // LS rlm@1: cond_res = !C_FLAG || Z_FLAG; rlm@1: break; rlm@1: case 0x0A: // GE rlm@1: cond_res = N_FLAG == V_FLAG; rlm@1: break; rlm@1: case 0x0B: // LT rlm@1: cond_res = N_FLAG != V_FLAG; rlm@1: break; rlm@1: case 0x0C: // GT rlm@1: cond_res = !Z_FLAG && (N_FLAG == V_FLAG); rlm@1: break; rlm@1: case 0x0D: // LE rlm@1: cond_res = Z_FLAG || (N_FLAG != V_FLAG); rlm@1: break; rlm@1: case 0x0E: rlm@1: cond_res = true; rlm@1: break; rlm@1: case 0x0F: rlm@1: default: rlm@1: // ??? rlm@1: cond_res = false; rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: if (cond_res) rlm@1: { rlm@1: switch (((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x0F)) rlm@1: { rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_AND, OP_AND, 0x000); rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_ANDS, OP_AND, 0x010); rlm@1: case 0x009: rlm@1: { rlm@1: // MUL Rd, Rm, Rs rlm@1: int dest = (opcode >> 16) & 0x0F; rlm@1: int mult = (opcode & 0x0F); rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: reg[dest].I = reg[mult].I * rs; rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 2; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 4; rlm@1: else rlm@1: clockTicks += 5; rlm@1: } rlm@1: break; rlm@1: case 0x019: rlm@1: { rlm@1: // MULS Rd, Rm, Rs rlm@1: int dest = (opcode >> 16) & 0x0F; rlm@1: int mult = (opcode & 0x0F); rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: reg[dest].I = reg[mult].I * rs; rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; rlm@1: Z_FLAG = (reg[dest].I) ? false : true; rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 2; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 4; rlm@1: else rlm@1: clockTicks += 5; rlm@1: } rlm@1: break; rlm@1: case 0x00b: rlm@1: case 0x02b: rlm@1: { rlm@1: // STRH Rd, [Rn], -Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x04b: rlm@1: case 0x06b: rlm@1: { rlm@1: // STRH Rd, [Rn], #-offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x08b: rlm@1: case 0x0ab: rlm@1: { rlm@1: // STRH Rd, [Rn], Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x0cb: rlm@1: case 0x0eb: rlm@1: { rlm@1: // STRH Rd, [Rn], #offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x10b: rlm@1: { rlm@1: // STRH Rd, [Rn, -Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: } rlm@1: break; rlm@1: case 0x12b: rlm@1: { rlm@1: // STRH Rd, [Rn, -Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x14b: rlm@1: { rlm@1: // STRH Rd, [Rn, -#offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: } rlm@1: break; rlm@1: case 0x16b: rlm@1: { rlm@1: // STRH Rd, [Rn, -#offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x18b: rlm@1: { rlm@1: // STRH Rd, [Rn, Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: } rlm@1: break; rlm@1: case 0x1ab: rlm@1: { rlm@1: // STRH Rd, [Rn, Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x1cb: rlm@1: { rlm@1: // STRH Rd, [Rn, #offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: } rlm@1: break; rlm@1: case 0x1eb: rlm@1: { rlm@1: // STRH Rd, [Rn, #offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 4 + CPUUpdateTicksAccess16(address); rlm@1: CPUWriteHalfWord(address, reg[dest].W.W0); rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x01b: rlm@1: case 0x03b: rlm@1: { rlm@1: // LDRH Rd, [Rn], -Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x05b: rlm@1: case 0x07b: rlm@1: { rlm@1: // LDRH Rd, [Rn], #-offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x09b: rlm@1: case 0x0bb: rlm@1: { rlm@1: // LDRH Rd, [Rn], Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x0db: rlm@1: case 0x0fb: rlm@1: { rlm@1: // LDRH Rd, [Rn], #offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x11b: rlm@1: { rlm@1: // LDRH Rd, [Rn, -Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: } rlm@1: break; rlm@1: case 0x13b: rlm@1: { rlm@1: // LDRH Rd, [Rn, -Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x15b: rlm@1: { rlm@1: // LDRH Rd, [Rn, -#offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: } rlm@1: break; rlm@1: case 0x17b: rlm@1: { rlm@1: // LDRH Rd, [Rn, -#offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x19b: rlm@1: { rlm@1: // LDRH Rd, [Rn, Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: } rlm@1: break; rlm@1: case 0x1bb: rlm@1: { rlm@1: // LDRH Rd, [Rn, Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x1db: rlm@1: { rlm@1: // LDRH Rd, [Rn, #offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: } rlm@1: break; rlm@1: case 0x1fb: rlm@1: { rlm@1: // LDRH Rd, [Rn, #offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = CPUReadHalfWord(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x01d: rlm@1: case 0x03d: rlm@1: { rlm@1: // LDRSB Rd, [Rn], -Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x05d: rlm@1: case 0x07d: rlm@1: { rlm@1: // LDRSB Rd, [Rn], #-offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x09d: rlm@1: case 0x0bd: rlm@1: { rlm@1: // LDRSB Rd, [Rn], Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x0dd: rlm@1: case 0x0fd: rlm@1: { rlm@1: // LDRSB Rd, [Rn], #offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x11d: rlm@1: { rlm@1: // LDRSB Rd, [Rn, -Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: } rlm@1: break; rlm@1: case 0x13d: rlm@1: { rlm@1: // LDRSB Rd, [Rn, -Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x15d: rlm@1: { rlm@1: // LDRSB Rd, [Rn, -#offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: } rlm@1: break; rlm@1: case 0x17d: rlm@1: { rlm@1: // LDRSB Rd, [Rn, -#offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x19d: rlm@1: { rlm@1: // LDRSB Rd, [Rn, Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: } rlm@1: break; rlm@1: case 0x1bd: rlm@1: { rlm@1: // LDRSB Rd, [Rn, Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x1dd: rlm@1: { rlm@1: // LDRSB Rd, [Rn, #offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: } rlm@1: break; rlm@1: case 0x1fd: rlm@1: { rlm@1: // LDRSB Rd, [Rn, #offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s8)CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x01f: rlm@1: case 0x03f: rlm@1: { rlm@1: // LDRSH Rd, [Rn], -Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x05f: rlm@1: case 0x07f: rlm@1: { rlm@1: // LDRSH Rd, [Rn], #-offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address -= offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x09f: rlm@1: case 0x0bf: rlm@1: { rlm@1: // LDRSH Rd, [Rn], Rm rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x0df: rlm@1: case 0x0ff: rlm@1: { rlm@1: // LDRSH Rd, [Rn], #offset rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I; rlm@1: int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: { rlm@1: address += offset; rlm@1: reg[base].I = address; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x11f: rlm@1: { rlm@1: // LDRSH Rd, [Rn, -Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: } rlm@1: break; rlm@1: case 0x13f: rlm@1: { rlm@1: // LDRSH Rd, [Rn, -Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x15f: rlm@1: { rlm@1: // LDRSH Rd, [Rn, -#offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: } rlm@1: break; rlm@1: case 0x17f: rlm@1: { rlm@1: // LDRSH Rd, [Rn, -#offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x19f: rlm@1: { rlm@1: // LDRSH Rd, [Rn, Rm] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: } rlm@1: break; rlm@1: case 0x1bf: rlm@1: { rlm@1: // LDRSH Rd, [Rn, Rm]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + reg[opcode & 0x0F].I; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: case 0x1df: rlm@1: { rlm@1: // LDRSH Rd, [Rn, #offset] rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: } rlm@1: break; rlm@1: case 0x1ff: rlm@1: { rlm@1: // LDRSH Rd, [Rn, #offset]! rlm@1: int base = (opcode >> 16) & 0x0F; rlm@1: int dest = (opcode >> 12) & 0x0F; rlm@1: u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0)); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: reg[dest].I = (s16)CPUReadHalfWordSigned(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: } rlm@1: break; rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR, OP_EOR, 0x020); rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EORS, OP_EOR, 0x030); rlm@1: case 0x029: rlm@1: { rlm@1: // MLA Rd, Rm, Rs, Rn rlm@1: int dest = (opcode >> 16) & 0x0F; rlm@1: int mult = (opcode & 0x0F); rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: reg[dest].I = reg[mult].I * rs + reg[(opcode >> 12) & 0x0f].I; rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 4; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 5; rlm@1: else rlm@1: clockTicks += 6; rlm@1: } rlm@1: break; rlm@1: case 0x039: rlm@1: { rlm@1: // MLAS Rd, Rm, Rs, Rn rlm@1: int dest = (opcode >> 16) & 0x0F; rlm@1: int mult = (opcode & 0x0F); rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: reg[dest].I = reg[mult].I * rs + reg[(opcode >> 12) & 0x0f].I; rlm@1: N_FLAG = (reg[dest].I & 0x80000000) ? true : false; rlm@1: Z_FLAG = (reg[dest].I) ? false : true; rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 4; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 5; rlm@1: else rlm@1: clockTicks += 6; rlm@1: } rlm@1: break; rlm@1: ARITHMETIC_DATA_OPCODE(OP_SUB, OP_SUB, 0x040); rlm@1: ARITHMETIC_DATA_OPCODE(OP_SUBS, OP_SUB, 0x050); rlm@1: ARITHMETIC_DATA_OPCODE(OP_RSB, OP_RSB, 0x060); rlm@1: ARITHMETIC_DATA_OPCODE(OP_RSBS, OP_RSB, 0x070); rlm@1: ARITHMETIC_DATA_OPCODE(OP_ADD, OP_ADD, 0x080); rlm@1: ARITHMETIC_DATA_OPCODE(OP_ADDS, OP_ADD, 0x090); rlm@1: case 0x089: rlm@1: { rlm@1: // UMULL RdLo, RdHi, Rn, Rs rlm@1: u32 umult = reg[(opcode & 0x0F)].I; rlm@1: u32 usource = reg[(opcode >> 8) & 0x0F].I; rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u64 uTemp = ((u64)umult) * ((u64)usource); rlm@1: reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(uTemp >> 32); rlm@1: if ((usource & 0xFFFFFF00) == 0) rlm@1: clockTicks += 2; rlm@1: else if ((usource & 0xFFFF0000) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((usource & 0xFF000000) == 0) rlm@1: clockTicks += 4; rlm@1: else rlm@1: clockTicks += 5; rlm@1: } rlm@1: break; rlm@1: case 0x099: rlm@1: { rlm@1: // UMULLS RdLo, RdHi, Rn, Rs rlm@1: u32 umult = reg[(opcode & 0x0F)].I; rlm@1: u32 usource = reg[(opcode >> 8) & 0x0F].I; rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u64 uTemp = ((u64)umult) * ((u64)usource); rlm@1: reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(uTemp >> 32); rlm@1: Z_FLAG = (uTemp) ? false : true; rlm@1: N_FLAG = (reg[destHi].I & 0x80000000) ? true : false; rlm@1: if ((usource & 0xFFFFFF00) == 0) rlm@1: clockTicks += 2; rlm@1: else if ((usource & 0xFFFF0000) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((usource & 0xFF000000) == 0) rlm@1: clockTicks += 4; rlm@1: else rlm@1: clockTicks += 5; rlm@1: } rlm@1: break; rlm@1: ARITHMETIC_DATA_OPCODE(OP_ADC, OP_ADC, 0x0a0); rlm@1: ARITHMETIC_DATA_OPCODE(OP_ADCS, OP_ADC, 0x0b0); rlm@1: case 0x0a9: rlm@1: { rlm@1: // UMLAL RdLo, RdHi, Rn, Rs rlm@1: u32 umult = reg[(opcode & 0x0F)].I; rlm@1: u32 usource = reg[(opcode >> 8) & 0x0F].I; rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u64 uTemp = (u64)reg[destHi].I; rlm@1: uTemp <<= 32; rlm@1: uTemp |= (u64)reg[destLo].I; rlm@1: uTemp += ((u64)umult) * ((u64)usource); rlm@1: reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(uTemp >> 32); rlm@1: if ((usource & 0xFFFFFF00) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((usource & 0xFFFF0000) == 0) rlm@1: clockTicks += 4; rlm@1: else if ((usource & 0xFF000000) == 0) rlm@1: clockTicks += 5; rlm@1: else rlm@1: clockTicks += 6; rlm@1: } rlm@1: break; rlm@1: case 0x0b9: rlm@1: { rlm@1: // UMLALS RdLo, RdHi, Rn, Rs rlm@1: u32 umult = reg[(opcode & 0x0F)].I; rlm@1: u32 usource = reg[(opcode >> 8) & 0x0F].I; rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u64 uTemp = (u64)reg[destHi].I; rlm@1: uTemp <<= 32; rlm@1: uTemp |= (u64)reg[destLo].I; rlm@1: uTemp += ((u64)umult) * ((u64)usource); rlm@1: reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(uTemp >> 32); rlm@1: Z_FLAG = (uTemp) ? false : true; rlm@1: N_FLAG = (reg[destHi].I & 0x80000000) ? true : false; rlm@1: if ((usource & 0xFFFFFF00) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((usource & 0xFFFF0000) == 0) rlm@1: clockTicks += 4; rlm@1: else if ((usource & 0xFF000000) == 0) rlm@1: clockTicks += 5; rlm@1: else rlm@1: clockTicks += 6; rlm@1: } rlm@1: break; rlm@1: ARITHMETIC_DATA_OPCODE(OP_SBC, OP_SBC, 0x0c0); rlm@1: ARITHMETIC_DATA_OPCODE(OP_SBCS, OP_SBC, 0x0d0); rlm@1: case 0x0c9: rlm@1: { rlm@1: // SMULL RdLo, RdHi, Rm, Rs rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: s64 m = (s32)reg[(opcode & 0x0F)].I; rlm@1: s64 s = (s32)rs; rlm@1: s64 sTemp = m * s; rlm@1: reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(sTemp >> 32); rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 2; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 4; rlm@1: else rlm@1: clockTicks += 5; rlm@1: } rlm@1: break; rlm@1: case 0x0d9: rlm@1: { rlm@1: // SMULLS RdLo, RdHi, Rm, Rs rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: s64 m = (s32)reg[(opcode & 0x0F)].I; rlm@1: s64 s = (s32)rs; rlm@1: s64 sTemp = m * s; rlm@1: reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(sTemp >> 32); rlm@1: Z_FLAG = (sTemp) ? false : true; rlm@1: N_FLAG = (sTemp < 0) ? true : false; rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 2; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 4; rlm@1: else rlm@1: clockTicks += 5; rlm@1: } rlm@1: break; rlm@1: ARITHMETIC_DATA_OPCODE(OP_RSC, OP_RSC, 0x0e0); rlm@1: ARITHMETIC_DATA_OPCODE(OP_RSCS, OP_RSC, 0x0f0); rlm@1: case 0x0e9: rlm@1: { rlm@1: // SMLAL RdLo, RdHi, Rm, Rs rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: s64 m = (s32)reg[(opcode & 0x0F)].I; rlm@1: s64 s = (s32)rs; rlm@1: s64 sTemp = (u64)reg[destHi].I; rlm@1: sTemp <<= 32; rlm@1: sTemp |= (u64)reg[destLo].I; rlm@1: sTemp += m * s; rlm@1: reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(sTemp >> 32); rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 4; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 5; rlm@1: else rlm@1: clockTicks += 6; rlm@1: } rlm@1: break; rlm@1: case 0x0f9: rlm@1: { rlm@1: // SMLALS RdLo, RdHi, Rm, Rs rlm@1: int destLo = (opcode >> 12) & 0x0F; rlm@1: int destHi = (opcode >> 16) & 0x0F; rlm@1: u32 rs = reg[(opcode >> 8) & 0x0F].I; rlm@1: s64 m = (s32)reg[(opcode & 0x0F)].I; rlm@1: s64 s = (s32)rs; rlm@1: s64 sTemp = (u64)reg[destHi].I; rlm@1: sTemp <<= 32; rlm@1: sTemp |= (u64)reg[destLo].I; rlm@1: sTemp += m * s; rlm@1: reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF); rlm@1: reg[destHi].I = (u32)(sTemp >> 32); rlm@1: Z_FLAG = (sTemp) ? false : true; rlm@1: N_FLAG = (sTemp < 0) ? true : false; rlm@1: if (((s32)rs) < 0) rlm@1: rs = ~rs; rlm@1: if ((rs & 0xFFFFFF00) == 0) rlm@1: clockTicks += 3; rlm@1: else if ((rs & 0xFFFF0000) == 0) rlm@1: clockTicks += 4; rlm@1: else if ((rs & 0xFF000000) == 0) rlm@1: clockTicks += 5; rlm@1: else rlm@1: clockTicks += 6; rlm@1: } rlm@1: break; rlm@1: LOGICAL_DATA_OPCODE(OP_TST, OP_TST, 0x110); rlm@1: case 0x100: rlm@1: // MRS Rd, CPSR rlm@1: // TODO: check if right instruction.... rlm@1: CPUUpdateCPSR(); rlm@1: reg[(opcode >> 12) & 0x0F].I = reg[16].I; rlm@1: break; rlm@1: case 0x109: rlm@1: { rlm@1: // SWP Rd, Rm, [Rn] rlm@1: u32 address = reg[(opcode >> 16) & 15].I; rlm@1: u32 temp = CPUReadMemory(address); rlm@1: CPUWriteMemory(address, reg[opcode & 15].I); rlm@1: reg[(opcode >> 12) & 15].I = temp; rlm@1: } rlm@1: break; rlm@1: LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130); rlm@1: case 0x120: rlm@1: { rlm@1: // MSR CPSR_fields, Rm rlm@1: CPUUpdateCPSR(); rlm@1: u32 value = reg[opcode & 15].I; rlm@1: u32 newValue = reg[16].I; rlm@1: if (armMode > 0x10) rlm@1: { rlm@1: if (opcode & 0x00010000) rlm@1: newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); rlm@1: if (opcode & 0x00020000) rlm@1: newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); rlm@1: if (opcode & 0x00040000) rlm@1: newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); rlm@1: } rlm@1: if (opcode & 0x00080000) rlm@1: newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); rlm@1: newValue |= 0x10; rlm@1: CPUSwitchMode(newValue & 0x1f, false); rlm@1: reg[16].I = newValue; rlm@1: CPUUpdateFlags(); rlm@1: } rlm@1: break; rlm@1: case 0x121: rlm@1: { rlm@1: // BX Rm rlm@1: // TODO: check if right instruction... rlm@1: clockTicks += 3; rlm@1: int base = opcode & 0x0F; rlm@1: armState = reg[base].I & 1 ? false : true; rlm@1: if (armState) rlm@1: { rlm@1: reg[15].I = reg[base].I & 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: reg[15].I = reg[base].I & 0xFFFFFFFE; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 2; rlm@1: } rlm@1: } rlm@1: break; rlm@1: ARITHMETIC_DATA_OPCODE(OP_CMP, OP_CMP, 0x150); rlm@1: case 0x140: rlm@1: // MRS Rd, SPSR rlm@1: // TODO: check if right instruction... rlm@1: reg[(opcode >> 12) & 0x0F].I = reg[17].I; rlm@1: break; rlm@1: case 0x149: rlm@1: { rlm@1: // SWPB Rd, Rm, [Rn] rlm@1: u32 address = reg[(opcode >> 16) & 15].I; rlm@1: u32 temp = CPUReadByte(address); rlm@1: CPUWriteByte(address, reg[opcode & 15].B.B0); rlm@1: reg[(opcode >> 12) & 15].I = temp; rlm@1: } rlm@1: break; rlm@1: ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170); rlm@1: case 0x160: rlm@1: { rlm@1: // MSR SPSR_fields, Rm rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (armMode > 0x10 && armMode < 0x1f) rlm@1: { rlm@1: if (opcode & 0x00010000) rlm@1: reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); rlm@1: if (opcode & 0x00020000) rlm@1: reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); rlm@1: if (opcode & 0x00040000) rlm@1: reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); rlm@1: if (opcode & 0x00080000) rlm@1: reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); rlm@1: } rlm@1: } rlm@1: break; rlm@1: LOGICAL_DATA_OPCODE(OP_ORR, OP_ORR, 0x180); rlm@1: LOGICAL_DATA_OPCODE(OP_ORRS, OP_ORR, 0x190); rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOV, OP_MOV, 0x1a0); rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOVS, OP_MOV, 0x1b0); rlm@1: LOGICAL_DATA_OPCODE(OP_BIC, OP_BIC, 0x1c0); rlm@1: LOGICAL_DATA_OPCODE(OP_BICS, OP_BIC, 0x1d0); rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVN, OP_MVN, 0x1e0); rlm@1: LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVNS, OP_MVN, 0x1f0); rlm@1: #ifdef BKPT_SUPPORT rlm@1: case 0x127: rlm@1: case 0x7ff: // for GDB support rlm@1: extern void (*dbgSignal)(int, int); rlm@1: reg[15].I -= 4; rlm@1: armNextPC -= 4; rlm@1: dbgSignal(5, (opcode & 0x0f) | ((opcode >> 4) & 0xfff0)); rlm@1: return; rlm@1: #endif rlm@1: case 0x320: rlm@1: case 0x321: rlm@1: case 0x322: rlm@1: case 0x323: rlm@1: case 0x324: rlm@1: case 0x325: rlm@1: case 0x326: rlm@1: case 0x327: rlm@1: case 0x328: rlm@1: case 0x329: rlm@1: case 0x32a: rlm@1: case 0x32b: rlm@1: case 0x32c: rlm@1: case 0x32d: rlm@1: case 0x32e: rlm@1: case 0x32f: rlm@1: { rlm@1: // MSR CPSR_fields, # rlm@1: CPUUpdateCPSR(); rlm@1: u32 value = opcode & 0xFF; rlm@1: int shift = (opcode & 0xF00) >> 7; rlm@1: if (shift) rlm@1: { rlm@1: ROR_IMM_MSR; rlm@1: } rlm@1: u32 newValue = reg[16].I; rlm@1: if (armMode > 0x10) rlm@1: { rlm@1: if (opcode & 0x00010000) rlm@1: newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); rlm@1: if (opcode & 0x00020000) rlm@1: newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); rlm@1: if (opcode & 0x00040000) rlm@1: newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); rlm@1: } rlm@1: if (opcode & 0x00080000) rlm@1: newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); rlm@1: rlm@1: newValue |= 0x10; rlm@1: rlm@1: CPUSwitchMode(newValue & 0x1f, false); rlm@1: reg[16].I = newValue; rlm@1: CPUUpdateFlags(); rlm@1: } rlm@1: break; rlm@1: case 0x360: rlm@1: case 0x361: rlm@1: case 0x362: rlm@1: case 0x363: rlm@1: case 0x364: rlm@1: case 0x365: rlm@1: case 0x366: rlm@1: case 0x367: rlm@1: case 0x368: rlm@1: case 0x369: rlm@1: case 0x36a: rlm@1: case 0x36b: rlm@1: case 0x36c: rlm@1: case 0x36d: rlm@1: case 0x36e: rlm@1: case 0x36f: rlm@1: { rlm@1: // MSR SPSR_fields, # rlm@1: if (armMode > 0x10 && armMode < 0x1f) rlm@1: { rlm@1: u32 value = opcode & 0xFF; rlm@1: int shift = (opcode & 0xF00) >> 7; rlm@1: if (shift) rlm@1: { rlm@1: ROR_IMM_MSR; rlm@1: } rlm@1: if (opcode & 0x00010000) rlm@1: reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); rlm@1: if (opcode & 0x00020000) rlm@1: reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); rlm@1: if (opcode & 0x00040000) rlm@1: reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); rlm@1: if (opcode & 0x00080000) rlm@1: reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x400) rlm@1: // T versions shouldn't be different on GBA rlm@1: CASE_16(0x420) rlm@1: { rlm@1: // STR Rd, [Rn], -# rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x480) rlm@1: // T versions shouldn't be different on GBA rlm@1: CASE_16(0x4a0) rlm@1: { rlm@1: // STR Rd, [Rn], # rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x500) rlm@1: { rlm@1: // STR Rd, [Rn, -#] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x520) rlm@1: { rlm@1: // STR Rd, [Rn, -#]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x580) rlm@1: { rlm@1: // STR Rd, [Rn, #] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x5a0) rlm@1: { rlm@1: // STR Rd, [Rn, #]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x410) rlm@1: { rlm@1: // LDR Rd, [Rn], -# rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I -= offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x430) rlm@1: { rlm@1: // LDRT Rd, [Rn], -# rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I -= offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x490) rlm@1: { rlm@1: // LDR Rd, [Rn], # rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I += offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x4b0) rlm@1: { rlm@1: // LDRT Rd, [Rn], # rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I += offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x510) rlm@1: { rlm@1: // LDR Rd, [Rn, -#] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x530) rlm@1: { rlm@1: // LDR Rd, [Rn, -#]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x590) rlm@1: { rlm@1: // LDR Rd, [Rn, #] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x5b0) rlm@1: { rlm@1: // LDR Rd, [Rn, #]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x440) rlm@1: // T versions shouldn't be different on GBA rlm@1: CASE_16(0x460) rlm@1: { rlm@1: // STRB Rd, [Rn], -# rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x4c0) rlm@1: // T versions shouldn't be different on GBA rlm@1: CASE_16(0x4e0) rlm@1: // STRB Rd, [Rn], # rlm@1: { rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x540) rlm@1: { rlm@1: // STRB Rd, [Rn, -#] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x560) rlm@1: { rlm@1: // STRB Rd, [Rn, -#]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x5c0) rlm@1: { rlm@1: // STRB Rd, [Rn, #] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x5e0) rlm@1: { rlm@1: // STRB Rd, [Rn, #]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x450) rlm@1: // T versions shouldn't be different rlm@1: CASE_16(0x470) rlm@1: { rlm@1: // LDRB Rd, [Rn], -# rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I -= offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x4d0) rlm@1: CASE_16(0x4f0) // T versions should not be different rlm@1: { rlm@1: // LDRB Rd, [Rn], # rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I += offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x550) rlm@1: { rlm@1: // LDRB Rd, [Rn, -#] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x570) rlm@1: { rlm@1: // LDRB Rd, [Rn, -#]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x5d0) rlm@1: { rlm@1: // LDRB Rd, [Rn, #] rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: CASE_16(0x5f0) rlm@1: { rlm@1: // LDRB Rd, [Rn, #]! rlm@1: int offset = opcode & 0xFFF; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x600: rlm@1: case 0x608: rlm@1: // T versions are the same rlm@1: case 0x620: rlm@1: case 0x628: rlm@1: { rlm@1: // STR Rd, [Rn], -Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x602: rlm@1: case 0x60a: rlm@1: // T versions are the same rlm@1: case 0x622: rlm@1: case 0x62a: rlm@1: { rlm@1: // STR Rd, [Rn], -Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x604: rlm@1: case 0x60c: rlm@1: // T versions are the same rlm@1: case 0x624: rlm@1: case 0x62c: rlm@1: { rlm@1: // STR Rd, [Rn], -Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x606: rlm@1: case 0x60e: rlm@1: // T versions are the same rlm@1: case 0x626: rlm@1: case 0x62e: rlm@1: { rlm@1: // STR Rd, [Rn], -Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address - value; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x680: rlm@1: case 0x688: rlm@1: // T versions are the same rlm@1: case 0x6a0: rlm@1: case 0x6a8: rlm@1: { rlm@1: // STR Rd, [Rn], Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x682: rlm@1: case 0x68a: rlm@1: // T versions are the same rlm@1: case 0x6a2: rlm@1: case 0x6aa: rlm@1: { rlm@1: // STR Rd, [Rn], Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x684: rlm@1: case 0x68c: rlm@1: // T versions are the same rlm@1: case 0x6a4: rlm@1: case 0x6ac: rlm@1: { rlm@1: // STR Rd, [Rn], Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x686: rlm@1: case 0x68e: rlm@1: // T versions are the same rlm@1: case 0x6a6: rlm@1: case 0x6ae: rlm@1: { rlm@1: // STR Rd, [Rn], Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: reg[base].I = address + value; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x700: rlm@1: case 0x708: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x702: rlm@1: case 0x70a: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x704: rlm@1: case 0x70c: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x706: rlm@1: case 0x70e: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x720: rlm@1: case 0x728: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x722: rlm@1: case 0x72a: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x724: rlm@1: case 0x72c: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x726: rlm@1: case 0x72e: rlm@1: { rlm@1: // STR Rd, [Rn, -Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x780: rlm@1: case 0x788: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x782: rlm@1: case 0x78a: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x784: rlm@1: case 0x78c: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x786: rlm@1: case 0x78e: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x7a0: rlm@1: case 0x7a8: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x7a2: rlm@1: case 0x7aa: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x7a4: rlm@1: case 0x7ac: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x7a6: rlm@1: case 0x7ae: rlm@1: { rlm@1: // STR Rd, [Rn, Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: reg[base].I = address; rlm@1: CPUWriteMemory(address, reg[dest].I); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: break; rlm@1: case 0x610: rlm@1: case 0x618: rlm@1: // T versions are the same rlm@1: case 0x630: rlm@1: case 0x638: rlm@1: { rlm@1: // LDR Rd, [Rn], -Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x612: rlm@1: case 0x61a: rlm@1: // T versions are the same rlm@1: case 0x632: rlm@1: case 0x63a: rlm@1: { rlm@1: // LDR Rd, [Rn], -Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x614: rlm@1: case 0x61c: rlm@1: // T versions are the same rlm@1: case 0x634: rlm@1: case 0x63c: rlm@1: { rlm@1: // LDR Rd, [Rn], -Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x616: rlm@1: case 0x61e: rlm@1: // T versions are the same rlm@1: case 0x636: rlm@1: case 0x63e: rlm@1: { rlm@1: // LDR Rd, [Rn], -Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - value; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x690: rlm@1: case 0x698: rlm@1: // T versions are the same rlm@1: case 0x6b0: rlm@1: case 0x6b8: rlm@1: { rlm@1: // LDR Rd, [Rn], Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x692: rlm@1: case 0x69a: rlm@1: // T versions are the same rlm@1: case 0x6b2: rlm@1: case 0x6ba: rlm@1: { rlm@1: // LDR Rd, [Rn], Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x694: rlm@1: case 0x69c: rlm@1: // T versions are the same rlm@1: case 0x6b4: rlm@1: case 0x6bc: rlm@1: { rlm@1: // LDR Rd, [Rn], Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x696: rlm@1: case 0x69e: rlm@1: // T versions are the same rlm@1: case 0x6b6: rlm@1: case 0x6be: rlm@1: { rlm@1: // LDR Rd, [Rn], Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + value; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x710: rlm@1: case 0x718: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x712: rlm@1: case 0x71a: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x714: rlm@1: case 0x71c: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x716: rlm@1: case 0x71e: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x730: rlm@1: case 0x738: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x732: rlm@1: case 0x73a: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x734: rlm@1: case 0x73c: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x736: rlm@1: case 0x73e: rlm@1: { rlm@1: // LDR Rd, [Rn, -Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x790: rlm@1: case 0x798: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x792: rlm@1: case 0x79a: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x794: rlm@1: case 0x79c: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x796: rlm@1: case 0x79e: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x7b0: rlm@1: case 0x7b8: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x7b2: rlm@1: case 0x7ba: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x7b4: rlm@1: case 0x7bc: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x7b6: rlm@1: case 0x7be: rlm@1: { rlm@1: // LDR Rd, [Rn, Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: reg[dest].I = CPUReadMemory(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess32(address); rlm@1: if (dest == 15) rlm@1: { rlm@1: clockTicks += 2; rlm@1: reg[15].I &= 0xFFFFFFFC; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 0x640: rlm@1: case 0x648: rlm@1: // T versions are the same rlm@1: case 0x660: rlm@1: case 0x668: rlm@1: { rlm@1: // STRB Rd, [Rn], -Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x642: rlm@1: case 0x64a: rlm@1: // T versions are the same rlm@1: case 0x662: rlm@1: case 0x66a: rlm@1: { rlm@1: // STRB Rd, [Rn], -Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x644: rlm@1: case 0x64c: rlm@1: // T versions are the same rlm@1: case 0x664: rlm@1: case 0x66c: rlm@1: { rlm@1: // STRB Rd, [Rn], -Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x646: rlm@1: case 0x64e: rlm@1: // T versions are the same rlm@1: case 0x666: rlm@1: case 0x66e: rlm@1: { rlm@1: // STRB Rd, [Rn], -Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address - value; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6c0: rlm@1: case 0x6c8: rlm@1: // T versions are the same rlm@1: case 0x6e0: rlm@1: case 0x6e8: rlm@1: { rlm@1: // STRB Rd, [Rn], Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6c2: rlm@1: case 0x6ca: rlm@1: // T versions are the same rlm@1: case 0x6e2: rlm@1: case 0x6ea: rlm@1: { rlm@1: // STRB Rd, [Rn], Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6c4: rlm@1: case 0x6cc: rlm@1: // T versions are the same rlm@1: case 0x6e4: rlm@1: case 0x6ec: rlm@1: { rlm@1: // STR Rd, [Rn], Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6c6: rlm@1: case 0x6ce: rlm@1: // T versions are the same rlm@1: case 0x6e6: rlm@1: case 0x6ee: rlm@1: { rlm@1: // STRB Rd, [Rn], Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: reg[base].I = address + value; rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x740: rlm@1: case 0x748: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x742: rlm@1: case 0x74a: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x744: rlm@1: case 0x74c: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x746: rlm@1: case 0x74e: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x760: rlm@1: case 0x768: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x762: rlm@1: case 0x76a: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x764: rlm@1: case 0x76c: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x766: rlm@1: case 0x76e: rlm@1: { rlm@1: // STRB Rd, [Rn, -Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7c0: rlm@1: case 0x7c8: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7c2: rlm@1: case 0x7ca: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7c4: rlm@1: case 0x7cc: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7c6: rlm@1: case 0x7ce: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7e0: rlm@1: case 0x7e8: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7e2: rlm@1: case 0x7ea: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7e4: rlm@1: case 0x7ec: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7e6: rlm@1: case 0x7ee: rlm@1: { rlm@1: // STRB Rd, [Rn, Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: reg[base].I = address; rlm@1: CPUWriteByte(address, reg[dest].B.B0); rlm@1: clockTicks += 2 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x650: rlm@1: case 0x658: rlm@1: // T versions are the same rlm@1: case 0x670: rlm@1: case 0x678: rlm@1: { rlm@1: // LDRB Rd, [Rn], -Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x652: rlm@1: case 0x65a: rlm@1: // T versions are the same rlm@1: case 0x672: rlm@1: case 0x67a: rlm@1: { rlm@1: // LDRB Rd, [Rn], -Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x654: rlm@1: case 0x65c: rlm@1: // T versions are the same rlm@1: case 0x674: rlm@1: case 0x67c: rlm@1: { rlm@1: // LDRB Rd, [Rn], -Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x656: rlm@1: case 0x65e: rlm@1: // T versions are the same rlm@1: case 0x676: rlm@1: case 0x67e: rlm@1: { rlm@1: // LDRB Rd, [Rn], -Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address - value; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6d0: rlm@1: case 0x6d8: rlm@1: // T versions are the same rlm@1: case 0x6f0: rlm@1: case 0x6f8: rlm@1: { rlm@1: // LDRB Rd, [Rn], Rm, LSL # rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6d2: rlm@1: case 0x6da: rlm@1: // T versions are the same rlm@1: case 0x6f2: rlm@1: case 0x6fa: rlm@1: { rlm@1: // LDRB Rd, [Rn], Rm, LSR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6d4: rlm@1: case 0x6dc: rlm@1: // T versions are the same rlm@1: case 0x6f4: rlm@1: case 0x6fc: rlm@1: { rlm@1: // LDRB Rd, [Rn], Rm, ASR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + offset; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x6d6: rlm@1: case 0x6de: rlm@1: // T versions are the same rlm@1: case 0x6f6: rlm@1: case 0x6fe: rlm@1: { rlm@1: // LDRB Rd, [Rn], Rm, ROR # rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address + value; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x750: rlm@1: case 0x758: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x752: rlm@1: case 0x75a: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x754: rlm@1: case 0x75c: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x756: rlm@1: case 0x75e: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x770: rlm@1: case 0x778: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x772: rlm@1: case 0x77a: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x774: rlm@1: case 0x77c: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x776: rlm@1: case 0x77e: rlm@1: { rlm@1: // LDRB Rd, [Rn, -Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I - value; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7d0: rlm@1: case 0x7d8: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, LSL #] rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7d2: rlm@1: case 0x7da: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, LSR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7d4: rlm@1: case 0x7dc: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, ASR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7d6: rlm@1: case 0x7de: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, ROR #] rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7f0: rlm@1: case 0x7f8: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, LSL #]! rlm@1: int offset = reg[opcode & 15].I << ((opcode >> 7) & 31); rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7f2: rlm@1: case 0x7fa: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, LSR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset = shift ? reg[opcode & 15].I >> shift : 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7f4: rlm@1: case 0x7fc: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, ASR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: int offset; rlm@1: if (shift) rlm@1: offset = (int)((s32)reg[opcode & 15].I >> shift); rlm@1: else if (reg[opcode & 15].I & 0x80000000) rlm@1: offset = 0xFFFFFFFF; rlm@1: else rlm@1: offset = 0; rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + offset; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: case 0x7f6: rlm@1: case 0x7fe: rlm@1: { rlm@1: // LDRB Rd, [Rn, Rm, ROR #]! rlm@1: int shift = (opcode >> 7) & 31; rlm@1: u32 value = reg[opcode & 15].I; rlm@1: if (shift) rlm@1: { rlm@1: ROR_VALUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: RCR_VALUE; rlm@1: } rlm@1: int dest = (opcode >> 12) & 15; rlm@1: int base = (opcode >> 16) & 15; rlm@1: u32 address = reg[base].I + value; rlm@1: reg[dest].I = CPUReadByte(address); rlm@1: if (dest != base) rlm@1: reg[base].I = address; rlm@1: clockTicks += 3 + CPUUpdateTicksAccess16(address); rlm@1: } rlm@1: break; rlm@1: #define STMW_REG(val, num) \ rlm@1: if (opcode & (val)) { \ rlm@1: CPUWriteMemory(address, reg[(num)].I); \ rlm@1: if (!offset) { \ rlm@1: reg[base].I = temp; \ rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); \ rlm@1: offset = 1; \ rlm@1: } else { \ rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \ rlm@1: } \ rlm@1: address += 4; \ rlm@1: } rlm@1: #define STM_REG(val, num) \ rlm@1: if (opcode & (val)) { \ rlm@1: CPUWriteMemory(address, reg[(num)].I); \ rlm@1: if (!offset) { \ rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); \ rlm@1: offset = 1; \ rlm@1: } else { \ rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \ rlm@1: } \ rlm@1: address += 4; \ rlm@1: } rlm@1: rlm@1: CASE_16(0x800) rlm@1: // STMDA Rn, {Rlist} rlm@1: { rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x820) rlm@1: { rlm@1: // STMDA Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x840) rlm@1: { rlm@1: // STMDA Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STM_REG(256, R8_FIQ); rlm@1: STM_REG(512, R9_FIQ); rlm@1: STM_REG(1024, R10_FIQ); rlm@1: STM_REG(2048, R11_FIQ); rlm@1: STM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STM_REG(8192, R13_USR); rlm@1: STM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x860) rlm@1: { rlm@1: // STMDA Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STMW_REG(256, R8_FIQ); rlm@1: STMW_REG(512, R9_FIQ); rlm@1: STMW_REG(1024, R10_FIQ); rlm@1: STMW_REG(2048, R11_FIQ); rlm@1: STMW_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STMW_REG(8192, R13_USR); rlm@1: STMW_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: rlm@1: CASE_16(0x880) rlm@1: { rlm@1: // STMIA Rn, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x8a0) rlm@1: { rlm@1: // STMIA Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + rlm@1: cpuBitsSet[(opcode >> 8) & 255]); rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: { rlm@1: reg[base].I = temp; rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x8c0) rlm@1: { rlm@1: // STMIA Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STM_REG(256, R8_FIQ); rlm@1: STM_REG(512, R9_FIQ); rlm@1: STM_REG(1024, R10_FIQ); rlm@1: STM_REG(2048, R11_FIQ); rlm@1: STM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: } rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STM_REG(8192, R13_USR); rlm@1: STM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: } rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x8e0) rlm@1: { rlm@1: // STMIA Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + rlm@1: cpuBitsSet[(opcode >> 8) & 255]); rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STMW_REG(256, R8_FIQ); rlm@1: STMW_REG(512, R9_FIQ); rlm@1: STMW_REG(1024, R10_FIQ); rlm@1: STMW_REG(2048, R11_FIQ); rlm@1: STMW_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: } rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STMW_REG(8192, R13_USR); rlm@1: STMW_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: } rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: { rlm@1: reg[base].I = temp; rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: rlm@1: CASE_16(0x900) rlm@1: { rlm@1: // STMDB Rn, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x920) rlm@1: { rlm@1: // STMDB Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x940) rlm@1: { rlm@1: // STMDB Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STM_REG(256, R8_FIQ); rlm@1: STM_REG(512, R9_FIQ); rlm@1: STM_REG(1024, R10_FIQ); rlm@1: STM_REG(2048, R11_FIQ); rlm@1: STM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STM_REG(8192, R13_USR); rlm@1: STM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x960) rlm@1: { rlm@1: // STMDB Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STMW_REG(256, R8_FIQ); rlm@1: STMW_REG(512, R9_FIQ); rlm@1: STMW_REG(1024, R10_FIQ); rlm@1: STMW_REG(2048, R11_FIQ); rlm@1: STMW_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STMW_REG(8192, R13_USR); rlm@1: STMW_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: rlm@1: CASE_16(0x980) rlm@1: // STMIB Rn, {Rlist} rlm@1: { rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x9a0) rlm@1: { rlm@1: // STMIB Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + rlm@1: cpuBitsSet[(opcode >> 8) & 255]); rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: { rlm@1: reg[base].I = temp; rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x9c0) rlm@1: { rlm@1: // STMIB Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: STM_REG(1, 0); rlm@1: STM_REG(2, 1); rlm@1: STM_REG(4, 2); rlm@1: STM_REG(8, 3); rlm@1: STM_REG(16, 4); rlm@1: STM_REG(32, 5); rlm@1: STM_REG(64, 6); rlm@1: STM_REG(128, 7); rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STM_REG(256, R8_FIQ); rlm@1: STM_REG(512, R9_FIQ); rlm@1: STM_REG(1024, R10_FIQ); rlm@1: STM_REG(2048, R11_FIQ); rlm@1: STM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(256, 8); rlm@1: STM_REG(512, 9); rlm@1: STM_REG(1024, 10); rlm@1: STM_REG(2048, 11); rlm@1: STM_REG(4096, 12); rlm@1: } rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STM_REG(8192, R13_USR); rlm@1: STM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STM_REG(8192, 13); rlm@1: STM_REG(16384, 14); rlm@1: } rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x9e0) rlm@1: { rlm@1: // STMIB Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + rlm@1: cpuBitsSet[(opcode >> 8) & 255]); rlm@1: STMW_REG(1, 0); rlm@1: STMW_REG(2, 1); rlm@1: STMW_REG(4, 2); rlm@1: STMW_REG(8, 3); rlm@1: STMW_REG(16, 4); rlm@1: STMW_REG(32, 5); rlm@1: STMW_REG(64, 6); rlm@1: STMW_REG(128, 7); rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: STMW_REG(256, R8_FIQ); rlm@1: STMW_REG(512, R9_FIQ); rlm@1: STMW_REG(1024, R10_FIQ); rlm@1: STMW_REG(2048, R11_FIQ); rlm@1: STMW_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(256, 8); rlm@1: STMW_REG(512, 9); rlm@1: STMW_REG(1024, 10); rlm@1: STMW_REG(2048, 11); rlm@1: STMW_REG(4096, 12); rlm@1: } rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: STMW_REG(8192, R13_USR); rlm@1: STMW_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: STMW_REG(8192, 13); rlm@1: STMW_REG(16384, 14); rlm@1: } rlm@1: if (opcode & 32768) rlm@1: { rlm@1: CPUWriteMemory(address, reg[15].I + 4); rlm@1: if (!offset) rlm@1: { rlm@1: reg[base].I = temp; rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); rlm@1: } rlm@1: else rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); rlm@1: } rlm@1: } rlm@1: break; rlm@1: rlm@1: #define LDM_REG(val, num) \ rlm@1: if (opcode & (val)) { \ rlm@1: reg[(num)].I = CPUReadMemory(address); \ rlm@1: if (offset) \ rlm@1: clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \ rlm@1: else { \ rlm@1: clockTicks += 1 + CPUUpdateTicksAccess32(address); \ rlm@1: offset = 1; \ rlm@1: } \ rlm@1: address += 4; \ rlm@1: } rlm@1: rlm@1: CASE_16(0x810) rlm@1: { rlm@1: // LDMDA Rn, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x830) rlm@1: { rlm@1: // LDMDA Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: break; rlm@1: CASE_16(0x850) rlm@1: { rlm@1: // LDMDA Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x870) rlm@1: { rlm@1: // LDMDA Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (temp + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: rlm@1: CASE_16(0x890) rlm@1: { rlm@1: // LDMIA Rn, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x8b0) rlm@1: { rlm@1: // LDMIA Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I + rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: break; rlm@1: CASE_16(0x8d0) rlm@1: { rlm@1: // LDMIA Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x8f0) rlm@1: { rlm@1: // LDMIA Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I + rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = reg[base].I & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: rlm@1: CASE_16(0x910) rlm@1: { rlm@1: // LDMDB Rn, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x930) rlm@1: { rlm@1: // LDMDB Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: break; rlm@1: CASE_16(0x950) rlm@1: { rlm@1: // LDMDB Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x970) rlm@1: { rlm@1: // LDMDB Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I - rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = temp & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: rlm@1: CASE_16(0x990) rlm@1: { rlm@1: // LDMIB Rn, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x9b0) rlm@1: { rlm@1: // LDMIB Rn!, {Rlist} rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I + rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: if (opcode & 32768) rlm@1: { rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: break; rlm@1: CASE_16(0x9d0) rlm@1: { rlm@1: // LDMIB Rn, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_16(0x9f0) rlm@1: { rlm@1: // LDMIB Rn!, {Rlist}^ rlm@1: int base = (opcode & 0x000F0000) >> 16; rlm@1: u32 temp = reg[base].I + rlm@1: 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); rlm@1: u32 address = (reg[base].I + 4) & 0xFFFFFFFC; rlm@1: clockTicks += 2; rlm@1: int offset = 0; rlm@1: if (opcode & 0x8000) rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: rlm@1: reg[15].I = CPUReadMemory(address); rlm@1: if (!offset) rlm@1: clockTicks += 2 + CPUUpdateTicksAccess32(address); rlm@1: else rlm@1: clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: rlm@1: CPUSwitchMode(reg[17].I & 0x1f, false); rlm@1: if (armState) rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFC; rlm@1: reg[15].I = armNextPC + 4; rlm@1: } rlm@1: else rlm@1: { rlm@1: armNextPC = reg[15].I & 0xFFFFFFFE; rlm@1: reg[15].I = armNextPC + 2; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(1, 0); rlm@1: LDM_REG(2, 1); rlm@1: LDM_REG(4, 2); rlm@1: LDM_REG(8, 3); rlm@1: LDM_REG(16, 4); rlm@1: LDM_REG(32, 5); rlm@1: LDM_REG(64, 6); rlm@1: LDM_REG(128, 7); rlm@1: rlm@1: if (armMode == 0x11) rlm@1: { rlm@1: LDM_REG(256, R8_FIQ); rlm@1: LDM_REG(512, R9_FIQ); rlm@1: LDM_REG(1024, R10_FIQ); rlm@1: LDM_REG(2048, R11_FIQ); rlm@1: LDM_REG(4096, R12_FIQ); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(256, 8); rlm@1: LDM_REG(512, 9); rlm@1: LDM_REG(1024, 10); rlm@1: LDM_REG(2048, 11); rlm@1: LDM_REG(4096, 12); rlm@1: } rlm@1: rlm@1: if (armMode != 0x10 && armMode != 0x1f) rlm@1: { rlm@1: LDM_REG(8192, R13_USR); rlm@1: LDM_REG(16384, R14_USR); rlm@1: } rlm@1: else rlm@1: { rlm@1: LDM_REG(8192, 13); rlm@1: LDM_REG(16384, 14); rlm@1: } rlm@1: rlm@1: if (!(opcode & (1 << base))) rlm@1: reg[base].I = temp; rlm@1: } rlm@1: } rlm@1: break; rlm@1: CASE_256(0xa00) rlm@1: { rlm@1: // B rlm@1: clockTicks += 3; rlm@1: int offset = opcode & 0x00FFFFFF; rlm@1: if (offset & 0x00800000) rlm@1: { rlm@1: offset |= 0xFF000000; rlm@1: } rlm@1: offset <<= 2; rlm@1: reg[15].I += offset; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: break; rlm@1: CASE_256(0xb00) rlm@1: { rlm@1: // BL rlm@1: clockTicks += 3; rlm@1: int offset = opcode & 0x00FFFFFF; rlm@1: if (offset & 0x00800000) rlm@1: { rlm@1: offset |= 0xFF000000; rlm@1: } rlm@1: offset <<= 2; rlm@1: reg[14].I = reg[15].I - 4; rlm@1: reg[15].I += offset; rlm@1: armNextPC = reg[15].I; rlm@1: reg[15].I += 4; rlm@1: } rlm@1: break; rlm@1: CASE_256(0xf00) rlm@1: // SWI rlm@1: clockTicks += 3; rlm@1: CPUSoftwareInterrupt(opcode & 0x00FFFFFF); rlm@1: break; rlm@1: #ifdef GP_SUPPORT rlm@1: case 0xe11: rlm@1: case 0xe13: rlm@1: case 0xe15: rlm@1: case 0xe17: rlm@1: case 0xe19: rlm@1: case 0xe1b: rlm@1: case 0xe1d: rlm@1: case 0xe1f: rlm@1: // MRC rlm@1: break; rlm@1: case 0xe01: rlm@1: case 0xe03: rlm@1: case 0xe05: rlm@1: case 0xe07: rlm@1: case 0xe09: rlm@1: case 0xe0b: rlm@1: case 0xe0d: rlm@1: case 0xe0f: rlm@1: // MRC rlm@1: break; rlm@1: #endif rlm@1: default: rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_UNDEFINED) rlm@1: log("Undefined ARM instruction %08x at %08x\n", opcode, rlm@1: armNextPC - 4); rlm@1: #endif rlm@1: CPUUndefinedException(); rlm@1: break; rlm@1: // END rlm@1: } rlm@1: }