Fix typo in last check-in.
[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 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 */
This page took 0.040607 seconds and 5 git commands to generate.