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 */
78 /* The PA instruction set variants. */
79 enum pa_arch
{pa10
= 10, pa11
= 11, pa20
= 20};
81 /* HP PA-RISC relocation types */
83 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
135 /* for compatibility */
136 enum hppa_reloc_field_selector_type_alt
138 e_fsel
= R_HPPA_FSEL
,
139 e_lssel
= R_HPPA_LSSEL
,
140 e_rssel
= R_HPPA_RSSEL
,
141 e_lsel
= R_HPPA_LSEL
,
142 e_rsel
= R_HPPA_RSEL
,
143 e_ldsel
= R_HPPA_LDSEL
,
144 e_rdsel
= R_HPPA_RDSEL
,
145 e_lrsel
= R_HPPA_LRSEL
,
146 e_rrsel
= R_HPPA_RRSEL
,
147 e_nsel
= R_HPPA_NSEL
,
148 e_nlsel
= R_HPPA_NLSEL
,
149 e_nlrsel
= R_HPPA_NLRSEL
,
150 e_psel
= R_HPPA_PSEL
,
151 e_lpsel
= R_HPPA_LPSEL
,
152 e_rpsel
= R_HPPA_RPSEL
,
153 e_tsel
= R_HPPA_TSEL
,
154 e_ltsel
= R_HPPA_LTSEL
,
155 e_rtsel
= R_HPPA_RTSEL
158 enum hppa_reloc_expr_type
168 /* for compatibility */
169 enum hppa_reloc_expr_type_alt
171 e_one
= R_HPPA_E_ONE
,
172 e_two
= R_HPPA_E_TWO
,
173 e_pcrel
= R_HPPA_E_PCREL
,
174 e_con
= R_HPPA_E_CON
,
175 e_plabel
= R_HPPA_E_PLABEL
,
180 #define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
182 /* These macros get bit fields using HP's numbering (MSB = 0),
183 * but note that "MASK" assumes that the LSB bits are what's
187 #define GET_FIELD(X, FROM, TO) \
188 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
190 #define GET_BIT(X, WHICH) \
191 GET_FIELD (X, WHICH, WHICH)
196 #define CATENATE(X, XSIZE, Y, YSIZE) \
197 (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
200 CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
202 /* Some functions to manipulate PA instructions. */
204 /* NOTE: these use the HP convention that f{1} is the _left_ most
205 * bit (MSB) of f; they sometimes have to impose an assumption
206 * about the size of a field; and as far as I can tell, most
210 static INLINE
unsigned long
214 return (int)(x
>> (len
- 1) ? (-1 << len
) | x
: x
);
217 static INLINE
unsigned int
221 return CATENATE (GET_BIT (x
, 2), 1, GET_FIELD (x
, 0, 1), 2);
225 dis_assemble_3 (x
, r
)
229 *r
= (((x
& 4) >> 2) | ((x
& 3) << 1)) & 7;
232 static INLINE
unsigned int
236 return (((x
& 0x1) << 5) + (32 - (y
& 0x1f)));
239 static INLINE
unsigned int
243 return CATENATE (CATENATE (y
, 1, GET_BIT (x
, 10), 1), 2,
244 GET_FIELD (x
, 0, 9), 9);
248 dis_assemble_12 (as12
, x
, y
)
252 *y
= (as12
& 0x800) >> 11;
253 *x
= ((as12
& 0x3ff) << 1) | ((as12
& 0x400) >> 10);
256 static INLINE
unsigned long
260 /* Depends on PSW W-bit !*/
264 temp
= CATENATE (CATENATE (GET_BIT (y
, 13), 1,
265 (GET_BIT (y
, 13) ^ GET_BIT (x
, 0)), 1), 2,
266 CATENATE ((GET_BIT (y
, 13) ^ GET_BIT (x
, 1)), 1,
267 GET_FIELD (y
, 0, 12), 13), 14);
269 temp
= CATENATE (CATENATE (GET_BIT (y
, 13), 1, GET_BIT (y
, 13), 1), 2,
270 CATENATE (GET_BIT (y
, 13), 1, GET_FIELD (y
, 0, 12), 13), 14);
272 return sign_extend (temp
, 16);
276 static INLINE
unsigned long
277 assemble_16a (x
, y
, z
)
278 unsigned int x
, y
, z
;
280 /* Depends on PSW W-bit !*/
284 temp
= CATENATE (CATENATE (z
, 1, (z
^ GET_BIT (x
, 0)), 1), 2,
285 CATENATE ((z
^ GET_BIT (x
, 1)), 1, y
, 11), 12);
287 temp
= CATENATE (CATENATE (z
, 1, z
, 1), 2, CATENATE (z
, 1, y
, 11), 12);
289 return sign_extend ((temp
<< 2), 16);
292 static INLINE
unsigned long
293 assemble_17 (x
, y
, z
)
294 unsigned int x
, y
, z
;
298 temp
= CATENATE (CATENATE (z
, 1, x
, 5), 6,
299 CATENATE (GET_BIT (y
, 10), 1, GET_FIELD (y
, 0, 9), 10), 11);
305 dis_assemble_17 (as17
, x
, y
, z
)
307 unsigned int *x
, *y
, *z
;
310 *z
= (as17
& 0x10000) >> 16;
311 *x
= (as17
& 0x0f800) >> 11;
312 *y
= (((as17
& 0x00400) >> 10) | ((as17
& 0x3ff) << 1)) & 0x7ff;
315 static INLINE
unsigned long
321 temp
= ((x
& 1) << 20) |
323 ((x
& 0xc000) >> 7) |
324 ((x
& 0x1f0000) >> 14) |
325 ((x
& 0x003000) >> 12);
326 return temp
& 0x1fffff;
329 static INLINE
unsigned long
330 assemble_22 (a
,b
,c
,d
)
331 unsigned int a
,b
,c
,d
;
335 temp
= CATENATE (CATENATE (d
, 1, a
, 5), 6,
336 CATENATE (b
, 5, ELEVEN (c
), 11), 16);
338 return sign_extend (temp
, 22);
342 dis_assemble_21 (as21
, x
)
343 unsigned int as21
, *x
;
348 temp
= (as21
& 0x100000) >> 20;
349 temp
|= (as21
& 0x0ffe00) >> 8;
350 temp
|= (as21
& 0x000180) << 7;
351 temp
|= (as21
& 0x00007c) << 14;
352 temp
|= (as21
& 0x000003) << 12;
356 static INLINE
unsigned int
360 unsigned int len_ones
;
367 len_ones
= (len_ones
<< 1) | 1;
375 sign_unext (x
, len
, result
)
377 unsigned int *result
;
379 unsigned int len_ones
;
381 len_ones
= ones (len
);
383 *result
= x
& len_ones
;
386 static INLINE
unsigned long
387 low_sign_extend (x
, len
)
390 return (int)((x
& 0x1 ? (-1 << (len
- 1)) : 0) | x
>> 1);
394 low_sign_unext (x
, len
, result
)
396 unsigned int *result
;
401 unsigned int one_bit_at_len
;
402 unsigned int len_ones
;
404 len_ones
= ones (len
);
405 one_bit_at_len
= 1 << (len
- 1);
407 sign_unext (x
, len
, &temp
);
408 sign
= temp
& one_bit_at_len
;
411 rest
= temp
& (len_ones
^ one_bit_at_len
);
414 *result
= rest
| sign
;
417 /* Handle field selectors for PA instructions. */
419 static INLINE
unsigned long
420 hppa_field_adjust (value
, constant_value
, r_field
)
422 unsigned long constant_value
;
423 unsigned short r_field
;
427 case e_fsel
: /* F : no change */
428 case e_nsel
: /* N : no change */
429 value
+= constant_value
;
432 case e_lssel
: /* LS : if (bit 21) then add 0x800
433 arithmetic shift right 11 bits */
434 value
+= constant_value
;
435 if (value
& 0x00000400)
437 value
= (value
& 0xfffff800) >> 11;
440 case e_rssel
: /* RS : Sign extend from bit 21 */
441 value
+= constant_value
;
442 if (value
& 0x00000400)
448 case e_lsel
: /* L : Arithmetic shift right 11 bits */
449 case e_nlsel
: /* NL : Arithmetic shift right 11 bits */
450 value
+= constant_value
;
451 value
= (value
& 0xfffff800) >> 11;
454 case e_rsel
: /* R : Set bits 0-20 to zero */
455 value
+= constant_value
;
456 value
= value
& 0x7ff;
459 case e_ldsel
: /* LD : Add 0x800, arithmetic shift
461 value
+= constant_value
;
463 value
= (value
& 0xfffff800) >> 11;
466 case e_rdsel
: /* RD : Set bits 0-20 to one */
467 value
+= constant_value
;
471 case e_lrsel
: /* LR : L with "rounded" constant */
472 case e_nlrsel
: /* NLR : NL with "rounded" constant */
473 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
474 value
= (value
& 0xfffff800) >> 11;
477 case e_rrsel
: /* RR : R with "rounded" constant */
478 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
479 value
= (value
& 0x7ff) + constant_value
- ((constant_value
+ 0x1000) & 0xffffe000);
489 /* PA-RISC OPCODES */
490 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
492 /* FIXME: this list is incomplete. It should also be an enumerated
493 type rather than #defines. */
532 /* Given a machine instruction, return its format.
534 FIXME: opcodes which do not map to a known format
535 should return an error of some sort. */
538 bfd_hppa_insn2fmt (insn
)
542 unsigned char op
= get_opcode (insn
);
593 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
596 static INLINE
unsigned long
597 hppa_rebuild_insn (abfd
, insn
, value
, r_format
)
601 unsigned long r_format
;
603 unsigned long const_part
;
604 unsigned long rebuilt_part
;
612 const_part
= insn
& 0xffffe002;
613 dis_assemble_12 (value
, &w1
, &w
);
614 rebuilt_part
= (w1
<< 2) | w
;
615 return const_part
| rebuilt_part
;
622 const_part
= insn
& 0xffffe002;
623 dis_assemble_12 (value
, &w1
, &w
);
624 rebuilt_part
= (w1
<< 2) | w
;
625 return const_part
| rebuilt_part
;
632 const_part
= insn
& 0xffffc000;
633 low_sign_unext (value
, 14, &ext
);
634 return const_part
| ext
;
641 const_part
= insn
& 0xffe0e002;
642 dis_assemble_17 (value
, &w1
, &w2
, &w
);
643 rebuilt_part
= (w2
<< 2) | (w1
<< 16) | w
;
644 return const_part
| rebuilt_part
;
651 const_part
= insn
& 0xffe00000;
652 dis_assemble_21 (value
, &w
);
653 return const_part
| w
;