]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/libhppa.h
Forgot to check these changes in yesterday.
[thirdparty/binutils-gdb.git] / bfd / libhppa.h
1 /* HP PA-RISC SOM object file format: definitions internal to BFD.
2 Copyright (C) 1990-1991 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
28 #ifndef INLINE
29 #ifdef __GNUC__
30 #define INLINE inline
31 #else
32 #define INLINE
33 #endif /* GNU C? */
34 #endif /* INLINE */
35
36 /* HP PA-RISC relocation types */
37
38 enum hppa_reloc_field_selector_type
39 {
40 R_HPPA_FSEL = 0x0,
41 R_HPPA_LSSEL = 0x1,
42 R_HPPA_RSSEL = 0x2,
43 R_HPPA_LSEL = 0x3,
44 R_HPPA_RSEL = 0x4,
45 R_HPPA_LDSEL = 0x5,
46 R_HPPA_RDSEL = 0x6,
47 R_HPPA_LRSEL = 0x7,
48 R_HPPA_RRSEL = 0x8,
49 R_HPPA_PSEL = 0x9,
50 R_HPPA_LPSEL = 0xa,
51 R_HPPA_RPSEL = 0xb,
52 R_HPPA_TSEL = 0xc,
53 R_HPPA_LTSEL = 0xd,
54 R_HPPA_RTSEL = 0xe
55 };
56
57 /* /usr/include/reloc.h defines these to constants. We want to use
58 them in enums, so #undef them before we start using them. We might
59 be able to fix this another way by simply managing not to include
60 /usr/include/reloc.h, but currently GDB picks up these defines
61 somewhere. */
62 #undef e_fsel
63 #undef e_lssel
64 #undef e_rssel
65 #undef e_lsel
66 #undef e_rsel
67 #undef e_ldsel
68 #undef e_rdsel
69 #undef e_lrsel
70 #undef e_rrsel
71 #undef e_psel
72 #undef e_lpsel
73 #undef e_rpsel
74 #undef e_tsel
75 #undef e_ltsel
76 #undef e_rtsel
77 #undef e_one
78 #undef e_two
79 #undef e_pcrel
80 #undef e_con
81 #undef e_plabel
82 #undef e_abs
83
84 /* for compatibility */
85 enum hppa_reloc_field_selector_type_alt
86 {
87 e_fsel = R_HPPA_FSEL,
88 e_lssel = R_HPPA_LSSEL,
89 e_rssel = R_HPPA_RSSEL,
90 e_lsel = R_HPPA_LSEL,
91 e_rsel = R_HPPA_RSEL,
92 e_ldsel = R_HPPA_LDSEL,
93 e_rdsel = R_HPPA_RDSEL,
94 e_lrsel = R_HPPA_LRSEL,
95 e_rrsel = R_HPPA_RRSEL,
96 e_psel = R_HPPA_PSEL,
97 e_lpsel = R_HPPA_LPSEL,
98 e_rpsel = R_HPPA_RPSEL,
99 e_tsel = R_HPPA_TSEL,
100 e_ltsel = R_HPPA_LTSEL,
101 e_rtsel = R_HPPA_RTSEL
102 };
103
104 enum hppa_reloc_expr_type
105 {
106 R_HPPA_E_ONE = 0,
107 R_HPPA_E_TWO = 1,
108 R_HPPA_E_PCREL = 2,
109 R_HPPA_E_CON = 3,
110 R_HPPA_E_PLABEL = 7,
111 R_HPPA_E_ABS = 18
112 };
113
114 /* for compatibility */
115 enum hppa_reloc_expr_type_alt
116 {
117 e_one = R_HPPA_E_ONE,
118 e_two = R_HPPA_E_TWO,
119 e_pcrel = R_HPPA_E_PCREL,
120 e_con = R_HPPA_E_CON,
121 e_plabel = R_HPPA_E_PLABEL,
122 e_abs = R_HPPA_E_ABS
123 };
124
125
126 /* Relocations for function calls must be accompanied by parameter
127 relocation bits. These bits describe exactly where the caller has
128 placed the function's arguments and where it expects to find a return
129 value.
130
131 Both ELF and SOM encode this information within the addend field
132 of the call relocation. (Note this could break very badly if one
133 was to make a call like bl foo + 0x12345678).
134
135 The high order 10 bits contain parameter relocation information,
136 the low order 22 bits contain the constant offset. */
137
138 #define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
139 #define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
140 #define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
141
142 /* Some functions to manipulate PA instructions. */
143 static INLINE unsigned int
144 assemble_3 (x)
145 unsigned int x;
146 {
147 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
148 }
149
150 static INLINE void
151 dis_assemble_3 (x, r)
152 unsigned int x;
153 unsigned int *r;
154 {
155 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
156 }
157
158 static INLINE unsigned int
159 assemble_12 (x, y)
160 unsigned int x, y;
161 {
162 return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
163 }
164
165 static INLINE void
166 dis_assemble_12 (as12, x, y)
167 unsigned int as12;
168 unsigned int *x, *y;
169 {
170 *y = (as12 & 0x800) >> 11;
171 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
172 }
173
174 static INLINE unsigned long
175 assemble_17 (x, y, z)
176 unsigned int x, y, z;
177 {
178 unsigned long temp;
179
180 temp = ((z & 1) << 16) |
181 ((x & 0x1f) << 11) |
182 ((y & 1) << 10) |
183 ((y & 0x7fe) >> 1);
184 return temp & 0x1ffff;
185 }
186
187 static INLINE void
188 dis_assemble_17 (as17, x, y, z)
189 unsigned int as17;
190 unsigned int *x, *y, *z;
191 {
192
193 *z = (as17 & 0x10000) >> 16;
194 *x = (as17 & 0x0f800) >> 11;
195 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
196 }
197
198 static INLINE unsigned long
199 assemble_21 (x)
200 unsigned int x;
201 {
202 unsigned long temp;
203
204 temp = ((x & 1) << 20) |
205 ((x & 0xffe) << 8) |
206 ((x & 0xc000) >> 7) |
207 ((x & 0x1f0000) >> 14) |
208 ((x & 0x003000) >> 12);
209 return temp & 0x1fffff;
210 }
211
212 static INLINE void
213 dis_assemble_21 (as21, x)
214 unsigned int as21, *x;
215 {
216 unsigned long temp;
217
218
219 temp = (as21 & 0x100000) >> 20;
220 temp |= (as21 & 0x0ffe00) >> 8;
221 temp |= (as21 & 0x000180) << 7;
222 temp |= (as21 & 0x00007c) << 14;
223 temp |= (as21 & 0x000003) << 12;
224 *x = temp;
225 }
226
227 static INLINE unsigned long
228 sign_ext (x, len)
229 unsigned int x, len;
230 {
231 return (x << (32 - len)) >> (32 - len);
232 }
233
234 static INLINE unsigned int
235 ones (n)
236 int n;
237 {
238 unsigned int len_ones;
239 int i;
240
241 i = 0;
242 len_ones = 0;
243 while (i < n)
244 {
245 len_ones = (len_ones << 1) | 1;
246 i++;
247 }
248
249 return len_ones;
250 }
251
252 static INLINE void
253 sign_unext (x, len, result)
254 unsigned int x, len;
255 unsigned int *result;
256 {
257 unsigned int len_ones;
258
259 len_ones = ones (len);
260
261 *result = x & len_ones;
262 }
263
264 static INLINE unsigned long
265 low_sign_ext (x, len)
266 unsigned int x, len;
267 {
268 unsigned int temp1, temp2;
269 unsigned int len_ones;
270
271 len_ones = ones (len);
272
273 temp1 = (x & 1) << (len - 1);
274 temp2 = ((x & 0xfffffffe) & len_ones) >> 1;
275 return sign_ext ((temp1 | temp2), len);
276 }
277
278 static INLINE void
279 low_sign_unext (x, len, result)
280 unsigned int x, len;
281 unsigned int *result;
282 {
283 unsigned int temp;
284 unsigned int sign;
285 unsigned int rest;
286 unsigned int one_bit_at_len;
287 unsigned int len_ones;
288
289 len_ones = ones (len);
290 one_bit_at_len = 1 << (len - 1);
291
292 sign_unext (x, len, &temp);
293 sign = temp & one_bit_at_len;
294 sign >>= (len - 1);
295
296 rest = temp & (len_ones ^ one_bit_at_len);
297 rest <<= 1;
298
299 *result = rest | sign;
300 }
301
302 /* Handle field selectors for PA instructions. */
303
304 static INLINE unsigned long
305 hppa_field_adjust (value, constant_value, r_field)
306 unsigned long value;
307 unsigned long constant_value;
308 unsigned short r_field;
309 {
310 value += constant_value;
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 */