1/* HP PA-RISC SOM object file format:  definitions internal to BFD.
2   Copyright (C) 1990-2022 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.  */
31enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20, pa20w = 25};
32
33/* HP PA-RISC relocation types */
34
35enum 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 */
90enum 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
114enum 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 */
125enum 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
162static inline unsigned ATTRIBUTE_UNUSED
163sign_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
170static inline unsigned ATTRIBUTE_UNUSED
171low_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
181static inline unsigned ATTRIBUTE_UNUSED
182sign_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
191static inline unsigned ATTRIBUTE_UNUSED
192low_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
204static inline unsigned ATTRIBUTE_UNUSED
205re_assemble_3 (unsigned as3)
206{
207  return ((  (as3 & 4) << (13-2))
208	  | ((as3 & 3) << (13+1)));
209}
210
211static inline unsigned ATTRIBUTE_UNUSED
212re_assemble_12 (unsigned as12)
213{
214  return ((  (as12 & 0x800) >> 11)
215	  | ((as12 & 0x400) >> (10 - 2))
216	  | ((as12 & 0x3ff) << (1 + 2)));
217}
218
219static inline unsigned ATTRIBUTE_UNUSED
220re_assemble_14 (unsigned as14)
221{
222  return ((  (as14 & 0x1fff) << 1)
223	  | ((as14 & 0x2000) >> 13));
224}
225
226static inline unsigned ATTRIBUTE_UNUSED
227re_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
237static inline unsigned ATTRIBUTE_UNUSED
238re_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
246static inline unsigned ATTRIBUTE_UNUSED
247re_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
256static inline unsigned ATTRIBUTE_UNUSED
257re_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
277static inline bfd_signed_vma ATTRIBUTE_UNUSED
278hppa_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
363enum 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
443static inline unsigned ATTRIBUTE_UNUSED
444bfd_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
525static inline unsigned ATTRIBUTE_UNUSED
526hppa_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 */
576