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
unsigned long assemble_21 (unsigned int)
56 __attribute ((__unused__
));
57 static INLINE
void dis_assemble_21 (unsigned int, unsigned int *)
58 __attribute__ ((__unused__
));
59 static INLINE
unsigned long sign_extend (unsigned int, unsigned int)
60 __attribute__ ((__unused__
));
61 static INLINE
unsigned int ones (int) __attribute ((__unused__
));
62 static INLINE
void sign_unext (unsigned int, unsigned int, unsigned int *)
63 __attribute__ ((__unused__
));
64 static INLINE
unsigned long low_sign_extend (unsigned int, unsigned int)
65 __attribute__ ((__unused__
));
66 static INLINE
void low_sign_unext (unsigned int, unsigned int, unsigned int *)
67 __attribute__ ((__unused__
));
68 static INLINE
unsigned long hppa_field_adjust (unsigned long, unsigned long,
70 __attribute__ ((__unused__
));
71 static INLINE
char bfd_hppa_insn2fmt (unsigned long)
72 __attribute__ ((__unused__
));
73 static INLINE
unsigned long hppa_rebuild_insn (bfd
*, unsigned long,
74 unsigned long, unsigned long)
75 __attribute__ ((__unused__
));
76 #endif /* gcc 2.7 or higher */
79 /* The PA instruction set variants. */
80 enum pa_arch
{pa10
= 10, pa11
= 11, pa20
= 20};
82 /* HP PA-RISC relocation types */
84 enum hppa_reloc_field_selector_type
104 R_HPPA_LTPSEL
= 0x12,
108 /* /usr/include/reloc.h defines these to constants. We want to use
109 them in enums, so #undef them before we start using them. We might
110 be able to fix this another way by simply managing not to include
111 /usr/include/reloc.h, but currently GDB picks up these defines
138 /* for compatibility */
139 enum hppa_reloc_field_selector_type_alt
141 e_fsel
= R_HPPA_FSEL
,
142 e_lssel
= R_HPPA_LSSEL
,
143 e_rssel
= R_HPPA_RSSEL
,
144 e_lsel
= R_HPPA_LSEL
,
145 e_rsel
= R_HPPA_RSEL
,
146 e_ldsel
= R_HPPA_LDSEL
,
147 e_rdsel
= R_HPPA_RDSEL
,
148 e_lrsel
= R_HPPA_LRSEL
,
149 e_rrsel
= R_HPPA_RRSEL
,
150 e_nsel
= R_HPPA_NSEL
,
151 e_nlsel
= R_HPPA_NLSEL
,
152 e_nlrsel
= R_HPPA_NLRSEL
,
153 e_psel
= R_HPPA_PSEL
,
154 e_lpsel
= R_HPPA_LPSEL
,
155 e_rpsel
= R_HPPA_RPSEL
,
156 e_tsel
= R_HPPA_TSEL
,
157 e_ltsel
= R_HPPA_LTSEL
,
158 e_rtsel
= R_HPPA_RTSEL
,
159 e_ltpsel
= R_HPPA_LTPSEL
,
160 e_rtpsel
= R_HPPA_RTPSEL
163 enum hppa_reloc_expr_type
173 /* for compatibility */
174 enum hppa_reloc_expr_type_alt
176 e_one
= R_HPPA_E_ONE
,
177 e_two
= R_HPPA_E_TWO
,
178 e_pcrel
= R_HPPA_E_PCREL
,
179 e_con
= R_HPPA_E_CON
,
180 e_plabel
= R_HPPA_E_PLABEL
,
185 /* Relocations for function calls must be accompanied by parameter
186 relocation bits. These bits describe exactly where the caller has
187 placed the function's arguments and where it expects to find a return
190 Both ELF and SOM encode this information within the addend field
191 of the call relocation. (Note this could break very badly if one
192 was to make a call like bl foo + 0x12345678).
194 The high order 10 bits contain parameter relocation information,
195 the low order 22 bits contain the constant offset. */
197 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
198 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
199 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
200 #define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
202 /* These macros get bit fields using HP's numbering (MSB = 0),
203 * but note that "MASK" assumes that the LSB bits are what's
207 #define GET_FIELD(X, FROM, TO) \
208 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
210 #define GET_BIT(X, WHICH) \
211 GET_FIELD (X, WHICH, WHICH)
216 #define CATENATE(X, XSIZE, Y, YSIZE) \
217 (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
220 CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
222 /* Some functions to manipulate PA instructions. */
224 /* NOTE: these use the HP convention that f{1} is the _left_ most
225 * bit (MSB) of f; they sometimes have to impose an assumption
226 * about the size of a field; and as far as I can tell, most
230 static INLINE
unsigned long
234 return (int)(x
>> (len
- 1) ? (-1 << len
) | x
: x
);
237 static INLINE
unsigned int
241 return CATENATE (GET_BIT (x
, 2), 1, GET_FIELD (x
, 0, 1), 2);
245 dis_assemble_3 (x
, r
)
249 *r
= (((x
& 4) >> 2) | ((x
& 3) << 1)) & 7;
252 static INLINE
unsigned int
256 return (((x
& 0x1) << 5) + (32 - (y
& 0x1f)));
259 static INLINE
unsigned int
263 return CATENATE (CATENATE (y
, 1, GET_BIT (x
, 10), 1), 2,
264 GET_FIELD (x
, 0, 9), 9);
268 dis_assemble_12 (as12
, x
, y
)
272 *y
= (as12
& 0x800) >> 11;
273 *x
= ((as12
& 0x3ff) << 1) | ((as12
& 0x400) >> 10);
276 static INLINE
unsigned long
280 /* Depends on PSW W-bit !*/
284 temp
= CATENATE (CATENATE (GET_BIT (y
, 13), 1,
285 (GET_BIT (y
, 13) ^ GET_BIT (x
, 0)), 1), 2,
286 CATENATE ((GET_BIT (y
, 13) ^ GET_BIT (x
, 1)), 1,
287 GET_FIELD (y
, 0, 12), 13), 14);
289 temp
= CATENATE (CATENATE (GET_BIT (y
, 13), 1, GET_BIT (y
, 13), 1), 2,
290 CATENATE (GET_BIT (y
, 13), 1, GET_FIELD (y
, 0, 12), 13), 14);
292 return sign_extend (temp
, 16);
296 static INLINE
unsigned long
297 assemble_16a (x
, y
, z
)
298 unsigned int x
, y
, z
;
300 /* Depends on PSW W-bit !*/
304 temp
= CATENATE (CATENATE (z
, 1, (z
^ GET_BIT (x
, 0)), 1), 2,
305 CATENATE ((z
^ GET_BIT (x
, 1)), 1, y
, 11), 12);
307 temp
= CATENATE (CATENATE (z
, 1, z
, 1), 2, CATENATE (z
, 1, y
, 11), 12);
309 return sign_extend ((temp
<< 2), 16);
312 static INLINE
unsigned long
313 assemble_17 (x
, y
, z
)
314 unsigned int x
, y
, z
;
318 temp
= CATENATE (CATENATE (z
, 1, x
, 5), 6,
319 CATENATE (GET_BIT (y
, 10), 1, GET_FIELD (y
, 0, 9), 10), 11);
325 dis_assemble_17 (as17
, x
, y
, z
)
327 unsigned int *x
, *y
, *z
;
330 *z
= (as17
& 0x10000) >> 16;
331 *x
= (as17
& 0x0f800) >> 11;
332 *y
= (((as17
& 0x00400) >> 10) | ((as17
& 0x3ff) << 1)) & 0x7ff;
335 static INLINE
unsigned long
341 temp
= ((x
& 1) << 20) |
343 ((x
& 0xc000) >> 7) |
344 ((x
& 0x1f0000) >> 14) |
345 ((x
& 0x003000) >> 12);
346 return temp
& 0x1fffff;
349 static INLINE
unsigned long
350 assemble_22 (a
,b
,c
,d
)
351 unsigned int a
,b
,c
,d
;
355 temp
= CATENATE (CATENATE (d
, 1, a
, 5), 6,
356 CATENATE (b
, 5, ELEVEN (c
), 11), 16);
358 return sign_extend (temp
, 22);
362 dis_assemble_21 (as21
, x
)
363 unsigned int as21
, *x
;
368 temp
= (as21
& 0x100000) >> 20;
369 temp
|= (as21
& 0x0ffe00) >> 8;
370 temp
|= (as21
& 0x000180) << 7;
371 temp
|= (as21
& 0x00007c) << 14;
372 temp
|= (as21
& 0x000003) << 12;
376 static INLINE
unsigned int
380 unsigned int len_ones
;
387 len_ones
= (len_ones
<< 1) | 1;
395 sign_unext (x
, len
, result
)
397 unsigned int *result
;
399 unsigned int len_ones
;
401 len_ones
= ones (len
);
403 *result
= x
& len_ones
;
406 static INLINE
unsigned long
407 low_sign_extend (x
, len
)
410 return (int)((x
& 0x1 ? (-1 << (len
- 1)) : 0) | x
>> 1);
414 low_sign_unext (x
, len
, result
)
416 unsigned int *result
;
421 unsigned int one_bit_at_len
;
422 unsigned int len_ones
;
424 len_ones
= ones (len
);
425 one_bit_at_len
= 1 << (len
- 1);
427 sign_unext (x
, len
, &temp
);
428 sign
= temp
& one_bit_at_len
;
431 rest
= temp
& (len_ones
^ one_bit_at_len
);
434 *result
= rest
| sign
;
437 /* Handle field selectors for PA instructions. */
439 static INLINE
unsigned long
440 hppa_field_adjust (value
, constant_value
, r_field
)
442 unsigned long constant_value
;
443 unsigned short r_field
;
447 case e_fsel
: /* F : no change */
448 case e_nsel
: /* N : no change */
449 value
+= constant_value
;
452 case e_lssel
: /* LS : if (bit 21) then add 0x800
453 arithmetic shift right 11 bits */
454 value
+= constant_value
;
455 if (value
& 0x00000400)
457 value
= (value
& 0xfffff800) >> 11;
460 case e_rssel
: /* RS : Sign extend from bit 21 */
461 value
+= constant_value
;
462 if (value
& 0x00000400)
468 case e_lsel
: /* L : Arithmetic shift right 11 bits */
469 case e_nlsel
: /* NL : Arithmetic shift right 11 bits */
470 value
+= constant_value
;
471 value
= (value
& 0xfffff800) >> 11;
474 case e_rsel
: /* R : Set bits 0-20 to zero */
475 value
+= constant_value
;
476 value
= value
& 0x7ff;
479 case e_ldsel
: /* LD : Add 0x800, arithmetic shift
481 value
+= constant_value
;
483 value
= (value
& 0xfffff800) >> 11;
486 case e_rdsel
: /* RD : Set bits 0-20 to one */
487 value
+= constant_value
;
491 case e_lrsel
: /* LR : L with "rounded" constant */
492 case e_nlrsel
: /* NLR : NL with "rounded" constant */
493 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
494 value
= (value
& 0xfffff800) >> 11;
497 case e_rrsel
: /* RR : R with "rounded" constant */
498 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
499 value
= (value
& 0x7ff) + constant_value
- ((constant_value
+ 0x1000) & 0xffffe000);
509 /* PA-RISC OPCODES */
510 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
512 /* FIXME: this list is incomplete. It should also be an enumerated
513 type rather than #defines. */
552 /* Given a machine instruction, return its format.
554 FIXME: opcodes which do not map to a known format
555 should return an error of some sort. */
558 bfd_hppa_insn2fmt (insn
)
562 unsigned char op
= get_opcode (insn
);
613 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
616 static INLINE
unsigned long
617 hppa_rebuild_insn (abfd
, insn
, value
, r_format
)
618 bfd
*abfd ATTRIBUTE_UNUSED
;
621 unsigned long r_format
;
623 unsigned long const_part
;
624 unsigned long rebuilt_part
;
632 const_part
= insn
& 0xffffe002;
633 dis_assemble_12 (value
, &w1
, &w
);
634 rebuilt_part
= (w1
<< 2) | w
;
635 return const_part
| rebuilt_part
;
642 const_part
= insn
& 0xffffe002;
643 dis_assemble_12 (value
, &w1
, &w
);
644 rebuilt_part
= (w1
<< 2) | w
;
645 return const_part
| rebuilt_part
;
652 const_part
= insn
& 0xffffc000;
653 low_sign_unext (value
, 14, &ext
);
654 return const_part
| ext
;
661 const_part
= insn
& 0xffe0e002;
662 dis_assemble_17 (value
, &w1
, &w2
, &w
);
663 rebuilt_part
= (w2
<< 2) | (w1
<< 16) | w
;
664 return const_part
| rebuilt_part
;
671 const_part
= insn
& 0xffe00000;
672 dis_assemble_21 (value
, &w
);
673 return const_part
| w
;