Revision 1497c961
b/target-arm/helper.c | ||
---|---|---|
322 | 322 |
env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); |
323 | 323 |
} |
324 | 324 |
|
325 |
#define HELPER(x) helper_##x |
|
326 | 325 |
/* Sign/zero extend */ |
327 | 326 |
uint32_t HELPER(sxtb16)(uint32_t x) |
328 | 327 |
{ |
... | ... | |
1894 | 1893 |
} |
1895 | 1894 |
|
1896 | 1895 |
#endif |
1897 |
|
b/target-arm/helpers.h | ||
---|---|---|
1 |
#ifndef DEF_HELPER |
|
2 | 1 |
#define DEF_HELPER(name, ret, args) ret helper_##name args; |
2 |
|
|
3 |
#ifdef GEN_HELPER |
|
4 |
#define DEF_HELPER_1_1(name, ret, args) \ |
|
5 |
DEF_HELPER(name, ret, args) \ |
|
6 |
static inline void gen_helper_##name(TCGv ret, TCGv arg1) \ |
|
7 |
{ \ |
|
8 |
tcg_gen_helper_1_1(helper_##name, ret, arg1); \ |
|
9 |
} |
|
10 |
#define DEF_HELPER_1_2(name, ret, args) \ |
|
11 |
DEF_HELPER(name, ret, args) \ |
|
12 |
static inline void gen_helper_##name(TCGv ret, TCGv arg1, TCGv arg2) \ |
|
13 |
{ \ |
|
14 |
tcg_gen_helper_1_2(helper_##name, ret, arg1, arg2); \ |
|
15 |
} |
|
16 |
#else /* !GEN_HELPER */ |
|
17 |
#define DEF_HELPER_1_1 DEF_HELPER |
|
18 |
#define DEF_HELPER_1_2 DEF_HELPER |
|
19 |
#define HELPER(x) helper_##x |
|
3 | 20 |
#endif |
4 | 21 |
|
5 |
DEF_HELPER(clz, uint32_t, (uint32_t)) |
|
6 |
DEF_HELPER(sxtb16, uint32_t, (uint32_t)) |
|
7 |
DEF_HELPER(uxtb16, uint32_t, (uint32_t)) |
|
22 |
DEF_HELPER_1_1(clz, uint32_t, (uint32_t)) |
|
23 |
DEF_HELPER_1_1(sxtb16, uint32_t, (uint32_t)) |
|
24 |
DEF_HELPER_1_1(uxtb16, uint32_t, (uint32_t)) |
|
25 |
|
|
26 |
DEF_HELPER_1_2(add_setq, uint32_t, (uint32_t, uint32_t)) |
|
27 |
DEF_HELPER_1_2(add_saturate, uint32_t, (uint32_t, uint32_t)) |
|
28 |
DEF_HELPER_1_2(sub_saturate, uint32_t, (uint32_t, uint32_t)) |
|
29 |
DEF_HELPER_1_2(add_usaturate, uint32_t, (uint32_t, uint32_t)) |
|
30 |
DEF_HELPER_1_2(sub_usaturate, uint32_t, (uint32_t, uint32_t)) |
|
31 |
DEF_HELPER_1_1(double_saturate, uint32_t, (int32_t)) |
|
32 |
|
|
33 |
#undef DEF_HELPER |
|
34 |
#undef DEF_HELPER_1_1 |
|
35 |
#undef DEF_HELPER_1_2 |
|
36 |
#undef GEN_HELPER |
b/target-arm/op.c | ||
---|---|---|
425 | 425 |
FORCE_RET(); |
426 | 426 |
} |
427 | 427 |
|
428 |
/* misc */ |
|
429 |
#define SIGNBIT (uint32_t)0x80000000 |
|
430 |
/* saturating arithmetic */ |
|
431 |
void OPPROTO op_addl_T0_T1_setq(void) |
|
432 |
{ |
|
433 |
uint32_t res; |
|
434 |
|
|
435 |
res = T0 + T1; |
|
436 |
if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) |
|
437 |
env->QF = 1; |
|
438 |
|
|
439 |
T0 = res; |
|
440 |
FORCE_RET(); |
|
441 |
} |
|
442 |
|
|
443 |
void OPPROTO op_addl_T0_T1_saturate(void) |
|
444 |
{ |
|
445 |
uint32_t res; |
|
446 |
|
|
447 |
res = T0 + T1; |
|
448 |
if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) { |
|
449 |
env->QF = 1; |
|
450 |
if (T0 & SIGNBIT) |
|
451 |
T0 = 0x80000000; |
|
452 |
else |
|
453 |
T0 = 0x7fffffff; |
|
454 |
} |
|
455 |
else |
|
456 |
T0 = res; |
|
457 |
|
|
458 |
FORCE_RET(); |
|
459 |
} |
|
460 |
|
|
461 |
void OPPROTO op_subl_T0_T1_saturate(void) |
|
462 |
{ |
|
463 |
uint32_t res; |
|
464 |
|
|
465 |
res = T0 - T1; |
|
466 |
if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) { |
|
467 |
env->QF = 1; |
|
468 |
if (T0 & SIGNBIT) |
|
469 |
T0 = 0x80000000; |
|
470 |
else |
|
471 |
T0 = 0x7fffffff; |
|
472 |
} |
|
473 |
else |
|
474 |
T0 = res; |
|
475 |
|
|
476 |
FORCE_RET(); |
|
477 |
} |
|
478 |
|
|
479 |
void OPPROTO op_double_T1_saturate(void) |
|
480 |
{ |
|
481 |
int32_t val; |
|
482 |
|
|
483 |
val = T1; |
|
484 |
if (val >= 0x40000000) { |
|
485 |
T1 = 0x7fffffff; |
|
486 |
env->QF = 1; |
|
487 |
} else if (val <= (int32_t)0xc0000000) { |
|
488 |
T1 = 0x80000000; |
|
489 |
env->QF = 1; |
|
490 |
} else { |
|
491 |
T1 = val << 1; |
|
492 |
} |
|
493 |
FORCE_RET(); |
|
494 |
} |
|
495 |
|
|
496 |
/* Unsigned saturating arithmetic for NEON. */ |
|
497 |
void OPPROTO op_addl_T0_T1_usaturate(void) |
|
498 |
{ |
|
499 |
uint32_t res; |
|
500 |
|
|
501 |
res = T0 + T1; |
|
502 |
if (res < T0) { |
|
503 |
env->QF = 1; |
|
504 |
T0 = 0xffffffff; |
|
505 |
} else { |
|
506 |
T0 = res; |
|
507 |
} |
|
508 |
|
|
509 |
FORCE_RET(); |
|
510 |
} |
|
511 |
|
|
512 |
void OPPROTO op_subl_T0_T1_usaturate(void) |
|
513 |
{ |
|
514 |
uint32_t res; |
|
515 |
|
|
516 |
res = T0 - T1; |
|
517 |
if (res > T0) { |
|
518 |
env->QF = 1; |
|
519 |
T0 = 0; |
|
520 |
} else { |
|
521 |
T0 = res; |
|
522 |
} |
|
523 |
|
|
524 |
FORCE_RET(); |
|
525 |
} |
|
526 |
|
|
527 | 428 |
/* exceptions */ |
528 | 429 |
|
529 | 430 |
void OPPROTO op_swi(void) |
b/target-arm/op_helper.c | ||
---|---|---|
18 | 18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | 19 |
*/ |
20 | 20 |
#include "exec.h" |
21 |
#include "helpers.h" |
|
21 | 22 |
|
22 | 23 |
void raise_exception(int tt) |
23 | 24 |
{ |
... | ... | |
303 | 304 |
env = saved_env; |
304 | 305 |
} |
305 | 306 |
#endif |
307 |
|
|
308 |
#define SIGNBIT (uint32_t)0x80000000 |
|
309 |
uint32_t HELPER(add_setq)(uint32_t a, uint32_t b) |
|
310 |
{ |
|
311 |
uint32_t res = a + b; |
|
312 |
if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) |
|
313 |
env->QF = 1; |
|
314 |
return res; |
|
315 |
} |
|
316 |
|
|
317 |
uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b) |
|
318 |
{ |
|
319 |
uint32_t res = a + b; |
|
320 |
if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) { |
|
321 |
env->QF = 1; |
|
322 |
res = ~(((int32_t)a >> 31) ^ SIGNBIT); |
|
323 |
} |
|
324 |
return res; |
|
325 |
} |
|
326 |
|
|
327 |
uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b) |
|
328 |
{ |
|
329 |
uint32_t res = a - b; |
|
330 |
if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) { |
|
331 |
env->QF = 1; |
|
332 |
res = ~(((int32_t)a >> 31) ^ SIGNBIT); |
|
333 |
} |
|
334 |
return res; |
|
335 |
} |
|
336 |
|
|
337 |
uint32_t HELPER(double_saturate)(int32_t val) |
|
338 |
{ |
|
339 |
uint32_t res; |
|
340 |
if (val >= 0x40000000) { |
|
341 |
res = ~SIGNBIT; |
|
342 |
env->QF = 1; |
|
343 |
} else if (val <= (int32_t)0xc0000000) { |
|
344 |
res = SIGNBIT; |
|
345 |
env->QF = 1; |
|
346 |
} else { |
|
347 |
res = val << 1; |
|
348 |
} |
|
349 |
return res; |
|
350 |
} |
|
351 |
|
|
352 |
uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b) |
|
353 |
{ |
|
354 |
uint32_t res = a + b; |
|
355 |
if (res < a) { |
|
356 |
env->QF = 1; |
|
357 |
res = ~0; |
|
358 |
} |
|
359 |
return res; |
|
360 |
} |
|
361 |
|
|
362 |
uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b) |
|
363 |
{ |
|
364 |
uint32_t res = a - b; |
|
365 |
if (res > a) { |
|
366 |
env->QF = 1; |
|
367 |
res = 0; |
|
368 |
} |
|
369 |
return res; |
|
370 |
} |
|
371 |
|
b/target-arm/op_neon.h | ||
---|---|---|
9 | 9 |
/* Note that for NEON an "l" prefix means it is a wide operation, unlike |
10 | 10 |
scalar arm ops where it means a word size operation. */ |
11 | 11 |
|
12 |
#define SIGNBIT (uint32_t)0x80000000 |
|
12 | 13 |
/* ??? NEON ops should probably have their own float status. */ |
13 | 14 |
#define NFS &env->vfp.fp_status |
14 | 15 |
#define NEON_OP(name) void OPPROTO op_neon_##name (void) |
b/target-arm/translate.c | ||
---|---|---|
29 | 29 |
#include "exec-all.h" |
30 | 30 |
#include "disas.h" |
31 | 31 |
#include "tcg-op.h" |
32 |
|
|
33 |
#define GEN_HELPER 1 |
|
32 | 34 |
#include "helpers.h" |
33 | 35 |
|
34 | 36 |
#define ENABLE_ARCH_5J 0 |
... | ... | |
200 | 202 |
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) |
201 | 203 |
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var) |
202 | 204 |
|
203 |
#define HELPER_ADDR(x) helper_##x |
|
204 |
|
|
205 |
#define gen_sxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(sxtb16), var, var) |
|
206 |
#define gen_uxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(uxtb16), var, var) |
|
205 |
#define gen_sxtb16(var) gen_helper_sxtb16(var, var) |
|
206 |
#define gen_uxtb16(var) gen_helper_uxtb16(var, var) |
|
207 | 207 |
|
208 |
#define gen_op_clz_T0(var) \ |
|
209 |
tcg_gen_helper_1_1(HELPER_ADDR(clz), cpu_T[0], cpu_T[0]) |
|
208 |
#define gen_op_addl_T0_T1_setq() \ |
|
209 |
gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1]) |
|
210 |
#define gen_op_addl_T0_T1_saturate() \ |
|
211 |
gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1]) |
|
212 |
#define gen_op_subl_T0_T1_saturate() \ |
|
213 |
gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1]) |
|
214 |
#define gen_op_addl_T0_T1_usaturate() \ |
|
215 |
gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]) |
|
216 |
#define gen_op_subl_T0_T1_usaturate() \ |
|
217 |
gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]) |
|
210 | 218 |
|
211 | 219 |
/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. |
212 | 220 |
tmp = (t0 ^ t1) & 0x8000; |
... | ... | |
4526 | 4534 |
switch (size) { |
4527 | 4535 |
case 0: gen_op_neon_clz_u8(); break; |
4528 | 4536 |
case 1: gen_op_neon_clz_u16(); break; |
4529 |
case 2: gen_op_clz_T0(); break;
|
|
4537 |
case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
|
|
4530 | 4538 |
default: return 1; |
4531 | 4539 |
} |
4532 | 4540 |
break; |
... | ... | |
5021 | 5029 |
} else if (op1 == 3) { |
5022 | 5030 |
/* clz */ |
5023 | 5031 |
rd = (insn >> 12) & 0xf; |
5024 |
gen_movl_T0_reg(s, rm);
|
|
5025 |
gen_op_clz_T0();
|
|
5026 |
gen_movl_reg_T0(s, rd);
|
|
5032 |
tmp = load_reg(s, rm);
|
|
5033 |
gen_helper_clz(tmp, tmp);
|
|
5034 |
store_reg(s, rd, tmp);
|
|
5027 | 5035 |
} else { |
5028 | 5036 |
goto illegal_op; |
5029 | 5037 |
} |
... | ... | |
5055 | 5063 |
gen_movl_T0_reg(s, rm); |
5056 | 5064 |
gen_movl_T1_reg(s, rn); |
5057 | 5065 |
if (op1 & 2) |
5058 |
gen_op_double_T1_saturate();
|
|
5066 |
gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
|
|
5059 | 5067 |
if (op1 & 1) |
5060 | 5068 |
gen_op_subl_T0_T1_saturate(); |
5061 | 5069 |
else |
... | ... | |
6317 | 6325 |
gen_movl_T0_reg(s, rm); |
6318 | 6326 |
gen_movl_T1_reg(s, rn); |
6319 | 6327 |
if (op & 2) |
6320 |
gen_op_double_T1_saturate();
|
|
6328 |
gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
|
|
6321 | 6329 |
if (op & 1) |
6322 | 6330 |
gen_op_subl_T0_T1_saturate(); |
6323 | 6331 |
else |
... | ... | |
6342 | 6350 |
gen_op_sel_T0_T1(); |
6343 | 6351 |
break; |
6344 | 6352 |
case 0x18: /* clz */ |
6345 |
gen_op_clz_T0();
|
|
6353 |
gen_helper_clz(cpu_T[0], cpu_T[0]);
|
|
6346 | 6354 |
break; |
6347 | 6355 |
default: |
6348 | 6356 |
goto illegal_op; |
Also available in: Unified diff