X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Flibhppa.h;h=40149999e3a55be4e212b35046bf4d1a9387c6f8;hb=9f554efd623851a218c9469065952d6014c7624a;hp=76b096e9ce49a51247c534ecc5cd90f101f50d89;hpb=d325e28cfd6281aa03629ebe2e33dd5cd77738ff;p=binutils-gdb.git diff --git a/bfd/libhppa.h b/bfd/libhppa.h index 76b096e9ce4..40149999e3a 100644 --- a/bfd/libhppa.h +++ b/bfd/libhppa.h @@ -1,184 +1,534 @@ /* HP PA-RISC SOM object file format: definitions internal to BFD. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Contributed by the Center for Software Science at the University of Utah (pa-gdb-bugs@cs.utah.edu). -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _LIBHPPA_H -#define _LIBHPPA_H +#ifndef _HPPA_H +#define _HPPA_H -#include "sysdep.h" - -#ifdef HOST_HPPAHPUX +#define BYTES_IN_WORD 4 +#define PA_PAGESIZE 0x1000 -#include -#include +#ifndef INLINE +#ifdef __GNUC__ +#define INLINE inline +#else +#define INLINE +#endif /* GNU C? */ +#endif /* INLINE */ -#endif /* HOST_HPPAHPUX */ +/* HP PA-RISC relocation types */ -#ifdef HOST_HPPABSD +enum hppa_reloc_field_selector_type + { + R_HPPA_FSEL = 0x0, + R_HPPA_LSSEL = 0x1, + R_HPPA_RSSEL = 0x2, + R_HPPA_LSEL = 0x3, + R_HPPA_RSEL = 0x4, + R_HPPA_LDSEL = 0x5, + R_HPPA_RDSEL = 0x6, + R_HPPA_LRSEL = 0x7, + R_HPPA_RRSEL = 0x8, + R_HPPA_PSEL = 0x9, + R_HPPA_LPSEL = 0xa, + R_HPPA_RPSEL = 0xb, + R_HPPA_TSEL = 0xc, + R_HPPA_LTSEL = 0xd, + R_HPPA_RTSEL = 0xe + }; + +/* /usr/include/reloc.h defines these to constants. We want to use + them in enums, so #undef them before we start using them. We might + be able to fix this another way by simply managing not to include + /usr/include/reloc.h, but currently GDB picks up these defines + somewhere. */ +#undef e_fsel +#undef e_lssel +#undef e_rssel +#undef e_lsel +#undef e_rsel +#undef e_ldsel +#undef e_rdsel +#undef e_lrsel +#undef e_rrsel +#undef e_psel +#undef e_lpsel +#undef e_rpsel +#undef e_tsel +#undef e_ltsel +#undef e_rtsel +#undef e_one +#undef e_two +#undef e_pcrel +#undef e_con +#undef e_plabel +#undef e_abs -/* Defining MAXCOMLEN avoids bringing in several (7 or 8) otherwise - useless include files which tend to clutter up the namespace. +/* for compatibility */ +enum hppa_reloc_field_selector_type_alt + { + e_fsel = R_HPPA_FSEL, + e_lssel = R_HPPA_LSSEL, + e_rssel = R_HPPA_RSSEL, + e_lsel = R_HPPA_LSEL, + e_rsel = R_HPPA_RSEL, + e_ldsel = R_HPPA_LDSEL, + e_rdsel = R_HPPA_RDSEL, + e_lrsel = R_HPPA_LRSEL, + e_rrsel = R_HPPA_RRSEL, + e_psel = R_HPPA_PSEL, + e_lpsel = R_HPPA_LPSEL, + e_rpsel = R_HPPA_RPSEL, + e_tsel = R_HPPA_TSEL, + e_ltsel = R_HPPA_LTSEL, + e_rtsel = R_HPPA_RTSEL + }; - BSD uses a completely different scheme for object file identification. - so for now, define _PA_RISC_ID to accept any random value for a model - number. */ -#include -#define MAXCOMLEN 16 -#define _PA_RISC_ID(__m_num) 1 +enum hppa_reloc_expr_type + { + R_HPPA_E_ONE = 0, + R_HPPA_E_TWO = 1, + R_HPPA_E_PCREL = 2, + R_HPPA_E_CON = 3, + R_HPPA_E_PLABEL = 7, + R_HPPA_E_ABS = 18 + }; -#endif /* HOST_HPPABSD */ +/* for compatibility */ +enum hppa_reloc_expr_type_alt + { + e_one = R_HPPA_E_ONE, + e_two = R_HPPA_E_TWO, + e_pcrel = R_HPPA_E_PCREL, + e_con = R_HPPA_E_CON, + e_plabel = R_HPPA_E_PLABEL, + e_abs = R_HPPA_E_ABS + }; + + +/* Relocations for function calls must be accompanied by parameter + relocation bits. These bits describe exactly where the caller has + placed the function's arguments and where it expects to find a return + value. + + Both ELF and SOM encode this information within the addend field + of the call relocation. (Note this could break very badly if one + was to make a call like bl foo + 0x12345678). + + The high order 10 bits contain parameter relocation information, + the low order 22 bits contain the constant offset. */ + +#define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF) +#define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10) +#define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF)) + +/* Some functions to manipulate PA instructions. */ +static INLINE unsigned int +assemble_3 (x) + unsigned int x; +{ + return (((x & 1) << 2) | ((x & 6) >> 1)) & 7; +} -#define BYTES_IN_WORD 4 +static INLINE void +dis_assemble_3 (x, r) + unsigned int x; + unsigned int *r; +{ + *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7; +} -struct header; -struct som_exec_auxhdr; -struct subspace_dictionary; +static INLINE unsigned int +assemble_12 (x, y) + unsigned int x, y; +{ + return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff; +} -#define FILE_HDR_SIZE sizeof(struct header) -#define AUX_HDR_SIZE sizeof(struct som_exec_auxhdr) +static INLINE void +dis_assemble_12 (as12, x, y) + unsigned int as12; + unsigned int *x, *y; +{ + *y = (as12 & 0x800) >> 11; + *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10); +} -typedef struct hppa_symbol +static INLINE unsigned long +assemble_17 (x, y, z) + unsigned int x, y, z; +{ + unsigned long temp; + + temp = ((z & 1) << 16) | + ((x & 0x1f) << 11) | + ((y & 1) << 10) | + ((y & 0x7fe) >> 1); + return temp & 0x1ffff; +} + +static INLINE void +dis_assemble_17 (as17, x, y, z) + unsigned int as17; + unsigned int *x, *y, *z; { - asymbol symbol; - short desc; - char other; - unsigned char type; -} hppa_symbol_type; -struct hppadata + *z = (as17 & 0x10000) >> 16; + *x = (as17 & 0x0f800) >> 11; + *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff; +} + +static INLINE unsigned long +assemble_21 (x) + unsigned int x; +{ + unsigned long temp; + + temp = ((x & 1) << 20) | + ((x & 0xffe) << 8) | + ((x & 0xc000) >> 7) | + ((x & 0x1f0000) >> 14) | + ((x & 0x003000) >> 12); + return temp & 0x1fffff; +} + +static INLINE void +dis_assemble_21 (as21, x) + unsigned int as21, *x; { - struct header *file_hdr; - struct som_exec_auxhdr *aux_hdr; - hppa_symbol_type *symbols; + unsigned long temp; - /* We remember these offsets so that after check_file_format, we have - no dependencies on the particular format of the exec_hdr. */ - file_ptr sym_filepos; - file_ptr str_filepos; + temp = (as21 & 0x100000) >> 20; + temp |= (as21 & 0x0ffe00) >> 8; + temp |= (as21 & 0x000180) << 7; + temp |= (as21 & 0x00007c) << 14; + temp |= (as21 & 0x000003) << 12; + *x = temp; +} - unsigned stringtab_size; +static INLINE unsigned long +sign_ext (x, len) + unsigned int x, len; +{ + return (x << (32 - len)) >> (32 - len); +} - /* Size of a symbol table entry in external form */ - unsigned hp_symbol_entry_size; -}; +static INLINE unsigned int +ones (n) + int n; +{ + unsigned int len_ones; + int i; + + i = 0; + len_ones = 0; + while (i < n) + { + len_ones = (len_ones << 1) | 1; + i++; + } + + return len_ones; +} + +static INLINE void +sign_unext (x, len, result) + unsigned int x, len; + unsigned int *result; +{ + unsigned int len_ones; -struct hppa_data_struct { - struct hppadata a; -}; + len_ones = ones (len); -#define padata(bfd) ((bfd)->tdata.hppa_data->a) -#define obj_file_hdr(bfd) (padata(bfd).file_hdr) -#define obj_aux_hdr(bfd) (padata(bfd).aux_hdr) -#define obj_pa_symbols(bfd) (padata(bfd).symbols) -#define obj_sym_filepos(bfd) (padata(bfd).sym_filepos) -#define obj_str_filepos(bfd) (padata(bfd).str_filepos) -#define obj_stringtab_size(bfd) (padata(bfd).stringtab_size) + *result = x & len_ones; +} -/* We take the address of the first element of an asymbol to ensure that the - macro is only ever applied to an asymbol */ -#define hppa_symbol(asymbol) ((hppa_symbol_type *)(&(asymbol)->the_bfd)) +static INLINE unsigned long +low_sign_ext (x, len) + unsigned int x, len; +{ + unsigned int temp1, temp2; + unsigned int len_ones; + len_ones = ones (len); -/* These are stored in the bfd's tdata */ + temp1 = (x & 1) << (len - 1); + temp2 = ((x & 0xfffffffe) & len_ones) >> 1; + return sign_ext ((temp1 | temp2), len); +} -struct hppa_core_struct +static INLINE void +low_sign_unext (x, len, result) + unsigned int x, len; + unsigned int *result; { - int sig; - char cmd[MAXCOMLEN + 1]; - asection *data_section; - asection *stack_section; - asection *reg_section; -}; + unsigned int temp; + unsigned int sign; + unsigned int rest; + unsigned int one_bit_at_len; + unsigned int len_ones; -#define core_hdr(bfd) ((bfd)->tdata.hppa_core_data) -#define core_signal(bfd) (core_hdr(bfd)->sig) -#define core_command(bfd) (core_hdr(bfd)->cmd) -#define core_datasec(bfd) (core_hdr(bfd)->data_section) -#define core_stacksec(bfd) (core_hdr(bfd)->stack_section) -#define core_regsec(bfd) (core_hdr(bfd)->reg_section) + len_ones = ones (len); + one_bit_at_len = 1 << (len - 1); -/* HP PA-RISC relocation types */ + sign_unext (x, len, &temp); + sign = temp & one_bit_at_len; + sign >>= (len - 1); -enum hppa_reloc_field_selector_type -{ - R_HPPA_FSEL = 0x0, - R_HPPA_LSSEL = 0x1, - R_HPPA_RSSEL = 0x2, - R_HPPA_LSEL = 0x3, - R_HPPA_RSEL = 0x4, - R_HPPA_LDSEL = 0x5, - R_HPPA_RDSEL = 0x6, - R_HPPA_LRSEL = 0x7, - R_HPPA_RRSEL = 0x8, - R_HPPA_PSEL = 0x9, /* P' : procedure address for shlib's */ - R_HPPA_LPSEL = 0xa, /* LP' : L' for procedure addresses */ - R_HPPA_RPSEL = 0xb, /* RP' : R' for procedure addresses */ - - R_HPPA_TSEL = 0xc, /* T' : DLT-relative offset for shlib's */ - R_HPPA_LTSEL = 0xd, /* LT' : L' for DLT-relative offsets */ - R_HPPA_RTSEL = 0xe /* RT' : R' for DLT-relative offsets */ - -}; + rest = temp & (len_ones ^ one_bit_at_len); + rest <<= 1; -/* for compatibility */ -enum hppa_reloc_field_selector_type_alt -{ - e_fsel = R_HPPA_FSEL, - e_lssel = R_HPPA_LSSEL, - e_rssel = R_HPPA_RSSEL, - e_lsel = R_HPPA_LSEL, - e_rsel = R_HPPA_RSEL, - e_ldsel = R_HPPA_LDSEL, - e_rdsel = R_HPPA_RDSEL, - e_lrsel = R_HPPA_LRSEL, - e_rrsel = R_HPPA_RRSEL, - e_psel = R_HPPA_PSEL, /* P' : procedure address for shlib's */ - e_lpsel = R_HPPA_LPSEL, /* LP' : L' for procedure addresses */ - e_rpsel = R_HPPA_RPSEL, /* RP' : R' for procedure addresses */ - - e_tsel = R_HPPA_TSEL, /* T' : DLT-relative offset for shlib's */ - e_ltsel = R_HPPA_LTSEL, /* LT' : L' for DLT-relative offsets */ - e_rtsel = R_HPPA_RTSEL /* RT' : R' for DLT-relative offsets */ -}; + *result = rest | sign; +} -enum hppa_reloc_expr_type -{ - R_HPPA_E_ONE = 0, - R_HPPA_E_TWO = 1, - R_HPPA_E_PCREL = 2, - R_HPPA_E_CON = 3, - R_HPPA_E_PLABEL = 7, - R_HPPA_E_ABS = 18 -}; +/* Handle field selectors for PA instructions. */ -/* for compatibility */ -enum hppa_reloc_expr_type_alt +static INLINE unsigned long +hppa_field_adjust (value, constant_value, r_field) + unsigned long value; + unsigned long constant_value; + unsigned short r_field; { - e_one = R_HPPA_E_ONE, - e_two = R_HPPA_E_TWO, - e_pcrel = R_HPPA_E_PCREL, - e_con = R_HPPA_E_CON, - e_plabel = R_HPPA_E_PLABEL, - e_abs = R_HPPA_E_ABS -}; - -#endif /* _LIBHPPA_H */ + switch (r_field) + { + case e_fsel: /* F : no change */ + break; + + case e_lssel: /* LS : if (bit 21) then add 0x800 + arithmetic shift right 11 bits */ + if (value & 0x00000400) + value += 0x800; + value = (value & 0xfffff800) >> 11; + break; + + case e_rssel: /* RS : Sign extend from bit 21 */ + if (value & 0x00000400) + value |= 0xfffff800; + else + value &= 0x7ff; + break; + + case e_lsel: /* L : Arithmetic shift right 11 bits */ + value = (value & 0xfffff800) >> 11; + break; + + case e_rsel: /* R : Set bits 0-20 to zero */ + value = value & 0x7ff; + break; + + case e_ldsel: /* LD : Add 0x800, arithmetic shift + right 11 bits */ + value += 0x800; + value = (value & 0xfffff800) >> 11; + break; + + case e_rdsel: /* RD : Set bits 0-20 to one */ + value |= 0xfffff800; + break; + + case e_lrsel: /* LR : L with "rounded" constant */ + value = value + ((constant_value + 0x1000) & 0xffffe000); + value = (value & 0xfffff800) >> 11; + break; + + case e_rrsel: /* RR : R with "rounded" constant */ + value = value + ((constant_value + 0x1000) & 0xffffe000); + value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000); + break; + + default: + abort (); + } + return value; + +} + +/* PA-RISC OPCODES */ +#define get_opcode(insn) ((insn) & 0xfc000000) >> 26 + +/* FIXME: this list is incomplete. It should also be an enumerated + type rather than #defines. */ + +#define LDO 0x0d +#define LDB 0x10 +#define LDH 0x11 +#define LDW 0x12 +#define LDWM 0x13 +#define STB 0x18 +#define STH 0x19 +#define STW 0x1a +#define STWM 0x1b +#define COMICLR 0x24 +#define SUBI 0x25 +#define SUBIO 0x25 +#define ADDIT 0x2c +#define ADDITO 0x2c +#define ADDI 0x2d +#define ADDIO 0x2d +#define LDIL 0x08 +#define ADDIL 0x0a + +#define MOVB 0x32 +#define MOVIB 0x33 +#define COMBT 0x20 +#define COMBF 0x22 +#define COMIBT 0x21 +#define COMIBF 0x23 +#define ADDBT 0x28 +#define ADDBF 0x2a +#define ADDIBT 0x29 +#define ADDIBF 0x2b +#define BVB 0x30 +#define BB 0x31 + +#define BL 0x3a +#define BLE 0x39 +#define BE 0x38 + + +/* Given a machine instruction, return its format. + + FIXME: opcodes which do not map to a known format + should return an error of some sort. */ + +static char +bfd_hppa_insn2fmt (insn) + unsigned long insn; +{ + char fmt = -1; + unsigned char op = get_opcode (insn); + + switch (op) + { + case ADDI: + case ADDIT: + case SUBI: + fmt = 11; + break; + case MOVB: + case MOVIB: + case COMBT: + case COMBF: + case COMIBT: + case COMIBF: + case ADDBT: + case ADDBF: + case ADDIBT: + case ADDIBF: + case BVB: + case BB: + fmt = 12; + break; + case LDO: + case LDB: + case LDH: + case LDW: + case LDWM: + case STB: + case STH: + case STW: + case STWM: + fmt = 14; + break; + case BL: + case BE: + case BLE: + fmt = 17; + break; + case LDIL: + case ADDIL: + fmt = 21; + break; + default: + fmt = 32; + break; + } + return fmt; +} + + +/* Insert VALUE into INSN using R_FORMAT to determine exactly what + bits to change. */ + +static unsigned long +hppa_rebuild_insn (abfd, insn, value, r_format) + bfd *abfd; + unsigned long insn; + unsigned long value; + unsigned long r_format; +{ + unsigned long const_part; + unsigned long rebuilt_part; + + switch (r_format) + { + case 11: + { + unsigned w1, w; + + const_part = insn & 0xffffe002; + dis_assemble_12 (value, &w1, &w); + rebuilt_part = (w1 << 2) | w; + return const_part | rebuilt_part; + } + + case 12: + { + unsigned w1, w; + + const_part = insn & 0xffffe002; + dis_assemble_12 (value, &w1, &w); + rebuilt_part = (w1 << 2) | w; + return const_part | rebuilt_part; + } + + case 14: + const_part = insn & 0xffffc000; + low_sign_unext (value, 14, &rebuilt_part); + return const_part | rebuilt_part; + + case 17: + { + unsigned w1, w2, w; + + const_part = insn & 0xffe0e002; + dis_assemble_17 (value, &w1, &w2, &w); + rebuilt_part = (w2 << 2) | (w1 << 16) | w; + return const_part | rebuilt_part; + } + + case 21: + const_part = insn & 0xffe00000; + dis_assemble_21 (value, &rebuilt_part); + return const_part | rebuilt_part; + + case 32: + const_part = 0; + return value; + + default: + abort (); + } + return insn; +} + +#endif /* _HPPA_H */