import gdb-1999-08-30 snapshot
[deliverable/binutils-gdb.git] / bfd / libhppa.h
CommitLineData
252b5132 1/* HP PA-RISC SOM object file format: definitions internal to BFD.
5f771d47
ILT
2 Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 98, 1999
3 Free Software Foundation, Inc.
252b5132
RH
4
5 Contributed by the Center for Software Science at the
6 University of Utah (pa-gdb-bugs@cs.utah.edu).
7
8 This file is part of BFD, the Binary File Descriptor library.
9
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.
14
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.
19
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. */
23
24#ifndef _HPPA_H
25#define _HPPA_H
26
27#define BYTES_IN_WORD 4
28#define PA_PAGESIZE 0x1000
29
30#ifndef INLINE
31#ifdef __GNUC__
32#define INLINE inline
33#else
34#define INLINE
35#endif /* GNU C? */
36#endif /* INLINE */
37
38#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
39/* Declare the functions with the unused attribute to avoid warnings. */
40static INLINE unsigned int assemble_3 (unsigned int)
41 __attribute__ ((__unused__));
42static INLINE void dis_assemble_3 (unsigned int, unsigned int *)
43 __attribute__ ((__unused__));
44static INLINE unsigned int assemble_12 (unsigned int, unsigned int)
45 __attribute__ ((__unused__));
46static INLINE void dis_assemble_12 (unsigned int, unsigned int *,
47 unsigned int *)
48 __attribute__ ((__unused__));
49static INLINE unsigned long assemble_17 (unsigned int, unsigned int,
50 unsigned int)
51 __attribute__ ((__unused__));
52static INLINE void dis_assemble_17 (unsigned int, unsigned int *,
53 unsigned int *, unsigned int *)
54 __attribute__ ((__unused__));
55static INLINE unsigned long assemble_21 (unsigned int)
56 __attribute ((__unused__));
57static INLINE void dis_assemble_21 (unsigned int, unsigned int *)
58 __attribute__ ((__unused__));
59static INLINE unsigned long sign_extend (unsigned int, unsigned int)
60 __attribute__ ((__unused__));
61static INLINE unsigned int ones (int) __attribute ((__unused__));
62static INLINE void sign_unext (unsigned int, unsigned int, unsigned int *)
63 __attribute__ ((__unused__));
64static INLINE unsigned long low_sign_extend (unsigned int, unsigned int)
65 __attribute__ ((__unused__));
66static INLINE void low_sign_unext (unsigned int, unsigned int, unsigned int *)
67 __attribute__ ((__unused__));
68static INLINE unsigned long hppa_field_adjust (unsigned long, unsigned long,
69 unsigned short)
70 __attribute__ ((__unused__));
71static INLINE char bfd_hppa_insn2fmt (unsigned long)
72 __attribute__ ((__unused__));
73static INLINE unsigned long hppa_rebuild_insn (bfd *, unsigned long,
74 unsigned long, unsigned long)
75 __attribute__ ((__unused__));
76#endif /* gcc 2.7 or higher */
77
78
79/* The PA instruction set variants. */
80enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
81
82/* HP PA-RISC relocation types */
83
84enum hppa_reloc_field_selector_type
85 {
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,
1560fbe4
JL
103 R_HPPA_RTSEL = 0x11,
104 R_HPPA_LTPSEL = 0x12,
105 R_HPPA_RTPSEL = 0x13
252b5132
RH
106 };
107
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
137
138/* for compatibility */
139enum hppa_reloc_field_selector_type_alt
140 {
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,
1560fbe4
JL
158 e_rtsel = R_HPPA_RTSEL,
159 e_ltpsel = R_HPPA_LTPSEL,
160 e_rtpsel = R_HPPA_RTPSEL
252b5132
RH
161 };
162
163enum hppa_reloc_expr_type
164 {
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
171 };
172
173/* for compatibility */
174enum hppa_reloc_expr_type_alt
175 {
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
182 };
183
184
37afc161
JL
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.
189
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).
193
194 The high order 10 bits contain parameter relocation information,
195 the low order 22 bits contain the constant offset. */
196
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))
5ba624b0 200#define HPPA_WIDE (0) /* PSW W-bit, need to check! FIXME */
252b5132
RH
201
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.
205 */
206#ifndef GET_FIELD
207#define GET_FIELD(X, FROM, TO) \
208 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
209#endif
5ba624b0
JL
210#define GET_BIT(X, WHICH) \
211 GET_FIELD (X, WHICH, WHICH)
252b5132 212
5ba624b0 213#define MASK(SIZE) \
252b5132
RH
214 (~((-1) << SIZE))
215
5ba624b0
JL
216#define CATENATE(X, XSIZE, Y, YSIZE) \
217 (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
252b5132 218
5ba624b0
JL
219#define ELEVEN(X) \
220 CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
252b5132
RH
221
222/* Some functions to manipulate PA instructions. */
223
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.
228 */
229
230static INLINE unsigned long
231sign_extend (x, len)
232 unsigned int x, len;
233{
234 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
235}
236
237static INLINE unsigned int
238assemble_3 (x)
239 unsigned int x;
240{
5ba624b0 241 return CATENATE (GET_BIT (x, 2), 1, GET_FIELD (x, 0, 1), 2);
252b5132
RH
242}
243
244static INLINE void
245dis_assemble_3 (x, r)
246 unsigned int x;
247 unsigned int *r;
248{
249 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
250}
251
5ba624b0 252static INLINE unsigned int
252b5132
RH
253assemble_6 (x, y)
254 unsigned int x, y;
255{
256 return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
257}
258
259static INLINE unsigned int
260assemble_12 (x, y)
261 unsigned int x, y;
262{
5ba624b0
JL
263 return CATENATE (CATENATE (y, 1, GET_BIT (x, 10), 1), 2,
264 GET_FIELD (x, 0, 9), 9);
252b5132
RH
265}
266
267static INLINE void
268dis_assemble_12 (as12, x, y)
269 unsigned int as12;
270 unsigned int *x, *y;
271{
272 *y = (as12 & 0x800) >> 11;
273 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
274}
275
5ba624b0 276static INLINE unsigned long
252b5132
RH
277assemble_16 (x, y)
278 unsigned int x, y;
279{
280 /* Depends on PSW W-bit !*/
281 unsigned int temp;
282
5ba624b0
JL
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);
291
292 return sign_extend (temp, 16);
252b5132
RH
293}
294
295
5ba624b0 296static INLINE unsigned long
252b5132
RH
297assemble_16a (x, y, z)
298 unsigned int x, y, z;
299{
300 /* Depends on PSW W-bit !*/
301 unsigned int temp;
302
5ba624b0
JL
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);
308
309 return sign_extend ((temp << 2), 16);
252b5132
RH
310}
311
312static INLINE unsigned long
313assemble_17 (x, y, z)
314 unsigned int x, y, z;
315{
316 unsigned long temp;
252b5132 317
5ba624b0
JL
318 temp = CATENATE (CATENATE (z, 1, x, 5), 6,
319 CATENATE (GET_BIT (y, 10), 1, GET_FIELD (y, 0, 9), 10), 11);
252b5132
RH
320
321 return temp;
322}
323
324static INLINE void
325dis_assemble_17 (as17, x, y, z)
326 unsigned int as17;
327 unsigned int *x, *y, *z;
328{
329
330 *z = (as17 & 0x10000) >> 16;
331 *x = (as17 & 0x0f800) >> 11;
332 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
333}
334
335static INLINE unsigned long
336assemble_21 (x)
337 unsigned int x;
338{
339 unsigned long temp;
340
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;
347}
348
5ba624b0 349static INLINE unsigned long
252b5132
RH
350assemble_22 (a,b,c,d)
351 unsigned int a,b,c,d;
352{
353 unsigned long temp;
354
5ba624b0
JL
355 temp = CATENATE (CATENATE (d, 1, a, 5), 6,
356 CATENATE (b, 5, ELEVEN (c), 11), 16);
252b5132 357
5ba624b0 358 return sign_extend (temp, 22);
252b5132
RH
359}
360
361static INLINE void
362dis_assemble_21 (as21, x)
363 unsigned int as21, *x;
364{
365 unsigned long temp;
366
367
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;
374}
375
376static INLINE unsigned int
377ones (n)
378 int n;
379{
380 unsigned int len_ones;
381 int i;
382
383 i = 0;
384 len_ones = 0;
385 while (i < n)
386 {
387 len_ones = (len_ones << 1) | 1;
388 i++;
389 }
390
391 return len_ones;
392}
393
394static INLINE void
395sign_unext (x, len, result)
396 unsigned int x, len;
397 unsigned int *result;
398{
399 unsigned int len_ones;
400
401 len_ones = ones (len);
402
403 *result = x & len_ones;
404}
405
406static INLINE unsigned long
407low_sign_extend (x, len)
408 unsigned int x, len;
409{
410 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
411}
412
413static INLINE void
414low_sign_unext (x, len, result)
415 unsigned int x, len;
416 unsigned int *result;
417{
418 unsigned int temp;
419 unsigned int sign;
420 unsigned int rest;
421 unsigned int one_bit_at_len;
422 unsigned int len_ones;
423
424 len_ones = ones (len);
425 one_bit_at_len = 1 << (len - 1);
426
427 sign_unext (x, len, &temp);
428 sign = temp & one_bit_at_len;
429 sign >>= (len - 1);
430
431 rest = temp & (len_ones ^ one_bit_at_len);
432 rest <<= 1;
433
434 *result = rest | sign;
435}
436
437/* Handle field selectors for PA instructions. */
438
439static INLINE unsigned long
440hppa_field_adjust (value, constant_value, r_field)
441 unsigned long value;
442 unsigned long constant_value;
443 unsigned short r_field;
444{
445 switch (r_field)
446 {
5ba624b0 447 case e_fsel: /* F : no change */
252b5132
RH
448 case e_nsel: /* N : no change */
449 value += constant_value;
450 break;
451
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;
459
5ba624b0 460 case e_rssel: /* RS : Sign extend from bit 21 */
252b5132
RH
461 value += constant_value;
462 if (value & 0x00000400)
463 value |= 0xfffff800;
464 else
465 value &= 0x7ff;
466 break;
467
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;
473
5ba624b0 474 case e_rsel: /* R : Set bits 0-20 to zero */
252b5132
RH
475 value += constant_value;
476 value = value & 0x7ff;
477 break;
478
479 case e_ldsel: /* LD : Add 0x800, arithmetic shift
5ba624b0 480 right 11 bits */
252b5132
RH
481 value += constant_value;
482 value += 0x800;
483 value = (value & 0xfffff800) >> 11;
484 break;
485
5ba624b0 486 case e_rdsel: /* RD : Set bits 0-20 to one */
252b5132
RH
487 value += constant_value;
488 value |= 0xfffff800;
489 break;
490
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;
496
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;
501
502 default:
503 abort ();
504 }
505 return value;
506
507}
508
509/* PA-RISC OPCODES */
510#define get_opcode(insn) ((insn) & 0xfc000000) >> 26
511
512/* FIXME: this list is incomplete. It should also be an enumerated
513 type rather than #defines. */
514
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
533
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
546
547#define BL 0x3a
548#define BLE 0x39
549#define BE 0x38
550
551
552/* Given a machine instruction, return its format.
553
554 FIXME: opcodes which do not map to a known format
555 should return an error of some sort. */
556
557static INLINE char
558bfd_hppa_insn2fmt (insn)
559 unsigned long insn;
560{
561 char fmt = -1;
562 unsigned char op = get_opcode (insn);
563
564 switch (op)
565 {
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;
608 }
609 return fmt;
610}
611
612
613/* Insert VALUE into INSN using R_FORMAT to determine exactly what
614 bits to change. */
615
616static INLINE unsigned long
617hppa_rebuild_insn (abfd, insn, value, r_format)
5f771d47 618 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
619 unsigned long insn;
620 unsigned long value;
621 unsigned long r_format;
622{
623 unsigned long const_part;
624 unsigned long rebuilt_part;
625
626 switch (r_format)
627 {
628 case 11:
629 {
630 unsigned w1, w;
631
632 const_part = insn & 0xffffe002;
633 dis_assemble_12 (value, &w1, &w);
634 rebuilt_part = (w1 << 2) | w;
635 return const_part | rebuilt_part;
636 }
637
638 case 12:
639 {
640 unsigned w1, w;
641
642 const_part = insn & 0xffffe002;
643 dis_assemble_12 (value, &w1, &w);
644 rebuilt_part = (w1 << 2) | w;
645 return const_part | rebuilt_part;
646 }
647
648 case 14:
649 {
650 unsigned int ext;
651
652 const_part = insn & 0xffffc000;
653 low_sign_unext (value, 14, &ext);
654 return const_part | ext;
655 }
656
657 case 17:
658 {
659 unsigned w1, w2, w;
660
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;
665 }
666
667 case 21:
668 {
669 unsigned int w;
670
671 const_part = insn & 0xffe00000;
672 dis_assemble_21 (value, &w);
673 return const_part | w;
674 }
675
676 case 32:
677 const_part = 0;
678 return value;
679
680 default:
681 abort ();
682 }
683 return insn;
684}
685
686#endif /* _HPPA_H */
This page took 0.080319 seconds and 4 git commands to generate.