diff options
author | Cooper Qu <cooper.qu@linux.alibaba.com> | 2020-09-17 14:30:28 +0800 |
---|---|---|
committer | Lifang Xia <xlf194833_xia@alibaba-inc.com> | 2020-09-23 23:55:36 +0800 |
commit | afdcafe89118cee761f9bf67ea1b1efc29311300 (patch) | |
tree | 6bfaa44e694d29891509d89d7bdcb1601418c27f /opcodes | |
parent | 20a5fcbd5b28cca88511ac5a9ad5e54251e8fa6d (diff) | |
download | binutils-afdcafe89118cee761f9bf67ea1b1efc29311300.zip binutils-afdcafe89118cee761f9bf67ea1b1efc29311300.tar.gz binutils-afdcafe89118cee761f9bf67ea1b1efc29311300.tar.bz2 |
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 <lifang_xia@c-sky.com>
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.
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/ChangeLog | 34 | ||||
-rw-r--r-- | opcodes/csky-dis.c | 148 | ||||
-rw-r--r-- | opcodes/csky-opc.h | 529 |
3 files changed, 531 insertions, 180 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 0ec12f9..2dd9d35 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,37 @@ +2020-09-17 Cooper Qu <<cooper.qu@linux.alibaba.com>> + + 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. + 2020-09-23 Lili Cui <lili.cui@intel.com> * i386-dis.c (enum): Add REG_0F38D8_PREFIX_1, diff --git a/opcodes/csky-dis.c b/opcodes/csky-dis.c index a28160b..67fb4ee 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) diff --git a/opcodes/csky-opc.h b/opcodes/csky-opc.h index a1c67e9..8cd0d1e 100644 --- a/opcodes/csky-opc.h +++ b/opcodes/csky-opc.h @@ -20,6 +20,7 @@ 02110-1301, USA. */ #include "opcode/csky.h" +#include "safe-ctype.h" #define OP_TABLE_NUM 2 #define MAX_OPRND_NUM 5 @@ -128,6 +129,8 @@ enum operand_type /* OPRND_TYPE_IMM5b_a_b means: Immediate in (a, b). */ OPRND_TYPE_IMM5b_1_31, OPRND_TYPE_IMM5b_7_31, + /* OPRND_TYPE_IMM5b_LS means: Imm <= prev Imm. */ + OPRND_TYPE_IMM5b_LS, /* Operand type for rori and rotri. */ OPRND_TYPE_IMM5b_RORI, OPRND_TYPE_IMM5b_POWER, @@ -624,128 +627,421 @@ struct csky_opcode #define V1_REG_SP 0 #define V1_REG_LR 15 -struct csky_reg +struct psrbit { + int value; + int isa; const char *name; - int index; - int flag; }; -const char *csky_general_reg[] = +const struct psrbit cskyv1_psr_bits[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - NULL, + {1, 0, "ie"}, + {2, 0, "fe"}, + {4, 0, "ee"}, + {8, 0, "af"}, + {0, 0, NULL}, }; -/* TODO: optimize. */ -const char *cskyv2_general_alias_reg[] = +const struct psrbit cskyv2_psr_bits[] = { - "a0", "a1", "a2", "a3", "l0", "l1", "l2", "l3", - "l4", "l5", "l6", "l7", "t0", "t1", "sp", "lr", - "l8", "l9", "t2", "t3", "t4", "t5", "t6", "t7", - "t8", "t9", "r26", "r27", "rdb", "gb", "r30", "r31", - NULL, + {8, 0, "ee"}, + {4, 0, "ie"}, + {2, 0, "fe"}, + {1, 0, "af"}, + {0x10, CSKY_ISA_TRUST, "sie"}, + {0, 0, NULL}, }; -/* TODO: optimize. */ -const char *cskyv1_general_alias_reg[] = +#define GENARAL_REG_BANK 0x80000000 +#define REG_SUPPORT_ALL 0xffffffff + +/* CSKY register description. */ +struct csky_reg_def { - "sp", "r1", "a0", "a1", "a2", "a3", "a4", "a5", - "fp", "l0", "l1", "l2", "l3", "l4", "gb", "lr", - NULL, + /* The group number for control registers, + and set the bank of genaral registers to a special number. */ + int bank; + int regno; + /* The name displayed by serial number. */ + const char *name; + /* The name displayed by ABI infomation, + used when objdump add option -Mabi-names. */ + const char *abi_name; + /* The flags indicate which arches support the register. */ + int arch_flag; + /* Some registers depend on special features. */ + char *features; }; -/* TODO: optimize. */ -const char *csky_fpu_reg[] = +/* Arch flag. */ +#define ASH(a) (1 << CSKY_ARCH_##a) + +/* All arches exclued 801. */ +#define REG_SUPPORT_A (REG_SUPPORT_ALL & ~ASH(801)) + +/* All arches exclued 801 and 802. */ +#define REG_SUPPORT_B (REG_SUPPORT_ALL & ~(ASH(801) | ASH(802))) + +/* All arches exclued 801, 802, 803, 805.*/ +#define REG_SUPPORT_C (REG_SUPPORT_ALL & ~(ASH(801) \ + | ASH(802) | ASH(803) | ASH(805))) + +/* All arches exclued 801, 802, 803, 805, 807, 810. */ +#define REG_SUPPORT_D (REG_SUPPORT_C & ~(ASH(807) | ASH(810))) + +/* All arches exclued 807, 810, 860. */ +#define REG_SUPPORT_E (REG_SUPPORT_ALL & ~(ASH(807) | ASH(810) | \ + ASH(860))) + +/* C-SKY V1 general registers table. */ +static struct csky_reg_def csky_abiv1_general_regs[] = { - "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", - "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15", - "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23", - "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31", - NULL, +#define DECLARE_REG(regno, abi_name, support) \ + {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL} + + DECLARE_REG (0, "sp", REG_SUPPORT_ALL), + DECLARE_REG (1, NULL, REG_SUPPORT_ALL), + DECLARE_REG (2, "a0", REG_SUPPORT_ALL), + DECLARE_REG (3, "a1", REG_SUPPORT_ALL), + DECLARE_REG (4, "a2", REG_SUPPORT_ALL), + DECLARE_REG (5, "a3", REG_SUPPORT_ALL), + DECLARE_REG (6, "a4", REG_SUPPORT_ALL), + DECLARE_REG (7, "a5", REG_SUPPORT_ALL), + DECLARE_REG (8, "fp", REG_SUPPORT_ALL), + DECLARE_REG (8, "l0", REG_SUPPORT_ALL), + DECLARE_REG (9, "l1", REG_SUPPORT_ALL), + DECLARE_REG (10, "l2", REG_SUPPORT_ALL), + DECLARE_REG (11, "l3", REG_SUPPORT_ALL), + DECLARE_REG (12, "l4", REG_SUPPORT_ALL), + DECLARE_REG (13, "l5", REG_SUPPORT_ALL), + DECLARE_REG (14, "gb", REG_SUPPORT_ALL), + DECLARE_REG (15, "lr", REG_SUPPORT_ALL), +#undef DECLARE_REG + {-1, -1, NULL, NULL, 0, NULL}, }; -/* Control Registers. */ -struct csky_reg csky_ctrl_regs[] = +/* C-SKY V1 control registers table. */ +static struct csky_reg_def csky_abiv1_control_regs[] = { - {"psr", 0, 0}, {"vbr", 1, 0}, {"epsr", 2, 0}, {"fpsr", 3, 0}, - {"epc", 4, 0}, {"fpc", 5, 0}, {"ss0", 6, 0}, {"ss1", 7, 0}, - {"ss2", 8, 0}, {"ss3", 9, 0}, {"ss4", 10, 0}, {"gcr", 11, 0}, - {"gsr", 12, 0}, {"cpuidr", 13, 0}, {"dcsr", 14, 0}, {"cwr", 15, 0}, - {"cfr", 16, 0}, {"ccr", 17, 0}, {"capr", 19, 0}, {"pacr", 20, 0}, - {"rid", 21, 0}, {"sedcr", 8, CSKY_ISA_TRUST}, {"sepcr", 9, CSKY_ISA_TRUST}, - {NULL, 0, 0} +#define DECLARE_REG(regno, abi_name, support) \ + {0, regno, "cr"#regno, abi_name, support, NULL} + + DECLARE_REG (0, "psr", REG_SUPPORT_ALL), + DECLARE_REG (1, "vbr", REG_SUPPORT_ALL), + DECLARE_REG (2, "epsr", REG_SUPPORT_ALL), + DECLARE_REG (3, "fpsr", REG_SUPPORT_ALL), + DECLARE_REG (4, "epc", REG_SUPPORT_ALL), + DECLARE_REG (5, "fpc", REG_SUPPORT_ALL), + DECLARE_REG (6, "ss0", REG_SUPPORT_ALL), + DECLARE_REG (7, "ss1", REG_SUPPORT_ALL), + DECLARE_REG (8, "ss2", REG_SUPPORT_ALL), + DECLARE_REG (9, "ss3", REG_SUPPORT_ALL), + DECLARE_REG (10, "ss4", REG_SUPPORT_ALL), + DECLARE_REG (11, "gcr", REG_SUPPORT_ALL), + DECLARE_REG (12, "gsr", REG_SUPPORT_ALL), + DECLARE_REG (13, "cpid", REG_SUPPORT_ALL), + DECLARE_REG (14, "dcsr", REG_SUPPORT_ALL), + DECLARE_REG (15, "cwr", REG_SUPPORT_ALL), + DECLARE_REG (16, NULL, REG_SUPPORT_ALL), + DECLARE_REG (17, "cfr", REG_SUPPORT_ALL), + DECLARE_REG (18, "ccr", REG_SUPPORT_ALL), + DECLARE_REG (19, "capr", REG_SUPPORT_ALL), + DECLARE_REG (20, "pacr", REG_SUPPORT_ALL), + DECLARE_REG (21, "prsr", REG_SUPPORT_ALL), + DECLARE_REG (22, "mir", REG_SUPPORT_ALL), + DECLARE_REG (23, "mrr", REG_SUPPORT_ALL), + DECLARE_REG (24, "mel0", REG_SUPPORT_ALL), + DECLARE_REG (25, "mel1", REG_SUPPORT_ALL), + DECLARE_REG (26, "meh", REG_SUPPORT_ALL), + DECLARE_REG (27, "mcr", REG_SUPPORT_ALL), + DECLARE_REG (28, "mpr", REG_SUPPORT_ALL), + DECLARE_REG (29, "mwr", REG_SUPPORT_ALL), + DECLARE_REG (30, "mcir", REG_SUPPORT_ALL), +#undef DECLARE_REG + {-1, -1, NULL, NULL, 0, NULL}, }; -const char *csky_cp_idx[] = +/* C-SKY V2 general registers table. */ +static struct csky_reg_def csky_abiv2_general_regs[] = { - "cp0", "cp1", "cp2", "cp3", "cp4", "cp5", "cp6", "cp7", - "cp8", "cp9", "cp10", "cp11", "cp12", "cp13", "cp14", "cp15", - "cp16", "cp17", "cp18", "cp19", "cp20", - NULL, +#ifdef DECLARE_REG +#undef DECLARE_REG +#endif +#define DECLARE_REG(regno, abi_name, support) \ + {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL} + + DECLARE_REG (0, "a0", REG_SUPPORT_ALL), + DECLARE_REG (1, "a1", REG_SUPPORT_ALL), + DECLARE_REG (2, "a2", REG_SUPPORT_ALL), + DECLARE_REG (3, "a3", REG_SUPPORT_ALL), + DECLARE_REG (4, "l0", REG_SUPPORT_ALL), + DECLARE_REG (5, "l1", REG_SUPPORT_ALL), + DECLARE_REG (6, "l2", REG_SUPPORT_ALL), + DECLARE_REG (7, "l3", REG_SUPPORT_ALL), + DECLARE_REG (8, "l4", REG_SUPPORT_ALL), + DECLARE_REG (9, "l5", REG_SUPPORT_A), + DECLARE_REG (10, "l6", REG_SUPPORT_A), + DECLARE_REG (11, "l7", REG_SUPPORT_A), + DECLARE_REG (12, "t0", REG_SUPPORT_A), + DECLARE_REG (13, "t1", REG_SUPPORT_ALL), + DECLARE_REG (14, "sp", REG_SUPPORT_ALL), + DECLARE_REG (15, "lr", REG_SUPPORT_ALL), + DECLARE_REG (16, "l8", REG_SUPPORT_B), + DECLARE_REG (17, "l9", REG_SUPPORT_B), + DECLARE_REG (18, "t2", REG_SUPPORT_B), + DECLARE_REG (19, "t3", REG_SUPPORT_B), + DECLARE_REG (20, "t4", REG_SUPPORT_B), + DECLARE_REG (21, "t5", REG_SUPPORT_B), + DECLARE_REG (22, "t6", REG_SUPPORT_B), + DECLARE_REG (23, "t7", REG_SUPPORT_B), + DECLARE_REG (24, "t8", REG_SUPPORT_B), + DECLARE_REG (25, "t9", REG_SUPPORT_B), + DECLARE_REG (26, NULL, REG_SUPPORT_B), + DECLARE_REG (27, NULL, REG_SUPPORT_B), + DECLARE_REG (28, "gb", REG_SUPPORT_B), + DECLARE_REG (28, "rgb", REG_SUPPORT_B), + DECLARE_REG (28, "rdb", REG_SUPPORT_B), + DECLARE_REG (29, "tb", REG_SUPPORT_B), + DECLARE_REG (29, "rtb", REG_SUPPORT_B), + DECLARE_REG (30, "svbr", REG_SUPPORT_A), + DECLARE_REG (31, "tls", REG_SUPPORT_B), + + /* The followings JAVA/BCTM's features. */ + DECLARE_REG (23, "fp", REG_SUPPORT_ALL), + DECLARE_REG (24, "top", REG_SUPPORT_ALL), + DECLARE_REG (25, "bsp", REG_SUPPORT_ALL), + + {-1, -1, NULL, NULL, 0, NULL}, }; -const char *csky_cp_reg[] = +/* C-SKY V2 control registers table. */ +static struct csky_reg_def csky_abiv2_control_regs[] = { - "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7", - "cpr8", "cpr9", "cpr10", "cpr11", "cpr12", "cpr13", "cpr14", "cpr15", - "cpr16", "cpr17", "cpr18", "cpr19", "cpr20", "cpr21", "cpr22", "cpr23", - "cpr24", "cpr25", "cpr26", "cpr27", "cpr28", "cpr29", "cpr30", "cpr31", - "cpr32", "cpr33", "cpr34", "cpr35", "cpr36", "cpr37", "cpr38", "cpr39", - "cpr40", "cpr41", "cpr42", "cpr43", "cpr44", "cpr45", "cpr46", "cpr47", - "cpr48", "cpr49", "cpr50", "cpr51", "cpr52", "cpr53", "cpr54", "cpr55", - "cpr56", "cpr57", "cpr58", "cpr59", "cpr60", "cpr61", "cpr62", "cpr63", - NULL, + +#ifdef DECLARE_REG +#undef DECLARE_REG +#endif + /* Bank0. */ +#define DECLARE_REG(regno, abi_name) \ + {0, regno, "cr<"#regno", 0>", abi_name, REG_SUPPORT_ALL, NULL} + DECLARE_REG (0, "psr"), + DECLARE_REG (1, "vbr"), + DECLARE_REG (2, "epsr"), + DECLARE_REG (3, "fpsr"), + DECLARE_REG (4, "epc"), + DECLARE_REG (5, "fpc"), + DECLARE_REG (6, "ss0"), + DECLARE_REG (7, "ss1"), + DECLARE_REG (8, "ss2"), + DECLARE_REG (9, "ss3"), + DECLARE_REG (10, "ss4"), + DECLARE_REG (11, "gcr"), + DECLARE_REG (12, "gsr"), + DECLARE_REG (13, "cpid"), + DECLARE_REG (14, "dcsr"), + DECLARE_REG (15, NULL), + DECLARE_REG (16, NULL), + DECLARE_REG (17, "cfr"), + DECLARE_REG (18, "ccr"), + DECLARE_REG (19, "capr"), + DECLARE_REG (20, "pacr"), + DECLARE_REG (21, "prsr"), + DECLARE_REG (22, "cir"), + DECLARE_REG (23, "ccr2"), + DECLARE_REG (24, NULL), + DECLARE_REG (25, "cer2"), + DECLARE_REG (26, NULL), + DECLARE_REG (27, NULL), + DECLARE_REG (28, "rvbr"), + DECLARE_REG (29, "rmr"), + DECLARE_REG (30, "mpid"), + +#undef DECLARE_REG +#define DECLARE_REG(regno, abi_name, support) \ + {0, regno, "cr<"#regno", 0>", abi_name, support, NULL} + DECLARE_REG (31, "chr", REG_SUPPORT_E), + DECLARE_REG (31, "hint", REG_SUPPORT_C), + + /* Bank1. */ +#undef DECLARE_REG +#define DECLARE_REG(regno, abi_name) \ + {1, regno, "cr<"#regno", 1>", abi_name, REG_SUPPORT_ALL, NULL} + + DECLARE_REG (14, "usp"), + DECLARE_REG (26, "cindex"), + DECLARE_REG (27, "cdata0"), + DECLARE_REG (28, "cdata1"), + DECLARE_REG (29, "cdata2"), + DECLARE_REG (30, "cdata3"), + DECLARE_REG (31, "cins"), + + /* Bank2. */ +#undef DECLARE_REG +#define DECLARE_REG(regno, abi_name) \ + {2, regno, "cr<"#regno", 2>", abi_name, REG_SUPPORT_ALL, NULL} + + DECLARE_REG (0, "fid"), + DECLARE_REG (1, "fcr"), + DECLARE_REG (2, "fesr"), + + /* Bank3. */ +#undef DECLARE_REG +#define DECLARE_REG(regno, abi_name) \ + {3, regno, "cr<"#regno", 3>", abi_name, REG_SUPPORT_ALL, NULL} + DECLARE_REG (8, "dcr"), + DECLARE_REG (8, "sedcr"), + DECLARE_REG (9, "pcr"), + DECLARE_REG (9, "sepcr"), + + /* Bank15. */ +#undef DECLARE_REG +#define DECLARE_REG(regno, abi_name) \ + {15, regno, "cr<"#regno", 15>", abi_name, REG_SUPPORT_ALL, NULL} + + DECLARE_REG (0, "mir"), + DECLARE_REG (2, "mel0"), + DECLARE_REG (3, "mel1"), + DECLARE_REG (4, "meh"), + DECLARE_REG (6, "mpr"), + DECLARE_REG (8, "mcir"), + DECLARE_REG (28, "mpgd0"), + DECLARE_REG (29, "mpgd"), + DECLARE_REG (29, "mpgd1"), + DECLARE_REG (30, "msa0"), + DECLARE_REG (31, "msa1"), +#undef DECLARE_REG + {-1, -1, NULL, NULL, 0, NULL}, }; -const char *csky_cp_creg[] = +/* Get register name according to giving parameters, + IS_ABI controls whether is ABI name or not. */ +static inline const char * +get_register_name (struct csky_reg_def *reg_table, + int arch, int bank, int regno, int is_abi) { - "cpcr0", "cpcr1", "cpcr2", "cpcr3", - "cpcr4", "cpcr5", "cpcr6", "cpcr7", - "cpcr8", "cpcr9", "cpcr10", "cpcr11", - "cpcr12", "cpcr13", "cpcr14", "cpcr15", - "cpcr16", "cpcr17", "cpcr18", "cpcr19", - "cpcr20", "cpcr21", "cpcr22", "cpcr23", - "cpcr24", "cpcr25", "cpcr26", "cpcr27", - "cpcr28", "cpcr29", "cpcr30", "cpcr31", - "cpcr32", "cpcr33", "cpcr34", "cpcr35", - "cpcr36", "cpcr37", "cpcr38", "cpcr39", - "cpcr40", "cpcr41", "cpcr42", "cpcr43", - "cpcr44", "cpcr45", "cpcr46", "cpcr47", - "cpcr48", "cpcr49", "cpcr50", "cpcr51", - "cpcr52", "cpcr53", "cpcr54", "cpcr55", - "cpcr56", "cpcr57", "cpcr58", "cpcr59", - "cpcr60", "cpcr61", "cpcr62", "cpcr63", - NULL, -}; + static char regname[64] = {0}; + unsigned int i = 0; + while (reg_table[i].name != NULL) + { + if (reg_table[i].bank == bank + && reg_table[i].regno == regno + && (reg_table[i].arch_flag & (1 << arch))) + { + if (is_abi && reg_table[i].abi_name) + return reg_table[i].abi_name; + else + return reg_table[i].name; + } + i++; + } -struct psrbit + if (bank & 0x80000000) + return "unkown register"; + + sprintf (regname, "cr<%d, %d>", regno, bank); + + return regname; +} + +/* Get register number according to giving parameters. + If not found, return -1. */ +static inline int +get_register_number (struct csky_reg_def *reg_table, + int arch, char *s, char **end, int *bank) { - int value; - int isa; - const char *name; -}; -const struct psrbit cskyv1_psr_bits[] = + unsigned int i = 0; + int len = 0; + while (reg_table[i].name != NULL) + { + len = strlen (reg_table[i].name); + if ((strncasecmp (reg_table[i].name, s, len) == 0) + && !(ISDIGIT (s[len])) + && (reg_table[i].arch_flag & (1 << arch))) + { + *end = s + len; + *bank = reg_table[i].bank; + return reg_table[i].regno; + } + + if (reg_table[i].abi_name == NULL) + { + i++; + continue; + } + + len = strlen (reg_table[i].abi_name); + if ((strncasecmp (reg_table[i].abi_name, s, len) == 0) + && !(ISALNUM (s[len])) + && (reg_table[i].arch_flag & (1 << arch))) + { + *end = s + len; + *bank = reg_table[i].bank; + return reg_table[i].regno; + } + i++; + } + return -1; +} + +/* Return general register's name. */ +static inline const char * +csky_get_general_reg_name (int arch, int regno, int is_abi) { - {1, 0, "ie"}, - {2, 0, "fe"}, - {4, 0, "ee"}, - {8, 0, "af"}, - {0, 0, NULL}, -}; -const struct psrbit cskyv2_psr_bits[] = + struct csky_reg_def *reg_table; + + if (IS_CSKY_ARCH_V1(arch)) + reg_table = csky_abiv1_general_regs; + else + reg_table = csky_abiv2_general_regs; + + return get_register_name (reg_table, arch, + GENARAL_REG_BANK, regno, is_abi); +} + +/* Return general register's number. */ +static inline int +csky_get_general_regno(int arch, char *s, char **end) { - {8, 0, "ee"}, - {4, 0, "ie"}, - {2, 0, "fe"}, - {1, 0, "af"}, - {0x10, CSKY_ISA_TRUST, "sie"}, - {0, 0, NULL}, -}; + struct csky_reg_def *reg_table; + int bank = 0; + if (IS_CSKY_ARCH_V1(arch)) + reg_table = csky_abiv1_general_regs; + else + reg_table = csky_abiv2_general_regs; + + return get_register_number (reg_table, arch, s, end, &bank); +} + +/* Return control register's name. */ +static inline const char * +csky_get_control_reg_name (int arch, int bank, int regno, int is_abi) +{ + struct csky_reg_def *reg_table; + + if (IS_CSKY_ARCH_V1(arch)) + reg_table = csky_abiv1_control_regs; + else + reg_table = csky_abiv2_control_regs; + + return get_register_name (reg_table, arch, bank, + regno, is_abi); +} + +/* Return control register's number. */ +static inline int +csky_get_control_regno(int arch, char *s, char **end, int *bank) +{ + struct csky_reg_def *reg_table; + + if (IS_CSKY_ARCH_V1(arch)) + reg_table = csky_abiv1_control_regs; + else + reg_table = csky_abiv2_control_regs; + + return get_register_number (reg_table, arch, s, end, bank); +} /* C-SKY V1 opcodes. */ const struct csky_opcode csky_v1_opcodes[] = @@ -3620,12 +3916,12 @@ const struct csky_opcode csky_v2_opcodes[] = #undef _TRANSFER #define _TRANSFER 0 DOP16_DOP32 ("bclri", - OPCODE_INFO3 (0x3880, + OPCODE_INFO2 (0x3880, (8_10, GREG0_7, OPRND_SHIFT_0_BIT), - (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT), (0_4, IMM5b, OPRND_SHIFT_0_BIT)), - OPCODE_INFO2 (0x3880, + OPCODE_INFO3 (0x3880, (8_10, GREG0_7, OPRND_SHIFT_0_BIT), + (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT), (0_4, IMM5b, OPRND_SHIFT_0_BIT)), CSKYV2_ISA_E1, OPCODE_INFO3 (0xc4002820, @@ -3637,12 +3933,12 @@ const struct csky_opcode csky_v2_opcodes[] = (21_25, IMM5b, OPRND_SHIFT_0_BIT)), CSKYV2_ISA_1E2), DOP16_DOP32 ("bseti", - OPCODE_INFO3 (0x38a0, + OPCODE_INFO2 (0x38a0, (8_10, GREG0_7, OPRND_SHIFT_0_BIT), - (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT), (0_4, IMM5b, OPRND_SHIFT_0_BIT)), - OPCODE_INFO2 (0x38a0, + OPCODE_INFO3 (0x38a0, (8_10, GREG0_7, OPRND_SHIFT_0_BIT), + (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT), (0_4, IMM5b, OPRND_SHIFT_0_BIT)), CSKYV2_ISA_E1, OPCODE_INFO3 (0xc4002840, @@ -3707,23 +4003,24 @@ const struct csky_opcode csky_v2_opcodes[] = (16_20, AREG, OPRND_SHIFT_0_BIT), (21_25, IMM5b, OPRND_SHIFT_0_BIT)), CSKYV2_ISA_1E2), - DOP16_DOP32 ("addc", - OPCODE_INFO2 (0x6001, - (6_9, GREG0_15, OPRND_SHIFT_0_BIT), - (2_5, GREG0_15, OPRND_SHIFT_0_BIT)), - OPCODE_INFO3 (0x6001, - (6_9, GREG0_15, OPRND_SHIFT_0_BIT), - (2_5, 2IN1_DUMMY, OPRND_SHIFT_0_BIT), - (2_5, 2IN1_DUMMY, OPRND_SHIFT_0_BIT)), - CSKYV2_ISA_E1, - OPCODE_INFO3 (0xc4000040, - (0_4, AREG, OPRND_SHIFT_0_BIT), - (16_20, AREG, OPRND_SHIFT_0_BIT), - (21_25, AREG, OPRND_SHIFT_0_BIT)), - OPCODE_INFO2 (0xc4000040, - (0_4or16_20, DUP_AREG, OPRND_SHIFT_0_BIT), - (21_25, AREG, OPRND_SHIFT_0_BIT)), - CSKYV2_ISA_1E2), + DOP16_DOP32_WITH_WORK ("addc", + OPCODE_INFO2 (0x6001, + (6_9, GREG0_15, OPRND_SHIFT_0_BIT), + (2_5, GREG0_15, OPRND_SHIFT_0_BIT)), + OPCODE_INFO3 (0x6001, + (6_9, GREG0_15, OPRND_SHIFT_0_BIT), + (2_5, GREG0_15, OPRND_SHIFT_0_BIT), + (2_5, GREG0_15, OPRND_SHIFT_0_BIT)), + CSKYV2_ISA_E1, + OPCODE_INFO3 (0xc4000040, + (0_4, AREG, OPRND_SHIFT_0_BIT), + (16_20, AREG, OPRND_SHIFT_0_BIT), + (21_25, AREG, OPRND_SHIFT_0_BIT)), + OPCODE_INFO2 (0xc4000040, + (0_4or16_20, AREG, OPRND_SHIFT_0_BIT), + (21_25, AREG, OPRND_SHIFT_0_BIT)), + CSKYV2_ISA_1E2, + v2_work_addc), DOP16_DOP32 ("subc", OPCODE_INFO2 (0x6003, (6_9, GREG0_15, OPRND_SHIFT_0_BIT), @@ -4015,14 +4312,14 @@ const struct csky_opcode csky_v2_opcodes[] = (0_4, AREG, OPRND_SHIFT_0_BIT), (16_20, AREG, OPRND_SHIFT_0_BIT), (5_9, IMM5b, OPRND_SHIFT_0_BIT), - (21_25, IMM5b, OPRND_SHIFT_0_BIT)), + (21_25, IMM5b_LS, OPRND_SHIFT_0_BIT)), CSKYV2_ISA_2E3), OP32 ("sext", OPCODE_INFO4 (0xc4005800, (0_4, AREG, OPRND_SHIFT_0_BIT), (16_20, AREG, OPRND_SHIFT_0_BIT), (5_9, IMM5b, OPRND_SHIFT_0_BIT), - (21_25, IMM5b, OPRND_SHIFT_0_BIT)), + (21_25, IMM5b_LS, OPRND_SHIFT_0_BIT)), CSKYV2_ISA_2E3), #undef _TRANSFER #define _TRANSFER 2 |