diff --git a/asm/arm64.cpp b/asm/arm64.cpp index 10142d4e..f8f6fc0a 100644 --- a/asm/arm64.cpp +++ b/asm/arm64.cpp @@ -66,6 +66,7 @@ enum OPTION_LSL, OPTION_LSR, OPTION_ASR, + OPTION_ROR, }; enum @@ -601,7 +602,7 @@ static int op_3_reg_shift( if (operand_count == 4) { if (operands[3].attribute < OPTION_LSL || - operands[3].attribute > OPTION_ASR) + operands[3].attribute > OPTION_ROR) { return -2; } @@ -765,6 +766,36 @@ static int op_2_reg_imm6_imm4( return 4; } +static int op_move( + AsmContext *asm_context, + struct _operand *operands, + int operand_count, + uint32_t opcode, + char *instr) +{ + if (operands[0].type != OPERAND_REG_32 && operands[0].type != OPERAND_REG_64) + { + return -2; + } + + if (operands[1].type != OPERAND_REG_32 && operands[1].type != OPERAND_REG_64) + { + return -2; + } + + if (operands[0].type != operands[1].type) + { + return -2; + } + + int size = operands[0].type == OPERAND_REG_32 ? 0 : 1; + + opcode |= (size << 31) | operands[0].value | (operands[1].value << 16); + add_bin32(asm_context, opcode, IS_OPCODE); + + return 4; +} + static int op_reg_relative( AsmContext *asm_context, struct _operand *operands, @@ -858,22 +889,25 @@ static int op_logical_imm( int size = operands[0].type == OPERAND_REG_32 ? 0 : 1; int imm = operands[2].value; + int immr = imm & 0x3f; + int imms = (imm >> 6) & 0x3f; + int n = (imm >> 12) & 1; int max = size == 0 ? 0xfff : 0x1fff; + if (size == 0) { n = 0; } + if (check_range(asm_context, "immediate", imm, 0, max) != 0) { return -1; } opcode |= operands[0].value | + (n << 22) | + (immr << 16) | + (imms << 10) | (operands[1].value << 5) | (size << 31); - opcode |= (imm & 0x3f) << 16; - opcode |= ((imm >> 6) & 0x3f) << 10; - - if (size == 1) { opcode |= ((imm >> 12) & 0x1) << 22; } - add_bin32(asm_context, opcode, IS_OPCODE); return 4; @@ -1355,6 +1389,13 @@ int parse_instruction_arm64(AsmContext *asm_context, char *instr) if (ret == -2) { continue; } return ret; } + case OP_MOVE: + { + ret = op_move(asm_context, operands, operand_count, table_arm64[n].opcode, instr); + + if (ret == -2) { continue; } + return ret; + } case OP_REG_RELATIVE: { ret = op_reg_relative(asm_context, operands, operand_count, table_arm64[n].opcode, instr); diff --git a/disasm/arm64.cpp b/disasm/arm64.cpp index 36290c21..5efbb9c5 100644 --- a/disasm/arm64.cpp +++ b/disasm/arm64.cpp @@ -194,6 +194,13 @@ int disasm_arm64( return 4; } + case OP_MOVE: + { + snprintf(instruction, length, "%s x%d, x%d", + table_arm64[n].instr, + rd, + rm); + } case OP_REG_RELATIVE: { imm = (opcode >> 5) & ((1 << 19) - 1); diff --git a/table/arm64.cpp b/table/arm64.cpp index 2cb9434f..76d4a671 100644 --- a/table/arm64.cpp +++ b/table/arm64.cpp @@ -206,7 +206,9 @@ struct _table_arm64 table_arm64[] = { "sbc", 0x5a000000, 0x7fe0fc00, 3, 'b', OP_MATH_R_R_R }, { "sbcs", 0x7a000000, 0x7fe0fc00, 3, 'b', OP_MATH_R_R_R }, - // C3.5.10 Logical (shifted register). + // C3.5.10 Logical (shifted register) (and aliases). + { "mov", 0x2a0003e0, 0x7f20ffe0, 2, 'b', OP_MOVE }, + { "and", 0x0a000000, 0x7f200000, 3, 'b', OP_MATH_R_R_R_SHIFT }, { "bic", 0x0a200000, 0x7f200000, 3, 'b', OP_MATH_R_R_R_SHIFT }, { "orr", 0x2a000000, 0x7f200000, 3, 'b', OP_MATH_R_R_R_SHIFT }, diff --git a/table/arm64.h b/table/arm64.h index 8a7a8e70..60602157 100644 --- a/table/arm64.h +++ b/table/arm64.h @@ -21,6 +21,7 @@ enum OP_MATH_R_R_R_SHIFT, OP_MATH_R_R_IMM_SHIFT, OP_MATH_R_R_IMM6_IMM4, + OP_MOVE, OP_REG_RELATIVE, OP_REG_PAGE_RELATIVE, OP_VECTOR_D_V,