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 void dis_assemble_16 (unsigned int, unsigned int *, int)
50 __attribute__ ((__unused__));
51 static INLINE unsigned long assemble_17 (unsigned int, unsigned int,
53 __attribute__ ((__unused__));
54 static INLINE void dis_assemble_17 (unsigned int, unsigned int *,
55 unsigned int *, unsigned int *)
56 __attribute__ ((__unused__));
57 static INLINE void dis_assemble_22 (unsigned int, unsigned int *,
58 unsigned int *, unsigned int *,
60 __attribute__ ((__unused__));
61 static INLINE unsigned long assemble_21 (unsigned int)
62 __attribute ((__unused__));
63 static INLINE void dis_assemble_21 (unsigned int, unsigned int *)
64 __attribute__ ((__unused__));
65 static INLINE unsigned long sign_extend (unsigned int, unsigned int)
66 __attribute__ ((__unused__));
67 static INLINE unsigned int ones (int) __attribute ((__unused__));
68 static INLINE void sign_unext (unsigned int, unsigned int, unsigned int *)
69 __attribute__ ((__unused__));
70 static INLINE unsigned long low_sign_extend (unsigned int, unsigned int)
71 __attribute__ ((__unused__));
72 static INLINE void low_sign_unext (unsigned int, unsigned int, unsigned int *)
73 __attribute__ ((__unused__));
74 static INLINE unsigned long hppa_field_adjust (unsigned long, unsigned long,
76 __attribute__ ((__unused__));
77 static INLINE int bfd_hppa_insn2fmt (unsigned long)
78 __attribute__ ((__unused__));
79 static INLINE unsigned long hppa_rebuild_insn (bfd *, unsigned long,
80 unsigned long, unsigned long)
81 __attribute__ ((__unused__));
82 #endif /* gcc 2.7 or higher */
85 /* The PA instruction set variants. */
86 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20, pa20w = 25};
88 /* HP PA-RISC relocation types */
90 enum hppa_reloc_field_selector_type
110 R_HPPA_LTPSEL = 0x12,
114 /* /usr/include/reloc.h defines these to constants. We want to use
115 them in enums, so #undef them before we start using them. We might
116 be able to fix this another way by simply managing not to include
117 /usr/include/reloc.h, but currently GDB picks up these defines
144 /* for compatibility */
145 enum hppa_reloc_field_selector_type_alt
147 e_fsel = R_HPPA_FSEL,
148 e_lssel = R_HPPA_LSSEL,
149 e_rssel = R_HPPA_RSSEL,
150 e_lsel = R_HPPA_LSEL,
151 e_rsel = R_HPPA_RSEL,
152 e_ldsel = R_HPPA_LDSEL,
153 e_rdsel = R_HPPA_RDSEL,
154 e_lrsel = R_HPPA_LRSEL,
155 e_rrsel = R_HPPA_RRSEL,
156 e_nsel = R_HPPA_NSEL,
157 e_nlsel = R_HPPA_NLSEL,
158 e_nlrsel = R_HPPA_NLRSEL,
159 e_psel = R_HPPA_PSEL,
160 e_lpsel = R_HPPA_LPSEL,
161 e_rpsel = R_HPPA_RPSEL,
162 e_tsel = R_HPPA_TSEL,
163 e_ltsel = R_HPPA_LTSEL,
164 e_rtsel = R_HPPA_RTSEL,
165 e_ltpsel = R_HPPA_LTPSEL,
166 e_rtpsel = R_HPPA_RTPSEL
169 enum hppa_reloc_expr_type
179 /* for compatibility */
180 enum hppa_reloc_expr_type_alt
182 e_one = R_HPPA_E_ONE,
183 e_two = R_HPPA_E_TWO,
184 e_pcrel = R_HPPA_E_PCREL,
185 e_con = R_HPPA_E_CON,
186 e_plabel = R_HPPA_E_PLABEL,
191 /* Relocations for function calls must be accompanied by parameter
192 relocation bits. These bits describe exactly where the caller has
193 placed the function's arguments and where it expects to find a return
196 Both ELF and SOM encode this information within the addend field
197 of the call relocation. (Note this could break very badly if one
198 was to make a call like bl foo + 0x12345678).
200 The high order 10 bits contain parameter relocation information,
201 the low order 22 bits contain the constant offset. */
203 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
204 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
205 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
206 #define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
208 /* These macros get bit fields using HP's numbering (MSB = 0),
209 * but note that "MASK" assumes that the LSB bits are what's
213 #define GET_FIELD(X, FROM, TO) \
214 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
216 #define GET_BIT(X, WHICH) \
217 GET_FIELD (X, WHICH, WHICH)
222 #define CATENATE(X, XSIZE, Y, YSIZE) \
223 (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
226 CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
228 /* Some functions to manipulate PA instructions. */
230 /* NOTE: these use the HP convention that f{1} is the _left_ most
231 * bit (MSB) of f; they sometimes have to impose an assumption
232 * about the size of a field; and as far as I can tell, most
236 static INLINE unsigned long
240 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
243 static INLINE unsigned int
247 return CATENATE (GET_BIT (x, 2), 1, GET_FIELD (x, 0, 1), 2);
251 dis_assemble_3 (x, r)
255 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
258 static INLINE unsigned int
262 return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
265 static INLINE unsigned int
269 return CATENATE (CATENATE (y, 1, GET_BIT (x, 10), 1), 2,
270 GET_FIELD (x, 0, 9), 9);
274 dis_assemble_12 (as12, x, y)
278 *y = (as12 & 0x800) >> 11;
279 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
283 dis_assemble_16 (as16, x, wide)
292 /* Unusual 16-bit encoding. */
293 t1 = (as16 << 1) & 0xffff;
294 t2 = (as16 & 0x8000);
295 *x = t1 ^ t2 ^ (t2 >> 1) | (t2 >> 15);
299 /* Standard 14-bit encoding. */
300 t1 = (as16 << 1) & 0x3fff;
301 t2 = (as16 & 0x2000);
302 *x = t1 | (t2 >> 13);
306 static INLINE unsigned long
310 /* Depends on PSW W-bit !*/
314 temp = CATENATE (CATENATE (GET_BIT (y, 13), 1,
315 (GET_BIT (y, 13) ^ GET_BIT (x, 0)), 1), 2,
316 CATENATE ((GET_BIT (y, 13) ^ GET_BIT (x, 1)), 1,
317 GET_FIELD (y, 0, 12), 13), 14);
319 temp = CATENATE (CATENATE (GET_BIT (y, 13), 1, GET_BIT (y, 13), 1), 2,
320 CATENATE (GET_BIT (y, 13), 1, GET_FIELD (y, 0, 12), 13), 14);
322 return sign_extend (temp, 16);
326 static INLINE unsigned long
327 assemble_16a (x, y, z)
328 unsigned int x, y, z;
330 /* Depends on PSW W-bit !*/
334 temp = CATENATE (CATENATE (z, 1, (z ^ GET_BIT (x, 0)), 1), 2,
335 CATENATE ((z ^ GET_BIT (x, 1)), 1, y, 11), 12);
337 temp = CATENATE (CATENATE (z, 1, z, 1), 2, CATENATE (z, 1, y, 11), 12);
339 return sign_extend ((temp << 2), 16);
342 static INLINE unsigned long
343 assemble_17 (x, y, z)
344 unsigned int x, y, z;
348 temp = CATENATE (CATENATE (z, 1, x, 5), 6,
349 CATENATE (GET_BIT (y, 10), 1, GET_FIELD (y, 0, 9), 10), 11);
355 dis_assemble_17 (as17, x, y, z)
357 unsigned int *x, *y, *z;
360 *z = (as17 & 0x10000) >> 16;
361 *x = (as17 & 0x0f800) >> 11;
362 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
366 dis_assemble_22 (as22, a, b, c, d)
368 unsigned int *a, *b, *c, *d;
371 *d = (as22 & 0x200000) >> 21;
372 *a = (as22 & 0x1f0000) >> 16;
373 *b = (as22 & 0x0f800) >> 11;
374 *c = (((as22 & 0x00400) >> 10) | ((as22 & 0x3ff) << 1)) & 0x7ff;
377 static INLINE unsigned long
383 temp = ((x & 1) << 20) |
385 ((x & 0xc000) >> 7) |
386 ((x & 0x1f0000) >> 14) |
387 ((x & 0x003000) >> 12);
388 return temp & 0x1fffff;
391 static INLINE unsigned long
392 assemble_22 (a,b,c,d)
393 unsigned int a,b,c,d;
397 temp = CATENATE (CATENATE (d, 1, a, 5), 6,
398 CATENATE (b, 5, ELEVEN (c), 11), 16);
400 return sign_extend (temp, 22);
404 dis_assemble_21 (as21, x)
405 unsigned int as21, *x;
410 temp = (as21 & 0x100000) >> 20;
411 temp |= (as21 & 0x0ffe00) >> 8;
412 temp |= (as21 & 0x000180) << 7;
413 temp |= (as21 & 0x00007c) << 14;
414 temp |= (as21 & 0x000003) << 12;
418 static INLINE unsigned int
422 unsigned int len_ones;
429 len_ones = (len_ones << 1) | 1;
437 sign_unext (x, len, result)
439 unsigned int *result;
441 unsigned int len_ones;
443 len_ones = ones (len);
445 *result = x & len_ones;
448 static INLINE unsigned long
449 low_sign_extend (x, len)
452 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
456 low_sign_unext (x, len, result)
458 unsigned int *result;
463 unsigned int one_bit_at_len;
464 unsigned int len_ones;
466 len_ones = ones (len);
467 one_bit_at_len = 1 << (len - 1);
469 sign_unext (x, len, &temp);
470 sign = temp & one_bit_at_len;
473 rest = temp & (len_ones ^ one_bit_at_len);
476 *result = rest | sign;
479 /* Handle field selectors for PA instructions. */
481 static INLINE unsigned long
482 hppa_field_adjust (value, constant_value, r_field)
484 unsigned long constant_value;
485 unsigned short r_field;
489 case e_fsel: /* F : no change */
490 case e_nsel: /* N : no change */
491 value += constant_value;
494 case e_lssel: /* LS : if (bit 21) then add 0x800
495 arithmetic shift right 11 bits */
496 value += constant_value;
497 if (value & 0x00000400)
499 value = (value & 0xfffff800) >> 11;
502 case e_rssel: /* RS : Sign extend from bit 21 */
503 value += constant_value;
504 if (value & 0x00000400)
510 case e_lsel: /* L : Arithmetic shift right 11 bits */
511 case e_nlsel: /* NL : Arithmetic shift right 11 bits */
512 value += constant_value;
513 value = (value & 0xfffff800) >> 11;
516 case e_rsel: /* R : Set bits 0-20 to zero */
517 value += constant_value;
518 value = value & 0x7ff;
521 case e_ldsel: /* LD : Add 0x800, arithmetic shift
523 value += constant_value;
525 value = (value & 0xfffff800) >> 11;
528 case e_rdsel: /* RD : Set bits 0-20 to one */
529 value += constant_value;
533 case e_lrsel: /* LR : L with "rounded" constant */
534 case e_nlrsel: /* NLR : NL with "rounded" constant */
535 value = value + ((constant_value + 0x1000) & 0xffffe000);
536 value = (value & 0xfffff800) >> 11;
539 case e_rrsel: /* RR : R with "rounded" constant */
540 value = value + ((constant_value + 0x1000) & 0xffffe000);
541 value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
551 /* PA-RISC OPCODES */
552 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
554 /* FIXME: this list is incomplete. It should also be an enumerated
555 type rather than #defines. */
603 /* Given a machine instruction, return its format.
605 FIXME: opcodes which do not map to a known format
606 should return an error of some sort. */
609 bfd_hppa_insn2fmt (insn)
613 unsigned char op = get_opcode (insn);
654 /* This is a hack. Unfortunately, format 11 is already taken
655 and we're using integers rather than an enum, so it's hard
656 to describe the 10a format. */
666 if ((insn & 0x00008000) == 0x00008000)
682 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
685 static INLINE unsigned long
686 hppa_rebuild_insn (abfd, insn, value, r_format)
687 bfd *abfd ATTRIBUTE_UNUSED;
690 unsigned long r_format;
692 unsigned long const_part;
693 unsigned long rebuilt_part;
701 const_part = insn & 0xffffe002;
702 dis_assemble_12 (value, &w1, &w);
703 rebuilt_part = (w1 << 2) | w;
704 return const_part | rebuilt_part;
711 const_part = insn & 0xffffe002;
712 dis_assemble_12 (value, &w1, &w);
713 rebuilt_part = (w1 << 2) | w;
714 return const_part | rebuilt_part;
721 const_part = insn & 0xffffc000;
722 low_sign_unext (value, 14, &ext);
723 return const_part | ext;
730 const_part = insn & 0xffe0e002;
731 dis_assemble_17 (value, &w1, &w2, &w);
732 rebuilt_part = (w2 << 2) | (w1 << 16) | w;
733 return const_part | rebuilt_part;
740 const_part = insn & 0xffe00000;
741 dis_assemble_21 (value, &w);
742 return const_part | w;