Commit 1497c961af2b6d45bd2a1da5a351be54edcadca2
1 parent
9a119ff6
ARM TCG conversion 4/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4141 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
121 additions
and
118 deletions
target-arm/helper.c
... | ... | @@ -322,7 +322,6 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) |
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,4 +1893,3 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, |
1894 | 1893 | } |
1895 | 1894 | |
1896 | 1895 | #endif |
1897 | - | ... | ... |
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 | ... | ... |
target-arm/op.c
... | ... | @@ -425,105 +425,6 @@ void OPPROTO op_rorl_T1_T0_cc(void) |
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) | ... | ... |
target-arm/op_helper.c
... | ... | @@ -18,6 +18,7 @@ |
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,3 +304,68 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
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 | + | ... | ... |
target-arm/op_neon.h
... | ... | @@ -9,6 +9,7 @@ |
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) | ... | ... |
target-arm/translate.c
... | ... | @@ -29,6 +29,8 @@ |
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,13 +202,19 @@ static void store_reg(DisasContext *s, int reg, TCGv var) |
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,7 +4534,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
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,9 +5029,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
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,7 +5063,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
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,7 +6325,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
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,7 +6350,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
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; | ... | ... |