1999-09-13 Donn Terry <donn@interix.com>
[binutils.git] / bfd / libhppa.h
blob4ce82ea4e2ef189e1b7cf252312831ce1f24f358
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. */
24 #ifndef _HPPA_H
25 #define _HPPA_H
27 #define BYTES_IN_WORD 4
28 #define PA_PAGESIZE 0x1000
30 #ifndef INLINE
31 #ifdef __GNUC__
32 #define INLINE inline
33 #else
34 #define INLINE
35 #endif /* GNU C? */
36 #endif /* INLINE */
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 *,
47 unsigned int *)
48 __attribute__ ((__unused__));
49 static INLINE unsigned long assemble_17 (unsigned int, unsigned int,
50 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,
69 unsigned short)
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
86 R_HPPA_FSEL = 0x0,
87 R_HPPA_LSSEL = 0x1,
88 R_HPPA_RSSEL = 0x2,
89 R_HPPA_LSEL = 0x3,
90 R_HPPA_RSEL = 0x4,
91 R_HPPA_LDSEL = 0x5,
92 R_HPPA_RDSEL = 0x6,
93 R_HPPA_LRSEL = 0x7,
94 R_HPPA_RRSEL = 0x8,
95 R_HPPA_NSEL = 0x9,
96 R_HPPA_NLSEL = 0xa,
97 R_HPPA_NLRSEL = 0xb,
98 R_HPPA_PSEL = 0xc,
99 R_HPPA_LPSEL = 0xd,
100 R_HPPA_RPSEL = 0xe,
101 R_HPPA_TSEL = 0xf,
102 R_HPPA_LTSEL = 0x10,
103 R_HPPA_RTSEL = 0x11,
104 R_HPPA_LTPSEL = 0x12,
105 R_HPPA_RTPSEL = 0x13
108 /* /usr/include/reloc.h defines these to constants. We want to use
109 them in enums, so #undef them before we start using them. We might
110 be able to fix this another way by simply managing not to include
111 /usr/include/reloc.h, but currently GDB picks up these defines
112 somewhere. */
113 #undef e_fsel
114 #undef e_lssel
115 #undef e_rssel
116 #undef e_lsel
117 #undef e_rsel
118 #undef e_ldsel
119 #undef e_rdsel
120 #undef e_lrsel
121 #undef e_rrsel
122 #undef e_nsel
123 #undef e_nlsel
124 #undef e_nlrsel
125 #undef e_psel
126 #undef e_lpsel
127 #undef e_rpsel
128 #undef e_tsel
129 #undef e_ltsel
130 #undef e_rtsel
131 #undef e_one
132 #undef e_two
133 #undef e_pcrel
134 #undef e_con
135 #undef e_plabel
136 #undef e_abs
138 /* for compatibility */
139 enum hppa_reloc_field_selector_type_alt
141 e_fsel = R_HPPA_FSEL,
142 e_lssel = R_HPPA_LSSEL,
143 e_rssel = R_HPPA_RSSEL,
144 e_lsel = R_HPPA_LSEL,
145 e_rsel = R_HPPA_RSEL,
146 e_ldsel = R_HPPA_LDSEL,
147 e_rdsel = R_HPPA_RDSEL,
148 e_lrsel = R_HPPA_LRSEL,
149 e_rrsel = R_HPPA_RRSEL,
150 e_nsel = R_HPPA_NSEL,
151 e_nlsel = R_HPPA_NLSEL,
152 e_nlrsel = R_HPPA_NLRSEL,
153 e_psel = R_HPPA_PSEL,
154 e_lpsel = R_HPPA_LPSEL,
155 e_rpsel = R_HPPA_RPSEL,
156 e_tsel = R_HPPA_TSEL,
157 e_ltsel = R_HPPA_LTSEL,
158 e_rtsel = R_HPPA_RTSEL,
159 e_ltpsel = R_HPPA_LTPSEL,
160 e_rtpsel = R_HPPA_RTPSEL
163 enum hppa_reloc_expr_type
165 R_HPPA_E_ONE = 0,
166 R_HPPA_E_TWO = 1,
167 R_HPPA_E_PCREL = 2,
168 R_HPPA_E_CON = 3,
169 R_HPPA_E_PLABEL = 7,
170 R_HPPA_E_ABS = 18
173 /* for compatibility */
174 enum hppa_reloc_expr_type_alt
176 e_one = R_HPPA_E_ONE,
177 e_two = R_HPPA_E_TWO,
178 e_pcrel = R_HPPA_E_PCREL,
179 e_con = R_HPPA_E_CON,
180 e_plabel = R_HPPA_E_PLABEL,
181 e_abs = R_HPPA_E_ABS
185 /* Relocations for function calls must be accompanied by parameter
186 relocation bits. These bits describe exactly where the caller has
187 placed the function's arguments and where it expects to find a return
188 value.
190 Both ELF and SOM encode this information within the addend field
191 of the call relocation. (Note this could break very badly if one
192 was to make a call like bl foo + 0x12345678).
194 The high order 10 bits contain parameter relocation information,
195 the low order 22 bits contain the constant offset. */
197 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
198 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
199 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
200 #define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
202 /* These macros get bit fields using HP's numbering (MSB = 0),
203 * but note that "MASK" assumes that the LSB bits are what's
204 * wanted.
206 #ifndef GET_FIELD
207 #define GET_FIELD(X, FROM, TO) \
208 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
209 #endif
210 #define GET_BIT(X, WHICH) \
211 GET_FIELD (X, WHICH, WHICH)
213 #define MASK(SIZE) \
214 (~((-1) << SIZE))
216 #define CATENATE(X, XSIZE, Y, YSIZE) \
217 (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
219 #define ELEVEN(X) \
220 CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
222 /* Some functions to manipulate PA instructions. */
224 /* NOTE: these use the HP convention that f{1} is the _left_ most
225 * bit (MSB) of f; they sometimes have to impose an assumption
226 * about the size of a field; and as far as I can tell, most
227 * aren't used.
230 static INLINE unsigned long
231 sign_extend (x, len)
232 unsigned int x, len;
234 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
237 static INLINE unsigned int
238 assemble_3 (x)
239 unsigned int x;
241 return CATENATE (GET_BIT (x, 2), 1, GET_FIELD (x, 0, 1), 2);
244 static INLINE void
245 dis_assemble_3 (x, r)
246 unsigned int x;
247 unsigned int *r;
249 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
252 static INLINE unsigned int
253 assemble_6 (x, y)
254 unsigned int x, y;
256 return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
259 static INLINE unsigned int
260 assemble_12 (x, y)
261 unsigned int x, y;
263 return CATENATE (CATENATE (y, 1, GET_BIT (x, 10), 1), 2,
264 GET_FIELD (x, 0, 9), 9);
267 static INLINE void
268 dis_assemble_12 (as12, x, y)
269 unsigned int as12;
270 unsigned int *x, *y;
272 *y = (as12 & 0x800) >> 11;
273 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
276 static INLINE unsigned long
277 assemble_16 (x, y)
278 unsigned int x, y;
280 /* Depends on PSW W-bit !*/
281 unsigned int temp;
283 if (HPPA_WIDE)
284 temp = CATENATE (CATENATE (GET_BIT (y, 13), 1,
285 (GET_BIT (y, 13) ^ GET_BIT (x, 0)), 1), 2,
286 CATENATE ((GET_BIT (y, 13) ^ GET_BIT (x, 1)), 1,
287 GET_FIELD (y, 0, 12), 13), 14);
288 else
289 temp = CATENATE (CATENATE (GET_BIT (y, 13), 1, GET_BIT (y, 13), 1), 2,
290 CATENATE (GET_BIT (y, 13), 1, GET_FIELD (y, 0, 12), 13), 14);
292 return sign_extend (temp, 16);
296 static INLINE unsigned long
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, (z ^ GET_BIT (x, 0)), 1), 2,
305 CATENATE ((z ^ GET_BIT (x, 1)), 1, y, 11), 12);
306 else
307 temp = CATENATE (CATENATE (z, 1, z, 1), 2, CATENATE (z, 1, y, 11), 12);
309 return sign_extend ((temp << 2), 16);
312 static INLINE unsigned long
313 assemble_17 (x, y, z)
314 unsigned int x, y, z;
316 unsigned long temp;
318 temp = CATENATE (CATENATE (z, 1, x, 5), 6,
319 CATENATE (GET_BIT (y, 10), 1, GET_FIELD (y, 0, 9), 10), 11);
321 return temp;
324 static INLINE void
325 dis_assemble_17 (as17, x, y, z)
326 unsigned int as17;
327 unsigned int *x, *y, *z;
330 *z = (as17 & 0x10000) >> 16;
331 *x = (as17 & 0x0f800) >> 11;
332 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
335 static INLINE unsigned long
336 assemble_21 (x)
337 unsigned int x;
339 unsigned long temp;
341 temp = ((x & 1) << 20) |
342 ((x & 0xffe) << 8) |
343 ((x & 0xc000) >> 7) |
344 ((x & 0x1f0000) >> 14) |
345 ((x & 0x003000) >> 12);
346 return temp & 0x1fffff;
349 static INLINE unsigned long
350 assemble_22 (a,b,c,d)
351 unsigned int a,b,c,d;
353 unsigned long temp;
355 temp = CATENATE (CATENATE (d, 1, a, 5), 6,
356 CATENATE (b, 5, ELEVEN (c), 11), 16);
358 return sign_extend (temp, 22);
361 static INLINE void
362 dis_assemble_21 (as21, x)
363 unsigned int as21, *x;
365 unsigned long temp;
368 temp = (as21 & 0x100000) >> 20;
369 temp |= (as21 & 0x0ffe00) >> 8;
370 temp |= (as21 & 0x000180) << 7;
371 temp |= (as21 & 0x00007c) << 14;
372 temp |= (as21 & 0x000003) << 12;
373 *x = temp;
376 static INLINE unsigned int
377 ones (n)
378 int n;
380 unsigned int len_ones;
381 int i;
383 i = 0;
384 len_ones = 0;
385 while (i < n)
387 len_ones = (len_ones << 1) | 1;
388 i++;
391 return len_ones;
394 static INLINE void
395 sign_unext (x, len, result)
396 unsigned int x, len;
397 unsigned int *result;
399 unsigned int len_ones;
401 len_ones = ones (len);
403 *result = x & len_ones;
406 static INLINE unsigned long
407 low_sign_extend (x, len)
408 unsigned int x, len;
410 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
413 static INLINE void
414 low_sign_unext (x, len, result)
415 unsigned int x, len;
416 unsigned int *result;
418 unsigned int temp;
419 unsigned int sign;
420 unsigned int rest;
421 unsigned int one_bit_at_len;
422 unsigned int len_ones;
424 len_ones = ones (len);
425 one_bit_at_len = 1 << (len - 1);
427 sign_unext (x, len, &temp);
428 sign = temp & one_bit_at_len;
429 sign >>= (len - 1);
431 rest = temp & (len_ones ^ one_bit_at_len);
432 rest <<= 1;
434 *result = rest | sign;
437 /* Handle field selectors for PA instructions. */
439 static INLINE unsigned long
440 hppa_field_adjust (value, constant_value, r_field)
441 unsigned long value;
442 unsigned long constant_value;
443 unsigned short r_field;
445 switch (r_field)
447 case e_fsel: /* F : no change */
448 case e_nsel: /* N : no change */
449 value += constant_value;
450 break;
452 case e_lssel: /* LS : if (bit 21) then add 0x800
453 arithmetic shift right 11 bits */
454 value += constant_value;
455 if (value & 0x00000400)
456 value += 0x800;
457 value = (value & 0xfffff800) >> 11;
458 break;
460 case e_rssel: /* RS : Sign extend from bit 21 */
461 value += constant_value;
462 if (value & 0x00000400)
463 value |= 0xfffff800;
464 else
465 value &= 0x7ff;
466 break;
468 case e_lsel: /* L : Arithmetic shift right 11 bits */
469 case e_nlsel: /* NL : Arithmetic shift right 11 bits */
470 value += constant_value;
471 value = (value & 0xfffff800) >> 11;
472 break;
474 case e_rsel: /* R : Set bits 0-20 to zero */
475 value += constant_value;
476 value = value & 0x7ff;
477 break;
479 case e_ldsel: /* LD : Add 0x800, arithmetic shift
480 right 11 bits */
481 value += constant_value;
482 value += 0x800;
483 value = (value & 0xfffff800) >> 11;
484 break;
486 case e_rdsel: /* RD : Set bits 0-20 to one */
487 value += constant_value;
488 value |= 0xfffff800;
489 break;
491 case e_lrsel: /* LR : L with "rounded" constant */
492 case e_nlrsel: /* NLR : NL with "rounded" constant */
493 value = value + ((constant_value + 0x1000) & 0xffffe000);
494 value = (value & 0xfffff800) >> 11;
495 break;
497 case e_rrsel: /* RR : R with "rounded" constant */
498 value = value + ((constant_value + 0x1000) & 0xffffe000);
499 value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
500 break;
502 default:
503 abort ();
505 return value;
509 /* PA-RISC OPCODES */
510 #define get_opcode(insn) ((insn) & 0xfc000000) >> 26
512 /* FIXME: this list is incomplete. It should also be an enumerated
513 type rather than #defines. */
515 #define LDO 0x0d
516 #define LDB 0x10
517 #define LDH 0x11
518 #define LDW 0x12
519 #define LDWM 0x13
520 #define STB 0x18
521 #define STH 0x19
522 #define STW 0x1a
523 #define STWM 0x1b
524 #define COMICLR 0x24
525 #define SUBI 0x25
526 #define SUBIO 0x25
527 #define ADDIT 0x2c
528 #define ADDITO 0x2c
529 #define ADDI 0x2d
530 #define ADDIO 0x2d
531 #define LDIL 0x08
532 #define ADDIL 0x0a
534 #define MOVB 0x32
535 #define MOVIB 0x33
536 #define COMBT 0x20
537 #define COMBF 0x22
538 #define COMIBT 0x21
539 #define COMIBF 0x23
540 #define ADDBT 0x28
541 #define ADDBF 0x2a
542 #define ADDIBT 0x29
543 #define ADDIBF 0x2b
544 #define BVB 0x30
545 #define BB 0x31
547 #define BL 0x3a
548 #define BLE 0x39
549 #define BE 0x38
552 /* Given a machine instruction, return its format.
554 FIXME: opcodes which do not map to a known format
555 should return an error of some sort. */
557 static INLINE char
558 bfd_hppa_insn2fmt (insn)
559 unsigned long insn;
561 char fmt = -1;
562 unsigned char op = get_opcode (insn);
564 switch (op)
566 case ADDI:
567 case ADDIT:
568 case SUBI:
569 fmt = 11;
570 break;
571 case MOVB:
572 case MOVIB:
573 case COMBT:
574 case COMBF:
575 case COMIBT:
576 case COMIBF:
577 case ADDBT:
578 case ADDBF:
579 case ADDIBT:
580 case ADDIBF:
581 case BVB:
582 case BB:
583 fmt = 12;
584 break;
585 case LDO:
586 case LDB:
587 case LDH:
588 case LDW:
589 case LDWM:
590 case STB:
591 case STH:
592 case STW:
593 case STWM:
594 fmt = 14;
595 break;
596 case BL:
597 case BE:
598 case BLE:
599 fmt = 17;
600 break;
601 case LDIL:
602 case ADDIL:
603 fmt = 21;
604 break;
605 default:
606 fmt = 32;
607 break;
609 return fmt;
613 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
614 bits to change. */
616 static INLINE unsigned long
617 hppa_rebuild_insn (abfd, insn, value, r_format)
618 bfd *abfd ATTRIBUTE_UNUSED;
619 unsigned long insn;
620 unsigned long value;
621 unsigned long r_format;
623 unsigned long const_part;
624 unsigned long rebuilt_part;
626 switch (r_format)
628 case 11:
630 unsigned w1, w;
632 const_part = insn & 0xffffe002;
633 dis_assemble_12 (value, &w1, &w);
634 rebuilt_part = (w1 << 2) | w;
635 return const_part | rebuilt_part;
638 case 12:
640 unsigned w1, w;
642 const_part = insn & 0xffffe002;
643 dis_assemble_12 (value, &w1, &w);
644 rebuilt_part = (w1 << 2) | w;
645 return const_part | rebuilt_part;
648 case 14:
650 unsigned int ext;
652 const_part = insn & 0xffffc000;
653 low_sign_unext (value, 14, &ext);
654 return const_part | ext;
657 case 17:
659 unsigned w1, w2, w;
661 const_part = insn & 0xffe0e002;
662 dis_assemble_17 (value, &w1, &w2, &w);
663 rebuilt_part = (w2 << 2) | (w1 << 16) | w;
664 return const_part | rebuilt_part;
667 case 21:
669 unsigned int w;
671 const_part = insn & 0xffe00000;
672 dis_assemble_21 (value, &w);
673 return const_part | w;
676 case 32:
677 const_part = 0;
678 return value;
680 default:
681 abort ();
683 return insn;
686 #endif /* _HPPA_H */