This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Cleanup MIPS gas register parsing


Hello All,

I applied this patch, it uses a general lookup routine to parse
register names and reserves all the known register names to prevent
their use as (local) symbols. Formerly this was only done for a
subset of registers.


Thiemo


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.


Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.335
diff -u -p -r1.335 tc-mips.c
--- gas/config/tc-mips.c	14 May 2006 15:35:21 -0000	1.335
+++ gas/config/tc-mips.c	18 May 2006 11:24:18 -0000
@@ -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 +1406,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 +1783,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 +1811,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 +1850,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 +1860,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 +1876,6 @@ md_begin (void)
 
 	      mips_regmask_frag = frag_more (sizeof (Elf64_External_RegInfo));
 	    }
-#endif
 	  }
 
 	if (ECOFF_DEBUGGING)
@@ -1621,7 +1885,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 +1893,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 +8275,8 @@ mips_ip (char *str, struct mips_cl_insn 
   char *s_reset;
   char save_c = 0;
   offsetT min_range, max_range;
+  int argnum;
+  unsigned int rtype;
 
   insn_error = NULL;
 
@@ -8079,6 +8384,7 @@ mips_ip (char *str, struct mips_cl_insn 
 
       create_insn (ip, insn);
       insn_error = NULL;
+      argnum = 1;
       for (args = insn->args;; ++args)
 	{
 	  int is_mdmx;
@@ -8495,11 +8801,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 +8939,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 +8950,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 +8972,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 +9053,6 @@ do_msbd:
 		  lastregno = regno;
 		  continue;
 		}
-	    notreg:
 	      switch (*args++)
 		{
 		case 'r':
@@ -8870,26 +9105,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 +9508,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 +9823,19 @@ mips16_ip (char *str, struct mips_cl_ins
 	    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 +10041,18 @@ mips16_ip (char *str, struct mips_cl_ins
 		  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 +10061,11 @@ mips16_ip (char *str, struct mips_cl_ins
 		    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 +10130,26 @@ mips16_ip (char *str, struct mips_cl_ins
 			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 +12906,11 @@ s_mips_weakext (int ignore ATTRIBUTE_UNU
 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 +14766,14 @@ mips_cfi_frame_initial_instructions (voi
   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;
+}
Index: gas/config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.43
diff -u -p -r1.43 tc-mips.h
--- gas/config/tc-mips.h	22 Mar 2006 09:28:13 -0000	1.43
+++ gas/config/tc-mips.h	18 May 2006 11:24:18 -0000
@@ -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
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]