libhppa.h revision 1.4
1/* HP PA-RISC SOM object file format:  definitions internal to BFD.
2   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000
3   Free Software Foundation, Inc.
4
5   Contributed by the Center for Software Science at the
6   University of Utah (pa-gdb-bugs@cs.utah.edu).
7
8   This file is part of BFD, the Binary File Descriptor library.
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24#ifndef _LIBHPPA_H
25#define _LIBHPPA_H
26
27#define BYTES_IN_WORD 4
28#define PA_PAGESIZE 0x1000
29
30#ifndef INLINE
31#ifdef __GNUC__
32#define INLINE inline
33#else
34#define INLINE
35#endif /* GNU C? */
36#endif /* INLINE */
37
38/* The PA instruction set variants.  */
39enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20, pa20w = 25};
40
41/* HP PA-RISC relocation types */
42
43enum hppa_reloc_field_selector_type
44  {
45    R_HPPA_FSEL = 0x0,
46    R_HPPA_LSSEL = 0x1,
47    R_HPPA_RSSEL = 0x2,
48    R_HPPA_LSEL = 0x3,
49    R_HPPA_RSEL = 0x4,
50    R_HPPA_LDSEL = 0x5,
51    R_HPPA_RDSEL = 0x6,
52    R_HPPA_LRSEL = 0x7,
53    R_HPPA_RRSEL = 0x8,
54    R_HPPA_NSEL  = 0x9,
55    R_HPPA_NLSEL  = 0xa,
56    R_HPPA_NLRSEL  = 0xb,
57    R_HPPA_PSEL = 0xc,
58    R_HPPA_LPSEL = 0xd,
59    R_HPPA_RPSEL = 0xe,
60    R_HPPA_TSEL = 0xf,
61    R_HPPA_LTSEL = 0x10,
62    R_HPPA_RTSEL = 0x11,
63    R_HPPA_LTPSEL = 0x12,
64    R_HPPA_RTPSEL = 0x13
65  };
66
67/* /usr/include/reloc.h defines these to constants.  We want to use
68   them in enums, so #undef them before we start using them.  We might
69   be able to fix this another way by simply managing not to include
70   /usr/include/reloc.h, but currently GDB picks up these defines
71   somewhere.  */
72#undef e_fsel
73#undef e_lssel
74#undef e_rssel
75#undef e_lsel
76#undef e_rsel
77#undef e_ldsel
78#undef e_rdsel
79#undef e_lrsel
80#undef e_rrsel
81#undef e_nsel
82#undef e_nlsel
83#undef e_nlrsel
84#undef e_psel
85#undef e_lpsel
86#undef e_rpsel
87#undef e_tsel
88#undef e_ltsel
89#undef e_rtsel
90#undef e_one
91#undef e_two
92#undef e_pcrel
93#undef e_con
94#undef e_plabel
95#undef e_abs
96
97/* for compatibility */
98enum hppa_reloc_field_selector_type_alt
99  {
100    e_fsel = R_HPPA_FSEL,
101    e_lssel = R_HPPA_LSSEL,
102    e_rssel = R_HPPA_RSSEL,
103    e_lsel = R_HPPA_LSEL,
104    e_rsel = R_HPPA_RSEL,
105    e_ldsel = R_HPPA_LDSEL,
106    e_rdsel = R_HPPA_RDSEL,
107    e_lrsel = R_HPPA_LRSEL,
108    e_rrsel = R_HPPA_RRSEL,
109    e_nsel = R_HPPA_NSEL,
110    e_nlsel = R_HPPA_NLSEL,
111    e_nlrsel = R_HPPA_NLRSEL,
112    e_psel = R_HPPA_PSEL,
113    e_lpsel = R_HPPA_LPSEL,
114    e_rpsel = R_HPPA_RPSEL,
115    e_tsel = R_HPPA_TSEL,
116    e_ltsel = R_HPPA_LTSEL,
117    e_rtsel = R_HPPA_RTSEL,
118    e_ltpsel = R_HPPA_LTPSEL,
119    e_rtpsel = R_HPPA_RTPSEL
120  };
121
122enum hppa_reloc_expr_type
123  {
124    R_HPPA_E_ONE = 0,
125    R_HPPA_E_TWO = 1,
126    R_HPPA_E_PCREL = 2,
127    R_HPPA_E_CON = 3,
128    R_HPPA_E_PLABEL = 7,
129    R_HPPA_E_ABS = 18
130  };
131
132/* for compatibility */
133enum hppa_reloc_expr_type_alt
134  {
135    e_one = R_HPPA_E_ONE,
136    e_two = R_HPPA_E_TWO,
137    e_pcrel = R_HPPA_E_PCREL,
138    e_con = R_HPPA_E_CON,
139    e_plabel = R_HPPA_E_PLABEL,
140    e_abs = R_HPPA_E_ABS
141  };
142
143
144/* Relocations for function calls must be accompanied by parameter
145   relocation bits.  These bits describe exactly where the caller has
146   placed the function's arguments and where it expects to find a return
147   value.
148
149   Both ELF and SOM encode this information within the addend field
150   of the call relocation.  (Note this could break very badly if one
151   was to make a call like bl foo + 0x12345678).
152
153   The high order 10 bits contain parameter relocation information,
154   the low order 22 bits contain the constant offset.  */
155
156#define HPPA_R_ARG_RELOC(a)	\
157  (((a) >> 22) & 0x3ff)
158#define HPPA_R_CONSTANT(a)	\
159  ((((bfd_signed_vma)(a)) << (BFD_ARCH_SIZE-22)) >> (BFD_ARCH_SIZE-22))
160#define HPPA_R_ADDEND(r, c)	\
161  (((r) << 22) + ((c) & 0x3fffff))
162
163
164/* Some functions to manipulate PA instructions.  */
165
166/* Declare the functions with the unused attribute to avoid warnings.  */
167static INLINE int sign_extend PARAMS ((int, int)) ATTRIBUTE_UNUSED;
168static INLINE int low_sign_extend PARAMS ((int, int)) ATTRIBUTE_UNUSED;
169static INLINE int sign_unext PARAMS ((int, int)) ATTRIBUTE_UNUSED;
170static INLINE int low_sign_unext PARAMS ((int, int)) ATTRIBUTE_UNUSED;
171static INLINE int re_assemble_3 PARAMS ((int)) ATTRIBUTE_UNUSED;
172static INLINE int re_assemble_12 PARAMS ((int)) ATTRIBUTE_UNUSED;
173static INLINE int re_assemble_14 PARAMS ((int)) ATTRIBUTE_UNUSED;
174static INLINE int re_assemble_16 PARAMS ((int)) ATTRIBUTE_UNUSED;
175static INLINE int re_assemble_17 PARAMS ((int)) ATTRIBUTE_UNUSED;
176static INLINE int re_assemble_21 PARAMS ((int)) ATTRIBUTE_UNUSED;
177static INLINE int re_assemble_22 PARAMS ((int)) ATTRIBUTE_UNUSED;
178static INLINE bfd_signed_vma hppa_field_adjust
179  PARAMS ((bfd_vma, bfd_signed_vma,
180	   enum hppa_reloc_field_selector_type_alt)) ATTRIBUTE_UNUSED;
181static INLINE int bfd_hppa_insn2fmt PARAMS ((bfd *, int)) ATTRIBUTE_UNUSED;
182static INLINE int hppa_rebuild_insn PARAMS ((int, int, int)) ATTRIBUTE_UNUSED;
183
184
185/* The *sign_extend functions are used to assemble various bitfields
186   taken from an instruction and return the resulting immediate
187   value.  */
188
189static INLINE int
190sign_extend (x, len)
191     int x, len;
192{
193  int signbit = (1 << (len - 1));
194  int mask = (signbit << 1) - 1;
195  return ((x & mask) ^ signbit) - signbit;
196}
197
198static INLINE int
199low_sign_extend (x, len)
200     int x, len;
201{
202  return (x >> 1) - ((x & 1) << (len - 1));
203}
204
205
206/* The re_assemble_* functions prepare an immediate value for
207   insertion into an opcode. pa-risc uses all sorts of weird bitfields
208   in the instruction to hold the value.  */
209
210static INLINE int
211sign_unext (x, len)
212     int x, len;
213{
214  int len_ones;
215
216  len_ones = (1 << len) - 1;
217
218  return x & len_ones;
219}
220
221static INLINE int
222low_sign_unext (x, len)
223     int x, len;
224{
225  int temp;
226  int sign;
227
228  sign = (x >> (len-1)) & 1;
229
230  temp = sign_unext (x, len-1);
231
232  return (temp << 1) | sign;
233}
234
235static INLINE int
236re_assemble_3 (as3)
237     int as3;
238{
239  return ((  (as3 & 4) << (13-2))
240	  | ((as3 & 3) << (13+1)));
241}
242
243static INLINE int
244re_assemble_12 (as12)
245     int as12;
246{
247  return ((  (as12 & 0x800) >> 11)
248	  | ((as12 & 0x400) >> (10 - 2))
249	  | ((as12 & 0x3ff) << (1 + 2)));
250}
251
252static INLINE int
253re_assemble_14 (as14)
254     int as14;
255{
256  return ((  (as14 & 0x1fff) << 1)
257	  | ((as14 & 0x2000) >> 13));
258}
259
260static INLINE int
261re_assemble_16 (as16)
262     int as16;
263{
264  int s, t;
265
266  /* Unusual 16-bit encoding, for wide mode only.  */
267  t = (as16 << 1) & 0xffff;
268  s = (as16 & 0x8000);
269  return (t ^ s ^ (s >> 1)) | (s >> 15);
270}
271
272static INLINE int
273re_assemble_17 (as17)
274     int as17;
275{
276  return ((  (as17 & 0x10000) >> 16)
277	  | ((as17 & 0x0f800) << (16 - 11))
278	  | ((as17 & 0x00400) >> (10 - 2))
279	  | ((as17 & 0x003ff) << (1 + 2)));
280}
281
282static INLINE int
283re_assemble_21 (as21)
284     int as21;
285{
286  return ((  (as21 & 0x100000) >> 20)
287	  | ((as21 & 0x0ffe00) >> 8)
288	  | ((as21 & 0x000180) << 7)
289	  | ((as21 & 0x00007c) << 14)
290	  | ((as21 & 0x000003) << 12));
291}
292
293static INLINE int
294re_assemble_22 (as22)
295     int as22;
296{
297  return ((  (as22 & 0x200000) >> 21)
298	  | ((as22 & 0x1f0000) << (21 - 16))
299	  | ((as22 & 0x00f800) << (16 - 11))
300	  | ((as22 & 0x000400) >> (10 - 2))
301	  | ((as22 & 0x0003ff) << (1 + 2)));
302}
303
304
305/* Handle field selectors for PA instructions.
306   The L and R (and LS, RS etc.) selectors are used in pairs to form a
307   full 32 bit address.  eg.
308
309   LDIL	L'start,%r1		; put left part into r1
310   LDW	R'start(%r1),%r2	; add r1 and right part to form address
311
312   This function returns sign extended values in all cases.
313*/
314
315static INLINE bfd_signed_vma
316hppa_field_adjust (sym_val, addend, r_field)
317     bfd_vma sym_val;
318     bfd_signed_vma addend;
319     enum hppa_reloc_field_selector_type_alt r_field;
320{
321  bfd_signed_vma value;
322
323  value = sym_val + addend;
324  switch (r_field)
325    {
326    case e_fsel:
327      /* F: No change.  */
328      break;
329
330    case e_nsel:
331      /* N: null selector.  I don't really understand what this is all
332	 about, but HP's documentation says "this indicates that zero
333	 bits are to be used for the displacement on the instruction.
334	 This fixup is used to identify three-instruction sequences to
335	 access data (for importing shared library data)."  */
336      value = 0;
337      break;
338
339    case e_lsel:
340    case e_nlsel:
341      /* L:  Select top 21 bits.  */
342      value = value >> 11;
343      break;
344
345    case e_rsel:
346      /* R:  Select bottom 11 bits.  */
347      value = value & 0x7ff;
348      break;
349
350    case e_lssel:
351      /* LS:  Round to nearest multiple of 2048 then select top 21 bits.  */
352      value = value + 0x400;
353      value = value >> 11;
354      break;
355
356    case e_rssel:
357      /* RS:  Select bottom 11 bits for LS.
358	 We need to return a value such that 2048 * LS'x + RS'x == x.
359	 ie. RS'x = x - ((x + 0x400) & -0x800)
360	 this is just a sign extension from bit 21.  */
361      value = ((value & 0x7ff) ^ 0x400) - 0x400;
362      break;
363
364    case e_ldsel:
365      /* LD:  Round to next multiple of 2048 then select top 21 bits.
366	 Yes, if we are already on a multiple of 2048, we go up to the
367	 next one.  RD in this case will be -2048.  */
368      value = value + 0x800;
369      value = value >> 11;
370      break;
371
372    case e_rdsel:
373      /* RD:  Set bits 0-20 to one.  */
374      value = value | -0x800;
375      break;
376
377    case e_lrsel:
378    case e_nlrsel:
379      /* LR:  L with rounding of the addend to nearest 8k.  */
380      value = sym_val + ((addend + 0x1000) & -0x2000);
381      value = value >> 11;
382      break;
383
384    case e_rrsel:
385      /* RR:  R with rounding of the addend to nearest 8k.
386	 We need to return a value such that 2048 * LR'x + RR'x == x
387	 ie. RR'x = s+a - (s + (((a + 0x1000) & -0x2000) & -0x800))
388	 .	  = s+a - ((s & -0x800) + ((a + 0x1000) & -0x2000))
389	 .	  = (s & 0x7ff) + a - ((a + 0x1000) & -0x2000)  */
390      value = (sym_val & 0x7ff) + (((addend & 0x1fff) ^ 0x1000) - 0x1000);
391      break;
392
393    default:
394      abort ();
395    }
396  return value;
397}
398
399/* PA-RISC OPCODES */
400#define get_opcode(insn)	(((insn) >> 26) & 0x3f)
401
402enum hppa_opcode_type
403{
404  /* None of the opcodes in the first group generate relocs, so we
405     aren't too concerned about them.  */
406  OP_SYSOP   = 0x00,
407  OP_MEMMNG  = 0x01,
408  OP_ALU     = 0x02,
409  OP_NDXMEM  = 0x03,
410  OP_SPOP    = 0x04,
411  OP_DIAG    = 0x05,
412  OP_FMPYADD = 0x06,
413  OP_UNDEF07 = 0x07,
414  OP_COPRW   = 0x09,
415  OP_COPRDW  = 0x0b,
416  OP_COPR    = 0x0c,
417  OP_FLOAT   = 0x0e,
418  OP_PRDSPEC = 0x0f,
419  OP_UNDEF15 = 0x15,
420  OP_UNDEF1d = 0x1d,
421  OP_FMPYSUB = 0x26,
422  OP_FPFUSED = 0x2e,
423  OP_SHEXDP0 = 0x34,
424  OP_SHEXDP1 = 0x35,
425  OP_SHEXDP2 = 0x36,
426  OP_UNDEF37 = 0x37,
427  OP_SHEXDP3 = 0x3c,
428  OP_SHEXDP4 = 0x3d,
429  OP_MULTMED = 0x3e,
430  OP_UNDEF3f = 0x3f,
431
432  OP_LDIL    = 0x08,
433  OP_ADDIL   = 0x0a,
434
435  OP_LDO     = 0x0d,
436  OP_LDB     = 0x10,
437  OP_LDH     = 0x11,
438  OP_LDW     = 0x12,
439  OP_LDWM    = 0x13,
440  OP_STB     = 0x18,
441  OP_STH     = 0x19,
442  OP_STW     = 0x1a,
443  OP_STWM    = 0x1b,
444
445  OP_LDD     = 0x14,
446  OP_STD     = 0x1c,
447
448  OP_FLDW    = 0x16,
449  OP_LDWL    = 0x17,
450  OP_FSTW    = 0x1e,
451  OP_STWL    = 0x1f,
452
453  OP_COMBT   = 0x20,
454  OP_COMIBT  = 0x21,
455  OP_COMBF   = 0x22,
456  OP_COMIBF  = 0x23,
457  OP_CMPBDT  = 0x27,
458  OP_ADDBT   = 0x28,
459  OP_ADDIBT  = 0x29,
460  OP_ADDBF   = 0x2a,
461  OP_ADDIBF  = 0x2b,
462  OP_CMPBDF  = 0x2f,
463  OP_BVB     = 0x30,
464  OP_BB      = 0x31,
465  OP_MOVB    = 0x32,
466  OP_MOVIB   = 0x33,
467  OP_CMPIBD  = 0x3b,
468
469  OP_COMICLR = 0x24,
470  OP_SUBI    = 0x25,
471  OP_ADDIT   = 0x2c,
472  OP_ADDI    = 0x2d,
473
474  OP_BE      = 0x38,
475  OP_BLE     = 0x39,
476  OP_BL      = 0x3a
477};
478
479
480/* Given a machine instruction, return its format.  */
481
482static INLINE int
483bfd_hppa_insn2fmt (abfd, insn)
484     bfd *abfd;
485     int insn;
486{
487  enum hppa_opcode_type op = get_opcode (insn);
488
489  switch (op)
490    {
491    case OP_COMICLR:
492    case OP_SUBI:
493    case OP_ADDIT:
494    case OP_ADDI:
495      return 11;
496
497    case OP_COMBT:
498    case OP_COMIBT:
499    case OP_COMBF:
500    case OP_COMIBF:
501    case OP_CMPBDT:
502    case OP_ADDBT:
503    case OP_ADDIBT:
504    case OP_ADDBF:
505    case OP_ADDIBF:
506    case OP_CMPBDF:
507    case OP_BVB:
508    case OP_BB:
509    case OP_MOVB:
510    case OP_MOVIB:
511    case OP_CMPIBD:
512      return 12;
513
514    case OP_LDO:
515    case OP_LDB:
516    case OP_LDH:
517    case OP_LDW:
518    case OP_LDWM:
519    case OP_STB:
520    case OP_STH:
521    case OP_STW:
522    case OP_STWM:
523      if (abfd->arch_info->mach >= 25)
524	return 16;	/* Wide mode, format 16.  */
525      return 14;
526
527    case OP_FLDW:
528    case OP_LDWL:
529    case OP_FSTW:
530    case OP_STWL:
531      /* This is a hack.  Unfortunately, format 11 is already taken
532	 and we're using integers rather than an enum, so it's hard
533	 to describe the 11a format.  */
534      if (abfd->arch_info->mach >= 25)
535	return -16;	/* Wide mode, format 16a.  */
536      return -11;
537
538    case OP_LDD:
539    case OP_STD:
540      if (abfd->arch_info->mach >= 25)
541	return -10;	/* Wide mode, format 10a.  */
542      return 10;
543
544    case OP_BL:
545      if ((insn & 0x8000) != 0)
546	return 22;
547      /* fall thru */
548    case OP_BE:
549    case OP_BLE:
550      return 17;
551
552    case OP_LDIL:
553    case OP_ADDIL:
554      return 21;
555
556    default:
557      break;
558    }
559  return 32;
560}
561
562
563/* Insert VALUE into INSN using R_FORMAT to determine exactly what
564   bits to change.  */
565
566static INLINE int
567hppa_rebuild_insn (insn, value, r_format)
568     int insn;
569     int value;
570     int r_format;
571{
572  switch (r_format)
573    {
574    case 11:
575      return (insn & ~ 0x7ff) | low_sign_unext (value, 11);
576
577    case 12:
578      return (insn & ~ 0x1ffd) | re_assemble_12 (value);
579
580
581    case 10:
582      return (insn & ~ 0x3ff1) | re_assemble_14 (value & -8);
583
584    case -11:
585      return (insn & ~ 0x3ff9) | re_assemble_14 (value & -4);
586
587    case 14:
588      return (insn & ~ 0x3fff) | re_assemble_14 (value);
589
590
591    case -10:
592      return (insn & ~ 0xfff1) | re_assemble_16 (value & -8);
593
594    case -16:
595      return (insn & ~ 0xfff9) | re_assemble_16 (value & -4);
596
597    case 16:
598      return (insn & ~ 0xffff) | re_assemble_16 (value);
599
600
601    case 17:
602      return (insn & ~ 0x1f1ffd) | re_assemble_17 (value);
603
604    case 21:
605      return (insn & ~ 0x1fffff) | re_assemble_21 (value);
606
607    case 22:
608      return (insn & ~ 0x3ff1ffd) | re_assemble_22 (value);
609
610    case 32:
611      return value;
612
613    default:
614      abort ();
615    }
616  return insn;
617}
618
619#endif /* _LIBHPPA_H */
620