1 /* HP PA-RISC SOM object file format: definitions internal to BFD.
2 Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 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
64 /* /usr/include/reloc.h defines these to constants. We want to use
65 them in enums, so #undef them before we start using them. We might
66 be able to fix this another way by simply managing not to include
67 /usr/include/reloc.h, but currently GDB picks up these defines
94 /* for compatibility */
95 enum hppa_reloc_field_selector_type_alt
98 e_lssel
= R_HPPA_LSSEL
,
99 e_rssel
= R_HPPA_RSSEL
,
100 e_lsel
= R_HPPA_LSEL
,
101 e_rsel
= R_HPPA_RSEL
,
102 e_ldsel
= R_HPPA_LDSEL
,
103 e_rdsel
= R_HPPA_RDSEL
,
104 e_lrsel
= R_HPPA_LRSEL
,
105 e_rrsel
= R_HPPA_RRSEL
,
106 e_nsel
= R_HPPA_NSEL
,
107 e_nlsel
= R_HPPA_NLSEL
,
108 e_nlrsel
= R_HPPA_NLRSEL
,
109 e_psel
= R_HPPA_PSEL
,
110 e_lpsel
= R_HPPA_LPSEL
,
111 e_rpsel
= R_HPPA_RPSEL
,
112 e_tsel
= R_HPPA_TSEL
,
113 e_ltsel
= R_HPPA_LTSEL
,
114 e_rtsel
= R_HPPA_RTSEL
117 enum hppa_reloc_expr_type
127 /* for compatibility */
128 enum hppa_reloc_expr_type_alt
130 e_one
= R_HPPA_E_ONE
,
131 e_two
= R_HPPA_E_TWO
,
132 e_pcrel
= R_HPPA_E_PCREL
,
133 e_con
= R_HPPA_E_CON
,
134 e_plabel
= R_HPPA_E_PLABEL
,
139 /* Relocations for function calls must be accompanied by parameter
140 relocation bits. These bits describe exactly where the caller has
141 placed the function's arguments and where it expects to find a return
144 Both ELF and SOM encode this information within the addend field
145 of the call relocation. (Note this could break very badly if one
146 was to make a call like bl foo + 0x12345678).
148 The high order 10 bits contain parameter relocation information,
149 the low order 22 bits contain the constant offset. */
151 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
152 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
153 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
155 /* Some functions to manipulate PA instructions. */
156 static INLINE
unsigned int
160 return (((x
& 1) << 2) | ((x
& 6) >> 1)) & 7;
164 dis_assemble_3 (x
, r
)
168 *r
= (((x
& 4) >> 2) | ((x
& 3) << 1)) & 7;
171 static INLINE
unsigned int
175 return (((y
& 1) << 11) | ((x
& 1) << 10) | ((x
& 0x7fe) >> 1)) & 0xfff;
179 dis_assemble_12 (as12
, x
, y
)
183 *y
= (as12
& 0x800) >> 11;
184 *x
= ((as12
& 0x3ff) << 1) | ((as12
& 0x400) >> 10);
187 static INLINE
unsigned long
188 assemble_17 (x
, y
, z
)
189 unsigned int x
, y
, z
;
193 temp
= ((z
& 1) << 16) |
197 return temp
& 0x1ffff;
201 dis_assemble_17 (as17
, x
, y
, z
)
203 unsigned int *x
, *y
, *z
;
206 *z
= (as17
& 0x10000) >> 16;
207 *x
= (as17
& 0x0f800) >> 11;
208 *y
= (((as17
& 0x00400) >> 10) | ((as17
& 0x3ff) << 1)) & 0x7ff;
211 static INLINE
unsigned long
217 temp
= ((x
& 1) << 20) |
219 ((x
& 0xc000) >> 7) |
220 ((x
& 0x1f0000) >> 14) |
221 ((x
& 0x003000) >> 12);
222 return temp
& 0x1fffff;
226 dis_assemble_21 (as21
, x
)
227 unsigned int as21
, *x
;
232 temp
= (as21
& 0x100000) >> 20;
233 temp
|= (as21
& 0x0ffe00) >> 8;
234 temp
|= (as21
& 0x000180) << 7;
235 temp
|= (as21
& 0x00007c) << 14;
236 temp
|= (as21
& 0x000003) << 12;
240 static INLINE
unsigned long
244 return (int)(x
>> (len
- 1) ? (-1 << len
) | x
: x
);
247 static INLINE
unsigned int
251 unsigned int len_ones
;
258 len_ones
= (len_ones
<< 1) | 1;
266 sign_unext (x
, len
, result
)
268 unsigned int *result
;
270 unsigned int len_ones
;
272 len_ones
= ones (len
);
274 *result
= x
& len_ones
;
277 static INLINE
unsigned long
278 low_sign_extend (x
, len
)
281 return (int)((x
& 0x1 ? (-1 << (len
- 1)) : 0) | x
>> 1);
285 low_sign_unext (x
, len
, result
)
287 unsigned int *result
;
292 unsigned int one_bit_at_len
;
293 unsigned int len_ones
;
295 len_ones
= ones (len
);
296 one_bit_at_len
= 1 << (len
- 1);
298 sign_unext (x
, len
, &temp
);
299 sign
= temp
& one_bit_at_len
;
302 rest
= temp
& (len_ones
^ one_bit_at_len
);
305 *result
= rest
| sign
;
308 /* Handle field selectors for PA instructions. */
310 static INLINE
unsigned long
311 hppa_field_adjust (value
, constant_value
, r_field
)
313 unsigned long constant_value
;
314 unsigned short r_field
;
318 case e_fsel
: /* F : no change */
319 case e_nsel
: /* N : no change */
320 value
+= constant_value
;
323 case e_lssel
: /* LS : if (bit 21) then add 0x800
324 arithmetic shift right 11 bits */
325 value
+= constant_value
;
326 if (value
& 0x00000400)
328 value
= (value
& 0xfffff800) >> 11;
331 case e_rssel
: /* RS : Sign extend from bit 21 */
332 value
+= constant_value
;
333 if (value
& 0x00000400)
339 case e_lsel
: /* L : Arithmetic shift right 11 bits */
340 case e_nlsel
: /* NL : Arithmetic shift right 11 bits */
341 value
+= constant_value
;
342 value
= (value
& 0xfffff800) >> 11;
345 case e_rsel
: /* R : Set bits 0-20 to zero */
346 value
+= constant_value
;
347 value
= value
& 0x7ff;
350 case e_ldsel
: /* LD : Add 0x800, arithmetic shift
352 value
+= constant_value
;
354 value
= (value
& 0xfffff800) >> 11;
357 case e_rdsel
: /* RD : Set bits 0-20 to one */
358 value
+= constant_value
;
362 case e_lrsel
: /* LR : L with "rounded" constant */
363 case e_nlrsel
: /* NLR : NL with "rounded" constant */
364 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
365 value
= (value
& 0xfffff800) >> 11;
368 case e_rrsel
: /* RR : R with "rounded" constant */
369 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
370 value
= (value
& 0x7ff) + constant_value
- ((constant_value
+ 0x1000) & 0xffffe000);
380 /* PA-RISC OPCODES */
381 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
383 /* FIXME: this list is incomplete. It should also be an enumerated
384 type rather than #defines. */
423 /* Given a machine instruction, return its format.
425 FIXME: opcodes which do not map to a known format
426 should return an error of some sort. */
429 bfd_hppa_insn2fmt (insn
)
433 unsigned char op
= get_opcode (insn
);
484 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
487 static INLINE
unsigned long
488 hppa_rebuild_insn (abfd
, insn
, value
, r_format
)
492 unsigned long r_format
;
494 unsigned long const_part
;
495 unsigned long rebuilt_part
;
503 const_part
= insn
& 0xffffe002;
504 dis_assemble_12 (value
, &w1
, &w
);
505 rebuilt_part
= (w1
<< 2) | w
;
506 return const_part
| rebuilt_part
;
513 const_part
= insn
& 0xffffe002;
514 dis_assemble_12 (value
, &w1
, &w
);
515 rebuilt_part
= (w1
<< 2) | w
;
516 return const_part
| rebuilt_part
;
520 const_part
= insn
& 0xffffc000;
521 low_sign_unext (value
, 14, &rebuilt_part
);
522 return const_part
| rebuilt_part
;
528 const_part
= insn
& 0xffe0e002;
529 dis_assemble_17 (value
, &w1
, &w2
, &w
);
530 rebuilt_part
= (w2
<< 2) | (w1
<< 16) | w
;
531 return const_part
| rebuilt_part
;
535 const_part
= insn
& 0xffe00000;
536 dis_assemble_21 (value
, &rebuilt_part
);
537 return const_part
| rebuilt_part
;