This is the mail archive of the binutils-cvs@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]

[binutils-gdb] gas: sparc: fix collision of registers and pseudo-ops.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8b8c7c9f49992750f66f81b4601d593a3858d98c

commit 8b8c7c9f49992750f66f81b4601d593a3858d98c
Author: Jose E. Marchesi <jose.marchesi@oracle.com>
Date:   Fri Jun 17 02:13:30 2016 -0700

    gas: sparc: fix collision of registers and pseudo-ops.
    
    The current sparc assembler breaks when the name of an ancillary-state
    register, privileged register or hyperprivileged register has a
    %-pseudo-operation name as a prefix.  For example, %hmcdper and %hm(),
    or %hintp and %hi().
    
    This patch fixes it by introducing a new table `perc_table' (for
    %-table) that contains an entry for every %name supported by the
    assembler, other than the general registers.  This table is used to
    detect name collisions when the assembler tries to detect a %-pseudo-op.
    
    This patch also fixes a related bug, making sure that v9a_asr_table and
    hpriv_reg_table are sorted in reverse lexicographic order, as otherwise
    the search code may fail.
    
    gas/ChangeLog:
    
    2016-06-17  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* config/tc-sparc.c (priv_reg_table): Use NULL instead of the
    	empty string to mark the end of the array.
    	(hpriv_reg_table): Likewise.
    	(v9a_asr_table): Likewise.
    	(cmp_reg_entry): Handle entries with NULL names.
    	(F_POP_V9): Define.
    	(F_POP_PCREL): Likewise.
    	(F_POP_TLS_CALL): Likewise.
    	(F_POP_POSTFIX): Likewise.
    	(struct pop_entry): New type.
    	(pop_table): New variable.
    	(enum pop_entry_type): New type.
    	(struct perc_entry): Likewise.
    	(NUM_PERC_ENTRIES): Define.
    	(perc_table): New variable.
    	(cmp_perc_entry): New function.
    	(md_begin): Sort hpriv_reg_table and v9a_asr_table, and initialize
    	perc_table.
    	(sparc_ip): Handle entries with NULL names in priv_reg_table,
    	hpriv_reg_table and v9a_asr_table.  Use perc_table to handle
    	%-pseudo-ops.

Diff:
---
 gas/ChangeLog         |  24 ++++
 gas/config/tc-sparc.c | 381 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 264 insertions(+), 141 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 64b62af..e183c11 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,27 @@
+2016-06-17  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* config/tc-sparc.c (priv_reg_table): Use NULL instead of the
+	empty string to mark the end of the array.
+	(hpriv_reg_table): Likewise.
+	(v9a_asr_table): Likewise.
+	(cmp_reg_entry): Handle entries with NULL names.
+	(F_POP_V9): Define.
+	(F_POP_PCREL): Likewise.
+	(F_POP_TLS_CALL): Likewise.
+	(F_POP_POSTFIX): Likewise.
+	(struct pop_entry): New type.
+	(pop_table): New variable.
+	(enum pop_entry_type): New type.
+	(struct perc_entry): Likewise.
+	(NUM_PERC_ENTRIES): Define.
+	(perc_table): New variable.
+	(cmp_perc_entry): New function.
+	(md_begin): Sort hpriv_reg_table and v9a_asr_table, and initialize
+	perc_table.
+	(sparc_ip): Handle entries with NULL names in priv_reg_table,
+	hpriv_reg_table and v9a_asr_table.  Use perc_table to handle
+	%-pseudo-ops.
+
 2016-06-15  Nick Clifton  <nickc@redhat.com>
 
 	* config/tc-ft32.c (md_assemble): Call dwarf2_emit_insn with the
diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c
index 1114afa..c8076bf 100644
--- a/gas/config/tc-sparc.c
+++ b/gas/config/tc-sparc.c
@@ -807,7 +807,7 @@ struct priv_reg_entry priv_reg_table[] =
   {"gl", 16},
   {"pmcdper", 23},
   {"ver", 31},
-  {"", -1},			/* End marker.  */
+  {NULL, -1},			/* End marker.  */
 };
 
 struct priv_reg_entry hpriv_reg_table[] =
@@ -820,11 +820,10 @@ struct priv_reg_entry hpriv_reg_table[] =
   {"hstick_offset", 28},
   {"hstick_enable", 29},
   {"hstick_cmpr", 31},
-  {"", -1},			/* End marker.  */
+  {NULL, -1},			/* End marker.  */
 };
 
-/* v9a specific asrs.  This table is ordered by initial
-   letter, in reverse.  */
+/* v9a or later specific ancillary state registers. */
 
 struct priv_reg_entry v9a_asr_table[] =
 {
@@ -845,7 +844,7 @@ struct priv_reg_entry v9a_asr_table[] =
   {"dcr", 18},
   {"cfr", 26},
   {"clear_softint", 21},
-  {"", -1},			/* End marker.  */
+  {NULL, -1},			/* End marker.  */
 };
 
 static int
@@ -854,7 +853,131 @@ cmp_reg_entry (const void *parg, const void *qarg)
   const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
   const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
 
-  return strcmp (q->name, p->name);
+  if (p->name == q->name)
+    return 0;
+  else if (p->name == NULL)
+    return 1;
+  else if (q->name == NULL)
+    return -1;
+  else
+    return strcmp (q->name, p->name);
+}
+
+/* sparc %-pseudo-operations.  */
+
+
+#define F_POP_V9       0x1 /* The pseudo-op is for v9 only.  */
+#define F_POP_PCREL    0x2 /* The pseudo-op can be used in pc-relative
+                              contexts.  */
+#define F_POP_TLS_CALL 0x4 /* The pseudo-op marks a tls call.  */
+#define F_POP_POSTFIX  0x8 /* The pseudo-op should appear after the
+                              last operand of an
+                              instruction. (Generally they can appear
+                              anywhere an immediate operand is
+                              expected.  */
+struct pop_entry
+{
+  /* The name as it appears in assembler.  */
+  const char *name;
+  /* The reloc this pseudo-op translates to.  */
+  int reloc;
+  /* Flags.  See F_POP_* above.  */
+  int flags;
+};
+
+struct pop_entry pop_table[] =
+{
+  { "hix",		BFD_RELOC_SPARC_HIX22,		F_POP_V9 },
+  { "lox",		BFD_RELOC_SPARC_LOX10, 		F_POP_V9 },
+  { "hi",		BFD_RELOC_HI22,			F_POP_PCREL },
+  { "lo",		BFD_RELOC_LO10,			F_POP_PCREL },
+  { "pc22",		BFD_RELOC_SPARC_PC22,		F_POP_PCREL },
+  { "pc10",		BFD_RELOC_SPARC_PC10,		F_POP_PCREL },
+  { "hh",		BFD_RELOC_SPARC_HH22,		F_POP_V9|F_POP_PCREL },
+  { "hm",		BFD_RELOC_SPARC_HM10,		F_POP_V9|F_POP_PCREL },
+  { "lm",		BFD_RELOC_SPARC_LM22,		F_POP_V9|F_POP_PCREL },
+  { "h34",		BFD_RELOC_SPARC_H34,		F_POP_V9 },
+  { "l34",		BFD_RELOC_SPARC_L44,		F_POP_V9 },
+  { "h44",		BFD_RELOC_SPARC_H44,		F_POP_V9 },
+  { "m44",		BFD_RELOC_SPARC_M44,		F_POP_V9 },
+  { "l44",		BFD_RELOC_SPARC_L44,		F_POP_V9 },
+  { "uhi",		BFD_RELOC_SPARC_HH22,		F_POP_V9 },
+  { "ulo",		BFD_RELOC_SPARC_HM10,		F_POP_V9 },
+  { "tgd_hi22",		BFD_RELOC_SPARC_TLS_GD_HI22, 	0 },
+  { "tgd_lo10",		BFD_RELOC_SPARC_TLS_GD_LO10, 	0 },
+  { "tldm_hi22",	BFD_RELOC_SPARC_TLS_LDM_HI22, 	0 },
+  { "tldm_lo10",	BFD_RELOC_SPARC_TLS_LDM_LO10, 	0 },
+  { "tldo_hix22",	BFD_RELOC_SPARC_TLS_LDO_HIX22, 	0 },
+  { "tldo_lox10",	BFD_RELOC_SPARC_TLS_LDO_LOX10, 	0 },
+  { "tie_hi22",		BFD_RELOC_SPARC_TLS_IE_HI22, 	0 },
+  { "tie_lo10",		BFD_RELOC_SPARC_TLS_IE_LO10, 	0 },
+  { "tle_hix22",	BFD_RELOC_SPARC_TLS_LE_HIX22, 	0 },
+  { "tle_lox10",	BFD_RELOC_SPARC_TLS_LE_LOX10, 	0 },
+  { "gdop_hix22",	BFD_RELOC_SPARC_GOTDATA_OP_HIX22, 0 },
+  { "gdop_lox10",	BFD_RELOC_SPARC_GOTDATA_OP_LOX10, 0 },
+  { "tgd_add", 		BFD_RELOC_SPARC_TLS_GD_ADD,	F_POP_POSTFIX },
+  { "tgd_call",		BFD_RELOC_SPARC_TLS_GD_CALL, 	F_POP_POSTFIX|F_POP_TLS_CALL },
+  { "tldm_add",		BFD_RELOC_SPARC_TLS_LDM_ADD, 	F_POP_POSTFIX },
+  { "tldm_call",	BFD_RELOC_SPARC_TLS_LDM_CALL,	F_POP_POSTFIX|F_POP_TLS_CALL },
+  { "tldo_add",		BFD_RELOC_SPARC_TLS_LDO_ADD, 	F_POP_POSTFIX },
+  { "tie_ldx",		BFD_RELOC_SPARC_TLS_IE_LDX, 	F_POP_POSTFIX },
+  { "tie_ld",		BFD_RELOC_SPARC_TLS_IE_LD,	F_POP_POSTFIX },
+  { "tie_add",		BFD_RELOC_SPARC_TLS_IE_ADD,	F_POP_POSTFIX },
+  { "gdop",	 	BFD_RELOC_SPARC_GOTDATA_OP,	F_POP_POSTFIX },
+  { NULL, 0, 0 },
+};
+
+/* Table of %-names that can appear in a sparc assembly program.  This
+   table is initialized in md_begin and contains entries for each
+   privileged/hyperprivileged/alternate register and %-pseudo-op.  */
+
+enum perc_entry_type
+{
+  perc_entry_none = 0,
+  perc_entry_reg,
+  perc_entry_post_pop,
+  perc_entry_imm_pop
+};
+
+struct perc_entry
+{
+  /* Entry type.  */
+  enum perc_entry_type type;
+  /* Name of the %-entity.  */
+  const char *name;
+  /* strlen (name).  */
+  int len;
+  /* Value.  Either a pop or a reg depending on type.*/
+  union
+  {
+    struct pop_entry *pop;
+    struct priv_reg_entry *reg;
+  };
+};
+
+#define NUM_PERC_ENTRIES \
+  (((sizeof (priv_reg_table) / sizeof (priv_reg_table[0])) - 1)         \
+   + ((sizeof (hpriv_reg_table) / sizeof (hpriv_reg_table[0])) - 1)     \
+   + ((sizeof (v9a_asr_table) / sizeof (v9a_asr_table[0])) - 1)         \
+   + ((sizeof (pop_table) / sizeof (pop_table[0])) - 1) \
+   + 1)
+
+struct perc_entry perc_table[NUM_PERC_ENTRIES];
+
+static int
+cmp_perc_entry (const void *parg, const void *qarg)
+{
+  const struct perc_entry *p = (const struct perc_entry *) parg;
+  const struct perc_entry *q = (const struct perc_entry *) qarg;
+
+  if (p->name == q->name)
+    return 0;
+  else if (p->name == NULL)
+    return 1;
+  else if (q->name == NULL)
+    return -1;
+  else
+    return strcmp (q->name, p->name);
 }
 
 /* This function is called once, at assembler startup time.  It should
@@ -932,7 +1055,11 @@ md_begin (void)
 
   qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
 	 sizeof (priv_reg_table[0]), cmp_reg_entry);
-
+  qsort (hpriv_reg_table, sizeof (hpriv_reg_table) / sizeof (hpriv_reg_table[0]),
+	 sizeof (hpriv_reg_table[0]), cmp_reg_entry);
+  qsort (v9a_asr_table, sizeof (v9a_asr_table) / sizeof (v9a_asr_table[0]),
+	 sizeof (v9a_asr_table[0]), cmp_reg_entry);
+  
   /* If -bump, record the architecture level at which we start issuing
      warnings.  The behaviour is different depending upon whether an
      architecture was explicitly specified.  If it wasn't, we issue warnings
@@ -964,6 +1091,50 @@ md_begin (void)
 				     current_max_architecture))
 	break;
   }
+
+  /* Prepare the tables of %-pseudo-ops.  */
+  {
+    struct priv_reg_entry *reg_tables[]
+      = {priv_reg_table, hpriv_reg_table, v9a_asr_table, NULL};
+    struct priv_reg_entry **reg_table;
+    int entry = 0;
+
+    /* Add registers.  */
+    for (reg_table = reg_tables; reg_table[0]; reg_table++)
+      {
+        struct priv_reg_entry *reg;
+        for (reg = *reg_table; reg->name; reg++)
+          {
+            struct perc_entry *p = &perc_table[entry++];
+            p->type = perc_entry_reg;
+            p->name = reg->name;
+            p->len = strlen (reg->name);
+            p->reg = reg;
+          }
+      }
+
+    /* Add %-pseudo-ops.  */
+    {
+      struct pop_entry *pop;
+
+      for (pop = pop_table; pop->name; pop++)
+        {
+          struct perc_entry *p = &perc_table[entry++];
+          p->type = (pop->flags & F_POP_POSTFIX
+                     ? perc_entry_post_pop : perc_entry_imm_pop);
+          p->name = pop->name;
+          p->len = strlen (pop->name);
+          p->pop = pop;
+        }
+    }
+
+    /* Last entry is the centinel.  */
+    perc_table[entry].type = perc_entry_none;
+
+    qsort (perc_table, sizeof (perc_table) / sizeof (perc_table[0]),
+           sizeof (perc_table[0]), cmp_perc_entry);
+
+  }
 }
 
 /* Called after all assembly has been done.  */
@@ -1709,20 +1880,19 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
 	      /* Parse a sparc64 privileged register.  */
 	      if (*s == '%')
 		{
-		  struct priv_reg_entry *p = priv_reg_table;
+		  struct priv_reg_entry *p;
 		  unsigned int len = 9999999; /* Init to make gcc happy.  */
 
 		  s += 1;
-		  while (p->name[0] > s[0])
-		    p++;
-		  while (p->name[0] == s[0])
-		    {
-		      len = strlen (p->name);
-		      if (strncmp (p->name, s, len) == 0)
-			break;
-		      p++;
-		    }
-		  if (p->name[0] != s[0])
+                  for (p = priv_reg_table; p->name; p++)
+                    if (p->name[0] == s[0])
+                      {
+                        len = strlen (p->name);
+                        if (strncmp (p->name, s, len) == 0)
+                          break;
+                      }
+
+		  if (!p->name)
 		    {
 		      error_message = _(": unrecognizable privileged register");
 		      goto error;
@@ -1745,20 +1915,19 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
 	      /* Parse a sparc64 hyperprivileged register.  */
 	      if (*s == '%')
 		{
-		  struct priv_reg_entry *p = hpriv_reg_table;
+		  struct priv_reg_entry *p;
 		  unsigned int len = 9999999; /* Init to make gcc happy.  */
 
 		  s += 1;
-		  while (p->name[0] > s[0])
-		    p++;
-		  while (p->name[0] == s[0])
-		    {
-		      len = strlen (p->name);
-		      if (strncmp (p->name, s, len) == 0)
-			break;
-		      p++;
-		    }
-		  if (p->name[0] != s[0])
+                  for (p = hpriv_reg_table; p->name; p++)
+                    if (p->name[0] == s[0])
+                      {
+                        len = strlen (p->name);
+                        if (strncmp (p->name, s, len) == 0)
+                          break;
+                      }
+
+		  if (!p->name)
 		    {
 		      error_message = _(": unrecognizable hyperprivileged register");
 		      goto error;
@@ -1781,20 +1950,19 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
 	      /* Parse a v9a/v9b ancillary state register.  */
 	      if (*s == '%')
 		{
-		  struct priv_reg_entry *p = v9a_asr_table;
+		  struct priv_reg_entry *p;
 		  unsigned int len = 9999999; /* Init to make gcc happy.  */
 
 		  s += 1;
-		  while (p->name[0] > s[0])
-		    p++;
-		  while (p->name[0] == s[0])
-		    {
-		      len = strlen (p->name);
-		      if (strncmp (p->name, s, len) == 0)
-			break;
-		      p++;
-		    }
-		  if (p->name[0] != s[0])
+                  for (p = v9a_asr_table; p->name; p++)
+                    if (p->name[0] == s[0])
+                      {
+                        len = strlen (p->name);
+                        if (strncmp (p->name, s, len) == 0)
+                          break;
+                      }
+
+		  if (!p->name)
 		    {
 		      error_message = _(": unrecognizable v9a or v9b ancillary state register");
 		      goto error;
@@ -2062,67 +2230,45 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
 	    case '\0':		/* End of args.  */
 	      if (s[0] == ',' && s[1] == '%')
 		{
-		  static const struct ops
-		  {
-		    /* The name as it appears in assembler.  */
-		    const char *name;
-		    /* strlen (name), precomputed for speed */
-		    int len;
-		    /* The reloc this pseudo-op translates to.  */
-		    int reloc;
-		    /* 1 if tls call.  */
-		    int tls_call;
-		  }
-		  ops[] =
-		  {
-		    { "tgd_add", 7, BFD_RELOC_SPARC_TLS_GD_ADD, 0 },
-		    { "tgd_call", 8, BFD_RELOC_SPARC_TLS_GD_CALL, 1 },
-		    { "tldm_add", 8, BFD_RELOC_SPARC_TLS_LDM_ADD, 0 },
-		    { "tldm_call", 9, BFD_RELOC_SPARC_TLS_LDM_CALL, 1 },
-		    { "tldo_add", 8, BFD_RELOC_SPARC_TLS_LDO_ADD, 0 },
-		    { "tie_ldx", 7, BFD_RELOC_SPARC_TLS_IE_LDX, 0 },
-		    { "tie_ld", 6, BFD_RELOC_SPARC_TLS_IE_LD, 0 },
-		    { "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 },
-		    { "gdop", 4, BFD_RELOC_SPARC_GOTDATA_OP, 0 },
-		    { NULL, 0, 0, 0 }
-		  };
-		  const struct ops *o;
 		  char *s1;
 		  int npar = 0;
+                  const struct perc_entry *p;
 
-		  for (o = ops; o->name; o++)
-		    if (strncmp (s + 2, o->name, o->len) == 0)
-		      break;
-		  if (o->name == NULL)
-		    break;
+                  for (p = perc_table; p->type != perc_entry_none; p++)
+                    if ((p->type == perc_entry_post_pop || p->type == perc_entry_reg)
+                        && strncmp (s + 2, p->name, p->len) == 0)
+                      break;
+                  if (p->type == perc_entry_none || p->type == perc_entry_reg)
+                    break;
 
-		  if (s[o->len + 2] != '(')
+		  if (s[p->len + 2] != '(')
 		    {
-		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
+		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), p->name);
 		      return special_case;
 		    }
 
-		  if (! o->tls_call && the_insn.reloc != BFD_RELOC_NONE)
+		  if (! (p->pop->flags & F_POP_TLS_CALL)
+                      && the_insn.reloc != BFD_RELOC_NONE)
 		    {
 		      as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"),
-			      o->name);
+			      p->name);
 		      return special_case;
 		    }
 
-		  if (o->tls_call
+		  if ((p->pop->flags & F_POP_TLS_CALL)
 		      && (the_insn.reloc != BFD_RELOC_32_PCREL_S2
 			  || the_insn.exp.X_add_number != 0
 			  || the_insn.exp.X_add_symbol
 			     != symbol_find_or_make ("__tls_get_addr")))
 		    {
 		      as_bad (_("Illegal operands: %%%s can be only used with call __tls_get_addr"),
-			      o->name);
+			      p->name);
 		      return special_case;
 		    }
 
-		  the_insn.reloc = o->reloc;
+		  the_insn.reloc = p->pop->reloc;
 		  memset (&the_insn.exp, 0, sizeof (the_insn.exp));
-		  s += o->len + 3;
+		  s += p->len + 3;
 
 		  for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
 		    if (*s1 == '(')
@@ -2136,7 +2282,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
 
 		  if (*s1 != ')')
 		    {
-		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
+		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), p->name);
 		      return special_case;
 		    }
 
@@ -2525,72 +2671,25 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
 		/* Check for %hi, etc.  */
 		if (*s == '%')
 		  {
-		    static const struct ops {
-		      /* The name as it appears in assembler.  */
-		      const char *name;
-		      /* strlen (name), precomputed for speed */
-		      int len;
-		      /* The reloc this pseudo-op translates to.  */
-		      int reloc;
-		      /* Non-zero if for v9 only.  */
-		      int v9_p;
-		      /* Non-zero if can be used in pc-relative contexts.  */
-		      int pcrel_p;/*FIXME:wip*/
-		    } ops[] = {
-		      /* hix/lox must appear before hi/lo so %hix won't be
-			 mistaken for %hi.  */
-		      { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
-		      { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
-		      { "hi", 2, BFD_RELOC_HI22, 0, 1 },
-		      { "lo", 2, BFD_RELOC_LO10, 0, 1 },
-		      { "pc22", 4, BFD_RELOC_SPARC_PC22, 0, 1 },
-		      { "pc10", 4, BFD_RELOC_SPARC_PC10, 0, 1 },
-		      { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
-		      { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
-		      { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
-		      { "h34", 3, BFD_RELOC_SPARC_H34, 1, 0 },
-		      { "l34", 3, BFD_RELOC_SPARC_L44, 1, 0 },
-		      { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
-		      { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
-		      { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
-		      { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
-		      { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
-		      { "tgd_hi22", 8, BFD_RELOC_SPARC_TLS_GD_HI22, 0, 0 },
-		      { "tgd_lo10", 8, BFD_RELOC_SPARC_TLS_GD_LO10, 0, 0 },
-		      { "tldm_hi22", 9, BFD_RELOC_SPARC_TLS_LDM_HI22, 0, 0 },
-		      { "tldm_lo10", 9, BFD_RELOC_SPARC_TLS_LDM_LO10, 0, 0 },
-		      { "tldo_hix22", 10, BFD_RELOC_SPARC_TLS_LDO_HIX22, 0,
-									 0 },
-		      { "tldo_lox10", 10, BFD_RELOC_SPARC_TLS_LDO_LOX10, 0,
-									 0 },
-		      { "tie_hi22", 8, BFD_RELOC_SPARC_TLS_IE_HI22, 0, 0 },
-		      { "tie_lo10", 8, BFD_RELOC_SPARC_TLS_IE_LO10, 0, 0 },
-		      { "tle_hix22", 9, BFD_RELOC_SPARC_TLS_LE_HIX22, 0, 0 },
-		      { "tle_lox10", 9, BFD_RELOC_SPARC_TLS_LE_LOX10, 0, 0 },
-		      { "gdop_hix22", 10, BFD_RELOC_SPARC_GOTDATA_OP_HIX22,
-			0, 0 },
-		      { "gdop_lox10", 10, BFD_RELOC_SPARC_GOTDATA_OP_LOX10,
-			0, 0 },
-		      { NULL, 0, 0, 0, 0 }
-		    };
-		    const struct ops *o;
-
-		    for (o = ops; o->name; o++)
-		      if (strncmp (s + 1, o->name, o->len) == 0)
-			break;
-		    if (o->name == NULL)
-		      break;
-
-		    if (s[o->len + 1] != '(')
+                    const struct perc_entry *p;
+                    
+                    for (p = perc_table; p->type != perc_entry_none; p++)
+                      if ((p->type == perc_entry_imm_pop || p->type == perc_entry_reg)
+                          && strncmp (s + 1, p->name, p->len) == 0)
+                        break;
+                    if (p->type == perc_entry_none || p->type == perc_entry_reg)
+                      break;
+
+		    if (s[p->len + 1] != '(')
 		      {
-			as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
+			as_bad (_("Illegal operands: %%%s requires arguments in ()"), p->name);
 			return special_case;
 		      }
 
-		    op_arg = o->name;
-		    the_insn.reloc = o->reloc;
-		    s += o->len + 2;
-		    v9_arg_p = o->v9_p;
+		    op_arg = p->name;
+		    the_insn.reloc = p->pop->reloc;
+		    s += p->len + 2;
+		    v9_arg_p = p->pop->flags & F_POP_V9;
 		  }
 
 		/* Note that if the get_expression() fails, we will still


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