This commit was generated by cvs2svn to track changes on a CVS vendor
[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, 96, 98, 1999
3    Free Software Foundation, Inc.
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.  */
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 */
77
78
79 /* The PA instruction set variants.  */
80 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
81
82 /* HP PA-RISC relocation types */
83
84 enum 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,
103     R_HPPA_RTSEL = 0x11
104   };
105
106 /* /usr/include/reloc.h defines these to constants.  We want to use
107    them in enums, so #undef them before we start using them.  We might
108    be able to fix this another way by simply managing not to include
109    /usr/include/reloc.h, but currently GDB picks up these defines
110    somewhere.  */
111 #undef e_fsel
112 #undef e_lssel
113 #undef e_rssel
114 #undef e_lsel
115 #undef e_rsel
116 #undef e_ldsel
117 #undef e_rdsel
118 #undef e_lrsel
119 #undef e_rrsel
120 #undef e_nsel
121 #undef e_nlsel
122 #undef e_nlrsel
123 #undef e_psel
124 #undef e_lpsel
125 #undef e_rpsel
126 #undef e_tsel
127 #undef e_ltsel
128 #undef e_rtsel
129 #undef e_one
130 #undef e_two
131 #undef e_pcrel
132 #undef e_con
133 #undef e_plabel
134 #undef e_abs
135
136 /* for compatibility */
137 enum hppa_reloc_field_selector_type_alt
138   {
139     e_fsel = R_HPPA_FSEL,
140     e_lssel = R_HPPA_LSSEL,
141     e_rssel = R_HPPA_RSSEL,
142     e_lsel = R_HPPA_LSEL,
143     e_rsel = R_HPPA_RSEL,
144     e_ldsel = R_HPPA_LDSEL,
145     e_rdsel = R_HPPA_RDSEL,
146     e_lrsel = R_HPPA_LRSEL,
147     e_rrsel = R_HPPA_RRSEL,
148     e_nsel = R_HPPA_NSEL,
149     e_nlsel = R_HPPA_NLSEL,
150     e_nlrsel = R_HPPA_NLRSEL,
151     e_psel = R_HPPA_PSEL,
152     e_lpsel = R_HPPA_LPSEL,
153     e_rpsel = R_HPPA_RPSEL,
154     e_tsel = R_HPPA_TSEL,
155     e_ltsel = R_HPPA_LTSEL,
156     e_rtsel = R_HPPA_RTSEL
157   };
158
159 enum hppa_reloc_expr_type
160   {
161     R_HPPA_E_ONE = 0,
162     R_HPPA_E_TWO = 1,
163     R_HPPA_E_PCREL = 2,
164     R_HPPA_E_CON = 3,
165     R_HPPA_E_PLABEL = 7,
166     R_HPPA_E_ABS = 18
167   };
168
169 /* for compatibility */
170 enum hppa_reloc_expr_type_alt
171   {
172     e_one = R_HPPA_E_ONE,
173     e_two = R_HPPA_E_TWO,
174     e_pcrel = R_HPPA_E_PCREL,
175     e_con = R_HPPA_E_CON,
176     e_plabel = R_HPPA_E_PLABEL,
177     e_abs = R_HPPA_E_ABS
178   };
179
180
181 /* Relocations for function calls must be accompanied by parameter
182    relocation bits.  These bits describe exactly where the caller has
183    placed the function's arguments and where it expects to find a return
184    value.
185
186    Both ELF and SOM encode this information within the addend field
187    of the call relocation.  (Note this could break very badly if one
188    was to make a call like bl foo + 0x12345678).
189
190    The high order 10 bits contain parameter relocation information,
191    the low order 22 bits contain the constant offset.  */
192    
193 #define HPPA_R_ARG_RELOC(a)     (((a) >> 22) & 0x3FF)
194 #define HPPA_R_CONSTANT(a)      ((((int)(a)) << 10) >> 10)
195 #define HPPA_R_ADDEND(r,c)      (((r) << 22) + ((c) & 0x3FFFFF))
196 #define HPPA_WIDE              (0) /* PSW W-bit, need to check! FIXME */
197
198 /* These macros get bit fields using HP's numbering (MSB = 0),
199  * but note that "MASK" assumes that the LSB bits are what's
200  * wanted.
201  */
202 #ifndef GET_FIELD
203 #define GET_FIELD(X, FROM, TO) \
204   ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
205 #endif  
206 #define GET_BIT(X, WHICH) \
207   GET_FIELD (X, WHICH, WHICH)
208
209 #define MASK(SIZE) \
210   (~((-1) << SIZE))
211   
212 #define CATENATE(X, XSIZE, Y, YSIZE) \
213   (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
214
215 #define ELEVEN(X) \
216   CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
217   
218 /* Some functions to manipulate PA instructions.  */
219
220 /* NOTE: these use the HP convention that f{1} is the _left_ most
221  *       bit (MSB) of f; they sometimes have to impose an assumption
222  *       about the size of a field; and as far as I can tell, most
223  *       aren't used.
224  */
225
226 static INLINE unsigned long
227 sign_extend (x, len)
228      unsigned int x, len;
229 {
230   return (int)(x >> (len - 1) ? (-1 << len) | x : x);
231 }
232
233 static INLINE unsigned int
234 assemble_3 (x)
235      unsigned int x;
236 {
237   return CATENATE (GET_BIT (x, 2), 1, GET_FIELD (x, 0, 1), 2);
238 }
239
240 static INLINE void
241 dis_assemble_3 (x, r)
242      unsigned int x;
243      unsigned int *r;
244 {
245   *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
246 }
247
248 static INLINE unsigned int
249 assemble_6 (x, y)
250      unsigned int x, y;
251 {
252   return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
253 }
254
255 static INLINE unsigned int
256 assemble_12 (x, y)
257      unsigned int x, y;
258 {
259   return CATENATE (CATENATE (y, 1, GET_BIT (x, 10), 1), 2,
260                    GET_FIELD (x, 0, 9), 9);
261 }
262
263 static INLINE void
264 dis_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
272 static INLINE unsigned long
273 assemble_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   else
285     temp = CATENATE (CATENATE (GET_BIT (y, 13), 1, GET_BIT (y, 13), 1), 2,
286                      CATENATE (GET_BIT (y, 13), 1, GET_FIELD (y, 0, 12), 13), 14);
287
288   return sign_extend (temp, 16);
289 }
290
291
292 static INLINE unsigned long
293 assemble_16a (x, y, z)
294      unsigned int x, y, z;
295 {
296   /* Depends on PSW W-bit !*/
297   unsigned int temp;
298
299   if (HPPA_WIDE)
300     temp = CATENATE (CATENATE (z, 1, (z ^ GET_BIT (x, 0)), 1), 2,
301                      CATENATE ((z ^ GET_BIT (x, 1)), 1, y, 11), 12);
302   else 
303       temp = CATENATE (CATENATE (z, 1, z, 1), 2, CATENATE (z, 1, y, 11), 12);
304
305   return sign_extend ((temp << 2), 16);
306 }
307
308 static INLINE unsigned long
309 assemble_17 (x, y, z)
310      unsigned int x, y, z;
311 {
312   unsigned long temp;
313
314   temp = CATENATE (CATENATE (z, 1, x, 5), 6,
315                    CATENATE (GET_BIT (y, 10), 1, GET_FIELD (y, 0, 9), 10), 11);
316   
317   return temp;
318 }
319
320 static INLINE void
321 dis_assemble_17 (as17, x, y, z)
322      unsigned int as17;
323      unsigned int *x, *y, *z;
324 {
325
326   *z = (as17 & 0x10000) >> 16;
327   *x = (as17 & 0x0f800) >> 11;
328   *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
329 }
330
331 static INLINE unsigned long
332 assemble_21 (x)
333      unsigned int x;
334 {
335   unsigned long temp;
336
337   temp = ((x & 1) << 20) |
338     ((x & 0xffe) << 8) |
339     ((x & 0xc000) >> 7) |
340     ((x & 0x1f0000) >> 14) |
341     ((x & 0x003000) >> 12);
342   return temp & 0x1fffff;
343 }
344
345 static INLINE unsigned long
346 assemble_22 (a,b,c,d)
347      unsigned int a,b,c,d;
348 {
349   unsigned long temp;
350   
351   temp = CATENATE (CATENATE (d, 1, a, 5), 6,
352                    CATENATE (b, 5, ELEVEN (c), 11), 16);
353
354   return sign_extend (temp, 22);
355 }
356
357 static INLINE void
358 dis_assemble_21 (as21, x)
359      unsigned int as21, *x;
360 {
361   unsigned long temp;
362
363
364   temp = (as21 & 0x100000) >> 20;
365   temp |= (as21 & 0x0ffe00) >> 8;
366   temp |= (as21 & 0x000180) << 7;
367   temp |= (as21 & 0x00007c) << 14;
368   temp |= (as21 & 0x000003) << 12;
369   *x = temp;
370 }
371
372 static INLINE unsigned int
373 ones (n)
374      int n;
375 {
376   unsigned int len_ones;
377   int i;
378
379   i = 0;
380   len_ones = 0;
381   while (i < n)
382     {
383       len_ones = (len_ones << 1) | 1;
384       i++;
385     }
386
387   return len_ones;
388 }
389
390 static INLINE void
391 sign_unext (x, len, result)
392      unsigned int x, len;
393      unsigned int *result;
394 {
395   unsigned int len_ones;
396
397   len_ones = ones (len);
398
399   *result = x & len_ones;
400 }
401
402 static INLINE unsigned long
403 low_sign_extend (x, len)
404      unsigned int x, len;
405 {
406   return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
407 }
408
409 static INLINE void
410 low_sign_unext (x, len, result)
411      unsigned int x, len;
412      unsigned int *result;
413 {
414   unsigned int temp;
415   unsigned int sign;
416   unsigned int rest;
417   unsigned int one_bit_at_len;
418   unsigned int len_ones;
419
420   len_ones = ones (len);
421   one_bit_at_len = 1 << (len - 1);
422
423   sign_unext (x, len, &temp);
424   sign = temp & one_bit_at_len;
425   sign >>= (len - 1);
426
427   rest = temp & (len_ones ^ one_bit_at_len);
428   rest <<= 1;
429
430   *result = rest | sign;
431 }
432
433 /* Handle field selectors for PA instructions.  */
434
435 static INLINE unsigned long
436 hppa_field_adjust (value, constant_value, r_field)
437      unsigned long value;
438      unsigned long constant_value;
439      unsigned short r_field;
440 {
441   switch (r_field)
442     {
443     case e_fsel:                /* F  : no change                     */
444     case e_nsel:                /* N  : no change                      */
445       value += constant_value;
446       break;
447
448     case e_lssel:               /* LS : if (bit 21) then add 0x800
449                                    arithmetic shift right 11 bits */
450       value += constant_value;
451       if (value & 0x00000400)
452         value += 0x800;
453       value = (value & 0xfffff800) >> 11;
454       break;
455
456     case e_rssel:               /* RS : Sign extend from bit 21 */
457       value += constant_value;
458       if (value & 0x00000400)
459         value |= 0xfffff800;
460       else
461         value &= 0x7ff;
462       break;
463
464     case e_lsel:                /* L  : Arithmetic shift right 11 bits */
465     case e_nlsel:               /* NL  : Arithmetic shift right 11 bits */
466       value += constant_value;
467       value = (value & 0xfffff800) >> 11;
468       break;
469
470     case e_rsel:                /* R  : Set bits 0-20 to zero     */
471       value += constant_value;
472       value = value & 0x7ff;
473       break;
474
475     case e_ldsel:               /* LD : Add 0x800, arithmetic shift
476                                    right 11 bits                  */
477       value += constant_value;
478       value += 0x800;
479       value = (value & 0xfffff800) >> 11;
480       break;
481
482     case e_rdsel:               /* RD : Set bits 0-20 to one       */
483       value += constant_value;
484       value |= 0xfffff800;
485       break;
486
487     case e_lrsel:               /* LR : L with "rounded" constant      */
488     case e_nlrsel:              /* NLR : NL with "rounded" constant      */
489       value = value + ((constant_value + 0x1000) & 0xffffe000);
490       value = (value & 0xfffff800) >> 11;
491       break;
492
493     case e_rrsel:               /* RR : R with "rounded" constant      */
494       value = value + ((constant_value + 0x1000) & 0xffffe000);
495       value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
496       break;
497
498     default:
499       abort ();
500     }
501   return value;
502
503 }
504
505 /* PA-RISC OPCODES */
506 #define get_opcode(insn)        ((insn) & 0xfc000000) >> 26
507
508 /* FIXME: this list is incomplete.  It should also be an enumerated
509    type rather than #defines.  */
510
511 #define LDO     0x0d
512 #define LDB     0x10
513 #define LDH     0x11
514 #define LDW     0x12
515 #define LDWM    0x13
516 #define STB     0x18
517 #define STH     0x19
518 #define STW     0x1a
519 #define STWM    0x1b
520 #define COMICLR 0x24
521 #define SUBI    0x25
522 #define SUBIO   0x25
523 #define ADDIT   0x2c
524 #define ADDITO  0x2c
525 #define ADDI    0x2d
526 #define ADDIO   0x2d
527 #define LDIL    0x08
528 #define ADDIL   0x0a
529
530 #define MOVB    0x32
531 #define MOVIB   0x33
532 #define COMBT   0x20
533 #define COMBF   0x22
534 #define COMIBT  0x21
535 #define COMIBF  0x23
536 #define ADDBT   0x28
537 #define ADDBF   0x2a
538 #define ADDIBT  0x29
539 #define ADDIBF  0x2b
540 #define BVB     0x30
541 #define BB      0x31
542
543 #define BL      0x3a
544 #define BLE     0x39
545 #define BE      0x38
546
547   
548 /* Given a machine instruction, return its format.
549
550    FIXME:  opcodes which do not map to a known format
551    should return an error of some sort.  */
552
553 static INLINE char
554 bfd_hppa_insn2fmt (insn)
555      unsigned long insn;
556 {
557   char fmt = -1;
558   unsigned char op = get_opcode (insn);
559   
560   switch (op)
561     {
562     case ADDI:
563     case ADDIT:
564     case SUBI:
565       fmt = 11;
566       break;
567     case MOVB:
568     case MOVIB:
569     case COMBT:
570     case COMBF:
571     case COMIBT:
572     case COMIBF:
573     case ADDBT:
574     case ADDBF:
575     case ADDIBT:
576     case ADDIBF:
577     case BVB:
578     case BB:
579       fmt = 12;
580       break;
581     case LDO:
582     case LDB:
583     case LDH:
584     case LDW:
585     case LDWM:
586     case STB:
587     case STH:
588     case STW:
589     case STWM:
590       fmt = 14;
591       break;
592     case BL:
593     case BE:
594     case BLE:
595       fmt = 17;
596       break;
597     case LDIL:
598     case ADDIL:
599       fmt = 21;
600       break;
601     default:
602       fmt = 32;
603       break;
604     }
605   return fmt;
606 }
607
608
609 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
610    bits to change.  */
611    
612 static INLINE unsigned long
613 hppa_rebuild_insn (abfd, insn, value, r_format)
614      bfd *abfd ATTRIBUTE_UNUSED;
615      unsigned long insn;
616      unsigned long value;
617      unsigned long r_format;
618 {
619   unsigned long const_part;
620   unsigned long rebuilt_part;
621
622   switch (r_format)
623     {
624     case 11:
625       {
626         unsigned w1, w;
627
628         const_part = insn & 0xffffe002;
629         dis_assemble_12 (value, &w1, &w);
630         rebuilt_part = (w1 << 2) | w;
631         return const_part | rebuilt_part;
632       }
633
634     case 12:
635       {
636         unsigned w1, w;
637
638         const_part = insn & 0xffffe002;
639         dis_assemble_12 (value, &w1, &w);
640         rebuilt_part = (w1 << 2) | w;
641         return const_part | rebuilt_part;
642       }
643
644     case 14:
645       {
646         unsigned int ext;
647         
648         const_part = insn & 0xffffc000;
649         low_sign_unext (value, 14, &ext);
650         return const_part | ext;
651       }
652
653     case 17:
654       {
655         unsigned w1, w2, w;
656
657         const_part = insn & 0xffe0e002;
658         dis_assemble_17 (value, &w1, &w2, &w);
659         rebuilt_part = (w2 << 2) | (w1 << 16) | w;
660         return const_part | rebuilt_part;
661       }
662
663     case 21:
664       {
665         unsigned int w;
666
667         const_part = insn & 0xffe00000;
668         dis_assemble_21 (value, &w);
669         return const_part | w;
670       }
671
672     case 32:
673       const_part = 0;
674       return value;
675
676     default:
677       abort ();
678     }
679   return insn;
680 }
681
682 #endif /* _HPPA_H */