aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog23
-rw-r--r--gas/config/tc-mips.c778
-rw-r--r--gas/config/tc-mips.h3
3 files changed, 432 insertions, 372 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 077395a..5cf2850 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,4 +1,27 @@
2006-05-19 Thiemo Seufer <ths@mips.com>
+ David Ung <davidu@mips.com>
+
+ * config/tc-mips.h (tc_mips_regname_to_dw2regnum): Declare.
+ * config/tc-mipc.c (ABI_NEEDS_64BIT_REGS, ISA_HAS_64BIT_REGS,
+ ISA_HAS_DROR, ISA_HAS_ROR): Reformat.
+ (regname, RTYPE_MASK, RTYPE_NUM, RTYPE_FPU, RTYPE_FCC, RTYPE_VEC,
+ RTYPE_GP, RTYPE_CP0, RTYPE_PC, RTYPE_ACC, RTYPE_CCC, RNUM_MASK,
+ RWARN, GENERIC_REGISTER_NUMBERS, FPU_REGISTER_NAMES,
+ FPU_CONDITION_CODE_NAMES, COPROC_CONDITION_CODE_NAMES,
+ N32N64_SYMBOLIC_REGISTER_NAMES, O32_SYMBOLIC_REGISTER_NAMES,
+ SYMBOLIC_REGISTER_NAMES, MIPS16_SPECIAL_REGISTER_NAMES,
+ MDMX_VECTOR_REGISTER_NAMES, MIPS_DSP_ACCUMULATOR_NAMES, reg_names,
+ reg_names_o32, reg_names_n32n64): Define register classes.
+ (reg_lookup): New function, use register classes.
+ (md_begin): Reserve register names in the symbol table. Simplify
+ OBJ_ELF defines.
+ (mips_ip): Fix comment formatting. Handle symbolic COP0 registers.
+ Use reg_lookup.
+ (mips16_ip): Use reg_lookup.
+ (tc_get_register): Likewise.
+ (tc_mips_regname_to_dw2regnum): New function.
+
+2006-05-19 Thiemo Seufer <ths@mips.com>
* config/tc-arm.c, config/tc-arm.h (tc_arm_regname_to_dw2regnum):
Un-constify string argument.
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 75c3ae9..c33b4ff 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -301,33 +301,31 @@ static int mips_32bitmode = 0;
#define ABI_NEEDS_32BIT_REGS(ABI) ((ABI) == O32_ABI)
/* Likewise 64-bit registers. */
-#define ABI_NEEDS_64BIT_REGS(ABI) \
- ((ABI) == N32_ABI \
- || (ABI) == N64_ABI \
+#define ABI_NEEDS_64BIT_REGS(ABI) \
+ ((ABI) == N32_ABI \
+ || (ABI) == N64_ABI \
|| (ABI) == O64_ABI)
/* Return true if ISA supports 64 bit gp register instructions. */
-#define ISA_HAS_64BIT_REGS(ISA) ( \
- (ISA) == ISA_MIPS3 \
- || (ISA) == ISA_MIPS4 \
- || (ISA) == ISA_MIPS5 \
- || (ISA) == ISA_MIPS64 \
- || (ISA) == ISA_MIPS64R2 \
- )
+#define ISA_HAS_64BIT_REGS(ISA) \
+ ((ISA) == ISA_MIPS3 \
+ || (ISA) == ISA_MIPS4 \
+ || (ISA) == ISA_MIPS5 \
+ || (ISA) == ISA_MIPS64 \
+ || (ISA) == ISA_MIPS64R2)
/* Return true if ISA supports 64-bit right rotate (dror et al.)
instructions. */
-#define ISA_HAS_DROR(ISA) ( \
- (ISA) == ISA_MIPS64R2 \
- )
+#define ISA_HAS_DROR(ISA) \
+ ((ISA) == ISA_MIPS64R2)
/* Return true if ISA supports 32-bit right rotate (ror et al.)
instructions. */
-#define ISA_HAS_ROR(ISA) ( \
- (ISA) == ISA_MIPS32R2 \
- || (ISA) == ISA_MIPS64R2 \
- || mips_opts.ase_smartmips \
- )
+#define ISA_HAS_ROR(ISA) \
+ ((ISA) == ISA_MIPS32R2 \
+ || (ISA) == ISA_MIPS64R2 \
+ || mips_opts.ase_smartmips)
+
#define HAVE_32BIT_GPRS \
(mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
@@ -1402,8 +1400,297 @@ init_vr4120_conflicts (void)
#undef CONFLICT
}
-/* This function is called once, at assembler startup time. It should
- set up all the tables, etc. that the MD part of the assembler will need. */
+struct regname {
+ const char *name;
+ unsigned int num;
+};
+
+#define RTYPE_MASK 0x1ff00
+#define RTYPE_NUM 0x00100
+#define RTYPE_FPU 0x00200
+#define RTYPE_FCC 0x00400
+#define RTYPE_VEC 0x00800
+#define RTYPE_GP 0x01000
+#define RTYPE_CP0 0x02000
+#define RTYPE_PC 0x04000
+#define RTYPE_ACC 0x08000
+#define RTYPE_CCC 0x10000
+#define RNUM_MASK 0x000ff
+#define RWARN 0x80000
+
+#define GENERIC_REGISTER_NUMBERS \
+ {"$0", RTYPE_NUM | 0}, \
+ {"$1", RTYPE_NUM | 1}, \
+ {"$2", RTYPE_NUM | 2}, \
+ {"$3", RTYPE_NUM | 3}, \
+ {"$4", RTYPE_NUM | 4}, \
+ {"$5", RTYPE_NUM | 5}, \
+ {"$6", RTYPE_NUM | 6}, \
+ {"$7", RTYPE_NUM | 7}, \
+ {"$8", RTYPE_NUM | 8}, \
+ {"$9", RTYPE_NUM | 9}, \
+ {"$10", RTYPE_NUM | 10}, \
+ {"$11", RTYPE_NUM | 11}, \
+ {"$12", RTYPE_NUM | 12}, \
+ {"$13", RTYPE_NUM | 13}, \
+ {"$14", RTYPE_NUM | 14}, \
+ {"$15", RTYPE_NUM | 15}, \
+ {"$16", RTYPE_NUM | 16}, \
+ {"$17", RTYPE_NUM | 17}, \
+ {"$18", RTYPE_NUM | 18}, \
+ {"$19", RTYPE_NUM | 19}, \
+ {"$20", RTYPE_NUM | 20}, \
+ {"$21", RTYPE_NUM | 21}, \
+ {"$22", RTYPE_NUM | 22}, \
+ {"$23", RTYPE_NUM | 23}, \
+ {"$24", RTYPE_NUM | 24}, \
+ {"$25", RTYPE_NUM | 25}, \
+ {"$26", RTYPE_NUM | 26}, \
+ {"$27", RTYPE_NUM | 27}, \
+ {"$28", RTYPE_NUM | 28}, \
+ {"$29", RTYPE_NUM | 29}, \
+ {"$30", RTYPE_NUM | 30}, \
+ {"$31", RTYPE_NUM | 31}
+
+#define FPU_REGISTER_NAMES \
+ {"$f0", RTYPE_FPU | 0}, \
+ {"$f1", RTYPE_FPU | 1}, \
+ {"$f2", RTYPE_FPU | 2}, \
+ {"$f3", RTYPE_FPU | 3}, \
+ {"$f4", RTYPE_FPU | 4}, \
+ {"$f5", RTYPE_FPU | 5}, \
+ {"$f6", RTYPE_FPU | 6}, \
+ {"$f7", RTYPE_FPU | 7}, \
+ {"$f8", RTYPE_FPU | 8}, \
+ {"$f9", RTYPE_FPU | 9}, \
+ {"$f10", RTYPE_FPU | 10}, \
+ {"$f11", RTYPE_FPU | 11}, \
+ {"$f12", RTYPE_FPU | 12}, \
+ {"$f13", RTYPE_FPU | 13}, \
+ {"$f14", RTYPE_FPU | 14}, \
+ {"$f15", RTYPE_FPU | 15}, \
+ {"$f16", RTYPE_FPU | 16}, \
+ {"$f17", RTYPE_FPU | 17}, \
+ {"$f18", RTYPE_FPU | 18}, \
+ {"$f19", RTYPE_FPU | 19}, \
+ {"$f20", RTYPE_FPU | 20}, \
+ {"$f21", RTYPE_FPU | 21}, \
+ {"$f22", RTYPE_FPU | 22}, \
+ {"$f23", RTYPE_FPU | 23}, \
+ {"$f24", RTYPE_FPU | 24}, \
+ {"$f25", RTYPE_FPU | 25}, \
+ {"$f26", RTYPE_FPU | 26}, \
+ {"$f27", RTYPE_FPU | 27}, \
+ {"$f28", RTYPE_FPU | 28}, \
+ {"$f29", RTYPE_FPU | 29}, \
+ {"$f30", RTYPE_FPU | 30}, \
+ {"$f31", RTYPE_FPU | 31}
+
+#define FPU_CONDITION_CODE_NAMES \
+ {"$fcc0", RTYPE_FCC | 0}, \
+ {"$fcc1", RTYPE_FCC | 1}, \
+ {"$fcc2", RTYPE_FCC | 2}, \
+ {"$fcc3", RTYPE_FCC | 3}, \
+ {"$fcc4", RTYPE_FCC | 4}, \
+ {"$fcc5", RTYPE_FCC | 5}, \
+ {"$fcc6", RTYPE_FCC | 6}, \
+ {"$fcc7", RTYPE_FCC | 7}
+
+#define COPROC_CONDITION_CODE_NAMES \
+ {"$cc0", RTYPE_FCC | RTYPE_CCC | 0}, \
+ {"$cc1", RTYPE_FCC | RTYPE_CCC | 1}, \
+ {"$cc2", RTYPE_FCC | RTYPE_CCC | 2}, \
+ {"$cc3", RTYPE_FCC | RTYPE_CCC | 3}, \
+ {"$cc4", RTYPE_FCC | RTYPE_CCC | 4}, \
+ {"$cc5", RTYPE_FCC | RTYPE_CCC | 5}, \
+ {"$cc6", RTYPE_FCC | RTYPE_CCC | 6}, \
+ {"$cc7", RTYPE_FCC | RTYPE_CCC | 7}
+
+#define N32N64_SYMBOLIC_REGISTER_NAMES \
+ {"$a4", RTYPE_GP | 8}, \
+ {"$a5", RTYPE_GP | 9}, \
+ {"$a6", RTYPE_GP | 10}, \
+ {"$a7", RTYPE_GP | 11}, \
+ {"$ta0", RTYPE_GP | 8}, /* alias for $a4 */ \
+ {"$ta1", RTYPE_GP | 9}, /* alias for $a5 */ \
+ {"$ta2", RTYPE_GP | 10}, /* alias for $a6 */ \
+ {"$ta3", RTYPE_GP | 11}, /* alias for $a7 */ \
+ {"$t0", RTYPE_GP | 12}, \
+ {"$t1", RTYPE_GP | 13}, \
+ {"$t2", RTYPE_GP | 14}, \
+ {"$t3", RTYPE_GP | 15}
+
+#define O32_SYMBOLIC_REGISTER_NAMES \
+ {"$t0", RTYPE_GP | 8}, \
+ {"$t1", RTYPE_GP | 9}, \
+ {"$t2", RTYPE_GP | 10}, \
+ {"$t3", RTYPE_GP | 11}, \
+ {"$t4", RTYPE_GP | 12}, \
+ {"$t5", RTYPE_GP | 13}, \
+ {"$t6", RTYPE_GP | 14}, \
+ {"$t7", RTYPE_GP | 15}, \
+ {"$ta0", RTYPE_GP | 12}, /* alias for $t4 */ \
+ {"$ta1", RTYPE_GP | 13}, /* alias for $t5 */ \
+ {"$ta2", RTYPE_GP | 14}, /* alias for $t6 */ \
+ {"$ta3", RTYPE_GP | 15} /* alias for $t7 */
+
+/* Remaining symbolic register names */
+#define SYMBOLIC_REGISTER_NAMES \
+ {"$zero", RTYPE_GP | 0}, \
+ {"$at", RTYPE_GP | 1}, \
+ {"$AT", RTYPE_GP | 1}, \
+ {"$v0", RTYPE_GP | 2}, \
+ {"$v1", RTYPE_GP | 3}, \
+ {"$a0", RTYPE_GP | 4}, \
+ {"$a1", RTYPE_GP | 5}, \
+ {"$a2", RTYPE_GP | 6}, \
+ {"$a3", RTYPE_GP | 7}, \
+ {"$s0", RTYPE_GP | 16}, \
+ {"$s1", RTYPE_GP | 17}, \
+ {"$s2", RTYPE_GP | 18}, \
+ {"$s3", RTYPE_GP | 19}, \
+ {"$s4", RTYPE_GP | 20}, \
+ {"$s5", RTYPE_GP | 21}, \
+ {"$s6", RTYPE_GP | 22}, \
+ {"$s7", RTYPE_GP | 23}, \
+ {"$t8", RTYPE_GP | 24}, \
+ {"$t9", RTYPE_GP | 25}, \
+ {"$k0", RTYPE_GP | 26}, \
+ {"$kt0", RTYPE_GP | 26}, \
+ {"$k1", RTYPE_GP | 27}, \
+ {"$kt1", RTYPE_GP | 27}, \
+ {"$gp", RTYPE_GP | 28}, \
+ {"$sp", RTYPE_GP | 29}, \
+ {"$s8", RTYPE_GP | 30}, \
+ {"$fp", RTYPE_GP | 30}, \
+ {"$ra", RTYPE_GP | 31}
+
+#define MIPS16_SPECIAL_REGISTER_NAMES \
+ {"$pc", RTYPE_PC | 0}
+
+#define MDMX_VECTOR_REGISTER_NAMES \
+ /* {"$v0", RTYPE_VEC | 0}, clash with REG 2 above */ \
+ /* {"$v1", RTYPE_VEC | 1}, clash with REG 3 above */ \
+ {"$v2", RTYPE_VEC | 2}, \
+ {"$v3", RTYPE_VEC | 3}, \
+ {"$v4", RTYPE_VEC | 4}, \
+ {"$v5", RTYPE_VEC | 5}, \
+ {"$v6", RTYPE_VEC | 6}, \
+ {"$v7", RTYPE_VEC | 7}, \
+ {"$v8", RTYPE_VEC | 8}, \
+ {"$v9", RTYPE_VEC | 9}, \
+ {"$v10", RTYPE_VEC | 10}, \
+ {"$v11", RTYPE_VEC | 11}, \
+ {"$v12", RTYPE_VEC | 12}, \
+ {"$v13", RTYPE_VEC | 13}, \
+ {"$v14", RTYPE_VEC | 14}, \
+ {"$v15", RTYPE_VEC | 15}, \
+ {"$v16", RTYPE_VEC | 16}, \
+ {"$v17", RTYPE_VEC | 17}, \
+ {"$v18", RTYPE_VEC | 18}, \
+ {"$v19", RTYPE_VEC | 19}, \
+ {"$v20", RTYPE_VEC | 20}, \
+ {"$v21", RTYPE_VEC | 21}, \
+ {"$v22", RTYPE_VEC | 22}, \
+ {"$v23", RTYPE_VEC | 23}, \
+ {"$v24", RTYPE_VEC | 24}, \
+ {"$v25", RTYPE_VEC | 25}, \
+ {"$v26", RTYPE_VEC | 26}, \
+ {"$v27", RTYPE_VEC | 27}, \
+ {"$v28", RTYPE_VEC | 28}, \
+ {"$v29", RTYPE_VEC | 29}, \
+ {"$v30", RTYPE_VEC | 30}, \
+ {"$v31", RTYPE_VEC | 31}
+
+#define MIPS_DSP_ACCUMULATOR_NAMES \
+ {"$ac0", RTYPE_ACC | 0}, \
+ {"$ac1", RTYPE_ACC | 1}, \
+ {"$ac2", RTYPE_ACC | 2}, \
+ {"$ac3", RTYPE_ACC | 3}
+
+static const struct regname reg_names[] = {
+ GENERIC_REGISTER_NUMBERS,
+ FPU_REGISTER_NAMES,
+ FPU_CONDITION_CODE_NAMES,
+ COPROC_CONDITION_CODE_NAMES,
+
+ /* The $txx registers depends on the abi,
+ these will be added later into the symbol table from
+ one of the tables below once mips_abi is set after
+ parsing of arguments from the command line. */
+ SYMBOLIC_REGISTER_NAMES,
+
+ MIPS16_SPECIAL_REGISTER_NAMES,
+ MDMX_VECTOR_REGISTER_NAMES,
+ MIPS_DSP_ACCUMULATOR_NAMES,
+ {0, 0}
+};
+
+static const struct regname reg_names_o32[] = {
+ O32_SYMBOLIC_REGISTER_NAMES,
+ {0, 0}
+};
+
+static const struct regname reg_names_n32n64[] = {
+ N32N64_SYMBOLIC_REGISTER_NAMES,
+ {0, 0}
+};
+
+static int
+reg_lookup (char **s, unsigned int types, unsigned int *regnop)
+{
+ symbolS *symbolP;
+ char *e;
+ char save_c;
+ int reg = -1;
+
+ /* Find end of name. */
+ e = *s;
+ if (is_name_beginner (*e))
+ ++e;
+ while (is_part_of_name (*e))
+ ++e;
+
+ /* Terminate name. */
+ save_c = *e;
+ *e = '\0';
+
+ /* Look for a register symbol. */
+ if ((symbolP = symbol_find (*s)) && S_GET_SEGMENT (symbolP) == reg_section)
+ {
+ int r = S_GET_VALUE (symbolP);
+ if (r & types)
+ reg = r & RNUM_MASK;
+ else if ((types & RTYPE_VEC) && (r & ~1) == (RTYPE_GP | 2))
+ /* Convert GP reg $v0/1 to MDMX reg $v0/1! */
+ reg = (r & RNUM_MASK) - 2;
+ }
+ /* Else see if this is a register defined in an itbl entry. */
+ else if ((types & RTYPE_GP) && itbl_have_entries)
+ {
+ char *n = *s;
+ unsigned long r;
+
+ if (*n == '$')
+ ++n;
+ if (itbl_get_reg_val (n, &r))
+ reg = r & RNUM_MASK;
+ }
+
+ /* Advance to next token if a register was recognised. */
+ if (reg >= 0)
+ *s = e;
+ else if (types & RWARN)
+ as_warn ("Unrecognized register name `%s'", *s);
+
+ *e = save_c;
+ if (regnop)
+ *regnop = reg;
+ return reg >= 0;
+}
+
+/* This function is called once, at assembler startup time. It should set up
+ all the tables, etc. that the MD part of the assembler will need. */
void
md_begin (void)
@@ -1490,46 +1777,20 @@ md_begin (void)
/* We add all the general register names to the symbol table. This
helps us detect invalid uses of them. */
- for (i = 0; i < 32; i++)
- {
- char buf[5];
-
- sprintf (buf, "$%d", i);
- symbol_table_insert (symbol_new (buf, reg_section, i,
+ for (i = 0; reg_names[i].name; i++)
+ symbol_table_insert (symbol_new (reg_names[i].name, reg_section,
+ reg_names[i].num, // & RNUM_MASK,
+ &zero_address_frag));
+ if (HAVE_NEWABI)
+ for (i = 0; reg_names_n32n64[i].name; i++)
+ symbol_table_insert (symbol_new (reg_names_n32n64[i].name, reg_section,
+ reg_names_n32n64[i].num, // & RNUM_MASK,
&zero_address_frag));
- }
- symbol_table_insert (symbol_new ("$ra", reg_section, RA,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$fp", reg_section, FP,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$sp", reg_section, SP,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$gp", reg_section, GP,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$at", reg_section, AT,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$kt0", reg_section, KT0,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$kt1", reg_section, KT1,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$zero", reg_section, ZERO,
- &zero_address_frag));
- symbol_table_insert (symbol_new ("$pc", reg_section, -1,
- &zero_address_frag));
-
- /* If we don't add these register names to the symbol table, they
- may end up being added as regular symbols by operand(), and then
- make it to the object file as undefined in case they're not
- regarded as local symbols. They're local in o32, since `$' is a
- local symbol prefix, but not in n32 or n64. */
- for (i = 0; i < 8; i++)
- {
- char buf[6];
-
- sprintf (buf, "$fcc%i", i);
- symbol_table_insert (symbol_new (buf, reg_section, -1,
+ else
+ for (i = 0; reg_names_o32[i].name; i++)
+ symbol_table_insert (symbol_new (reg_names_o32[i].name, reg_section,
+ reg_names_o32[i].num, // & RNUM_MASK,
&zero_address_frag));
- }
mips_no_prev_insn ();
@@ -1544,6 +1805,7 @@ md_begin (void)
bfd_set_gp_size (stdoutput, g_switch_value);
+#ifdef OBJ_ELF
if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
{
/* On a native system other than VxWorks, sections must be aligned
@@ -1582,9 +1844,7 @@ md_begin (void)
bfd_set_section_flags (stdoutput, sec, flags);
bfd_set_section_alignment (stdoutput, sec, HAVE_NEWABI ? 3 : 2);
-#ifdef OBJ_ELF
mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));
-#endif
}
else
{
@@ -1594,7 +1854,6 @@ md_begin (void)
bfd_set_section_flags (stdoutput, sec, flags);
bfd_set_section_alignment (stdoutput, sec, 3);
-#ifdef OBJ_ELF
/* Set up the option header. */
{
Elf_Internal_Options opthdr;
@@ -1611,7 +1870,6 @@ md_begin (void)
mips_regmask_frag = frag_more (sizeof (Elf64_External_RegInfo));
}
-#endif
}
if (ECOFF_DEBUGGING)
@@ -1621,7 +1879,6 @@ md_begin (void)
SEC_HAS_CONTENTS | SEC_READONLY);
(void) bfd_set_section_alignment (stdoutput, sec, 2);
}
-#ifdef OBJ_ELF
else if (OUTPUT_FLAVOR == bfd_target_elf_flavour && mips_flag_pdr)
{
pdr_seg = subseg_new (".pdr", (subsegT) 0);
@@ -1630,11 +1887,11 @@ md_begin (void)
| SEC_DEBUGGING);
(void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);
}
-#endif
subseg_set (seg, subseg);
}
}
+#endif /* OBJ_ELF */
if (! ECOFF_DEBUGGING)
md_obj_begin ();
@@ -7972,6 +8229,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
char *s_reset;
char save_c = 0;
offsetT min_range, max_range;
+ int argnum;
+ unsigned int rtype;
insn_error = NULL;
@@ -8079,6 +8338,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
create_insn (ip, insn);
insn_error = NULL;
+ argnum = 1;
for (args = insn->args;; ++args)
{
int is_mdmx;
@@ -8495,11 +8755,11 @@ do_msbd:
s = expr_end;
continue;
- case 'T': /* Coprocessor register */
+ case 'T': /* Coprocessor register. */
/* +T is for disassembly only; never match. */
break;
- case 't': /* Coprocessor register number */
+ case 't': /* Coprocessor register number. */
if (s[0] == '$' && ISDIGIT (s[1]))
{
++s;
@@ -8633,7 +8893,7 @@ do_msbd:
s = expr_end;
continue;
- case 'P': /* Performance register */
+ case 'P': /* Performance register. */
my_getExpression (&imm_expr, s);
check_absolute_expr (ip, &imm_expr);
if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1)
@@ -8644,6 +8904,20 @@ do_msbd:
s = expr_end;
continue;
+ case 'G': /* Coprocessor destination register. */
+ if (((ip->insn_opcode >> OP_SH_OP) & OP_MASK_OP) == OP_OP_COP0)
+ ok = reg_lookup (&s, RTYPE_NUM | RTYPE_CP0, &regno);
+ else
+ ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno);
+ ip->insn_opcode |= regno << OP_SH_RD;
+ if (ok)
+ {
+ lastregno = regno;
+ continue;
+ }
+ else
+ break;
+
case 'b': /* base register */
case 'd': /* destination register */
case 's': /* source register */
@@ -8652,106 +8926,22 @@ do_msbd:
case 'v': /* both dest and source */
case 'w': /* both dest and target */
case 'E': /* coprocessor target register */
- case 'G': /* coprocessor destination register */
case 'K': /* 'rdhwr' destination register */
case 'x': /* ignore register name */
case 'z': /* must be zero register */
case 'U': /* destination register (clo/clz). */
case 'g': /* coprocessor destination register */
- s_reset = s;
- if (s[0] == '$')
+ s_reset = s;
+ if (*args == 'E' || *args == 'K')
+ ok = reg_lookup (&s, RTYPE_NUM, &regno);
+ else
+ {
+ ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno);
+ if (regno == AT && ! mips_opts.noat)
+ as_warn ("Used $at without \".set noat\"");
+ }
+ if (ok)
{
- if (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 if (*args == 'E' || *args == 'G' || *args == 'K')
- goto notreg;
- else
- {
- if (s[1] == 'r' && s[2] == 'a')
- {
- s += 3;
- regno = RA;
- }
- else if (s[1] == 'f' && s[2] == 'p')
- {
- s += 3;
- regno = FP;
- }
- else if (s[1] == 's' && s[2] == 'p')
- {
- s += 3;
- regno = SP;
- }
- else if (s[1] == 'g' && s[2] == 'p')
- {
- s += 3;
- regno = GP;
- }
- else if (s[1] == 'a' && s[2] == 't')
- {
- s += 3;
- regno = AT;
- }
- else if (s[1] == 'k' && s[2] == 't' && s[3] == '0')
- {
- s += 4;
- regno = KT0;
- }
- else if (s[1] == 'k' && s[2] == 't' && s[3] == '1')
- {
- s += 4;
- regno = KT1;
- }
- else if (s[1] == 'z' && s[2] == 'e' && s[3] == 'r' && s[4] == 'o')
- {
- s += 5;
- regno = ZERO;
- }
- else if (itbl_have_entries)
- {
- char *p, *n;
- unsigned long r;
-
- p = s + 1; /* advance past '$' */
- n = itbl_get_field (&p); /* n is name */
-
- /* See if this is a register defined in an
- itbl entry. */
- if (itbl_get_reg_val (n, &r))
- {
- /* Get_field advances to the start of
- the next field, so we need to back
- rack to the end of the last field. */
- if (p)
- s = p - 1;
- else
- s = strchr (s, '\0');
- regno = r;
- }
- else
- goto notreg;
- }
- else
- goto notreg;
- }
- if (regno == AT
- && ! mips_opts.noat
- && *args != 'E'
- && *args != 'G'
- && *args != 'K')
- as_warn (_("Used $at without \".set noat\""));
c = *args;
if (*s == ' ')
++s;
@@ -8817,7 +9007,6 @@ do_msbd:
lastregno = regno;
continue;
}
- notreg:
switch (*args++)
{
case 'r':
@@ -8870,26 +9059,19 @@ do_msbd:
case 'R': /* floating point source register */
case 'V':
case 'W':
+ rtype = RTYPE_FPU;
+ if (is_mdmx
+ || (mips_opts.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;
- /* Accept $fN for FP and MDMX register numbers, and in
- addition accept $vN for MDMX register numbers. */
- if ((s[0] == '$' && s[1] == 'f' && ISDIGIT (s[2]))
- || (is_mdmx != 0 && s[0] == '$' && s[1] == 'v'
- && ISDIGIT (s[2])))
+ if (reg_lookup (&s, rtype, &regno))
{
- s += 2;
- regno = 0;
- do
- {
- regno *= 10;
- regno += *s - '0';
- ++s;
- }
- while (ISDIGIT (*s));
-
- if (regno > 31)
- as_bad (_("Invalid float register number (%d)"), regno);
-
if ((regno & 1) != 0
&& HAVE_32BIT_FPRS
&& ! (strcmp (str, "mtc1") == 0
@@ -9291,19 +9473,11 @@ do_msbd:
case 'N': /* 3 bit branch condition code */
case 'M': /* 3 bit compare condition code */
- if (strncmp (s, "$fcc", 4) != 0)
+ rtype = RTYPE_CCC;
+ if (ip->insn_mo->pinfo & (FP_D| FP_S))
+ rtype |= RTYPE_FCC;
+ if (!reg_lookup (&s, rtype, &regno))
break;
- s += 4;
- regno = 0;
- do
- {
- regno *= 10;
- regno += *s - '0';
- ++s;
- }
- while (ISDIGIT (*s));
- if (regno > 7)
- as_bad (_("Invalid condition code register $fcc%d"), regno);
if ((strcmp(str + strlen(str) - 3, ".ps") == 0
|| strcmp(str + strlen(str) - 5, "any2f") == 0
|| strcmp(str + strlen(str) - 5, "any2t") == 0)
@@ -9614,70 +9788,19 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
case 'R':
case 'X':
case 'Y':
- if (s[0] != '$')
- break;
- s_reset = s;
- if (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);
- regno = 2;
- }
- }
- else
+ s_reset = s;
+ if (!reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno))
{
- if (s[1] == 'r' && s[2] == 'a')
- {
- s += 3;
- regno = RA;
- }
- else if (s[1] == 'f' && s[2] == 'p')
- {
- s += 3;
- regno = FP;
- }
- else if (s[1] == 's' && s[2] == 'p')
- {
- s += 3;
- regno = SP;
- }
- else if (s[1] == 'g' && s[2] == 'p')
- {
- s += 3;
- regno = GP;
- }
- else if (s[1] == 'a' && s[2] == 't')
- {
- s += 3;
- regno = AT;
- }
- else if (s[1] == 'k' && s[2] == 't' && s[3] == '0')
- {
- s += 4;
- regno = KT0;
- }
- else if (s[1] == 'k' && s[2] == 't' && s[3] == '1')
- {
- s += 4;
- regno = KT1;
- }
- else if (s[1] == 'z' && s[2] == 'e' && s[3] == 'r' && s[4] == 'o')
+ if (c == 'v' || c == 'w')
{
- s += 5;
- regno = ZERO;
+ if (c == 'v')
+ ip->insn_opcode |= lastregno << MIPS16OP_SH_RX;
+ else
+ ip->insn_opcode |= lastregno << MIPS16OP_SH_RY;
+ ++args;
+ continue;
}
- else
- break;
+ break;
}
if (*s == ' ')
@@ -9883,29 +10006,18 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
mask = 7 << 3;
while (*s != '\0')
{
- int freg, reg1, reg2;
+ unsigned int freg, reg1, reg2;
while (*s == ' ' || *s == ',')
++s;
- if (*s != '$')
- {
- as_bad (_("can't parse register list"));
- break;
- }
- ++s;
- if (*s != 'f')
+ if (reg_lookup (&s, RTYPE_GP | RTYPE_NUM, &reg1))
freg = 0;
+ else if (reg_lookup (&s, RTYPE_FPU, &reg1))
+ freg = 1;
else
{
- freg = 1;
- ++s;
- }
- reg1 = 0;
- while (ISDIGIT (*s))
- {
- reg1 *= 10;
- reg1 += *s - '0';
- ++s;
+ as_bad (_("can't parse register list"));
+ break;
}
if (*s == ' ')
++s;
@@ -9914,25 +10026,11 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
else
{
++s;
- if (*s != '$')
- break;
- ++s;
- if (freg)
- {
- if (*s == 'f')
- ++s;
- else
- {
- as_bad (_("invalid register list"));
- break;
- }
- }
- reg2 = 0;
- while (ISDIGIT (*s))
+ if (!reg_lookup (&s, freg ? RTYPE_FPU
+ : (RTYPE_GP | RTYPE_NUM), &reg2))
{
- reg2 *= 10;
- reg2 += *s - '0';
- ++s;
+ as_bad (_("invalid register list"));
+ break;
}
}
if (freg && reg1 == 0 && reg2 == 0 && c == 'L')
@@ -9997,39 +10095,26 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
continue;
}
- if (*s != '$')
+ if (! reg_lookup (&s, RTYPE_GP | RTYPE_NUM, &reg1))
{
as_bad (_("can't parse register list"));
break;
}
- ++s;
- reg1 = 0;
- while (ISDIGIT (*s))
- {
- reg1 *= 10;
- reg1 += *s - '0';
- ++s;
- }
- SKIP_SPACE_TABS (s);
+ while (*s == ' ')
+ ++s;
+
if (*s != '-')
reg2 = reg1;
else
{
++s;
- if (*s != '$')
+ if (! reg_lookup (&s, RTYPE_GP | RTYPE_NUM, &reg2)
+ || reg2 < reg1)
{
as_bad (_("can't parse register list"));
break;
}
- ++s;
- reg2 = 0;
- while (ISDIGIT (*s))
- {
- reg2 *= 10;
- reg2 += *s - '0';
- ++s;
- }
}
while (reg1 <= reg2)
@@ -12786,73 +12871,11 @@ s_mips_weakext (int ignore ATTRIBUTE_UNUSED)
int
tc_get_register (int frame)
{
- int reg;
+ unsigned int reg;
SKIP_WHITESPACE ();
- if (*input_line_pointer++ != '$')
- {
- as_warn (_("expected `$'"));
- reg = ZERO;
- }
- else if (ISDIGIT (*input_line_pointer))
- {
- reg = get_absolute_expression ();
- if (reg < 0 || reg >= 32)
- {
- as_warn (_("Bad register number"));
- reg = ZERO;
- }
- }
- else
- {
- if (strncmp (input_line_pointer, "ra", 2) == 0)
- {
- reg = RA;
- input_line_pointer += 2;
- }
- else if (strncmp (input_line_pointer, "fp", 2) == 0)
- {
- reg = FP;
- input_line_pointer += 2;
- }
- else if (strncmp (input_line_pointer, "sp", 2) == 0)
- {
- reg = SP;
- input_line_pointer += 2;
- }
- else if (strncmp (input_line_pointer, "gp", 2) == 0)
- {
- reg = GP;
- input_line_pointer += 2;
- }
- else if (strncmp (input_line_pointer, "at", 2) == 0)
- {
- reg = AT;
- input_line_pointer += 2;
- }
- else if (strncmp (input_line_pointer, "kt0", 3) == 0)
- {
- reg = KT0;
- input_line_pointer += 3;
- }
- else if (strncmp (input_line_pointer, "kt1", 3) == 0)
- {
- reg = KT1;
- input_line_pointer += 3;
- }
- else if (strncmp (input_line_pointer, "zero", 4) == 0)
- {
- reg = ZERO;
- input_line_pointer += 4;
- }
- else
- {
- as_warn (_("Unrecognized register name"));
- reg = ZERO;
- while (ISALNUM(*input_line_pointer))
- input_line_pointer++;
- }
- }
+ if (! reg_lookup (&input_line_pointer, RWARN | RTYPE_NUM | RTYPE_GP, &reg))
+ reg = 0;
if (frame)
{
mips_frame_reg = reg != 0 ? reg : SP;
@@ -14708,3 +14731,14 @@ mips_cfi_frame_initial_instructions (void)
cfi_add_CFA_def_cfa_register (SP);
}
+int
+tc_mips_regname_to_dw2regnum (char *regname)
+{
+ unsigned int regnum = -1;
+ unsigned int reg;
+
+ if (reg_lookup (&regname, RTYPE_GP | RTYPE_NUM, &reg))
+ regnum = reg;
+
+ return regnum;
+}
diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h
index 5665d3d..fadf320 100644
--- a/gas/config/tc-mips.h
+++ b/gas/config/tc-mips.h
@@ -160,6 +160,9 @@ extern int mips_dwarf2_addr_size (void);
#define tc_cfi_frame_initial_instructions mips_cfi_frame_initial_instructions
extern void mips_cfi_frame_initial_instructions (void);
+#define tc_regname_to_dw2regnum tc_mips_regname_to_dw2regnum
+extern int tc_mips_regname_to_dw2regnum (char *regname);
+
#define DWARF2_DEFAULT_RETURN_COLUMN 31
#define DWARF2_CIE_DATA_ALIGNMENT -4