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, 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 /* The PA instruction set variants.  */
78 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
79
80 /* HP PA-RISC relocation types */
81
82 enum hppa_reloc_field_selector_type
83   {
84     R_HPPA_FSEL = 0x0,
85     R_HPPA_LSSEL = 0x1,
86     R_HPPA_RSSEL = 0x2,
87     R_HPPA_LSEL = 0x3,
88     R_HPPA_RSEL = 0x4,
89     R_HPPA_LDSEL = 0x5,
90     R_HPPA_RDSEL = 0x6,
91     R_HPPA_LRSEL = 0x7,
92     R_HPPA_RRSEL = 0x8,
93     R_HPPA_NSEL  = 0x9,
94     R_HPPA_NLSEL  = 0xa,
95     R_HPPA_NLRSEL  = 0xb,
96     R_HPPA_PSEL = 0xc,
97     R_HPPA_LPSEL = 0xd,
98     R_HPPA_RPSEL = 0xe,
99     R_HPPA_TSEL = 0xf,
100     R_HPPA_LTSEL = 0x10,
101     R_HPPA_RTSEL = 0x11,
102     R_HPPA_ESEL = 0xff
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_esel
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     e_esel = R_HPPA_ESEL
158   };
159
160 enum hppa_reloc_expr_type
161   {
162     R_HPPA_E_ONE = 0,
163     R_HPPA_E_TWO = 1,
164     R_HPPA_E_PCREL = 2,
165     R_HPPA_E_CON = 3,
166     R_HPPA_E_PLABEL = 7,
167     R_HPPA_E_ABS = 18
168   };
169
170 /* for compatibility */
171 enum hppa_reloc_expr_type_alt
172   {
173     e_one = R_HPPA_E_ONE,
174     e_two = R_HPPA_E_TWO,
175     e_pcrel = R_HPPA_E_PCREL,
176     e_con = R_HPPA_E_CON,
177     e_plabel = R_HPPA_E_PLABEL,
178     e_abs = R_HPPA_E_ABS
179   };
180
181
182 /* Relocations for function calls must be accompanied by parameter
183    relocation bits.  These bits describe exactly where the caller has
184    placed the function's arguments and where it expects to find a return
185    value.
186
187    Both ELF and SOM encode this information within the addend field
188    of the call relocation.  (Note this could break very badly if one
189    was to make a call like bl foo + 0x12345678).
190
191    The high order 10 bits contain parameter relocation information,
192    the low order 22 bits contain the constant offset.  */
193    
194 #define HPPA_R_ARG_RELOC(a)     (((a) >> 22) & 0x3FF)
195 #define HPPA_R_CONSTANT(a)      ((((int)(a)) << 10) >> 10)
196 #define HPPA_R_ADDEND(r,c)      (((r) << 22) + ((c) & 0x3FFFFF))
197
198 /* Some functions to manipulate PA instructions.  */
199 static INLINE unsigned int
200 assemble_3 (x)
201      unsigned int x;
202 {
203   return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
204 }
205
206 static INLINE void
207 dis_assemble_3 (x, r)
208      unsigned int x;
209      unsigned int *r;
210 {
211   *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
212 }
213
214 static INLINE unsigned int
215 assemble_12 (x, y)
216      unsigned int x, y;
217 {
218   return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
219 }
220
221 static INLINE void
222 dis_assemble_12 (as12, x, y)
223      unsigned int as12;
224      unsigned int *x, *y;
225 {
226   *y = (as12 & 0x800) >> 11;
227   *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
228 }
229
230 static INLINE unsigned long
231 assemble_17 (x, y, z)
232      unsigned int x, y, z;
233 {
234   unsigned long temp;
235
236   temp = ((z & 1) << 16) |
237     ((x & 0x1f) << 11) |
238     ((y & 1) << 10) |
239     ((y & 0x7fe) >> 1);
240   return temp & 0x1ffff;
241 }
242
243 static INLINE void
244 dis_assemble_17 (as17, x, y, z)
245      unsigned int as17;
246      unsigned int *x, *y, *z;
247 {
248
249   *z = (as17 & 0x10000) >> 16;
250   *x = (as17 & 0x0f800) >> 11;
251   *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
252 }
253
254 static INLINE unsigned long
255 assemble_21 (x)
256      unsigned int x;
257 {
258   unsigned long temp;
259
260   temp = ((x & 1) << 20) |
261     ((x & 0xffe) << 8) |
262     ((x & 0xc000) >> 7) |
263     ((x & 0x1f0000) >> 14) |
264     ((x & 0x003000) >> 12);
265   return temp & 0x1fffff;
266 }
267
268 static INLINE void
269 dis_assemble_21 (as21, x)
270      unsigned int as21, *x;
271 {
272   unsigned long temp;
273
274
275   temp = (as21 & 0x100000) >> 20;
276   temp |= (as21 & 0x0ffe00) >> 8;
277   temp |= (as21 & 0x000180) << 7;
278   temp |= (as21 & 0x00007c) << 14;
279   temp |= (as21 & 0x000003) << 12;
280   *x = temp;
281 }
282
283 static INLINE unsigned long
284 sign_extend (x, len)
285      unsigned int x, len;
286 {
287   return (int)(x >> (len - 1) ? (-1 << len) | x : x);
288 }
289
290 static INLINE unsigned int
291 ones (n)
292      int n;
293 {
294   unsigned int len_ones;
295   int i;
296
297   i = 0;
298   len_ones = 0;
299   while (i < n)
300     {
301       len_ones = (len_ones << 1) | 1;
302       i++;
303     }
304
305   return len_ones;
306 }
307
308 static INLINE void
309 sign_unext (x, len, result)
310      unsigned int x, len;
311      unsigned int *result;
312 {
313   unsigned int len_ones;
314
315   len_ones = ones (len);
316
317   *result = x & len_ones;
318 }
319
320 static INLINE unsigned long
321 low_sign_extend (x, len)
322      unsigned int x, len;
323 {
324   return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
325 }
326
327 static INLINE void
328 low_sign_unext (x, len, result)
329      unsigned int x, len;
330      unsigned int *result;
331 {
332   unsigned int temp;
333   unsigned int sign;
334   unsigned int rest;
335   unsigned int one_bit_at_len;
336   unsigned int len_ones;
337
338   len_ones = ones (len);
339   one_bit_at_len = 1 << (len - 1);
340
341   sign_unext (x, len, &temp);
342   sign = temp & one_bit_at_len;
343   sign >>= (len - 1);
344
345   rest = temp & (len_ones ^ one_bit_at_len);
346   rest <<= 1;
347
348   *result = rest | sign;
349 }
350
351 /* Handle field selectors for PA instructions.  */
352
353 static INLINE unsigned long
354 hppa_field_adjust (value, constant_value, r_field)
355      unsigned long value;
356      unsigned long constant_value;
357      unsigned short r_field;
358 {
359   switch (r_field)
360     {
361     case e_fsel:                /* F  : no change                      */
362     case e_nsel:                /* N  : no change                      */
363       value += constant_value;
364       break;
365
366     case e_lssel:               /* LS : if (bit 21) then add 0x800
367                                    arithmetic shift right 11 bits */
368       value += constant_value;
369       if (value & 0x00000400)
370         value += 0x800;
371       value = (value & 0xfffff800) >> 11;
372       break;
373
374     case e_rssel:               /* RS : Sign extend from bit 21        */
375       value += constant_value;
376       if (value & 0x00000400)
377         value |= 0xfffff800;
378       else
379         value &= 0x7ff;
380       break;
381
382     case e_lsel:                /* L  : Arithmetic shift right 11 bits */
383     case e_nlsel:               /* NL  : Arithmetic shift right 11 bits */
384       value += constant_value;
385       value = (value & 0xfffff800) >> 11;
386       break;
387
388     case e_rsel:                /* R  : Set bits 0-20 to zero          */
389       value += constant_value;
390       value = value & 0x7ff;
391       break;
392
393     case e_ldsel:               /* LD : Add 0x800, arithmetic shift
394                                    right 11 bits                  */
395       value += constant_value;
396       value += 0x800;
397       value = (value & 0xfffff800) >> 11;
398       break;
399
400     case e_rdsel:               /* RD : Set bits 0-20 to one           */
401       value += constant_value;
402       value |= 0xfffff800;
403       break;
404
405     case e_lrsel:               /* LR : L with "rounded" constant      */
406     case e_nlrsel:              /* NLR : NL with "rounded" constant      */
407       value = value + ((constant_value + 0x1000) & 0xffffe000);
408       value = (value & 0xfffff800) >> 11;
409       break;
410
411     case e_rrsel:               /* RR : R with "rounded" constant      */
412       value = value + ((constant_value + 0x1000) & 0xffffe000);
413       value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
414       break;
415
416     default:
417       abort ();
418     }
419   return value;
420
421 }
422
423 /* PA-RISC OPCODES */
424 #define get_opcode(insn)        ((insn) & 0xfc000000) >> 26
425
426 /* FIXME: this list is incomplete.  It should also be an enumerated
427    type rather than #defines.  */
428
429 #define LDO     0x0d
430 #define LDB     0x10
431 #define LDH     0x11
432 #define LDW     0x12
433 #define LDWM    0x13
434 #define STB     0x18
435 #define STH     0x19
436 #define STW     0x1a
437 #define STWM    0x1b
438 #define COMICLR 0x24
439 #define SUBI    0x25
440 #define SUBIO   0x25
441 #define ADDIT   0x2c
442 #define ADDITO  0x2c
443 #define ADDI    0x2d
444 #define ADDIO   0x2d
445 #define LDIL    0x08
446 #define ADDIL   0x0a
447
448 #define MOVB    0x32
449 #define MOVIB   0x33
450 #define COMBT   0x20
451 #define COMBF   0x22
452 #define COMIBT  0x21
453 #define COMIBF  0x23
454 #define ADDBT   0x28
455 #define ADDBF   0x2a
456 #define ADDIBT  0x29
457 #define ADDIBF  0x2b
458 #define BVB     0x30
459 #define BB      0x31
460
461 #define BL      0x3a
462 #define BLE     0x39
463 #define BE      0x38
464
465   
466 /* Given a machine instruction, return its format.
467
468    FIXME:  opcodes which do not map to a known format
469    should return an error of some sort.  */
470
471 static INLINE char
472 bfd_hppa_insn2fmt (insn)
473      unsigned long insn;
474 {
475   char fmt = -1;
476   unsigned char op = get_opcode (insn);
477   
478   switch (op)
479     {
480     case ADDI:
481     case ADDIT:
482     case SUBI:
483       fmt = 11;
484       break;
485     case MOVB:
486     case MOVIB:
487     case COMBT:
488     case COMBF:
489     case COMIBT:
490     case COMIBF:
491     case ADDBT:
492     case ADDBF:
493     case ADDIBT:
494     case ADDIBF:
495     case BVB:
496     case BB:
497       fmt = 12;
498       break;
499     case LDO:
500     case LDB:
501     case LDH:
502     case LDW:
503     case LDWM:
504     case STB:
505     case STH:
506     case STW:
507     case STWM:
508       fmt = 14;
509       break;
510     case BL:
511     case BE:
512     case BLE:
513       fmt = 17;
514       break;
515     case LDIL:
516     case ADDIL:
517       fmt = 21;
518       break;
519     default:
520       fmt = 32;
521       break;
522     }
523   return fmt;
524 }
525
526
527 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
528    bits to change.  */
529    
530 static INLINE unsigned long
531 hppa_rebuild_insn (abfd, insn, value, r_format)
532      bfd *abfd;
533      unsigned long insn;
534      unsigned long value;
535      unsigned long r_format;
536 {
537   unsigned long const_part;
538   unsigned long rebuilt_part;
539
540   switch (r_format)
541     {
542     case 11:
543       {
544         unsigned w1, w;
545
546         const_part = insn & 0xffffe002;
547         dis_assemble_12 (value, &w1, &w);
548         rebuilt_part = (w1 << 2) | w;
549         return const_part | rebuilt_part;
550       }
551
552     case 12:
553       {
554         unsigned w1, w;
555
556         const_part = insn & 0xffffe002;
557         dis_assemble_12 (value, &w1, &w);
558         rebuilt_part = (w1 << 2) | w;
559         return const_part | rebuilt_part;
560       }
561
562     case 14:
563       {
564         unsigned int ext;
565         
566         const_part = insn & 0xffffc000;
567         low_sign_unext (value, 14, &ext);
568         return const_part | ext;
569       }
570
571     case 17:
572       {
573         unsigned w1, w2, w;
574
575         const_part = insn & 0xffe0e002;
576         dis_assemble_17 (value, &w1, &w2, &w);
577         rebuilt_part = (w2 << 2) | (w1 << 16) | w;
578         return const_part | rebuilt_part;
579       }
580
581     case 21:
582       {
583         unsigned int w;
584
585         const_part = insn & 0xffe00000;
586         dis_assemble_21 (value, &w);
587         return const_part | w;
588       }
589
590     case 32:
591       const_part = 0;
592       return value;
593
594     default:
595       abort ();
596     }
597   return insn;
598 }
599
600 #endif /* _HPPA_H */