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
31 #define HINLINE extern inline
33 /* INLINE is defined in bfd.h. */
34 #define HINLINE static INLINE
38 /* The PA instruction set variants. */
39 enum pa_arch
{pa10
= 10, pa11
= 11, pa20
= 20};
41 /* HP PA-RISC relocation types */
43 enum hppa_reloc_field_selector_type
65 /* /usr/include/reloc.h defines these to constants. We want to use
66 them in enums, so #undef them before we start using them. We might
67 be able to fix this another way by simply managing not to include
68 /usr/include/reloc.h, but currently GDB picks up these defines
95 /* for compatibility */
96 enum hppa_reloc_field_selector_type_alt
99 e_lssel
= R_HPPA_LSSEL
,
100 e_rssel
= R_HPPA_RSSEL
,
101 e_lsel
= R_HPPA_LSEL
,
102 e_rsel
= R_HPPA_RSEL
,
103 e_ldsel
= R_HPPA_LDSEL
,
104 e_rdsel
= R_HPPA_RDSEL
,
105 e_lrsel
= R_HPPA_LRSEL
,
106 e_rrsel
= R_HPPA_RRSEL
,
107 e_nsel
= R_HPPA_NSEL
,
108 e_nlsel
= R_HPPA_NLSEL
,
109 e_nlrsel
= R_HPPA_NLRSEL
,
110 e_psel
= R_HPPA_PSEL
,
111 e_lpsel
= R_HPPA_LPSEL
,
112 e_rpsel
= R_HPPA_RPSEL
,
113 e_tsel
= R_HPPA_TSEL
,
114 e_ltsel
= R_HPPA_LTSEL
,
115 e_rtsel
= R_HPPA_RTSEL
118 enum hppa_reloc_expr_type
128 /* for compatibility */
129 enum hppa_reloc_expr_type_alt
131 e_one
= R_HPPA_E_ONE
,
132 e_two
= R_HPPA_E_TWO
,
133 e_pcrel
= R_HPPA_E_PCREL
,
134 e_con
= R_HPPA_E_CON
,
135 e_plabel
= R_HPPA_E_PLABEL
,
140 /* Relocations for function calls must be accompanied by parameter
141 relocation bits. These bits describe exactly where the caller has
142 placed the function's arguments and where it expects to find a return
145 Both ELF and SOM encode this information within the addend field
146 of the call relocation. (Note this could break very badly if one
147 was to make a call like bl foo + 0x12345678).
149 The high order 10 bits contain parameter relocation information,
150 the low order 22 bits contain the constant offset. */
152 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
153 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
154 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
156 /* Some functions to manipulate PA instructions. */
161 return (((x
& 1) << 2) | ((x
& 6) >> 1)) & 7;
165 dis_assemble_3 (x
, r
)
169 *r
= (((x
& 4) >> 2) | ((x
& 3) << 1)) & 7;
176 return (((y
& 1) << 11) | ((x
& 1) << 10) | ((x
& 0x7fe) >> 1)) & 0xfff;
180 dis_assemble_12 (as12
, x
, y
)
184 *y
= (as12
& 0x800) >> 11;
185 *x
= ((as12
& 0x3ff) << 1) | ((as12
& 0x400) >> 10);
188 HINLINE
unsigned long
189 assemble_17 (x
, y
, z
)
190 unsigned int x
, y
, z
;
194 temp
= ((z
& 1) << 16) |
198 return temp
& 0x1ffff;
202 dis_assemble_17 (as17
, x
, y
, z
)
204 unsigned int *x
, *y
, *z
;
207 *z
= (as17
& 0x10000) >> 16;
208 *x
= (as17
& 0x0f800) >> 11;
209 *y
= (((as17
& 0x00400) >> 10) | ((as17
& 0x3ff) << 1)) & 0x7ff;
212 HINLINE
unsigned long
218 temp
= ((x
& 1) << 20) |
220 ((x
& 0xc000) >> 7) |
221 ((x
& 0x1f0000) >> 14) |
222 ((x
& 0x003000) >> 12);
223 return temp
& 0x1fffff;
227 dis_assemble_21 (as21
, x
)
228 unsigned int as21
, *x
;
233 temp
= (as21
& 0x100000) >> 20;
234 temp
|= (as21
& 0x0ffe00) >> 8;
235 temp
|= (as21
& 0x000180) << 7;
236 temp
|= (as21
& 0x00007c) << 14;
237 temp
|= (as21
& 0x000003) << 12;
241 HINLINE
unsigned long
245 return (int)(x
>> (len
- 1) ? (-1 << len
) | x
: x
);
252 unsigned int len_ones
;
259 len_ones
= (len_ones
<< 1) | 1;
267 sign_unext (x
, len
, result
)
269 unsigned int *result
;
271 unsigned int len_ones
;
273 len_ones
= ones (len
);
275 *result
= x
& len_ones
;
278 HINLINE
unsigned long
279 low_sign_extend (x
, len
)
282 return (int)((x
& 0x1 ? (-1 << (len
- 1)) : 0) | x
>> 1);
286 low_sign_unext (x
, len
, result
)
288 unsigned int *result
;
293 unsigned int one_bit_at_len
;
294 unsigned int len_ones
;
296 len_ones
= ones (len
);
297 one_bit_at_len
= 1 << (len
- 1);
299 sign_unext (x
, len
, &temp
);
300 sign
= temp
& one_bit_at_len
;
303 rest
= temp
& (len_ones
^ one_bit_at_len
);
306 *result
= rest
| sign
;
309 /* Handle field selectors for PA instructions. */
311 HINLINE
unsigned long
312 hppa_field_adjust (value
, constant_value
, r_field
)
314 unsigned long constant_value
;
315 unsigned short r_field
;
319 case e_fsel
: /* F : no change */
320 case e_nsel
: /* N : no change */
321 value
+= constant_value
;
324 case e_lssel
: /* LS : if (bit 21) then add 0x800
325 arithmetic shift right 11 bits */
326 value
+= constant_value
;
327 if (value
& 0x00000400)
329 value
= (value
& 0xfffff800) >> 11;
332 case e_rssel
: /* RS : Sign extend from bit 21 */
333 value
+= constant_value
;
334 if (value
& 0x00000400)
340 case e_lsel
: /* L : Arithmetic shift right 11 bits */
341 case e_nlsel
: /* NL : Arithmetic shift right 11 bits */
342 value
+= constant_value
;
343 value
= (value
& 0xfffff800) >> 11;
346 case e_rsel
: /* R : Set bits 0-20 to zero */
347 value
+= constant_value
;
348 value
= value
& 0x7ff;
351 case e_ldsel
: /* LD : Add 0x800, arithmetic shift
353 value
+= constant_value
;
355 value
= (value
& 0xfffff800) >> 11;
358 case e_rdsel
: /* RD : Set bits 0-20 to one */
359 value
+= constant_value
;
363 case e_lrsel
: /* LR : L with "rounded" constant */
364 case e_nlrsel
: /* NLR : NL with "rounded" constant */
365 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
366 value
= (value
& 0xfffff800) >> 11;
369 case e_rrsel
: /* RR : R with "rounded" constant */
370 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
371 value
= (value
& 0x7ff) + constant_value
- ((constant_value
+ 0x1000) & 0xffffe000);
381 /* PA-RISC OPCODES */
382 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
384 /* FIXME: this list is incomplete. It should also be an enumerated
385 type rather than #defines. */
424 /* Given a machine instruction, return its format.
426 FIXME: opcodes which do not map to a known format
427 should return an error of some sort. */
430 bfd_hppa_insn2fmt (insn
)
434 unsigned char op
= get_opcode (insn
);
485 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
488 HINLINE
unsigned long
489 hppa_rebuild_insn (abfd
, insn
, value
, r_format
)
493 unsigned long r_format
;
495 unsigned long const_part
;
496 unsigned long rebuilt_part
;
504 const_part
= insn
& 0xffffe002;
505 dis_assemble_12 (value
, &w1
, &w
);
506 rebuilt_part
= (w1
<< 2) | w
;
507 return const_part
| rebuilt_part
;
514 const_part
= insn
& 0xffffe002;
515 dis_assemble_12 (value
, &w1
, &w
);
516 rebuilt_part
= (w1
<< 2) | w
;
517 return const_part
| rebuilt_part
;
521 const_part
= insn
& 0xffffc000;
522 low_sign_unext (value
, 14, &rebuilt_part
);
523 return const_part
| rebuilt_part
;
529 const_part
= insn
& 0xffe0e002;
530 dis_assemble_17 (value
, &w1
, &w2
, &w
);
531 rebuilt_part
= (w2
<< 2) | (w1
<< 16) | w
;
532 return const_part
| rebuilt_part
;
536 const_part
= insn
& 0xffe00000;
537 dis_assemble_21 (value
, &rebuilt_part
);
538 return const_part
| rebuilt_part
;