* Makefile.am (PROGS,bin_PROGRAMS): Add @BUILD_MISC@
[deliverable/binutils-gdb.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 */
This page took 0.043723 seconds and 4 git commands to generate.