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