summaryrefslogtreecommitdiffstats
path: root/binutils-2.25/gas/config/tc-mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.25/gas/config/tc-mips.c')
-rw-r--r--binutils-2.25/gas/config/tc-mips.c184
1 files changed, 172 insertions, 12 deletions
diff --git a/binutils-2.25/gas/config/tc-mips.c b/binutils-2.25/gas/config/tc-mips.c
index cfc4fa54..0f7e0c58 100644
--- a/binutils-2.25/gas/config/tc-mips.c
+++ b/binutils-2.25/gas/config/tc-mips.c
@@ -1409,10 +1409,14 @@ enum options
OPTION_NO_SMARTMIPS,
OPTION_DSPR2,
OPTION_NO_DSPR2,
+ OPTION_DSPR6,
+ OPTION_NO_DSPR6,
OPTION_EVA,
OPTION_NO_EVA,
OPTION_XPA,
OPTION_NO_XPA,
+ OPTION_MXU,
+ OPTION_NO_MXU,
OPTION_MICROMIPS,
OPTION_NO_MICROMIPS,
OPTION_MCU,
@@ -1521,6 +1525,8 @@ struct option md_longopts[] =
{"mno-smartmips", no_argument, NULL, OPTION_NO_SMARTMIPS},
{"mdspr2", no_argument, NULL, OPTION_DSPR2},
{"mno-dspr2", no_argument, NULL, OPTION_NO_DSPR2},
+ {"mdspr6", no_argument, NULL, OPTION_DSPR6},
+ {"mno-dspr6", no_argument, NULL, OPTION_NO_DSPR6},
{"meva", no_argument, NULL, OPTION_EVA},
{"mno-eva", no_argument, NULL, OPTION_NO_EVA},
{"mmicromips", no_argument, NULL, OPTION_MICROMIPS},
@@ -1533,6 +1539,8 @@ struct option md_longopts[] =
{"mno-msa", no_argument, NULL, OPTION_NO_MSA},
{"mxpa", no_argument, NULL, OPTION_XPA},
{"mno-xpa", no_argument, NULL, OPTION_NO_XPA},
+ {"mmxu", no_argument, NULL, OPTION_MXU},
+ {"mno-mxu", no_argument, NULL, OPTION_NO_MXU},
/* Old-style architecture options. Don't add more of these. */
{"m4650", no_argument, NULL, OPTION_M4650},
@@ -1662,6 +1670,11 @@ static const struct mips_ase mips_ases[] = {
2, 2, 2, 2,
-1 },
+ { "dspr6", ASE_DSP | ASE_DSPR2 | ASE_DSPR6, 0,
+ OPTION_DSPR6, OPTION_NO_DSPR6,
+ 6, 6, 6, 6,
+ -1 },
+
{ "eva", ASE_EVA, 0,
OPTION_EVA, OPTION_NO_EVA,
2, 2, 2, 2,
@@ -1708,6 +1721,11 @@ static const struct mips_ase mips_ases[] = {
OPTION_XPA, OPTION_NO_XPA,
2, 2, -1, -1,
-1 },
+
+ { "mxu", ASE_MXU, 0,
+ OPTION_MXU, OPTION_NO_MXU,
+ 1, 1, -1, -1,
+ -1 },
};
/* The set of ASEs that require -mfp64. */
@@ -1715,7 +1733,7 @@ static const struct mips_ase mips_ases[] = {
/* Groups of ASE_* flags that represent different revisions of an ASE. */
static const unsigned int mips_ase_groups[] = {
- ASE_DSP | ASE_DSPR2
+ ASE_DSP | ASE_DSPR2 | ASE_DSPR6
};
/* Pseudo-op table.
@@ -2490,7 +2508,7 @@ struct regname {
};
#define RNUM_MASK 0x00000ff
-#define RTYPE_MASK 0x0ffff00
+#define RTYPE_MASK 0x1ffff00
#define RTYPE_NUM 0x0000100
#define RTYPE_FPU 0x0000200
#define RTYPE_FCC 0x0000400
@@ -2507,6 +2525,7 @@ struct regname {
#define RTYPE_R5900_R 0x0200000
#define RTYPE_R5900_ACC 0x0400000
#define RTYPE_MSA 0x0800000
+#define RTYPE_MXU 0x1000000
#define RWARN 0x8000000
#define GENERIC_REGISTER_NUMBERS \
@@ -2711,6 +2730,26 @@ struct regname {
{"$ac2", RTYPE_ACC | 2}, \
{"$ac3", RTYPE_ACC | 3}
+#define MXU_REGISTER_NAMES \
+ {"xr0", RTYPE_MXU | 0}, \
+ {"xr1", RTYPE_MXU | 1}, \
+ {"xr2", RTYPE_MXU | 2}, \
+ {"xr3", RTYPE_MXU | 3}, \
+ {"xr4", RTYPE_MXU | 4}, \
+ {"xr5", RTYPE_MXU | 5}, \
+ {"xr6", RTYPE_MXU | 6}, \
+ {"xr7", RTYPE_MXU | 7}, \
+ {"xr8", RTYPE_MXU | 8}, \
+ {"xr9", RTYPE_MXU | 9}, \
+ {"xr10", RTYPE_MXU | 10}, \
+ {"xr11", RTYPE_MXU | 11}, \
+ {"xr12", RTYPE_MXU | 12}, \
+ {"xr13", RTYPE_MXU | 13}, \
+ {"xr14", RTYPE_MXU | 14}, \
+ {"xr15", RTYPE_MXU | 15}, \
+ {"xr16", RTYPE_MXU | 16}, \
+ {"mxu_cr", RTYPE_MXU | 16}
+
static const struct regname reg_names[] = {
GENERIC_REGISTER_NUMBERS,
FPU_REGISTER_NAMES,
@@ -2730,6 +2769,7 @@ static const struct regname reg_names[] = {
R5900_R_NAMES,
R5900_ACC_NAMES,
MIPS_DSP_ACCUMULATOR_NAMES,
+ MXU_REGISTER_NAMES,
{0, 0}
};
@@ -3361,7 +3401,7 @@ validate_mips_insn (const struct mips_opcode *opcode,
used_bits &= ~(mask & 0x700);
}
/* Skip prefix characters. */
- if (decode_operand && (*s == '+' || *s == 'm' || *s == '-'))
+ if (decode_operand && (*s == '+' || *s == 'm' || *s == '-' || *s == '`'))
++s;
opno += 1;
break;
@@ -4415,6 +4455,8 @@ operand_reg_mask (const struct mips_cl_insn *insn,
case OP_VU0_SUFFIX:
case OP_VU0_MATCH_SUFFIX:
case OP_IMM_INDEX:
+ case OP_MAPPED_STRING:
+ case OP_MXU_STRIDE:
abort ();
case OP_REG:
@@ -4788,6 +4830,12 @@ convert_reg_type (const struct mips_opcode *opcode,
{
switch (type)
{
+ case OP_REG_MXU:
+ return RTYPE_NUM | RTYPE_MXU;
+
+ case OP_REG_MXU_GP:
+ return RTYPE_GP | RTYPE_MXU;
+
case OP_REG_GP:
return RTYPE_NUM | RTYPE_GP;
@@ -5113,6 +5161,65 @@ match_msb_operand (struct mips_arg_info *arg,
return TRUE;
}
+
+/* OP_MAPPED_STRING matcher. */
+
+static bfd_boolean
+match_string_operand (struct mips_arg_info *arg,
+ const struct mips_operand *operand_base)
+{
+ const struct mips_mapped_string_operand *operand;
+ expressionS ex;
+ bfd_reloc_code_real_type r[3];
+ int i;
+ unsigned int store_val;
+ const char * symbol_name;
+ bfd_boolean match;
+
+ operand = (const struct mips_mapped_string_operand *) operand_base;
+
+ if (!match_expression (arg, &ex, r))
+ return FALSE;
+
+ if (operand->allow_constants && ex.X_op == O_constant
+ && r[0] == BFD_RELOC_UNUSED)
+ store_val = ex.X_add_number;
+ else if (r[0] == BFD_RELOC_UNUSED && ex.X_op == O_symbol
+ && ex.X_add_number == 0 && ex.X_op_symbol == NULL)
+ {
+ symbol_name = S_GET_NAME (ex.X_add_symbol);
+ match = FALSE;
+
+ for (i = 0 ; i < (1 << operand_base->size) ; i++)
+ {
+ if (strcmp (operand->strings[i], symbol_name) == 0)
+ {
+ store_val = i;
+ match = TRUE;
+ break;
+ }
+ }
+
+ if (!match)
+ {
+ set_insn_error (arg->argnum, _("Invalid string in operand"));
+ return FALSE;
+ }
+ }
+ else
+ return FALSE;
+
+ if (store_val >= (unsigned int) (1 << operand_base->size))
+ {
+ match_out_of_range (arg);
+ return FALSE;
+ }
+
+ insn_insert_operand (arg->insn, operand_base, store_val);
+ return TRUE;
+}
+
+
/* OP_REG matcher. */
static bfd_boolean
@@ -5138,6 +5245,13 @@ match_reg_operand (struct mips_arg_info *arg,
else
uval = regno;
+ if (operand_base->size > 0
+ && uval >= (unsigned int) (1 << operand_base->size))
+ {
+ match_out_of_range (arg);
+ return FALSE;
+ }
+
arg->last_regno = regno;
if (arg->opnum == 1)
arg->dest_regno = regno;
@@ -5665,6 +5779,24 @@ match_imm_index_operand (struct mips_arg_info *arg,
return TRUE;
}
+/* OP_MXU_STRIDE matcher. */
+
+static bfd_boolean
+match_mxu_stride_operand (struct mips_arg_info *arg,
+ const struct mips_operand *operand)
+{
+ offsetT sval;
+
+ if (!match_const_int (arg, &sval))
+ return FALSE;
+
+ if (sval < 0 || sval > 2)
+ return FALSE;
+
+ insn_insert_operand (arg->insn, operand, sval);
+ return TRUE;
+}
+
/* OP_REG_INDEX matcher. */
static bfd_boolean
@@ -5941,6 +6073,9 @@ match_operand (struct mips_arg_info *arg,
case OP_MSB:
return match_msb_operand (arg, operand);
+ case OP_MAPPED_STRING:
+ return match_string_operand (arg, operand);
+
case OP_REG:
case OP_OPTIONAL_REG:
return match_reg_operand (arg, operand);
@@ -6001,6 +6136,9 @@ match_operand (struct mips_arg_info *arg,
case OP_NON_ZERO_REG:
return match_non_zero_reg_operand (arg, operand);
+
+ case OP_MXU_STRIDE:
+ return match_mxu_stride_operand (arg, operand);
}
abort ();
}
@@ -6777,6 +6915,11 @@ get_append_method (struct mips_cl_insn *ip, expressionS *address_expr,
if (mips_relax.sequence == 2)
return APPEND_ADD;
+ /* Convert a non-compact to compact branch/jump instruction. */
+ if (ISA_IS_R6 (mips_opts.isa)
+ && (ip->insn_mo->pinfo2 & INSN2_CONVERTED_TO_COMPACT))
+ return APPEND_ADD_COMPACT;
+
/* We must not dabble with instructions in a ".set norerorder" block. */
if (mips_opts.noreorder)
return APPEND_ADD;
@@ -7455,12 +7598,20 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
break;
case APPEND_ADD_COMPACT:
- /* Convert MIPS16 jr/jalr into a "compact" jump. */
- gas_assert (mips_opts.mips16);
- ip->insn_opcode |= 0x0080;
- find_altered_mips16_opcode (ip);
- install_insn (ip);
- insert_into_history (0, 1, ip);
+ gas_assert(mips_opts.mips16 || ISA_IS_R6 (mips_opts.isa));
+ if (mips_opts.mips16)
+ {
+ /* Convert MIPS16 jr/jalr into a "compact" jump. */
+ ip->insn_opcode |= 0x0080;
+ find_altered_mips16_opcode (ip);
+ install_insn (ip);
+ insert_into_history (0, 1, ip);
+ }
+ else
+ {
+ install_insn (ip);
+ insert_into_history (0, 1, ip);
+ }
break;
case APPEND_SWAP:
@@ -7497,8 +7648,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
}
/* If we have just completed an unconditional branch, clear the history. */
- if ((delayed_branch_p (&history[1]) && uncond_branch_p (&history[1]))
+ if (((delayed_branch_p (&history[1]) && uncond_branch_p (&history[1]))
|| (compact_branch_p (&history[0]) && uncond_branch_p (&history[0])))
+ && !(history[0].insn_mo->pinfo2 & INSN2_CONVERTED_TO_COMPACT))
{
unsigned int i;
@@ -7876,7 +8028,7 @@ match_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
abort ();
/* Skip prefixes. */
- if (*args == '+' || *args == 'm' || *args == '-')
+ if (*args == '+' || *args == 'm' || *args == '-' || *args == '`')
args++;
if (mips_optional_operand_p (operand)
@@ -8530,7 +8682,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
uval |= (uval << 5);
insn_insert_operand (&insn, operand, uval);
- if (*fmt == '+' || *fmt == 'm' || *fmt == '-')
+ if (*fmt == '+' || *fmt == 'm' || *fmt == '-' || *fmt == '`')
++fmt;
break;
}
@@ -17906,6 +18058,8 @@ mips_convert_ase_flags (int ase)
ext_ases |= AFL_ASE_DSP;
if (ase & ASE_DSPR2)
ext_ases |= AFL_ASE_DSPR2;
+ if (ase & ASE_DSPR6)
+ ext_ases |= AFL_ASE_DSPR6;
if (ase & ASE_EVA)
ext_ases |= AFL_ASE_EVA;
if (ase & ASE_MCU)
@@ -18680,6 +18834,9 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
MIPS64R2 rather than MIPS64. */
{ "xlp", 0, 0, ISA_MIPS64R2, CPU_XLR },
+ /* i6400. */
+ { "i6400", 0, ASE_MSA, ISA_MIPS64R6, CPU_MIPS64R6},
+
/* End marker */
{ NULL, 0, 0, 0, 0 }
};
@@ -18918,6 +19075,9 @@ MIPS options:\n\
-mxpa generate eXtended Physical Address (XPA) instructions\n\
-mno-xpa do not generate eXtended Physical Address (XPA) instructions\n"));
fprintf (stream, _("\
+-mmxu generate MXU instructions\n\
+-mno-mxu do not generate MXU instructions\n"));
+ fprintf (stream, _("\
-mvirt generate Virtualization instructions\n\
-mno-virt do not generate Virtualization instructions\n"));
fprintf (stream, _("\