root / target-arm / op.c @ 6ddbc6e4
History | View | Annotate | Download (16.4 kB)
1 |
/*
|
---|---|
2 |
* ARM micro operations
|
3 |
*
|
4 |
* Copyright (c) 2003 Fabrice Bellard
|
5 |
* Copyright (c) 2005-2007 CodeSourcery, LLC
|
6 |
*
|
7 |
* This library is free software; you can redistribute it and/or
|
8 |
* modify it under the terms of the GNU Lesser General Public
|
9 |
* License as published by the Free Software Foundation; either
|
10 |
* version 2 of the License, or (at your option) any later version.
|
11 |
*
|
12 |
* This library is distributed in the hope that it will be useful,
|
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 |
* Lesser General Public License for more details.
|
16 |
*
|
17 |
* You should have received a copy of the GNU Lesser General Public
|
18 |
* License along with this library; if not, write to the Free Software
|
19 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
20 |
*/
|
21 |
#include "exec.h" |
22 |
|
23 |
void OPPROTO op_addl_T0_T1_cc(void) |
24 |
{ |
25 |
unsigned int src1; |
26 |
src1 = T0; |
27 |
T0 += T1; |
28 |
env->NZF = T0; |
29 |
env->CF = T0 < src1; |
30 |
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
|
31 |
} |
32 |
|
33 |
void OPPROTO op_adcl_T0_T1_cc(void) |
34 |
{ |
35 |
unsigned int src1; |
36 |
src1 = T0; |
37 |
if (!env->CF) {
|
38 |
T0 += T1; |
39 |
env->CF = T0 < src1; |
40 |
} else {
|
41 |
T0 += T1 + 1;
|
42 |
env->CF = T0 <= src1; |
43 |
} |
44 |
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
|
45 |
env->NZF = T0; |
46 |
FORCE_RET(); |
47 |
} |
48 |
|
49 |
#define OPSUB(sub, sbc, res, T0, T1) \
|
50 |
\ |
51 |
void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ |
52 |
{ \ |
53 |
unsigned int src1; \ |
54 |
src1 = T0; \ |
55 |
T0 -= T1; \ |
56 |
env->NZF = T0; \ |
57 |
env->CF = src1 >= T1; \ |
58 |
env->VF = (src1 ^ T1) & (src1 ^ T0); \ |
59 |
res = T0; \ |
60 |
} \ |
61 |
\ |
62 |
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ |
63 |
{ \ |
64 |
unsigned int src1; \ |
65 |
src1 = T0; \ |
66 |
if (!env->CF) { \
|
67 |
T0 = T0 - T1 - 1; \
|
68 |
env->CF = src1 > T1; \ |
69 |
} else { \
|
70 |
T0 = T0 - T1; \ |
71 |
env->CF = src1 >= T1; \ |
72 |
} \ |
73 |
env->VF = (src1 ^ T1) & (src1 ^ T0); \ |
74 |
env->NZF = T0; \ |
75 |
res = T0; \ |
76 |
FORCE_RET(); \ |
77 |
} |
78 |
|
79 |
OPSUB(sub, sbc, T0, T0, T1) |
80 |
|
81 |
OPSUB(rsb, rsc, T0, T1, T0) |
82 |
|
83 |
#define EIP (env->regs[15]) |
84 |
|
85 |
void OPPROTO op_test_eq(void) |
86 |
{ |
87 |
if (env->NZF == 0) |
88 |
GOTO_LABEL_PARAM(1);;
|
89 |
FORCE_RET(); |
90 |
} |
91 |
|
92 |
void OPPROTO op_test_ne(void) |
93 |
{ |
94 |
if (env->NZF != 0) |
95 |
GOTO_LABEL_PARAM(1);;
|
96 |
FORCE_RET(); |
97 |
} |
98 |
|
99 |
void OPPROTO op_test_cs(void) |
100 |
{ |
101 |
if (env->CF != 0) |
102 |
GOTO_LABEL_PARAM(1);
|
103 |
FORCE_RET(); |
104 |
} |
105 |
|
106 |
void OPPROTO op_test_cc(void) |
107 |
{ |
108 |
if (env->CF == 0) |
109 |
GOTO_LABEL_PARAM(1);
|
110 |
FORCE_RET(); |
111 |
} |
112 |
|
113 |
void OPPROTO op_test_mi(void) |
114 |
{ |
115 |
if ((env->NZF & 0x80000000) != 0) |
116 |
GOTO_LABEL_PARAM(1);
|
117 |
FORCE_RET(); |
118 |
} |
119 |
|
120 |
void OPPROTO op_test_pl(void) |
121 |
{ |
122 |
if ((env->NZF & 0x80000000) == 0) |
123 |
GOTO_LABEL_PARAM(1);
|
124 |
FORCE_RET(); |
125 |
} |
126 |
|
127 |
void OPPROTO op_test_vs(void) |
128 |
{ |
129 |
if ((env->VF & 0x80000000) != 0) |
130 |
GOTO_LABEL_PARAM(1);
|
131 |
FORCE_RET(); |
132 |
} |
133 |
|
134 |
void OPPROTO op_test_vc(void) |
135 |
{ |
136 |
if ((env->VF & 0x80000000) == 0) |
137 |
GOTO_LABEL_PARAM(1);
|
138 |
FORCE_RET(); |
139 |
} |
140 |
|
141 |
void OPPROTO op_test_hi(void) |
142 |
{ |
143 |
if (env->CF != 0 && env->NZF != 0) |
144 |
GOTO_LABEL_PARAM(1);
|
145 |
FORCE_RET(); |
146 |
} |
147 |
|
148 |
void OPPROTO op_test_ls(void) |
149 |
{ |
150 |
if (env->CF == 0 || env->NZF == 0) |
151 |
GOTO_LABEL_PARAM(1);
|
152 |
FORCE_RET(); |
153 |
} |
154 |
|
155 |
void OPPROTO op_test_ge(void) |
156 |
{ |
157 |
if (((env->VF ^ env->NZF) & 0x80000000) == 0) |
158 |
GOTO_LABEL_PARAM(1);
|
159 |
FORCE_RET(); |
160 |
} |
161 |
|
162 |
void OPPROTO op_test_lt(void) |
163 |
{ |
164 |
if (((env->VF ^ env->NZF) & 0x80000000) != 0) |
165 |
GOTO_LABEL_PARAM(1);
|
166 |
FORCE_RET(); |
167 |
} |
168 |
|
169 |
void OPPROTO op_test_gt(void) |
170 |
{ |
171 |
if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0) |
172 |
GOTO_LABEL_PARAM(1);
|
173 |
FORCE_RET(); |
174 |
} |
175 |
|
176 |
void OPPROTO op_test_le(void) |
177 |
{ |
178 |
if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0) |
179 |
GOTO_LABEL_PARAM(1);
|
180 |
FORCE_RET(); |
181 |
} |
182 |
|
183 |
void OPPROTO op_test_T0(void) |
184 |
{ |
185 |
if (T0)
|
186 |
GOTO_LABEL_PARAM(1);
|
187 |
FORCE_RET(); |
188 |
} |
189 |
void OPPROTO op_testn_T0(void) |
190 |
{ |
191 |
if (!T0)
|
192 |
GOTO_LABEL_PARAM(1);
|
193 |
FORCE_RET(); |
194 |
} |
195 |
|
196 |
void OPPROTO op_movl_T0_cpsr(void) |
197 |
{ |
198 |
/* Execution state bits always read as zero. */
|
199 |
T0 = cpsr_read(env) & ~CPSR_EXEC; |
200 |
FORCE_RET(); |
201 |
} |
202 |
|
203 |
void OPPROTO op_movl_T0_spsr(void) |
204 |
{ |
205 |
T0 = env->spsr; |
206 |
} |
207 |
|
208 |
void OPPROTO op_movl_spsr_T0(void) |
209 |
{ |
210 |
uint32_t mask = PARAM1; |
211 |
env->spsr = (env->spsr & ~mask) | (T0 & mask); |
212 |
} |
213 |
|
214 |
void OPPROTO op_movl_cpsr_T0(void) |
215 |
{ |
216 |
cpsr_write(env, T0, PARAM1); |
217 |
FORCE_RET(); |
218 |
} |
219 |
|
220 |
/* 48 bit signed mul, top 32 bits */
|
221 |
void OPPROTO op_imulw_T0_T1(void) |
222 |
{ |
223 |
uint64_t res; |
224 |
res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); |
225 |
T0 = res >> 16;
|
226 |
} |
227 |
|
228 |
void OPPROTO op_addq_T0_T1(void) |
229 |
{ |
230 |
uint64_t res; |
231 |
res = ((uint64_t)T1 << 32) | T0;
|
232 |
res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
|
233 |
T1 = res >> 32;
|
234 |
T0 = res; |
235 |
} |
236 |
|
237 |
void OPPROTO op_addq_lo_T0_T1(void) |
238 |
{ |
239 |
uint64_t res; |
240 |
res = ((uint64_t)T1 << 32) | T0;
|
241 |
res += (uint64_t)(env->regs[PARAM1]); |
242 |
T1 = res >> 32;
|
243 |
T0 = res; |
244 |
} |
245 |
|
246 |
/* Dual 16-bit accumulate. */
|
247 |
void OPPROTO op_addq_T0_T1_dual(void) |
248 |
{ |
249 |
uint64_t res; |
250 |
res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
|
251 |
res += (int32_t)T0; |
252 |
res += (int32_t)T1; |
253 |
env->regs[PARAM1] = (uint32_t)res; |
254 |
env->regs[PARAM2] = res >> 32;
|
255 |
} |
256 |
|
257 |
/* Dual 16-bit subtract accumulate. */
|
258 |
void OPPROTO op_subq_T0_T1_dual(void) |
259 |
{ |
260 |
uint64_t res; |
261 |
res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
|
262 |
res += (int32_t)T0; |
263 |
res -= (int32_t)T1; |
264 |
env->regs[PARAM1] = (uint32_t)res; |
265 |
env->regs[PARAM2] = res >> 32;
|
266 |
} |
267 |
|
268 |
void OPPROTO op_logicq_cc(void) |
269 |
{ |
270 |
env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0); |
271 |
} |
272 |
|
273 |
/* memory access */
|
274 |
|
275 |
#define MEMSUFFIX _raw
|
276 |
#include "op_mem.h" |
277 |
|
278 |
#if !defined(CONFIG_USER_ONLY)
|
279 |
#define MEMSUFFIX _user
|
280 |
#include "op_mem.h" |
281 |
#define MEMSUFFIX _kernel
|
282 |
#include "op_mem.h" |
283 |
#endif
|
284 |
|
285 |
void OPPROTO op_clrex(void) |
286 |
{ |
287 |
cpu_lock(); |
288 |
helper_clrex(env); |
289 |
cpu_unlock(); |
290 |
} |
291 |
|
292 |
/* T1 based, use T0 as shift count */
|
293 |
|
294 |
void OPPROTO op_shll_T1_T0(void) |
295 |
{ |
296 |
int shift;
|
297 |
shift = T0 & 0xff;
|
298 |
if (shift >= 32) |
299 |
T1 = 0;
|
300 |
else
|
301 |
T1 = T1 << shift; |
302 |
FORCE_RET(); |
303 |
} |
304 |
|
305 |
void OPPROTO op_shrl_T1_T0(void) |
306 |
{ |
307 |
int shift;
|
308 |
shift = T0 & 0xff;
|
309 |
if (shift >= 32) |
310 |
T1 = 0;
|
311 |
else
|
312 |
T1 = (uint32_t)T1 >> shift; |
313 |
FORCE_RET(); |
314 |
} |
315 |
|
316 |
void OPPROTO op_sarl_T1_T0(void) |
317 |
{ |
318 |
int shift;
|
319 |
shift = T0 & 0xff;
|
320 |
if (shift >= 32) |
321 |
shift = 31;
|
322 |
T1 = (int32_t)T1 >> shift; |
323 |
} |
324 |
|
325 |
void OPPROTO op_rorl_T1_T0(void) |
326 |
{ |
327 |
int shift;
|
328 |
shift = T0 & 0x1f;
|
329 |
if (shift) {
|
330 |
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
331 |
} |
332 |
FORCE_RET(); |
333 |
} |
334 |
|
335 |
/* T1 based, use T0 as shift count and compute CF */
|
336 |
|
337 |
void OPPROTO op_shll_T1_T0_cc(void) |
338 |
{ |
339 |
int shift;
|
340 |
shift = T0 & 0xff;
|
341 |
if (shift >= 32) { |
342 |
if (shift == 32) |
343 |
env->CF = T1 & 1;
|
344 |
else
|
345 |
env->CF = 0;
|
346 |
T1 = 0;
|
347 |
} else if (shift != 0) { |
348 |
env->CF = (T1 >> (32 - shift)) & 1; |
349 |
T1 = T1 << shift; |
350 |
} |
351 |
FORCE_RET(); |
352 |
} |
353 |
|
354 |
void OPPROTO op_shrl_T1_T0_cc(void) |
355 |
{ |
356 |
int shift;
|
357 |
shift = T0 & 0xff;
|
358 |
if (shift >= 32) { |
359 |
if (shift == 32) |
360 |
env->CF = (T1 >> 31) & 1; |
361 |
else
|
362 |
env->CF = 0;
|
363 |
T1 = 0;
|
364 |
} else if (shift != 0) { |
365 |
env->CF = (T1 >> (shift - 1)) & 1; |
366 |
T1 = (uint32_t)T1 >> shift; |
367 |
} |
368 |
FORCE_RET(); |
369 |
} |
370 |
|
371 |
void OPPROTO op_sarl_T1_T0_cc(void) |
372 |
{ |
373 |
int shift;
|
374 |
shift = T0 & 0xff;
|
375 |
if (shift >= 32) { |
376 |
env->CF = (T1 >> 31) & 1; |
377 |
T1 = (int32_t)T1 >> 31;
|
378 |
} else if (shift != 0) { |
379 |
env->CF = (T1 >> (shift - 1)) & 1; |
380 |
T1 = (int32_t)T1 >> shift; |
381 |
} |
382 |
FORCE_RET(); |
383 |
} |
384 |
|
385 |
void OPPROTO op_rorl_T1_T0_cc(void) |
386 |
{ |
387 |
int shift1, shift;
|
388 |
shift1 = T0 & 0xff;
|
389 |
shift = shift1 & 0x1f;
|
390 |
if (shift == 0) { |
391 |
if (shift1 != 0) |
392 |
env->CF = (T1 >> 31) & 1; |
393 |
} else {
|
394 |
env->CF = (T1 >> (shift - 1)) & 1; |
395 |
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
396 |
} |
397 |
FORCE_RET(); |
398 |
} |
399 |
|
400 |
/* exceptions */
|
401 |
|
402 |
void OPPROTO op_swi(void) |
403 |
{ |
404 |
env->exception_index = EXCP_SWI; |
405 |
cpu_loop_exit(); |
406 |
} |
407 |
|
408 |
void OPPROTO op_undef_insn(void) |
409 |
{ |
410 |
env->exception_index = EXCP_UDEF; |
411 |
cpu_loop_exit(); |
412 |
} |
413 |
|
414 |
void OPPROTO op_debug(void) |
415 |
{ |
416 |
env->exception_index = EXCP_DEBUG; |
417 |
cpu_loop_exit(); |
418 |
} |
419 |
|
420 |
void OPPROTO op_wfi(void) |
421 |
{ |
422 |
env->exception_index = EXCP_HLT; |
423 |
env->halted = 1;
|
424 |
cpu_loop_exit(); |
425 |
} |
426 |
|
427 |
void OPPROTO op_bkpt(void) |
428 |
{ |
429 |
env->exception_index = EXCP_BKPT; |
430 |
cpu_loop_exit(); |
431 |
} |
432 |
|
433 |
void OPPROTO op_exception_exit(void) |
434 |
{ |
435 |
env->exception_index = EXCP_EXCEPTION_EXIT; |
436 |
cpu_loop_exit(); |
437 |
} |
438 |
|
439 |
/* VFP support. We follow the convention used for VFP instrunctions:
|
440 |
Single precition routines have a "s" suffix, double precision a
|
441 |
"d" suffix. */
|
442 |
|
443 |
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void) |
444 |
|
445 |
#define VFP_BINOP(name) \
|
446 |
VFP_OP(name, s) \ |
447 |
{ \ |
448 |
FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status); \ |
449 |
} \ |
450 |
VFP_OP(name, d) \ |
451 |
{ \ |
452 |
FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status); \ |
453 |
} |
454 |
VFP_BINOP(add) |
455 |
VFP_BINOP(sub) |
456 |
VFP_BINOP(mul) |
457 |
VFP_BINOP(div) |
458 |
#undef VFP_BINOP
|
459 |
|
460 |
#define VFP_HELPER(name) \
|
461 |
VFP_OP(name, s) \ |
462 |
{ \ |
463 |
do_vfp_##name##s(); \ |
464 |
} \ |
465 |
VFP_OP(name, d) \ |
466 |
{ \ |
467 |
do_vfp_##name##d(); \ |
468 |
} |
469 |
VFP_HELPER(abs) |
470 |
VFP_HELPER(sqrt) |
471 |
VFP_HELPER(cmp) |
472 |
VFP_HELPER(cmpe) |
473 |
#undef VFP_HELPER
|
474 |
|
475 |
/* XXX: Will this do the right thing for NANs. Should invert the signbit
|
476 |
without looking at the rest of the value. */
|
477 |
VFP_OP(neg, s) |
478 |
{ |
479 |
FT0s = float32_chs(FT0s); |
480 |
} |
481 |
|
482 |
VFP_OP(neg, d) |
483 |
{ |
484 |
FT0d = float64_chs(FT0d); |
485 |
} |
486 |
|
487 |
VFP_OP(F1_ld0, s) |
488 |
{ |
489 |
union {
|
490 |
uint32_t i; |
491 |
float32 s; |
492 |
} v; |
493 |
v.i = 0;
|
494 |
FT1s = v.s; |
495 |
} |
496 |
|
497 |
VFP_OP(F1_ld0, d) |
498 |
{ |
499 |
union {
|
500 |
uint64_t i; |
501 |
float64 d; |
502 |
} v; |
503 |
v.i = 0;
|
504 |
FT1d = v.d; |
505 |
} |
506 |
|
507 |
/* Helper routines to perform bitwise copies between float and int. */
|
508 |
static inline float32 vfp_itos(uint32_t i) |
509 |
{ |
510 |
union {
|
511 |
uint32_t i; |
512 |
float32 s; |
513 |
} v; |
514 |
|
515 |
v.i = i; |
516 |
return v.s;
|
517 |
} |
518 |
|
519 |
static inline uint32_t vfp_stoi(float32 s) |
520 |
{ |
521 |
union {
|
522 |
uint32_t i; |
523 |
float32 s; |
524 |
} v; |
525 |
|
526 |
v.s = s; |
527 |
return v.i;
|
528 |
} |
529 |
|
530 |
static inline float64 vfp_itod(uint64_t i) |
531 |
{ |
532 |
union {
|
533 |
uint64_t i; |
534 |
float64 d; |
535 |
} v; |
536 |
|
537 |
v.i = i; |
538 |
return v.d;
|
539 |
} |
540 |
|
541 |
static inline uint64_t vfp_dtoi(float64 d) |
542 |
{ |
543 |
union {
|
544 |
uint64_t i; |
545 |
float64 d; |
546 |
} v; |
547 |
|
548 |
v.d = d; |
549 |
return v.i;
|
550 |
} |
551 |
|
552 |
/* Integer to float conversion. */
|
553 |
VFP_OP(uito, s) |
554 |
{ |
555 |
FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); |
556 |
} |
557 |
|
558 |
VFP_OP(uito, d) |
559 |
{ |
560 |
FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); |
561 |
} |
562 |
|
563 |
VFP_OP(sito, s) |
564 |
{ |
565 |
FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); |
566 |
} |
567 |
|
568 |
VFP_OP(sito, d) |
569 |
{ |
570 |
FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); |
571 |
} |
572 |
|
573 |
/* Float to integer conversion. */
|
574 |
VFP_OP(toui, s) |
575 |
{ |
576 |
FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status)); |
577 |
} |
578 |
|
579 |
VFP_OP(toui, d) |
580 |
{ |
581 |
FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status)); |
582 |
} |
583 |
|
584 |
VFP_OP(tosi, s) |
585 |
{ |
586 |
FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status)); |
587 |
} |
588 |
|
589 |
VFP_OP(tosi, d) |
590 |
{ |
591 |
FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status)); |
592 |
} |
593 |
|
594 |
/* TODO: Set rounding mode properly. */
|
595 |
VFP_OP(touiz, s) |
596 |
{ |
597 |
FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status)); |
598 |
} |
599 |
|
600 |
VFP_OP(touiz, d) |
601 |
{ |
602 |
FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status)); |
603 |
} |
604 |
|
605 |
VFP_OP(tosiz, s) |
606 |
{ |
607 |
FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status)); |
608 |
} |
609 |
|
610 |
VFP_OP(tosiz, d) |
611 |
{ |
612 |
FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status)); |
613 |
} |
614 |
|
615 |
/* floating point conversion */
|
616 |
VFP_OP(fcvtd, s) |
617 |
{ |
618 |
FT0d = float32_to_float64(FT0s, &env->vfp.fp_status); |
619 |
} |
620 |
|
621 |
VFP_OP(fcvts, d) |
622 |
{ |
623 |
FT0s = float64_to_float32(FT0d, &env->vfp.fp_status); |
624 |
} |
625 |
|
626 |
/* VFP3 fixed point conversion. */
|
627 |
#define VFP_CONV_FIX(name, p, ftype, itype, sign) \
|
628 |
VFP_OP(name##to, p) \ |
629 |
{ \ |
630 |
ftype tmp; \ |
631 |
tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(FT0##p), \ |
632 |
&env->vfp.fp_status); \ |
633 |
FT0##p = ftype##_scalbn(tmp, PARAM1, &env->vfp.fp_status); \ |
634 |
} \ |
635 |
VFP_OP(to##name, p) \ |
636 |
{ \ |
637 |
ftype tmp; \ |
638 |
tmp = ftype##_scalbn(FT0##p, PARAM1, &env->vfp.fp_status); \ |
639 |
FT0##p = vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \ |
640 |
&env->vfp.fp_status)); \ |
641 |
} |
642 |
|
643 |
VFP_CONV_FIX(sh, d, float64, int16, ) |
644 |
VFP_CONV_FIX(sl, d, float64, int32, ) |
645 |
VFP_CONV_FIX(uh, d, float64, uint16, u) |
646 |
VFP_CONV_FIX(ul, d, float64, uint32, u) |
647 |
VFP_CONV_FIX(sh, s, float32, int16, ) |
648 |
VFP_CONV_FIX(sl, s, float32, int32, ) |
649 |
VFP_CONV_FIX(uh, s, float32, uint16, u) |
650 |
VFP_CONV_FIX(ul, s, float32, uint32, u) |
651 |
|
652 |
/* Get and Put values from registers. */
|
653 |
VFP_OP(getreg_F0, d) |
654 |
{ |
655 |
FT0d = *(float64 *)((char *) env + PARAM1);
|
656 |
} |
657 |
|
658 |
VFP_OP(getreg_F0, s) |
659 |
{ |
660 |
FT0s = *(float32 *)((char *) env + PARAM1);
|
661 |
} |
662 |
|
663 |
VFP_OP(getreg_F1, d) |
664 |
{ |
665 |
FT1d = *(float64 *)((char *) env + PARAM1);
|
666 |
} |
667 |
|
668 |
VFP_OP(getreg_F1, s) |
669 |
{ |
670 |
FT1s = *(float32 *)((char *) env + PARAM1);
|
671 |
} |
672 |
|
673 |
VFP_OP(setreg_F0, d) |
674 |
{ |
675 |
*(float64 *)((char *) env + PARAM1) = FT0d;
|
676 |
} |
677 |
|
678 |
VFP_OP(setreg_F0, s) |
679 |
{ |
680 |
*(float32 *)((char *) env + PARAM1) = FT0s;
|
681 |
} |
682 |
|
683 |
void OPPROTO op_vfp_movl_T0_fpscr(void) |
684 |
{ |
685 |
do_vfp_get_fpscr (); |
686 |
} |
687 |
|
688 |
void OPPROTO op_vfp_movl_T0_fpscr_flags(void) |
689 |
{ |
690 |
T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28); |
691 |
} |
692 |
|
693 |
void OPPROTO op_vfp_movl_fpscr_T0(void) |
694 |
{ |
695 |
do_vfp_set_fpscr(); |
696 |
} |
697 |
|
698 |
void OPPROTO op_vfp_movl_T0_xreg(void) |
699 |
{ |
700 |
T0 = env->vfp.xregs[PARAM1]; |
701 |
} |
702 |
|
703 |
void OPPROTO op_vfp_movl_xreg_T0(void) |
704 |
{ |
705 |
env->vfp.xregs[PARAM1] = T0; |
706 |
} |
707 |
|
708 |
/* Move between FT0s to T0 */
|
709 |
void OPPROTO op_vfp_mrs(void) |
710 |
{ |
711 |
T0 = vfp_stoi(FT0s); |
712 |
} |
713 |
|
714 |
void OPPROTO op_vfp_msr(void) |
715 |
{ |
716 |
FT0s = vfp_itos(T0); |
717 |
} |
718 |
|
719 |
/* Move between FT0d and {T0,T1} */
|
720 |
void OPPROTO op_vfp_mrrd(void) |
721 |
{ |
722 |
CPU_DoubleU u; |
723 |
|
724 |
u.d = FT0d; |
725 |
T0 = u.l.lower; |
726 |
T1 = u.l.upper; |
727 |
} |
728 |
|
729 |
void OPPROTO op_vfp_mdrr(void) |
730 |
{ |
731 |
CPU_DoubleU u; |
732 |
|
733 |
u.l.lower = T0; |
734 |
u.l.upper = T1; |
735 |
FT0d = u.d; |
736 |
} |
737 |
|
738 |
/* Load immediate. PARAM1 is the 32 most significant bits of the value. */
|
739 |
void OPPROTO op_vfp_fconstd(void) |
740 |
{ |
741 |
CPU_DoubleU u; |
742 |
u.l.upper = PARAM1; |
743 |
u.l.lower = 0;
|
744 |
FT0d = u.d; |
745 |
} |
746 |
|
747 |
void OPPROTO op_vfp_fconsts(void) |
748 |
{ |
749 |
FT0s = vfp_itos(PARAM1); |
750 |
} |
751 |
|
752 |
void OPPROTO op_movl_cp_T0(void) |
753 |
{ |
754 |
helper_set_cp(env, PARAM1, T0); |
755 |
FORCE_RET(); |
756 |
} |
757 |
|
758 |
void OPPROTO op_movl_T0_cp(void) |
759 |
{ |
760 |
T0 = helper_get_cp(env, PARAM1); |
761 |
FORCE_RET(); |
762 |
} |
763 |
|
764 |
void OPPROTO op_movl_cp15_T0(void) |
765 |
{ |
766 |
helper_set_cp15(env, PARAM1, T0); |
767 |
FORCE_RET(); |
768 |
} |
769 |
|
770 |
void OPPROTO op_movl_T0_cp15(void) |
771 |
{ |
772 |
T0 = helper_get_cp15(env, PARAM1); |
773 |
FORCE_RET(); |
774 |
} |
775 |
|
776 |
/* Access to user mode registers from privileged modes. */
|
777 |
void OPPROTO op_movl_T0_user(void) |
778 |
{ |
779 |
int regno = PARAM1;
|
780 |
if (regno == 13) { |
781 |
T0 = env->banked_r13[0];
|
782 |
} else if (regno == 14) { |
783 |
T0 = env->banked_r14[0];
|
784 |
} else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { |
785 |
T0 = env->usr_regs[regno - 8];
|
786 |
} else {
|
787 |
T0 = env->regs[regno]; |
788 |
} |
789 |
FORCE_RET(); |
790 |
} |
791 |
|
792 |
|
793 |
void OPPROTO op_movl_user_T0(void) |
794 |
{ |
795 |
int regno = PARAM1;
|
796 |
if (regno == 13) { |
797 |
env->banked_r13[0] = T0;
|
798 |
} else if (regno == 14) { |
799 |
env->banked_r14[0] = T0;
|
800 |
} else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { |
801 |
env->usr_regs[regno - 8] = T0;
|
802 |
} else {
|
803 |
env->regs[regno] = T0; |
804 |
} |
805 |
FORCE_RET(); |
806 |
} |
807 |
|
808 |
void OPPROTO op_movl_T1_r13_banked(void) |
809 |
{ |
810 |
T1 = helper_get_r13_banked(env, PARAM1); |
811 |
} |
812 |
|
813 |
void OPPROTO op_movl_r13_T1_banked(void) |
814 |
{ |
815 |
helper_set_r13_banked(env, PARAM1, T1); |
816 |
} |
817 |
|
818 |
void OPPROTO op_v7m_mrs_T0(void) |
819 |
{ |
820 |
T0 = helper_v7m_mrs(env, PARAM1); |
821 |
} |
822 |
|
823 |
void OPPROTO op_v7m_msr_T0(void) |
824 |
{ |
825 |
helper_v7m_msr(env, PARAM1, T0); |
826 |
} |
827 |
|
828 |
void OPPROTO op_movl_T0_sp(void) |
829 |
{ |
830 |
if (PARAM1 == env->v7m.current_sp)
|
831 |
T0 = env->regs[13];
|
832 |
else
|
833 |
T0 = env->v7m.other_sp; |
834 |
FORCE_RET(); |
835 |
} |
836 |
|
837 |
#include "op_neon.h" |
838 |
|
839 |
/* iwMMXt support */
|
840 |
#include "op_iwmmxt.c" |