1 /*
2  *  Copyright (C) 2005-2011  Anders Gavare.  All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions are met:
6  *
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. The name of the author may not be used to endorse or promote products
13  *     derived from this software without specific prior written permission.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  *  SUCH DAMAGE.
26  *
27  *
28  *  Alpha ALU instructions.  (Included from tmp_alpha_misc.c.)
29  *
30  *
31  *  Most ALU instructions have the following arguments:
32  *
33  *  arg[0] = pointer to destination uint64_t
34  *  arg[1] = pointer to source uint64_t nr 1
35  *  arg[2] = pointer to source uint64_t nr 2
36  *
37  *  or, if ALU_IMM is set, arg[2] contains an 8-bit immediate value.
38  *
39  *  The main function groups are:
40  *
41  *	ALU_INS				inserts
42  *	ALU_EXT				extracts
43  *	ALU_MSK				masks
44  *	ALU_CMOV			conditional moves
45  *	ALU_CMP				compares
46  *	ALU_CMPBGE			byte compare
47  *	none of the above		everything else (add, sub, ...)
48  */
49 
ALU_N(struct cpu * cpu,struct alpha_instr_call * ic)50 void ALU_N(struct cpu *cpu, struct alpha_instr_call *ic)
51 {
52 #ifdef ALU_INS
53 
54 	uint64_t x = *((uint64_t *)ic->arg[1]);
55 	int r = (
56 #ifdef ALU_IMM
57 	    ic->arg[2]
58 #else
59 	    (*((uint64_t *)ic->arg[2]))
60 #endif
61 	    & 7) * 8;
62 
63 #ifdef ALU_B
64 	x &= 0xff;
65 #endif
66 #ifdef ALU_W
67 	x &= 0xffff;
68 #endif
69 #ifdef ALU_L
70 	x &= 0xffffffffULL;
71 #endif
72 
73 #ifdef ALU_LO
74 	x <<= r;
75 #else
76 	r = 64 - r;
77 	if (r == 64)
78 		x = 0;
79 	else
80 		x >>= r;
81 #endif
82 	*((uint64_t *)ic->arg[0]) = x;
83 
84 #else	/*  ! INS  */
85 
86 #ifdef ALU_EXT
87 
88 	uint64_t x = *((uint64_t *)ic->arg[1]);
89 	int r = (
90 #ifdef ALU_IMM
91 	    ic->arg[2]
92 #else
93 	    (*((uint64_t *)ic->arg[2]))
94 #endif
95 	    & 7) * 8;
96 #ifdef ALU_LO
97 	x >>= r;
98 #else
99 	r = 64 - r;
100 	if (r != 64)
101 		x <<= r;
102 #endif
103 #ifdef ALU_B
104 	x &= 0xff;
105 #endif
106 #ifdef ALU_W
107 	x &= 0xffff;
108 #endif
109 #ifdef ALU_L
110 	x &= 0xffffffffULL;
111 #endif
112 	*((uint64_t *)ic->arg[0]) = x;
113 
114 #else	/*  ! EXT  */
115 
116 #ifdef ALU_MSK
117 
118 	uint64_t x = *((uint64_t *)ic->arg[1]);
119 #ifdef ALU_B
120 	uint64_t mask = 0x00000000000000ffULL;
121 #endif
122 #ifdef ALU_W
123 	uint64_t mask = 0x000000000000ffffULL;
124 #endif
125 #ifdef ALU_L
126 	uint64_t mask = 0x00000000ffffffffULL;
127 #endif
128 #ifdef ALU_Q
129 	uint64_t mask = 0xffffffffffffffffULL;
130 #endif
131 	int r = (
132 #ifdef ALU_IMM
133 	    ic->arg[2]
134 #else
135 	    (*((uint64_t *)ic->arg[2]))
136 #endif
137 	    & 7) * 8;
138 
139 #ifdef ALU_LO
140 	mask <<= r;
141 #else
142 	if (r == 0)
143 		mask = 0;
144 	else
145 		mask >>= (64 - r);
146 #endif
147 
148 	*((uint64_t *)ic->arg[0]) = x & ~mask;
149 
150 #else	/*  !MSK  */
151 
152 #ifdef ALU_CMOV
153 
154 	if (
155 #ifdef ALU_CMOV_lbc
156 	    !(
157 #endif
158 	    (*((int64_t *)ic->arg[1]))
159 #ifdef ALU_CMOV_eq
160 	    == 0
161 #endif
162 #ifdef ALU_CMOV_ne
163 	    != 0
164 #endif
165 #ifdef ALU_CMOV_le
166 	    <= 0
167 #endif
168 #ifdef ALU_CMOV_lt
169 	    < 0
170 #endif
171 #ifdef ALU_CMOV_ge
172 	    >= 0
173 #endif
174 #ifdef ALU_CMOV_gt
175 	    > 0
176 #endif
177 #ifdef ALU_CMOV_lbs
178 	    & 1
179 #endif
180 #ifdef ALU_CMOV_lbc
181 	    & 1)
182 #endif
183 	    )
184 		*((uint64_t *)ic->arg[0]) =
185 #ifdef ALU_IMM
186 		    (uint64_t)ic->arg[2]
187 #else
188 		    (*((uint64_t *)ic->arg[2]))
189 #endif
190 		    ;
191 
192 #else	/*  ! CMOV  */
193 
194 #ifdef ALU_CMPBGE
195 
196 	uint64_t ra = *((uint64_t *)ic->arg[1]), rc = 0, rb =
197 #ifdef ALU_IMM
198 		    (uint64_t)ic->arg[2]
199 #else
200 		    (*((uint64_t *)ic->arg[2]))
201 #endif
202 		    ;
203 	int i;
204 	for (i=7; i>=0; i--) {
205 		if ((uint8_t)ra >= (uint8_t)rb)
206 			rc |= (1 << i);
207 		rb >>= 8; ra >>= 8;
208 	}
209 
210 	*((uint64_t *)ic->arg[0]) = rc;
211 
212 #else	/*  ! CMPBGE  */
213 
214 #ifdef ALU_CMP
215 
216 	uint64_t x;
217 
218 	x = (*((
219 #ifdef ALU_UNSIGNED
220 	    uint64_t
221 #else
222 	    int64_t
223 #endif
224 	    *)ic->arg[1]))
225 
226 #ifdef ALU_CMP_EQ
227 	    ==
228 #endif
229 #ifdef ALU_CMP_LE
230 	    <=
231 #endif
232 #ifdef ALU_CMP_LT
233 	    <
234 #endif
235 
236 #ifdef ALU_IMM
237 #ifdef ALU_UNSIGNED
238 	    (uint64_t)ic->arg[2]
239 #else
240 	    (int64_t)ic->arg[2]
241 #endif
242 #else
243 #ifdef ALU_UNSIGNED
244 	    (*((uint64_t *)ic->arg[2]))
245 #else
246 	    (*((int64_t *)ic->arg[2]))
247 #endif
248 #endif
249 	    ;
250 
251 #else	/*  !ALU_CMP  */
252 
253 #ifdef ALU_LONG
254 	/*  Long  */
255 	int32_t x;
256 #else
257 	/*  Quad  */
258 	int64_t x;
259 #endif
260 
261 #ifdef ALU_ZAP
262 	/*  Prepare for zapping:  */
263 	uint64_t zapmask = 0xffffffffffffffffULL;
264 	int zapbytes =
265 #ifdef ALU_NOT
266 	    ~
267 #endif
268 #ifdef ALU_IMM
269 	    (int64_t)ic->arg[2]
270 #else
271 	    (*((uint64_t *)ic->arg[2]))
272 #endif
273 	    ;
274 	if (zapbytes & 0x80)
275 		zapmask &= ~0xff00000000000000ULL;
276 	if (zapbytes & 0x40)
277 		zapmask &= ~0xff000000000000ULL;
278 	if (zapbytes & 0x20)
279 		zapmask &= ~0xff0000000000ULL;
280 	if (zapbytes & 0x10)
281 		zapmask &= ~0xff00000000ULL;
282 	if (zapbytes & 0x08)
283 		zapmask &= ~0xff000000ULL;
284 	if (zapbytes & 0x04)
285 		zapmask &= ~0xff0000ULL;
286 	if (zapbytes & 0x02)
287 		zapmask &= ~0xff00ULL;
288 	if (zapbytes & 0x01)
289 		zapmask &= ~0xffULL;
290 #endif	/*  ZAP  */
291 
292 	x = (
293 #ifdef ALU_SRA
294 	    (int64_t)
295 #endif
296 	    (*((uint64_t *)ic->arg[1]))
297 #ifdef ALU_S4
298 	    * 4
299 #endif
300 #ifdef ALU_S8
301 	    * 8
302 #endif
303 	    )
304 #ifdef ALU_ADD
305 	    +
306 #endif
307 #ifdef ALU_SUB
308 	    -
309 #endif
310 #ifdef ALU_OR
311 	    |
312 #endif
313 #ifdef ALU_XOR
314 	    ^
315 #endif
316 #ifdef ALU_AND
317 	    &
318 #endif
319 #ifdef ALU_SLL
320 	    <<
321 #endif
322 #if defined(ALU_SRA) || defined(ALU_SRL)
323 	    >>
324 #endif
325 
326 #ifdef ALU_ZAP
327 	    & zapmask
328 #else	/*  !ZAP  */
329 	    (
330 #ifdef ALU_NOT
331 	    ~
332 #endif
333 	    (
334 #ifdef ALU_IMM
335 	    (int64_t)ic->arg[2]
336 #else
337 	    (*((uint64_t *)ic->arg[2]))
338 #endif
339 #if defined(ALU_SRA) || defined(ALU_SRL) || defined(ALU_SLL)
340 	    & 63
341 #endif
342 	    )
343 	    )
344 #endif	/*  !ZAP  */
345 
346 	    ;
347 
348 #endif	/*  !ALU_CMP  */
349 
350 	*((uint64_t *)ic->arg[0]) = x;
351 #endif	/*  ! CMPBGE  */
352 #endif	/*  ! CMOV  */
353 #endif	/*  ! MSK  */
354 #endif	/*  ! EXT  */
355 #endif	/*  ! INS  */
356 }
357 
358