diff options
Diffstat (limited to 'bfd/libhppa.h')
-rw-r--r-- | bfd/libhppa.h | 187 |
1 files changed, 186 insertions, 1 deletions
diff --git a/bfd/libhppa.h b/bfd/libhppa.h index f357fe5d47..73a12920b0 100644 --- a/bfd/libhppa.h +++ b/bfd/libhppa.h @@ -123,6 +123,22 @@ enum hppa_reloc_expr_type_alt }; +/* 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) @@ -291,7 +307,6 @@ hppa_field_adjust (value, constant_value, r_field) unsigned long constant_value; unsigned short r_field; { - unsigned long init_value = value; value += constant_value; switch (r_field) { @@ -346,4 +361,174 @@ hppa_field_adjust (value, constant_value, r_field) 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 */ |