OSDN Git Service

* libhppa.h (R_HPPA_LTPSEL, R_HPPA_RTPSEL): New field selectors
[pf3gnuchains/pf3gnuchains4x.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     R_HPPA_LTPSEL = 0x12,
105     R_HPPA_RTPSEL = 0x13
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 */
139 enum 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,
158     e_rtsel = R_HPPA_RTSEL,
159     e_ltpsel = R_HPPA_LTPSEL,
160     e_rtpsel = R_HPPA_RTPSEL
161   };
162
163 enum 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 */
174 enum 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
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))
200 #define HPPA_WIDE              (0) /* PSW W-bit, need to check! FIXME */
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  
210 #define GET_BIT(X, WHICH) \
211   GET_FIELD (X, WHICH, WHICH)
212
213 #define MASK(SIZE) \
214   (~((-1) << SIZE))
215   
216 #define CATENATE(X, XSIZE, Y, YSIZE) \
217   (((X & MASK (XSIZE)) << YSIZE) | (Y & MASK (YSIZE)))
218
219 #define ELEVEN(X) \
220   CATENATE (GET_BIT (X, 10), 1, GET_FIELD (X, 0, 9), 10)
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
230 static INLINE unsigned long
231 sign_extend (x, len)
232      unsigned int x, len;
233 {
234   return (int)(x >> (len - 1) ? (-1 << len) | x : x);
235 }
236
237 static INLINE unsigned int
238 assemble_3 (x)
239      unsigned int x;
240 {
241   return CATENATE (GET_BIT (x, 2), 1, GET_FIELD (x, 0, 1), 2);
242 }
243
244 static INLINE void
245 dis_assemble_3 (x, r)
246      unsigned int x;
247      unsigned int *r;
248 {
249   *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
250 }
251
252 static INLINE unsigned int
253 assemble_6 (x, y)
254      unsigned int x, y;
255 {
256   return (((x & 0x1) << 5) + (32 - (y & 0x1f)));
257 }
258
259 static INLINE unsigned int
260 assemble_12 (x, y)
261      unsigned int x, y;
262 {
263   return CATENATE (CATENATE (y, 1, GET_BIT (x, 10), 1), 2,
264                    GET_FIELD (x, 0, 9), 9);
265 }
266
267 static INLINE void
268 dis_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
276 static INLINE unsigned long
277 assemble_16 (x, y)
278      unsigned int x, y;
279 {
280   /* Depends on PSW W-bit !*/
281   unsigned int temp;
282
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);
293 }
294
295
296 static INLINE unsigned long
297 assemble_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, (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);
310 }
311
312 static INLINE unsigned long
313 assemble_17 (x, y, z)
314      unsigned int x, y, z;
315 {
316   unsigned long temp;
317
318   temp = CATENATE (CATENATE (z, 1, x, 5), 6,
319                    CATENATE (GET_BIT (y, 10), 1, GET_FIELD (y, 0, 9), 10), 11);
320   
321   return temp;
322 }
323
324 static INLINE void
325 dis_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
335 static INLINE unsigned long
336 assemble_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
349 static INLINE unsigned long
350 assemble_22 (a,b,c,d)
351      unsigned int a,b,c,d;
352 {
353   unsigned long temp;
354   
355   temp = CATENATE (CATENATE (d, 1, a, 5), 6,
356                    CATENATE (b, 5, ELEVEN (c), 11), 16);
357
358   return sign_extend (temp, 22);
359 }
360
361 static INLINE void
362 dis_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
376 static INLINE unsigned int
377 ones (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
394 static INLINE void
395 sign_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
406 static INLINE unsigned long
407 low_sign_extend (x, len)
408      unsigned int x, len;
409 {
410   return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
411 }
412
413 static INLINE void
414 low_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
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;
444 {
445   switch (r_field)
446     {
447     case e_fsel:                /* F  : no change                     */
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
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;
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
474     case e_rsel:                /* R  : Set bits 0-20 to zero     */
475       value += constant_value;
476       value = value & 0x7ff;
477       break;
478
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;
485
486     case e_rdsel:               /* RD : Set bits 0-20 to one       */
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
557 static INLINE char
558 bfd_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    
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;
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 */