diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2004-12-16 16:56:04 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2004-12-16 16:56:04 +0000 |
commit | 1e50d24d553250622687bbc21027e8bfdb31870f (patch) | |
tree | c66a5fff096c41f49cd675874937fafe98209022 /gas/config/tc-v850.c | |
parent | 2fbd2a87e2cd23eba4eae6341661ce0149be08b1 (diff) | |
download | gdb-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.c | 29 |
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); |