From afdcafe89118cee761f9bf67ea1b1efc29311300 Mon Sep 17 00:00:00 2001 From: Cooper Qu Date: Thu, 17 Sep 2020 14:30:28 +0800 Subject: CSKY: Add objdump option -M abi-names. Add option parser for disassembler, and refine the codes of parse register operand and disassemble register operand. While strengthen the operands legality check of some instructions. Co-Authored-By: Lifang Xia gas/ * config/tc-csky.c (parse_type_ctrlreg): Use function csky_get_control_regno to operand. (csky_get_reg_val): Likewise. (is_reg_sp_with_bracket): Use function csky_get_reg_val to parse operand. (is_reg_sp): Refine. (is_oimm_within_range): Fix, report error when operand is not constant. (parse_type_cpreg): Refine. (parse_type_cpcreg): Refine. (get_operand_value): Add handle of OPRND_TYPE_IMM5b_LS. (md_assemble): Fix no error reporting somtimes when operands number are not fit. (csky_addc64): Refine. (csky_subc64): Refine. (csky_or64): Refine. (v1_work_fpu_fo): Refine. (v1_work_fpu_read): Refine. (v1_work_fpu_writed): Refine. (v1_work_fpu_readd): Refine. (v2_work_addc): New function, strengthen the operands legality check of addc. * gas/testsuite/gas/csky/all.d : Use register number format when disassemble register name by default. * gas/testsuite/gas/csky/cskyv2_all.d : Likewise. * gas/testsuite/gas/csky/trust.d: Likewise. * gas/testsuite/gas/csky/cskyv2_ck860.d : Fix. * gas/testsuite/gas/csky/trust.s : Fix. opcodes/ * csky-dis.c (using_abi): New. (parse_csky_dis_options): New function. (get_gr_name): New function. (get_cr_name): New function. (csky_output_operand): Use get_gr_name and get_cr_name to disassemble and add handle of OPRND_TYPE_IMM5b_LS. (print_insn_csky): Parse disassembler options. * opcodes/csky-opc.h (OPRND_TYPE_IMM5b_LS): New enum. (GENARAL_REG_BANK): Define. (REG_SUPPORT_ALL): Define. (REG_SUPPORT_ALL): New. (ASH): Define. (REG_SUPPORT_A): Define. (REG_SUPPORT_B): Define. (REG_SUPPORT_C): Define. (REG_SUPPORT_D): Define. (REG_SUPPORT_E): Define. (csky_abiv1_general_regs): New. (csky_abiv1_control_regs): New. (csky_abiv2_general_regs): New. (csky_abiv2_control_regs): New. (get_register_name): New function. (get_register_number): New function. (csky_get_general_reg_name): New function. (csky_get_general_regno): New function. (csky_get_control_reg_name): New function. (csky_get_control_regno): New function. (csky_v2_opcodes): Prefer two oprerans format for bclri and bseti, strengthen the operands legality check of addc, zext and sext. --- opcodes/csky-dis.c | 148 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 64 deletions(-) (limited to 'opcodes/csky-dis.c') diff --git a/opcodes/csky-dis.c b/opcodes/csky-dis.c index a28160b984e..67fb4ee87ed 100644 --- a/opcodes/csky-dis.c +++ b/opcodes/csky-dis.c @@ -60,6 +60,7 @@ struct csky_dis_info enum sym_type last_type; int last_map_sym = 1; bfd_vma last_map_addr = 0; +int using_abi = 0; /* Only for objdump tool. */ #define INIT_MACH_FLAG 0xffffffff @@ -262,6 +263,40 @@ csky_get_disassembler (bfd *abfd) return print_insn_csky; } +/* Parse the string of disassembler options. */ +static void +parse_csky_dis_options (const char *opts_in) +{ + char *opts = xstrdup (opts_in); + char *opt = opts; + char *opt_end = opts; + + for (; opt_end != NULL; opt = opt_end + 1) + { + if ((opt_end = strchr (opt, ',')) != NULL) + *opt_end = 0; + if (strcmp (opt, "abi-names") == 0) + using_abi = 1; + else + fprintf (stderr, + "unrecognized disassembler option: %s", opt); + } +} + +/* Get general register name. */ +static const char * +get_gr_name (int regno) +{ + return csky_get_general_reg_name (mach_flag & CSKY_ABI_MASK, regno, using_abi); +} + +/* Get control register name. */ +static const char * +get_cr_name (unsigned int regno, int bank) +{ + return csky_get_control_reg_name (mach_flag & CSKY_ABI_MASK, bank, regno, using_abi); +} + static int csky_output_operand (char *str, struct operand const *oprnd, CSKY_INST_TYPE inst, int reloc ATTRIBUTE_UNUSED) @@ -289,30 +324,10 @@ csky_output_operand (char *str, struct operand const *oprnd, switch (oprnd->type) { case OPRND_TYPE_CTRLREG: - if (IS_CSKY_V1 (mach_flag)) - { - /* In V1 only cr0-cr12 have alias names. */ - if (value <= 12) - strcat (str, csky_ctrl_regs[value].name); - /* Others using crn(n > 12). */ - else if (value <= 30) - { - sprintf (buf, "cr%d", (int)value); - strcat (str, buf); - } - else - return -1; - } - else - { - int sel; - int crx; - sel = value >> 5; - crx = value & 0x1f; - sprintf (buf, "cr<%d, %d>", crx, sel); - strcat (str, buf); - } - break; + if (IS_CSKY_V1(mach_flag) && ((value & 0x1f) == 0x1f)) + return -1; + strcat (str, get_cr_name((value & 0x1f), (value >> 5))); + break; case OPRND_TYPE_DUMMY_REG: mask = dis_info.opinfo->oprnd.oprnds[0].mask; value = inst & mask; @@ -323,21 +338,18 @@ csky_output_operand (char *str, struct operand const *oprnd, bit++; } value = result; - strcat (str, csky_general_reg[value]); + strcat (str, get_gr_name (value)); break; case OPRND_TYPE_GREG0_7: case OPRND_TYPE_GREG0_15: case OPRND_TYPE_GREG16_31: case OPRND_TYPE_REGnsplr: case OPRND_TYPE_AREG: - if (IS_CSKY_V2 (mach_flag) && value == 14) - strcat (str, "sp"); - else - strcat (str, csky_general_reg[value]); - dis_info.value = value; + strcat (str, get_gr_name (value)); break; case OPRND_TYPE_CPREG: - strcat (str, csky_cp_reg[value]); + sprintf (buf, "cpr%d", (int)value); + strcat (str, buf); break; case OPRND_TYPE_FREG: sprintf (buf, "fr%d", (int)value); @@ -349,10 +361,12 @@ csky_output_operand (char *str, struct operand const *oprnd, strcat (str, buf); break; case OPRND_TYPE_CPCREG: - strcat (str, csky_cp_creg[value]); + sprintf (buf, "cpcr%d", (int)value); + strcat (str, buf); break; case OPRND_TYPE_CPIDX: - strcat (str, csky_cp_idx[value]); + sprintf (buf, "cp%d", (int)value); + strcat (str, buf); break; case OPRND_TYPE_IMM2b_JMPIX: value = (value + 2) << 3; @@ -419,6 +433,7 @@ csky_output_operand (char *str, struct operand const *oprnd, case OPRND_TYPE_IMM2b: case OPRND_TYPE_IMM4b: case OPRND_TYPE_IMM5b: + case OPRND_TYPE_IMM5b_LS: case OPRND_TYPE_IMM7b: case OPRND_TYPE_IMM8b: case OPRND_TYPE_IMM12b: @@ -734,14 +749,19 @@ csky_output_operand (char *str, struct operand const *oprnd, case OPRND_TYPE_REGLIST_DASH: if (IS_CSKY_V1 (mach_flag)) { - strcat (str, csky_general_reg[value]); - strcat (str, "-r15"); + sprintf (buf, "%s-r15", get_gr_name (value)); + strcat (str, buf); } else { - strcat (str, csky_general_reg[value >> 5]); + if ((value & 0x1f) + (value >> 5) > 31) + { + ret = -1; + break; + } + strcat (str, get_gr_name ((value >> 5))); strcat (str, "-"); - strcat (str, csky_general_reg[(value & 0x1f) + (value >> 5)]); + strcat (str, get_gr_name ((value & 0x1f) + (value >> 5))); } break; case OPRND_TYPE_PSR_BITS_LIST: @@ -776,33 +796,25 @@ csky_output_operand (char *str, struct operand const *oprnd, } case OPRND_TYPE_REGbsp: if (IS_CSKY_V1 (mach_flag)) - strcat (str, "(sp)"); + sprintf(buf, "(%s)", get_gr_name (0)); else - strcat (str, "(sp)"); + sprintf(buf, "(%s)", get_gr_name (14)); + strcat (str, buf); break; case OPRND_TYPE_REGsp: if (IS_CSKY_V1 (mach_flag)) - strcat (str, "sp"); + strcat (str, get_gr_name (0)); else - strcat (str, "sp"); + strcat (str, get_gr_name (14)); break; case OPRND_TYPE_REGnr4_r7: case OPRND_TYPE_AREG_WITH_BRACKET: - if (IS_CSKY_V1 (mach_flag) && (value < 4 || value > 7)) - { - strcat (str, "("); - strcat (str, csky_general_reg[value]); - strcat (str, ")"); - } - else - { - strcat (str, "("); - strcat (str, csky_general_reg[value]); - strcat (str, ")"); - } + strcat (str, "("); + strcat (str, get_gr_name (value)); + strcat (str, ")"); break; case OPRND_TYPE_AREG_WITH_LSHIFT: - strcat (str, csky_general_reg[value >> 5]); + strcat (str, get_gr_name (value >> 5)); strcat (str, " << "); if ((value & 0x1f) == 0x1) strcat (str, "0"); @@ -814,7 +826,7 @@ csky_output_operand (char *str, struct operand const *oprnd, strcat (str, "3"); break; case OPRND_TYPE_AREG_WITH_LSHIFT_FPU: - strcat (str, csky_general_reg[value >> 2]); + strcat (str, get_gr_name (value >> 2)); strcat (str, " << "); if ((value & 0x3) == 0x0) strcat (str, "0"); @@ -835,27 +847,28 @@ csky_output_operand (char *str, struct operand const *oprnd, } case OPRND_TYPE_REGr4_r7: if (IS_CSKY_V1 (mach_flag)) - strcat (str, "r4-r7"); + sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7)); + strcat (str, buf); break; case OPRND_TYPE_CONST1: strcat (str, "1"); break; case OPRND_TYPE_REG_r1a: case OPRND_TYPE_REG_r1b: - strcat (str, "r1"); + strcat (str, get_gr_name (1)); break; case OPRND_TYPE_REG_r28: - strcat (str, "r28"); + strcat (str, get_gr_name (28)); break; case OPRND_TYPE_REGLIST_DASH_COMMA: /* 16-bit reglist. */ if (value & 0xf) { - strcat (str, "r4"); + strcat (str, get_gr_name (4)); if ((value & 0xf) > 1) { strcat (str, "-"); - strcat (str, csky_general_reg[(value & 0xf) + 3]); + strcat (str, get_gr_name ((value & 0xf) + 3)); } if (value & ~0xf) strcat (str, ", "); @@ -863,7 +876,7 @@ csky_output_operand (char *str, struct operand const *oprnd, if (value & 0x10) { /* r15. */ - strcat (str, "r15"); + strcat (str, get_gr_name (15)); if (value & ~0x1f) strcat (str, ", "); } @@ -873,18 +886,18 @@ csky_output_operand (char *str, struct operand const *oprnd, value >>= 5; if (value & 0x3) { - strcat (str, "r16"); + strcat (str, get_gr_name (16)); if ((value & 0x7) > 1) { strcat (str, "-"); - strcat (str, csky_general_reg[(value & 0xf) + 15]); + strcat (str, get_gr_name ((value & 0x7) + 15)); } if (value & ~0x7) strcat (str, ", "); } if (value & 0x8) /* r15. */ - strcat (str, "r28"); + strcat (str, get_gr_name (28)); } break; case OPRND_TYPE_UNCOND10b: @@ -1027,6 +1040,13 @@ print_insn_csky (bfd_vma memaddr, struct disassemble_info *info) dis_info.mem = memaddr; dis_info.info = info; dis_info.need_output_symbol = 0; + + if (info->disassembler_options) + { + parse_csky_dis_options (info->disassembler_options); + info->disassembler_options = NULL; + } + if (mach_flag != INIT_MACH_FLAG && mach_flag != BINARY_MACH_FLAG) info->mach = mach_flag; else if (mach_flag == INIT_MACH_FLAG) -- cgit v1.2.1