ARMv7 opcode table fixed

This commit is contained in:
Nekotekina 2015-01-22 23:35:22 +03:00
parent e01528137e
commit cbd56fc4f5
2 changed files with 76 additions and 54 deletions

View file

@ -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;

View file

@ -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;
}