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