git: 7396802b1ea2 - stable/13 - arm64/disassem.c: Add shifted register instruction definitions
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 09 Jun 2023 19:58:22 UTC
The branch stable/13 has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=7396802b1ea2db1b695a4793678760b955b9c72f commit 7396802b1ea2db1b695a4793678760b955b9c72f Author: Mykola Hohsadze <koliagogsadze@gmail.com> AuthorDate: 2023-05-25 14:41:55 +0000 Commit: Mitchell Horne <mhorne@FreeBSD.org> CommitDate: 2023-06-09 19:48:06 +0000 arm64/disassem.c: Add shifted register instruction definitions Add disassembly support for the following shifted register instructions: * adds * subs * sub * neg * negs * cmp * cmn The 'Mandatory Tokens' checks are relaxed to allow for the alias instructions (e.g. cmp) which hard-code one or more registers as xzr. Reviewed by: mhorne MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D40006 (cherry picked from commit ffa75b573f043951c7958c200c1e0e1b1f703740) --- sys/arm64/arm64/disassem.c | 58 +++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/sys/arm64/arm64/disassem.c b/sys/arm64/arm64/disassem.c index 2ec0d04d5491..f1a4f9206c1b 100644 --- a/sys/arm64/arm64/disassem.c +++ b/sys/arm64/arm64/disassem.c @@ -91,6 +91,8 @@ enum arm64_format_type { /* * OP <RD>, <RN>, <RM>{, <shift [LSL, LSR, ASR]> #imm} SF32/64 * OP <RD>, <RN>, #<imm>{, <shift [0, 12]>} SF32/64 + * OP <RD>, <RM> {, <shift> #<imm> } + * OP <RN>, <RM> {, <shift> #<imm> } */ TYPE_01, @@ -151,6 +153,10 @@ static struct arm64_insn arm64_i[] = { TYPE_01, OP_RD_SP | OP_RN_SP }, /* mov (to/from sp) */ { "add", "SF(1)|0010001|SHIFT(2)|IMM(12)|RN(5)|RD(5)", TYPE_01, OP_RD_SP | OP_RN_SP }, /* add immediate */ + { "cmn", "SF(1)|0101011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|11111", + TYPE_01, 0 }, /* cmn shifted register */ + { "adds", "SF(1)|0101011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|RD(5)", + TYPE_01, 0 }, /* adds shifted register */ { "ldr", "1|SF(1)|111000010|IMM(9)|OPTION(2)|RN(5)|RT(5)", TYPE_02, OP_SIGN_EXT | OP_RN_SP }, /* ldr immediate post/pre index */ { "ldr", "1|SF(1)|11100101|IMM(12)|RN(5)|RT(5)", @@ -216,6 +222,16 @@ static struct arm64_insn arm64_i[] = { { "strh", "01111000001|RM(5)|OPTION(3)|SCALE(1)|10|RN(5)|RT(5)", TYPE_02, OP_SF32 | OP_RN_SP }, /* strh register */ + { "neg", "SF(1)|1001011|SHIFT(2)|0|RM(5)|IMM(6)|11111|RD(5)", + TYPE_01, 0 }, /* neg shifted register */ + { "sub", "SF(1)|1001011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|RD(5)", + TYPE_01, 0 }, /* sub shifted register */ + { "cmp", "SF(1)|1101011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|11111", + TYPE_01, 0 }, /* cmp shifted register */ + { "negs", "SF(1)|1101011|SHIFT(2)|0|RM(5)|IMM(6)|11111|RD(5)", + TYPE_01, 0 }, /* negs shifted register */ + { "subs", "SF(1)|1101011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|RD(5)", + TYPE_01, 0 }, /* subs shifted register */ { NULL, NULL } }; @@ -397,7 +413,7 @@ disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt) int ret; int shift, rm, rt, rd, rn, imm, sf, idx, option, scale, amount; int sign_ext; - int rm_absent; + bool rm_absent, rd_absent, rn_absent; /* Indicate if immediate should be outside or inside brackets */ int inside; /* Print exclamation mark if pre-incremented */ @@ -454,27 +470,37 @@ disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt) /* * OP <RD>, <RN>, <RM>{, <shift [LSL, LSR, ASR]> #<imm>} SF32/64 * OP <RD>, <RN>, #<imm>{, <shift [0, 12]>} SF32/64 + * OP <RD>, <RM> {, <shift> #<imm> } + * OP <RN>, <RM> {, <shift> #<imm> } */ - /* Mandatory tokens */ - ret = arm64_disasm_read_token(i_ptr, insn, "RD", &rd); - ret |= arm64_disasm_read_token(i_ptr, insn, "RN", &rn); - if (ret != 0) { - printf("ERROR: " - "Missing mandatory token for op %s type %d\n", - i_ptr->name, i_ptr->type); - goto undefined; - } - - /* Optional tokens */ - arm64_disasm_read_token(i_ptr, insn, "SHIFT", &shift); + rd_absent = arm64_disasm_read_token(i_ptr, insn, "RD", &rd); + rn_absent = arm64_disasm_read_token(i_ptr, insn, "RN", &rn); rm_absent = arm64_disasm_read_token(i_ptr, insn, "RM", &rm); + arm64_disasm_read_token(i_ptr, insn, "SHIFT", &shift); - di->di_printf("%s\t%s, %s", i_ptr->name, - arm64_reg(sf, rd, rd_sp), arm64_reg(sf, rn, rn_sp)); + di->di_printf("%s\t", i_ptr->name); + + /* + * If RD and RN are present, we will display the following + * patterns: + * - OP <RD>, <RN>, <RM>{, <shift [LSL, LSR, ASR]> #<imm>} SF32/64 + * - OP <RD>, <RN>, #<imm>{, <shift [0, 12]>} SF32/64 + * Otherwise if only RD is present: + * - OP <RD>, <RM> {, <shift> #<imm> } + * Otherwise if only RN is present: + * - OP <RN>, <RM> {, <shift> #<imm> } + */ + if (!rd_absent && !rn_absent) + di->di_printf("%s, %s", arm64_reg(sf, rd, rd_sp), + arm64_reg(sf, rn, rn_sp)); + else if (!rd_absent) + di->di_printf("%s", arm64_reg(sf, rd, rd_sp)); + else + di->di_printf("%s", arm64_reg(sf, rn, rn_sp)); /* If RM is present use it, otherwise use immediate notation */ - if (rm_absent == 0) { + if (!rm_absent) { di->di_printf(", %s", arm64_reg(sf, rm, rm_sp)); if (imm != 0) di->di_printf(", %s #%d", shift_2[shift], imm);