* 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>
* 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,
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;
}