aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorCatherine Moore <clm@redhat.com>1998-11-10 20:50:34 +0000
committerCatherine Moore <clm@redhat.com>1998-11-10 20:50:34 +0000
commitde2c5b0daed8ba4536cae7922e79aaab9239f861 (patch)
tree991b20f25e8ff0c64621ff79adbabc83c356be28 /gas
parent1c8f439ec6f8f43fa3a6e1987fb5ea23ebd910f8 (diff)
downloadgdb-de2c5b0daed8ba4536cae7922e79aaab9239f861.zip
gdb-de2c5b0daed8ba4536cae7922e79aaab9239f861.tar.gz
gdb-de2c5b0daed8ba4536cae7922e79aaab9239f861.tar.bz2
* config/tc-d10v.h (obj_fix_adjustable): Define.
(TC_FORCE_RELOCATION): Define. (d10v_force_relocation): Declare. * config/tc-d10v.c (tc_gen_reloc): Handle Vtable relocs. (md_apply_fix3): Handle Vtable relocs. (d10v_fix_adjustable): New. (d10v_force_relocation): New.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog10
-rw-r--r--gas/config/tc-d10v.c138
2 files changed, 133 insertions, 15 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 7e1f5c2..c94d703 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,13 @@
+Tue Nov 10 14:41:33 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-d10v.h (obj_fix_adjustable): Define.
+ (TC_FORCE_RELOCATION): Define.
+ (d10v_force_relocation): Declare.
+ * config/tc-d10v.c (tc_gen_reloc): Handle Vtable relocs.
+ (md_apply_fix3): Handle Vtable relocs.
+ (d10v_fix_adjustable): New.
+ (d10v_force_relocation): New.
+
Mon Nov 9 14:25:06 1998 Nick Clifton <nickc@cygnus.com>
* config/tc-d30v.c: Change default behaviour to ignore potential
diff --git a/gas/config/tc-d10v.c b/gas/config/tc-d10v.c
index b8ffc4e..3ec5b8b 100644
--- a/gas/config/tc-d10v.c
+++ b/gas/config/tc-d10v.c
@@ -85,8 +85,10 @@ static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_ty
static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
struct d10v_opcode *opcode2, unsigned long insn2,
int exec_type));
+static symbolS * find_symbol_matching_register PARAMS ((expressionS *));
-struct option md_longopts[] = {
+struct option md_longopts[] =
+{
#define OPTION_NOWARNSWAP (OPTION_MD_BASE)
{"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP},
{NULL, no_argument, NULL, 0}
@@ -1124,6 +1126,29 @@ do_assemble (str, opcode)
return (insn);
}
+/* Find the symbol which has the same name as the register in the given expression. */
+static symbolS *
+find_symbol_matching_register (exp)
+ expressionS * exp;
+{
+ int i;
+
+ if (exp->X_op != O_register)
+ return NULL;
+
+ /* Find the name of the register. */
+ for (i = d10v_reg_name_cnt (); i--;)
+ if (d10v_predefined_registers [i].value == exp->X_add_number)
+ break;
+
+ if (i < 0)
+ abort ();
+
+ /* Now see if a symbol has been defined with the same name. */
+ return symbol_find (d10v_predefined_registers [i].name);
+}
+
+
/* find_opcode() gets a pointer to an entry in the opcode table. */
/* It must look at all opcodes with the same name and use the operands */
/* to choose the correct opcode. */
@@ -1240,9 +1265,9 @@ find_opcode (opcode, myops)
int X_op = myops[i].X_op;
int num = myops[i].X_add_number;
- if (X_op==0)
+ if (X_op == 0)
{
- match=0;
+ match = 0;
break;
}
@@ -1254,33 +1279,61 @@ find_opcode (opcode, myops)
| OPERAND_FFLAG | OPERAND_CFLAG
| OPERAND_CONTROL)))
{
- match=0;
+ match = 0;
break;
}
}
- if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS))) ||
- ((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||
+ if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS))) ||
+ ((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||
((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) ||
- ((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||
- ((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN))))
+ ((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||
+ ((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN))))
{
- match=0;
+ match = 0;
break;
- }
+ }
+
+ /* Unfortunatly, for the indirect operand in instructions such as
+ ``ldb r1, @(c,r14)'' this function can be passed X_op == O_register
+ (because 'c' is a valid register name). However we cannot just
+ ignore the case when X_op == O_register but flags & OPERAND_REG is
+ null, so we check to see if a symbol of the same name as the register
+ exists. If the symbol does exist, then the parser was unable to
+ distinguish the two cases and we fix things here. (Ref: PR14826) */
+
+ if (!(flags & OPERAND_REG) && (X_op == O_register))
+ {
+ symbolS * sym;
+
+ sym = find_symbol_matching_register (& myops[i]);
+
+ if (sym != NULL)
+ {
+ myops [i].X_op == X_op == O_symbol;
+ myops [i].X_add_symbol = sym;
+ }
+ else
+ as_bad
+ (_("illegal operand - register name found where none expected"));
+ }
}
- /* we're only done if the operands matched so far AND there
- are no more to check */
- if (match && myops[i].X_op==0)
+
+ /* We're only done if the operands matched so far AND there
+ are no more to check. */
+ if (match && myops[i].X_op == 0)
break;
else
match = 0;
- next_opcode = opcode+1;
+ next_opcode = opcode + 1;
+
if (next_opcode->opcode == 0)
break;
- if (strcmp(next_opcode->name, opcode->name))
+
+ if (strcmp (next_opcode->name, opcode->name))
break;
+
opcode = next_opcode;
}
}
@@ -1332,7 +1385,13 @@ tc_gen_reloc (seg, fixp)
_("reloc %d not supported by object file format"), (int)fixp->fx_r_type);
return NULL;
}
+
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ reloc->address = fixp->fx_offset;
+
reloc->addend = fixp->fx_addnumber;
+
return reloc;
}
@@ -1427,6 +1486,17 @@ md_apply_fix3 (fixp, valuep, seg)
bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
else
{
+ struct d10v_opcode *rep, *repi;
+
+ rep = (struct d10v_opcode *) hash_find (d10v_hash, "rep");
+ repi = (struct d10v_opcode *) hash_find (d10v_hash, "repi");
+ if ((insn & FM11) == FM11
+ && (repi != NULL && (insn & repi->mask) == repi->opcode
+ || rep != NULL && (insn & rep->mask) == rep->opcode)
+ && value < 4)
+ as_fatal
+ (_("line %d: rep or repi must include at least 4 instructions"),
+ fixp->fx_line);
insn = d10v_insert_operand (insn, op_type, (offsetT)value, left, fixp);
bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
}
@@ -1437,6 +1507,12 @@ md_apply_fix3 (fixp, valuep, seg)
case BFD_RELOC_16:
bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixp->fx_done = 0;
+ return 1;
+
default:
as_fatal (_("line %d: unknown relocation type: 0x%x"),fixp->fx_line,fixp->fx_r_type);
}
@@ -1525,3 +1601,35 @@ md_operand (expressionP)
}
}
+boolean
+d10v_fix_adjustable (fixP)
+ fixS *fixP;
+{
+
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+
+ /* We need the symbol name for the VTABLE entries */
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
+
+int
+d10v_force_relocation (fixp)
+ struct fix *fixp;
+{
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ return 0;
+}