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