* 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:
parent
1c8f439ec6
commit
de2c5b0dae
2 changed files with 133 additions and 15 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue