GNU Binutils v2.34
[binutils.git] / bfd / libhppa.h
1 /* HP PA-RISC SOM object file format:  definitions internal to BFD.
2    Copyright (C) 1990-2020 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) & 0x3fffff) ^ 0x200000) - 0x200000)
152 #define HPPA_R_ADDEND(r, c)     \
153   (((r) << 22) + ((c) & 0x3fffff))
154
155
156 /* Some functions to manipulate PA instructions.  */
157
158 /* The *sign_extend functions are used to assemble various bitfields
159    taken from an instruction and return the resulting immediate
160    value.  */
161
162 static inline unsigned ATTRIBUTE_UNUSED
163 sign_extend (unsigned x, unsigned len)
164 {
165   unsigned signbit = (1 << (len - 1));
166   unsigned mask = (signbit << 1) - 1;
167   return ((x & mask) ^ signbit) - signbit;
168 }
169
170 static inline unsigned ATTRIBUTE_UNUSED
171 low_sign_extend (unsigned x, unsigned len)
172 {
173   return (x >> 1) - ((x & 1) << (len - 1));
174 }
175
176
177 /* The re_assemble_* functions prepare an immediate value for
178    insertion into an opcode. pa-risc uses all sorts of weird bitfields
179    in the instruction to hold the value.  */
180
181 static inline unsigned ATTRIBUTE_UNUSED
182 sign_unext (unsigned x, unsigned len)
183 {
184   unsigned len_ones;
185
186   len_ones = (1 << len) - 1;
187
188   return x & len_ones;
189 }
190
191 static inline unsigned ATTRIBUTE_UNUSED
192 low_sign_unext (unsigned x, unsigned len)
193 {
194   unsigned temp;
195   unsigned sign;
196
197   sign = (x >> (len-1)) & 1;
198
199   temp = sign_unext (x, len-1);
200
201   return (temp << 1) | sign;
202 }
203
204 static inline unsigned ATTRIBUTE_UNUSED
205 re_assemble_3 (unsigned as3)
206 {
207   return ((  (as3 & 4) << (13-2))
208           | ((as3 & 3) << (13+1)));
209 }
210
211 static inline unsigned ATTRIBUTE_UNUSED
212 re_assemble_12 (unsigned as12)
213 {
214   return ((  (as12 & 0x800) >> 11)
215           | ((as12 & 0x400) >> (10 - 2))
216           | ((as12 & 0x3ff) << (1 + 2)));
217 }
218
219 static inline unsigned ATTRIBUTE_UNUSED
220 re_assemble_14 (unsigned as14)
221 {
222   return ((  (as14 & 0x1fff) << 1)
223           | ((as14 & 0x2000) >> 13));
224 }
225
226 static inline unsigned ATTRIBUTE_UNUSED
227 re_assemble_16 (unsigned as16)
228 {
229   unsigned s, t;
230
231   /* Unusual 16-bit encoding, for wide mode only.  */
232   t = (as16 << 1) & 0xffff;
233   s = (as16 & 0x8000);
234   return (t ^ s ^ (s >> 1)) | (s >> 15);
235 }
236
237 static inline unsigned ATTRIBUTE_UNUSED
238 re_assemble_17 (unsigned as17)
239 {
240   return ((  (as17 & 0x10000) >> 16)
241           | ((as17 & 0x0f800) << (16 - 11))
242           | ((as17 & 0x00400) >> (10 - 2))
243           | ((as17 & 0x003ff) << (1 + 2)));
244 }
245
246 static inline unsigned ATTRIBUTE_UNUSED
247 re_assemble_21 (unsigned as21)
248 {
249   return ((  (as21 & 0x100000) >> 20)
250           | ((as21 & 0x0ffe00) >> 8)
251           | ((as21 & 0x000180) << 7)
252           | ((as21 & 0x00007c) << 14)
253           | ((as21 & 0x000003) << 12));
254 }
255
256 static inline unsigned ATTRIBUTE_UNUSED
257 re_assemble_22 (unsigned as22)
258 {
259   return ((  (as22 & 0x200000) >> 21)
260           | ((as22 & 0x1f0000) << (21 - 16))
261           | ((as22 & 0x00f800) << (16 - 11))
262           | ((as22 & 0x000400) >> (10 - 2))
263           | ((as22 & 0x0003ff) << (1 + 2)));
264 }
265
266
267 /* Handle field selectors for PA instructions.
268    The L and R (and LS, RS etc.) selectors are used in pairs to form a
269    full 32 bit address.  eg.
270
271    LDIL L'start,%r1             ; put left part into r1
272    LDW  R'start(%r1),%r2        ; add r1 and right part to form address
273
274    This function returns sign extended values in all cases.
275 */
276
277 static inline bfd_signed_vma ATTRIBUTE_UNUSED
278 hppa_field_adjust (bfd_vma sym_val,
279                    bfd_signed_vma addend,
280                    enum hppa_reloc_field_selector_type_alt r_field)
281 {
282   bfd_signed_vma value;
283
284   value = sym_val + addend;
285   switch (r_field)
286     {
287     case e_fsel:
288       /* F: No change.  */
289       break;
290
291     case e_nsel:
292       /* N: null selector.  I don't really understand what this is all
293          about, but HP's documentation says "this indicates that zero
294          bits are to be used for the displacement on the instruction.
295          This fixup is used to identify three-instruction sequences to
296          access data (for importing shared library data)."  */
297       value = 0;
298       break;
299
300     case e_lsel:
301     case e_nlsel:
302       /* L:  Select top 21 bits.  */
303       value = value >> 11;
304       break;
305
306     case e_rsel:
307       /* R:  Select bottom 11 bits.  */
308       value = value & 0x7ff;
309       break;
310
311     case e_lssel:
312       /* LS:  Round to nearest multiple of 2048 then select top 21 bits.  */
313       value = value + 0x400;
314       value = value >> 11;
315       break;
316
317     case e_rssel:
318       /* RS:  Select bottom 11 bits for LS.
319          We need to return a value such that 2048 * LS'x + RS'x == x.
320          ie. RS'x = x - ((x + 0x400) & -0x800)
321          this is just a sign extension from bit 21.  */
322       value = ((value & 0x7ff) ^ 0x400) - 0x400;
323       break;
324
325     case e_ldsel:
326       /* LD:  Round to next multiple of 2048 then select top 21 bits.
327          Yes, if we are already on a multiple of 2048, we go up to the
328          next one.  RD in this case will be -2048.  */
329       value = value + 0x800;
330       value = value >> 11;
331       break;
332
333     case e_rdsel:
334       /* RD:  Set bits 0-20 to one.  */
335       value = value | -0x800;
336       break;
337
338     case e_lrsel:
339     case e_nlrsel:
340       /* LR:  L with rounding of the addend to nearest 8k.  */
341       value = sym_val + ((addend + 0x1000) & -0x2000);
342       value = value >> 11;
343       break;
344
345     case e_rrsel:
346       /* RR:  R with rounding of the addend to nearest 8k.
347          We need to return a value such that 2048 * LR'x + RR'x == x
348          ie. RR'x = s+a - (s + (((a + 0x1000) & -0x2000) & -0x800))
349          .        = s+a - ((s & -0x800) + ((a + 0x1000) & -0x2000))
350          .        = (s & 0x7ff) + a - ((a + 0x1000) & -0x2000)  */
351       value = (sym_val & 0x7ff) + (((addend & 0x1fff) ^ 0x1000) - 0x1000);
352       break;
353
354     default:
355       abort ();
356     }
357   return value;
358 }
359
360 /* PA-RISC OPCODES */
361 #define get_opcode(insn)        (((insn) >> 26) & 0x3f)
362
363 enum hppa_opcode_type
364 {
365   /* None of the opcodes in the first group generate relocs, so we
366      aren't too concerned about them.  */
367   OP_SYSOP   = 0x00,
368   OP_MEMMNG  = 0x01,
369   OP_ALU     = 0x02,
370   OP_NDXMEM  = 0x03,
371   OP_SPOP    = 0x04,
372   OP_DIAG    = 0x05,
373   OP_FMPYADD = 0x06,
374   OP_UNDEF07 = 0x07,
375   OP_COPRW   = 0x09,
376   OP_COPRDW  = 0x0b,
377   OP_COPR    = 0x0c,
378   OP_FLOAT   = 0x0e,
379   OP_PRDSPEC = 0x0f,
380   OP_UNDEF15 = 0x15,
381   OP_UNDEF1d = 0x1d,
382   OP_FMPYSUB = 0x26,
383   OP_FPFUSED = 0x2e,
384   OP_SHEXDP0 = 0x34,
385   OP_SHEXDP1 = 0x35,
386   OP_SHEXDP2 = 0x36,
387   OP_UNDEF37 = 0x37,
388   OP_SHEXDP3 = 0x3c,
389   OP_SHEXDP4 = 0x3d,
390   OP_MULTMED = 0x3e,
391   OP_UNDEF3f = 0x3f,
392
393   OP_LDIL    = 0x08,
394   OP_ADDIL   = 0x0a,
395
396   OP_LDO     = 0x0d,
397   OP_LDB     = 0x10,
398   OP_LDH     = 0x11,
399   OP_LDW     = 0x12,
400   OP_LDWM    = 0x13,
401   OP_STB     = 0x18,
402   OP_STH     = 0x19,
403   OP_STW     = 0x1a,
404   OP_STWM    = 0x1b,
405
406   OP_LDD     = 0x14,
407   OP_STD     = 0x1c,
408
409   OP_FLDW    = 0x16,
410   OP_LDWL    = 0x17,
411   OP_FSTW    = 0x1e,
412   OP_STWL    = 0x1f,
413
414   OP_COMBT   = 0x20,
415   OP_COMIBT  = 0x21,
416   OP_COMBF   = 0x22,
417   OP_COMIBF  = 0x23,
418   OP_CMPBDT  = 0x27,
419   OP_ADDBT   = 0x28,
420   OP_ADDIBT  = 0x29,
421   OP_ADDBF   = 0x2a,
422   OP_ADDIBF  = 0x2b,
423   OP_CMPBDF  = 0x2f,
424   OP_BVB     = 0x30,
425   OP_BB      = 0x31,
426   OP_MOVB    = 0x32,
427   OP_MOVIB   = 0x33,
428   OP_CMPIBD  = 0x3b,
429
430   OP_COMICLR = 0x24,
431   OP_SUBI    = 0x25,
432   OP_ADDIT   = 0x2c,
433   OP_ADDI    = 0x2d,
434
435   OP_BE      = 0x38,
436   OP_BLE     = 0x39,
437   OP_BL      = 0x3a
438 };
439
440
441 /* Given a machine instruction, return its format.  */
442
443 static inline unsigned ATTRIBUTE_UNUSED
444 bfd_hppa_insn2fmt (bfd *abfd, unsigned insn)
445 {
446   enum hppa_opcode_type op = (enum hppa_opcode_type) get_opcode (insn);
447
448   switch (op)
449     {
450     case OP_COMICLR:
451     case OP_SUBI:
452     case OP_ADDIT:
453     case OP_ADDI:
454       return 11;
455
456     case OP_COMBT:
457     case OP_COMIBT:
458     case OP_COMBF:
459     case OP_COMIBF:
460     case OP_CMPBDT:
461     case OP_ADDBT:
462     case OP_ADDIBT:
463     case OP_ADDBF:
464     case OP_ADDIBF:
465     case OP_CMPBDF:
466     case OP_BVB:
467     case OP_BB:
468     case OP_MOVB:
469     case OP_MOVIB:
470     case OP_CMPIBD:
471       return 12;
472
473     case OP_LDO:
474     case OP_LDB:
475     case OP_LDH:
476     case OP_LDW:
477     case OP_LDWM:
478     case OP_STB:
479     case OP_STH:
480     case OP_STW:
481     case OP_STWM:
482       if (abfd->arch_info->mach >= 25)
483         return 16;      /* Wide mode, format 16.  */
484       return 14;
485
486     case OP_FLDW:
487     case OP_LDWL:
488     case OP_FSTW:
489     case OP_STWL:
490       /* This is a hack.  Unfortunately, format 11 is already taken
491          and we're using integers rather than an enum, so it's hard
492          to describe the 11a format.  */
493       if (abfd->arch_info->mach >= 25)
494         return -16;     /* Wide mode, format 16a.  */
495       return -11;
496
497     case OP_LDD:
498     case OP_STD:
499       if (abfd->arch_info->mach >= 25)
500         return -10;     /* Wide mode, format 10a.  */
501       return 10;
502
503     case OP_BL:
504       if ((insn & 0x8000) != 0)
505         return 22;
506       /* fall thru */
507     case OP_BE:
508     case OP_BLE:
509       return 17;
510
511     case OP_LDIL:
512     case OP_ADDIL:
513       return 21;
514
515     default:
516       break;
517     }
518   return 32;
519 }
520
521
522 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
523    bits to change.  */
524
525 static inline unsigned ATTRIBUTE_UNUSED
526 hppa_rebuild_insn (unsigned insn, unsigned value, int r_format)
527 {
528   switch (r_format)
529     {
530     case 11:
531       return (insn & ~ 0x7ff) | low_sign_unext (value, 11);
532
533     case 12:
534       return (insn & ~ 0x1ffd) | re_assemble_12 (value);
535
536
537     case 10:
538       return (insn & ~ 0x3ff1) | re_assemble_14 (value & -8);
539
540     case -11:
541       return (insn & ~ 0x3ff9) | re_assemble_14 (value & -4);
542
543     case 14:
544       return (insn & ~ 0x3fff) | re_assemble_14 (value);
545
546
547     case -10:
548       return (insn & ~ 0xfff1) | re_assemble_16 (value & -8);
549
550     case -16:
551       return (insn & ~ 0xfff9) | re_assemble_16 (value & -4);
552
553     case 16:
554       return (insn & ~ 0xffff) | re_assemble_16 (value);
555
556
557     case 17:
558       return (insn & ~ 0x1f1ffd) | re_assemble_17 (value);
559
560     case 21:
561       return (insn & ~ 0x1fffff) | re_assemble_21 (value);
562
563     case 22:
564       return (insn & ~ 0x3ff1ffd) | re_assemble_22 (value);
565
566     case 32:
567       return value;
568
569     default:
570       abort ();
571     }
572   return insn;
573 }
574
575 #endif /* _LIBHPPA_H */