1 /* HP PA-RISC SOM object file format: definitions internal to BFD.
2 Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
4 Contributed by the Center for Software Science at the
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #define BYTES_IN_WORD 4
27 #define PA_PAGESIZE 0x1000
37 /* HP PA-RISC relocation types */
39 enum hppa_reloc_field_selector_type
58 /* /usr/include/reloc.h defines these to constants. We want to use
59 them in enums, so #undef them before we start using them. We might
60 be able to fix this another way by simply managing not to include
61 /usr/include/reloc.h, but currently GDB picks up these defines
85 /* for compatibility */
86 enum hppa_reloc_field_selector_type_alt
89 e_lssel = R_HPPA_LSSEL,
90 e_rssel = R_HPPA_RSSEL,
93 e_ldsel = R_HPPA_LDSEL,
94 e_rdsel = R_HPPA_RDSEL,
95 e_lrsel = R_HPPA_LRSEL,
96 e_rrsel = R_HPPA_RRSEL,
98 e_lpsel = R_HPPA_LPSEL,
99 e_rpsel = R_HPPA_RPSEL,
100 e_tsel = R_HPPA_TSEL,
101 e_ltsel = R_HPPA_LTSEL,
102 e_rtsel = R_HPPA_RTSEL
105 enum hppa_reloc_expr_type
115 /* for compatibility */
116 enum hppa_reloc_expr_type_alt
118 e_one = R_HPPA_E_ONE,
119 e_two = R_HPPA_E_TWO,
120 e_pcrel = R_HPPA_E_PCREL,
121 e_con = R_HPPA_E_CON,
122 e_plabel = R_HPPA_E_PLABEL,
127 /* Relocations for function calls must be accompanied by parameter
128 relocation bits. These bits describe exactly where the caller has
129 placed the function's arguments and where it expects to find a return
132 Both ELF and SOM encode this information within the addend field
133 of the call relocation. (Note this could break very badly if one
134 was to make a call like bl foo + 0x12345678).
136 The high order 10 bits contain parameter relocation information,
137 the low order 22 bits contain the constant offset. */
139 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
140 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
141 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
143 /* Some functions to manipulate PA instructions. */
144 static INLINE unsigned int
148 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
152 dis_assemble_3 (x, r)
156 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
159 static INLINE unsigned int
163 return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
167 dis_assemble_12 (as12, x, y)
171 *y = (as12 & 0x800) >> 11;
172 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
175 static INLINE unsigned long
176 assemble_17 (x, y, z)
177 unsigned int x, y, z;
181 temp = ((z & 1) << 16) |
185 return temp & 0x1ffff;
189 dis_assemble_17 (as17, x, y, z)
191 unsigned int *x, *y, *z;
194 *z = (as17 & 0x10000) >> 16;
195 *x = (as17 & 0x0f800) >> 11;
196 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
199 static INLINE unsigned long
205 temp = ((x & 1) << 20) |
207 ((x & 0xc000) >> 7) |
208 ((x & 0x1f0000) >> 14) |
209 ((x & 0x003000) >> 12);
210 return temp & 0x1fffff;
214 dis_assemble_21 (as21, x)
215 unsigned int as21, *x;
220 temp = (as21 & 0x100000) >> 20;
221 temp |= (as21 & 0x0ffe00) >> 8;
222 temp |= (as21 & 0x000180) << 7;
223 temp |= (as21 & 0x00007c) << 14;
224 temp |= (as21 & 0x000003) << 12;
228 static INLINE unsigned long
232 return (x << (32 - len)) >> (32 - len);
235 static INLINE unsigned int
239 unsigned int len_ones;
246 len_ones = (len_ones << 1) | 1;
254 sign_unext (x, len, result)
256 unsigned int *result;
258 unsigned int len_ones;
260 len_ones = ones (len);
262 *result = x & len_ones;
265 static INLINE unsigned long
266 low_sign_ext (x, len)
269 unsigned int temp1, temp2;
270 unsigned int len_ones;
272 len_ones = ones (len);
274 temp1 = (x & 1) << (len - 1);
275 temp2 = ((x & 0xfffffffe) & len_ones) >> 1;
276 return sign_ext ((temp1 | temp2), len);
280 low_sign_unext (x, len, result)
282 unsigned int *result;
287 unsigned int one_bit_at_len;
288 unsigned int len_ones;
290 len_ones = ones (len);
291 one_bit_at_len = 1 << (len - 1);
293 sign_unext (x, len, &temp);
294 sign = temp & one_bit_at_len;
297 rest = temp & (len_ones ^ one_bit_at_len);
300 *result = rest | sign;
303 /* Handle field selectors for PA instructions. */
305 static INLINE unsigned long
306 hppa_field_adjust (value, constant_value, r_field)
308 unsigned long constant_value;
309 unsigned short r_field;
313 case e_fsel: /* F : no change */
316 case e_lssel: /* LS : if (bit 21) then add 0x800
317 arithmetic shift right 11 bits */
318 if (value & 0x00000400)
320 value = (value & 0xfffff800) >> 11;
323 case e_rssel: /* RS : Sign extend from bit 21 */
324 if (value & 0x00000400)
330 case e_lsel: /* L : Arithmetic shift right 11 bits */
331 value = (value & 0xfffff800) >> 11;
334 case e_rsel: /* R : Set bits 0-20 to zero */
335 value = value & 0x7ff;
338 case e_ldsel: /* LD : Add 0x800, arithmetic shift
341 value = (value & 0xfffff800) >> 11;
344 case e_rdsel: /* RD : Set bits 0-20 to one */
348 case e_lrsel: /* LR : L with "rounded" constant */
349 value = value + ((constant_value + 0x1000) & 0xffffe000);
350 value = (value & 0xfffff800) >> 11;
353 case e_rrsel: /* RR : R with "rounded" constant */
354 value = value + ((constant_value + 0x1000) & 0xffffe000);
355 value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
365 /* PA-RISC OPCODES */
366 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
368 /* FIXME: this list is incomplete. It should also be an enumerated
369 type rather than #defines. */
408 /* Given a machine instruction, return its format.
410 FIXME: opcodes which do not map to a known format
411 should return an error of some sort. */
414 bfd_hppa_insn2fmt (insn)
418 unsigned char op = get_opcode (insn);
469 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
473 hppa_rebuild_insn (abfd, insn, value, r_format)
477 unsigned long r_format;
479 unsigned long const_part;
480 unsigned long rebuilt_part;
488 const_part = insn & 0xffffe002;
489 dis_assemble_12 (value, &w1, &w);
490 rebuilt_part = (w1 << 2) | w;
491 return const_part | rebuilt_part;
498 const_part = insn & 0xffffe002;
499 dis_assemble_12 (value, &w1, &w);
500 rebuilt_part = (w1 << 2) | w;
501 return const_part | rebuilt_part;
505 const_part = insn & 0xffffc000;
506 low_sign_unext (value, 14, &rebuilt_part);
507 return const_part | rebuilt_part;
513 const_part = insn & 0xffe0e002;
514 dis_assemble_17 (value, &w1, &w2, &w);
515 rebuilt_part = (w2 << 2) | (w1 << 16) | w;
516 return const_part | rebuilt_part;
520 const_part = insn & 0xffe00000;
521 dis_assemble_21 (value, &rebuilt_part);
522 return const_part | rebuilt_part;