revert yesterdays change
[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 /* The PA instruction set variants. */
38 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
39
40 /* HP PA-RISC relocation types */
41
42 enum 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,
53 R_HPPA_NSEL = 0x9,
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
62 };
63
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
78 #undef e_nsel
79 #undef e_nlsel
80 #undef e_nlrsel
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
94 /* for compatibility */
95 enum 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,
106 e_nsel = R_HPPA_NSEL,
107 e_nlsel = R_HPPA_NLSEL,
108 e_nlrsel = R_HPPA_NLRSEL,
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 };
116
117 enum 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 };
126
127 /* for compatibility */
128 enum 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
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
155 /* Some functions to manipulate PA instructions. */
156 static INLINE unsigned int
157 assemble_3 (x)
158 unsigned int x;
159 {
160 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
161 }
162
163 static INLINE void
164 dis_assemble_3 (x, r)
165 unsigned int x;
166 unsigned int *r;
167 {
168 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
169 }
170
171 static INLINE unsigned int
172 assemble_12 (x, y)
173 unsigned int x, y;
174 {
175 return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
176 }
177
178 static INLINE void
179 dis_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 }
186
187 static INLINE unsigned long
188 assemble_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
200 static INLINE void
201 dis_assemble_17 (as17, x, y, z)
202 unsigned int as17;
203 unsigned int *x, *y, *z;
204 {
205
206 *z = (as17 & 0x10000) >> 16;
207 *x = (as17 & 0x0f800) >> 11;
208 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
209 }
210
211 static INLINE unsigned long
212 assemble_21 (x)
213 unsigned int x;
214 {
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
225 static INLINE void
226 dis_assemble_21 (as21, x)
227 unsigned int as21, *x;
228 {
229 unsigned long temp;
230
231
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 }
239
240 static INLINE unsigned long
241 sign_extend (x, len)
242 unsigned int x, len;
243 {
244 return (int)(x >> (len - 1) ? (-1 << len) | x : x);
245 }
246
247 static INLINE unsigned int
248 ones (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
265 static INLINE void
266 sign_unext (x, len, result)
267 unsigned int x, len;
268 unsigned int *result;
269 {
270 unsigned int len_ones;
271
272 len_ones = ones (len);
273
274 *result = x & len_ones;
275 }
276
277 static INLINE unsigned long
278 low_sign_extend (x, len)
279 unsigned int x, len;
280 {
281 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
282 }
283
284 static INLINE void
285 low_sign_unext (x, len, result)
286 unsigned int x, len;
287 unsigned int *result;
288 {
289 unsigned int temp;
290 unsigned int sign;
291 unsigned int rest;
292 unsigned int one_bit_at_len;
293 unsigned int len_ones;
294
295 len_ones = ones (len);
296 one_bit_at_len = 1 << (len - 1);
297
298 sign_unext (x, len, &temp);
299 sign = temp & one_bit_at_len;
300 sign >>= (len - 1);
301
302 rest = temp & (len_ones ^ one_bit_at_len);
303 rest <<= 1;
304
305 *result = rest | sign;
306 }
307
308 /* Handle field selectors for PA instructions. */
309
310 static INLINE unsigned long
311 hppa_field_adjust (value, constant_value, r_field)
312 unsigned long value;
313 unsigned long constant_value;
314 unsigned short r_field;
315 {
316 switch (r_field)
317 {
318 case e_fsel: /* F : no change */
319 case e_nsel: /* N : no change */
320 value += constant_value;
321 break;
322
323 case e_lssel: /* LS : if (bit 21) then add 0x800
324 arithmetic shift right 11 bits */
325 value += constant_value;
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 */
332 value += constant_value;
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 */
340 case e_nlsel: /* NL : Arithmetic shift right 11 bits */
341 value += constant_value;
342 value = (value & 0xfffff800) >> 11;
343 break;
344
345 case e_rsel: /* R : Set bits 0-20 to zero */
346 value += constant_value;
347 value = value & 0x7ff;
348 break;
349
350 case e_ldsel: /* LD : Add 0x800, arithmetic shift
351 right 11 bits */
352 value += constant_value;
353 value += 0x800;
354 value = (value & 0xfffff800) >> 11;
355 break;
356
357 case e_rdsel: /* RD : Set bits 0-20 to one */
358 value += constant_value;
359 value |= 0xfffff800;
360 break;
361
362 case e_lrsel: /* LR : L with "rounded" constant */
363 case e_nlrsel: /* NLR : NL with "rounded" constant */
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 }
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
428 static INLINE char
429 bfd_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
487 static INLINE unsigned long
488 hppa_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
549 #endif /* _HPPA_H */
This page took 0.044681 seconds and 5 git commands to generate.