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
5 University of Utah (pa-gdb-bugs@cs.utah.edu).
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26 #define BYTES_IN_WORD 4
27 #define PA_PAGESIZE 0x1000
37 /* The PA instruction set variants. */
38 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
40 /* HP PA-RISC relocation types */
42 enum hppa_reloc_field_selector_type
62 /* /usr/include/reloc.h defines these to constants. We want to use
63 them in enums, so #undef them before we start using them. We might
64 be able to fix this another way by simply managing not to include
65 /usr/include/reloc.h, but currently GDB picks up these defines
90 /* for compatibility */
91 enum hppa_reloc_field_selector_type_alt
94 e_lssel = R_HPPA_LSSEL,
95 e_rssel = R_HPPA_RSSEL,
98 e_ldsel = R_HPPA_LDSEL,
99 e_rdsel = R_HPPA_RDSEL,
100 e_lrsel = R_HPPA_LRSEL,
101 e_rrsel = R_HPPA_RRSEL,
102 e_nsel = R_HPPA_NSEL,
103 e_psel = R_HPPA_PSEL,
104 e_lpsel = R_HPPA_LPSEL,
105 e_rpsel = R_HPPA_RPSEL,
106 e_tsel = R_HPPA_TSEL,
107 e_ltsel = R_HPPA_LTSEL,
108 e_rtsel = R_HPPA_RTSEL
111 enum hppa_reloc_expr_type
121 /* for compatibility */
122 enum hppa_reloc_expr_type_alt
124 e_one = R_HPPA_E_ONE,
125 e_two = R_HPPA_E_TWO,
126 e_pcrel = R_HPPA_E_PCREL,
127 e_con = R_HPPA_E_CON,
128 e_plabel = R_HPPA_E_PLABEL,
133 /* Relocations for function calls must be accompanied by parameter
134 relocation bits. These bits describe exactly where the caller has
135 placed the function's arguments and where it expects to find a return
138 Both ELF and SOM encode this information within the addend field
139 of the call relocation. (Note this could break very badly if one
140 was to make a call like bl foo + 0x12345678).
142 The high order 10 bits contain parameter relocation information,
143 the low order 22 bits contain the constant offset. */
145 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
146 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
147 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
149 /* Some functions to manipulate PA instructions. */
150 static INLINE unsigned int
154 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
158 dis_assemble_3 (x, r)
162 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
165 static INLINE unsigned int
169 return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
173 dis_assemble_12 (as12, x, y)
177 *y = (as12 & 0x800) >> 11;
178 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
181 static INLINE unsigned long
182 assemble_17 (x, y, z)
183 unsigned int x, y, z;
187 temp = ((z & 1) << 16) |
191 return temp & 0x1ffff;
195 dis_assemble_17 (as17, x, y, z)
197 unsigned int *x, *y, *z;
200 *z = (as17 & 0x10000) >> 16;
201 *x = (as17 & 0x0f800) >> 11;
202 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
205 static INLINE unsigned long
211 temp = ((x & 1) << 20) |
213 ((x & 0xc000) >> 7) |
214 ((x & 0x1f0000) >> 14) |
215 ((x & 0x003000) >> 12);
216 return temp & 0x1fffff;
220 dis_assemble_21 (as21, x)
221 unsigned int as21, *x;
226 temp = (as21 & 0x100000) >> 20;
227 temp |= (as21 & 0x0ffe00) >> 8;
228 temp |= (as21 & 0x000180) << 7;
229 temp |= (as21 & 0x00007c) << 14;
230 temp |= (as21 & 0x000003) << 12;
234 static INLINE unsigned long
238 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
241 static INLINE unsigned int
245 unsigned int len_ones;
252 len_ones = (len_ones << 1) | 1;
260 sign_unext (x, len, result)
262 unsigned int *result;
264 unsigned int len_ones;
266 len_ones = ones (len);
268 *result = x & len_ones;
271 static INLINE unsigned long
272 low_sign_extend (x, len)
275 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
279 low_sign_unext (x, len, result)
281 unsigned int *result;
286 unsigned int one_bit_at_len;
287 unsigned int len_ones;
289 len_ones = ones (len);
290 one_bit_at_len = 1 << (len - 1);
292 sign_unext (x, len, &temp);
293 sign = temp & one_bit_at_len;
296 rest = temp & (len_ones ^ one_bit_at_len);
299 *result = rest | sign;
302 /* Handle field selectors for PA instructions. */
304 static INLINE unsigned long
305 hppa_field_adjust (value, constant_value, r_field)
307 unsigned long constant_value;
308 unsigned short r_field;
312 case e_fsel: /* F : no change */
313 value += constant_value;
316 case e_lssel: /* LS : if (bit 21) then add 0x800
317 arithmetic shift right 11 bits */
318 value += constant_value;
319 if (value & 0x00000400)
321 value = (value & 0xfffff800) >> 11;
324 case e_rssel: /* RS : Sign extend from bit 21 */
325 value += constant_value;
326 if (value & 0x00000400)
332 case e_lsel: /* L : Arithmetic shift right 11 bits */
333 value += constant_value;
334 value = (value & 0xfffff800) >> 11;
337 case e_rsel: /* R : Set bits 0-20 to zero */
338 value += constant_value;
339 value = value & 0x7ff;
342 case e_ldsel: /* LD : Add 0x800, arithmetic shift
344 value += constant_value;
346 value = (value & 0xfffff800) >> 11;
349 case e_rdsel: /* RD : Set bits 0-20 to one */
350 value += constant_value;
354 case e_nsel: /* Just a guess at the moment. */
355 case e_lrsel: /* LR : L with "rounded" constant */
356 value = value + ((constant_value + 0x1000) & 0xffffe000);
357 value = (value & 0xfffff800) >> 11;
360 case e_rrsel: /* RR : R with "rounded" constant */
361 value = value + ((constant_value + 0x1000) & 0xffffe000);
362 value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
372 /* PA-RISC OPCODES */
373 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
375 /* FIXME: this list is incomplete. It should also be an enumerated
376 type rather than #defines. */
415 /* Given a machine instruction, return its format.
417 FIXME: opcodes which do not map to a known format
418 should return an error of some sort. */
421 bfd_hppa_insn2fmt (insn)
425 unsigned char op = get_opcode (insn);
476 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
479 static INLINE unsigned long
480 hppa_rebuild_insn (abfd, insn, value, r_format)
484 unsigned long r_format;
486 unsigned long const_part;
487 unsigned long rebuilt_part;
495 const_part = insn & 0xffffe002;
496 dis_assemble_12 (value, &w1, &w);
497 rebuilt_part = (w1 << 2) | w;
498 return const_part | rebuilt_part;
505 const_part = insn & 0xffffe002;
506 dis_assemble_12 (value, &w1, &w);
507 rebuilt_part = (w1 << 2) | w;
508 return const_part | rebuilt_part;
512 const_part = insn & 0xffffc000;
513 low_sign_unext (value, 14, &rebuilt_part);
514 return const_part | rebuilt_part;
520 const_part = insn & 0xffe0e002;
521 dis_assemble_17 (value, &w1, &w2, &w);
522 rebuilt_part = (w2 << 2) | (w1 << 16) | w;
523 return const_part | rebuilt_part;
527 const_part = insn & 0xffe00000;
528 dis_assemble_21 (value, &rebuilt_part);
529 return const_part | rebuilt_part;