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 #if __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
38 /* Declare the functions with the unused attribute to avoid warnings. */
39 static INLINE
unsigned int assemble_3 (unsigned int)
40 __attribute__ ((__unused__
));
41 static INLINE
void dis_assemble_3 (unsigned int, unsigned int *)
42 __attribute__ ((__unused__
));
43 static INLINE
unsigned int assemble_12 (unsigned int, unsigned int)
44 __attribute__ ((__unused__
));
45 static INLINE
void dis_assemble_12 (unsigned int, unsigned int *,
47 __attribute__ ((__unused__
));
48 static INLINE
unsigned long assemble_17 (unsigned int, unsigned int,
50 __attribute__ ((__unused__
));
51 static INLINE
void dis_assemble_17 (unsigned int, unsigned int *,
52 unsigned int *, unsigned int *)
53 __attribute__ ((__unused__
));
54 static INLINE
unsigned long assemble_21 (unsigned int)
55 __attribute ((__unused__
));
56 static INLINE
void dis_assemble_21 (unsigned int, unsigned int *)
57 __attribute__ ((__unused__
));
58 static INLINE
unsigned long sign_extend (unsigned int, unsigned int)
59 __attribute__ ((__unused__
));
60 static INLINE
unsigned int ones (int) __attribute ((__unused__
));
61 static INLINE
void sign_unext (unsigned int, unsigned int, unsigned int *)
62 __attribute__ ((__unused__
));
63 static INLINE
unsigned long low_sign_extend (unsigned int, unsigned int)
64 __attribute__ ((__unused__
));
65 static INLINE
void low_sign_unext (unsigned int, unsigned int, unsigned int *)
66 __attribute__ ((__unused__
));
67 static INLINE
unsigned long hppa_field_adjust (unsigned long, unsigned long,
69 __attribute__ ((__unused__
));
70 static INLINE
char bfd_hppa_insn2fmt (unsigned long)
71 __attribute__ ((__unused__
));
72 static INLINE
unsigned long hppa_rebuild_insn (bfd
*, unsigned long,
73 unsigned long, unsigned long)
74 __attribute__ ((__unused__
));
75 #endif /* gcc 2.7 or higher */
77 /* The PA instruction set variants. */
78 enum pa_arch
{pa10
= 10, pa11
= 11, pa20
= 20};
80 /* HP PA-RISC relocation types */
82 enum hppa_reloc_field_selector_type
105 /* /usr/include/reloc.h defines these to constants. We want to use
106 them in enums, so #undef them before we start using them. We might
107 be able to fix this another way by simply managing not to include
108 /usr/include/reloc.h, but currently GDB picks up these defines
136 /* for compatibility */
137 enum hppa_reloc_field_selector_type_alt
139 e_fsel
= R_HPPA_FSEL
,
140 e_lssel
= R_HPPA_LSSEL
,
141 e_rssel
= R_HPPA_RSSEL
,
142 e_lsel
= R_HPPA_LSEL
,
143 e_rsel
= R_HPPA_RSEL
,
144 e_ldsel
= R_HPPA_LDSEL
,
145 e_rdsel
= R_HPPA_RDSEL
,
146 e_lrsel
= R_HPPA_LRSEL
,
147 e_rrsel
= R_HPPA_RRSEL
,
148 e_nsel
= R_HPPA_NSEL
,
149 e_nlsel
= R_HPPA_NLSEL
,
150 e_nlrsel
= R_HPPA_NLRSEL
,
151 e_psel
= R_HPPA_PSEL
,
152 e_lpsel
= R_HPPA_LPSEL
,
153 e_rpsel
= R_HPPA_RPSEL
,
154 e_tsel
= R_HPPA_TSEL
,
155 e_ltsel
= R_HPPA_LTSEL
,
156 e_rtsel
= R_HPPA_RTSEL
,
160 enum hppa_reloc_expr_type
170 /* for compatibility */
171 enum hppa_reloc_expr_type_alt
173 e_one
= R_HPPA_E_ONE
,
174 e_two
= R_HPPA_E_TWO
,
175 e_pcrel
= R_HPPA_E_PCREL
,
176 e_con
= R_HPPA_E_CON
,
177 e_plabel
= R_HPPA_E_PLABEL
,
182 /* Relocations for function calls must be accompanied by parameter
183 relocation bits. These bits describe exactly where the caller has
184 placed the function's arguments and where it expects to find a return
187 Both ELF and SOM encode this information within the addend field
188 of the call relocation. (Note this could break very badly if one
189 was to make a call like bl foo + 0x12345678).
191 The high order 10 bits contain parameter relocation information,
192 the low order 22 bits contain the constant offset. */
194 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
195 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
196 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
198 /* Some functions to manipulate PA instructions. */
199 static INLINE
unsigned int
203 return (((x
& 1) << 2) | ((x
& 6) >> 1)) & 7;
207 dis_assemble_3 (x
, r
)
211 *r
= (((x
& 4) >> 2) | ((x
& 3) << 1)) & 7;
214 static INLINE
unsigned int
218 return (((y
& 1) << 11) | ((x
& 1) << 10) | ((x
& 0x7fe) >> 1)) & 0xfff;
222 dis_assemble_12 (as12
, x
, y
)
226 *y
= (as12
& 0x800) >> 11;
227 *x
= ((as12
& 0x3ff) << 1) | ((as12
& 0x400) >> 10);
230 static INLINE
unsigned long
231 assemble_17 (x
, y
, z
)
232 unsigned int x
, y
, z
;
236 temp
= ((z
& 1) << 16) |
240 return temp
& 0x1ffff;
244 dis_assemble_17 (as17
, x
, y
, z
)
246 unsigned int *x
, *y
, *z
;
249 *z
= (as17
& 0x10000) >> 16;
250 *x
= (as17
& 0x0f800) >> 11;
251 *y
= (((as17
& 0x00400) >> 10) | ((as17
& 0x3ff) << 1)) & 0x7ff;
254 static INLINE
unsigned long
260 temp
= ((x
& 1) << 20) |
262 ((x
& 0xc000) >> 7) |
263 ((x
& 0x1f0000) >> 14) |
264 ((x
& 0x003000) >> 12);
265 return temp
& 0x1fffff;
269 dis_assemble_21 (as21
, x
)
270 unsigned int as21
, *x
;
275 temp
= (as21
& 0x100000) >> 20;
276 temp
|= (as21
& 0x0ffe00) >> 8;
277 temp
|= (as21
& 0x000180) << 7;
278 temp
|= (as21
& 0x00007c) << 14;
279 temp
|= (as21
& 0x000003) << 12;
283 static INLINE
unsigned long
287 return (int)(x
>> (len
- 1) ? (-1 << len
) | x
: x
);
290 static INLINE
unsigned int
294 unsigned int len_ones
;
301 len_ones
= (len_ones
<< 1) | 1;
309 sign_unext (x
, len
, result
)
311 unsigned int *result
;
313 unsigned int len_ones
;
315 len_ones
= ones (len
);
317 *result
= x
& len_ones
;
320 static INLINE
unsigned long
321 low_sign_extend (x
, len
)
324 return (int)((x
& 0x1 ? (-1 << (len
- 1)) : 0) | x
>> 1);
328 low_sign_unext (x
, len
, result
)
330 unsigned int *result
;
335 unsigned int one_bit_at_len
;
336 unsigned int len_ones
;
338 len_ones
= ones (len
);
339 one_bit_at_len
= 1 << (len
- 1);
341 sign_unext (x
, len
, &temp
);
342 sign
= temp
& one_bit_at_len
;
345 rest
= temp
& (len_ones
^ one_bit_at_len
);
348 *result
= rest
| sign
;
351 /* Handle field selectors for PA instructions. */
353 static INLINE
unsigned long
354 hppa_field_adjust (value
, constant_value
, r_field
)
356 unsigned long constant_value
;
357 unsigned short r_field
;
361 case e_fsel
: /* F : no change */
362 case e_nsel
: /* N : no change */
363 value
+= constant_value
;
366 case e_lssel
: /* LS : if (bit 21) then add 0x800
367 arithmetic shift right 11 bits */
368 value
+= constant_value
;
369 if (value
& 0x00000400)
371 value
= (value
& 0xfffff800) >> 11;
374 case e_rssel
: /* RS : Sign extend from bit 21 */
375 value
+= constant_value
;
376 if (value
& 0x00000400)
382 case e_lsel
: /* L : Arithmetic shift right 11 bits */
383 case e_nlsel
: /* NL : Arithmetic shift right 11 bits */
384 value
+= constant_value
;
385 value
= (value
& 0xfffff800) >> 11;
388 case e_rsel
: /* R : Set bits 0-20 to zero */
389 value
+= constant_value
;
390 value
= value
& 0x7ff;
393 case e_ldsel
: /* LD : Add 0x800, arithmetic shift
395 value
+= constant_value
;
397 value
= (value
& 0xfffff800) >> 11;
400 case e_rdsel
: /* RD : Set bits 0-20 to one */
401 value
+= constant_value
;
405 case e_lrsel
: /* LR : L with "rounded" constant */
406 case e_nlrsel
: /* NLR : NL with "rounded" constant */
407 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
408 value
= (value
& 0xfffff800) >> 11;
411 case e_rrsel
: /* RR : R with "rounded" constant */
412 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
413 value
= (value
& 0x7ff) + constant_value
- ((constant_value
+ 0x1000) & 0xffffe000);
423 /* PA-RISC OPCODES */
424 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
426 /* FIXME: this list is incomplete. It should also be an enumerated
427 type rather than #defines. */
466 /* Given a machine instruction, return its format.
468 FIXME: opcodes which do not map to a known format
469 should return an error of some sort. */
472 bfd_hppa_insn2fmt (insn
)
476 unsigned char op
= get_opcode (insn
);
527 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
530 static INLINE
unsigned long
531 hppa_rebuild_insn (abfd
, insn
, value
, r_format
)
535 unsigned long r_format
;
537 unsigned long const_part
;
538 unsigned long rebuilt_part
;
546 const_part
= insn
& 0xffffe002;
547 dis_assemble_12 (value
, &w1
, &w
);
548 rebuilt_part
= (w1
<< 2) | w
;
549 return const_part
| rebuilt_part
;
556 const_part
= insn
& 0xffffe002;
557 dis_assemble_12 (value
, &w1
, &w
);
558 rebuilt_part
= (w1
<< 2) | w
;
559 return const_part
| rebuilt_part
;
566 const_part
= insn
& 0xffffc000;
567 low_sign_unext (value
, 14, &ext
);
568 return const_part
| ext
;
575 const_part
= insn
& 0xffe0e002;
576 dis_assemble_17 (value
, &w1
, &w2
, &w
);
577 rebuilt_part
= (w2
<< 2) | (w1
<< 16) | w
;
578 return const_part
| rebuilt_part
;
585 const_part
= insn
& 0xffe00000;
586 dis_assemble_21 (value
, &w
);
587 return const_part
| w
;