* 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:
Nick Clifton 2005-05-17 11:56:13 +00:00
parent 641bd09305
commit 2d034539b1
7 changed files with 83 additions and 18 deletions

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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