From cbd56fc4f57d1188e5e5a5bd2e8629d573ac7150 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 22 Jan 2015 23:35:22 +0300 Subject: [PATCH] ARMv7 opcode table fixed --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 72 ++++++++++++++++++---------- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 58 +++++++++++----------- 2 files changed, 76 insertions(+), 54 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 4cfdc42fed..df10fe52a0 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -14,12 +14,18 @@ struct ARMv7_opcode_t const char* name; ARMv7_encoding type; void(*func)(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + bool(*skip)(u32 code); }; // single 16-bit value -#define ARMv7_OP2(mask, code, type, name) { (u32)((mask) << 16), (u32)((code) << 16), 2, #name "_" #type, type, ARMv7_instrs::name } +#define ARMv7_OP2(mask, code, type, name, ...) { (u32)((mask) << 16), (u32)((code) << 16), 2, #name "_" #type, type, ARMv7_instrs::name, __VA_ARGS__ } // two 16-bit values -#define ARMv7_OP4(mask0, mask1, code0, code1, type, name) { (u32)((mask0) << 16) | (mask1), (u32)((code0) << 16) | (code1), 4, #name "_" #type, type, ARMv7_instrs::name } +#define ARMv7_OP4(mask0, mask1, code0, code1, type, name, ...) { (u32)((mask0) << 16) | (mask1), (u32)((code0) << 16) | (code1), 4, #name "_" #type, type, ARMv7_instrs::name, __VA_ARGS__ } + +#define SKIP_IF(cond) [](u32 c) -> bool { return cond; } + +#define BF(start, end) ((c << (31 - (end))) >> ((start) + 31 - (end))) +#define BT(pos) ((c >> (pos)) & 1) const ARMv7_opcode_t ARMv7_opcode_table[] = { @@ -35,6 +41,16 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR), + ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM), + ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || (BF(16, 19) == 13) )), + ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM), + ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM), + ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG), + ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG, SKIP_IF( (c & 0x87) == 0x85 || BF(3, 6) == 13 )), + ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG), + ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG), + ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR), ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI), ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI), ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI), @@ -44,16 +60,6 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR), ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR), ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR), - ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM), - ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM), - ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM), - ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM), - ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM), - ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG), - ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG), - ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG), - ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR), ARMv7_OP2(0xf800, 0xa000, T1, ADR), ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR), @@ -166,7 +172,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfff0, 0x0fc0, 0xf810, 0x0000, T2, LDRB_REG), ARMv7_OP4(0x0e50, 0x0010, 0x0650, 0x0000, A1, LDRB_REG), - ARMv7_OP4(0xfe50, 0x0000, 0xe850, 0x0000, T1, LDRD_IMM), + ARMv7_OP4(0xfe50, 0x0000, 0xe850, 0x0000, T1, LDRD_IMM, SKIP_IF( (!BT(21) && !BT(24)) || BF(16, 19) == 15 )), ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00d0, A1, LDRD_IMM), ARMv7_OP4(0xfe7f, 0x0000, 0xe85f, 0x0000, T1, LDRD_LIT), ARMv7_OP4(0x0f7f, 0x00f0, 0x014f, 0x00d0, A1, LDRD_LIT), @@ -488,7 +494,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfff0, 0x0fc0, 0xf800, 0x0000, T2, STRB_REG), ARMv7_OP4(0x0e50, 0x0010, 0x0640, 0x0000, A1, STRB_REG), - ARMv7_OP4(0xfe50, 0x0000, 0xe840, 0x0000, T1, STRD_IMM), + ARMv7_OP4(0xfe50, 0x0000, 0xe840, 0x0000, T1, STRD_IMM, SKIP_IF(!BT(21) && !BT(24))), ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00f0, A1, STRD_IMM), ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00f0, A1, STRD_REG), @@ -509,21 +515,21 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfff0, 0x0fc0, 0xf820, 0x0000, T2, STRH_REG), ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00b0, A1, STRH_REG), + ARMv7_OP2(0xfe00, 0x1e00, T1, SUB_IMM), + ARMv7_OP2(0xf800, 0x3800, T2, SUB_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf1a0, 0x0000, T3, SUB_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || (BF(16, 19) == 13) )), + ARMv7_OP4(0xfbf0, 0x8000, 0xf2a0, 0x0000, T4, SUB_IMM), + ARMv7_OP4(0x0fe0, 0x0000, 0x0240, 0x0000, A1, SUB_IMM), + ARMv7_OP2(0xfe00, 0x1a00, T1, SUB_REG), + ARMv7_OP4(0xffe0, 0x8000, 0xeba0, 0x0000, T2, SUB_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || (BF(16, 19) == 13) )), + ARMv7_OP4(0x0fe0, 0x0010, 0x0040, 0x0000, A1, SUB_REG), + ARMv7_OP4(0x0fe0, 0x0090, 0x0040, 0x0010, A1, SUB_RSR), ARMv7_OP2(0xff80, 0xb080, T1, SUB_SPI), ARMv7_OP4(0xfbef, 0x8000, 0xf1ad, 0x0000, T2, SUB_SPI), ARMv7_OP4(0xfbff, 0x8000, 0xf2ad, 0x0000, T3, SUB_SPI), ARMv7_OP4(0x0fef, 0x0000, 0x024d, 0x0000, A1, SUB_SPI), ARMv7_OP4(0xffef, 0x8000, 0xebad, 0x0000, T1, SUB_SPR), ARMv7_OP4(0x0fef, 0x0010, 0x004d, 0x0000, A1, SUB_SPR), - ARMv7_OP2(0xfe00, 0x1e00, T1, SUB_IMM), - ARMv7_OP2(0xf800, 0x3800, T2, SUB_IMM), - ARMv7_OP4(0xfbe0, 0x8000, 0xf1a0, 0x0000, T3, SUB_IMM), - ARMv7_OP4(0xfbf0, 0x8000, 0xf2a0, 0x0000, T4, SUB_IMM), - ARMv7_OP4(0x0fe0, 0x0000, 0x0240, 0x0000, A1, SUB_IMM), - ARMv7_OP2(0xfe00, 0x1a00, T1, SUB_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xeba0, 0x0000, T2, SUB_REG), - ARMv7_OP4(0x0fe0, 0x0010, 0x0040, 0x0000, A1, SUB_REG), - ARMv7_OP4(0x0fe0, 0x0090, 0x0040, 0x0010, A1, SUB_RSR), ARMv7_OP2(0xff00, 0xdf00, T1, SVC), ARMv7_OP4(0x0f00, 0x0000, 0x0f00, 0x0000, A1, SVC), @@ -1091,6 +1097,12 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0x0fff, 0xffff, 0x0320, 0xf001, A1, YIELD), }; +#undef ARMv7_OP2 +#undef ARMv7_OP4 +#undef SKIP_IF +#undef BF +#undef BT + struct ARMv7_op2_table_t { const ARMv7_opcode_t* data[0x10000]; @@ -1103,6 +1115,11 @@ struct ARMv7_op2_table_t { if (opcode.length == 2) { + if (opcode.code & ~opcode.mask) + { + LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%04x, code=0x%04x)", opcode.name, opcode.mask >> 16, opcode.code >> 16); + } + t2.push_back(&opcode); } } @@ -1113,7 +1130,7 @@ struct ARMv7_op2_table_t for (auto& opcode : t2) { - if (((i << 16) & opcode->mask) == opcode->code) + if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i))) { data[i] = opcode; break; @@ -1134,6 +1151,11 @@ struct ARMv7_op4t_table_t { if (opcode.length == 4 && opcode.type < A1) { + if (opcode.code & ~opcode.mask) + { + LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%04x 0x%04x, code=0x%04x 0x%04x)", opcode.name, opcode.mask >> 16, (u16)opcode.mask, opcode.code >> 16, (u16)opcode.code); + } + table.push_back(&opcode); } } @@ -1173,7 +1195,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) { for (auto opcode : g_op4t.table) { - if ((code.data & opcode->mask) == opcode->code) + if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) { g_opct[code.data] = (found = opcode); break; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 2488f1b1a9..3610925ecd 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -354,11 +354,11 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (d == 15 && set_flags) { - throw "CMN (immediate)"; + throw "ADD_IMM_T3: CMN (immediate)"; } if (n == 13) { - throw "ADD (SP plus immediate)"; + throw "ADD_IMM_T3: ADD (SP plus immediate)"; } break; } @@ -371,11 +371,11 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (n == 15) { - throw "ADR"; + throw "ADD_IMM_T4: ADR"; } if (n == 13) { - throw "ADD (SP plus immediate)"; + throw "ADD_IMM_T4: ADD (SP plus immediate)"; } break; } @@ -429,7 +429,7 @@ void ARMv7_instrs::ADD_REG(ARMv7Context& context, const ARMv7Code code, const AR if (n == 13 || m == 13) { - throw "ADD (SP plus register)"; + throw "ADD_REG_T2: ADD (SP plus register)"; } break; } @@ -443,11 +443,11 @@ void ARMv7_instrs::ADD_REG(ARMv7Context& context, const ARMv7Code code, const AR if (d == 15 && set_flags) { - throw "CMN (register)"; + throw "ADD_REG_T3: CMN (register)"; } if (n == 13) { - throw "ADD (SP plus register)"; + throw "ADD_REG_T3: ADD (SP plus register)"; } break; } @@ -512,7 +512,7 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (d == 15 && set_flags) { - throw "CMN (immediate)"; + throw "ADD_SPI_T3: CMN (immediate)"; } break; } @@ -674,7 +674,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en cond = (code.data >> 8) & 0xf; if (cond == 0xf) { - throw "SVC"; + throw "B_T1: SVC"; } jump = 4 + sign<9, u32>((code.data & 0xff) << 1); @@ -1165,7 +1165,7 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (n == 15) { - throw "LDR (literal)"; + throw "LDR_IMM_T3: LDR (literal)"; } break; } @@ -1180,15 +1180,15 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (n == 15) { - throw "LDR (literal)"; + throw "LDR_IMM_T4: LDR (literal)"; } if (index && add && !wback) { - throw "LDRT"; + throw "LDR_IMM_T4: LDRT"; } if (n == 13 && !index && add && wback && imm32 == 4) { - throw "POP"; + throw "LDR_IMM_T4: POP"; } if (!index && !wback) { @@ -1252,7 +1252,7 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR if (n == 15) { - throw "LDR (literal)"; + throw "LDR_REG_T2: LDR (literal)"; } break; } @@ -1334,7 +1334,7 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A } if (n == 15) { - throw "LDRD (literal)"; + throw "LDRD_IMM_T1: LDRD (literal)"; } break; } @@ -1538,7 +1538,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (!shift_n) { - throw "MOV (register)"; + throw "LSL_IMM_T1: MOV (register)"; } break; } @@ -1551,7 +1551,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (!shift_n) { - throw "MOV (register)"; + throw "LSL_IMM_T2: MOV (register)"; } break; } @@ -1949,7 +1949,7 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ reg_list = code.data & 0xffff; if (BitCount(reg_list) < 2) { - throw "LDM / LDMIA / LDMFD"; + throw "POP_A1: LDM / LDMIA / LDMFD"; } break; } @@ -2006,7 +2006,7 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 reg_list = code.data & 0xffff; if (BitCount(reg_list) < 2) { - throw "STMDB / STMFD"; + throw "PUSH_A1: STMDB / STMFD"; } break; } @@ -2666,11 +2666,11 @@ void ARMv7_instrs::STR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (index && add && !wback) { - throw "STRT"; + throw "STR_IMM_T4: STRT"; } if (n == 13 && index && !add && wback && imm32 == 4) { - throw "PUSH"; + throw "STR_IMM_T4: PUSH"; } if (n == 15 || (!index && !wback)) { @@ -2900,11 +2900,11 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (d == 15 && set_flags) { - throw "CMP (immediate)"; + throw "SUB_IMM_T3: CMP (immediate)"; } if (n == 13) { - throw "SUB (SP minus immediate)"; + throw "SUB_IMM_T3: SUB (SP minus immediate)"; } break; } @@ -2917,11 +2917,11 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (d == 15) { - throw "ADR"; + throw "SUB_IMM_T4: ADR"; } if (n == 13) { - throw "SUB (SP minus immediate)"; + throw "SUB_IMM_T4: SUB (SP minus immediate)"; } break; } @@ -2977,11 +2977,11 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR if (d == 15 && set_flags) { - throw "CMP (register)"; + throw "SUB_REG_T2: CMP (register)"; } if (n == 13) { - throw "SUB (SP minus register)"; + throw "SUB_REG_T2: SUB (SP minus register)"; } break; } @@ -3040,7 +3040,7 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (d == 15 && set_flags) { - throw "CMP (immediate)"; + throw "SUB_SPI_T2: CMP (immediate)"; } break; } @@ -4773,7 +4773,7 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (cp - 10 < 2) { - throw "Advanced SIMD and VFP"; + throw "MRC_(T1/A1): Advanced SIMD and VFP"; } break; }