aboutsummaryrefslogtreecommitdiff
path: root/bfd/coff-z80.c
diff options
context:
space:
mode:
authorSergey Belyashov <sergey.belyashov@gmail.com>2020-01-02 14:10:40 +0000
committerNick Clifton <nickc@redhat.com>2020-01-02 14:14:59 +0000
commit6655dba246bd164d953fe220a0e3d4eed85bb268 (patch)
tree423258b5dadb447dc649e71c6ce48aaeed8ba385 /bfd/coff-z80.c
parent0db131fb835e4c4f6a024e86743467e7e01c965e (diff)
downloadgdb-6655dba246bd164d953fe220a0e3d4eed85bb268.zip
gdb-6655dba246bd164d953fe220a0e3d4eed85bb268.tar.gz
gdb-6655dba246bd164d953fe220a0e3d4eed85bb268.tar.bz2
Add support for the GBZ80, Z180, and eZ80 variants of the Z80 architecure. Add an ELF based target for these as well.
PR 25224 bfd * Makefile.am: Add z80-elf target support. * configure.ac: Likewise. * targets.c: Likewise. * config.bfd: Add z80-elf target support and new arches: ez80 and z180. * elf32-z80.c: New file. * archures.c: Add new z80 architectures: eZ80 and Z180. * coffcode.h: Likewise. * cpu-z80.c: Likewise. * bfd-in2.h: Likewise plus additional Z80 relocations. * coff-z80.c: Add new relocations for Z80 target and local label check. gas * config/tc-z80.c: Add new architectures: Z180 and eZ80. Add support for assembler code generated by SDCC. Add new relocation types. Add z80-elf target support. * config/tc-z80.h: Add z80-elf target support. Enable dollar local labels. Local labels starts from ".L". * testsuite/gas/all/fwdexp.d: Fix failure due to symbol conflict. * testsuite/gas/all/fwdexp.s: Likewise. * testsuite/gas/z80/suffix.d: Fix failure on ELF target. * testsuite/gas/z80/z80.exp: Add new tests * testsuite/gas/z80/dollar.d: New file. * testsuite/gas/z80/dollar.s: New file. * testsuite/gas/z80/ez80_adl_all.d: New file. * testsuite/gas/z80/ez80_adl_all.s: New file. * testsuite/gas/z80/ez80_adl_suf.d: New file. * testsuite/gas/z80/ez80_isuf.s: New file. * testsuite/gas/z80/ez80_z80_all.d: New file. * testsuite/gas/z80/ez80_z80_all.s: New file. * testsuite/gas/z80/ez80_z80_suf.d: New file. * testsuite/gas/z80/r800_extra.d: New file. * testsuite/gas/z80/r800_extra.s: New file. * testsuite/gas/z80/r800_ii8.d: New file. * testsuite/gas/z80/r800_z80_doc.d: New file. * testsuite/gas/z80/z180.d: New file. * testsuite/gas/z80/z180.s: New file. * testsuite/gas/z80/z180_z80_doc.d: New file. * testsuite/gas/z80/z80_doc.d: New file. * testsuite/gas/z80/z80_doc.s: New file. * testsuite/gas/z80/z80_ii8.d: New file. * testsuite/gas/z80/z80_ii8.s: New file. * testsuite/gas/z80/z80_in_f_c.d: New file. * testsuite/gas/z80/z80_in_f_c.s: New file. * testsuite/gas/z80/z80_op_ii_ld.d: New file. * testsuite/gas/z80/z80_op_ii_ld.s: New file. * testsuite/gas/z80/z80_out_c_0.d: New file. * testsuite/gas/z80/z80_out_c_0.s: New file. * testsuite/gas/z80/z80_reloc.d: New file. * testsuite/gas/z80/z80_reloc.s: New file. * testsuite/gas/z80/z80_sli.d: New file. * testsuite/gas/z80/z80_sli.s: New file. ld * Makefile.am: Add new target z80-elf * configure.tgt: Likewise. * emultempl/z80.em: Add support for eZ80 and Z180 architectures. * emulparams/elf32z80.sh: New file. * emultempl/z80elf.em: Likewise. * testsuite/ld-z80/arch_ez80_adl.d: Likewise. * testsuite/ld-z80/arch_ez80_z80.d: Likewise. * testsuite/ld-z80/arch_r800.d: Likewise. * testsuite/ld-z80/arch_z180.d: Likewise. * testsuite/ld-z80/arch_z80.d: Likewise. * testsuite/ld-z80/comb_arch_ez80_z80.d: Likewise. * testsuite/ld-z80/comb_arch_z180.d: Likewise. * testsuite/ld-z80/labels.s: Likewise. * testsuite/ld-z80/relocs.s: Likewise. * testsuite/ld-z80/relocs_b_ez80.d: Likewise. * testsuite/ld-z80/relocs_b_z80.d: Likewise. * testsuite/ld-z80/relocs_f_z80.d: Likewise. * testsuite/ld-z80/z80.exp: Likewise. opcodes * z80-dis.c: Add support for eZ80 and Z80 instructions.
Diffstat (limited to 'bfd/coff-z80.c')
-rw-r--r--bfd/coff-z80.c362
1 files changed, 269 insertions, 93 deletions
diff --git a/bfd/coff-z80.c b/bfd/coff-z80.c
index 40bb60d..bb519fd 100644
--- a/bfd/coff-z80.c
+++ b/bfd/coff-z80.c
@@ -26,39 +26,204 @@
#include "coff/z80.h"
#include "coff/internal.h"
#include "libcoff.h"
+#include "libiberty.h"
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
-static reloc_howto_type r_imm32 =
-HOWTO (R_IMM32, 0, 2, 32, FALSE, 0,
- complain_overflow_dont, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff,
- FALSE);
+typedef struct {
+ bfd_reloc_code_real_type r_type;
+ reloc_howto_type howto;
+} bfd_howto_type;
-static reloc_howto_type r_imm24 =
-HOWTO (R_IMM24, 0, 1, 24, FALSE, 0,
- complain_overflow_dont, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff,
- FALSE);
-
-static reloc_howto_type r_imm16 =
-HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
- complain_overflow_dont, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff,
- FALSE);
-
-static reloc_howto_type r_imm8 =
-HOWTO (R_IMM8, 0, 0, 8, FALSE, 0,
- complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff,
- FALSE);
-
-static reloc_howto_type r_jr =
-HOWTO (R_JR, 0, 0, 8, TRUE, 0,
- complain_overflow_signed, 0, "r_jr", FALSE, 0, 0xFF,
- FALSE);
-
-static reloc_howto_type r_off8 =
-HOWTO (R_OFF8, 0, 0, 8, FALSE, 0,
- complain_overflow_signed, 0,"r_off8", FALSE, 0, 0xff,
- FALSE);
+#define BFD_EMPTY_HOWTO(rt,x) {rt, EMPTY_HOWTO(x)}
+#define BFD_HOWTO(rt,a,b,c,d,e,f,g,h,i,j,k,l,m) {rt, HOWTO(a,b,c,d,e,f,g,h,i,j,k,l,m)}
+static bfd_howto_type howto_table[] =
+{
+ BFD_EMPTY_HOWTO (BFD_RELOC_NONE, 0),
+
+ BFD_HOWTO (BFD_RELOC_32,
+ R_IMM32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_imm32", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_24,
+ R_IMM24, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_imm24", /* name */
+ FALSE, /* partial_inplace */
+ 0x00ffffff, /* src_mask */
+ 0x00ffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_16,
+ R_IMM16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_imm16", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_8,
+ R_IMM8, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_imm8", /* name */
+ FALSE, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_8_PCREL,
+ R_JR, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_jr", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xFF, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_Z80_DISP8,
+ R_OFF8, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_off8", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_Z80_BYTE0,
+ R_BYTE0, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_byte0", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_Z80_BYTE1,
+ R_BYTE1, /* type */
+ 8, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_byte1", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_Z80_BYTE2,
+ R_BYTE2, /* type */
+ 16, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_byte2", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_Z80_BYTE3,
+ R_BYTE3, /* type */
+ 24, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_byte3", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_Z80_WORD0,
+ R_WORD0, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_word0", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ BFD_HOWTO (BFD_RELOC_Z80_WORD1,
+ R_WORD1, /* type */
+ 16, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "r_word1", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+};
+
+#define NUM_HOWTOS ARRAY_SIZE (howto_table)
#define BADMAG(x) Z80BADMAG(x)
#define Z80 1 /* Customize coffcode.h. */
@@ -74,34 +239,19 @@ HOWTO (R_OFF8, 0, 0, 8, FALSE, 0,
dst->r_stuff[1] = 'C';
/* Code to turn a r_type into a howto ptr, uses the above howto table. */
-
static void
rtype2howto (arelent *internal, struct internal_reloc *dst)
{
- switch (dst->r_type)
+ unsigned i;
+ for (i = 0; i < NUM_HOWTOS; i++)
{
- default:
- internal->howto = NULL;
- break;
- case R_IMM8:
- internal->howto = &r_imm8;
- break;
- case R_IMM16:
- internal->howto = &r_imm16;
- break;
- case R_IMM24:
- internal->howto = &r_imm24;
- break;
- case R_IMM32:
- internal->howto = &r_imm32;
- break;
- case R_JR:
- internal->howto = &r_jr;
- break;
- case R_OFF8:
- internal->howto = &r_off8;
- break;
+ if (howto_table[i].howto.type == dst->r_type)
+ {
+ internal->howto = &howto_table[i].howto;
+ return;
+ }
}
+ internal->howto = NULL;
}
#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
@@ -110,35 +260,23 @@ static reloc_howto_type *
coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
bfd_reloc_code_real_type code)
{
- switch (code)
- {
- case BFD_RELOC_8: return & r_imm8;
- case BFD_RELOC_16: return & r_imm16;
- case BFD_RELOC_24: return & r_imm24;
- case BFD_RELOC_32: return & r_imm32;
- case BFD_RELOC_8_PCREL: return & r_jr;
- case BFD_RELOC_Z80_DISP8: return & r_off8;
- default: BFD_FAIL ();
- return NULL;
- }
+ unsigned i;
+ for (i = 0; i < NUM_HOWTOS; i++)
+ if (howto_table[i].r_type == code)
+ return &howto_table[i].howto;
+
+ BFD_FAIL ();
+ return NULL;
}
static reloc_howto_type *
coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
const char *r_name)
{
- if (strcasecmp (r_imm8.name, r_name) == 0)
- return &r_imm8;
- if (strcasecmp (r_imm16.name, r_name) == 0)
- return &r_imm16;
- if (strcasecmp (r_imm24.name, r_name) == 0)
- return &r_imm24;
- if (strcasecmp (r_imm32.name, r_name) == 0)
- return &r_imm32;
- if (strcasecmp (r_jr.name, r_name) == 0)
- return &r_jr;
- if (strcasecmp (r_off8.name, r_name) == 0)
- return &r_off8;
+ unsigned i;
+ for (i = 0; i < NUM_HOWTOS; i++)
+ if (strcasecmp(howto_table[i].howto.name, r_name) == 0)
+ return &howto_table[i].howto;
return NULL;
}
@@ -180,14 +318,15 @@ extra_case (bfd *in_abfd,
unsigned int *dst_ptr)
{
asection * input_section = link_order->u.indirect.section;
- int val;
+ int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
switch (reloc->howto->type)
{
case R_OFF8:
- val = bfd_coff_reloc16_get_value (reloc, link_info,
- input_section);
- if (val>127 || val<-128) /* Test for overflow. */
+ if (reloc->howto->partial_inplace)
+ val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
+ & reloc->howto->src_mask);
+ if (val>127 || val<-128) /* Test for overflow. */
(*link_info->callbacks->reloc_overflow)
(link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
@@ -198,26 +337,55 @@ extra_case (bfd *in_abfd,
(*src_ptr) += 1;
break;
+ case R_BYTE3:
+ bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
+ (*dst_ptr) += 1;
+ (*src_ptr) += 1;
+ break;
+
+ case R_BYTE2:
+ bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
+ (*dst_ptr) += 1;
+ (*src_ptr) += 1;
+ break;
+
+ case R_BYTE1:
+ bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
+ (*dst_ptr) += 1;
+ (*src_ptr) += 1;
+ break;
+
case R_IMM8:
- val = bfd_get_8 ( in_abfd, data+*src_ptr)
- + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ if (reloc->howto->partial_inplace)
+ val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+ //fallthrough
+ case R_BYTE0:
bfd_put_8 (in_abfd, val, data + *dst_ptr);
(*dst_ptr) += 1;
(*src_ptr) += 1;
break;
+ case R_WORD1:
+ bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
+ (*dst_ptr) += 2;
+ (*src_ptr) += 2;
+ break;
+
case R_IMM16:
- val = bfd_get_16 ( in_abfd, data+*src_ptr)
- + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ if (reloc->howto->partial_inplace)
+ val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+ //fallthrough
+ case R_WORD0:
bfd_put_16 (in_abfd, val, data + *dst_ptr);
(*dst_ptr) += 2;
(*src_ptr) += 2;
break;
case R_IMM24:
- val = bfd_get_16 ( in_abfd, data+*src_ptr)
- + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16)
- + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ if (reloc->howto->partial_inplace)
+ val += (bfd_get_16 ( in_abfd, data+*src_ptr)
+ + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16))
+ & reloc->howto->src_mask;
bfd_put_16 (in_abfd, val, data + *dst_ptr);
bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
(*dst_ptr) += 3;
@@ -225,8 +393,8 @@ extra_case (bfd *in_abfd,
break;
case R_IMM32:
- val = bfd_get_32 ( in_abfd, data+*src_ptr)
- + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ if (reloc->howto->partial_inplace)
+ val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
bfd_put_32 (in_abfd, val, data + *dst_ptr);
(*dst_ptr) += 4;
(*src_ptr) += 4;
@@ -234,15 +402,13 @@ extra_case (bfd *in_abfd,
case R_JR:
{
- bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
- input_section);
+ if (reloc->howto->partial_inplace)
+ val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
+ & reloc->howto->src_mask);
bfd_vma dot = (*dst_ptr
+ input_section->output_offset
+ input_section->output_section->vma);
- int gap = dst - dot - 1; /* -1, Since the offset is relative
- to the value of PC after reading
- the offset. */
-
+ int gap = val - dot;
if (gap >= 128 || gap < -128)
(*link_info->callbacks->reloc_overflow)
(link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
@@ -260,6 +426,16 @@ extra_case (bfd *in_abfd,
}
}
+static int
+z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
+ const char * name)
+{
+ return (name[0] == '.' && name[1] == 'L') ||
+ _bfd_coff_is_local_label_name (abfd, name);
+}
+
+#define coff_bfd_is_local_label_name z80_is_local_label_name
+
#define coff_reloc16_extra_cases extra_case
#define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
#define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup