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