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