19990502 sourceware import
[deliverable/binutils-gdb.git] / bfd / libhppa.h
CommitLineData
252b5132
RH
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.
3
4 Contributed by the Center for Software Science at the
5 University of Utah (pa-gdb-bugs@cs.utah.edu).
6
7 This file is part of BFD, the Binary File Descriptor library.
8
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.
13
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.
18
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. */
22
23#ifndef _HPPA_H
24#define _HPPA_H
25
26#define BYTES_IN_WORD 4
27#define PA_PAGESIZE 0x1000
28
29#ifndef INLINE
30#ifdef __GNUC__
31#define INLINE inline
32#else
33#define INLINE
34#endif /* GNU C? */
35#endif /* INLINE */
36
37#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
38/* Declare the functions with the unused attribute to avoid warnings. */
39static INLINE unsigned int assemble_3 (unsigned int)
40 __attribute__ ((__unused__));
41static INLINE void dis_assemble_3 (unsigned int, unsigned int *)
42 __attribute__ ((__unused__));
43static INLINE unsigned int assemble_12 (unsigned int, unsigned int)
44 __attribute__ ((__unused__));
45static INLINE void dis_assemble_12 (unsigned int, unsigned int *,
46 unsigned int *)
47 __attribute__ ((__unused__));
48static INLINE unsigned long assemble_17 (unsigned int, unsigned int,
49 unsigned int)
50 __attribute__ ((__unused__));
51static INLINE void dis_assemble_17 (unsigned int, unsigned int *,
52 unsigned int *, unsigned int *)
53 __attribute__ ((__unused__));
54static INLINE unsigned long assemble_21 (unsigned int)
55 __attribute ((__unused__));
56static INLINE void dis_assemble_21 (unsigned int, unsigned int *)
57 __attribute__ ((__unused__));
58static INLINE unsigned long sign_extend (unsigned int, unsigned int)
59 __attribute__ ((__unused__));
60static INLINE unsigned int ones (int) __attribute ((__unused__));
61static INLINE void sign_unext (unsigned int, unsigned int, unsigned int *)
62 __attribute__ ((__unused__));
63static INLINE unsigned long low_sign_extend (unsigned int, unsigned int)
64 __attribute__ ((__unused__));
65static INLINE void low_sign_unext (unsigned int, unsigned int, unsigned int *)
66 __attribute__ ((__unused__));
67static INLINE unsigned long hppa_field_adjust (unsigned long, unsigned long,
68 unsigned short)
69 __attribute__ ((__unused__));
70static INLINE char bfd_hppa_insn2fmt (unsigned long)
71 __attribute__ ((__unused__));
72static INLINE unsigned long hppa_rebuild_insn (bfd *, unsigned long,
73 unsigned long, unsigned long)
74 __attribute__ ((__unused__));
75#endif /* gcc 2.7 or higher */
76
77
78/* The PA instruction set variants. */
79enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
80
81/* HP PA-RISC relocation types */
82
83enum hppa_reloc_field_selector_type
84 {
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
103 };
104
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
134
135/* for compatibility */
136enum hppa_reloc_field_selector_type_alt
137 {
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
156 };
157
158enum hppa_reloc_expr_type
159 {
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
166 };
167
168/* for compatibility */
169enum hppa_reloc_expr_type_alt
170 {
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
177 };
178
179
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.
184
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).
188
189 The high order 10 bits contain parameter relocation information,
190 the low order 22 bits contain the constant offset. */
191
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 */
196
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.
200 */
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 )
207
208#define MASK( SIZE ) \
209 (~((-1) << SIZE))
210
211#define CATENATE( X, XSIZE, Y, YSIZE ) \
212 (((X & MASK( XSIZE )) << YSIZE) | (Y & MASK( YSIZE )))
213
214#define ELEVEN( X ) \
215 CATENATE( GET_BIT( X, 10 ), 1, GET_FIELD( X, 0, 9 ), 10)
216
217/* Some functions to manipulate PA instructions. */
218
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.
223 */
224
225static INLINE unsigned long
226sign_extend (x, len)
227 unsigned int x, len;
228{
229 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
230}
231
232static INLINE unsigned int
233assemble_3 (x)
234 unsigned int x;
235{
236 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
237}
238
239static INLINE void
240dis_assemble_3 (x, r)
241 unsigned int x;
242 unsigned int *r;
243{
244 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
245}
246
247static INLINE unsigned int /* PA 2.0 */
248assemble_6 (x, y)
249 unsigned int x, y;
250{
251 return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
252}
253
254static INLINE unsigned int
255assemble_12 (x, y)
256 unsigned int x, y;
257{
258 return CATENATE( CATENATE( y, 1,
259 GET_BIT( x, 10 ), 1), 2,
260 GET_FIELD( x, 0, 9 ), 9);
261}
262
263static INLINE void
264dis_assemble_12 (as12, x, y)
265 unsigned int as12;
266 unsigned int *x, *y;
267{
268 *y = (as12 & 0x800) >> 11;
269 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
270}
271
272static INLINE unsigned long /* PA 2.0 */
273assemble_16 (x, y)
274 unsigned int x, y;
275{
276 /* Depends on PSW W-bit !*/
277 unsigned int temp;
278
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 );
284 }
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 );
290 }
291
292 return sign_extend( temp, 16 );
293}
294
295
296static INLINE unsigned long /* PA 2.0 */
297assemble_16a (x, y, z)
298 unsigned int x, y, z;
299{
300 /* Depends on PSW W-bit !*/
301 unsigned int temp;
302
303 if( HPPA_WIDE ) {
304 temp = CATENATE( CATENATE( z, 1,
305 (z^GET_BIT( x, 0 )), 1), 2,
306
307 CATENATE( (z^GET_BIT( x, 1 )), 1,
308 y, 11), 12);
309 }
310 else {
311 temp = CATENATE( CATENATE( z, 1,
312 z, 1), 2,
313 CATENATE( z, 1,
314 y, 11), 12);
315
316 }
317
318 return sign_extend( (temp << 2), 16 );
319}
320
321static INLINE unsigned long
322assemble_17 (x, y, z)
323 unsigned int x, y, z;
324{
325 unsigned long temp;
326 int q;
327
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);
332
333 return temp;
334}
335
336static INLINE void
337dis_assemble_17 (as17, x, y, z)
338 unsigned int as17;
339 unsigned int *x, *y, *z;
340{
341
342 *z = (as17 & 0x10000) >> 16;
343 *x = (as17 & 0x0f800) >> 11;
344 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
345}
346
347static INLINE unsigned long
348assemble_21 (x)
349 unsigned int x;
350{
351 unsigned long temp;
352
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;
359}
360
361static INLINE unsigned long /* PA 2.0 */
362assemble_22 (a,b,c,d)
363 unsigned int a,b,c,d;
364{
365 unsigned long temp;
366
367 temp = CATENATE( CATENATE( d, 1,
368 a, 5 ), 6,
369 CATENATE( b, 5,
370 ELEVEN( c ), 11 ), 16 );
371
372 return sign_extend( temp, 22 );
373}
374
375static INLINE void
376dis_assemble_21 (as21, x)
377 unsigned int as21, *x;
378{
379 unsigned long temp;
380
381
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;
388}
389
390static INLINE unsigned int
391ones (n)
392 int n;
393{
394 unsigned int len_ones;
395 int i;
396
397 i = 0;
398 len_ones = 0;
399 while (i < n)
400 {
401 len_ones = (len_ones << 1) | 1;
402 i++;
403 }
404
405 return len_ones;
406}
407
408static INLINE void
409sign_unext (x, len, result)
410 unsigned int x, len;
411 unsigned int *result;
412{
413 unsigned int len_ones;
414
415 len_ones = ones (len);
416
417 *result = x & len_ones;
418}
419
420static INLINE unsigned long
421low_sign_extend (x, len)
422 unsigned int x, len;
423{
424 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
425}
426
427static INLINE void
428low_sign_unext (x, len, result)
429 unsigned int x, len;
430 unsigned int *result;
431{
432 unsigned int temp;
433 unsigned int sign;
434 unsigned int rest;
435 unsigned int one_bit_at_len;
436 unsigned int len_ones;
437
438 len_ones = ones (len);
439 one_bit_at_len = 1 << (len - 1);
440
441 sign_unext (x, len, &temp);
442 sign = temp & one_bit_at_len;
443 sign >>= (len - 1);
444
445 rest = temp & (len_ones ^ one_bit_at_len);
446 rest <<= 1;
447
448 *result = rest | sign;
449}
450
451/* Handle field selectors for PA instructions. */
452
453static INLINE unsigned long
454hppa_field_adjust (value, constant_value, r_field)
455 unsigned long value;
456 unsigned long constant_value;
457 unsigned short r_field;
458{
459 switch (r_field)
460 {
461 case e_fsel: /* F : no change */
462 case e_nsel: /* N : no change */
463 value += constant_value;
464 break;
465
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;
473
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;
481
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;
487
488 case e_rsel: /* R : Set bits 0-20 to zero */
489 value += constant_value;
490 value = value & 0x7ff;
491 break;
492
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;
499
500 case e_rdsel: /* RD : Set bits 0-20 to one */
501 value += constant_value;
502 value |= 0xfffff800;
503 break;
504
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;
510
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;
515
516 default:
517 abort ();
518 }
519 return value;
520
521}
522
523/* PA-RISC OPCODES */
524#define get_opcode(insn) ((insn) & 0xfc000000) >> 26
525
526/* FIXME: this list is incomplete. It should also be an enumerated
527 type rather than #defines. */
528
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
547
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
560
561#define BL 0x3a
562#define BLE 0x39
563#define BE 0x38
564
565
566/* Given a machine instruction, return its format.
567
568 FIXME: opcodes which do not map to a known format
569 should return an error of some sort. */
570
571static INLINE char
572bfd_hppa_insn2fmt (insn)
573 unsigned long insn;
574{
575 char fmt = -1;
576 unsigned char op = get_opcode (insn);
577
578 switch (op)
579 {
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;
622 }
623 return fmt;
624}
625
626
627/* Insert VALUE into INSN using R_FORMAT to determine exactly what
628 bits to change. */
629
630static INLINE unsigned long
631hppa_rebuild_insn (abfd, insn, value, r_format)
632 bfd *abfd;
633 unsigned long insn;
634 unsigned long value;
635 unsigned long r_format;
636{
637 unsigned long const_part;
638 unsigned long rebuilt_part;
639
640 switch (r_format)
641 {
642 case 11:
643 {
644 unsigned w1, w;
645
646 const_part = insn & 0xffffe002;
647 dis_assemble_12 (value, &w1, &w);
648 rebuilt_part = (w1 << 2) | w;
649 return const_part | rebuilt_part;
650 }
651
652 case 12:
653 {
654 unsigned w1, w;
655
656 const_part = insn & 0xffffe002;
657 dis_assemble_12 (value, &w1, &w);
658 rebuilt_part = (w1 << 2) | w;
659 return const_part | rebuilt_part;
660 }
661
662 case 14:
663 {
664 unsigned int ext;
665
666 const_part = insn & 0xffffc000;
667 low_sign_unext (value, 14, &ext);
668 return const_part | ext;
669 }
670
671 case 17:
672 {
673 unsigned w1, w2, w;
674
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;
679 }
680
681 case 21:
682 {
683 unsigned int w;
684
685 const_part = insn & 0xffe00000;
686 dis_assemble_21 (value, &w);
687 return const_part | w;
688 }
689
690 case 32:
691 const_part = 0;
692 return value;
693
694 default:
695 abort ();
696 }
697 return insn;
698}
699
700#endif /* _HPPA_H */
This page took 0.048151 seconds and 4 git commands to generate.