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; | ... | ... |