* config/tc-v850,h (TC_FIX_TYPE): Define. (TC_INIT_FIX_TYPE): Define.
* config/tc-v850.c (md_assemble): When creating a fix record the operand in the tc_fix_data field. (md_apply_fix3): When applying a resolved fix use the operand's insertion procedure to store the value, if the operand has been recorded. * gas/v850/split-lo16.s: Add test for a lo() pseudo reloc corrupting an ld.w instruction. * gas/v850/split-lo16.d: Add expected, correct (ie not corrupt) output.
This commit is contained in:
parent
641bd09305
commit
2d034539b1
7 changed files with 83 additions and 18 deletions
|
@ -1,3 +1,13 @@
|
|||
2005-05-17 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* config/tc-v850,h (TC_FIX_TYPE): Define.
|
||||
(TC_INIT_FIX_TYPE): Define.
|
||||
* config/tc-v850.c (md_assemble): When creating a fix record the
|
||||
operand in the tc_fix_data field.
|
||||
(md_apply_fix3): When applying a resolved fix use the operand's
|
||||
insertion procedure to store the value, if the operand has been
|
||||
recorded.
|
||||
|
||||
2005-05-15 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* Makefile.am (m68k-parse.c, itbl-parse.c): Update ylwrap
|
||||
|
|
|
@ -2125,6 +2125,8 @@ md_assemble (char *str)
|
|||
reloc_howto->pc_relative,
|
||||
reloc);
|
||||
|
||||
fixP->tc_fix_data = (void *) operand;
|
||||
|
||||
switch (reloc)
|
||||
{
|
||||
case BFD_RELOC_LO16:
|
||||
|
@ -2319,16 +2321,42 @@ md_apply_fix3 (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
|
|||
/* We still have to insert the value into memory! */
|
||||
where = fixP->fx_frag->fr_literal + fixP->fx_where;
|
||||
|
||||
if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
|
||||
bfd_putl32 (((value << 16) & 0xfffe0000)
|
||||
| ((value << 5) & 0x20)
|
||||
| (bfd_getl32 (where) & ~0xfffe0020), where);
|
||||
else if (fixP->fx_size == 1)
|
||||
*where = value & 0xff;
|
||||
else if (fixP->fx_size == 2)
|
||||
bfd_putl16 (value & 0xffff, (unsigned char *) where);
|
||||
else if (fixP->fx_size == 4)
|
||||
bfd_putl32 (value, (unsigned char *) where);
|
||||
if (fixP->tc_fix_data != NULL)
|
||||
{
|
||||
struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data;
|
||||
unsigned long insn;
|
||||
|
||||
/* The variable "where" currently points at the exact point inside
|
||||
the insn where we need to insert the value. But we need to
|
||||
extract the entire insn so we probably need to move "where"
|
||||
back a few bytes. */
|
||||
if (fixP->fx_size == 2)
|
||||
where -= 2;
|
||||
else if (fixP->fx_size == 1)
|
||||
where -= 3;
|
||||
|
||||
insn = bfd_getl32 ((unsigned char *) where);
|
||||
|
||||
/* Use the operand's insertion procedure, if present, in order to
|
||||
make sure that the value is correctly stored in the insn. */
|
||||
insn = v850_insert_operand (insn, operand, (offsetT) value,
|
||||
fixP->fx_file, fixP->fx_line, NULL);
|
||||
|
||||
bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
|
||||
bfd_putl32 (((value << 16) & 0xfffe0000)
|
||||
| ((value << 5) & 0x20)
|
||||
| (bfd_getl32 (where) & ~0xfffe0020), where);
|
||||
else if (fixP->fx_size == 1)
|
||||
*where = value & 0xff;
|
||||
else if (fixP->fx_size == 2)
|
||||
bfd_putl16 (value & 0xffff, (unsigned char *) where);
|
||||
else if (fixP->fx_size == 4)
|
||||
bfd_putl32 (value, (unsigned char *) where);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,3 +78,8 @@ extern void v850_handle_align (fragS *);
|
|||
extern long v850_pcrel_from_section (struct fix *, asection *);
|
||||
|
||||
#define DWARF2_LINE_MIN_INSN_LENGTH 2
|
||||
|
||||
/* We need to record the operand involved when a pseudo-reloc is
|
||||
processed so that the resulting value can be inserted correctly. */
|
||||
#define TC_FIX_TYPE void *
|
||||
#define TC_INIT_FIX_DATA(fixP) (fixP)->tc_fix_data = NULL
|
||||
|
|
|
@ -906,6 +906,7 @@ resolve_symbol_value (symbolS *symp)
|
|||
offsetT left, right;
|
||||
segT seg_left, seg_right;
|
||||
operatorT op;
|
||||
int move_seg_ok;
|
||||
|
||||
symp->sy_resolving = 1;
|
||||
|
||||
|
@ -1091,18 +1092,15 @@ resolve_symbol_value (symbolS *symp)
|
|||
}
|
||||
}
|
||||
|
||||
move_seg_ok = 1;
|
||||
/* Equality and non-equality tests are permitted on anything.
|
||||
Subtraction, and other comparison operators are permitted if
|
||||
both operands are in the same section. Otherwise, both
|
||||
operands must be absolute. We already handled the case of
|
||||
addition or subtraction of a constant above. This will
|
||||
probably need to be changed for an object file format which
|
||||
supports arbitrary expressions, such as IEEE-695.
|
||||
|
||||
Don't emit messages unless we're finalizing the symbol value,
|
||||
otherwise we may get the same message multiple times. */
|
||||
if (finalize_syms
|
||||
&& !(seg_left == absolute_section
|
||||
supports arbitrary expressions, such as IEEE-695. */
|
||||
if (!(seg_left == absolute_section
|
||||
&& seg_right == absolute_section)
|
||||
&& !(op == O_eq || op == O_ne)
|
||||
&& !((op == O_subtract
|
||||
|
@ -1110,9 +1108,21 @@ resolve_symbol_value (symbolS *symp)
|
|||
&& seg_left == seg_right
|
||||
&& (seg_left != undefined_section
|
||||
|| add_symbol == op_symbol)))
|
||||
report_op_error (symp, add_symbol, op_symbol);
|
||||
{
|
||||
/* Don't emit messages unless we're finalizing the symbol value,
|
||||
otherwise we may get the same message multiple times. */
|
||||
if (finalize_syms)
|
||||
report_op_error (symp, add_symbol, op_symbol);
|
||||
/* However do not move the symbol into the absolute section
|
||||
if it cannot currently be resolved - this would confuse
|
||||
other parts of the assembler into believing that the
|
||||
expression had been evaluated to zero. */
|
||||
else
|
||||
move_seg_ok = 0;
|
||||
}
|
||||
|
||||
if (final_seg == expr_section || final_seg == undefined_section)
|
||||
if (move_seg_ok
|
||||
&& (final_seg == expr_section || final_seg == undefined_section))
|
||||
final_seg = absolute_section;
|
||||
|
||||
/* Check for division by zero. */
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2005-05-17 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* gas/v850/split-lo16.s: Add test for a lo() pseudo reloc
|
||||
corrupting an ld.w instruction.
|
||||
* gas/v850/split-lo16.d: Add expected, correct (ie not corrupt)
|
||||
output.
|
||||
|
||||
2005-05-10 Michael Matz <matz@suse.de>
|
||||
|
||||
* gas/hppa/parse/block1.s: Use official limit (0x3fffffff) for
|
||||
|
|
|
@ -13,4 +13,6 @@
|
|||
c: R_V850_LO16_SPLIT_OFFSET foo
|
||||
10: a1 17 45 23 ld\.bu 9029\[r1\],r2
|
||||
14: 81 17 57 34 ld\.bu 13398\[r1\],r2
|
||||
18: 20 57 01 00 ld.w 0\[r0\],r10
|
||||
1c: 20 57 79 56 ld.w 22136\[r0\],r10
|
||||
#pass
|
||||
|
|
|
@ -5,3 +5,6 @@
|
|||
|
||||
ld.bu lo(0x12345),r1,r2
|
||||
ld.bu lo(0x123456),r1,r2
|
||||
|
||||
ld.w lo(0)[r0], r10
|
||||
ld.w lo(0x12345678)[r0], r10
|
||||
|
|
Loading…
Reference in a new issue