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