1 /* HP PA-RISC SOM object file format: definitions internal to BFD.
2 Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 98, 1999
3 Free Software Foundation, Inc.
5 Contributed by the Center for Software Science at the
6 University of Utah (pa-gdb-bugs@cs.utah.edu).
8 This file is part of BFD, the Binary File Descriptor library.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #define BYTES_IN_WORD 4
28 #define PA_PAGESIZE 0x1000
38 #if __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
39 /* Declare the functions with the unused attribute to avoid warnings. */
40 static INLINE
unsigned int assemble_3 (unsigned int)
41 __attribute__ ((__unused__
));
42 static INLINE
void dis_assemble_3 (unsigned int, unsigned int *)
43 __attribute__ ((__unused__
));
44 static INLINE
unsigned int assemble_12 (unsigned int, unsigned int)
45 __attribute__ ((__unused__
));
46 static INLINE
void dis_assemble_12 (unsigned int, unsigned int *,
48 __attribute__ ((__unused__
));
49 static INLINE
unsigned long assemble_17 (unsigned int, unsigned int,
51 __attribute__ ((__unused__
));
52 static INLINE
void dis_assemble_17 (unsigned int, unsigned int *,
53 unsigned int *, unsigned int *)
54 __attribute__ ((__unused__
));
55 static INLINE
void dis_assemble_22 (unsigned int, unsigned int *,
56 unsigned int *, unsigned int *,
58 __attribute__ ((__unused__
));
59 static INLINE
unsigned long assemble_21 (unsigned int)
60 __attribute ((__unused__
));
61 static INLINE
void dis_assemble_21 (unsigned int, unsigned int *)
62 __attribute__ ((__unused__
));
63 static INLINE
unsigned long sign_extend (unsigned int, unsigned int)
64 __attribute__ ((__unused__
));
65 static INLINE
unsigned int ones (int) __attribute ((__unused__
));
66 static INLINE
void sign_unext (unsigned int, unsigned int, unsigned int *)
67 __attribute__ ((__unused__
));
68 static INLINE
unsigned long low_sign_extend (unsigned int, unsigned int)
69 __attribute__ ((__unused__
));
70 static INLINE
void low_sign_unext (unsigned int, unsigned int, unsigned int *)
71 __attribute__ ((__unused__
));
72 static INLINE
unsigned long hppa_field_adjust (unsigned long, unsigned long,
74 __attribute__ ((__unused__
));
75 static INLINE
int bfd_hppa_insn2fmt (unsigned long)
76 __attribute__ ((__unused__
));
77 static INLINE
unsigned long hppa_rebuild_insn (bfd
*, unsigned long,
78 unsigned long, unsigned long)
79 __attribute__ ((__unused__
));
80 #endif /* gcc 2.7 or higher */
83 /* The PA instruction set variants. */
84 enum pa_arch
{pa10
= 10, pa11
= 11, pa20
= 20};
86 /* HP PA-RISC relocation types */
88 enum hppa_reloc_field_selector_type
108 R_HPPA_LTPSEL
= 0x12,
112 /* /usr/include/reloc.h defines these to constants. We want to use
113 them in enums, so #undef them before we start using them. We might
114 be able to fix this another way by simply managing not to include
115 /usr/include/reloc.h, but currently GDB picks up these defines
142 /* for compatibility */
143 enum hppa_reloc_field_selector_type_alt
145 e_fsel
= R_HPPA_FSEL
,
146 e_lssel
= R_HPPA_LSSEL
,
147 e_rssel
= R_HPPA_RSSEL
,
148 e_lsel
= R_HPPA_LSEL
,
149 e_rsel
= R_HPPA_RSEL
,
150 e_ldsel
= R_HPPA_LDSEL
,
151 e_rdsel
= R_HPPA_RDSEL
,
152 e_lrsel
= R_HPPA_LRSEL
,
153 e_rrsel
= R_HPPA_RRSEL
,
154 e_nsel
= R_HPPA_NSEL
,
155 e_nlsel
= R_HPPA_NLSEL
,
156 e_nlrsel
= R_HPPA_NLRSEL
,
157 e_psel
= R_HPPA_PSEL
,
158 e_lpsel
= R_HPPA_LPSEL
,
159 e_rpsel
= R_HPPA_RPSEL
,
160 e_tsel
= R_HPPA_TSEL
,
161 e_ltsel
= R_HPPA_LTSEL
,
162 e_rtsel
= R_HPPA_RTSEL
,
163 e_ltpsel
= R_HPPA_LTPSEL
,
164 e_rtpsel
= R_HPPA_RTPSEL
167 enum hppa_reloc_expr_type
177 /* for compatibility */
178 enum hppa_reloc_expr_type_alt
180 e_one
= R_HPPA_E_ONE
,
181 e_two
= R_HPPA_E_TWO
,
182 e_pcrel
= R_HPPA_E_PCREL
,
183 e_con
= R_HPPA_E_CON
,
184 e_plabel
= R_HPPA_E_PLABEL
,
189 /* Relocations for function calls must be accompanied by parameter
190 relocation bits. These bits describe exactly where the caller has
191 placed the function's arguments and where it expects to find a return
194 Both ELF and SOM encode this information within the addend field
195 of the call relocation. (Note this could break very badly if one
196 was to make a call like bl foo + 0x12345678).
198 The high order 10 bits contain parameter relocation information,
199 the low order 22 bits contain the constant offset. */
201 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
202 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
203 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
204 #define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
206 /* These macros get bit fields using HP's numbering (MSB = 0),
207 * but note that "MASK" assumes that the LSB bits are what's
211 #define GET_FIELD(X, FROM, TO) \
212 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
214 #define GET_BIT(X, WHICH) \
215 GET_FIELD (X, WHICH, WHICH)
220 #define CATENATE(X, XSIZE, Y, YSIZE) \
221 (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
224 CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
226 /* Some functions to manipulate PA instructions. */
228 /* NOTE: these use the HP convention that f{1} is the _left_ most
229 * bit (MSB) of f; they sometimes have to impose an assumption
230 * about the size of a field; and as far as I can tell, most
234 static INLINE
unsigned long
238 return (int)(x
>> (len
- 1) ? (-1 << len
) | x
: x
);
241 static INLINE
unsigned int
245 return CATENATE (GET_BIT (x
, 2), 1, GET_FIELD (x
, 0, 1), 2);
249 dis_assemble_3 (x
, r
)
253 *r
= (((x
& 4) >> 2) | ((x
& 3) << 1)) & 7;
256 static INLINE
unsigned int
260 return (((x
& 0x1) << 5) + (32 - (y
& 0x1f)));
263 static INLINE
unsigned int
267 return CATENATE (CATENATE (y
, 1, GET_BIT (x
, 10), 1), 2,
268 GET_FIELD (x
, 0, 9), 9);
272 dis_assemble_12 (as12
, x
, y
)
276 *y
= (as12
& 0x800) >> 11;
277 *x
= ((as12
& 0x3ff) << 1) | ((as12
& 0x400) >> 10);
280 static INLINE
unsigned long
284 /* Depends on PSW W-bit !*/
288 temp
= CATENATE (CATENATE (GET_BIT (y
, 13), 1,
289 (GET_BIT (y
, 13) ^ GET_BIT (x
, 0)), 1), 2,
290 CATENATE ((GET_BIT (y
, 13) ^ GET_BIT (x
, 1)), 1,
291 GET_FIELD (y
, 0, 12), 13), 14);
293 temp
= CATENATE (CATENATE (GET_BIT (y
, 13), 1, GET_BIT (y
, 13), 1), 2,
294 CATENATE (GET_BIT (y
, 13), 1, GET_FIELD (y
, 0, 12), 13), 14);
296 return sign_extend (temp
, 16);
300 static INLINE
unsigned long
301 assemble_16a (x
, y
, z
)
302 unsigned int x
, y
, z
;
304 /* Depends on PSW W-bit !*/
308 temp
= CATENATE (CATENATE (z
, 1, (z
^ GET_BIT (x
, 0)), 1), 2,
309 CATENATE ((z
^ GET_BIT (x
, 1)), 1, y
, 11), 12);
311 temp
= CATENATE (CATENATE (z
, 1, z
, 1), 2, CATENATE (z
, 1, y
, 11), 12);
313 return sign_extend ((temp
<< 2), 16);
316 static INLINE
unsigned long
317 assemble_17 (x
, y
, z
)
318 unsigned int x
, y
, z
;
322 temp
= CATENATE (CATENATE (z
, 1, x
, 5), 6,
323 CATENATE (GET_BIT (y
, 10), 1, GET_FIELD (y
, 0, 9), 10), 11);
329 dis_assemble_17 (as17
, x
, y
, z
)
331 unsigned int *x
, *y
, *z
;
334 *z
= (as17
& 0x10000) >> 16;
335 *x
= (as17
& 0x0f800) >> 11;
336 *y
= (((as17
& 0x00400) >> 10) | ((as17
& 0x3ff) << 1)) & 0x7ff;
340 dis_assemble_22 (as22
, a
, b
, c
, d
)
342 unsigned int *a
, *b
, *c
, *d
;
345 *d
= (as22
& 0x200000) >> 21;
346 *a
= (as22
& 0x1f0000) >> 16;
347 *b
= (as22
& 0x0f800) >> 11;
348 *c
= (((as22
& 0x00400) >> 10) | ((as22
& 0x3ff) << 1)) & 0x7ff;
351 static INLINE
unsigned long
357 temp
= ((x
& 1) << 20) |
359 ((x
& 0xc000) >> 7) |
360 ((x
& 0x1f0000) >> 14) |
361 ((x
& 0x003000) >> 12);
362 return temp
& 0x1fffff;
365 static INLINE
unsigned long
366 assemble_22 (a
,b
,c
,d
)
367 unsigned int a
,b
,c
,d
;
371 temp
= CATENATE (CATENATE (d
, 1, a
, 5), 6,
372 CATENATE (b
, 5, ELEVEN (c
), 11), 16);
374 return sign_extend (temp
, 22);
378 dis_assemble_21 (as21
, x
)
379 unsigned int as21
, *x
;
384 temp
= (as21
& 0x100000) >> 20;
385 temp
|= (as21
& 0x0ffe00) >> 8;
386 temp
|= (as21
& 0x000180) << 7;
387 temp
|= (as21
& 0x00007c) << 14;
388 temp
|= (as21
& 0x000003) << 12;
392 static INLINE
unsigned int
396 unsigned int len_ones
;
403 len_ones
= (len_ones
<< 1) | 1;
411 sign_unext (x
, len
, result
)
413 unsigned int *result
;
415 unsigned int len_ones
;
417 len_ones
= ones (len
);
419 *result
= x
& len_ones
;
422 static INLINE
unsigned long
423 low_sign_extend (x
, len
)
426 return (int)((x
& 0x1 ? (-1 << (len
- 1)) : 0) | x
>> 1);
430 low_sign_unext (x
, len
, result
)
432 unsigned int *result
;
437 unsigned int one_bit_at_len
;
438 unsigned int len_ones
;
440 len_ones
= ones (len
);
441 one_bit_at_len
= 1 << (len
- 1);
443 sign_unext (x
, len
, &temp
);
444 sign
= temp
& one_bit_at_len
;
447 rest
= temp
& (len_ones
^ one_bit_at_len
);
450 *result
= rest
| sign
;
453 /* Handle field selectors for PA instructions. */
455 static INLINE
unsigned long
456 hppa_field_adjust (value
, constant_value
, r_field
)
458 unsigned long constant_value
;
459 unsigned short r_field
;
463 case e_fsel
: /* F : no change */
464 case e_nsel
: /* N : no change */
465 value
+= constant_value
;
468 case e_lssel
: /* LS : if (bit 21) then add 0x800
469 arithmetic shift right 11 bits */
470 value
+= constant_value
;
471 if (value
& 0x00000400)
473 value
= (value
& 0xfffff800) >> 11;
476 case e_rssel
: /* RS : Sign extend from bit 21 */
477 value
+= constant_value
;
478 if (value
& 0x00000400)
484 case e_lsel
: /* L : Arithmetic shift right 11 bits */
485 case e_nlsel
: /* NL : Arithmetic shift right 11 bits */
486 value
+= constant_value
;
487 value
= (value
& 0xfffff800) >> 11;
490 case e_rsel
: /* R : Set bits 0-20 to zero */
491 value
+= constant_value
;
492 value
= value
& 0x7ff;
495 case e_ldsel
: /* LD : Add 0x800, arithmetic shift
497 value
+= constant_value
;
499 value
= (value
& 0xfffff800) >> 11;
502 case e_rdsel
: /* RD : Set bits 0-20 to one */
503 value
+= constant_value
;
507 case e_lrsel
: /* LR : L with "rounded" constant */
508 case e_nlrsel
: /* NLR : NL with "rounded" constant */
509 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
510 value
= (value
& 0xfffff800) >> 11;
513 case e_rrsel
: /* RR : R with "rounded" constant */
514 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
515 value
= (value
& 0x7ff) + constant_value
- ((constant_value
+ 0x1000) & 0xffffe000);
525 /* PA-RISC OPCODES */
526 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
528 /* FIXME: this list is incomplete. It should also be an enumerated
529 type rather than #defines. */
577 /* Given a machine instruction, return its format.
579 FIXME: opcodes which do not map to a known format
580 should return an error of some sort. */
583 bfd_hppa_insn2fmt (insn
)
587 unsigned char op
= get_opcode (insn
);
628 /* This is a hack. Unfortunately, format 11 is already taken
629 and we're using integers rather than an enum, so it's hard
630 to describe the 10a format. */
640 if ((insn
& 0x00008000) == 0x00008000)
656 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
659 static INLINE
unsigned long
660 hppa_rebuild_insn (abfd
, insn
, value
, r_format
)
661 bfd
*abfd ATTRIBUTE_UNUSED
;
664 unsigned long r_format
;
666 unsigned long const_part
;
667 unsigned long rebuilt_part
;
675 const_part
= insn
& 0xffffe002;
676 dis_assemble_12 (value
, &w1
, &w
);
677 rebuilt_part
= (w1
<< 2) | w
;
678 return const_part
| rebuilt_part
;
685 const_part
= insn
& 0xffffe002;
686 dis_assemble_12 (value
, &w1
, &w
);
687 rebuilt_part
= (w1
<< 2) | w
;
688 return const_part
| rebuilt_part
;
695 const_part
= insn
& 0xffffc000;
696 low_sign_unext (value
, 14, &ext
);
697 return const_part
| ext
;
704 const_part
= insn
& 0xffe0e002;
705 dis_assemble_17 (value
, &w1
, &w2
, &w
);
706 rebuilt_part
= (w2
<< 2) | (w1
<< 16) | w
;
707 return const_part
| rebuilt_part
;
714 const_part
= insn
& 0xffe00000;
715 dis_assemble_21 (value
, &w
);
716 return const_part
| w
;