From 9e12b7a2b02287bfb0aed676132f7ba22fc9532d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 14 Jul 2013 13:49:14 +0000 Subject: [PATCH] gas/ * config/tc-mips.c: Enable functions commented out in previous patch. (SKIP_SPACE_TABS): Move further up file. (mips32_to_micromips_reg_b_map, mips32_to_micromips_reg_c_map) (mips32_to_micromips_reg_d_map, mips32_to_micromips_reg_e_map) (ips32_to_micromips_reg_f_map, mips32_to_micromips_reg_g_map) (mips32_to_micromips_reg_l_map, mips32_to_micromips_reg_m_map) (mips32_to_micromips_reg_q_map, mips32_to_micromips_reg_n_map) (micromips_imm_b_map, micromips_imm_c_map): Delete. (mips_lookup_reg_pair): Delete. (macro): Use report_bad_range and report_bad_field. (mips_immed, expr_const_in_range): Delete. (mips_ip): Rewrite main parsing loop to use new functions. gas/testsuite/ * gas/mips/at-2.l: Remove duplicated $at warnings. * gas/mips/ext-ill.l, gas/mips/lui-1.l, gas/mips/mips32r2-ill.l, gas/mips/mips32r2-ill-nofp.l, gas/mips/mips32r2-ill-fp64.l, gas/mips/mips64r2-ill.l, gas/mips/octeon-ill.l: Update error messages. Expect negative numbers to be printed as such, rather than as large unsigned positive numbers. --- gas/ChangeLog | 15 + gas/config/tc-mips.c | 2887 ++++------------------------ gas/testsuite/ChangeLog | 9 + gas/testsuite/gas/mips/at-2.l | 6 - gas/testsuite/gas/mips/ext-ill.l | 10 +- gas/testsuite/gas/mips/lui-1.l | 4 +- gas/testsuite/gas/mips/mips32r2-ill-fp64.l | 24 +- gas/testsuite/gas/mips/mips32r2-ill-nofp.l | 24 +- gas/testsuite/gas/mips/mips32r2-ill.l | 24 +- gas/testsuite/gas/mips/mips64r2-ill.l | 112 +- gas/testsuite/gas/mips/octeon-ill.l | 36 +- 11 files changed, 523 insertions(+), 2628 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 77dc629..ceeb1b2 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,20 @@ 2013-07-14 Richard Sandiford + * config/tc-mips.c: Enable functions commented out in previous patch. + (SKIP_SPACE_TABS): Move further up file. + (mips32_to_micromips_reg_b_map, mips32_to_micromips_reg_c_map) + (mips32_to_micromips_reg_d_map, mips32_to_micromips_reg_e_map) + (ips32_to_micromips_reg_f_map, mips32_to_micromips_reg_g_map) + (mips32_to_micromips_reg_l_map, mips32_to_micromips_reg_m_map) + (mips32_to_micromips_reg_q_map, mips32_to_micromips_reg_n_map) + (micromips_imm_b_map, micromips_imm_c_map): Delete. + (mips_lookup_reg_pair): Delete. + (macro): Use report_bad_range and report_bad_field. + (mips_immed, expr_const_in_range): Delete. + (mips_ip): Rewrite main parsing loop to use new functions. + +2013-07-14 Richard Sandiford + * config/tc-mips.c (mips_oddfpreg_ok): Move further up file. Change return type to bfd_boolean. (report_bad_range, report_bad_field): New functions. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index e0e2d1d..c7e0edc 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -44,6 +44,9 @@ typedef char static_assert2[sizeof (valueT) < 8 ? -1 : 1]; #define DBG(x) #endif +#define SKIP_SPACE_TABS(S) \ + do { while (*(S) == ' ' || *(S) == '\t') ++(S); } while (0) + /* Clean up namespace so we can include obj-elf.h too. */ static int mips_output_flavor (void); static int mips_output_flavor (void) { return OUTPUT_FLAVOR; } @@ -771,38 +774,6 @@ static const unsigned int mips16_to_32_reg_map[] = 16, 17, 2, 3, 4, 5, 6, 7 }; -/* Map normal MIPS register numbers to microMIPS register numbers. */ - -#define mips32_to_micromips_reg_b_map mips32_to_16_reg_map -#define mips32_to_micromips_reg_c_map mips32_to_16_reg_map -#define mips32_to_micromips_reg_d_map mips32_to_16_reg_map -#define mips32_to_micromips_reg_e_map mips32_to_16_reg_map -#define mips32_to_micromips_reg_f_map mips32_to_16_reg_map -#define mips32_to_micromips_reg_g_map mips32_to_16_reg_map -#define mips32_to_micromips_reg_l_map mips32_to_16_reg_map - -#define X ILLEGAL_REG -/* reg type m: 0, 17, 2, 3, 16, 18, 19, 20. */ -static const int mips32_to_micromips_reg_m_map[] = -{ - 0, X, 2, 3, X, X, X, X, - X, X, X, X, X, X, X, X, - 4, 1, 5, 6, 7, X, X, X, - X, X, X, X, X, X, X, X -}; - -/* reg type q: 0, 2-7. 17. */ -static const int mips32_to_micromips_reg_q_map[] = -{ - 0, X, 2, 3, 4, 5, 6, 7, - X, X, X, X, X, X, X, X, - X, 1, X, X, X, X, X, X, - X, X, X, X, X, X, X, X -}; - -#define mips32_to_micromips_reg_n_map mips32_to_micromips_reg_m_map -#undef X - /* Map microMIPS register numbers to normal MIPS register numbers. */ #define micromips_to_32_reg_b_map mips16_to_32_reg_map @@ -838,18 +809,6 @@ static const unsigned int micromips_to_32_reg_q_map[] = 0, 17, 2, 3, 4, 5, 6, 7 }; -/* microMIPS imm type B. */ -static const int micromips_imm_b_map[] = -{ - 1, 4, 8, 12, 16, 20, 24, -1 -}; - -/* microMIPS imm type C. */ -static const int micromips_imm_c_map[] = -{ - 128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 255, 32768, 65535 -}; - /* Classifies the kind of instructions we're interested in when implementing -mfix-vr4120. */ enum fix_vr4120_class @@ -2595,19 +2554,6 @@ reglist_lookup (char **s, unsigned int types, unsigned int *reglistp) return ok && reglist != 0; } -static unsigned int -mips_lookup_reg_pair (unsigned int regno1, unsigned int regno2, - const unsigned int *map1, const unsigned int *map2, - unsigned int count) -{ - unsigned int i; - - for (i = 0; i < count; i++) - if (map1[i] == regno1 && map2[i] == regno2) - return i; - return ILLEGAL_REG; -} - /* Return TRUE if opcode MO is valid on the currently selected ISA, ASE and architecture. Use is_opcode_valid_16 for MIPS16 opcodes. */ @@ -3744,7 +3690,6 @@ mips_oddfpreg_ok (const struct mips_opcode *insn, int opnum) return FALSE; } -#if 0 /* Report that user-supplied argument ARGNUM for INSN was VAL, but should have been in the range [MIN_VAL, MAX_VAL]. PRINT_HEX says whether this operand is normally printed in hex or decimal. */ @@ -4541,7 +4486,6 @@ check_completed_insn (struct mips_arg_info *arg) as_warn (_("Used $%u with \".set at=$%u\""), AT, AT); } } -#endif /* Classify an instruction according to the FIX_VR4120_* enumeration. Return NUM_FIX_VR4120_CLASSES if the instruction isn't affected @@ -8046,13 +7990,12 @@ macro (struct mips_cl_insn *ip, char *str) if (pos > 63) { - as_bad (_("Improper position (%lu)"), (unsigned long) pos); + report_bad_range (ip, 3, pos, 0, 63, FALSE); pos = 1; } if (size == 0 || size > 64 || (pos + size - 1) > 63) { - as_bad (_("Improper extract size (%lu, position %lu)"), - (unsigned long) size, (unsigned long) pos); + report_bad_field (pos, size); size = 1; } @@ -8095,13 +8038,12 @@ macro (struct mips_cl_insn *ip, char *str) if (pos > 63) { - as_bad (_("Improper position (%lu)"), (unsigned long) pos); + report_bad_range (ip, 3, pos, 0, 63, FALSE); pos = 1; } if (size == 0 || size > 64 || (pos + size - 1) > 63) { - as_bad (_("Improper insert size (%lu, position %lu)"), - (unsigned long) size, (unsigned long) pos); + report_bad_field (pos, size); size = 1; } @@ -11501,33 +11443,6 @@ mips16_macro (struct mips_cl_insn *ip) } } -/* UDI immediates. */ -struct mips_immed { - char type; - unsigned int shift; - unsigned long mask; - const char * desc; -}; - -static const struct mips_immed mips_immed[] = { - { '1', OP_SH_UDI1, OP_MASK_UDI1, 0}, - { '2', OP_SH_UDI2, OP_MASK_UDI2, 0}, - { '3', OP_SH_UDI3, OP_MASK_UDI3, 0}, - { '4', OP_SH_UDI4, OP_MASK_UDI4, 0}, - { 0,0,0,0 } -}; - -/* Check if EXPR is a constant between MIN (inclusive) and MAX (exclusive) - taking bits from BIT up. */ -static int -expr_const_in_range (expressionS *ep, offsetT min, offsetT max, int bit) -{ - return (ep->X_op == O_constant - && (ep->X_add_number & ((1 << bit) - 1)) == 0 - && ep->X_add_number >= min << bit - && ep->X_add_number < max << bit); -} - /* Assemble an instruction into its binary format. If the instruction is a macro, set imm_expr, imm2_expr and offset_expr to the values associated with "I", "+I" and "A" operands respectively. Otherwise @@ -11548,20 +11463,12 @@ mips_ip (char *str, struct mips_cl_insn *ip) char c = 0; struct mips_opcode *insn; char *argsStart; - unsigned int regno, regno2; - unsigned int lastregno; - unsigned int destregno = 0; - unsigned int lastpos = 0; - unsigned int limlo, limhi; - int sizelo; - char *s_reset; - offsetT min_range, max_range; long opend; char *name; - int argnum; - unsigned int rtype; char *dot; long end; + const struct mips_operand *operand; + struct mips_arg_info arg; insn_error = NULL; @@ -11630,6 +11537,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) bfd_boolean delay_slot_ok; bfd_boolean size_ok; bfd_boolean ok; + bfd_boolean more_alts; gas_assert (strcmp (insn->name, name) == 0); @@ -11641,11 +11549,13 @@ mips_ip (char *str, struct mips_cl_insn *ip) firstinsn = insn; wrong_delay_slot_insns = TRUE; } + more_alts = (insn + 1 < past + && strcmp (insn[0].name, insn[1].name) == 0); if (!ok || !size_ok || delay_slot_ok != need_delay_slot_ok) { static char buf[256]; - if (insn + 1 < past && strcmp (insn->name, insn[1].name) == 0) + if (more_alts) { ++insn; continue; @@ -11685,2484 +11595,453 @@ mips_ip (char *str, struct mips_cl_insn *ip) create_insn (ip, insn); insn_error = NULL; - argnum = 1; - lastregno = 0xffffffff; + memset (&arg, 0, sizeof (arg)); + arg.insn = ip; + arg.argnum = 1; + arg.last_regno = ILLEGAL_REG; + arg.dest_regno = ILLEGAL_REG; + arg.soft_match = (more_alts + || (wrong_delay_slot_insns && need_delay_slot_ok)); for (args = insn->args;; ++args) { - int is_mdmx; - - s += strspn (s, " \t"); - is_mdmx = 0; - switch (*args) + SKIP_SPACE_TABS (s); + if (*s == 0) { - case '\0': /* end of args */ - if (*s == '\0') - return; - break; - - case '2': - /* DSP 2-bit unsigned immediate in bit 11 (for standard MIPS - code) or 14 (for microMIPS code). */ - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number != 1 - && (unsigned long) imm_expr.X_add_number != 3) - { - as_bad (_("BALIGN immediate not 1 or 3 (%lu)"), - (unsigned long) imm_expr.X_add_number); - } - INSERT_OPERAND (mips_opts.micromips, - BP, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case '3': - /* DSP 3-bit unsigned immediate in bit 21 (for standard MIPS - code) or 13 (for microMIPS code). */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_SA3 : OP_MASK_SA3); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_bad (_("DSP immediate not in range 0..%lu (%lu)"), - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - SA3, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case '4': - /* DSP 4-bit unsigned immediate in bit 21 (for standard MIPS - code) or 12 (for microMIPS code). */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_SA4 : OP_MASK_SA4); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_bad (_("DSP immediate not in range 0..%lu (%lu)"), - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - SA4, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; + /* Handle unary instructions in which only one operand is given. + The source is then the same as the destination. */ + if (arg.opnum == 1 && *args == ',') + switch (args[1]) + { + case 'r': + case 'v': + case 'w': + case 'W': + case 'V': + arg.argnum = 1; + s = argsStart; + continue; + } - case '5': - /* DSP 8-bit unsigned immediate in bit 16 (for standard MIPS - code) or 13 (for microMIPS code). */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_IMM8 : OP_MASK_IMM8); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_bad (_("DSP immediate not in range 0..%lu (%lu)"), - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - IMM8, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; + /* Treat elided base registers as $0. */ + if (strcmp (args, "(b)") == 0) + args += 3; - case '6': - /* DSP 5-bit unsigned immediate in bit 21 (for standard MIPS - code) or 16 (for microMIPS code). */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_RS : OP_MASK_RS); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_bad (_("DSP immediate not in range 0..%lu (%lu)"), - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - RS, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; + /* Fail the match if there were too few operands. */ + if (*args) + break; - case '7': - /* Four DSP accumulators in bit 11 (for standard MIPS code) - or 14 (for microMIPS code). */ - if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' - && s[3] >= '0' && s[3] <= '3') + /* Successful match. */ + if (arg.dest_regno == arg.last_regno + && strncmp (ip->insn_mo->name, "jalr", 4) == 0) { - regno = s[3] - '0'; - s += 4; - INSERT_OPERAND (mips_opts.micromips, DSPACC, *ip, regno); - continue; + if (arg.opnum == 2) + as_bad (_("Source and destination must be different")); + else if (arg.last_regno == 31) + as_bad (_("A destination register must be supplied")); } - else - as_bad (_("Invalid dsp acc register")); - break; + check_completed_insn (&arg); + return; + } - case '8': - /* DSP 6-bit unsigned immediate in bit 11 (for standard MIPS - code) or 14 (for microMIPS code). */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_WRDSP - : OP_MASK_WRDSP); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_bad (_("DSP immediate not in range 0..%lu (%lu)"), - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - WRDSP, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } + /* Fail the match if the line has too many operands. */ + if (*args == 0) + break; + + /* Handle characters that need to match exactly. */ + if (*args == '(' || *args == ')' || *args == ',') + { + if (*s != *args) + break; + if (*s == ',') + arg.argnum += 1; + ++s; continue; + } - case '9': /* Four DSP accumulators in bits 21,22. */ - gas_assert (!mips_opts.micromips); - if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' - && s[3] >= '0' && s[3] <= '3') + /* Handle special macro operands. Work out the properties of + other operands. */ + arg.opnum += 1; + arg.optional_reg = FALSE; + arg.lax_max = FALSE; + switch (*args) + { + case '+': + switch (args[1]) { - regno = s[3] - '0'; - s += 4; - INSERT_OPERAND (0, DSPACC_S, *ip, regno); + case '1': + case '2': + case '3': + case '4': + case 'B': + case 'C': + case 'F': + case 'G': + case 'H': + case 'J': + case 'Q': + case 'S': + case 's': + /* If these integer forms come last, there is no other + form of the instruction that could match. Prefer to + give detailed error messages where possible. */ + if (args[2] == 0) + arg.soft_match = FALSE; + break; + + case 'I': + /* "+I" is like "I", except that imm2_expr is used. */ + my_getExpression (&imm2_expr, s); + if (imm2_expr.X_op != O_big + && imm2_expr.X_op != O_constant) + insn_error = _("absolute expression required"); + if (HAVE_32BIT_GPRS) + normalize_constant_expr (&imm2_expr); + s = expr_end; + ++args; continue; + + case 'i': + *offset_reloc = BFD_RELOC_MIPS_JMP; + break; } - else - as_bad (_("Invalid dsp acc register")); break; + case '\'': + case ':': + case '@': + case '^': + case '$': + case '\\': + case '%': + case '|': case '0': - /* DSP 6-bit signed immediate in bit 20 (for standard MIPS - code) or 16 (for microMIPS code). */ - { - long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_DSPSFT : OP_MASK_DSPSFT); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - min_range = -((mask + 1) >> 1); - max_range = ((mask + 1) >> 1) - 1; - if (imm_expr.X_add_number < min_range - || imm_expr.X_add_number > max_range) - as_bad (_("DSP immediate not in range %ld..%ld (%ld)"), - (long) min_range, (long) max_range, - (long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - DSPSFT, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case '\'': /* DSP 6-bit unsigned immediate in bit 16. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if (imm_expr.X_add_number & ~OP_MASK_RDDSP) - { - as_bad (_("DSP immediate not in range 0..%d (%lu)"), - OP_MASK_RDDSP, - (unsigned long) imm_expr.X_add_number); - } - INSERT_OPERAND (0, RDDSP, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case ':': /* DSP 7-bit signed immediate in bit 19. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - min_range = -((OP_MASK_DSPSFT_7 + 1) >> 1); - max_range = ((OP_MASK_DSPSFT_7 + 1) >> 1) - 1; - if (imm_expr.X_add_number < min_range || - imm_expr.X_add_number > max_range) - { - as_bad (_("DSP immediate not in range %ld..%ld (%ld)"), - (long) min_range, (long) max_range, - (long) imm_expr.X_add_number); - } - INSERT_OPERAND (0, DSPSFT_7, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case '@': /* DSP 10-bit signed immediate in bit 16. */ - { - long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_IMM10 : OP_MASK_IMM10); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - min_range = -((mask + 1) >> 1); - max_range = ((mask + 1) >> 1) - 1; - if (imm_expr.X_add_number < min_range - || imm_expr.X_add_number > max_range) - as_bad (_("DSP immediate not in range %ld..%ld (%ld)"), - (long) min_range, (long) max_range, - (long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - IMM10, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case '^': /* DSP 5-bit unsigned immediate in bit 11. */ - gas_assert (mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if (imm_expr.X_add_number & ~MICROMIPSOP_MASK_RD) - as_bad (_("DSP immediate not in range 0..%d (%lu)"), - MICROMIPSOP_MASK_RD, - (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (1, RD, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '8': + case 'B': + case 'C': + case 'J': + case 'O': + case 'P': + case 'Q': + case 'c': + case 'h': + case 'q': + /* If these integer forms come last, there is no other + form of the instruction that could match. Prefer to + give detailed error messages where possible. */ + if (args[1] == 0) + arg.soft_match = FALSE; + break; - case '!': /* MT usermode flag bit. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if (imm_expr.X_add_number & ~OP_MASK_MT_U) - as_bad (_("MT usermode bit not 0 or 1 (%lu)"), - (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (0, MT_U, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; + case 'r': + case 'v': + case 'w': + case 'W': + case 'V': + /* We have already matched a comma by this point, so the register + is only optional if there is another operand to come. */ + gas_assert (arg.opnum == 2); + arg.optional_reg = (args[1] == ','); + break; - case '$': /* MT load high flag bit. */ - gas_assert (!mips_opts.micromips); + case 'I': my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if (imm_expr.X_add_number & ~OP_MASK_MT_H) - as_bad (_("MT load high bit not 0 or 1 (%lu)"), - (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (0, MT_H, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; + if (imm_expr.X_op != O_big + && imm_expr.X_op != O_constant) + insn_error = _("absolute expression required"); + if (HAVE_32BIT_GPRS) + normalize_constant_expr (&imm_expr); s = expr_end; continue; - case '*': /* Four DSP accumulators in bits 18,19. */ - gas_assert (!mips_opts.micromips); - if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && - s[3] >= '0' && s[3] <= '3') + case 'A': + my_getSmallExpression (&offset_expr, offset_reloc, s); + if (offset_expr.X_op == O_register) { - regno = s[3] - '0'; - s += 4; - INSERT_OPERAND (0, MTACC_T, *ip, regno); - continue; + /* Assume that the offset has been elided and that what + we saw was a base register. The match will fail later + if that assumption turns out to be wrong. */ + offset_expr.X_op = O_constant; + offset_expr.X_add_number = 0; } else - as_bad (_("Invalid dsp/smartmips acc register")); - break; - - case '&': /* Four DSP accumulators in bits 13,14. */ - gas_assert (!mips_opts.micromips); - if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && - s[3] >= '0' && s[3] <= '3') { - regno = s[3] - '0'; - s += 4; - INSERT_OPERAND (0, MTACC_D, *ip, regno); - continue; + normalize_address_expr (&offset_expr); + s = expr_end; } - else - as_bad (_("Invalid dsp/smartmips acc register")); - break; + continue; - case '\\': /* 3-bit bit position. */ + case 'F': + case 'L': + case 'f': + case 'l': { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_3BITPOS - : OP_MASK_3BITPOS); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_warn (_("Bit position for %s not in range 0..%lu (%lu)"), - ip->insn_mo->name, - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - 3BITPOS, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; + int f64; + int using_gprs; + char *save_in; + char *err; + unsigned char temp[8]; + int len; + unsigned int length; + segT seg; + subsegT subseg; + char *p; - case ',': - ++argnum; - if (*s++ == *args) - continue; - s--; - switch (*++args) - { - case 'r': - case 'v': - INSERT_OPERAND (mips_opts.micromips, RS, *ip, lastregno); - continue; + /* These only appear as the last operand in an + instruction, and every instruction that accepts + them in any variant accepts them in all variants. + This means we don't have to worry about backing out + any changes if the instruction does not match. - case 'w': - INSERT_OPERAND (mips_opts.micromips, RT, *ip, lastregno); - continue; + The difference between them is the size of the + floating point constant and where it goes. For 'F' + and 'L' the constant is 64 bits; for 'f' and 'l' it + is 32 bits. Where the constant is placed is based + on how the MIPS assembler does things: + F -- .rdata + L -- .lit8 + f -- immediate value + l -- .lit4 - case 'W': - gas_assert (!mips_opts.micromips); - INSERT_OPERAND (0, FT, *ip, lastregno); - continue; + The .lit4 and .lit8 sections are only used if + permitted by the -G argument. - case 'V': - INSERT_OPERAND (mips_opts.micromips, FS, *ip, lastregno); - continue; - } - break; + The code below needs to know whether the target register + is 32 or 64 bits wide. It relies on the fact 'f' and + 'F' are used with GPR-based instructions and 'l' and + 'L' are used with FPR-based instructions. */ - case '(': - /* Handle optional base register. - Either the base register is omitted or - we must have a left paren. */ - /* This is dependent on the next operand specifier - is a base register specification. */ - gas_assert (args[1] == 'b' - || (mips_opts.micromips - && args[1] == 'm' - && (args[2] == 'l' || args[2] == 'n' - || args[2] == 's' || args[2] == 'a'))); - if (*s == '\0' && args[1] == 'b') - return; - /* Fall through. */ - - case ')': /* These must match exactly. */ - if (*s++ == *args) - continue; - break; - - case '+': /* Opcode extension character. */ - switch (*++args) - { - case '1': /* UDI immediates. */ - case '2': - case '3': - case '4': - gas_assert (!mips_opts.micromips); - { - const struct mips_immed *imm = mips_immed; - - while (imm->type && imm->type != *args) - ++imm; - if (! imm->type) - abort (); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number & ~imm->mask) - { - as_warn (_("Illegal %s number (%lu, 0x%lx)"), - imm->desc ? imm->desc : ip->insn_mo->name, - (unsigned long) imm_expr.X_add_number, - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= imm->mask; - } - ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number - << imm->shift); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case 'J': /* 10-bit hypcall code. */ - gas_assert (!mips_opts.micromips); - { - unsigned long mask = OP_MASK_CODE10; - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_warn (_("Code for %s not in range 0..%lu (%lu)"), - ip->insn_mo->name, - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (0, CODE10, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case 'A': /* ins/ext position, becomes LSB. */ - limlo = 0; - limhi = 31; - goto do_lsb; - case 'E': - limlo = 32; - limhi = 63; - goto do_lsb; - do_lsb: - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number < limlo - || (unsigned long) imm_expr.X_add_number > limhi) - { - as_bad (_("Improper position (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number = limlo; - } - lastpos = imm_expr.X_add_number; - INSERT_OPERAND (mips_opts.micromips, - EXTLSB, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'B': /* ins size, becomes MSB. */ - limlo = 1; - limhi = 32; - goto do_msb; - case 'F': - limlo = 33; - limhi = 64; - goto do_msb; - do_msb: - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - /* Check for negative input so that small negative numbers - will not succeed incorrectly. The checks against - (pos+size) transitively check "size" itself, - assuming that "pos" is reasonable. */ - if ((long) imm_expr.X_add_number < 0 - || ((unsigned long) imm_expr.X_add_number - + lastpos) < limlo - || ((unsigned long) imm_expr.X_add_number - + lastpos) > limhi) - { - as_bad (_("Improper insert size (%lu, position %lu)"), - (unsigned long) imm_expr.X_add_number, - (unsigned long) lastpos); - imm_expr.X_add_number = limlo - lastpos; - } - INSERT_OPERAND (mips_opts.micromips, INSMSB, *ip, - lastpos + imm_expr.X_add_number - 1); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'C': /* ext size, becomes MSBD. */ - limlo = 1; - limhi = 32; - sizelo = 1; - goto do_msbd; - case 'G': - limlo = 33; - limhi = 64; - sizelo = 33; - goto do_msbd; - case 'H': - limlo = 33; - limhi = 64; - sizelo = 1; - goto do_msbd; - do_msbd: - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - /* The checks against (pos+size) don't transitively check - "size" itself, assuming that "pos" is reasonable. - We also need to check the lower bound of "size". */ - if ((long) imm_expr.X_add_number < sizelo - || ((unsigned long) imm_expr.X_add_number - + lastpos) < limlo - || ((unsigned long) imm_expr.X_add_number - + lastpos) > limhi) - { - as_bad (_("Improper extract size (%lu, position %lu)"), - (unsigned long) imm_expr.X_add_number, - (unsigned long) lastpos); - imm_expr.X_add_number = limlo - lastpos; - } - INSERT_OPERAND (mips_opts.micromips, - EXTMSBD, *ip, imm_expr.X_add_number - 1); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'I': - /* "+I" is like "I", except that imm2_expr is used. */ - my_getExpression (&imm2_expr, s); - if (imm2_expr.X_op != O_big - && imm2_expr.X_op != O_constant) - insn_error = _("absolute expression required"); - if (HAVE_32BIT_GPRS) - normalize_constant_expr (&imm2_expr); - s = expr_end; - continue; - - case 't': /* Coprocessor register number. */ - gas_assert (!mips_opts.micromips); - if (s[0] == '$' && ISDIGIT (s[1])) - { - ++s; - regno = 0; - do - { - regno *= 10; - regno += *s - '0'; - ++s; - } - while (ISDIGIT (*s)); - if (regno > 31) - as_bad (_("Invalid register number (%d)"), regno); - else - { - INSERT_OPERAND (0, RT, *ip, regno); - continue; - } - } - else - as_bad (_("Invalid coprocessor 0 register number")); - break; - - case 'x': - /* bbit[01] and bbit[01]32 bit index. Give error if index - is not in the valid range. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned) imm_expr.X_add_number > 31) - { - as_bad (_("Improper bit index (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number = 0; - } - INSERT_OPERAND (0, BBITIND, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'X': - /* bbit[01] bit index when bbit is used but we generate - bbit[01]32 because the index is over 32. Move to the - next candidate if index is not in the valid range. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned) imm_expr.X_add_number < 32 - || (unsigned) imm_expr.X_add_number > 63) - break; - INSERT_OPERAND (0, BBITIND, *ip, imm_expr.X_add_number - 32); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'p': - /* cins, cins32, exts and exts32 position field. Give error - if it's not in the valid range. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned) imm_expr.X_add_number > 31) - { - as_bad (_("Improper position (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number = 0; - } - lastpos = imm_expr.X_add_number; - INSERT_OPERAND (0, CINSPOS, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'P': - /* cins, cins32, exts and exts32 position field. Move to - the next candidate if it's not in the valid range. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned) imm_expr.X_add_number < 32 - || (unsigned) imm_expr.X_add_number > 63) - break; - lastpos = imm_expr.X_add_number; - INSERT_OPERAND (0, CINSPOS, *ip, imm_expr.X_add_number - 32); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 's': - /* cins32 and exts32 length-minus-one field. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > 31 - || (unsigned long) imm_expr.X_add_number + lastpos > 31) - { - as_bad (_("Improper size (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number = 0; - } - INSERT_OPERAND (0, CINSLM1, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'S': - /* cins/exts length-minus-one field. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > 31 - || (unsigned long) imm_expr.X_add_number + lastpos > 63) - { - as_bad (_("Improper size (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number = 0; - } - INSERT_OPERAND (0, CINSLM1, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'Q': - /* seqi/snei immediate field. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((long) imm_expr.X_add_number < -512 - || (long) imm_expr.X_add_number >= 512) - { - as_bad (_("Improper immediate (%ld)"), - (long) imm_expr.X_add_number); - imm_expr.X_add_number = 0; - } - INSERT_OPERAND (0, SEQI, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'a': /* 8-bit signed offset in bit 6 */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - min_range = -((OP_MASK_OFFSET_A + 1) >> 1); - max_range = ((OP_MASK_OFFSET_A + 1) >> 1) - 1; - if (imm_expr.X_add_number < min_range - || imm_expr.X_add_number > max_range) - { - as_bad (_("Offset not in range %ld..%ld (%ld)"), - (long) min_range, (long) max_range, - (long) imm_expr.X_add_number); - } - INSERT_OPERAND (0, OFFSET_A, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'b': /* 8-bit signed offset in bit 3 */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - min_range = -((OP_MASK_OFFSET_B + 1) >> 1); - max_range = ((OP_MASK_OFFSET_B + 1) >> 1) - 1; - if (imm_expr.X_add_number < min_range - || imm_expr.X_add_number > max_range) - { - as_bad (_("Offset not in range %ld..%ld (%ld)"), - (long) min_range, (long) max_range, - (long) imm_expr.X_add_number); - } - INSERT_OPERAND (0, OFFSET_B, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'c': /* 9-bit signed offset in bit 6 */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - min_range = -((OP_MASK_OFFSET_C + 1) >> 1); - max_range = ((OP_MASK_OFFSET_C + 1) >> 1) - 1; - /* We check the offset range before adjusted. */ - min_range <<= 4; - max_range <<= 4; - if (imm_expr.X_add_number < min_range - || imm_expr.X_add_number > max_range) - { - as_bad (_("Offset not in range %ld..%ld (%ld)"), - (long) min_range, (long) max_range, - (long) imm_expr.X_add_number); - } - if (imm_expr.X_add_number & 0xf) - { - as_bad (_("Offset not 16 bytes alignment (%ld)"), - (long) imm_expr.X_add_number); - } - /* Right shift 4 bits to adjust the offset operand. */ - INSERT_OPERAND (0, OFFSET_C, *ip, - imm_expr.X_add_number >> 4); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'z': - gas_assert (!mips_opts.micromips); - if (!reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no)) - break; - if (regno == AT && mips_opts.at) - { - if (mips_opts.at == ATREG) - as_warn (_("used $at without \".set noat\"")); - else - as_warn (_("used $%u with \".set at=$%u\""), - regno, mips_opts.at); - } - INSERT_OPERAND (0, RZ, *ip, regno); - continue; - - case 'Z': - gas_assert (!mips_opts.micromips); - if (!reg_lookup (&s, RTYPE_FPU, ®no)) - break; - INSERT_OPERAND (0, FZ, *ip, regno); - continue; - - case 'i': - goto jump; - - case 'j': - { - int shift = 8; - size_t i; - bfd_reloc_code_real_type r[3]; - - /* Check whether there is only a single bracketed expression - left. If so, it must be the base register and the - constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) - continue; - - /* If this value won't fit into the offset, then go find - a macro that will generate a 16- or 32-bit offset code - pattern. */ - i = my_getSmallExpression (&imm_expr, r, s); - if ((i == 0 && (imm_expr.X_op != O_constant - || imm_expr.X_add_number >= 1 << shift - || imm_expr.X_add_number < -1 << shift)) - || i > 0) - { - imm_expr.X_op = O_absent; - break; - } - INSERT_OPERAND (mips_opts.micromips, EVAOFFSET, *ip, - imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - default: - as_bad (_("Internal error: bad %s opcode " - "(unknown extension operand type `+%c'): %s %s"), - mips_opts.micromips ? "microMIPS" : "MIPS", - *args, insn->name, insn->args); - /* Further processing is fruitless. */ - return; - } - break; - - case '.': /* 10-bit offset. */ - gas_assert (mips_opts.micromips); - case '~': /* 12-bit offset. */ - { - int shift = *args == '.' ? 9 : 11; - size_t i; - bfd_reloc_code_real_type r[3]; - - /* Check whether there is only a single bracketed expression - left. If so, it must be the base register and the - constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) - continue; - - /* If this value won't fit into the offset, then go find - a macro that will generate a 16- or 32-bit offset code - pattern. */ - i = my_getSmallExpression (&imm_expr, r, s); - if ((i == 0 && (imm_expr.X_op != O_constant - || imm_expr.X_add_number >= 1 << shift - || imm_expr.X_add_number < -1 << shift)) - || i > 0) - { - imm_expr.X_op = O_absent; - break; - } - if (shift == 9) - INSERT_OPERAND (1, OFFSET10, *ip, imm_expr.X_add_number); - else - INSERT_OPERAND (mips_opts.micromips, - OFFSET12, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case '<': /* must be at least one digit */ - /* - * According to the manual, if the shift amount is greater - * than 31 or less than 0, then the shift amount should be - * mod 32. In reality the mips assembler issues an error. - * We issue a warning and mask out all but the low 5 bits. - */ - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > 31) - as_warn (_("Improper shift amount (%lu)"), - (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - SHAMT, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case '>': /* shift amount minus 32 */ - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number < 32 - || (unsigned long) imm_expr.X_add_number > 63) - break; - INSERT_OPERAND (mips_opts.micromips, - SHAMT, *ip, imm_expr.X_add_number - 32); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'k': /* CACHE code. */ - case 'h': /* PREFX code. */ - case '1': /* SYNC type. */ - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > 31) - as_warn (_("Invalid value for `%s' (%lu)"), - ip->insn_mo->name, - (unsigned long) imm_expr.X_add_number); - switch (*args) - { - case 'k': - if (mips_fix_cn63xxp1 - && !mips_opts.micromips - && strcmp ("pref", insn->name) == 0) - switch (imm_expr.X_add_number) - { - case 5: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: /* These are ok. */ - break; - - default: /* The rest must be changed to 28. */ - imm_expr.X_add_number = 28; - break; - } - INSERT_OPERAND (mips_opts.micromips, - CACHE, *ip, imm_expr.X_add_number); - break; - case 'h': - INSERT_OPERAND (mips_opts.micromips, - PREFX, *ip, imm_expr.X_add_number); - break; - case '1': - INSERT_OPERAND (mips_opts.micromips, - STYPE, *ip, imm_expr.X_add_number); - break; - } - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'c': /* BREAK code. */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_CODE - : OP_MASK_CODE); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_warn (_("Code for %s not in range 0..%lu (%lu)"), - ip->insn_mo->name, - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - CODE, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case 'q': /* Lower BREAK code. */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_CODE2 - : OP_MASK_CODE2); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_warn (_("Lower code for %s not in range 0..%lu (%lu)"), - ip->insn_mo->name, - mask, (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - CODE2, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case 'B': /* 20- or 10-bit syscall/break/wait code. */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_CODE10 - : OP_MASK_CODE20); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_warn (_("Code for %s not in range 0..%lu (%lu)"), - ip->insn_mo->name, - mask, (unsigned long) imm_expr.X_add_number); - if (mips_opts.micromips) - INSERT_OPERAND (1, CODE10, *ip, imm_expr.X_add_number); - else - INSERT_OPERAND (0, CODE20, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case 'C': /* 25- or 23-bit coprocessor code. */ - { - unsigned long mask = (mips_opts.micromips - ? MICROMIPSOP_MASK_COPZ - : OP_MASK_COPZ); - - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > mask) - as_warn (_("Coproccesor code > %u bits (%lu)"), - mips_opts.micromips ? 23U : 25U, - (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (mips_opts.micromips, - COPZ, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - } - continue; - - case 'J': /* 19-bit WAIT code. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE19) - { - as_warn (_("Illegal 19-bit code (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= OP_MASK_CODE19; - } - INSERT_OPERAND (0, CODE19, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'P': /* Performance register. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1) - as_warn (_("Invalid performance register (%lu)"), - (unsigned long) imm_expr.X_add_number); - if (imm_expr.X_add_number != 0 && mips_opts.arch == CPU_R5900 - && (!strcmp(insn->name,"mfps") || !strcmp(insn->name,"mtps"))) - as_warn (_("Invalid performance register (%lu)"), - (unsigned long) imm_expr.X_add_number); - INSERT_OPERAND (0, PERFREG, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'G': /* Coprocessor destination register. */ - { - unsigned long opcode = ip->insn_opcode; - unsigned long mask; - unsigned int types; - int cop0; - - if (mips_opts.micromips) - { - mask = ~((MICROMIPSOP_MASK_RT << MICROMIPSOP_SH_RT) - | (MICROMIPSOP_MASK_RS << MICROMIPSOP_SH_RS) - | (MICROMIPSOP_MASK_SEL << MICROMIPSOP_SH_SEL)); - opcode &= mask; - switch (opcode) - { - case 0x000000fc: /* mfc0 */ - case 0x000002fc: /* mtc0 */ - case 0x580000fc: /* dmfc0 */ - case 0x580002fc: /* dmtc0 */ - cop0 = 1; - break; - default: - cop0 = 0; - break; - } - } - else - { - opcode = (opcode >> OP_SH_OP) & OP_MASK_OP; - cop0 = opcode == OP_OP_COP0; - } - types = RTYPE_NUM | (cop0 ? RTYPE_CP0 : RTYPE_GP); - ok = reg_lookup (&s, types, ®no); - if (mips_opts.micromips) - INSERT_OPERAND (1, RS, *ip, regno); - else - INSERT_OPERAND (0, RD, *ip, regno); - if (ok) - { - lastregno = regno; - continue; - } - } - break; - - case 'y': /* ALNV.PS source register. */ - gas_assert (mips_opts.micromips); - goto do_reg; - case 'x': /* Ignore register name. */ - case 'U': /* Destination register (CLO/CLZ). */ - case 'g': /* Coprocessor destination register. */ - gas_assert (!mips_opts.micromips); - case 'b': /* Base register. */ - case 'd': /* Destination register. */ - case 's': /* Source register. */ - case 't': /* Target register. */ - case 'r': /* Both target and source. */ - case 'v': /* Both dest and source. */ - case 'w': /* Both dest and target. */ - case 'E': /* Coprocessor target register. */ - case 'K': /* RDHWR destination register. */ - case 'z': /* Must be zero register. */ - do_reg: - s_reset = s; - if (*args == 'E' || *args == 'K') - ok = reg_lookup (&s, RTYPE_NUM, ®no); - else - { - ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no); - if (regno == AT && mips_opts.at) - { - if (mips_opts.at == ATREG) - as_warn (_("Used $at without \".set noat\"")); - else - as_warn (_("Used $%u with \".set at=$%u\""), - regno, mips_opts.at); - } - } - if (ok) - { - c = *args; - if (*s == ' ') - ++s; - if (args[1] != *s) - { - if (c == 'r' || c == 'v' || c == 'w') - { - regno = lastregno; - s = s_reset; - ++args; - } - } - /* 'z' only matches $0. */ - if (c == 'z' && regno != 0) - break; - - if (c == 's' && !strncmp (ip->insn_mo->name, "jalr", 4)) - { - if (regno == lastregno) - { - insn_error - = _("Source and destination must be different"); - continue; - } - if (regno == 31 && lastregno == 0xffffffff) - { - insn_error - = _("A destination register must be supplied"); - continue; - } - } - /* Now that we have assembled one operand, we use the args - string to figure out where it goes in the instruction. */ - switch (c) - { - case 'r': - case 's': - case 'v': - case 'b': - INSERT_OPERAND (mips_opts.micromips, RS, *ip, regno); - break; - - case 'K': - if (mips_opts.micromips) - INSERT_OPERAND (1, RS, *ip, regno); - else - INSERT_OPERAND (0, RD, *ip, regno); - break; - - case 'd': - case 'g': - INSERT_OPERAND (mips_opts.micromips, RD, *ip, regno); - break; - - case 'U': - gas_assert (!mips_opts.micromips); - INSERT_OPERAND (0, RD, *ip, regno); - INSERT_OPERAND (0, RT, *ip, regno); - break; - - case 'w': - case 't': - case 'E': - INSERT_OPERAND (mips_opts.micromips, RT, *ip, regno); - break; - - case 'y': - gas_assert (mips_opts.micromips); - INSERT_OPERAND (1, RS3, *ip, regno); - break; - - case 'x': - /* This case exists because on the r3000 trunc - expands into a macro which requires a gp - register. On the r6000 or r4000 it is - assembled into a single instruction which - ignores the register. Thus the insn version - is MIPS_ISA2 and uses 'x', and the macro - version is MIPS_ISA1 and uses 't'. */ - break; - - case 'z': - /* This case is for the div instruction, which - acts differently if the destination argument - is $0. This only matches $0, and is checked - outside the switch. */ - break; - } - lastregno = regno; - continue; - } - switch (*args++) - { - case 'r': - case 'v': - INSERT_OPERAND (mips_opts.micromips, RS, *ip, lastregno); - continue; - - case 'w': - INSERT_OPERAND (mips_opts.micromips, RT, *ip, lastregno); - continue; - } - break; - - case 'O': /* MDMX alignment immediate constant. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > OP_MASK_ALN) - as_warn (_("Improper align amount (%ld), using low bits"), - (long) imm_expr.X_add_number); - INSERT_OPERAND (0, ALN, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'Q': /* MDMX vector, element sel, or const. */ - if (s[0] != '$') - { - /* MDMX Immediate. */ - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > OP_MASK_FT) - as_warn (_("Invalid MDMX Immediate (%ld)"), - (long) imm_expr.X_add_number); - INSERT_OPERAND (0, FT, *ip, imm_expr.X_add_number); - if (ip->insn_opcode & (OP_MASK_VSEL << OP_SH_VSEL)) - ip->insn_opcode |= MDMX_FMTSEL_IMM_QH << OP_SH_VSEL; - else - ip->insn_opcode |= MDMX_FMTSEL_IMM_OB << OP_SH_VSEL; - imm_expr.X_op = O_absent; - s = expr_end; - continue; - } - /* Not MDMX Immediate. Fall through. */ - case 'X': /* MDMX destination register. */ - case 'Y': /* MDMX source register. */ - case 'Z': /* MDMX target register. */ - is_mdmx = !(insn->membership & INSN_5400); - case 'W': - gas_assert (!mips_opts.micromips); - case 'D': /* Floating point destination register. */ - case 'S': /* Floating point source register. */ - case 'T': /* Floating point target register. */ - case 'R': /* Floating point source register. */ - case 'V': - rtype = RTYPE_FPU; - if (is_mdmx - || ((mips_opts.ase & ASE_MDMX) - && (ip->insn_mo->pinfo & FP_D) - && (ip->insn_mo->pinfo & (INSN_COPROC_MOVE_DELAY - | INSN_COPROC_MEMORY_DELAY - | INSN_LOAD_COPROC_DELAY - | INSN_LOAD_MEMORY_DELAY - | INSN_STORE_MEMORY)))) - rtype |= RTYPE_VEC; - s_reset = s; - if (reg_lookup (&s, rtype, ®no)) - { - if ((regno & 1) != 0 - && HAVE_32BIT_FPRS - && !mips_oddfpreg_ok (ip->insn_mo, argnum)) - as_warn (_("Float register should be even, was %d"), - regno); - - c = *args; - if (*s == ' ') - ++s; - if (args[1] != *s) - { - if (c == 'V' || c == 'W') - { - regno = lastregno; - s = s_reset; - ++args; - } - } - switch (c) - { - case 'D': - case 'X': - INSERT_OPERAND (mips_opts.micromips, FD, *ip, regno); - break; - - case 'V': - case 'S': - case 'Y': - INSERT_OPERAND (mips_opts.micromips, FS, *ip, regno); - break; - - case 'Q': - /* This is like 'Z', but also needs to fix the MDMX - vector/scalar select bits. Note that the - scalar immediate case is handled above. */ - if ((ip->insn_mo->membership & INSN_5400) - && strcmp (insn->name, "rzu.ob") == 0) - as_bad (_("Operand %d of `%s' must be an immediate"), - argnum, ip->insn_mo->name); - - if (*s == '[') - { - int is_qh = (ip->insn_opcode & (1 << OP_SH_VSEL)); - int max_el = (is_qh ? 3 : 7); - s++; - my_getExpression(&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - s = expr_end; - if (imm_expr.X_add_number > max_el) - as_bad (_("Bad element selector %ld"), - (long) imm_expr.X_add_number); - imm_expr.X_add_number &= max_el; - ip->insn_opcode |= (imm_expr.X_add_number - << (OP_SH_VSEL + - (is_qh ? 2 : 1))); - imm_expr.X_op = O_absent; - if (*s != ']') - as_warn (_("Expecting ']' found '%s'"), s); - else - s++; - } - else - { - if ((ip->insn_mo->membership & INSN_5400) - && (strcmp (insn->name, "sll.ob") == 0 - || strcmp (insn->name, "srl.ob") == 0)) - as_bad (_("Operand %d of `%s' must be scalar"), - argnum, ip->insn_mo->name); - - if (ip->insn_opcode & (OP_MASK_VSEL << OP_SH_VSEL)) - ip->insn_opcode |= (MDMX_FMTSEL_VEC_QH - << OP_SH_VSEL); - else - ip->insn_opcode |= (MDMX_FMTSEL_VEC_OB << - OP_SH_VSEL); - } - /* Fall through. */ - case 'W': - case 'T': - case 'Z': - INSERT_OPERAND (mips_opts.micromips, FT, *ip, regno); - break; - - case 'R': - INSERT_OPERAND (mips_opts.micromips, FR, *ip, regno); - break; - } - lastregno = regno; - continue; - } - - switch (*args++) - { - case 'V': - INSERT_OPERAND (mips_opts.micromips, FS, *ip, lastregno); - continue; - - case 'W': - INSERT_OPERAND (mips_opts.micromips, FT, *ip, lastregno); - continue; - } - break; - - case 'I': - my_getExpression (&imm_expr, s); - if (imm_expr.X_op != O_big - && imm_expr.X_op != O_constant) - insn_error = _("absolute expression required"); - if (HAVE_32BIT_GPRS) - normalize_constant_expr (&imm_expr); - s = expr_end; - continue; - - case 'A': - my_getSmallExpression (&offset_expr, offset_reloc, s); - if (offset_expr.X_op == O_register) - { - /* Assume that the offset has been elided and that what - we saw was a base register. The match will fail later - if that assumption turns out to be wrong. */ - offset_expr.X_op = O_constant; - offset_expr.X_add_number = 0; - } - else - { - normalize_address_expr (&offset_expr); - s = expr_end; - } - continue; - - case 'F': - case 'L': - case 'f': - case 'l': - { - int f64; - int using_gprs; - char *save_in; - char *err; - unsigned char temp[8]; - int len; - unsigned int length; - segT seg; - subsegT subseg; - char *p; - - /* These only appear as the last operand in an - instruction, and every instruction that accepts - them in any variant accepts them in all variants. - This means we don't have to worry about backing out - any changes if the instruction does not match. - - The difference between them is the size of the - floating point constant and where it goes. For 'F' - and 'L' the constant is 64 bits; for 'f' and 'l' it - is 32 bits. Where the constant is placed is based - on how the MIPS assembler does things: - F -- .rdata - L -- .lit8 - f -- immediate value - l -- .lit4 - - The .lit4 and .lit8 sections are only used if - permitted by the -G argument. - - The code below needs to know whether the target register - is 32 or 64 bits wide. It relies on the fact 'f' and - 'F' are used with GPR-based instructions and 'l' and - 'L' are used with FPR-based instructions. */ - - f64 = *args == 'F' || *args == 'L'; - using_gprs = *args == 'F' || *args == 'f'; - - save_in = input_line_pointer; - input_line_pointer = s; - err = md_atof (f64 ? 'd' : 'f', (char *) temp, &len); - length = len; - s = input_line_pointer; - input_line_pointer = save_in; - if (err != NULL && *err != '\0') - { - as_bad (_("Bad floating point constant: %s"), err); - memset (temp, '\0', sizeof temp); - length = f64 ? 8 : 4; - } - - gas_assert (length == (unsigned) (f64 ? 8 : 4)); - - if (*args == 'f' - || (*args == 'l' - && (g_switch_value < 4 - || (temp[0] == 0 && temp[1] == 0) - || (temp[2] == 0 && temp[3] == 0)))) - { - imm_expr.X_op = O_constant; - if (!target_big_endian) - imm_expr.X_add_number = bfd_getl32 (temp); - else - imm_expr.X_add_number = bfd_getb32 (temp); - } - else if (length > 4 - && !mips_disable_float_construction - /* Constants can only be constructed in GPRs and - copied to FPRs if the GPRs are at least as wide - as the FPRs. Force the constant into memory if - we are using 64-bit FPRs but the GPRs are only - 32 bits wide. */ - && (using_gprs - || !(HAVE_64BIT_FPRS && HAVE_32BIT_GPRS)) - && ((temp[0] == 0 && temp[1] == 0) - || (temp[2] == 0 && temp[3] == 0)) - && ((temp[4] == 0 && temp[5] == 0) - || (temp[6] == 0 && temp[7] == 0))) - { - /* The value is simple enough to load with a couple of - instructions. If using 32-bit registers, set - imm_expr to the high order 32 bits and offset_expr to - the low order 32 bits. Otherwise, set imm_expr to - the entire 64 bit constant. */ - if (using_gprs ? HAVE_32BIT_GPRS : HAVE_32BIT_FPRS) - { - imm_expr.X_op = O_constant; - offset_expr.X_op = O_constant; - if (!target_big_endian) - { - imm_expr.X_add_number = bfd_getl32 (temp + 4); - offset_expr.X_add_number = bfd_getl32 (temp); - } - else - { - imm_expr.X_add_number = bfd_getb32 (temp); - offset_expr.X_add_number = bfd_getb32 (temp + 4); - } - if (offset_expr.X_add_number == 0) - offset_expr.X_op = O_absent; - } - else - { - imm_expr.X_op = O_constant; - if (!target_big_endian) - imm_expr.X_add_number = bfd_getl64 (temp); - else - imm_expr.X_add_number = bfd_getb64 (temp); - } - } - else - { - const char *newname; - segT new_seg; - - /* Switch to the right section. */ - seg = now_seg; - subseg = now_subseg; - switch (*args) - { - default: /* unused default case avoids warnings. */ - case 'L': - newname = RDATA_SECTION_NAME; - if (g_switch_value >= 8) - newname = ".lit8"; - break; - case 'F': - newname = RDATA_SECTION_NAME; - break; - case 'l': - gas_assert (g_switch_value >= 4); - newname = ".lit4"; - break; - } - new_seg = subseg_new (newname, (subsegT) 0); - bfd_set_section_flags (stdoutput, new_seg, - (SEC_ALLOC - | SEC_LOAD - | SEC_READONLY - | SEC_DATA)); - frag_align (*args == 'l' ? 2 : 3, 0, 0); - if (strncmp (TARGET_OS, "elf", 3) != 0) - record_alignment (new_seg, 4); - else - record_alignment (new_seg, *args == 'l' ? 2 : 3); - if (seg == now_seg) - as_bad (_("Can't use floating point insn in this section")); - - /* Set the argument to the current address in the - section. */ - offset_expr.X_op = O_symbol; - offset_expr.X_add_symbol = symbol_temp_new_now (); - offset_expr.X_add_number = 0; - - /* Put the floating point number into the section. */ - p = frag_more ((int) length); - memcpy (p, temp, length); - - /* Switch back to the original section. */ - subseg_set (seg, subseg); - } - } - continue; - - case 'i': /* 16-bit unsigned immediate. */ - case 'j': /* 16-bit signed immediate. */ - *offset_reloc = BFD_RELOC_LO16; - if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0) - { - int more; - offsetT minval, maxval; - - more = (insn + 1 < past - && strcmp (insn->name, insn[1].name) == 0); - - /* For compatibility with older assemblers, we accept - 0x8000-0xffff as signed 16-bit numbers when only - signed numbers are allowed. */ - if (*args == 'i') - minval = 0, maxval = 0xffff; - else if (more) - minval = -0x8000, maxval = 0x7fff; - else - minval = -0x8000, maxval = 0xffff; - - if (offset_expr.X_op != O_constant - || offset_expr.X_add_number < minval - || offset_expr.X_add_number > maxval) - { - if (more) - break; - if (offset_expr.X_op == O_constant - || offset_expr.X_op == O_big) - as_bad (_("Expression out of range")); - } - } - s = expr_end; - continue; - - case 'o': /* 16-bit offset. */ - offset_reloc[0] = BFD_RELOC_LO16; - offset_reloc[1] = BFD_RELOC_UNUSED; - offset_reloc[2] = BFD_RELOC_UNUSED; - - /* Check whether there is only a single bracketed expression - left. If so, it must be the base register and the - constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) - { - offset_expr.X_op = O_constant; - offset_expr.X_add_number = 0; - continue; - } - - /* If this value won't fit into a 16 bit offset, then go - find a macro that will generate the 32 bit offset - code pattern. */ - if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0 - && (offset_expr.X_op != O_constant - || offset_expr.X_add_number >= 0x8000 - || offset_expr.X_add_number < -0x8000)) - break; - - s = expr_end; - continue; - - case 'p': /* PC-relative offset. */ - *offset_reloc = BFD_RELOC_16_PCREL_S2; - my_getExpression (&offset_expr, s); - s = expr_end; - continue; - - case 'u': /* Upper 16 bits. */ - *offset_reloc = BFD_RELOC_LO16; - if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0 - && offset_expr.X_op == O_constant - && (offset_expr.X_add_number < 0 - || offset_expr.X_add_number >= 0x10000)) - as_bad (_("lui expression (%lu) not in range 0..65535"), - (unsigned long) offset_expr.X_add_number); - s = expr_end; - continue; - - case 'a': /* 26-bit address. */ - jump: - *offset_reloc = BFD_RELOC_MIPS_JMP; - my_getExpression (&offset_expr, s); - s = expr_end; - continue; - - case 'N': /* 3-bit branch condition code. */ - case 'M': /* 3-bit compare condition code. */ - rtype = RTYPE_CCC; - if (ip->insn_mo->pinfo & (FP_D | FP_S)) - rtype |= RTYPE_FCC; - if (!reg_lookup (&s, rtype, ®no)) - break; - if ((strcmp (str + strlen (str) - 3, ".ps") == 0 - || strcmp (str + strlen (str) - 5, "any2f") == 0 - || strcmp (str + strlen (str) - 5, "any2t") == 0) - && (regno & 1) != 0) - as_warn (_("Condition code register should be even for %s, " - "was %d"), - str, regno); - if ((strcmp (str + strlen (str) - 5, "any4f") == 0 - || strcmp (str + strlen (str) - 5, "any4t") == 0) - && (regno & 3) != 0) - as_warn (_("Condition code register should be 0 or 4 for %s, " - "was %d"), - str, regno); - if (*args == 'N') - INSERT_OPERAND (mips_opts.micromips, BCC, *ip, regno); - else - INSERT_OPERAND (mips_opts.micromips, CCC, *ip, regno); - continue; - - case 'H': - if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) - s += 2; - if (ISDIGIT (*s)) - { - c = 0; - do - { - c *= 10; - c += *s - '0'; - ++s; - } - while (ISDIGIT (*s)); - } - else - c = 8; /* Invalid sel value. */ - - if (c > 7) - as_bad (_("Invalid coprocessor sub-selection value (0-7)")); - INSERT_OPERAND (mips_opts.micromips, SEL, *ip, c); - continue; - - case 'e': - gas_assert (!mips_opts.micromips); - /* Must be at least one digit. */ - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - - if ((unsigned long) imm_expr.X_add_number - > (unsigned long) OP_MASK_VECBYTE) - { - as_bad (_("bad byte vector index (%ld)"), - (long) imm_expr.X_add_number); - imm_expr.X_add_number = 0; - } - - INSERT_OPERAND (0, VECBYTE, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case '%': - gas_assert (!mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - - if ((unsigned long) imm_expr.X_add_number - > (unsigned long) OP_MASK_VECALIGN) - { - as_bad (_("bad byte vector index (%ld)"), - (long) imm_expr.X_add_number); - imm_expr.X_add_number = 0; - } - - INSERT_OPERAND (0, VECALIGN, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; - - case 'm': /* Opcode extension character. */ - gas_assert (mips_opts.micromips); - c = *++args; - switch (c) - { - case 'r': - if (strncmp (s, "$pc", 3) == 0) - { - s += 3; - continue; - } - break; - - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'j': - case 'l': - case 'm': - case 'n': - case 'p': - case 'q': - case 's': - case 't': - case 'x': - case 'y': - case 'z': - s_reset = s; - ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no); - if (regno == AT && mips_opts.at) - { - if (mips_opts.at == ATREG) - as_warn (_("Used $at without \".set noat\"")); - else - as_warn (_("Used $%u with \".set at=$%u\""), - regno, mips_opts.at); - } - if (!ok) - { - if (c == 'c') - { - gas_assert (args[1] == ','); - regno = lastregno; - ++args; - } - else if (c == 't') - { - gas_assert (args[1] == ','); - ++args; - continue; /* Nothing to do. */ - } - else - break; - } - - if (c == 'j' && !strncmp (ip->insn_mo->name, "jalr", 4)) - { - if (regno == lastregno) - { - insn_error - = _("Source and destination must be different"); - continue; - } - if (regno == 31 && lastregno == 0xffffffff) - { - insn_error - = _("A destination register must be supplied"); - continue; - } - } - - if (*s == ' ') - ++s; - if (args[1] != *s) - { - if (c == 'e') - { - gas_assert (args[1] == ','); - regno = lastregno; - s = s_reset; - ++args; - } - else if (c == 't') - { - gas_assert (args[1] == ','); - s = s_reset; - ++args; - continue; /* Nothing to do. */ - } - } - - /* Make sure regno is the same as lastregno. */ - if (c == 't' && regno != lastregno) - break; - - /* Make sure regno is the same as destregno. */ - if (c == 'x' && regno != destregno) - break; - - /* We need to save regno, before regno maps to the - microMIPS register encoding. */ - lastregno = regno; - - if (c == 'f') - destregno = regno; - - switch (c) - { - case 'a': - if (regno != GP) - regno = ILLEGAL_REG; - break; - - case 'b': - regno = mips32_to_micromips_reg_b_map[regno]; - break; - - case 'c': - regno = mips32_to_micromips_reg_c_map[regno]; - break; - - case 'd': - regno = mips32_to_micromips_reg_d_map[regno]; - break; - - case 'e': - regno = mips32_to_micromips_reg_e_map[regno]; - break; - - case 'f': - regno = mips32_to_micromips_reg_f_map[regno]; - break; - - case 'g': - regno = mips32_to_micromips_reg_g_map[regno]; - break; - - case 'h': - s += strspn (s, " \t"); - if (*s != ',') - { - regno = ILLEGAL_REG; - break; - } - ++s; - s += strspn (s, " \t"); - ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no2); - if (!ok) - { - regno = ILLEGAL_REG; - break; - } - if (regno2 == AT && mips_opts.at) - { - if (mips_opts.at == ATREG) - as_warn (_("Used $at without \".set noat\"")); - else - as_warn (_("Used $%u with \".set at=$%u\""), - regno2, mips_opts.at); - } - regno = (mips_lookup_reg_pair - (regno, regno2, - micromips_to_32_reg_h_map1, - micromips_to_32_reg_h_map2, 8)); - break; - - case 'l': - regno = mips32_to_micromips_reg_l_map[regno]; - break; - - case 'm': - regno = mips32_to_micromips_reg_m_map[regno]; - break; - - case 'n': - regno = mips32_to_micromips_reg_n_map[regno]; - break; - - case 'q': - regno = mips32_to_micromips_reg_q_map[regno]; - break; - - case 's': - if (regno != SP) - regno = ILLEGAL_REG; - break; - - case 'y': - if (regno != 31) - regno = ILLEGAL_REG; - break; - - case 'z': - if (regno != ZERO) - regno = ILLEGAL_REG; - break; - - case 'j': /* Do nothing. */ - case 'p': - case 't': - case 'x': - break; - - default: - abort (); - } - - if (regno == ILLEGAL_REG) - break; - - switch (c) - { - case 'b': - INSERT_OPERAND (1, MB, *ip, regno); - break; - - case 'c': - INSERT_OPERAND (1, MC, *ip, regno); - break; - - case 'd': - INSERT_OPERAND (1, MD, *ip, regno); - break; - - case 'e': - INSERT_OPERAND (1, ME, *ip, regno); - break; - - case 'f': - INSERT_OPERAND (1, MF, *ip, regno); - break; - - case 'g': - INSERT_OPERAND (1, MG, *ip, regno); - break; - - case 'h': - INSERT_OPERAND (1, MH, *ip, regno); - break; - - case 'j': - INSERT_OPERAND (1, MJ, *ip, regno); - break; - - case 'l': - INSERT_OPERAND (1, ML, *ip, regno); - break; - - case 'm': - INSERT_OPERAND (1, MM, *ip, regno); - break; - - case 'n': - INSERT_OPERAND (1, MN, *ip, regno); - break; - - case 'p': - INSERT_OPERAND (1, MP, *ip, regno); - break; - - case 'q': - INSERT_OPERAND (1, MQ, *ip, regno); - break; - - case 'a': /* Do nothing. */ - case 's': /* Do nothing. */ - case 't': /* Do nothing. */ - case 'x': /* Do nothing. */ - case 'y': /* Do nothing. */ - case 'z': /* Do nothing. */ - break; - - default: - abort (); - } - continue; - - case 'A': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - /* Check whether there is only a single bracketed - expression left. If so, it must be the base register - and the constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) - { - INSERT_OPERAND (1, IMMA, *ip, 0); - continue; - } - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, -64, 64, 2)) - break; - - imm = ep.X_add_number >> 2; - INSERT_OPERAND (1, IMMA, *ip, imm); - } - s = expr_end; - continue; - - case 'B': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || ep.X_op != O_constant) - break; - - for (imm = 0; imm < 8; imm++) - if (micromips_imm_b_map[imm] == ep.X_add_number) - break; - if (imm >= 8) - break; - - INSERT_OPERAND (1, IMMB, *ip, imm); - } - s = expr_end; - continue; - - case 'C': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || ep.X_op != O_constant) - break; - - for (imm = 0; imm < 16; imm++) - if (micromips_imm_c_map[imm] == ep.X_add_number) - break; - if (imm >= 16) - break; - - INSERT_OPERAND (1, IMMC, *ip, imm); - } - s = expr_end; - continue; - - case 'D': /* pc relative offset */ - case 'E': /* pc relative offset */ - my_getExpression (&offset_expr, s); - if (offset_expr.X_op == O_register) - break; - - if (!forced_insn_length) - *offset_reloc = (int) BFD_RELOC_UNUSED + c; - else if (c == 'D') - *offset_reloc = BFD_RELOC_MICROMIPS_10_PCREL_S1; - else - *offset_reloc = BFD_RELOC_MICROMIPS_7_PCREL_S1; - s = expr_end; - continue; - - case 'F': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 16, 0)) - break; - - imm = ep.X_add_number; - INSERT_OPERAND (1, IMMF, *ip, imm); - } - s = expr_end; - continue; - - case 'G': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - /* Check whether there is only a single bracketed - expression left. If so, it must be the base register - and the constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) - { - INSERT_OPERAND (1, IMMG, *ip, 0); - continue; - } - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, -1, 15, 0)) - break; - - imm = ep.X_add_number & 15; - INSERT_OPERAND (1, IMMG, *ip, imm); - } - s = expr_end; - continue; + f64 = *args == 'F' || *args == 'L'; + using_gprs = *args == 'F' || *args == 'f'; - case 'H': + save_in = input_line_pointer; + input_line_pointer = s; + err = md_atof (f64 ? 'd' : 'f', (char *) temp, &len); + length = len; + s = input_line_pointer; + input_line_pointer = save_in; + if (err != NULL && *err != '\0') { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - /* Check whether there is only a single bracketed - expression left. If so, it must be the base register - and the constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) - { - INSERT_OPERAND (1, IMMH, *ip, 0); - continue; - } - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 16, 1)) - break; - - imm = ep.X_add_number >> 1; - INSERT_OPERAND (1, IMMH, *ip, imm); + as_bad (_("Bad floating point constant: %s"), err); + memset (temp, '\0', sizeof temp); + length = f64 ? 8 : 4; } - s = expr_end; - continue; - - case 'I': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, -1, 127, 0)) - break; + gas_assert (length == (unsigned) (f64 ? 8 : 4)); - imm = ep.X_add_number & 127; - INSERT_OPERAND (1, IMMI, *ip, imm); + if (*args == 'f' + || (*args == 'l' + && (g_switch_value < 4 + || (temp[0] == 0 && temp[1] == 0) + || (temp[2] == 0 && temp[3] == 0)))) + { + imm_expr.X_op = O_constant; + if (!target_big_endian) + imm_expr.X_add_number = bfd_getl32 (temp); + else + imm_expr.X_add_number = bfd_getb32 (temp); } - s = expr_end; - continue; - - case 'J': + else if (length > 4 + && !mips_disable_float_construction + /* Constants can only be constructed in GPRs and + copied to FPRs if the GPRs are at least as wide + as the FPRs. Force the constant into memory if + we are using 64-bit FPRs but the GPRs are only + 32 bits wide. */ + && (using_gprs + || !(HAVE_64BIT_FPRS && HAVE_32BIT_GPRS)) + && ((temp[0] == 0 && temp[1] == 0) + || (temp[2] == 0 && temp[3] == 0)) + && ((temp[4] == 0 && temp[5] == 0) + || (temp[6] == 0 && temp[7] == 0))) { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - /* Check whether there is only a single bracketed - expression left. If so, it must be the base register - and the constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) + /* The value is simple enough to load with a couple of + instructions. If using 32-bit registers, set + imm_expr to the high order 32 bits and offset_expr to + the low order 32 bits. Otherwise, set imm_expr to + the entire 64 bit constant. */ + if (using_gprs ? HAVE_32BIT_GPRS : HAVE_32BIT_FPRS) { - INSERT_OPERAND (1, IMMJ, *ip, 0); - continue; + imm_expr.X_op = O_constant; + offset_expr.X_op = O_constant; + if (!target_big_endian) + { + imm_expr.X_add_number = bfd_getl32 (temp + 4); + offset_expr.X_add_number = bfd_getl32 (temp); + } + else + { + imm_expr.X_add_number = bfd_getb32 (temp); + offset_expr.X_add_number = bfd_getb32 (temp + 4); + } + if (offset_expr.X_add_number == 0) + offset_expr.X_op = O_absent; } - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 16, 2)) - break; - - imm = ep.X_add_number >> 2; - INSERT_OPERAND (1, IMMJ, *ip, imm); - } - s = expr_end; - continue; - - case 'L': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - /* Check whether there is only a single bracketed - expression left. If so, it must be the base register - and the constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) + else { - INSERT_OPERAND (1, IMML, *ip, 0); - continue; + imm_expr.X_op = O_constant; + if (!target_big_endian) + imm_expr.X_add_number = bfd_getl64 (temp); + else + imm_expr.X_add_number = bfd_getb64 (temp); } - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 16, 0)) - break; - - imm = ep.X_add_number; - INSERT_OPERAND (1, IMML, *ip, imm); - } - s = expr_end; - continue; - - case 'M': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 1, 9, 0)) - break; - - imm = ep.X_add_number & 7; - INSERT_OPERAND (1, IMMM, *ip, imm); - } - s = expr_end; - continue; - - case 'N': /* Register list for lwm and swm. */ - { - /* A comma-separated list of registers and/or - dash-separated contiguous ranges including - both ra and a set of one or more registers - starting at s0 up to s3 which have to be - consecutive, e.g.: - - s0, ra - s0, s1, ra, s2, s3 - s0-s2, ra - - and any permutations of these. */ - unsigned int reglist; - int imm; - - if (!reglist_lookup (&s, RTYPE_NUM | RTYPE_GP, ®list)) - break; - - if ((reglist & 0xfff1ffff) != 0x80010000) - break; - - reglist = (reglist >> 17) & 7; - reglist += 1; - if ((reglist & -reglist) != reglist) - break; - - imm = ffs (reglist) - 1; - INSERT_OPERAND (1, IMMN, *ip, imm); - } - continue; - - case 'O': /* sdbbp 4-bit code. */ - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 16, 0)) - break; - - imm = ep.X_add_number; - INSERT_OPERAND (1, IMMO, *ip, imm); - } - s = expr_end; - continue; - - case 'P': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 32, 2)) - break; - - imm = ep.X_add_number >> 2; - INSERT_OPERAND (1, IMMP, *ip, imm); } - s = expr_end; - continue; - - case 'Q': + else { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, -0x400000, 0x400000, 2)) - break; - - imm = ep.X_add_number >> 2; - INSERT_OPERAND (1, IMMQ, *ip, imm); - } - s = expr_end; - continue; + const char *newname; + segT new_seg; - case 'U': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - /* Check whether there is only a single bracketed - expression left. If so, it must be the base register - and the constant must be zero. */ - if (*s == '(' && strchr (s + 1, '(') == 0) + /* Switch to the right section. */ + seg = now_seg; + subseg = now_subseg; + switch (*args) { - INSERT_OPERAND (1, IMMU, *ip, 0); - continue; + default: /* unused default case avoids warnings. */ + case 'L': + newname = RDATA_SECTION_NAME; + if (g_switch_value >= 8) + newname = ".lit8"; + break; + case 'F': + newname = RDATA_SECTION_NAME; + break; + case 'l': + gas_assert (g_switch_value >= 4); + newname = ".lit4"; + break; } + new_seg = subseg_new (newname, (subsegT) 0); + bfd_set_section_flags (stdoutput, new_seg, + (SEC_ALLOC + | SEC_LOAD + | SEC_READONLY + | SEC_DATA)); + frag_align (*args == 'l' ? 2 : 3, 0, 0); + if (strncmp (TARGET_OS, "elf", 3) != 0) + record_alignment (new_seg, 4); + else + record_alignment (new_seg, *args == 'l' ? 2 : 3); + if (seg == now_seg) + as_bad (_("Can't use floating point insn in this section")); - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 32, 2)) - break; - - imm = ep.X_add_number >> 2; - INSERT_OPERAND (1, IMMU, *ip, imm); - } - s = expr_end; - continue; - - case 'W': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; + /* Set the argument to the current address in the + section. */ + offset_expr.X_op = O_symbol; + offset_expr.X_add_symbol = symbol_temp_new_now (); + offset_expr.X_add_number = 0; - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 64, 2)) - break; + /* Put the floating point number into the section. */ + p = frag_more ((int) length); + memcpy (p, temp, length); - imm = ep.X_add_number >> 2; - INSERT_OPERAND (1, IMMW, *ip, imm); + /* Switch back to the original section. */ + subseg_set (seg, subseg); } - s = expr_end; - continue; - - case 'X': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, -8, 8, 0)) - break; + } + continue; - imm = ep.X_add_number; - INSERT_OPERAND (1, IMMX, *ip, imm); - } - s = expr_end; - continue; + /* ??? This is the traditional behavior, but is flaky if + there are alternative versions of the same instruction + for different subarchitectures. The next alternative + might not be suitable. */ + case 'j': + /* For compatibility with older assemblers, we accept + 0x8000-0xffff as signed 16-bit numbers when only + signed numbers are allowed. */ + arg.lax_max = !more_alts; + case 'i': + /* Only accept non-constant operands if this is the + final alternative. Later alternatives might include + a macro implementation. */ + arg.allow_nonconst = !more_alts; + break; - case 'Y': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; - int imm; - - if (my_getSmallExpression (&ep, r, s) > 0 - || expr_const_in_range (&ep, -2, 2, 2) - || !expr_const_in_range (&ep, -258, 258, 2)) - break; - - imm = ep.X_add_number >> 2; - imm = ((imm >> 1) & ~0xff) | (imm & 0xff); - INSERT_OPERAND (1, IMMY, *ip, imm); - } - s = expr_end; - continue; + case 'u': + /* There are no macro implementations for out-of-range values. */ + arg.allow_nonconst = TRUE; + break; - case 'Z': - { - bfd_reloc_code_real_type r[3]; - expressionS ep; + case 'o': + /* There should always be a macro implementation. */ + arg.allow_nonconst = FALSE; + break; - if (my_getSmallExpression (&ep, r, s) > 0 - || !expr_const_in_range (&ep, 0, 1, 0)) - break; - } - s = expr_end; - continue; + case 'p': + *offset_reloc = BFD_RELOC_16_PCREL_S2; + break; - default: - as_bad (_("Internal error: bad microMIPS opcode " - "(unknown extension operand type `m%c'): %s %s"), - *args, insn->name, insn->args); - /* Further processing is fruitless. */ - return; - } + case 'a': + *offset_reloc = BFD_RELOC_MIPS_JMP; break; - case 'n': /* Register list for 32-bit lwm and swm. */ + case 'm': gas_assert (mips_opts.micromips); - { - /* A comma-separated list of registers and/or - dash-separated contiguous ranges including - at least one of ra and a set of one or more - registers starting at s0 up to s7 and then - s8 which have to be consecutive, e.g.: - - ra - s0 - ra, s0, s1, s2 - s0-s8 - s0-s5, ra - - and any permutations of these. */ - unsigned int reglist; - int imm; - int ra; - - if (!reglist_lookup (&s, RTYPE_NUM | RTYPE_GP, ®list)) + c = args[1]; + switch (c) + { + case 't': + case 'c': + case 'e': + /* We have already matched a comma by this point, + so the register is only optional if there is another + operand to come. */ + gas_assert (arg.opnum == 2); + arg.optional_reg = (args[2] == ','); break; - if ((reglist & 0x3f00ffff) != 0) + case 'D': + case 'E': + if (!forced_insn_length) + *offset_reloc = (int) BFD_RELOC_UNUSED + c; + else if (c == 'D') + *offset_reloc = BFD_RELOC_MICROMIPS_10_PCREL_S1; + else + *offset_reloc = BFD_RELOC_MICROMIPS_7_PCREL_S1; break; + } + break; + } - ra = (reglist >> 27) & 0x10; - reglist = ((reglist >> 22) & 0x100) | ((reglist >> 16) & 0xff); - reglist += 1; - if ((reglist & -reglist) != reglist) - break; + operand = (mips_opts.micromips + ? decode_micromips_operand (args) + : decode_mips_operand (args)); + if (!operand) + abort (); - imm = (ffs (reglist) - 1) | ra; - INSERT_OPERAND (1, RT, *ip, imm); - imm_expr.X_op = O_absent; - } - continue; + s = match_operand (&arg, operand, s); + if (!s && arg.optional_reg) + { + /* Assume that the register has been elided and is the + same as the first operand. */ + arg.optional_reg = FALSE; + arg.argnum = 1; + s = argsStart; + SKIP_SPACE_TABS (s); + s = match_operand (&arg, operand, s); + } + if (!s) + break; - case '|': /* 4-bit trap code. */ - gas_assert (mips_opts.micromips); - my_getExpression (&imm_expr, s); - check_absolute_expr (ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number - > MICROMIPSOP_MASK_TRAP) - as_bad (_("Trap code (%lu) for %s not in 0..15 range"), - (unsigned long) imm_expr.X_add_number, - ip->insn_mo->name); - INSERT_OPERAND (1, TRAP, *ip, imm_expr.X_add_number); - imm_expr.X_op = O_absent; - s = expr_end; - continue; + /* Skip prefixes. */ + if (*args == '+' || *args == 'm') + args++; - default: - as_bad (_("Bad char = '%c'\n"), *args); - abort (); - } - break; + continue; } /* Args don't match. */ s = argsStart; insn_error = _("Illegal operands"); - if (insn + 1 < past && !strcmp (insn->name, insn[1].name)) + if (more_alts) { ++insn; continue; } - else if (wrong_delay_slot_insns && need_delay_slot_ok) + if (wrong_delay_slot_insns && need_delay_slot_ok) { gas_assert (firstinsn); need_delay_slot_ok = FALSE; @@ -14174,8 +12053,6 @@ mips_ip (char *str, struct mips_cl_insn *ip) } } -#define SKIP_SPACE_TABS(S) { while (*(S) == ' ' || *(S) == '\t') ++(S); } - /* As for mips_ip, but used when assembling MIPS16 code. Also set forced_insn_length to the resulting instruction size in bytes if the user explicitly requested a small or extended instruction. */ diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 882bcc6..47b2f03 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2013-07-14 Richard Sandiford + + * gas/mips/at-2.l: Remove duplicated $at warnings. + * gas/mips/ext-ill.l, gas/mips/lui-1.l, gas/mips/mips32r2-ill.l, + gas/mips/mips32r2-ill-nofp.l, gas/mips/mips32r2-ill-fp64.l, + gas/mips/mips64r2-ill.l, gas/mips/octeon-ill.l: Update error + messages. Expect negative numbers to be printed as such, + rather than as large unsigned positive numbers. + 2013-07-12 Maciej W. Rozycki * gas/mips/nan-2008-1.d: New test. diff --git a/gas/testsuite/gas/mips/at-2.l b/gas/testsuite/gas/mips/at-2.l index cea1017..ca6bb6b 100644 --- a/gas/testsuite/gas/mips/at-2.l +++ b/gas/testsuite/gas/mips/at-2.l @@ -3,11 +3,5 @@ .*\.s:5: Error: Macro used \$at after ".set noat" .*\.s:6: Error: Macro used \$at after ".set noat" .*\.s:8: Warning: Used \$at without ".set noat" -.*\.s:8: Warning: Used \$at without ".set noat" -.*\.s:8: Warning: Used \$at without ".set noat" -.*\.s:13: Warning: Used \$26 with ".set at=\$26" .*\.s:13: Warning: Used \$26 with ".set at=\$26" -.*\.s:13: Warning: Used \$26 with ".set at=\$26" -.*\.s:18: Warning: Used \$27 with ".set at=\$27" -.*\.s:18: Warning: Used \$27 with ".set at=\$27" .*\.s:18: Warning: Used \$27 with ".set at=\$27" diff --git a/gas/testsuite/gas/mips/ext-ill.l b/gas/testsuite/gas/mips/ext-ill.l index 0f4ed35..b61f03c 100644 --- a/gas/testsuite/gas/mips/ext-ill.l +++ b/gas/testsuite/gas/mips/ext-ill.l @@ -1,6 +1,6 @@ .*: Assembler messages: -.*:5: Error: Improper extract size \(0, position 1\) -.*:6: Error: Improper extract size \(0, position 1\) -.*:7: Error: Improper extract size \(2, position 31\) -.*:8: Error: Improper extract size \(32, position 1\) -.*:9: Error: Improper extract size \(0, position 33\) +.*:5: Error: Invalid field specification \(position 1, size 0\) +.*:6: Error: Invalid field specification \(position 1, size 0\) +.*:7: Error: Invalid field specification \(position 31, size 2\) +.*:8: Error: Invalid field specification \(position 1, size 32\) +.*:9: Error: Invalid field specification \(position 33, size 0\) diff --git a/gas/testsuite/gas/mips/lui-1.l b/gas/testsuite/gas/mips/lui-1.l index e4362b6..464bd75 100644 --- a/gas/testsuite/gas/mips/lui-1.l +++ b/gas/testsuite/gas/mips/lui-1.l @@ -1,5 +1,5 @@ .*\.s: Assembler messages: -.*\.s:5: Error: lui expression \((18446744073709551615|4294967295)\) not in range 0\.\.65535 -.*\.s:6: Error: lui expression \(65536\) not in range 0\.\.65535 +.*\.s:5: Error: Operand 2 of `lui' must be in the range \[0x0, 0xffff\], was -1. +.*\.s:6: Error: Operand 2 of `lui' must be in the range \[0x0, 0xffff\], was 0x10000. .*\.s:7: Error: bignum invalid .*\.s:8: Error: register value used as expression diff --git a/gas/testsuite/gas/mips/mips32r2-ill-fp64.l b/gas/testsuite/gas/mips/mips32r2-ill-fp64.l index 2b3c727..3e0e30e 100644 --- a/gas/testsuite/gas/mips/mips32r2-ill-fp64.l +++ b/gas/testsuite/gas/mips/mips32r2-ill-fp64.l @@ -1,13 +1,13 @@ .*: Assembler messages: -.*:12: Error: Improper position \([0-9]*\) -.*:15: Error: Improper position \(32\) -.*:18: Error: Improper extract size \(0, position 0\) -.*:21: Error: Improper extract size \(33, position 0\) -.*:24: Error: Improper extract size \(0, position 0\) -.*:27: Error: Improper extract size \(2, position 31\) -.*:30: Error: Improper position \([0-9]*\) -.*:33: Error: Improper position \(32\) -.*:36: Error: Improper insert size \(0, position 0\) -.*:39: Error: Improper insert size \(33, position 0\) -.*:42: Error: Improper insert size \(0, position 0\) -.*:45: Error: Improper insert size \(2, position 31\) +.*:12: Error: Operand 3 of `ext' must be in the range \[0, 31\], was -1. +.*:15: Error: Operand 3 of `ext' must be in the range \[0, 31\], was 32. +.*:18: Error: Invalid field specification \(position 0, size 0\) +.*:21: Error: Invalid field specification \(position 0, size 33\) +.*:24: Error: Invalid field specification \(position 0, size 0\) +.*:27: Error: Invalid field specification \(position 31, size 2\) +.*:30: Error: Operand 3 of `ins' must be in the range \[0, 31\], was -1. +.*:33: Error: Operand 3 of `ins' must be in the range \[0, 31\], was 32. +.*:36: Error: Invalid field specification \(position 0, size 0\) +.*:39: Error: Invalid field specification \(position 0, size 33\) +.*:42: Error: Invalid field specification \(position 0, size 0\) +.*:45: Error: Invalid field specification \(position 31, size 2\) diff --git a/gas/testsuite/gas/mips/mips32r2-ill-nofp.l b/gas/testsuite/gas/mips/mips32r2-ill-nofp.l index 2b3c727..3e0e30e 100644 --- a/gas/testsuite/gas/mips/mips32r2-ill-nofp.l +++ b/gas/testsuite/gas/mips/mips32r2-ill-nofp.l @@ -1,13 +1,13 @@ .*: Assembler messages: -.*:12: Error: Improper position \([0-9]*\) -.*:15: Error: Improper position \(32\) -.*:18: Error: Improper extract size \(0, position 0\) -.*:21: Error: Improper extract size \(33, position 0\) -.*:24: Error: Improper extract size \(0, position 0\) -.*:27: Error: Improper extract size \(2, position 31\) -.*:30: Error: Improper position \([0-9]*\) -.*:33: Error: Improper position \(32\) -.*:36: Error: Improper insert size \(0, position 0\) -.*:39: Error: Improper insert size \(33, position 0\) -.*:42: Error: Improper insert size \(0, position 0\) -.*:45: Error: Improper insert size \(2, position 31\) +.*:12: Error: Operand 3 of `ext' must be in the range \[0, 31\], was -1. +.*:15: Error: Operand 3 of `ext' must be in the range \[0, 31\], was 32. +.*:18: Error: Invalid field specification \(position 0, size 0\) +.*:21: Error: Invalid field specification \(position 0, size 33\) +.*:24: Error: Invalid field specification \(position 0, size 0\) +.*:27: Error: Invalid field specification \(position 31, size 2\) +.*:30: Error: Operand 3 of `ins' must be in the range \[0, 31\], was -1. +.*:33: Error: Operand 3 of `ins' must be in the range \[0, 31\], was 32. +.*:36: Error: Invalid field specification \(position 0, size 0\) +.*:39: Error: Invalid field specification \(position 0, size 33\) +.*:42: Error: Invalid field specification \(position 0, size 0\) +.*:45: Error: Invalid field specification \(position 31, size 2\) diff --git a/gas/testsuite/gas/mips/mips32r2-ill.l b/gas/testsuite/gas/mips/mips32r2-ill.l index 66223a2..7f9bedc 100644 --- a/gas/testsuite/gas/mips/mips32r2-ill.l +++ b/gas/testsuite/gas/mips/mips32r2-ill.l @@ -1,15 +1,15 @@ .*: Assembler messages: -.*:12: Error: Improper position \([0-9]*\) -.*:15: Error: Improper position \(32\) -.*:18: Error: Improper extract size \(0, position 0\) -.*:21: Error: Improper extract size \(33, position 0\) -.*:24: Error: Improper extract size \(0, position 0\) -.*:27: Error: Improper extract size \(2, position 31\) -.*:30: Error: Improper position \([0-9]*\) -.*:33: Error: Improper position \(32\) -.*:36: Error: Improper insert size \(0, position 0\) -.*:39: Error: Improper insert size \(33, position 0\) -.*:42: Error: Improper insert size \(0, position 0\) -.*:45: Error: Improper insert size \(2, position 31\) +.*:12: Error: Operand 3 of `ext' must be in the range \[0, 31\], was -1. +.*:15: Error: Operand 3 of `ext' must be in the range \[0, 31\], was 32. +.*:18: Error: Invalid field specification \(position 0, size 0\) +.*:21: Error: Invalid field specification \(position 0, size 33\) +.*:24: Error: Invalid field specification \(position 0, size 0\) +.*:27: Error: Invalid field specification \(position 31, size 2\) +.*:30: Error: Operand 3 of `ins' must be in the range \[0, 31\], was -1. +.*:33: Error: Operand 3 of `ins' must be in the range \[0, 31\], was 32. +.*:36: Error: Invalid field specification \(position 0, size 0\) +.*:39: Error: Invalid field specification \(position 0, size 33\) +.*:42: Error: Invalid field specification \(position 0, size 0\) +.*:45: Error: Invalid field specification \(position 31, size 2\) .*:54: Warning: Float register should be even, was 1 .*:57: Warning: Float register should be even, was 1 diff --git a/gas/testsuite/gas/mips/mips64r2-ill.l b/gas/testsuite/gas/mips/mips64r2-ill.l index c95e546..6cc6b35 100644 --- a/gas/testsuite/gas/mips/mips64r2-ill.l +++ b/gas/testsuite/gas/mips/mips64r2-ill.l @@ -1,57 +1,57 @@ .*: Assembler messages: -.*:12: Error: Improper position \([0-9]*\) -.*:15: Error: Improper position \(64\) -.*:18: Error: Improper extract size \(0, position 0\) -.*:21: Error: Improper extract size \(65, position 0\) -.*:31: Error: Improper extract size \(64, position 1\) -.*:33: Error: Improper extract size \(2, position 63\) -.*:34: Error: Improper extract size \(63, position 63\) -.*:35: Error: Improper extract size \(64, position 63\) -.*:40: Error: Improper position \([0-9]*\) -.*:43: Error: Improper position \(32\) -.*:46: Error: Improper extract size \(32, position 0\) -.*:49: Error: Improper extract size \(65, position 0\) -.*:59: Error: Improper extract size \(64, position 1\) -.*:61: Error: Improper extract size \(34, position 31\) -.*:62: Error: Improper extract size \(63, position 31\) -.*:63: Error: Improper extract size \(64, position 31\) -.*:68: Error: Improper position \(31\) -.*:71: Error: Improper position \(64\) -.*:74: Error: Improper extract size \(0, position 32\) -.*:77: Error: Improper extract size \(33, position 32\) -.*:87: Error: Improper extract size \(32, position 33\) -.*:89: Error: Improper extract size \(2, position 63\) -.*:90: Error: Improper extract size \(31, position 63\) -.*:91: Error: Improper extract size \(32, position 63\) -.*:96: Error: Improper position \([0-9]*\) -.*:99: Error: Improper position \(64\) -.*:102: Error: Improper insert size \(0, position 0\) -.*:105: Error: Improper insert size \(65, position 0\) -.*:115: Error: Improper insert size \(64, position 1\) -.*:117: Error: Improper insert size \(2, position 63\) -.*:118: Error: Improper insert size \(63, position 63\) -.*:119: Error: Improper insert size \(64, position 63\) -.*:124: Error: Improper position \([0-9]*\) -.*:127: Error: Improper position \(32\) -.*:130: Error: Improper insert size \(1, position 31\) -.*:133: Error: Improper insert size \(65, position 0\) -.*:136: Error: Improper insert size \(2, position 0\) -.*:137: Error: Improper insert size \(3, position 0\) -.*:140: Error: Improper insert size \(2, position 1\) -.*:141: Error: Improper insert size \(3, position 1\) -.*:143: Error: Improper insert size \(64, position 1\) -.*:144: Error: Improper insert size \(2, position 30\) -.*:146: Error: Improper insert size \(63, position 30\) -.*:147: Error: Improper insert size \(64, position 30\) -.*:150: Error: Improper insert size \(63, position 31\) -.*:151: Error: Improper insert size \(64, position 31\) -.*:156: Error: Improper position \(31\) -.*:159: Error: Improper position \(64\) -.*:162: Error: Improper insert size \(0, position 32\) -.*:165: Error: Improper insert size \(33, position 32\) -.*:175: Error: Improper insert size \(32, position 33\) -.*:178: Error: Improper insert size \(31, position 62\) -.*:179: Error: Improper insert size \(32, position 62\) -.*:181: Error: Improper insert size \(2, position 63\) -.*:182: Error: Improper insert size \(31, position 63\) -.*:183: Error: Improper insert size \(32, position 63\) +.*:12: Error: Operand 3 of `dext' must be in the range \[0, 63\], was -1. +.*:15: Error: Operand 3 of `dext' must be in the range \[0, 63\], was 64. +.*:18: Error: Invalid field specification \(position 0, size 0\) +.*:21: Error: Invalid field specification \(position 0, size 65\) +.*:31: Error: Invalid field specification \(position 1, size 64\) +.*:33: Error: Invalid field specification \(position 63, size 2\) +.*:34: Error: Invalid field specification \(position 63, size 63\) +.*:35: Error: Invalid field specification \(position 63, size 64\) +.*:40: Error: Operand 3 of `dextm' must be in the range \[0, 31\], was -1. +.*:43: Error: Operand 3 of `dextm' must be in the range \[0, 31\], was 32. +.*:46: Error: Invalid field specification \(position 0, size 32\) +.*:49: Error: Invalid field specification \(position 0, size 65\) +.*:59: Error: Invalid field specification \(position 1, size 64\) +.*:61: Error: Invalid field specification \(position 31, size 34\) +.*:62: Error: Invalid field specification \(position 31, size 63\) +.*:63: Error: Invalid field specification \(position 31, size 64\) +.*:68: Error: Operand 3 of `dextu' must be in the range \[32, 63\], was 31. +.*:71: Error: Operand 3 of `dextu' must be in the range \[32, 63\], was 64. +.*:74: Error: Invalid field specification \(position 32, size 0\) +.*:77: Error: Invalid field specification \(position 32, size 33\) +.*:87: Error: Invalid field specification \(position 33, size 32\) +.*:89: Error: Invalid field specification \(position 63, size 2\) +.*:90: Error: Invalid field specification \(position 63, size 31\) +.*:91: Error: Invalid field specification \(position 63, size 32\) +.*:96: Error: Operand 3 of `dins' must be in the range \[0, 63\], was -1. +.*:99: Error: Operand 3 of `dins' must be in the range \[0, 63\], was 64. +.*:102: Error: Invalid field specification \(position 0, size 0\) +.*:105: Error: Invalid field specification \(position 0, size 65\) +.*:115: Error: Invalid field specification \(position 1, size 64\) +.*:117: Error: Invalid field specification \(position 63, size 2\) +.*:118: Error: Invalid field specification \(position 63, size 63\) +.*:119: Error: Invalid field specification \(position 63, size 64\) +.*:124: Error: Operand 3 of `dinsm' must be in the range \[0, 31\], was -1. +.*:127: Error: Operand 3 of `dinsm' must be in the range \[0, 31\], was 32. +.*:130: Error: Invalid field specification \(position 31, size 1\) +.*:133: Error: Invalid field specification \(position 0, size 65\) +.*:136: Error: Invalid field specification \(position 0, size 2\) +.*:137: Error: Invalid field specification \(position 0, size 3\) +.*:140: Error: Invalid field specification \(position 1, size 2\) +.*:141: Error: Invalid field specification \(position 1, size 3\) +.*:143: Error: Invalid field specification \(position 1, size 64\) +.*:144: Error: Invalid field specification \(position 30, size 2\) +.*:146: Error: Invalid field specification \(position 30, size 63\) +.*:147: Error: Invalid field specification \(position 30, size 64\) +.*:150: Error: Invalid field specification \(position 31, size 63\) +.*:151: Error: Invalid field specification \(position 31, size 64\) +.*:156: Error: Operand 3 of `dinsu' must be in the range \[32, 63\], was 31. +.*:159: Error: Operand 3 of `dinsu' must be in the range \[32, 63\], was 64. +.*:162: Error: Invalid field specification \(position 32, size 0\) +.*:165: Error: Invalid field specification \(position 32, size 33\) +.*:175: Error: Invalid field specification \(position 33, size 32\) +.*:178: Error: Invalid field specification \(position 62, size 31\) +.*:179: Error: Invalid field specification \(position 62, size 32\) +.*:181: Error: Invalid field specification \(position 63, size 2\) +.*:182: Error: Invalid field specification \(position 63, size 31\) +.*:183: Error: Invalid field specification \(position 63, size 32\) diff --git a/gas/testsuite/gas/mips/octeon-ill.l b/gas/testsuite/gas/mips/octeon-ill.l index 49c16c8..6ff4fde 100644 --- a/gas/testsuite/gas/mips/octeon-ill.l +++ b/gas/testsuite/gas/mips/octeon-ill.l @@ -1,13 +1,13 @@ .*: Assembler messages: -.*:5: Error: Improper bit index \(51\) -.*:7: Error: Improper bit index \(71\) -.*:10: Error: Improper bit index \(49\) -.*:12: Error: Improper bit index \(74\) -.*:15: Error: Improper size \(37\) -.*:17: Error: Improper position \(39\) -.*:18: Error: Improper size \(25\) -.*:20: Error: Improper position \(64\) -.*:21: Error: Improper size \(14\) +.*:5: Error: Operand 2 of `bbit032' must be in the range \[0, 31\], was 51. +.*:7: Error: Operand 2 of `bbit0' must be in the range \[0, 31\], was 71. +.*:10: Error: Operand 2 of `bbit132' must be in the range \[0, 31\], was 49. +.*:12: Error: Operand 2 of `bbit1' must be in the range \[0, 31\], was 74. +.*:15: Error: Invalid field specification \(position 0, size 37\) +.*:17: Error: Operand 3 of `cins32' must be in the range \[0, 31\], was 39. +.*:18: Error: Invalid field specification \(position 7, size 25\) +.*:20: Error: Operand 3 of `cins' must be in the range \[0, 31\], was 64. +.*:21: Error: Invalid field specification \(position 50, size 14\) .*:23: Error: Opcode not supported on this processor.* .*:24: Error: Opcode not supported on this processor.* .*:25: Error: Opcode not supported on this processor.* @@ -34,12 +34,12 @@ .*:48: Error: Illegal operands `dmfc2 \$4,\$15,4' .*:49: Error: Illegal operands `dmtc2 \$16,\$8' .*:50: Error: Illegal operands `dmtc2 \$22,\$7,\$4' -.*:52: Error: Improper size \(32\) -.*:54: Error: Improper position \(32\) -.*:55: Error: Improper size \(29\) -.*:57: Error: Improper position \(70\) -.*:58: Error: Improper size \(25\) -.*:60: Error: Improper immediate \(512\) -.*:61: Error: Improper immediate \(-771\) -.*:62: Error: Improper immediate \(615\) -.*:63: Error: Improper immediate \(-513\) +.*:52: Error: Invalid field specification \(position 26, size 32\) +.*:54: Error: Operand 3 of `exts32' must be in the range \[0, 31\], was 32. +.*:55: Error: Invalid field specification \(position 3, size 29\) +.*:57: Error: Operand 3 of `exts' must be in the range \[0, 31\], was 70. +.*:58: Error: Invalid field specification \(position 39, size 25\) +.*:60: Error: Operand 3 of `seqi' must be in the range \[-512, 511\], was 512. +.*:61: Error: Operand 2 of `seqi' must be in the range \[-512, 511\], was -771. +.*:62: Error: Operand 3 of `snei' must be in the range \[-512, 511\], was 615. +.*:63: Error: Operand 2 of `snei' must be in the range \[-512, 511\], was -513. -- 2.7.4