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 /* Relocations for function calls must be accompanied by parameter
181 relocation bits. These bits describe exactly where the caller has
182 placed the function's arguments and where it expects to find a return
185 Both ELF and SOM encode this information within the addend field
186 of the call relocation. (Note this could break very badly if one
187 was to make a call like bl foo + 0x12345678).
189 The high order 10 bits contain parameter relocation information,
190 the low order 22 bits contain the constant offset. */
192 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
193 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
194 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
195 #define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
197 /* These macros get bit fields using HP's numbering (MSB = 0),
198 * but note that "MASK" assumes that the LSB bits are what's
202 #define GET_FIELD(X, FROM, TO) \
203 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
205 #define GET_BIT( X, WHICH ) \
206 GET_FIELD( X, WHICH, WHICH )
208 #define MASK( SIZE ) \
211 #define CATENATE( X, XSIZE, Y, YSIZE ) \
212 (((X & MASK( XSIZE )) << YSIZE) | (Y & MASK( YSIZE )))
214 #define ELEVEN( X ) \
215 CATENATE( GET_BIT( X, 10 ), 1, GET_FIELD( X, 0, 9 ), 10)
217 /* Some functions to manipulate PA instructions. */
219 /* NOTE: these use the HP convention that f{1} is the _left_ most
220 * bit (MSB) of f; they sometimes have to impose an assumption
221 * about the size of a field; and as far as I can tell, most
225 static INLINE
unsigned long
229 return (int)(x
>> (len
- 1) ? (-1 << len
) | x
: x
);
232 static INLINE
unsigned int
236 return (((x
& 1) << 2) | ((x
& 6) >> 1)) & 7;
240 dis_assemble_3 (x
, r
)
244 *r
= (((x
& 4) >> 2) | ((x
& 3) << 1)) & 7;
247 static INLINE
unsigned int /* PA 2.0 */
251 return (((x
& 0x1) << 5) + (32 - (y
& 0x1f)));
254 static INLINE
unsigned int
258 return CATENATE( CATENATE( y
, 1,
259 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 /* PA 2.0 */
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 );
286 temp
= CATENATE( CATENATE( GET_BIT( y
, 13 ), 1,
287 GET_BIT( y
, 13 ), 1 ), 2,
288 CATENATE( GET_BIT( y
, 13 ), 1,
289 GET_FIELD( y
, 0, 12 ), 13 ), 14 );
292 return sign_extend( temp
, 16 );
296 static INLINE
unsigned long /* PA 2.0 */
297 assemble_16a (x
, y
, z
)
298 unsigned int x
, y
, z
;
300 /* Depends on PSW W-bit !*/
304 temp
= CATENATE( CATENATE( z
, 1,
305 (z
^GET_BIT( x
, 0 )), 1), 2,
307 CATENATE( (z
^GET_BIT( x
, 1 )), 1,
311 temp
= CATENATE( CATENATE( z
, 1,
318 return sign_extend( (temp
<< 2), 16 );
321 static INLINE
unsigned long
322 assemble_17 (x
, y
, z
)
323 unsigned int x
, y
, z
;
328 temp
= CATENATE( CATENATE( z
, q
,
330 CATENATE( GET_BIT( y
, 1 ), 1,
331 GET_FIELD( y
, 0, 9 ), 10), 11);
337 dis_assemble_17 (as17
, x
, y
, z
)
339 unsigned int *x
, *y
, *z
;
342 *z
= (as17
& 0x10000) >> 16;
343 *x
= (as17
& 0x0f800) >> 11;
344 *y
= (((as17
& 0x00400) >> 10) | ((as17
& 0x3ff) << 1)) & 0x7ff;
347 static INLINE
unsigned long
353 temp
= ((x
& 1) << 20) |
355 ((x
& 0xc000) >> 7) |
356 ((x
& 0x1f0000) >> 14) |
357 ((x
& 0x003000) >> 12);
358 return temp
& 0x1fffff;
361 static INLINE
unsigned long /* PA 2.0 */
362 assemble_22 (a
,b
,c
,d
)
363 unsigned int a
,b
,c
,d
;
367 temp
= CATENATE( CATENATE( d
, 1,
370 ELEVEN( c
), 11 ), 16 );
372 return sign_extend( temp
, 22 );
376 dis_assemble_21 (as21
, x
)
377 unsigned int as21
, *x
;
382 temp
= (as21
& 0x100000) >> 20;
383 temp
|= (as21
& 0x0ffe00) >> 8;
384 temp
|= (as21
& 0x000180) << 7;
385 temp
|= (as21
& 0x00007c) << 14;
386 temp
|= (as21
& 0x000003) << 12;
390 static INLINE
unsigned int
394 unsigned int len_ones
;
401 len_ones
= (len_ones
<< 1) | 1;
409 sign_unext (x
, len
, result
)
411 unsigned int *result
;
413 unsigned int len_ones
;
415 len_ones
= ones (len
);
417 *result
= x
& len_ones
;
420 static INLINE
unsigned long
421 low_sign_extend (x
, len
)
424 return (int)((x
& 0x1 ? (-1 << (len
- 1)) : 0) | x
>> 1);
428 low_sign_unext (x
, len
, result
)
430 unsigned int *result
;
435 unsigned int one_bit_at_len
;
436 unsigned int len_ones
;
438 len_ones
= ones (len
);
439 one_bit_at_len
= 1 << (len
- 1);
441 sign_unext (x
, len
, &temp
);
442 sign
= temp
& one_bit_at_len
;
445 rest
= temp
& (len_ones
^ one_bit_at_len
);
448 *result
= rest
| sign
;
451 /* Handle field selectors for PA instructions. */
453 static INLINE
unsigned long
454 hppa_field_adjust (value
, constant_value
, r_field
)
456 unsigned long constant_value
;
457 unsigned short r_field
;
461 case e_fsel
: /* F : no change */
462 case e_nsel
: /* N : no change */
463 value
+= constant_value
;
466 case e_lssel
: /* LS : if (bit 21) then add 0x800
467 arithmetic shift right 11 bits */
468 value
+= constant_value
;
469 if (value
& 0x00000400)
471 value
= (value
& 0xfffff800) >> 11;
474 case e_rssel
: /* RS : Sign extend from bit 21 */
475 value
+= constant_value
;
476 if (value
& 0x00000400)
482 case e_lsel
: /* L : Arithmetic shift right 11 bits */
483 case e_nlsel
: /* NL : Arithmetic shift right 11 bits */
484 value
+= constant_value
;
485 value
= (value
& 0xfffff800) >> 11;
488 case e_rsel
: /* R : Set bits 0-20 to zero */
489 value
+= constant_value
;
490 value
= value
& 0x7ff;
493 case e_ldsel
: /* LD : Add 0x800, arithmetic shift
495 value
+= constant_value
;
497 value
= (value
& 0xfffff800) >> 11;
500 case e_rdsel
: /* RD : Set bits 0-20 to one */
501 value
+= constant_value
;
505 case e_lrsel
: /* LR : L with "rounded" constant */
506 case e_nlrsel
: /* NLR : NL with "rounded" constant */
507 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
508 value
= (value
& 0xfffff800) >> 11;
511 case e_rrsel
: /* RR : R with "rounded" constant */
512 value
= value
+ ((constant_value
+ 0x1000) & 0xffffe000);
513 value
= (value
& 0x7ff) + constant_value
- ((constant_value
+ 0x1000) & 0xffffe000);
523 /* PA-RISC OPCODES */
524 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
526 /* FIXME: this list is incomplete. It should also be an enumerated
527 type rather than #defines. */
566 /* Given a machine instruction, return its format.
568 FIXME: opcodes which do not map to a known format
569 should return an error of some sort. */
572 bfd_hppa_insn2fmt (insn
)
576 unsigned char op
= get_opcode (insn
);
627 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
630 static INLINE
unsigned long
631 hppa_rebuild_insn (abfd
, insn
, value
, r_format
)
635 unsigned long r_format
;
637 unsigned long const_part
;
638 unsigned long rebuilt_part
;
646 const_part
= insn
& 0xffffe002;
647 dis_assemble_12 (value
, &w1
, &w
);
648 rebuilt_part
= (w1
<< 2) | w
;
649 return const_part
| rebuilt_part
;
656 const_part
= insn
& 0xffffe002;
657 dis_assemble_12 (value
, &w1
, &w
);
658 rebuilt_part
= (w1
<< 2) | w
;
659 return const_part
| rebuilt_part
;
666 const_part
= insn
& 0xffffc000;
667 low_sign_unext (value
, 14, &ext
);
668 return const_part
| ext
;
675 const_part
= insn
& 0xffe0e002;
676 dis_assemble_17 (value
, &w1
, &w2
, &w
);
677 rebuilt_part
= (w2
<< 2) | (w1
<< 16) | w
;
678 return const_part
| rebuilt_part
;
685 const_part
= insn
& 0xffe00000;
686 dis_assemble_21 (value
, &w
);
687 return const_part
| w
;