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