* 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.
This commit is contained in:
Catherine Moore 1998-11-10 20:50:34 +00:00
parent 1c8f439ec6
commit de2c5b0dae
2 changed files with 133 additions and 15 deletions

View file

@ -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> Mon Nov 9 14:25:06 1998 Nick Clifton <nickc@cygnus.com>
* config/tc-d30v.c: Change default behaviour to ignore potential * config/tc-d30v.c: Change default behaviour to ignore potential

View file

@ -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, static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
struct d10v_opcode *opcode2, unsigned long insn2, struct d10v_opcode *opcode2, unsigned long insn2,
int exec_type)); 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) #define OPTION_NOWARNSWAP (OPTION_MD_BASE)
{"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP}, {"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP},
{NULL, no_argument, NULL, 0} {NULL, no_argument, NULL, 0}
@ -1124,6 +1126,29 @@ do_assemble (str, opcode)
return (insn); 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. */ /* 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 */ /* It must look at all opcodes with the same name and use the operands */
/* to choose the correct opcode. */ /* to choose the correct opcode. */
@ -1240,9 +1265,9 @@ find_opcode (opcode, myops)
int X_op = myops[i].X_op; int X_op = myops[i].X_op;
int num = myops[i].X_add_number; int num = myops[i].X_add_number;
if (X_op==0) if (X_op == 0)
{ {
match=0; match = 0;
break; break;
} }
@ -1254,33 +1279,61 @@ find_opcode (opcode, myops)
| OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_FFLAG | OPERAND_CFLAG
| OPERAND_CONTROL))) | OPERAND_CONTROL)))
{ {
match=0; match = 0;
break; break;
} }
} }
if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS))) || if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS))) ||
((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS))) || ((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||
((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) || ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) ||
((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR))) || ((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||
((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN)))) ((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN))))
{ {
match=0; match = 0;
break; 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 */ /* We're only done if the operands matched so far AND there
if (match && myops[i].X_op==0) are no more to check. */
if (match && myops[i].X_op == 0)
break; break;
else else
match = 0; match = 0;
next_opcode = opcode+1; next_opcode = opcode + 1;
if (next_opcode->opcode == 0) if (next_opcode->opcode == 0)
break; break;
if (strcmp(next_opcode->name, opcode->name))
if (strcmp (next_opcode->name, opcode->name))
break; break;
opcode = next_opcode; 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); _("reloc %d not supported by object file format"), (int)fixp->fx_r_type);
return NULL; 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; reloc->addend = fixp->fx_addnumber;
return reloc; return reloc;
} }
@ -1427,6 +1486,17 @@ md_apply_fix3 (fixp, valuep, seg)
bfd_putb16 ((bfd_vma) value, (unsigned char *) where); bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
else 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); insn = d10v_insert_operand (insn, op_type, (offsetT)value, left, fixp);
bfd_putb32 ((bfd_vma) insn, (unsigned char *) where); bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
} }
@ -1437,6 +1507,12 @@ md_apply_fix3 (fixp, valuep, seg)
case BFD_RELOC_16: case BFD_RELOC_16:
bfd_putb16 ((bfd_vma) value, (unsigned char *) where); bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
break; break;
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
fixp->fx_done = 0;
return 1;
default: default:
as_fatal (_("line %d: unknown relocation type: 0x%x"),fixp->fx_line,fixp->fx_r_type); 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;
}