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