diff options
-rw-r--r-- | bfd/ChangeLog | 13 | ||||
-rw-r--r-- | bfd/libhppa.h | 43 | ||||
-rw-r--r-- | bfd/som.c | 45 |
3 files changed, 100 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 503f1590872..ef66d8d80f0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +Sun Sep 19 12:16:47 1999 Jeffrey A Law (law@cygnus.com) + + * som.c (NO_PCREL_MODES): Define if the system does not define + R_SHORT_PCREL_MODE. + (hppa_som_gen_reloc_type): Handle both short and long pcrel branches. + (som_write_fixups): Eliminate redundant pcrel mode relocs. Handle + R_LONG_PCREL_MODE and R_SHORT_PCREL_MODE + * libhppa.h (dis_assemble_22): New function. + (bfd_hppa_insn2fmt): Handle long branch. + + * libhppa.h (bfd_hppa_insn2fmt): Decode and handle formats found + in PA2.0. + 1999-09-17 Alan Modra <alan@spri.levels.unisa.edu.au> * coff-i386.c (coff_i386_reloc_type_lookup): Support BFD_RELOC_16, diff --git a/bfd/libhppa.h b/bfd/libhppa.h index 4ce82ea4e2e..15181088add 100644 --- a/bfd/libhppa.h +++ b/bfd/libhppa.h @@ -52,6 +52,10 @@ static INLINE unsigned long assemble_17 (unsigned int, unsigned int, static INLINE void dis_assemble_17 (unsigned int, unsigned int *, unsigned int *, unsigned int *) __attribute__ ((__unused__)); +static INLINE void dis_assemble_22 (unsigned int, unsigned int *, + unsigned int *, unsigned int *, + unsigned int *) + __attribute__ ((__unused__)); static INLINE unsigned long assemble_21 (unsigned int) __attribute ((__unused__)); static INLINE void dis_assemble_21 (unsigned int, unsigned int *) @@ -332,6 +336,18 @@ dis_assemble_17 (as17, x, y, z) *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff; } +static INLINE void +dis_assemble_22 (as22, a, b, c, d) + unsigned int as22; + unsigned int *a, *b, *c, *d; +{ + + *d = (as22 & 0x200000) >> 21; + *a = (as22 & 0x1f0000) >> 16; + *b = (as22 & 0x0f800) >> 11; + *c = (((as22 & 0x00400) >> 10) | ((as22 & 0x3ff) << 1)) & 0x7ff; +} + static INLINE unsigned long assemble_21 (x) unsigned int x; @@ -548,6 +564,15 @@ hppa_field_adjust (value, constant_value, r_field) #define BLE 0x39 #define BE 0x38 +#define CMPBDT 0x27 +#define CMPBDF 0x2f +#define CMPIBD 0x3b +#define LDD 0x14 +#define STD 0x1c +#define LDWL 0x17 +#define STWL 0x1f +#define FDLW 0x16 +#define FSTW 0x1e /* Given a machine instruction, return its format. @@ -580,6 +605,9 @@ bfd_hppa_insn2fmt (insn) case ADDIBF: case BVB: case BB: + case CMPBDT: + case CMPBDF: + case CMPIBD: fmt = 12; break; case LDO: @@ -593,9 +621,24 @@ bfd_hppa_insn2fmt (insn) case STWM: fmt = 14; break; + case LDWL: + case STWL: + case FDLW: + case FSTW: + /* This is a hack. Unfortunately, format 11 is already taken + and we're using integers rather than an enum, so it's hard + to describe the 10a format. */ + fmt = -11; + break; + case LDD: + case STD: + fmt = 10; + break; case BL: case BE: case BLE: + if ((insn & 0x00008000) == 0x00008000) + return 22; fmt = 17; break; case LDIL: diff --git a/bfd/som.c b/bfd/som.c index 16a5e4a7cf9..77de9583f93 100644 --- a/bfd/som.c +++ b/bfd/som.c @@ -751,6 +751,7 @@ static const int comp3_opcodes[] = /* And these first appeared in hpux10. */ #ifndef R_SHORT_PCREL_MODE +#define NO_PCREL_MODES #define R_SHORT_PCREL_MODE 0x3e #endif @@ -1684,9 +1685,28 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff, sym) case R_HPPA_NONE: case R_HPPA_ABS_CALL: - case R_HPPA_PCREL_CALL: /* Right now we can default all these. */ break; + + case R_HPPA_PCREL_CALL: + { +#ifndef NO_PCREL_MODES + /* If we have short and long pcrel modes, then generate the proper + mode selector, then the pcrel relocation. Redundant selectors + will be eliminted as the relocs are sized and emitted. */ + final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); + if (!final_types[0]) + return NULL; + if (format == 17) + *final_types[0] = R_SHORT_PCREL_MODE; + else + *final_types[0] = R_LONG_PCREL_MODE; + final_types[1] = final_type; + final_types[2] = NULL; + *final_type = base_type; +#endif + break; + } } return final_types; } @@ -2665,6 +2685,9 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep) subsection = subsection->next) { int reloc_offset, current_rounding_mode; +#ifndef NO_PCREL_MODES + int current_call_mode; +#endif /* Find a subspace of this space. */ if (!som_is_subspace (subsection) @@ -2699,6 +2722,9 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep) reloc_offset = 0; som_initialize_reloc_queue (reloc_queue); current_rounding_mode = R_N_MODE; +#ifndef NO_PCREL_MODES + current_call_mode = R_SHORT_PCREL_MODE; +#endif /* Translate each BFD relocation into one or more SOM relocations. */ @@ -2763,6 +2789,10 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep) case R_END_TRY: case R_N0SEL: case R_N1SEL: +#ifndef NO_PCREL_MODES + case R_SHORT_PCREL_MODE: + case R_LONG_PCREL_MODE: +#endif reloc_offset = bfd_reloc->address; break; @@ -2887,6 +2917,19 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep) } break; +#ifndef NO_PCREL_MODES + case R_LONG_PCREL_MODE: + case R_SHORT_PCREL_MODE: + if (bfd_reloc->howto->type != current_call_mode) + { + bfd_put_8 (abfd, bfd_reloc->howto->type, p); + subspace_reloc_size += 1; + p += 1; + current_call_mode = bfd_reloc->howto->type; + } + break; +#endif + case R_EXIT: case R_ALT_ENTRY: case R_FSEL: |