* libhppa.h: Fix various formatting errors.
[external/binutils.git] / bfd / libhppa.h
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.  */
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 */
76
77
78 /* The PA instruction set variants.  */
79 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
80
81 /* HP PA-RISC relocation types */
82
83 enum 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 */
136 enum 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
158 enum 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 */
169 enum 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
225 static INLINE unsigned long
226 sign_extend (x, len)
227      unsigned int x, len;
228 {
229   return (int)(x >> (len - 1) ? (-1 << len) | x : x);
230 }
231
232 static INLINE unsigned int
233 assemble_3 (x)
234      unsigned int x;
235 {
236   return CATENATE (GET_BIT (x, 2), 1, GET_FIELD (x, 0, 1), 2);
237 }
238
239 static INLINE void
240 dis_assemble_3 (x, r)
241      unsigned int x;
242      unsigned int *r;
243 {
244   *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
245 }
246
247 static INLINE unsigned int
248 assemble_6 (x, y)
249      unsigned int x, y;
250 {
251   return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
252 }
253
254 static INLINE unsigned int
255 assemble_12 (x, y)
256      unsigned int x, y;
257 {
258   return CATENATE (CATENATE (y, 1, GET_BIT (x, 10), 1), 2,
259                    GET_FIELD (x, 0, 9), 9);
260 }
261
262 static INLINE void
263 dis_assemble_12 (as12, x, y)
264      unsigned int as12;
265      unsigned int *x, *y;
266 {
267   *y = (as12 & 0x800) >> 11;
268   *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
269 }
270
271 static INLINE unsigned long
272 assemble_16 (x, y)
273      unsigned int x, y;
274 {
275   /* Depends on PSW W-bit !*/
276   unsigned int temp;
277
278   if (HPPA_WIDE)
279     temp = CATENATE (CATENATE (GET_BIT (y, 13), 1,
280                                (GET_BIT (y, 13) ^ GET_BIT (x, 0)), 1), 2,
281                      CATENATE ((GET_BIT (y, 13) ^ GET_BIT (x, 1)), 1,
282                                GET_FIELD (y, 0, 12), 13), 14);
283   else
284     temp = CATENATE (CATENATE (GET_BIT (y, 13), 1, GET_BIT (y, 13), 1), 2,
285                      CATENATE (GET_BIT (y, 13), 1, GET_FIELD (y, 0, 12), 13), 14);
286
287   return sign_extend (temp, 16);
288 }
289
290
291 static INLINE unsigned long
292 assemble_16a (x, y, z)
293      unsigned int x, y, z;
294 {
295   /* Depends on PSW W-bit !*/
296   unsigned int temp;
297
298   if (HPPA_WIDE)
299     temp = CATENATE (CATENATE (z, 1, (z ^ GET_BIT (x, 0)), 1), 2,
300                      CATENATE ((z ^ GET_BIT (x, 1)), 1, y, 11), 12);
301   else 
302       temp = CATENATE (CATENATE (z, 1, z, 1), 2, CATENATE (z, 1, y, 11), 12);
303
304   return sign_extend ((temp << 2), 16);
305 }
306
307 static INLINE unsigned long
308 assemble_17 (x, y, z)
309      unsigned int x, y, z;
310 {
311   unsigned long temp;
312
313   temp = CATENATE (CATENATE (z, 1, x, 5), 6,
314                    CATENATE (GET_BIT (y, 10), 1, GET_FIELD (y, 0, 9), 10), 11);
315   
316   return temp;
317 }
318
319 static INLINE void
320 dis_assemble_17 (as17, x, y, z)
321      unsigned int as17;
322      unsigned int *x, *y, *z;
323 {
324
325   *z = (as17 & 0x10000) >> 16;
326   *x = (as17 & 0x0f800) >> 11;
327   *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
328 }
329
330 static INLINE unsigned long
331 assemble_21 (x)
332      unsigned int x;
333 {
334   unsigned long temp;
335
336   temp = ((x & 1) << 20) |
337     ((x & 0xffe) << 8) |
338     ((x & 0xc000) >> 7) |
339     ((x & 0x1f0000) >> 14) |
340     ((x & 0x003000) >> 12);
341   return temp & 0x1fffff;
342 }
343
344 static INLINE unsigned long
345 assemble_22 (a,b,c,d)
346      unsigned int a,b,c,d;
347 {
348   unsigned long temp;
349   
350   temp = CATENATE (CATENATE (d, 1, a, 5), 6,
351                    CATENATE (b, 5, ELEVEN (c), 11), 16);
352
353   return sign_extend (temp, 22);
354 }
355
356 static INLINE void
357 dis_assemble_21 (as21, x)
358      unsigned int as21, *x;
359 {
360   unsigned long temp;
361
362
363   temp = (as21 & 0x100000) >> 20;
364   temp |= (as21 & 0x0ffe00) >> 8;
365   temp |= (as21 & 0x000180) << 7;
366   temp |= (as21 & 0x00007c) << 14;
367   temp |= (as21 & 0x000003) << 12;
368   *x = temp;
369 }
370
371 static INLINE unsigned int
372 ones (n)
373      int n;
374 {
375   unsigned int len_ones;
376   int i;
377
378   i = 0;
379   len_ones = 0;
380   while (i < n)
381     {
382       len_ones = (len_ones << 1) | 1;
383       i++;
384     }
385
386   return len_ones;
387 }
388
389 static INLINE void
390 sign_unext (x, len, result)
391      unsigned int x, len;
392      unsigned int *result;
393 {
394   unsigned int len_ones;
395
396   len_ones = ones (len);
397
398   *result = x & len_ones;
399 }
400
401 static INLINE unsigned long
402 low_sign_extend (x, len)
403      unsigned int x, len;
404 {
405   return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
406 }
407
408 static INLINE void
409 low_sign_unext (x, len, result)
410      unsigned int x, len;
411      unsigned int *result;
412 {
413   unsigned int temp;
414   unsigned int sign;
415   unsigned int rest;
416   unsigned int one_bit_at_len;
417   unsigned int len_ones;
418
419   len_ones = ones (len);
420   one_bit_at_len = 1 << (len - 1);
421
422   sign_unext (x, len, &temp);
423   sign = temp & one_bit_at_len;
424   sign >>= (len - 1);
425
426   rest = temp & (len_ones ^ one_bit_at_len);
427   rest <<= 1;
428
429   *result = rest | sign;
430 }
431
432 /* Handle field selectors for PA instructions.  */
433
434 static INLINE unsigned long
435 hppa_field_adjust (value, constant_value, r_field)
436      unsigned long value;
437      unsigned long constant_value;
438      unsigned short r_field;
439 {
440   switch (r_field)
441     {
442     case e_fsel:                /* F  : no change                     */
443     case e_nsel:                /* N  : no change                      */
444       value += constant_value;
445       break;
446
447     case e_lssel:               /* LS : if (bit 21) then add 0x800
448                                    arithmetic shift right 11 bits */
449       value += constant_value;
450       if (value & 0x00000400)
451         value += 0x800;
452       value = (value & 0xfffff800) >> 11;
453       break;
454
455     case e_rssel:               /* RS : Sign extend from bit 21 */
456       value += constant_value;
457       if (value & 0x00000400)
458         value |= 0xfffff800;
459       else
460         value &= 0x7ff;
461       break;
462
463     case e_lsel:                /* L  : Arithmetic shift right 11 bits */
464     case e_nlsel:               /* NL  : Arithmetic shift right 11 bits */
465       value += constant_value;
466       value = (value & 0xfffff800) >> 11;
467       break;
468
469     case e_rsel:                /* R  : Set bits 0-20 to zero     */
470       value += constant_value;
471       value = value & 0x7ff;
472       break;
473
474     case e_ldsel:               /* LD : Add 0x800, arithmetic shift
475                                    right 11 bits                  */
476       value += constant_value;
477       value += 0x800;
478       value = (value & 0xfffff800) >> 11;
479       break;
480
481     case e_rdsel:               /* RD : Set bits 0-20 to one       */
482       value += constant_value;
483       value |= 0xfffff800;
484       break;
485
486     case e_lrsel:               /* LR : L with "rounded" constant      */
487     case e_nlrsel:              /* NLR : NL with "rounded" constant      */
488       value = value + ((constant_value + 0x1000) & 0xffffe000);
489       value = (value & 0xfffff800) >> 11;
490       break;
491
492     case e_rrsel:               /* RR : R with "rounded" constant      */
493       value = value + ((constant_value + 0x1000) & 0xffffe000);
494       value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
495       break;
496
497     default:
498       abort ();
499     }
500   return value;
501
502 }
503
504 /* PA-RISC OPCODES */
505 #define get_opcode(insn)        ((insn) & 0xfc000000) >> 26
506
507 /* FIXME: this list is incomplete.  It should also be an enumerated
508    type rather than #defines.  */
509
510 #define LDO     0x0d
511 #define LDB     0x10
512 #define LDH     0x11
513 #define LDW     0x12
514 #define LDWM    0x13
515 #define STB     0x18
516 #define STH     0x19
517 #define STW     0x1a
518 #define STWM    0x1b
519 #define COMICLR 0x24
520 #define SUBI    0x25
521 #define SUBIO   0x25
522 #define ADDIT   0x2c
523 #define ADDITO  0x2c
524 #define ADDI    0x2d
525 #define ADDIO   0x2d
526 #define LDIL    0x08
527 #define ADDIL   0x0a
528
529 #define MOVB    0x32
530 #define MOVIB   0x33
531 #define COMBT   0x20
532 #define COMBF   0x22
533 #define COMIBT  0x21
534 #define COMIBF  0x23
535 #define ADDBT   0x28
536 #define ADDBF   0x2a
537 #define ADDIBT  0x29
538 #define ADDIBF  0x2b
539 #define BVB     0x30
540 #define BB      0x31
541
542 #define BL      0x3a
543 #define BLE     0x39
544 #define BE      0x38
545
546   
547 /* Given a machine instruction, return its format.
548
549    FIXME:  opcodes which do not map to a known format
550    should return an error of some sort.  */
551
552 static INLINE char
553 bfd_hppa_insn2fmt (insn)
554      unsigned long insn;
555 {
556   char fmt = -1;
557   unsigned char op = get_opcode (insn);
558   
559   switch (op)
560     {
561     case ADDI:
562     case ADDIT:
563     case SUBI:
564       fmt = 11;
565       break;
566     case MOVB:
567     case MOVIB:
568     case COMBT:
569     case COMBF:
570     case COMIBT:
571     case COMIBF:
572     case ADDBT:
573     case ADDBF:
574     case ADDIBT:
575     case ADDIBF:
576     case BVB:
577     case BB:
578       fmt = 12;
579       break;
580     case LDO:
581     case LDB:
582     case LDH:
583     case LDW:
584     case LDWM:
585     case STB:
586     case STH:
587     case STW:
588     case STWM:
589       fmt = 14;
590       break;
591     case BL:
592     case BE:
593     case BLE:
594       fmt = 17;
595       break;
596     case LDIL:
597     case ADDIL:
598       fmt = 21;
599       break;
600     default:
601       fmt = 32;
602       break;
603     }
604   return fmt;
605 }
606
607
608 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
609    bits to change.  */
610    
611 static INLINE unsigned long
612 hppa_rebuild_insn (abfd, insn, value, r_format)
613      bfd *abfd;
614      unsigned long insn;
615      unsigned long value;
616      unsigned long r_format;
617 {
618   unsigned long const_part;
619   unsigned long rebuilt_part;
620
621   switch (r_format)
622     {
623     case 11:
624       {
625         unsigned w1, w;
626
627         const_part = insn & 0xffffe002;
628         dis_assemble_12 (value, &w1, &w);
629         rebuilt_part = (w1 << 2) | w;
630         return const_part | rebuilt_part;
631       }
632
633     case 12:
634       {
635         unsigned w1, w;
636
637         const_part = insn & 0xffffe002;
638         dis_assemble_12 (value, &w1, &w);
639         rebuilt_part = (w1 << 2) | w;
640         return const_part | rebuilt_part;
641       }
642
643     case 14:
644       {
645         unsigned int ext;
646         
647         const_part = insn & 0xffffc000;
648         low_sign_unext (value, 14, &ext);
649         return const_part | ext;
650       }
651
652     case 17:
653       {
654         unsigned w1, w2, w;
655
656         const_part = insn & 0xffe0e002;
657         dis_assemble_17 (value, &w1, &w2, &w);
658         rebuilt_part = (w2 << 2) | (w1 << 16) | w;
659         return const_part | rebuilt_part;
660       }
661
662     case 21:
663       {
664         unsigned int w;
665
666         const_part = insn & 0xffe00000;
667         dis_assemble_21 (value, &w);
668         return const_part | w;
669       }
670
671     case 32:
672       const_part = 0;
673       return value;
674
675     default:
676       abort ();
677     }
678   return insn;
679 }
680
681 #endif /* _HPPA_H */