include/elf/

* v850.h (R_V850_LO16_SPLIT_OFFSET): New reloc.

bfd/
	* reloc.c (BFD_RELOC_V850_LO16_SPLIT_OFFSET): New bfd_reloc_code_type.
	* elf32-v850.c (v850_elf_howto_table): Add entry for
	R_V850_LO16_SPLIT_OFFSET.
	(v850_elf_reloc_map): Map it to BFD_RELOC_V850_LO16_SPLIT_OFFSET.
	(v850_elf_perform_lo16_relocation): New function, extracted from...
	(v850_elf_perform_relocation): ...here.  Use it to handle
	R_V850_LO16_SPLIT_OFFSET.
	(v850_elf_check_relocs, v850_elf_final_link_relocate): Handle
	R_V850_LO16_SPLIT_OFFSET.
	* libbfd.h, bfd-in2.h: Regenerate.

gas/
	* config/tc-v850.c (handle_lo16): New function.
	(v850_reloc_prefix): Use it to check lo().
	(md_assemble, md_apply_fix3): Handle BFD_RELOC_V850_LO16_SPLIT_OFFSET.

gas/testsuite/
	* gas/v850/split-lo16.{s,d}: New test.
	* gas/v850/v850.exp: Run it.

ld/testsuite/
	* ld-v850: New directory.
This commit is contained in:
Richard Sandiford 2004-12-16 16:56:04 +00:00
parent 2fbd2a87e2
commit 1e50d24d55
18 changed files with 369 additions and 179 deletions

View file

@ -1,3 +1,16 @@
2004-12-16 Richard Sandiford <rsandifo@redhat.com>
* reloc.c (BFD_RELOC_V850_LO16_SPLIT_OFFSET): New bfd_reloc_code_type.
* elf32-v850.c (v850_elf_howto_table): Add entry for
R_V850_LO16_SPLIT_OFFSET.
(v850_elf_reloc_map): Map it to BFD_RELOC_V850_LO16_SPLIT_OFFSET.
(v850_elf_perform_lo16_relocation): New function, extracted from...
(v850_elf_perform_relocation): ...here. Use it to handle
R_V850_LO16_SPLIT_OFFSET.
(v850_elf_check_relocs, v850_elf_final_link_relocate): Handle
R_V850_LO16_SPLIT_OFFSET.
* libbfd.h, bfd-in2.h: Regenerate.
2004-12-14 P.J. Darcy <darcypj@us.ibm.com>
* config.bfd: Add s390x-ibm-tpf support.

View file

@ -2967,6 +2967,10 @@ bits placed non-contiguously in the instruction. */
/* Used to maintain alignment whilst relaxing. */
BFD_RELOC_V850_ALIGN,
/* This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu
instructions. */
BFD_RELOC_V850_LO16_SPLIT_OFFSET,
/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
instruction. */
BFD_RELOC_MN10300_32_PCREL,

View file

@ -533,6 +533,21 @@ static reloc_howto_type v850_elf_howto_table[] =
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* An ld.bu version of R_V850_LO16. */
HOWTO (R_V850_LO16_SPLIT_OFFSET, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
v850_elf_reloc, /* special_function */
"R_V850_LO16_SPLIT_OFFSET", /* name */
FALSE, /* partial_inplace */
0xfffe0020, /* src_mask */
0xfffe0020, /* dst_mask */
FALSE), /* pcrel_offset */
};
/* Map BFD reloc types to V850 ELF reloc types. */
@ -567,6 +582,7 @@ static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
{ BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
{ BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET },
{ BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET },
{ BFD_RELOC_V850_LO16_SPLIT_OFFSET, R_V850_LO16_SPLIT_OFFSET },
{ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
{ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
{ BFD_RELOC_V850_CALLT_6_7_OFFSET, R_V850_CALLT_6_7_OFFSET },
@ -687,6 +703,7 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
case R_V850_HI16_S:
case R_V850_HI16:
case R_V850_LO16:
case R_V850_LO16_SPLIT_OFFSET:
case R_V850_ABS32:
case R_V850_REL32:
case R_V850_16:
@ -902,83 +919,15 @@ find_remembered_hi16s_reloc (addend, already_found)
return addr;
}
/* FIXME: The code here probably ought to be removed and the code in reloc.c
allowed to do its stuff instead. At least for most of the relocs, anyway. */
/* Calculate the final operand value for a R_V850_LO16 or
R_V850_LO16_SPLIT_OFFSET. *INSN is the current operand value and
ADDEND is the sum of the relocation symbol and offset. Store the
operand value in *INSN and return true on success.
static bfd_reloc_status_type
v850_elf_perform_relocation (abfd, r_type, addend, address)
bfd *abfd;
unsigned int r_type;
bfd_vma addend;
bfd_byte *address;
{
unsigned long insn;
bfd_signed_vma saddend = (bfd_signed_vma) addend;
switch (r_type)
{
default:
/* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */
return bfd_reloc_notsupported;
case R_V850_REL32:
case R_V850_ABS32:
bfd_put_32 (abfd, addend, address);
return bfd_reloc_ok;
case R_V850_22_PCREL:
if (saddend > 0x1fffff || saddend < -0x200000)
return bfd_reloc_overflow;
if ((addend % 2) != 0)
return bfd_reloc_dangerous;
insn = bfd_get_32 (abfd, address);
insn &= ~0xfffe003f;
insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16));
bfd_put_32 (abfd, (bfd_vma) insn, address);
return bfd_reloc_ok;
case R_V850_9_PCREL:
if (saddend > 0xff || saddend < -0x100)
return bfd_reloc_overflow;
if ((addend % 2) != 0)
return bfd_reloc_dangerous;
insn = bfd_get_16 (abfd, address);
insn &= ~ 0xf870;
insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3);
break;
case R_V850_HI16:
addend += (bfd_get_16 (abfd, address) << 16);
addend = (addend >> 16);
insn = addend;
break;
case R_V850_HI16_S:
/* Remember where this relocation took place. */
remember_hi16s_reloc (abfd, addend, address);
addend += (bfd_get_16 (abfd, address) << 16);
addend = (addend >> 16) + ((addend & 0x8000) != 0);
/* This relocation cannot overflow. */
if (addend > 0x7fff)
addend = 0;
insn = addend;
break;
case R_V850_LO16:
/* Calculate the sum of the value stored in the instruction and the
addend and check for overflow from the low 16 bits into the high
16 bits. The assembler has already done some of this: If the
value stored in the instruction has its 15th bit set, (counting
from zero) then the assembler will have added 1 to the value
stored in the associated HI16S reloc. So for example, these
relocations:
The assembler has already done some of this: If the value stored in
the instruction has its 15th bit set, (counting from zero) then the
assembler will have added 1 to the value stored in the associated
HI16S reloc. So for example, these relocations:
movhi hi( fred ), r0, r1
movea lo( fred ), r1, r1
@ -1111,18 +1060,16 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
+ 0x00006fff (bit 15 not set, so the top half is zero)
------------
0x00006fff which is wrong (assuming that fred is at 0xffff). */
static bfd_boolean
v850_elf_perform_lo16_relocation (bfd *abfd, unsigned long *insn,
unsigned long addend)
{
long result;
insn = bfd_get_16 (abfd, address);
result = insn + addend;
#define BIT15_SET(x) ((x) & 0x8000)
#define OVERFLOWS(a,i) ((((a) & 0xffff) + (i)) > 0xffff)
if ((BIT15_SET (result) && ! BIT15_SET (addend))
|| (OVERFLOWS (addend, insn)
&& ((! BIT15_SET (insn)) || (BIT15_SET (addend)))))
if ((BIT15_SET (*insn + addend) && ! BIT15_SET (addend))
|| (OVERFLOWS (addend, *insn)
&& ((! BIT15_SET (*insn)) || (BIT15_SET (addend)))))
{
bfd_boolean already_updated;
bfd_byte *hi16s_address = find_remembered_hi16s_reloc
@ -1133,22 +1080,101 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
{
if (! already_updated)
{
insn = bfd_get_16 (abfd, hi16s_address);
insn += 1;
bfd_put_16 (abfd, (bfd_vma) insn, hi16s_address);
unsigned long hi_insn = bfd_get_16 (abfd, hi16s_address);
hi_insn += 1;
bfd_put_16 (abfd, hi_insn, hi16s_address);
}
}
else
{
fprintf (stderr, _("FAILED to find previous HI16 reloc\n"));
return bfd_reloc_overflow;
return FALSE;
}
}
#undef OVERFLOWS
#undef BIT15_SET
/* Do not complain if value has top bit set, as this has been
anticipated. */
*insn = (*insn + addend) & 0xffff;
return TRUE;
}
/* Do not complain if value has top bit set, as this has been anticipated. */
insn = result & 0xffff;
/* FIXME: The code here probably ought to be removed and the code in reloc.c
allowed to do its stuff instead. At least for most of the relocs, anyway. */
static bfd_reloc_status_type
v850_elf_perform_relocation (abfd, r_type, addend, address)
bfd *abfd;
unsigned int r_type;
bfd_vma addend;
bfd_byte *address;
{
unsigned long insn;
unsigned long result;
bfd_signed_vma saddend = (bfd_signed_vma) addend;
switch (r_type)
{
default:
/* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */
return bfd_reloc_notsupported;
case R_V850_REL32:
case R_V850_ABS32:
bfd_put_32 (abfd, addend, address);
return bfd_reloc_ok;
case R_V850_22_PCREL:
if (saddend > 0x1fffff || saddend < -0x200000)
return bfd_reloc_overflow;
if ((addend % 2) != 0)
return bfd_reloc_dangerous;
insn = bfd_get_32 (abfd, address);
insn &= ~0xfffe003f;
insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16));
bfd_put_32 (abfd, (bfd_vma) insn, address);
return bfd_reloc_ok;
case R_V850_9_PCREL:
if (saddend > 0xff || saddend < -0x100)
return bfd_reloc_overflow;
if ((addend % 2) != 0)
return bfd_reloc_dangerous;
insn = bfd_get_16 (abfd, address);
insn &= ~ 0xf870;
insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3);
break;
case R_V850_HI16:
addend += (bfd_get_16 (abfd, address) << 16);
addend = (addend >> 16);
insn = addend;
break;
case R_V850_HI16_S:
/* Remember where this relocation took place. */
remember_hi16s_reloc (abfd, addend, address);
addend += (bfd_get_16 (abfd, address) << 16);
addend = (addend >> 16) + ((addend & 0x8000) != 0);
/* This relocation cannot overflow. */
if (addend > 0x7fff)
addend = 0;
insn = addend;
break;
case R_V850_LO16:
insn = bfd_get_16 (abfd, address);
if (! v850_elf_perform_lo16_relocation (abfd, &insn, addend))
return bfd_reloc_overflow;
break;
}
case R_V850_8:
addend += (char) bfd_get_8 (abfd, address);
@ -1278,6 +1304,17 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
insn |= addend;
break;
case R_V850_LO16_SPLIT_OFFSET:
insn = bfd_get_32 (abfd, address);
result = ((insn & 0xfffe0000) >> 16) | ((insn & 0x20) >> 5);
if (! v850_elf_perform_lo16_relocation (abfd, &result, addend))
return bfd_reloc_overflow;
insn = (((result << 16) & 0xfffe0000)
| ((result << 5) & 0x20)
| (insn & ~0xfffe0020));
bfd_put_32 (abfd, insn, address);
return bfd_reloc_ok;
case R_V850_ZDA_16_16_SPLIT_OFFSET:
case R_V850_SDA_16_16_SPLIT_OFFSET:
insn = bfd_get_32 (abfd, address);
@ -1492,6 +1529,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
case R_V850_HI16_S:
case R_V850_HI16:
case R_V850_LO16:
case R_V850_LO16_SPLIT_OFFSET:
case R_V850_16:
case R_V850_ABS32:
case R_V850_8:

View file

@ -1299,6 +1299,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_V850_LONGCALL",
"BFD_RELOC_V850_LONGJUMP",
"BFD_RELOC_V850_ALIGN",
"BFD_RELOC_V850_LO16_SPLIT_OFFSET",
"BFD_RELOC_MN10300_32_PCREL",
"BFD_RELOC_MN10300_16_PCREL",
"BFD_RELOC_TIC30_LDP",

View file

@ -3098,6 +3098,11 @@ ENUM
BFD_RELOC_V850_ALIGN
ENUMDOC
Used to maintain alignment whilst relaxing.
ENUM
BFD_RELOC_V850_LO16_SPLIT_OFFSET
ENUMDOC
This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu
instructions.
ENUM
BFD_RELOC_MN10300_32_PCREL
ENUMDOC

View file

@ -1,3 +1,9 @@
2004-12-16 Richard Sandiford <rsandifo@redhat.com>
* config/tc-v850.c (handle_lo16): New function.
(v850_reloc_prefix): Use it to check lo().
(md_assemble, md_apply_fix3): Handle BFD_RELOC_V850_LO16_SPLIT_OFFSET.
2004-12-14 P.J. Darcy <darcypj@us.ibm.com>
* configure.in: Add s390x-ibm-tpf support.

View file

@ -1375,6 +1375,25 @@ md_begin ()
bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
}
static bfd_reloc_code_real_type
handle_lo16 (const struct v850_operand *operand)
{
if (operand != NULL)
{
if (operand->bits == -1)
return BFD_RELOC_V850_LO16_SPLIT_OFFSET;
if (!(operand->bits == 16 && operand->shift == 16)
&& !(operand->bits == 15 && operand->shift == 17))
{
as_bad (_("lo() relocation used on an instruction which does "
"not support it"));
return BFD_RELOC_64; /* Used to indicate an error condition. */
}
}
return BFD_RELOC_LO16;
}
static bfd_reloc_code_real_type handle_ctoff
PARAMS ((const struct v850_operand *));
@ -1516,7 +1535,7 @@ v850_reloc_prefix (operand)
CHECK_ ("hi0", BFD_RELOC_HI16 );
CHECK_ ("hi", BFD_RELOC_HI16_S );
CHECK_ ("lo", BFD_RELOC_LO16 );
CHECK_ ("lo", handle_lo16 (operand) );
CHECK_ ("sdaoff", handle_sdaoff (operand));
CHECK_ ("zdaoff", handle_zdaoff (operand));
CHECK_ ("tdaoff", handle_tdaoff (operand));
@ -1755,6 +1774,7 @@ md_assemble (str)
/* Fall through. */
case BFD_RELOC_LO16:
case BFD_RELOC_V850_LO16_SPLIT_OFFSET:
{
/* Truncate, then sign extend the value. */
ex.X_add_number = SEXT16 (ex.X_add_number);
@ -2199,6 +2219,7 @@ md_assemble (str)
switch (reloc)
{
case BFD_RELOC_LO16:
case BFD_RELOC_V850_LO16_SPLIT_OFFSET:
case BFD_RELOC_HI16:
case BFD_RELOC_HI16_S:
fixP->fx_no_overflow = 1;
@ -2405,7 +2426,11 @@ md_apply_fix3 (fixP, valueP, seg)
/* We still have to insert the value into memory! */
where = fixP->fx_frag->fr_literal + fixP->fx_where;
if (fixP->fx_size == 1)
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);

View file

@ -1,3 +1,8 @@
2004-12-16 Richard Sandiford <rsandifo@redhat.com>
* gas/v850/split-lo16.{s,d}: New test.
* gas/v850/v850.exp: Run it.
2004-12-15 Jan Beulich <jbeulich@novell.com>
* gas/elf/section5.[els]: New.

View file

@ -436,4 +436,5 @@ if [istarget v850*-*-*] then {
gas_test_error "range.s" "-mwarn-signed-overflow" "Check for range error on byte load/store"
run_dump_test "v850e1"
run_dump_test "split-lo16"
}

View file

@ -0,0 +1,16 @@
#objdump: -dr
#name: V850E split LO16 tests
#as: -mv850e
#...
00000000 <.*>:
0: 40 0e 00 00 movhi 0, r0, r1
2: R_V850_HI16_S foo
4: 01 16 00 00 addi 0, r1, r2
6: R_V850_LO16 foo
8: 01 17 00 00 ld\.b 0\[r1\],r2
a: R_V850_LO16 foo
c: 81 17 01 00 ld\.bu 0\[r1\],r2
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
#pass

View file

@ -0,0 +1,7 @@
movhi hi(foo),r0,r1
addi lo(foo),r1,r2
ld.b lo(foo),r1,r2
ld.bu lo(foo),r1,r2
ld.bu lo(0x12345),r1,r2
ld.bu lo(0x123456),r1,r2

View file

@ -1,3 +1,7 @@
2004-12-16 Richard Sandiford <rsandifo@redhat.com>
* v850.h (R_V850_LO16_SPLIT_OFFSET): New reloc.
2004-12-09 Ian Lance Taylor <ian@wasabisystems.com>
* mips.h (E_MIPS_MACH_9000): Define.

View file

@ -79,6 +79,7 @@ START_RELOC_NUMBERS (v850_reloc_type)
RELOC_NUMBER (R_V850_LONGJUMP, 26)
RELOC_NUMBER (R_V850_ALIGN, 27)
RELOC_NUMBER (R_V850_REL32, 28)
RELOC_NUMBER (R_V850_LO16_SPLIT_OFFSET, 29) /* For ld.bu */
END_RELOC_NUMBERS (R_V850_max)

View file

@ -1,3 +1,7 @@
2004-12-16 Richard Sandiford <rsandifo@redhat.com>
* ld-v850: New directory.
2004-12-14 Richard Sandiford <rsandifo@redhat.com>
* ld-mips-elf/jal-overflow-2.[sd]: New test.

View file

@ -0,0 +1,26 @@
#source: split-lo16.s -mv850e
#ld: -Tsplit-lo16.ld
#objdump: -d
#...
00010000 <.*>:
10000: 40 0e 34 12 movhi 4660, r0, r1
10004: 01 16 78 56 addi 22136, r1, r2
10008: 81 17 79 56 ld\.bu 22136\[r1\],r2
1000c: 40 0e 36 12 movhi 4662, r0, r1
10010: 01 16 78 d8 addi -10120, r1, r2
10014: 81 17 79 d8 ld\.bu -10120\[r1\],r2
10018: 40 0e 12 00 movhi 18, r0, r1
1001c: 81 17 57 34 ld\.bu 13398\[r1\],r2
10020: 01 16 56 34 addi 13398, r1, r2
10024: 40 0e 14 00 movhi 20, r0, r1
10028: 81 17 57 b6 ld\.bu -18858\[r1\],r2
1002c: 01 16 56 b6 addi -18858, r1, r2
10030: 40 0e 79 56 movhi 22137, r0, r1
10034: 01 16 bc 9a addi -25924, r1, r2
10038: 81 17 bd 9a ld\.bu -25924\[r1\],r2
1003c: 40 0e 9b 78 movhi 30875, r0, r1
10040: 81 17 df bc ld\.bu -17186\[r1\],r2
10044: 01 16 de bc addi -17186, r1, r2
10048: 40 0e 45 23 movhi 9029, r0, r1
1004c: a1 17 89 67 ld\.bu 26505\[r1\],r2
#pass

View file

@ -0,0 +1,11 @@
SECTIONS
{
lo16_carry = 0x56789abc;
lo16_nocarry = 0x12345678;
split_lo16_carry = 0x789abcde;
split_lo16_nocarry = 0x00123456;
odd = 0x23456789;
. = 0x10000;
.text : { *(.text); }
/DISCARD/ : { *(*); }
}

View file

@ -0,0 +1,20 @@
movhi hi(lo16_nocarry),r0,r1
addi lo(lo16_nocarry),r1,r2
ld.bu lo(lo16_nocarry)[r1],r2
movhi hi(lo16_nocarry + 0x18200),r0,r1
addi lo(lo16_nocarry + 0x18200),r1,r2
ld.bu lo(lo16_nocarry + 0x18200)[r1],r2
movhi hi(split_lo16_nocarry),r0,r1
ld.bu lo(split_lo16_nocarry)[r1],r2
addi lo(split_lo16_nocarry),r1,r2
movhi hi(split_lo16_nocarry + 0x18200),r0,r1
ld.bu lo(split_lo16_nocarry + 0x18200)[r1],r2
addi lo(split_lo16_nocarry + 0x18200),r1,r2
movhi hi(lo16_carry),r0,r1
addi lo(lo16_carry),r1,r2
ld.bu lo(lo16_carry)[r1],r2
movhi hi(split_lo16_carry),r0,r1
ld.bu lo(split_lo16_carry)[r1],r2
addi lo(split_lo16_carry),r1,r2
movhi hi(odd),r0,r1
ld.bu lo(odd)[r1],r2

View file

@ -0,0 +1,3 @@
if [istarget v850*-*-*] {
run_dump_test "split-lo16"
}