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