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
106 /* /usr/include/reloc.h defines these to constants. We want to use
107 them in enums, so #undef them before we start using them. We might
108 be able to fix this another way by simply managing not to include
109 /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
159 enum hppa_reloc_expr_type
169 /* for compatibility */
170 enum hppa_reloc_expr_type_alt
172 e_one = R_HPPA_E_ONE,
173 e_two = R_HPPA_E_TWO,
174 e_pcrel = R_HPPA_E_PCREL,
175 e_con = R_HPPA_E_CON,
176 e_plabel = R_HPPA_E_PLABEL,
181 /* Relocations for function calls must be accompanied by parameter
182 relocation bits. These bits describe exactly where the caller has
183 placed the function's arguments and where it expects to find a return
186 Both ELF and SOM encode this information within the addend field
187 of the call relocation. (Note this could break very badly if one
188 was to make a call like bl foo + 0x12345678).
190 The high order 10 bits contain parameter relocation information,
191 the low order 22 bits contain the constant offset. */
193 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
194 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
195 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
196 #define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
198 /* These macros get bit fields using HP's numbering (MSB = 0),
199 * but note that "MASK" assumes that the LSB bits are what's
203 #define GET_FIELD(X, FROM, TO) \
204 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
206 #define GET_BIT(X, WHICH) \
207 GET_FIELD (X, WHICH, WHICH)
212 #define CATENATE(X, XSIZE, Y, YSIZE) \
213 (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
216 CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
218 /* Some functions to manipulate PA instructions. */
220 /* NOTE: these use the HP convention that f{1} is the _left_ most
221 * bit (MSB) of f; they sometimes have to impose an assumption
222 * about the size of a field; and as far as I can tell, most
226 static INLINE unsigned long
230 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
233 static INLINE unsigned int
237 return CATENATE (GET_BIT (x, 2), 1, GET_FIELD (x, 0, 1), 2);
241 dis_assemble_3 (x, r)
245 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
248 static INLINE unsigned int
252 return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
255 static INLINE unsigned int
259 return CATENATE (CATENATE (y, 1, GET_BIT (x, 10), 1), 2,
260 GET_FIELD (x, 0, 9), 9);
264 dis_assemble_12 (as12, x, y)
268 *y = (as12 & 0x800) >> 11;
269 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
272 static INLINE unsigned long
276 /* Depends on PSW W-bit !*/
280 temp = CATENATE (CATENATE (GET_BIT (y, 13), 1,
281 (GET_BIT (y, 13) ^ GET_BIT (x, 0)), 1), 2,
282 CATENATE ((GET_BIT (y, 13) ^ GET_BIT (x, 1)), 1,
283 GET_FIELD (y, 0, 12), 13), 14);
285 temp = CATENATE (CATENATE (GET_BIT (y, 13), 1, GET_BIT (y, 13), 1), 2,
286 CATENATE (GET_BIT (y, 13), 1, GET_FIELD (y, 0, 12), 13), 14);
288 return sign_extend (temp, 16);
292 static INLINE unsigned long
293 assemble_16a (x, y, z)
294 unsigned int x, y, z;
296 /* Depends on PSW W-bit !*/
300 temp = CATENATE (CATENATE (z, 1, (z ^ GET_BIT (x, 0)), 1), 2,
301 CATENATE ((z ^ GET_BIT (x, 1)), 1, y, 11), 12);
303 temp = CATENATE (CATENATE (z, 1, z, 1), 2, CATENATE (z, 1, y, 11), 12);
305 return sign_extend ((temp << 2), 16);
308 static INLINE unsigned long
309 assemble_17 (x, y, z)
310 unsigned int x, y, z;
314 temp = CATENATE (CATENATE (z, 1, x, 5), 6,
315 CATENATE (GET_BIT (y, 10), 1, GET_FIELD (y, 0, 9), 10), 11);
321 dis_assemble_17 (as17, x, y, z)
323 unsigned int *x, *y, *z;
326 *z = (as17 & 0x10000) >> 16;
327 *x = (as17 & 0x0f800) >> 11;
328 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
331 static INLINE unsigned long
337 temp = ((x & 1) << 20) |
339 ((x & 0xc000) >> 7) |
340 ((x & 0x1f0000) >> 14) |
341 ((x & 0x003000) >> 12);
342 return temp & 0x1fffff;
345 static INLINE unsigned long
346 assemble_22 (a,b,c,d)
347 unsigned int a,b,c,d;
351 temp = CATENATE (CATENATE (d, 1, a, 5), 6,
352 CATENATE (b, 5, ELEVEN (c), 11), 16);
354 return sign_extend (temp, 22);
358 dis_assemble_21 (as21, x)
359 unsigned int as21, *x;
364 temp = (as21 & 0x100000) >> 20;
365 temp |= (as21 & 0x0ffe00) >> 8;
366 temp |= (as21 & 0x000180) << 7;
367 temp |= (as21 & 0x00007c) << 14;
368 temp |= (as21 & 0x000003) << 12;
372 static INLINE unsigned int
376 unsigned int len_ones;
383 len_ones = (len_ones << 1) | 1;
391 sign_unext (x, len, result)
393 unsigned int *result;
395 unsigned int len_ones;
397 len_ones = ones (len);
399 *result = x & len_ones;
402 static INLINE unsigned long
403 low_sign_extend (x, len)
406 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
410 low_sign_unext (x, len, result)
412 unsigned int *result;
417 unsigned int one_bit_at_len;
418 unsigned int len_ones;
420 len_ones = ones (len);
421 one_bit_at_len = 1 << (len - 1);
423 sign_unext (x, len, &temp);
424 sign = temp & one_bit_at_len;
427 rest = temp & (len_ones ^ one_bit_at_len);
430 *result = rest | sign;
433 /* Handle field selectors for PA instructions. */
435 static INLINE unsigned long
436 hppa_field_adjust (value, constant_value, r_field)
438 unsigned long constant_value;
439 unsigned short r_field;
443 case e_fsel: /* F : no change */
444 case e_nsel: /* N : no change */
445 value += constant_value;
448 case e_lssel: /* LS : if (bit 21) then add 0x800
449 arithmetic shift right 11 bits */
450 value += constant_value;
451 if (value & 0x00000400)
453 value = (value & 0xfffff800) >> 11;
456 case e_rssel: /* RS : Sign extend from bit 21 */
457 value += constant_value;
458 if (value & 0x00000400)
464 case e_lsel: /* L : Arithmetic shift right 11 bits */
465 case e_nlsel: /* NL : Arithmetic shift right 11 bits */
466 value += constant_value;
467 value = (value & 0xfffff800) >> 11;
470 case e_rsel: /* R : Set bits 0-20 to zero */
471 value += constant_value;
472 value = value & 0x7ff;
475 case e_ldsel: /* LD : Add 0x800, arithmetic shift
477 value += constant_value;
479 value = (value & 0xfffff800) >> 11;
482 case e_rdsel: /* RD : Set bits 0-20 to one */
483 value += constant_value;
487 case e_lrsel: /* LR : L with "rounded" constant */
488 case e_nlrsel: /* NLR : NL with "rounded" constant */
489 value = value + ((constant_value + 0x1000) & 0xffffe000);
490 value = (value & 0xfffff800) >> 11;
493 case e_rrsel: /* RR : R with "rounded" constant */
494 value = value + ((constant_value + 0x1000) & 0xffffe000);
495 value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
505 /* PA-RISC OPCODES */
506 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
508 /* FIXME: this list is incomplete. It should also be an enumerated
509 type rather than #defines. */
548 /* Given a machine instruction, return its format.
550 FIXME: opcodes which do not map to a known format
551 should return an error of some sort. */
554 bfd_hppa_insn2fmt (insn)
558 unsigned char op = get_opcode (insn);
609 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
612 static INLINE unsigned long
613 hppa_rebuild_insn (abfd, insn, value, r_format)
614 bfd *abfd ATTRIBUTE_UNUSED;
617 unsigned long r_format;
619 unsigned long const_part;
620 unsigned long rebuilt_part;
628 const_part = insn & 0xffffe002;
629 dis_assemble_12 (value, &w1, &w);
630 rebuilt_part = (w1 << 2) | w;
631 return const_part | rebuilt_part;
638 const_part = insn & 0xffffe002;
639 dis_assemble_12 (value, &w1, &w);
640 rebuilt_part = (w1 << 2) | w;
641 return const_part | rebuilt_part;
648 const_part = insn & 0xffffc000;
649 low_sign_unext (value, 14, &ext);
650 return const_part | ext;
657 const_part = insn & 0xffe0e002;
658 dis_assemble_17 (value, &w1, &w2, &w);
659 rebuilt_part = (w2 << 2) | (w1 << 16) | w;
660 return const_part | rebuilt_part;
667 const_part = insn & 0xffe00000;
668 dis_assemble_21 (value, &w);
669 return const_part | w;