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,7 +322,6 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) | ||
| 322 | env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); | 322 | env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | -#define HELPER(x) helper_##x | ||
| 326 | /* Sign/zero extend */ | 325 | /* Sign/zero extend */ |
| 327 | uint32_t HELPER(sxtb16)(uint32_t x) | 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,4 +1893,3 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, | ||
| 1894 | } | 1893 | } |
| 1895 | 1894 | ||
| 1896 | #endif | 1895 | #endif |
| 1897 | - |
target-arm/helpers.h
| 1 | -#ifndef DEF_HELPER | ||
| 2 | #define DEF_HELPER(name, ret, args) ret helper_##name args; | 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 | #endif | 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,105 +425,6 @@ void OPPROTO op_rorl_T1_T0_cc(void) | ||
| 425 | FORCE_RET(); | 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 | /* exceptions */ | 428 | /* exceptions */ |
| 528 | 429 | ||
| 529 | void OPPROTO op_swi(void) | 430 | void OPPROTO op_swi(void) |
target-arm/op_helper.c
| @@ -18,6 +18,7 @@ | @@ -18,6 +18,7 @@ | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | #include "exec.h" | 20 | #include "exec.h" |
| 21 | +#include "helpers.h" | ||
| 21 | 22 | ||
| 22 | void raise_exception(int tt) | 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,3 +304,68 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) | ||
| 303 | env = saved_env; | 304 | env = saved_env; |
| 304 | } | 305 | } |
| 305 | #endif | 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,6 +9,7 @@ | ||
| 9 | /* Note that for NEON an "l" prefix means it is a wide operation, unlike | 9 | /* Note that for NEON an "l" prefix means it is a wide operation, unlike |
| 10 | scalar arm ops where it means a word size operation. */ | 10 | scalar arm ops where it means a word size operation. */ |
| 11 | 11 | ||
| 12 | +#define SIGNBIT (uint32_t)0x80000000 | ||
| 12 | /* ??? NEON ops should probably have their own float status. */ | 13 | /* ??? NEON ops should probably have their own float status. */ |
| 13 | #define NFS &env->vfp.fp_status | 14 | #define NFS &env->vfp.fp_status |
| 14 | #define NEON_OP(name) void OPPROTO op_neon_##name (void) | 15 | #define NEON_OP(name) void OPPROTO op_neon_##name (void) |
target-arm/translate.c
| @@ -29,6 +29,8 @@ | @@ -29,6 +29,8 @@ | ||
| 29 | #include "exec-all.h" | 29 | #include "exec-all.h" |
| 30 | #include "disas.h" | 30 | #include "disas.h" |
| 31 | #include "tcg-op.h" | 31 | #include "tcg-op.h" |
| 32 | + | ||
| 33 | +#define GEN_HELPER 1 | ||
| 32 | #include "helpers.h" | 34 | #include "helpers.h" |
| 33 | 35 | ||
| 34 | #define ENABLE_ARCH_5J 0 | 36 | #define ENABLE_ARCH_5J 0 |
| @@ -200,13 +202,19 @@ static void store_reg(DisasContext *s, int reg, TCGv var) | @@ -200,13 +202,19 @@ static void store_reg(DisasContext *s, int reg, TCGv var) | ||
| 200 | #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) | 202 | #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) |
| 201 | #define gen_sxth(var) tcg_gen_ext16s_i32(var, var) | 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 | /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. | 219 | /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. |
| 212 | tmp = (t0 ^ t1) & 0x8000; | 220 | tmp = (t0 ^ t1) & 0x8000; |
| @@ -4526,7 +4534,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -4526,7 +4534,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 4526 | switch (size) { | 4534 | switch (size) { |
| 4527 | case 0: gen_op_neon_clz_u8(); break; | 4535 | case 0: gen_op_neon_clz_u8(); break; |
| 4528 | case 1: gen_op_neon_clz_u16(); break; | 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 | default: return 1; | 4538 | default: return 1; |
| 4531 | } | 4539 | } |
| 4532 | break; | 4540 | break; |
| @@ -5021,9 +5029,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | @@ -5021,9 +5029,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | ||
| 5021 | } else if (op1 == 3) { | 5029 | } else if (op1 == 3) { |
| 5022 | /* clz */ | 5030 | /* clz */ |
| 5023 | rd = (insn >> 12) & 0xf; | 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 | } else { | 5035 | } else { |
| 5028 | goto illegal_op; | 5036 | goto illegal_op; |
| 5029 | } | 5037 | } |
| @@ -5055,7 +5063,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | @@ -5055,7 +5063,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | ||
| 5055 | gen_movl_T0_reg(s, rm); | 5063 | gen_movl_T0_reg(s, rm); |
| 5056 | gen_movl_T1_reg(s, rn); | 5064 | gen_movl_T1_reg(s, rn); |
| 5057 | if (op1 & 2) | 5065 | if (op1 & 2) |
| 5058 | - gen_op_double_T1_saturate(); | 5066 | + gen_helper_double_saturate(cpu_T[1], cpu_T[1]); |
| 5059 | if (op1 & 1) | 5067 | if (op1 & 1) |
| 5060 | gen_op_subl_T0_T1_saturate(); | 5068 | gen_op_subl_T0_T1_saturate(); |
| 5061 | else | 5069 | else |
| @@ -6317,7 +6325,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | @@ -6317,7 +6325,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | ||
| 6317 | gen_movl_T0_reg(s, rm); | 6325 | gen_movl_T0_reg(s, rm); |
| 6318 | gen_movl_T1_reg(s, rn); | 6326 | gen_movl_T1_reg(s, rn); |
| 6319 | if (op & 2) | 6327 | if (op & 2) |
| 6320 | - gen_op_double_T1_saturate(); | 6328 | + gen_helper_double_saturate(cpu_T[1], cpu_T[1]); |
| 6321 | if (op & 1) | 6329 | if (op & 1) |
| 6322 | gen_op_subl_T0_T1_saturate(); | 6330 | gen_op_subl_T0_T1_saturate(); |
| 6323 | else | 6331 | else |
| @@ -6342,7 +6350,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | @@ -6342,7 +6350,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | ||
| 6342 | gen_op_sel_T0_T1(); | 6350 | gen_op_sel_T0_T1(); |
| 6343 | break; | 6351 | break; |
| 6344 | case 0x18: /* clz */ | 6352 | case 0x18: /* clz */ |
| 6345 | - gen_op_clz_T0(); | 6353 | + gen_helper_clz(cpu_T[0], cpu_T[0]); |
| 6346 | break; | 6354 | break; |
| 6347 | default: | 6355 | default: |
| 6348 | goto illegal_op; | 6356 | goto illegal_op; |