* symbols.c (symbol_set_tc): Correct name.
[binutils.git] / bfd / libhppa.h
blob35b40efe86e7a4db8aa95822d8fffab454caf482
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. */
23 #ifndef _HPPA_H
24 #define _HPPA_H
26 #define BYTES_IN_WORD 4
27 #define PA_PAGESIZE 0x1000
29 #ifndef INLINE
30 #ifdef __GNUC__
31 #define INLINE inline
32 #else
33 #define INLINE
34 #endif /* GNU C? */
35 #endif /* INLINE */
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 *,
46 unsigned int *)
47 __attribute__ ((__unused__));
48 static INLINE unsigned long assemble_17 (unsigned int, unsigned int,
49 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,
68 unsigned short)
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
85 R_HPPA_FSEL = 0x0,
86 R_HPPA_LSSEL = 0x1,
87 R_HPPA_RSSEL = 0x2,
88 R_HPPA_LSEL = 0x3,
89 R_HPPA_RSEL = 0x4,
90 R_HPPA_LDSEL = 0x5,
91 R_HPPA_RDSEL = 0x6,
92 R_HPPA_LRSEL = 0x7,
93 R_HPPA_RRSEL = 0x8,
94 R_HPPA_NSEL = 0x9,
95 R_HPPA_NLSEL = 0xa,
96 R_HPPA_NLRSEL = 0xb,
97 R_HPPA_PSEL = 0xc,
98 R_HPPA_LPSEL = 0xd,
99 R_HPPA_RPSEL = 0xe,
100 R_HPPA_TSEL = 0xf,
101 R_HPPA_LTSEL = 0x10,
102 R_HPPA_RTSEL = 0x11
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
109 somewhere. */
110 #undef e_fsel
111 #undef e_lssel
112 #undef e_rssel
113 #undef e_lsel
114 #undef e_rsel
115 #undef e_ldsel
116 #undef e_rdsel
117 #undef e_lrsel
118 #undef e_rrsel
119 #undef e_nsel
120 #undef e_nlsel
121 #undef e_nlrsel
122 #undef e_psel
123 #undef e_lpsel
124 #undef e_rpsel
125 #undef e_tsel
126 #undef e_ltsel
127 #undef e_rtsel
128 #undef e_one
129 #undef e_two
130 #undef e_pcrel
131 #undef e_con
132 #undef e_plabel
133 #undef e_abs
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
160 R_HPPA_E_ONE = 0,
161 R_HPPA_E_TWO = 1,
162 R_HPPA_E_PCREL = 2,
163 R_HPPA_E_CON = 3,
164 R_HPPA_E_PLABEL = 7,
165 R_HPPA_E_ABS = 18
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,
176 e_abs = R_HPPA_E_ABS
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
183 value.
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
199 * wanted.
201 #ifndef GET_FIELD
202 #define GET_FIELD(X, FROM, TO) \
203 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
204 #endif
205 #define GET_BIT( X, WHICH ) \
206 GET_FIELD( X, WHICH, WHICH )
208 #define MASK( SIZE ) \
209 (~((-1) << 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
222 * aren't used.
225 static INLINE unsigned long
226 sign_extend (x, len)
227 unsigned int x, len;
229 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
232 static INLINE unsigned int
233 assemble_3 (x)
234 unsigned int x;
236 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
239 static INLINE void
240 dis_assemble_3 (x, r)
241 unsigned int x;
242 unsigned int *r;
244 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
247 static INLINE unsigned int /* PA 2.0 */
248 assemble_6 (x, y)
249 unsigned int x, y;
251 return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
254 static INLINE unsigned int
255 assemble_12 (x, y)
256 unsigned int x, y;
258 return CATENATE( CATENATE( y, 1,
259 GET_BIT( x, 10 ), 1), 2,
260 GET_FIELD( x, 0, 9 ), 9);
263 static INLINE void
264 dis_assemble_12 (as12, x, y)
265 unsigned int as12;
266 unsigned int *x, *y;
268 *y = (as12 & 0x800) >> 11;
269 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
272 static INLINE unsigned long /* PA 2.0 */
273 assemble_16 (x, y)
274 unsigned int x, y;
276 /* Depends on PSW W-bit !*/
277 unsigned int temp;
279 if( HPPA_WIDE ) {
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 else {
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 !*/
301 unsigned int temp;
303 if( HPPA_WIDE ) {
304 temp = CATENATE( CATENATE( z, 1,
305 (z^GET_BIT( x, 0 )), 1), 2,
307 CATENATE( (z^GET_BIT( x, 1 )), 1,
308 y, 11), 12);
310 else {
311 temp = CATENATE( CATENATE( z, 1,
312 z, 1), 2,
313 CATENATE( z, 1,
314 y, 11), 12);
318 return sign_extend( (temp << 2), 16 );
321 static INLINE unsigned long
322 assemble_17 (x, y, z)
323 unsigned int x, y, z;
325 unsigned long temp;
326 int q;
328 temp = CATENATE( CATENATE( z, q,
329 x, q), q,
330 CATENATE( GET_BIT( y, 1 ), 1,
331 GET_FIELD( y, 0, 9 ), 10), 11);
333 return temp;
336 static INLINE void
337 dis_assemble_17 (as17, x, y, z)
338 unsigned int as17;
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
348 assemble_21 (x)
349 unsigned int x;
351 unsigned long temp;
353 temp = ((x & 1) << 20) |
354 ((x & 0xffe) << 8) |
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;
365 unsigned long temp;
367 temp = CATENATE( CATENATE( d, 1,
368 a, 5 ), 6,
369 CATENATE( b, 5,
370 ELEVEN( c ), 11 ), 16 );
372 return sign_extend( temp, 22 );
375 static INLINE void
376 dis_assemble_21 (as21, x)
377 unsigned int as21, *x;
379 unsigned long temp;
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;
387 *x = temp;
390 static INLINE unsigned int
391 ones (n)
392 int n;
394 unsigned int len_ones;
395 int i;
397 i = 0;
398 len_ones = 0;
399 while (i < n)
401 len_ones = (len_ones << 1) | 1;
402 i++;
405 return len_ones;
408 static INLINE void
409 sign_unext (x, len, result)
410 unsigned int x, len;
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)
422 unsigned int x, len;
424 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
427 static INLINE void
428 low_sign_unext (x, len, result)
429 unsigned int x, len;
430 unsigned int *result;
432 unsigned int temp;
433 unsigned int sign;
434 unsigned int rest;
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;
443 sign >>= (len - 1);
445 rest = temp & (len_ones ^ one_bit_at_len);
446 rest <<= 1;
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)
455 unsigned long value;
456 unsigned long constant_value;
457 unsigned short r_field;
459 switch (r_field)
461 case e_fsel: /* F : no change */
462 case e_nsel: /* N : no change */
463 value += constant_value;
464 break;
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)
470 value += 0x800;
471 value = (value & 0xfffff800) >> 11;
472 break;
474 case e_rssel: /* RS : Sign extend from bit 21 */
475 value += constant_value;
476 if (value & 0x00000400)
477 value |= 0xfffff800;
478 else
479 value &= 0x7ff;
480 break;
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;
486 break;
488 case e_rsel: /* R : Set bits 0-20 to zero */
489 value += constant_value;
490 value = value & 0x7ff;
491 break;
493 case e_ldsel: /* LD : Add 0x800, arithmetic shift
494 right 11 bits */
495 value += constant_value;
496 value += 0x800;
497 value = (value & 0xfffff800) >> 11;
498 break;
500 case e_rdsel: /* RD : Set bits 0-20 to one */
501 value += constant_value;
502 value |= 0xfffff800;
503 break;
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;
509 break;
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);
514 break;
516 default:
517 abort ();
519 return value;
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. */
529 #define LDO 0x0d
530 #define LDB 0x10
531 #define LDH 0x11
532 #define LDW 0x12
533 #define LDWM 0x13
534 #define STB 0x18
535 #define STH 0x19
536 #define STW 0x1a
537 #define STWM 0x1b
538 #define COMICLR 0x24
539 #define SUBI 0x25
540 #define SUBIO 0x25
541 #define ADDIT 0x2c
542 #define ADDITO 0x2c
543 #define ADDI 0x2d
544 #define ADDIO 0x2d
545 #define LDIL 0x08
546 #define ADDIL 0x0a
548 #define MOVB 0x32
549 #define MOVIB 0x33
550 #define COMBT 0x20
551 #define COMBF 0x22
552 #define COMIBT 0x21
553 #define COMIBF 0x23
554 #define ADDBT 0x28
555 #define ADDBF 0x2a
556 #define ADDIBT 0x29
557 #define ADDIBF 0x2b
558 #define BVB 0x30
559 #define BB 0x31
561 #define BL 0x3a
562 #define BLE 0x39
563 #define BE 0x38
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. */
571 static INLINE char
572 bfd_hppa_insn2fmt (insn)
573 unsigned long insn;
575 char fmt = -1;
576 unsigned char op = get_opcode (insn);
578 switch (op)
580 case ADDI:
581 case ADDIT:
582 case SUBI:
583 fmt = 11;
584 break;
585 case MOVB:
586 case MOVIB:
587 case COMBT:
588 case COMBF:
589 case COMIBT:
590 case COMIBF:
591 case ADDBT:
592 case ADDBF:
593 case ADDIBT:
594 case ADDIBF:
595 case BVB:
596 case BB:
597 fmt = 12;
598 break;
599 case LDO:
600 case LDB:
601 case LDH:
602 case LDW:
603 case LDWM:
604 case STB:
605 case STH:
606 case STW:
607 case STWM:
608 fmt = 14;
609 break;
610 case BL:
611 case BE:
612 case BLE:
613 fmt = 17;
614 break;
615 case LDIL:
616 case ADDIL:
617 fmt = 21;
618 break;
619 default:
620 fmt = 32;
621 break;
623 return fmt;
627 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
628 bits to change. */
630 static INLINE unsigned long
631 hppa_rebuild_insn (abfd, insn, value, r_format)
632 bfd *abfd;
633 unsigned long insn;
634 unsigned long value;
635 unsigned long r_format;
637 unsigned long const_part;
638 unsigned long rebuilt_part;
640 switch (r_format)
642 case 11:
644 unsigned w1, w;
646 const_part = insn & 0xffffe002;
647 dis_assemble_12 (value, &w1, &w);
648 rebuilt_part = (w1 << 2) | w;
649 return const_part | rebuilt_part;
652 case 12:
654 unsigned w1, w;
656 const_part = insn & 0xffffe002;
657 dis_assemble_12 (value, &w1, &w);
658 rebuilt_part = (w1 << 2) | w;
659 return const_part | rebuilt_part;
662 case 14:
664 unsigned int ext;
666 const_part = insn & 0xffffc000;
667 low_sign_unext (value, 14, &ext);
668 return const_part | ext;
671 case 17:
673 unsigned w1, w2, w;
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;
681 case 21:
683 unsigned int w;
685 const_part = insn & 0xffe00000;
686 dis_assemble_21 (value, &w);
687 return const_part | w;
690 case 32:
691 const_part = 0;
692 return value;
694 default:
695 abort ();
697 return insn;
700 #endif /* _HPPA_H */