diff options
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r-- | gas/config/tc-mips.c | 451 |
1 files changed, 407 insertions, 44 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 2dabdf4..8d4a80b 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -267,8 +267,11 @@ struct mips_set_options /* Specifies whether module level options have been checked yet. */ static bfd_boolean file_mips_opts_checked = FALSE; -/* True if -mnan=2008, false if -mnan=legacy. */ -static bfd_boolean mips_flag_nan2008 = FALSE; +/* Do we support nan2008? 0 if we don't, 1 if we do, and -1 if the + value has not been initialized. Changed by `.nan legacy' and + `.nan 2008', and the -mnan=legacy and -mnan=2008 command line + options, and the default CPU. */ +static int mips_nan2008 = -1; /* This is the struct we use to hold the module level set of options. Note that we must set the isa field to ISA_UNKNOWN and the ASE, gp and @@ -350,6 +353,10 @@ static int mips_32bitmode = 0; || (ABI) == N64_ABI \ || (ABI) == O64_ABI) +#define ISA_IS_R6(ISA) \ + ((ISA) == ISA_MIPS32R6 \ + || (ISA) == ISA_MIPS64R6) + /* Return true if ISA supports 64 bit wide gp registers. */ #define ISA_HAS_64BIT_REGS(ISA) \ ((ISA) == ISA_MIPS3 \ @@ -358,7 +365,8 @@ static int mips_32bitmode = 0; || (ISA) == ISA_MIPS64 \ || (ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R3 \ - || (ISA) == ISA_MIPS64R5) + || (ISA) == ISA_MIPS64R5 \ + || (ISA) == ISA_MIPS64R6) /* Return true if ISA supports 64 bit wide float registers. */ #define ISA_HAS_64BIT_FPRS(ISA) \ @@ -368,10 +376,12 @@ static int mips_32bitmode = 0; || (ISA) == ISA_MIPS32R2 \ || (ISA) == ISA_MIPS32R3 \ || (ISA) == ISA_MIPS32R5 \ + || (ISA) == ISA_MIPS32R6 \ || (ISA) == ISA_MIPS64 \ || (ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R3 \ - || (ISA) == ISA_MIPS64R5 ) + || (ISA) == ISA_MIPS64R5 \ + || (ISA) == ISA_MIPS64R6) /* Return true if ISA supports 64-bit right rotate (dror et al.) instructions. */ @@ -379,6 +389,7 @@ static int mips_32bitmode = 0; ((ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R3 \ || (ISA) == ISA_MIPS64R5 \ + || (ISA) == ISA_MIPS64R6 \ || (mips_opts.micromips \ && ISA_HAS_64BIT_REGS (ISA)) \ ) @@ -389,9 +400,11 @@ static int mips_32bitmode = 0; ((ISA) == ISA_MIPS32R2 \ || (ISA) == ISA_MIPS32R3 \ || (ISA) == ISA_MIPS32R5 \ + || (ISA) == ISA_MIPS32R6 \ || (ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R3 \ || (ISA) == ISA_MIPS64R5 \ + || (ISA) == ISA_MIPS64R6 \ || (mips_opts.ase & ASE_SMARTMIPS) \ || mips_opts.micromips \ ) @@ -402,10 +415,12 @@ static int mips_32bitmode = 0; || (ISA) == ISA_MIPS32R2 \ || (ISA) == ISA_MIPS32R3 \ || (ISA) == ISA_MIPS32R5 \ + || (ISA) == ISA_MIPS32R6 \ || (ISA) == ISA_MIPS64 \ || (ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R3 \ || (ISA) == ISA_MIPS64R5 \ + || (ISA) == ISA_MIPS64R6 \ || (CPU) == CPU_R5900) \ && (CPU) != CPU_LOONGSON_3A) @@ -415,6 +430,24 @@ static int mips_32bitmode = 0; ((ISA) == ISA_MIPS32R2 \ || (ISA) == ISA_MIPS32R3 \ || (ISA) == ISA_MIPS32R5 \ + || (ISA) == ISA_MIPS32R6 \ + || (ISA) == ISA_MIPS64R2 \ + || (ISA) == ISA_MIPS64R3 \ + || (ISA) == ISA_MIPS64R5 \ + || (ISA) == ISA_MIPS64R6) + +/* Return true if ISA supports legacy NAN. */ +#define ISA_HAS_LEGACY_NAN(ISA) \ + ((ISA) == ISA_MIPS1 \ + || (ISA) == ISA_MIPS2 \ + || (ISA) == ISA_MIPS3 \ + || (ISA) == ISA_MIPS4 \ + || (ISA) == ISA_MIPS5 \ + || (ISA) == ISA_MIPS32 \ + || (ISA) == ISA_MIPS32R2 \ + || (ISA) == ISA_MIPS32R3 \ + || (ISA) == ISA_MIPS32R5 \ + || (ISA) == ISA_MIPS64 \ || (ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R3 \ || (ISA) == ISA_MIPS64R5) @@ -503,10 +536,12 @@ static int mips_32bitmode = 0; || mips_opts.isa == ISA_MIPS32R2 \ || mips_opts.isa == ISA_MIPS32R3 \ || mips_opts.isa == ISA_MIPS32R5 \ + || mips_opts.isa == ISA_MIPS32R6 \ || mips_opts.isa == ISA_MIPS64 \ || mips_opts.isa == ISA_MIPS64R2 \ || mips_opts.isa == ISA_MIPS64R3 \ || mips_opts.isa == ISA_MIPS64R5 \ + || mips_opts.isa == ISA_MIPS64R6 \ || mips_opts.arch == CPU_R4010 \ || mips_opts.arch == CPU_R5900 \ || mips_opts.arch == CPU_R10000 \ @@ -1351,9 +1386,11 @@ enum options OPTION_MIPS32R2, OPTION_MIPS32R3, OPTION_MIPS32R5, + OPTION_MIPS32R6, OPTION_MIPS64R2, OPTION_MIPS64R3, OPTION_MIPS64R5, + OPTION_MIPS64R6, OPTION_MIPS16, OPTION_NO_MIPS16, OPTION_MIPS3D, @@ -1463,9 +1500,11 @@ struct option md_longopts[] = {"mips32r2", no_argument, NULL, OPTION_MIPS32R2}, {"mips32r3", no_argument, NULL, OPTION_MIPS32R3}, {"mips32r5", no_argument, NULL, OPTION_MIPS32R5}, + {"mips32r6", no_argument, NULL, OPTION_MIPS32R6}, {"mips64r2", no_argument, NULL, OPTION_MIPS64R2}, {"mips64r3", no_argument, NULL, OPTION_MIPS64R3}, {"mips64r5", no_argument, NULL, OPTION_MIPS64R5}, + {"mips64r6", no_argument, NULL, OPTION_MIPS64R6}, /* Options which specify Application Specific Extensions (ASEs). */ {"mips16", no_argument, NULL, OPTION_MIPS16}, @@ -1605,55 +1644,70 @@ struct mips_ase int mips64_rev; int micromips32_rev; int micromips64_rev; + + /* The architecture where the ASE was removed or -1 if the extension has not + been removed. */ + int rem_rev; }; /* A table of all supported ASEs. */ static const struct mips_ase mips_ases[] = { { "dsp", ASE_DSP, ASE_DSP64, OPTION_DSP, OPTION_NO_DSP, - 2, 2, 2, 2 }, + 2, 2, 2, 2, + -1 }, { "dspr2", ASE_DSP | ASE_DSPR2, 0, OPTION_DSPR2, OPTION_NO_DSPR2, - 2, 2, 2, 2 }, + 2, 2, 2, 2, + -1 }, { "eva", ASE_EVA, 0, OPTION_EVA, OPTION_NO_EVA, - 2, 2, 2, 2 }, + 2, 2, 2, 2, + -1 }, { "mcu", ASE_MCU, 0, OPTION_MCU, OPTION_NO_MCU, - 2, 2, 2, 2 }, + 2, 2, 2, 2, + -1 }, /* Deprecated in MIPS64r5, but we don't implement that yet. */ { "mdmx", ASE_MDMX, 0, OPTION_MDMX, OPTION_NO_MDMX, - -1, 1, -1, -1 }, + -1, 1, -1, -1, + 6 }, /* Requires 64-bit FPRs, so the minimum MIPS32 revision is 2. */ { "mips3d", ASE_MIPS3D, 0, OPTION_MIPS3D, OPTION_NO_MIPS3D, - 2, 1, -1, -1 }, + 2, 1, -1, -1, + 6 }, { "mt", ASE_MT, 0, OPTION_MT, OPTION_NO_MT, - 2, 2, -1, -1 }, + 2, 2, -1, -1, + -1 }, { "smartmips", ASE_SMARTMIPS, 0, OPTION_SMARTMIPS, OPTION_NO_SMARTMIPS, - 1, -1, -1, -1 }, + 1, -1, -1, -1, + 6 }, { "virt", ASE_VIRT, ASE_VIRT64, OPTION_VIRT, OPTION_NO_VIRT, - 2, 2, 2, 2 }, + 2, 2, 2, 2, + -1 }, { "msa", ASE_MSA, ASE_MSA64, OPTION_MSA, OPTION_NO_MSA, - 2, 2, 2, 2 }, + 2, 2, 2, 2, + -1 }, { "xpa", ASE_XPA, 0, OPTION_XPA, OPTION_NO_XPA, - 2, 2, -1, -1 } + 2, 2, -1, -1, + -1 }, }; /* The set of ASEs that require -mfp64. */ @@ -1915,6 +1969,9 @@ mips_isa_rev (void) if (mips_opts.isa == ISA_MIPS32R5 || mips_opts.isa == ISA_MIPS64R5) return 5; + if (mips_opts.isa == ISA_MIPS32R6 || mips_opts.isa == ISA_MIPS64R6) + return 6; + /* microMIPS implies revision 2 or above. */ if (mips_opts.micromips) return 2; @@ -1966,6 +2023,16 @@ mips_check_isa_supports_ase (const struct mips_ase *ase) as_warn (_("the `%s' extension requires %s%d revision %d or greater"), ase->name, base, size, min_rev); } + else if ((ase->rem_rev > 0 && mips_isa_rev () >= ase->rem_rev) + && (warned_isa & ase->flags) != ase->flags) + { + warned_isa |= ase->flags; + base = mips_opts.micromips ? "microMIPS" : "MIPS"; + size = ISA_HAS_64BIT_REGS (mips_opts.isa) ? 64 : 32; + as_warn (_("the `%s' extension was removed in %s%d revision %d"), + ase->name, base, size, ase->rem_rev); + } + if ((ase->flags & FP64_ASES) && mips_opts.fp != 64 && (warned_fp32 & ase->flags) != ase->flags) @@ -3294,7 +3361,7 @@ validate_mips_insn (const struct mips_opcode *opcode, used_bits &= ~(mask & 0x700); } /* Skip prefix characters. */ - if (decode_operand && (*s == '+' || *s == 'm')) + if (decode_operand && (*s == '+' || *s == 'm' || *s == '-')) ++s; opno += 1; break; @@ -3772,6 +3839,8 @@ mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks) if (abi_checks && ABI_NEEDS_64BIT_REGS (mips_abi)) as_warn (_("`fp=32' used with a 64-bit ABI")); + if (ISA_IS_R6 (mips_opts.isa) && opts->single_float == 0) + as_bad (_("`fp=32' used with a MIPS R6 cpu")); break; default: as_bad (_("Unknown size of floating point registers")); @@ -3783,6 +3852,16 @@ mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks) if (opts->micromips == 1 && opts->mips16 == 1) as_bad (_("`mips16' cannot be used with `micromips'")); + else if (ISA_IS_R6 (mips_opts.isa) + && (opts->micromips == 1 + || opts->mips16 == 1)) + as_fatal (_("`%s' can not be used with `%s'"), + opts->micromips ? "micromips" : "mips16", + mips_cpu_info_from_isa (mips_opts.isa)->name); + + if (ISA_IS_R6 (opts->isa) && mips_relax_branch) + as_fatal (_("branch relaxation is not supported in `%s'"), + mips_cpu_info_from_isa (opts->isa)->name); } /* Perform consistency checks on the module level options exactly once. @@ -3831,6 +3910,9 @@ file_mips_check_options (void) && ISA_HAS_64BIT_FPRS (file_mips_opts.isa)) /* Handle ASEs that require 64-bit float registers, if possible. */ file_mips_opts.fp = 64; + else if (ISA_IS_R6 (mips_opts.isa)) + /* R6 implies 64-bit float registers. */ + file_mips_opts.fp = 64; else /* 32-bit float registers. */ file_mips_opts.fp = 32; @@ -3868,6 +3950,12 @@ file_mips_check_options (void) file_mips_opts.micromips = (CPU_HAS_MICROMIPS (file_mips_opts.arch)) ? 1 : 0; + if (mips_nan2008 == -1) + mips_nan2008 = (ISA_HAS_LEGACY_NAN (file_mips_opts.isa)) ? 0 : 1; + else if (!ISA_HAS_LEGACY_NAN (file_mips_opts.isa) && mips_nan2008 == 0) + as_fatal (_("`%s' does not support legacy NaN"), + mips_cpu_info_from_arch (file_mips_opts.arch)->name); + /* Some ASEs require 64-bit FPRs, so -mfp32 should stop those ASEs from being selected implicitly. */ if (file_mips_opts.fp != 64) @@ -4047,9 +4135,15 @@ limited_pcrel_reloc_p (bfd_reloc_code_real_type reloc) case BFD_RELOC_MICROMIPS_7_PCREL_S1: case BFD_RELOC_MICROMIPS_10_PCREL_S1: case BFD_RELOC_MICROMIPS_16_PCREL_S1: + case BFD_RELOC_MIPS_21_PCREL_S2: + case BFD_RELOC_MIPS_26_PCREL_S2: + case BFD_RELOC_MIPS_18_PCREL_S3: + case BFD_RELOC_MIPS_19_PCREL_S2: return TRUE; case BFD_RELOC_32_PCREL: + case BFD_RELOC_HI16_S_PCREL: + case BFD_RELOC_LO16_PCREL: return HAVE_64BIT_ADDRESSES; default: @@ -4352,6 +4446,20 @@ operand_reg_mask (const struct mips_cl_insn *insn, uval = insn_extract_operand (insn, operand); return (1 << (uval & 31)) | (1 << (uval >> 5)); + case OP_SAME_RS_RT: + if (!(type_mask & (1 << OP_REG_GP))) + return 0; + uval = insn_extract_operand (insn, operand); + gas_assert ((uval & 31) == (uval >> 5)); + return 1 << (uval & 31); + + case OP_CHECK_PREV: + case OP_NON_ZERO_REG: + if (!(type_mask & (1 << OP_REG_GP))) + return 0; + uval = insn_extract_operand (insn, operand); + return 1 << (uval & 31); + case OP_LWM_SWM_LIST: abort (); @@ -5144,6 +5252,58 @@ match_clo_clz_dest_operand (struct mips_arg_info *arg, return TRUE; } +/* OP_CHECK_PREV matcher. */ + +static bfd_boolean +match_check_prev_operand (struct mips_arg_info *arg, + const struct mips_operand *operand_base) +{ + const struct mips_check_prev_operand *operand; + unsigned int regno; + + operand = (const struct mips_check_prev_operand *) operand_base; + + if (!match_reg (arg, OP_REG_GP, ®no)) + return FALSE; + + if (!operand->zero_ok && regno == 0) + return FALSE; + + if ((operand->less_than_ok && regno < arg->last_regno) + || (operand->greater_than_ok && regno > arg->last_regno) + || (operand->equal_ok && regno == arg->last_regno)) + { + arg->last_regno = regno; + insn_insert_operand (arg->insn, operand_base, regno); + return TRUE; + } + + return FALSE; +} + +/* OP_SAME_RS_RT matcher. */ + +static bfd_boolean +match_same_rs_rt_operand (struct mips_arg_info *arg, + const struct mips_operand *operand) +{ + unsigned int regno; + + if (!match_reg (arg, OP_REG_GP, ®no)) + return FALSE; + + if (regno == 0) + { + set_insn_error (arg->argnum, _("the source register must not be $0")); + return FALSE; + } + + arg->last_regno = regno; + + insn_insert_operand (arg->insn, operand, regno | (regno << 5)); + return TRUE; +} + /* OP_LWM_SWM_LIST matcher. */ static bfd_boolean @@ -5537,6 +5697,25 @@ match_pc_operand (struct mips_arg_info *arg) return FALSE; } +/* OP_NON_ZERO_REG matcher. */ + +static bfd_boolean +match_non_zero_reg_operand (struct mips_arg_info *arg, + const struct mips_operand *operand) +{ + unsigned int regno; + + if (!match_reg (arg, OP_REG_GP, ®no)) + return FALSE; + + if (regno == 0) + return FALSE; + + arg->last_regno = regno; + insn_insert_operand (arg->insn, operand, regno); + return TRUE; +} + /* OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG matcher. OTHER_REGNO is the register that we need to match. */ @@ -5813,6 +5992,15 @@ match_operand (struct mips_arg_info *arg, case OP_REG_INDEX: return match_reg_index_operand (arg, operand); + + case OP_SAME_RS_RT: + return match_same_rs_rt_operand (arg, operand); + + case OP_CHECK_PREV: + return match_check_prev_operand (arg, operand); + + case OP_NON_ZERO_REG: + return match_non_zero_reg_operand (arg, operand); } abort (); } @@ -6013,6 +6201,14 @@ insns_between (const struct mips_cl_insn *insn1, return 1; } + /* Forbidden slots can not contain Control Transfer Instructions (CTIs) + CTIs include all branches and jumps, nal, eret, eretnc, deret, wait + and pause. */ + if ((insn1->insn_mo->pinfo2 & INSN2_FORBIDDEN_SLOT) + && ((pinfo2 & INSN_NO_DELAY_SLOT) + || (insn2 && delayed_branch_p (insn2)))) + return 1; + return 0; } @@ -6870,6 +7066,40 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, } break; + case BFD_RELOC_MIPS_21_PCREL_S2: + { + int shift; + + shift = 2; + if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0) + as_bad (_("branch to misaligned address (0x%lx)"), + (unsigned long) address_expr->X_add_number); + if ((address_expr->X_add_number + (1 << (shift + 20))) + & ~((1 << (shift + 21)) - 1)) + as_bad (_("branch address range overflow (0x%lx)"), + (unsigned long) address_expr->X_add_number); + ip->insn_opcode |= ((address_expr->X_add_number >> shift) + & 0x1fffff); + } + break; + + case BFD_RELOC_MIPS_26_PCREL_S2: + { + int shift; + + shift = 2; + if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0) + as_bad (_("branch to misaligned address (0x%lx)"), + (unsigned long) address_expr->X_add_number); + if ((address_expr->X_add_number + (1 << (shift + 25))) + & ~((1 << (shift + 26)) - 1)) + as_bad (_("branch address range overflow (0x%lx)"), + (unsigned long) address_expr->X_add_number); + ip->insn_opcode |= ((address_expr->X_add_number >> shift) + & 0x3ffffff); + } + break; + default: { offsetT value; @@ -7534,12 +7764,33 @@ match_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode, arg.opnum += 1; switch (*args) { + case '-': + switch (args[1]) + { + case 'A': + *offset_reloc = BFD_RELOC_MIPS_19_PCREL_S2; + break; + + case 'B': + *offset_reloc = BFD_RELOC_MIPS_18_PCREL_S3; + break; + } + break; + case '+': switch (args[1]) { case 'i': *offset_reloc = BFD_RELOC_MIPS_JMP; break; + + case '\'': + *offset_reloc = BFD_RELOC_MIPS_26_PCREL_S2; + break; + + case '\"': + *offset_reloc = BFD_RELOC_MIPS_21_PCREL_S2; + break; } break; @@ -7625,7 +7876,7 @@ match_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode, abort (); /* Skip prefixes. */ - if (*args == '+' || *args == 'm') + if (*args == '+' || *args == 'm' || *args == '-') args++; if (mips_optional_operand_p (operand) @@ -8095,10 +8346,13 @@ static const char * const shft_fmt[2] = { "d,w,<", "t,r,<" }; static const char * const trap_fmt[2] = { "s,t,q", "s,t,|" }; #define BRK_FMT (brk_fmt[mips_opts.micromips][mips_opts.insn32]) -#define COP12_FMT (cop12_fmt[mips_opts.micromips]) +#define COP12_FMT (ISA_IS_R6 (mips_opts.isa) ? "E,+:(d)" \ + : cop12_fmt[mips_opts.micromips]) #define JALR_FMT (jalr_fmt[mips_opts.micromips]) #define LUI_FMT (lui_fmt[mips_opts.micromips]) #define MEM12_FMT (mem12_fmt[mips_opts.micromips]) +#define LL_SC_FMT (ISA_IS_R6 (mips_opts.isa) ? "t,+j(b)" \ + : mem12_fmt[mips_opts.micromips]) #define MFHL_FMT (mfhl_fmt[mips_opts.micromips][mips_opts.insn32]) #define SHFT_FMT (shft_fmt[mips_opts.micromips]) #define TRAP_FMT (trap_fmt[mips_opts.micromips]) @@ -8276,7 +8530,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) uval |= (uval << 5); insn_insert_operand (&insn, operand, uval); - if (*fmt == '+' || *fmt == 'm') + if (*fmt == '+' || *fmt == 'm' || *fmt == '-') ++fmt; break; } @@ -11045,7 +11299,9 @@ macro (struct mips_cl_insn *ip, char *str) case M_LWC2_AB: s = "lwc2"; fmt = COP12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 11 + : 16); /* Itbl support may require additional care here. */ coproc = 1; goto ld_st; @@ -11075,7 +11331,9 @@ macro (struct mips_cl_insn *ip, char *str) case M_LDC2_AB: s = "ldc2"; fmt = COP12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 11 + : 16); /* Itbl support may require additional care here. */ coproc = 1; goto ld_st; @@ -11103,13 +11361,17 @@ macro (struct mips_cl_insn *ip, char *str) goto ld_st; case M_LL_AB: s = "ll"; - fmt = MEM12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + fmt = LL_SC_FMT; + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 9 + : 16); goto ld; case M_LLD_AB: s = "lld"; - fmt = MEM12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + fmt = LL_SC_FMT; + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 9 + : 16); goto ld; case M_LWU_AB: s = "lwu"; @@ -11179,7 +11441,9 @@ macro (struct mips_cl_insn *ip, char *str) case M_SWC2_AB: s = "swc2"; fmt = COP12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 11 + : 16); /* Itbl support may require additional care here. */ coproc = 1; goto ld_st; @@ -11202,18 +11466,26 @@ macro (struct mips_cl_insn *ip, char *str) goto ld_st; case M_SC_AB: s = "sc"; - fmt = MEM12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + fmt = LL_SC_FMT; + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 9 + : 16); goto ld_st; case M_SCD_AB: s = "scd"; - fmt = MEM12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + fmt = LL_SC_FMT; + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 9 + : 16); goto ld_st; case M_CACHE_AB: s = "cache"; - fmt = mips_opts.micromips ? "k,~(b)" : "k,o(b)"; - offbits = (mips_opts.micromips ? 12 : 16); + fmt = (mips_opts.micromips ? "k,~(b)" + : ISA_IS_R6 (mips_opts.isa) ? "k,+j(b)" + : "k,o(b)"); + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 9 + : 16); goto ld_st; case M_CACHEE_AB: s = "cachee"; @@ -11222,8 +11494,12 @@ macro (struct mips_cl_insn *ip, char *str) goto ld_st; case M_PREF_AB: s = "pref"; - fmt = !mips_opts.micromips ? "k,o(b)" : "k,~(b)"; - offbits = (mips_opts.micromips ? 12 : 16); + fmt = (mips_opts.micromips ? "k,~(b)" + : ISA_IS_R6 (mips_opts.isa) ? "k,+j(b)" + : "k,o(b)"); + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 9 + : 16); goto ld_st; case M_PREFE_AB: s = "prefe"; @@ -11239,7 +11515,9 @@ macro (struct mips_cl_insn *ip, char *str) case M_SDC2_AB: s = "sdc2"; fmt = COP12_FMT; - offbits = (mips_opts.micromips ? 12 : 16); + offbits = (mips_opts.micromips ? 12 + : ISA_IS_R6 (mips_opts.isa) ? 11 + : 16); /* Itbl support may require additional care here. */ coproc = 1; goto ld_st; @@ -13566,7 +13844,9 @@ static const struct percent_op_match mips_percent_op[] = {"%tprel_hi", BFD_RELOC_MIPS_TLS_TPREL_HI16}, {"%tprel_lo", BFD_RELOC_MIPS_TLS_TPREL_LO16}, {"%gottprel", BFD_RELOC_MIPS_TLS_GOTTPREL}, - {"%hi", BFD_RELOC_HI16_S} + {"%hi", BFD_RELOC_HI16_S}, + {"%pcrel_hi", BFD_RELOC_HI16_S_PCREL}, + {"%pcrel_lo", BFD_RELOC_LO16_PCREL} }; static const struct percent_op_match mips16_percent_op[] = @@ -13844,6 +14124,10 @@ md_parse_option (int c, char *arg) file_mips_opts.isa = ISA_MIPS32R5; break; + case OPTION_MIPS32R6: + file_mips_opts.isa = ISA_MIPS32R6; + break; + case OPTION_MIPS64R2: file_mips_opts.isa = ISA_MIPS64R2; break; @@ -13856,6 +14140,10 @@ md_parse_option (int c, char *arg) file_mips_opts.isa = ISA_MIPS64R5; break; + case OPTION_MIPS64R6: + file_mips_opts.isa = ISA_MIPS64R6; + break; + case OPTION_MIPS64: file_mips_opts.isa = ISA_MIPS64; break; @@ -14161,9 +14449,9 @@ md_parse_option (int c, char *arg) case OPTION_NAN: if (strcmp (arg, "2008") == 0) - mips_flag_nan2008 = TRUE; + mips_nan2008 = 1; else if (strcmp (arg, "legacy") == 0) - mips_flag_nan2008 = FALSE; + mips_nan2008 = 0; else { as_fatal (_("invalid NaN setting -mnan=%s"), arg); @@ -14290,6 +14578,8 @@ md_pcrel_from (fixS *fixP) case BFD_RELOC_MICROMIPS_16_PCREL_S1: case BFD_RELOC_MICROMIPS_JMP: case BFD_RELOC_16_PCREL_S2: + case BFD_RELOC_MIPS_21_PCREL_S2: + case BFD_RELOC_MIPS_26_PCREL_S2: case BFD_RELOC_MIPS_JMP: /* Return the address of the delay slot. */ return addr + 4; @@ -14455,6 +14745,17 @@ mips_force_relocation (fixS *fixp) || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1) return 1; + /* We want all PC-relative relocations to be kept for R6 relaxation. */ + if (ISA_IS_R6 (mips_opts.isa) + && (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_MIPS_21_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_MIPS_18_PCREL_S3 + || fixp->fx_r_type == BFD_RELOC_MIPS_19_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL + || fixp->fx_r_type == BFD_RELOC_LO16_PCREL)) + return 1; + return 0; } @@ -14499,6 +14800,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_MICROMIPS_10_PCREL_S1: case BFD_RELOC_MICROMIPS_16_PCREL_S1: case BFD_RELOC_32_PCREL: + case BFD_RELOC_MIPS_21_PCREL_S2: + case BFD_RELOC_MIPS_26_PCREL_S2: + case BFD_RELOC_MIPS_18_PCREL_S3: + case BFD_RELOC_MIPS_19_PCREL_S2: + case BFD_RELOC_HI16_S_PCREL: + case BFD_RELOC_LO16_PCREL: break; case BFD_RELOC_32: @@ -14691,6 +14998,38 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) md_number_to_chars (buf, *valP, fixP->fx_size); break; + case BFD_RELOC_MIPS_21_PCREL_S2: + case BFD_RELOC_MIPS_26_PCREL_S2: + if ((*valP & 0x3) != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("branch to misaligned address (%lx)"), (long) *valP); + + gas_assert (!fixP->fx_done); + break; + + case BFD_RELOC_MIPS_18_PCREL_S3: + if ((*valP & 0x7) != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("PC-relative access to misaligned address (%lx)"), + (long) *valP); + + gas_assert (!fixP->fx_done); + break; + + case BFD_RELOC_MIPS_19_PCREL_S2: + if ((*valP & 0x3) != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("PC-relative access to misaligned address (%lx)"), + (long) *valP); + + gas_assert (!fixP->fx_done); + break; + + case BFD_RELOC_HI16_S_PCREL: + case BFD_RELOC_LO16_PCREL: + gas_assert (!fixP->fx_done); + break; + case BFD_RELOC_16_PCREL_S2: if ((*valP & 0x3) != 0) as_bad_where (fixP->fx_file, fixP->fx_line, @@ -15369,6 +15708,10 @@ s_mipsset (int x ATTRIBUTE_UNUSED) if (mips_opts.fp != 0) mips_opts.fp = 32; break; + case ISA_MIPS32R6: + mips_opts.gp = 32; + mips_opts.fp = 64; + break; case ISA_MIPS3: case ISA_MIPS4: case ISA_MIPS5: @@ -15376,6 +15719,7 @@ s_mipsset (int x ATTRIBUTE_UNUSED) case ISA_MIPS64R2: case ISA_MIPS64R3: case ISA_MIPS64R5: + case ISA_MIPS64R6: mips_opts.gp = 64; if (mips_opts.fp != 0) { @@ -16018,10 +16362,16 @@ s_nan (int ignore ATTRIBUTE_UNUSED) if (i == sizeof (str_2008) - 1 && memcmp (input_line_pointer, str_2008, i) == 0) - mips_flag_nan2008 = TRUE; + mips_nan2008 = 1; else if (i == sizeof (str_legacy) - 1 && memcmp (input_line_pointer, str_legacy, i) == 0) - mips_flag_nan2008 = FALSE; + { + if (ISA_HAS_LEGACY_NAN (file_mips_opts.isa)) + mips_nan2008 = 0; + else + as_bad (_("`%s' does not support legacy NaN"), + mips_cpu_info_from_isa (file_mips_opts.isa)->name); + } else as_bad (_("bad .nan directive")); @@ -16718,8 +17068,11 @@ mips_fix_adjustable (fixS *fixp) /* There is no place to store an in-place offset for JALR relocations. Likewise an in-range offset of limited PC-relative relocations may overflow the in-place relocatable field if recalculated against the - start address of the symbol's containing section. */ - if (HAVE_IN_PLACE_ADDENDS + start address of the symbol's containing section. + + Also, PC relative relocations for MIPS R6 need to be symbol rather than + section relative to allow linker relaxations to be performed later on. */ + if ((HAVE_IN_PLACE_ADDENDS || ISA_IS_R6 (mips_opts.isa)) && (limited_pcrel_reloc_p (fixp->fx_r_type) || jalr_reloc_p (fixp->fx_r_type))) return 0; @@ -16799,7 +17152,13 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) || fixp->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1 - || fixp->fx_r_type == BFD_RELOC_32_PCREL); + || fixp->fx_r_type == BFD_RELOC_32_PCREL + || fixp->fx_r_type == BFD_RELOC_MIPS_21_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_MIPS_18_PCREL_S3 + || fixp->fx_r_type == BFD_RELOC_MIPS_19_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL + || fixp->fx_r_type == BFD_RELOC_LO16_PCREL); /* At this point, fx_addnumber is "symbol offset - pcrel address". Relocations want only the symbol offset. */ @@ -17724,7 +18083,7 @@ mips_elf_final_processing (void) if (mips_32bitmode) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_32BITMODE; - if (mips_flag_nan2008) + if (mips_nan2008 == 1) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_NAN2008; /* 32 bit code with 64 bit FP registers. */ @@ -18170,10 +18529,12 @@ static const struct mips_cpu_info mips_cpu_info_table[] = { "mips32r2", MIPS_CPU_IS_ISA, 0, ISA_MIPS32R2, CPU_MIPS32R2 }, { "mips32r3", MIPS_CPU_IS_ISA, 0, ISA_MIPS32R3, CPU_MIPS32R3 }, { "mips32r5", MIPS_CPU_IS_ISA, 0, ISA_MIPS32R5, CPU_MIPS32R5 }, + { "mips32r6", MIPS_CPU_IS_ISA, 0, ISA_MIPS32R6, CPU_MIPS32R6 }, { "mips64", MIPS_CPU_IS_ISA, 0, ISA_MIPS64, CPU_MIPS64 }, { "mips64r2", MIPS_CPU_IS_ISA, 0, ISA_MIPS64R2, CPU_MIPS64R2 }, { "mips64r3", MIPS_CPU_IS_ISA, 0, ISA_MIPS64R3, CPU_MIPS64R3 }, { "mips64r5", MIPS_CPU_IS_ISA, 0, ISA_MIPS64R5, CPU_MIPS64R5 }, + { "mips64r6", MIPS_CPU_IS_ISA, 0, ISA_MIPS64R6, CPU_MIPS64R6 }, /* MIPS I */ { "r3000", 0, 0, ISA_MIPS1, CPU_R3000 }, @@ -18489,10 +18850,12 @@ MIPS options:\n\ -mips32r2 generate MIPS32 release 2 ISA instructions\n\ -mips32r3 generate MIPS32 release 3 ISA instructions\n\ -mips32r5 generate MIPS32 release 5 ISA instructions\n\ +-mips32r6 generate MIPS32 release 6 ISA instructions\n\ -mips64 generate MIPS64 ISA instructions\n\ -mips64r2 generate MIPS64 release 2 ISA instructions\n\ -mips64r3 generate MIPS64 release 3 ISA instructions\n\ -mips64r5 generate MIPS64 release 5 ISA instructions\n\ +-mips64r6 generate MIPS64 release 6 ISA instructions\n\ -march=CPU/-mtune=CPU generate code/schedule for CPU, where CPU is one of:\n")); first = 1; |