aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-v850.c
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2004-12-16 16:56:04 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2004-12-16 16:56:04 +0000
commit1e50d24d553250622687bbc21027e8bfdb31870f (patch)
treec66a5fff096c41f49cd675874937fafe98209022 /gas/config/tc-v850.c
parent2fbd2a87e2cd23eba4eae6341661ce0149be08b1 (diff)
downloadgdb-1e50d24d553250622687bbc21027e8bfdb31870f.zip
gdb-1e50d24d553250622687bbc21027e8bfdb31870f.tar.gz
gdb-1e50d24d553250622687bbc21027e8bfdb31870f.tar.bz2
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.
Diffstat (limited to 'gas/config/tc-v850.c')
-rw-r--r--gas/config/tc-v850.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c
index ed208ee..dfa1c7f 100644
--- a/gas/config/tc-v850.c
+++ b/gas/config/tc-v850.c
@@ -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);