1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#include <stdint.h>
24#include "stuff/hppa.h"
25/*
26 * calc_hppa_HILO() is the specific calculation for all left/right type relocs
27 * for the hppa relocation for the hp field selectors LR% RR% which allow
28 * sharing of the LR% when the round value of the offset is the same.
29 * See hppa/reloc.h for more infomation.
30 */
31__private_extern__
32void
33calc_hppa_HILO(
34uint32_t base,
35uint32_t offset,
36uint32_t *left21,
37uint32_t *right14)
38{
39    uint32_t rounded;
40
41	rounded = (offset + (0x2000/2)) & ~(0x2000 - 1);
42
43	*left21   = (base + rounded) & 0xfffff800;
44	*right14 = ((base + rounded) & 0x000007ff) + (offset - rounded);
45}
46
47/*
48 * 2 helper routines for branch displacement calculations on hppa
49 */
50__private_extern__
51uint32_t
52assemble_17(
53uint32_t x,
54uint32_t y,
55uint32_t z)
56{
57    uint32_t temp;
58
59	temp = ( ( z &     1 ) << 16 ) |
60	       ( ( x &  0x1f ) << 11 ) |
61	       ( ( y &     1 ) << 10 ) |
62	       ( ( y & 0x7fe ) >> 1);
63	if(z)
64	    temp |= 0xfffe0000;   /* sign extend it */
65	return(temp);
66}
67
68__private_extern__
69uint32_t
70assemble_21(
71uint32_t x)
72{
73    uint32_t temp;
74
75	temp = ( ( x &        1 ) << 20 ) |
76	       ( ( x &    0xffe ) <<  8 ) |
77	       ( ( x &   0xc000 ) >>  7 ) |
78	       ( ( x & 0x1f0000 ) >> 14 ) |
79	       ( ( x & 0x003000 ) >> 12 );
80	return(temp & 0x1fffff);
81}
82
83/*
84 * The following functions are all from hppa_ctrl_funcs.c in the assembler.
85 */
86__private_extern__
87uint32_t
88assemble_12(
89uint32_t x,
90uint32_t y)
91{
92    uint32_t temp;
93
94	temp = ( ( y     & 1 ) << 11 ) |
95	       ( ( x     & 1 ) << 10 ) |
96	       ( ( x & 0x7fe ) >> 1);
97	return(temp & 0xfff);
98}
99
100__private_extern__
101uint32_t
102assemble_3(
103uint32_t x)
104{
105    uint32_t temp;
106
107	temp = ( ( x & 1 ) << 2 ) |
108	       ( ( x & 6 ) >> 1 );
109	return(temp & 7);
110}
111
112__private_extern__
113uint32_t
114sign_ext(
115uint32_t x,
116uint32_t len)
117{
118    uint32_t sign;
119    uint32_t result;
120    uint32_t len_ones;
121    uint32_t i;
122
123	i = 0;
124	len_ones = 0;
125	while(i < len){
126	    len_ones = (len_ones << 1) | 1;
127	    i++;
128	}
129
130	sign = (x >> (len-1)) & 1;
131
132	if(sign)
133	    result = ( ~0 ^ len_ones ) | ( len_ones & x );
134	else
135	    result = len_ones & x;
136
137	return(result);
138}
139
140static
141uint32_t
142ones(
143uint32_t n)
144{
145    uint32_t len_ones;
146    uint32_t i;
147
148	i = 0;
149	len_ones = 0;
150	while(i < n){
151	    len_ones = (len_ones << 1) | 1;
152	    i++;
153	}
154	return(len_ones);
155}
156
157__private_extern__
158uint32_t
159low_sign_ext(
160uint32_t x,
161uint32_t len)
162{
163    uint32_t temp1, temp2;
164    uint32_t len_ones;
165
166	len_ones = ones(len);
167
168	temp1 = ( x & 1 ) << (len-1);
169	temp2 = ( ( x & 0xfffffffe ) & len_ones ) >> 1;
170	return(sign_ext( (temp1 | temp2),len));
171}
172
173__private_extern__
174uint32_t
175dis_assemble_21(
176uint32_t as21)
177{
178    uint32_t temp;
179
180	temp  = ( as21 & 0x100000 ) >> 20;
181	temp |= ( as21 & 0x0ffe00 ) >> 8;
182	temp |= ( as21 & 0x000180 ) << 7;
183	temp |= ( as21 & 0x00007c ) << 14;
184	temp |= ( as21 & 0x000003 ) << 12;
185	return(temp);
186}
187
188__private_extern__
189uint32_t
190low_sign_unext(
191uint32_t x,
192uint32_t len)
193{
194    uint32_t temp;
195    uint32_t sign;
196    uint32_t rest;
197    uint32_t one_bit_at_len;
198    uint32_t len_ones;
199
200	len_ones = ones(len);
201	one_bit_at_len = 1 << (len-1);
202
203	temp = sign_unext(x, len);
204	sign = temp & one_bit_at_len;
205	sign >>= (len - 1);
206
207	rest = temp & ( len_ones ^ one_bit_at_len );
208	rest <<= 1;
209
210	return(rest | sign);
211}
212
213__private_extern__
214void
215dis_assemble_17(
216uint32_t as17,
217uint32_t *x,
218uint32_t *y,
219uint32_t *z)
220{
221	*z =   ( as17 & 0x10000 ) >> 16;
222	*x =   ( as17 & 0x0f800 ) >> 11;
223	*y = ( ( as17 & 0x00400 ) >> 10 ) | ( ( as17 & 0x3ff ) << 1 );
224}
225
226__private_extern__
227uint32_t
228sign_unext(
229uint32_t x,
230uint32_t len)
231{
232    uint32_t len_ones;
233
234	len_ones = ones(len);
235	return(x & len_ones);
236}
237
238__private_extern__
239uint32_t
240dis_assemble_3(
241uint32_t x)
242{
243    uint32_t r;
244
245	r = ( ( (x & 4 ) >> 2 ) | ( ( x & 3 ) << 1 ) ) & 7;
246	return(r);
247}
248
249__private_extern__
250void
251dis_assemble_12(
252uint32_t as12,
253uint32_t *x,
254uint32_t *y)
255{
256	*y =   ( as12 & 0x800 ) >> 11;
257	*x = ( ( as12 & 0x3ff ) << 1 ) | ( ( as12 & 0x400 ) >> 10 );
258}
259