* elflink.h (elf_link_add_object_symbols): Calling check_relocs
[deliverable/binutils-gdb.git] / bfd / libhppa.h
CommitLineData
76c7e44d 1/* HP PA-RISC SOM object file format: definitions internal to BFD.
d3e572fe 2 Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
76c7e44d
SG
3
4 Contributed by the Center for Software Science at the
5 University of Utah (pa-gdb-bugs@cs.utah.edu).
6
d9ad93bc 7 This file is part of BFD, the Binary File Descriptor library.
76c7e44d 8
d9ad93bc
KR
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.
76c7e44d 13
d9ad93bc
KR
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.
76c7e44d 18
d9ad93bc
KR
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
6c7b3090 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
76c7e44d 22
d9ad93bc
KR
23#ifndef _HPPA_H
24#define _HPPA_H
d325e28c 25
d9ad93bc 26#define BYTES_IN_WORD 4
85579659 27#define PA_PAGESIZE 0x1000
205d660d 28
f68990e6 29#ifndef INLINE
d9ad93bc 30#ifdef __GNUC__
f68990e6 31#define INLINE inline
d9ad93bc 32#else
f68990e6 33#define INLINE
d9ad93bc 34#endif /* GNU C? */
f68990e6 35#endif /* INLINE */
d325e28c 36
ad240a82
JL
37#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
38/* Declare the functions with the unused attribute to avoid warnings. */
39static INLINE unsigned int assemble_3 (unsigned int)
40 __attribute__ ((__unused__));
41static INLINE void dis_assemble_3 (unsigned int, unsigned int *)
42 __attribute__ ((__unused__));
43static INLINE unsigned int assemble_12 (unsigned int, unsigned int)
44 __attribute__ ((__unused__));
45static INLINE void dis_assemble_12 (unsigned int, unsigned int *,
46 unsigned int *)
47 __attribute__ ((__unused__));
48static INLINE unsigned long assemble_17 (unsigned int, unsigned int,
49 unsigned int)
50 __attribute__ ((__unused__));
51static INLINE void dis_assemble_17 (unsigned int, unsigned int *,
52 unsigned int *, unsigned int *)
53 __attribute__ ((__unused__));
54static INLINE unsigned long assemble_21 (unsigned int)
55 __attribute ((__unused__));
56static INLINE void dis_assemble_21 (unsigned int, unsigned int *)
57 __attribute__ ((__unused__));
58static INLINE unsigned long sign_extend (unsigned int, unsigned int)
59 __attribute__ ((__unused__));
60static INLINE unsigned int ones (int) __attribute ((__unused__));
61static INLINE void sign_unext (unsigned int, unsigned int, unsigned int *)
62 __attribute__ ((__unused__));
63static INLINE unsigned long low_sign_extend (unsigned int, unsigned int)
64 __attribute__ ((__unused__));
65static INLINE void low_sign_unext (unsigned int, unsigned int, unsigned int *)
66 __attribute__ ((__unused__));
67static INLINE unsigned long hppa_field_adjust (unsigned long, unsigned long,
68 unsigned short)
69 __attribute__ ((__unused__));
70static INLINE char bfd_hppa_insn2fmt (unsigned long)
71 __attribute__ ((__unused__));
72static 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
6c7b3090
JL
77/* The PA instruction set variants. */
78enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
79
d9ad93bc 80/* HP PA-RISC relocation types */
d325e28c 81
d9ad93bc
KR
82enum 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,
6c7b3090 93 R_HPPA_NSEL = 0x9,
1680791e
ILT
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,
ad240a82
JL
101 R_HPPA_RTSEL = 0x11,
102 R_HPPA_ESEL = 0xff
d9ad93bc 103 };
89c789f6 104
aef3ae9a
JK
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
6c7b3090 119#undef e_nsel
1680791e
ILT
120#undef e_nlsel
121#undef e_nlrsel
aef3ae9a
JK
122#undef e_psel
123#undef e_lpsel
124#undef e_rpsel
125#undef e_tsel
126#undef e_ltsel
127#undef e_rtsel
ad240a82 128#undef e_esel
aef3ae9a
JK
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
d9ad93bc
KR
136/* for compatibility */
137enum 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,
6c7b3090 148 e_nsel = R_HPPA_NSEL,
1680791e
ILT
149 e_nlsel = R_HPPA_NLSEL,
150 e_nlrsel = R_HPPA_NLRSEL,
d9ad93bc
KR
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,
ad240a82
JL
156 e_rtsel = R_HPPA_RTSEL,
157 e_esel = R_HPPA_ESEL
d9ad93bc 158 };
89c789f6 159
d9ad93bc
KR
160enum 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 };
d325e28c 169
d9ad93bc
KR
170/* for compatibility */
171enum 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
f6061456
JL
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
d9ad93bc 198/* Some functions to manipulate PA instructions. */
f68990e6 199static INLINE unsigned int
d9ad93bc
KR
200assemble_3 (x)
201 unsigned int x;
202{
203 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
204}
d325e28c 205
f68990e6 206static INLINE void
d9ad93bc
KR
207dis_assemble_3 (x, r)
208 unsigned int x;
209 unsigned int *r;
210{
211 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
212}
89c789f6 213
f68990e6 214static INLINE unsigned int
d9ad93bc
KR
215assemble_12 (x, y)
216 unsigned int x, y;
217{
218 return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
219}
89c789f6 220
f68990e6 221static INLINE void
d9ad93bc
KR
222dis_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}
76c7e44d 229
f68990e6 230static INLINE unsigned long
d9ad93bc
KR
231assemble_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
f68990e6 243static INLINE void
d9ad93bc
KR
244dis_assemble_17 (as17, x, y, z)
245 unsigned int as17;
246 unsigned int *x, *y, *z;
247{
76c7e44d 248
d9ad93bc
KR
249 *z = (as17 & 0x10000) >> 16;
250 *x = (as17 & 0x0f800) >> 11;
251 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
252}
76c7e44d 253
f68990e6 254static INLINE unsigned long
d9ad93bc
KR
255assemble_21 (x)
256 unsigned int x;
76c7e44d 257{
d9ad93bc
KR
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
f68990e6 268static INLINE void
d9ad93bc
KR
269dis_assemble_21 (as21, x)
270 unsigned int as21, *x;
76c7e44d 271{
d9ad93bc 272 unsigned long temp;
76c7e44d 273
76c7e44d 274
d9ad93bc
KR
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}
76c7e44d 282
f68990e6 283static INLINE unsigned long
6c7b3090 284sign_extend (x, len)
d9ad93bc
KR
285 unsigned int x, len;
286{
6c7b3090 287 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
d9ad93bc 288}
76c7e44d 289
f68990e6 290static INLINE unsigned int
d9ad93bc
KR
291ones (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
f68990e6 308static INLINE void
d9ad93bc
KR
309sign_unext (x, len, result)
310 unsigned int x, len;
311 unsigned int *result;
312{
313 unsigned int len_ones;
76c7e44d 314
d9ad93bc 315 len_ones = ones (len);
76c7e44d 316
d9ad93bc
KR
317 *result = x & len_ones;
318}
76c7e44d 319
f68990e6 320static INLINE unsigned long
6c7b3090 321low_sign_extend (x, len)
d9ad93bc
KR
322 unsigned int x, len;
323{
6c7b3090 324 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
d9ad93bc 325}
205d660d 326
f68990e6 327static INLINE void
d9ad93bc
KR
328low_sign_unext (x, len, result)
329 unsigned int x, len;
330 unsigned int *result;
76c7e44d 331{
d9ad93bc
KR
332 unsigned int temp;
333 unsigned int sign;
334 unsigned int rest;
335 unsigned int one_bit_at_len;
336 unsigned int len_ones;
8568acaa 337
d9ad93bc
KR
338 len_ones = ones (len);
339 one_bit_at_len = 1 << (len - 1);
8568acaa 340
d9ad93bc
KR
341 sign_unext (x, len, &temp);
342 sign = temp & one_bit_at_len;
343 sign >>= (len - 1);
b2057735 344
d9ad93bc
KR
345 rest = temp & (len_ones ^ one_bit_at_len);
346 rest <<= 1;
8568acaa 347
d9ad93bc
KR
348 *result = rest | sign;
349}
8568acaa 350
d9ad93bc
KR
351/* Handle field selectors for PA instructions. */
352
f68990e6 353static INLINE unsigned long
d9ad93bc
KR
354hppa_field_adjust (value, constant_value, r_field)
355 unsigned long value;
356 unsigned long constant_value;
357 unsigned short r_field;
8568acaa 358{
d9ad93bc
KR
359 switch (r_field)
360 {
361 case e_fsel: /* F : no change */
1680791e 362 case e_nsel: /* N : no change */
6c7b3090 363 value += constant_value;
d9ad93bc
KR
364 break;
365
366 case e_lssel: /* LS : if (bit 21) then add 0x800
367 arithmetic shift right 11 bits */
6c7b3090 368 value += constant_value;
d9ad93bc
KR
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 */
6c7b3090 375 value += constant_value;
d9ad93bc
KR
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 */
1680791e 383 case e_nlsel: /* NL : Arithmetic shift right 11 bits */
6c7b3090 384 value += constant_value;
d9ad93bc
KR
385 value = (value & 0xfffff800) >> 11;
386 break;
387
388 case e_rsel: /* R : Set bits 0-20 to zero */
6c7b3090 389 value += constant_value;
d9ad93bc
KR
390 value = value & 0x7ff;
391 break;
392
393 case e_ldsel: /* LD : Add 0x800, arithmetic shift
394 right 11 bits */
6c7b3090 395 value += constant_value;
d9ad93bc
KR
396 value += 0x800;
397 value = (value & 0xfffff800) >> 11;
398 break;
399
400 case e_rdsel: /* RD : Set bits 0-20 to one */
6c7b3090 401 value += constant_value;
d9ad93bc
KR
402 value |= 0xfffff800;
403 break;
404
405 case e_lrsel: /* LR : L with "rounded" constant */
1680791e 406 case e_nlrsel: /* NLR : NL with "rounded" constant */
d9ad93bc
KR
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}
f6061456
JL
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
f68990e6 471static INLINE char
f6061456
JL
472bfd_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
f68990e6 530static INLINE unsigned long
f6061456
JL
531hppa_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:
ad240a82
JL
563 {
564 unsigned int ext;
565
566 const_part = insn & 0xffffc000;
567 low_sign_unext (value, 14, &ext);
568 return const_part | ext;
569 }
f6061456
JL
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:
ad240a82
JL
582 {
583 unsigned int w;
584
585 const_part = insn & 0xffe00000;
586 dis_assemble_21 (value, &w);
587 return const_part | w;
588 }
f6061456
JL
589
590 case 32:
591 const_part = 0;
592 return value;
593
594 default:
595 abort ();
596 }
597 return insn;
598}
599
d9ad93bc 600#endif /* _HPPA_H */
This page took 0.241449 seconds and 4 git commands to generate.