From 880fc278cadb4c057bc85ef27b199cac12f8c095 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 31 Aug 2020 09:07:03 +0930 Subject: [PATCH] crx: ubsan: cannot be represented * config/tc-crx.c: Formatting. (CRX_PRINT): Wrap params in parentheses. Remove parens from uses throughout file. (reset_vars, get_register, get_copregister, get_optype, get_opbits), (get_opflags, get_number_of_operands, parse_operand, gettrap), (handle_LoadStor, getconstant, check_range, getreg_image), (parse_operands, parse_insn, print_operand, print_constant), (exponent2scale, mask_reg, process_label_constant, set_operand), (assemble_insn, print_insn): Delete unnecessary forward declaration. (print_insn): Make static. (print_constant): Make "constant" unsigned. (assemble_insn): Tidy REVERSE_MATCH index calc. * expr.c (generic_bignum_to_int32): Cast elements to valueT. --- gas/ChangeLog | 16 ++++ gas/config/tc-crx.c | 224 +++++++++++++++++++------------------------- gas/expr.c | 4 +- 3 files changed, 116 insertions(+), 128 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 16e425b371c..38c7f70b22e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,19 @@ +2020-08-31 Alan Modra + + * config/tc-crx.c: Formatting. + (CRX_PRINT): Wrap params in parentheses. Remove parens from uses + throughout file. + (reset_vars, get_register, get_copregister, get_optype, get_opbits), + (get_opflags, get_number_of_operands, parse_operand, gettrap), + (handle_LoadStor, getconstant, check_range, getreg_image), + (parse_operands, parse_insn, print_operand, print_constant), + (exponent2scale, mask_reg, process_label_constant, set_operand), + (assemble_insn, print_insn): Delete unnecessary forward declaration. + (print_insn): Make static. + (print_constant): Make "constant" unsigned. + (assemble_insn): Tidy REVERSE_MATCH index calc. + * expr.c (generic_bignum_to_int32): Cast elements to valueT. + 2020-08-31 Alan Modra PR 26509 diff --git a/gas/config/tc-crx.c b/gas/config/tc-crx.c index 03a5e6e3225..041b9eb7778 100644 --- a/gas/config/tc-crx.c +++ b/gas/config/tc-crx.c @@ -47,7 +47,7 @@ /* Assign a number NUM, shifted by SHIFT bytes, into a location pointed by index BYTE of array 'output_opcode'. */ -#define CRX_PRINT(BYTE, NUM, SHIFT) output_opcode[BYTE] |= (NUM << SHIFT) +#define CRX_PRINT(BYTE, NUM, SHIFT) output_opcode[BYTE] |= (NUM) << (SHIFT) /* Operand errors. */ typedef enum @@ -140,31 +140,8 @@ const relax_typeS md_relax_table[] = {0xfffffe, -0x1000000, 6, 0} /* 24 */ }; -static void reset_vars (char *); -static reg get_register (char *); -static copreg get_copregister (char *); -static argtype get_optype (operand_type); -static int get_opbits (operand_type); -static int get_opflags (operand_type); -static int get_number_of_operands (void); -static void parse_operand (char *, ins *); -static int gettrap (const char *); -static void handle_LoadStor (const char *); -static int get_cinv_parameters (const char *); -static long getconstant (long, int); -static op_err check_range (long *, int, unsigned int, int); -static int getreg_image (int); -static void parse_operands (ins *, char *); -static void parse_insn (ins *, char *); -static void print_operand (int, int, argument *); -static void print_constant (int, int, argument *); -static int exponent2scale (int); -static void mask_reg (int, unsigned short *); -static void process_label_constant (char *, ins *); -static void set_operand (char *, ins *); -static char * preprocess_reglist (char *, int *); -static int assemble_insn (char *, ins *); -static void print_insn (ins *); +static int get_cinv_parameters (const char *); +static char * preprocess_reglist (char *, int *); static void warn_if_needed (ins *); static int adjust_if_needed (ins *); @@ -618,42 +595,42 @@ process_label_constant (char *str, ins * crx_ins) switch (cur_arg->type) { case arg_cr: - if (IS_INSN_TYPE (LD_STOR_INS_INC)) + if (IS_INSN_TYPE (LD_STOR_INS_INC)) crx_ins->rtype = BFD_RELOC_CRX_REGREL12; - else if (IS_INSN_TYPE (CSTBIT_INS) + else if (IS_INSN_TYPE (CSTBIT_INS) || IS_INSN_TYPE (STOR_IMM_INS)) crx_ins->rtype = BFD_RELOC_CRX_REGREL28; - else + else crx_ins->rtype = BFD_RELOC_CRX_REGREL32; break; case arg_idxr: - crx_ins->rtype = BFD_RELOC_CRX_REGREL22; + crx_ins->rtype = BFD_RELOC_CRX_REGREL22; break; case arg_c: - if (IS_INSN_MNEMONIC ("bal") || IS_INSN_TYPE (DCR_BRANCH_INS)) + if (IS_INSN_MNEMONIC ("bal") || IS_INSN_TYPE (DCR_BRANCH_INS)) crx_ins->rtype = BFD_RELOC_CRX_REL16; else if (IS_INSN_TYPE (BRANCH_INS)) crx_ins->rtype = BFD_RELOC_CRX_REL8; - else if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (STOR_IMM_INS) + else if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (STOR_IMM_INS) || IS_INSN_TYPE (CSTBIT_INS)) crx_ins->rtype = BFD_RELOC_CRX_ABS32; else if (IS_INSN_TYPE (BRANCH_NEQ_INS)) crx_ins->rtype = BFD_RELOC_CRX_REL4; - else if (IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (COP_BRANCH_INS)) + else if (IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (COP_BRANCH_INS)) crx_ins->rtype = BFD_RELOC_CRX_REL8_CMP; break; case arg_ic: - if (IS_INSN_TYPE (ARITH_INS)) + if (IS_INSN_TYPE (ARITH_INS)) crx_ins->rtype = BFD_RELOC_CRX_IMM32; else if (IS_INSN_TYPE (ARITH_BYTE_INS)) crx_ins->rtype = BFD_RELOC_CRX_IMM16; break; default: break; - } + } break; default: @@ -782,7 +759,7 @@ set_operand (char *operand, ins * crx_ins) if (c == ')') cur_arg->scale = 0; else - { + { while (*operandE != ')') operandE++; *operandE = '\0'; @@ -796,12 +773,12 @@ set_operand (char *operand, ins * crx_ins) scale_val = scale.X_add_number; /* Check if the scale value is legal. */ - if (scale_val != 1 && scale_val != 2 - && scale_val != 4 && scale_val != 8) + if (scale_val != 1 && scale_val != 2 + && scale_val != 4 && scale_val != 8) as_bad (_("Illegal Scale - `%d'"), scale_val); cur_arg->scale = exponent2scale (scale_val); - } + } break; default: @@ -849,7 +826,7 @@ parse_operand (char *operand, ins * crx_ins) if (strchr (operand, '(') != NULL) cur_arg->type = arg_icr; else - cur_arg->type = arg_ic; + cur_arg->type = arg_ic; goto set_params; break; @@ -864,14 +841,14 @@ parse_operand (char *operand, ins * crx_ins) break; default: - break; + break; } if (strchr (operand, '(') != NULL) { if (strchr (operand, ',') != NULL - && (strchr (operand, ',') > strchr (operand, '('))) - cur_arg->type = arg_idxr; + && (strchr (operand, ',') > strchr (operand, '('))) + cur_arg->type = arg_idxr; else cur_arg->type = arg_cr; } @@ -906,12 +883,12 @@ parse_operands (ins * crx_ins, char *operands) while (*operandT != '\0') { if (*operandT == ',' && bracket_flag != 1 && sq_bracket_flag != 1) - { + { *operandT++ = '\0'; operand[op_num++] = strdup (operandH); - operandH = operandT; - continue; - } + operandH = operandT; + continue; + } if (*operandT == ' ') as_bad (_("Illegal operands (whitespace): `%s'"), ins_parse); @@ -1169,8 +1146,7 @@ static void print_constant (int nbits, int shift, argument *arg) { unsigned long mask = 0; - - long constant = getconstant (arg->constant, nbits); + unsigned long constant = getconstant (arg->constant, nbits); switch (nbits) { @@ -1191,7 +1167,7 @@ print_constant (int nbits, int shift, argument *arg) output_opcode[0] output_opcode[1] */ CRX_PRINT (0, (constant >> WORD_SHIFT) & mask, 0); - CRX_PRINT (1, (constant & 0xFFFF), WORD_SHIFT); + CRX_PRINT (1, constant & 0xFFFF, WORD_SHIFT); break; case 16: @@ -1455,9 +1431,9 @@ assemble_insn (char *mnemonic, ins *insn) /* Operand error (used for issuing various constant error messages). */ op_err op_error, const_err = OP_LEGAL; -/* Retrieve data (based on FUNC) for each operand of a given instruction. */ -#define GET_CURRENT_DATA(FUNC, ARRAY) \ - for (i = 0; i < insn->nargs; i++) \ + /* Retrieve data (based on FUNC) for each operand of a given instruction. */ +#define GET_CURRENT_DATA(FUNC, ARRAY) \ + for (i = 0; i < insn->nargs; i++) \ ARRAY[i] = FUNC (instruction->operands[i].op_type) #define GET_CURRENT_TYPE GET_CURRENT_DATA(get_optype, cur_type) @@ -1500,7 +1476,7 @@ assemble_insn (char *mnemonic, ins *insn) /* Check for type compatibility. */ for (i = 0; i < insn->nargs; i++) - { + { if (cur_type[i] != insn->arg[i].type) { if (invalid_optype == -1) @@ -1516,32 +1492,29 @@ assemble_insn (char *mnemonic, ins *insn) Index 0 -->> 1 Index 1 -->> 0 Other index -->> stays the same. */ - int j = instruction->flags & REVERSE_MATCH ? - i == 0 ? 1 : - i == 1 ? 0 : i : - i; + int j = (instruction->flags & REVERSE_MATCH) && i <= 1 ? 1 - i : i; /* Only check range - don't update the constant's value, since the current instruction may not be the last we try to match. The constant's value will be updated later, right before printing it to the object file. */ - if ((insn->arg[j].X_op == O_constant) - && (op_error = check_range (&insn->arg[j].constant, cur_size[j], - cur_flags[j], 0))) - { + if ((insn->arg[j].X_op == O_constant) + && (op_error = check_range (&insn->arg[j].constant, cur_size[j], + cur_flags[j], 0))) + { if (invalid_const == -1) - { - invalid_const = j + 1; - const_err = op_error; - } + { + invalid_const = j + 1; + const_err = op_error; + } goto next_insn; } /* For symbols, we make sure the relocation size (which was already determined) is sufficient. */ else if ((insn->arg[j].X_op == O_symbol) - && ((bfd_reloc_type_lookup (stdoutput, insn->rtype))->bitsize - > cur_size[j])) - goto next_insn; + && ((bfd_reloc_type_lookup (stdoutput, insn->rtype))->bitsize + > cur_size[j])) + goto next_insn; } found_const_within_range = 1; @@ -1562,30 +1535,32 @@ assemble_insn (char *mnemonic, ins *insn) else if (!found_same_argument_types) as_bad (_("Illegal type of operand (arg %d)"), invalid_optype); else if (!found_const_within_range) - { - switch (const_err) { - case OP_OUT_OF_RANGE: - as_bad (_("Operand out of range (arg %d)"), invalid_const); - break; - case OP_NOT_EVEN: - as_bad (_("Operand has odd displacement (arg %d)"), invalid_const); - break; - case OP_ILLEGAL_DISPU4: - as_bad (_("Invalid DISPU4 operand value (arg %d)"), invalid_const); - break; - case OP_ILLEGAL_CST4: - as_bad (_("Invalid CST4 operand value (arg %d)"), invalid_const); - break; - case OP_NOT_UPPER_64KB: - as_bad (_("Operand value is not within upper 64 KB (arg %d)"), - invalid_const); - break; - default: - as_bad (_("Illegal operand (arg %d)"), invalid_const); - break; + switch (const_err) + { + case OP_OUT_OF_RANGE: + as_bad (_("Operand out of range (arg %d)"), invalid_const); + break; + case OP_NOT_EVEN: + as_bad (_("Operand has odd displacement (arg %d)"), + invalid_const); + break; + case OP_ILLEGAL_DISPU4: + as_bad (_("Invalid DISPU4 operand value (arg %d)"), + invalid_const); + break; + case OP_ILLEGAL_CST4: + as_bad (_("Invalid CST4 operand value (arg %d)"), invalid_const); + break; + case OP_NOT_UPPER_64KB: + as_bad (_("Operand value is not within upper 64 KB (arg %d)"), + invalid_const); + break; + default: + as_bad (_("Illegal operand (arg %d)"), invalid_const); + break; + } } - } return 0; } @@ -1603,28 +1578,25 @@ assemble_insn (char *mnemonic, ins *insn) GET_CURRENT_SIZE; for (i = 0; i < insn->nargs; i++) - { - int j = instruction->flags & REVERSE_MATCH ? - i == 0 ? 1 : - i == 1 ? 0 : i : - i; + { + int j = (instruction->flags & REVERSE_MATCH) && i <= 1 ? 1 - i : i; /* This time, update constant value before printing it. */ - if ((insn->arg[j].X_op == O_constant) - && (check_range (&insn->arg[j].constant, cur_size[j], - cur_flags[j], 1) != OP_LEGAL)) - as_fatal (_("Illegal operand (arg %d)"), j+1); + if ((insn->arg[j].X_op == O_constant) + && (check_range (&insn->arg[j].constant, cur_size[j], + cur_flags[j], 1) != OP_LEGAL)) + as_fatal (_("Illegal operand (arg %d)"), j+1); } /* First, copy the instruction's opcode. */ output_opcode[0] = BIN (instruction->match, instruction->match_bits); for (i = 0; i < insn->nargs; i++) - { + { cur_arg_num = i; - print_operand (cur_size[i], instruction->operands[i].shift, + print_operand (cur_size[i], instruction->operands[i].shift, &insn->arg[i]); - } + } } return 1; @@ -1681,13 +1653,13 @@ adjust_if_needed (ins *insn) { if ((instruction->operands[0].op_type == cst4) && instruction->operands[1].op_type == regr) - { - if (insn->arg[0].constant == 0 && insn->arg[1].r == r0) + { + if (insn->arg[0].constant == 0 && insn->arg[1].r == r0) { instruction++; ret_value = 1; } - } + } } /* Optimization: Omit a zero displacement in bit operations, @@ -1695,12 +1667,12 @@ adjust_if_needed (ins *insn) if (IS_INSN_TYPE (CSTBIT_INS)) { if ((instruction->operands[1].op_type == rbase_disps12) - && (insn->arg[1].X_op == O_constant) - && (insn->arg[1].constant == 0)) - { - instruction--; - ret_value = 1; - } + && (insn->arg[1].X_op == O_constant) + && (insn->arg[1].constant == 0)) + { + instruction--; + ret_value = 1; + } } return ret_value; @@ -1766,21 +1738,21 @@ preprocess_reglist (char *param, int *allocated) /* Coprocessor register c. */ if (IS_INSN_TYPE (COP_REG_INS)) - { - if (((cr = get_copregister (reg_name)) == nullcopregister) + { + if (((cr = get_copregister (reg_name)) == nullcopregister) || (crx_copregtab[cr-MAX_REG].type != CRX_C_REGTYPE)) as_fatal (_("Illegal register `%s' in cop-register list"), reg_name); mask_reg (getreg_image (cr - c0), &mask); - } + } /* Coprocessor Special register cs. */ else if (IS_INSN_TYPE (COPS_REG_INS)) - { - if (((cr = get_copregister (reg_name)) == nullcopregister) + { + if (((cr = get_copregister (reg_name)) == nullcopregister) || (crx_copregtab[cr-MAX_REG].type != CRX_CS_REGTYPE)) as_fatal (_("Illegal register `%s' in cop-special-register list"), reg_name); mask_reg (getreg_image (cr - cs0), &mask); - } + } /* User register u. */ else if (instruction->flags & USER_REG) { @@ -1794,15 +1766,15 @@ preprocess_reglist (char *param, int *allocated) lo_found = 1; goto next_inst; } - else if (((r = get_register (reg_name)) == nullregister) - || (crx_regtab[r].type != CRX_U_REGTYPE)) + else if (((r = get_register (reg_name)) == nullregister) + || (crx_regtab[r].type != CRX_U_REGTYPE)) as_fatal (_("Illegal register `%s' in user register list"), reg_name); mask_reg (getreg_image (r - u0), &mask); } /* General purpose register r. */ else - { + { if (streq(reg_name, "hi")) { hi_found = 1; @@ -1813,12 +1785,12 @@ preprocess_reglist (char *param, int *allocated) lo_found = 1; goto next_inst; } - else if (((r = get_register (reg_name)) == nullregister) - || (crx_regtab[r].type != CRX_R_REGTYPE)) + else if (((r = get_register (reg_name)) == nullregister) + || (crx_regtab[r].type != CRX_R_REGTYPE)) as_fatal (_("Illegal register `%s' in register list"), reg_name); mask_reg (getreg_image (r - r0), &mask); - } + } if (++reg_counter > MAX_REGS_IN_MASK16) as_bad (_("Maximum %d bits may be set in `mask16' operand"), @@ -1826,7 +1798,7 @@ preprocess_reglist (char *param, int *allocated) next_inst: while (!ISALNUM (*paramP) && *paramP != '}') - paramP++; + paramP++; } if (*++paramP != '\0') @@ -1864,7 +1836,7 @@ preprocess_reglist (char *param, int *allocated) /* Print the instruction. Handle also cases where the instruction is relaxable/relocatable. */ -void +static void print_insn (ins *insn) { unsigned int i, j, insn_size; diff --git a/gas/expr.c b/gas/expr.c index 7c002c0d964..da4fbcf8cd6 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -224,8 +224,8 @@ static valueT generic_bignum_to_int32 (void) { valueT number = - ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) - | (generic_bignum[0] & LITTLENUM_MASK); + ((((valueT) generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) + | ((valueT) generic_bignum[0] & LITTLENUM_MASK)); number &= 0xffffffff; return number; } -- 2.30.2