Commit 22e0e173376d702bdd9757d308924b6df7cd6529
1 parent
3b63c04e
target-ppc: convert POWER bridge instructions to TCG
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5891 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
219 additions
and
287 deletions
target-ppc/helper.h
... | ... | @@ -171,5 +171,13 @@ DEF_HELPER_1(602_mfrom, tl, tl) |
171 | 171 | #endif |
172 | 172 | |
173 | 173 | DEF_HELPER_3(dlmzb, tl, tl, tl, i32) |
174 | +DEF_HELPER_1(clcs, tl, i32) | |
175 | +#if !defined(CONFIG_USER_ONLY) | |
176 | +DEF_HELPER_1(rac, tl, tl) | |
177 | +#endif | |
178 | +DEF_HELPER_2(div, tl, tl, tl) | |
179 | +DEF_HELPER_2(divo, tl, tl, tl) | |
180 | +DEF_HELPER_2(divs, tl, tl, tl) | |
181 | +DEF_HELPER_2(divso, tl, tl, tl) | |
174 | 182 | |
175 | 183 | #include "def-helper.h" | ... | ... |
target-ppc/op.c
... | ... | @@ -370,112 +370,6 @@ void OPPROTO op_store_601_batu (void) |
370 | 370 | } |
371 | 371 | #endif /* !defined(CONFIG_USER_ONLY) */ |
372 | 372 | |
373 | -/* PowerPC 601 specific instructions (POWER bridge) */ | |
374 | -/* XXX: those micro-ops need tests ! */ | |
375 | -void OPPROTO op_POWER_abs (void) | |
376 | -{ | |
377 | - if ((int32_t)T0 == INT32_MIN) | |
378 | - T0 = INT32_MAX; | |
379 | - else if ((int32_t)T0 < 0) | |
380 | - T0 = -T0; | |
381 | - RETURN(); | |
382 | -} | |
383 | - | |
384 | -void OPPROTO op_POWER_abso (void) | |
385 | -{ | |
386 | - do_POWER_abso(); | |
387 | - RETURN(); | |
388 | -} | |
389 | - | |
390 | -void OPPROTO op_POWER_clcs (void) | |
391 | -{ | |
392 | - do_POWER_clcs(); | |
393 | - RETURN(); | |
394 | -} | |
395 | - | |
396 | -void OPPROTO op_POWER_div (void) | |
397 | -{ | |
398 | - do_POWER_div(); | |
399 | - RETURN(); | |
400 | -} | |
401 | - | |
402 | -void OPPROTO op_POWER_divo (void) | |
403 | -{ | |
404 | - do_POWER_divo(); | |
405 | - RETURN(); | |
406 | -} | |
407 | - | |
408 | -void OPPROTO op_POWER_divs (void) | |
409 | -{ | |
410 | - do_POWER_divs(); | |
411 | - RETURN(); | |
412 | -} | |
413 | - | |
414 | -void OPPROTO op_POWER_divso (void) | |
415 | -{ | |
416 | - do_POWER_divso(); | |
417 | - RETURN(); | |
418 | -} | |
419 | - | |
420 | -void OPPROTO op_POWER_doz (void) | |
421 | -{ | |
422 | - if ((int32_t)T1 > (int32_t)T0) | |
423 | - T0 = T1 - T0; | |
424 | - else | |
425 | - T0 = 0; | |
426 | - RETURN(); | |
427 | -} | |
428 | - | |
429 | -void OPPROTO op_POWER_dozo (void) | |
430 | -{ | |
431 | - do_POWER_dozo(); | |
432 | - RETURN(); | |
433 | -} | |
434 | - | |
435 | -void OPPROTO op_POWER_maskg (void) | |
436 | -{ | |
437 | - do_POWER_maskg(); | |
438 | - RETURN(); | |
439 | -} | |
440 | - | |
441 | -void OPPROTO op_POWER_maskir (void) | |
442 | -{ | |
443 | - T0 = (T0 & ~T2) | (T1 & T2); | |
444 | - RETURN(); | |
445 | -} | |
446 | - | |
447 | -void OPPROTO op_POWER_mul (void) | |
448 | -{ | |
449 | - uint64_t tmp; | |
450 | - | |
451 | - tmp = (uint64_t)T0 * (uint64_t)T1; | |
452 | - env->spr[SPR_MQ] = tmp >> 32; | |
453 | - T0 = tmp; | |
454 | - RETURN(); | |
455 | -} | |
456 | - | |
457 | -void OPPROTO op_POWER_mulo (void) | |
458 | -{ | |
459 | - do_POWER_mulo(); | |
460 | - RETURN(); | |
461 | -} | |
462 | - | |
463 | -void OPPROTO op_POWER_nabs (void) | |
464 | -{ | |
465 | - if (T0 > 0) | |
466 | - T0 = -T0; | |
467 | - RETURN(); | |
468 | -} | |
469 | - | |
470 | -void OPPROTO op_POWER_nabso (void) | |
471 | -{ | |
472 | - /* nabs never overflows */ | |
473 | - if (T0 > 0) | |
474 | - T0 = -T0; | |
475 | - env->xer &= ~(1 << XER_OV); | |
476 | - RETURN(); | |
477 | -} | |
478 | - | |
479 | 373 | /* POWER instructions not implemented in PowerPC 601 */ |
480 | 374 | #if !defined(CONFIG_USER_ONLY) |
481 | 375 | void OPPROTO op_POWER_mfsri (void) |
... | ... | @@ -484,12 +378,6 @@ void OPPROTO op_POWER_mfsri (void) |
484 | 378 | T0 = env->sr[T1]; |
485 | 379 | RETURN(); |
486 | 380 | } |
487 | - | |
488 | -void OPPROTO op_POWER_rac (void) | |
489 | -{ | |
490 | - do_POWER_rac(); | |
491 | - RETURN(); | |
492 | -} | |
493 | 381 | #endif |
494 | 382 | |
495 | 383 | /* PowerPC 4xx specific micro-ops */ | ... | ... |
target-ppc/op_helper.c
... | ... | @@ -1587,147 +1587,101 @@ void do_POWER_abso (void) |
1587 | 1587 | } |
1588 | 1588 | } |
1589 | 1589 | |
1590 | -void do_POWER_clcs (void) | |
1590 | +target_ulong helper_clcs (uint32_t arg) | |
1591 | 1591 | { |
1592 | - switch (T0) { | |
1592 | + switch (arg) { | |
1593 | 1593 | case 0x0CUL: |
1594 | 1594 | /* Instruction cache line size */ |
1595 | - T0 = env->icache_line_size; | |
1595 | + return env->icache_line_size; | |
1596 | 1596 | break; |
1597 | 1597 | case 0x0DUL: |
1598 | 1598 | /* Data cache line size */ |
1599 | - T0 = env->dcache_line_size; | |
1599 | + return env->dcache_line_size; | |
1600 | 1600 | break; |
1601 | 1601 | case 0x0EUL: |
1602 | 1602 | /* Minimum cache line size */ |
1603 | - T0 = env->icache_line_size < env->dcache_line_size ? | |
1604 | - env->icache_line_size : env->dcache_line_size; | |
1603 | + return (env->icache_line_size < env->dcache_line_size) ? | |
1604 | + env->icache_line_size : env->dcache_line_size; | |
1605 | 1605 | break; |
1606 | 1606 | case 0x0FUL: |
1607 | 1607 | /* Maximum cache line size */ |
1608 | - T0 = env->icache_line_size > env->dcache_line_size ? | |
1609 | - env->icache_line_size : env->dcache_line_size; | |
1608 | + return (env->icache_line_size > env->dcache_line_size) ? | |
1609 | + env->icache_line_size : env->dcache_line_size; | |
1610 | 1610 | break; |
1611 | 1611 | default: |
1612 | 1612 | /* Undefined */ |
1613 | + return 0; | |
1613 | 1614 | break; |
1614 | 1615 | } |
1615 | 1616 | } |
1616 | 1617 | |
1617 | -void do_POWER_div (void) | |
1618 | +target_ulong helper_div (target_ulong arg1, target_ulong arg2) | |
1618 | 1619 | { |
1619 | - uint64_t tmp; | |
1620 | + uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ]; | |
1620 | 1621 | |
1621 | - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || | |
1622 | - (int32_t)T1 == 0) { | |
1623 | - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); | |
1622 | + if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || | |
1623 | + (int32_t)arg2 == 0) { | |
1624 | 1624 | env->spr[SPR_MQ] = 0; |
1625 | + return INT32_MIN; | |
1625 | 1626 | } else { |
1626 | - tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ]; | |
1627 | - env->spr[SPR_MQ] = tmp % T1; | |
1628 | - T0 = tmp / (int32_t)T1; | |
1627 | + env->spr[SPR_MQ] = tmp % arg2; | |
1628 | + return tmp / (int32_t)arg2; | |
1629 | 1629 | } |
1630 | 1630 | } |
1631 | 1631 | |
1632 | -void do_POWER_divo (void) | |
1632 | +target_ulong helper_divo (target_ulong arg1, target_ulong arg2) | |
1633 | 1633 | { |
1634 | - int64_t tmp; | |
1634 | + uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ]; | |
1635 | 1635 | |
1636 | - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || | |
1637 | - (int32_t)T1 == 0) { | |
1638 | - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); | |
1639 | - env->spr[SPR_MQ] = 0; | |
1636 | + if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || | |
1637 | + (int32_t)arg2 == 0) { | |
1640 | 1638 | env->xer |= (1 << XER_OV) | (1 << XER_SO); |
1641 | - } else { | |
1642 | - tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ]; | |
1643 | - env->spr[SPR_MQ] = tmp % T1; | |
1644 | - tmp /= (int32_t)T1; | |
1645 | - if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) { | |
1646 | - env->xer |= (1 << XER_OV) | (1 << XER_SO); | |
1647 | - } else { | |
1648 | - env->xer &= ~(1 << XER_OV); | |
1649 | - } | |
1650 | - T0 = tmp; | |
1651 | - } | |
1652 | -} | |
1653 | - | |
1654 | -void do_POWER_divs (void) | |
1655 | -{ | |
1656 | - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || | |
1657 | - (int32_t)T1 == 0) { | |
1658 | - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); | |
1659 | - env->spr[SPR_MQ] = 0; | |
1660 | - } else { | |
1661 | - env->spr[SPR_MQ] = T0 % T1; | |
1662 | - T0 = (int32_t)T0 / (int32_t)T1; | |
1663 | - } | |
1664 | -} | |
1665 | - | |
1666 | -void do_POWER_divso (void) | |
1667 | -{ | |
1668 | - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || | |
1669 | - (int32_t)T1 == 0) { | |
1670 | - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); | |
1671 | 1639 | env->spr[SPR_MQ] = 0; |
1672 | - env->xer |= (1 << XER_OV) | (1 << XER_SO); | |
1640 | + return INT32_MIN; | |
1673 | 1641 | } else { |
1674 | - T0 = (int32_t)T0 / (int32_t)T1; | |
1675 | - env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1; | |
1676 | - env->xer &= ~(1 << XER_OV); | |
1677 | - } | |
1678 | -} | |
1679 | - | |
1680 | -void do_POWER_dozo (void) | |
1681 | -{ | |
1682 | - if ((int32_t)T1 > (int32_t)T0) { | |
1683 | - T2 = T0; | |
1684 | - T0 = T1 - T0; | |
1685 | - if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) & | |
1686 | - ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) { | |
1642 | + env->spr[SPR_MQ] = tmp % arg2; | |
1643 | + tmp /= (int32_t)arg2; | |
1644 | + if ((int32_t)tmp != tmp) { | |
1687 | 1645 | env->xer |= (1 << XER_OV) | (1 << XER_SO); |
1688 | 1646 | } else { |
1689 | 1647 | env->xer &= ~(1 << XER_OV); |
1690 | 1648 | } |
1691 | - } else { | |
1692 | - T0 = 0; | |
1693 | - env->xer &= ~(1 << XER_OV); | |
1649 | + return tmp; | |
1694 | 1650 | } |
1695 | 1651 | } |
1696 | 1652 | |
1697 | -void do_POWER_maskg (void) | |
1653 | +target_ulong helper_divs (target_ulong arg1, target_ulong arg2) | |
1698 | 1654 | { |
1699 | - uint32_t ret; | |
1700 | - | |
1701 | - if ((uint32_t)T0 == (uint32_t)(T1 + 1)) { | |
1702 | - ret = UINT32_MAX; | |
1655 | + if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || | |
1656 | + (int32_t)arg2 == 0) { | |
1657 | + env->spr[SPR_MQ] = 0; | |
1658 | + return INT32_MIN; | |
1703 | 1659 | } else { |
1704 | - ret = (UINT32_MAX >> ((uint32_t)T0)) ^ | |
1705 | - ((UINT32_MAX >> ((uint32_t)T1)) >> 1); | |
1706 | - if ((uint32_t)T0 > (uint32_t)T1) | |
1707 | - ret = ~ret; | |
1660 | + env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2; | |
1661 | + return (int32_t)arg1 / (int32_t)arg2; | |
1708 | 1662 | } |
1709 | - T0 = ret; | |
1710 | 1663 | } |
1711 | 1664 | |
1712 | -void do_POWER_mulo (void) | |
1665 | +target_ulong helper_divso (target_ulong arg1, target_ulong arg2) | |
1713 | 1666 | { |
1714 | - uint64_t tmp; | |
1715 | - | |
1716 | - tmp = (uint64_t)T0 * (uint64_t)T1; | |
1717 | - env->spr[SPR_MQ] = tmp >> 32; | |
1718 | - T0 = tmp; | |
1719 | - if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) { | |
1667 | + if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || | |
1668 | + (int32_t)arg2 == 0) { | |
1720 | 1669 | env->xer |= (1 << XER_OV) | (1 << XER_SO); |
1670 | + env->spr[SPR_MQ] = 0; | |
1671 | + return INT32_MIN; | |
1721 | 1672 | } else { |
1722 | 1673 | env->xer &= ~(1 << XER_OV); |
1674 | + env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2; | |
1675 | + return (int32_t)arg1 / (int32_t)arg2; | |
1723 | 1676 | } |
1724 | 1677 | } |
1725 | 1678 | |
1726 | 1679 | #if !defined (CONFIG_USER_ONLY) |
1727 | -void do_POWER_rac (void) | |
1680 | +target_ulong helper_rac (target_ulong addr) | |
1728 | 1681 | { |
1729 | 1682 | mmu_ctx_t ctx; |
1730 | 1683 | int nb_BATs; |
1684 | + target_ulong ret = 0; | |
1731 | 1685 | |
1732 | 1686 | /* We don't have to generate many instances of this instruction, |
1733 | 1687 | * as rac is supervisor only. |
... | ... | @@ -1735,9 +1689,10 @@ void do_POWER_rac (void) |
1735 | 1689 | /* XXX: FIX THIS: Pretend we have no BAT */ |
1736 | 1690 | nb_BATs = env->nb_BATs; |
1737 | 1691 | env->nb_BATs = 0; |
1738 | - if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0) | |
1739 | - T0 = ctx.raddr; | |
1692 | + if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) | |
1693 | + ret = ctx.raddr; | |
1740 | 1694 | env->nb_BATs = nb_BATs; |
1695 | + return ret; | |
1741 | 1696 | } |
1742 | 1697 | |
1743 | 1698 | void helper_rfsvc (void) | ... | ... |
target-ppc/op_helper.h
... | ... | @@ -33,15 +33,6 @@ void do_store_msr (void); |
33 | 33 | #endif |
34 | 34 | |
35 | 35 | /* POWER / PowerPC 601 specific helpers */ |
36 | -void do_POWER_abso (void); | |
37 | -void do_POWER_clcs (void); | |
38 | -void do_POWER_div (void); | |
39 | -void do_POWER_divo (void); | |
40 | -void do_POWER_divs (void); | |
41 | -void do_POWER_divso (void); | |
42 | -void do_POWER_dozo (void); | |
43 | -void do_POWER_maskg (void); | |
44 | -void do_POWER_mulo (void); | |
45 | 36 | #if !defined(CONFIG_USER_ONLY) |
46 | 37 | void do_POWER_rac (void); |
47 | 38 | void do_store_hid0_601 (void); | ... | ... |
target-ppc/translate.c
... | ... | @@ -4435,105 +4435,139 @@ GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN) |
4435 | 4435 | /* abs - abs. */ |
4436 | 4436 | GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR) |
4437 | 4437 | { |
4438 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4439 | - gen_op_POWER_abs(); | |
4440 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4438 | + int l1 = gen_new_label(); | |
4439 | + int l2 = gen_new_label(); | |
4440 | + tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1); | |
4441 | + tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4442 | + tcg_gen_br(l2); | |
4443 | + gen_set_label(l1); | |
4444 | + tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4445 | + gen_set_label(l2); | |
4441 | 4446 | if (unlikely(Rc(ctx->opcode) != 0)) |
4442 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4447 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4443 | 4448 | } |
4444 | 4449 | |
4445 | 4450 | /* abso - abso. */ |
4446 | 4451 | GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR) |
4447 | 4452 | { |
4448 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4449 | - gen_op_POWER_abso(); | |
4450 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4453 | + int l1 = gen_new_label(); | |
4454 | + int l2 = gen_new_label(); | |
4455 | + int l3 = gen_new_label(); | |
4456 | + /* Start with XER OV disabled, the most likely case */ | |
4457 | + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV)); | |
4458 | + tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2); | |
4459 | + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1); | |
4460 | + tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO)); | |
4461 | + tcg_gen_br(l2); | |
4462 | + gen_set_label(l1); | |
4463 | + tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4464 | + tcg_gen_br(l3); | |
4465 | + gen_set_label(l2); | |
4466 | + tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4467 | + gen_set_label(l3); | |
4451 | 4468 | if (unlikely(Rc(ctx->opcode) != 0)) |
4452 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4469 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4453 | 4470 | } |
4454 | 4471 | |
4455 | 4472 | /* clcs */ |
4456 | 4473 | GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR) |
4457 | 4474 | { |
4458 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4459 | - gen_op_POWER_clcs(); | |
4475 | + TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode)); | |
4476 | + gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0); | |
4477 | + tcg_temp_free_i32(t0); | |
4460 | 4478 | /* Rc=1 sets CR0 to an undefined state */ |
4461 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4462 | 4479 | } |
4463 | 4480 | |
4464 | 4481 | /* div - div. */ |
4465 | 4482 | GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR) |
4466 | 4483 | { |
4467 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4468 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4469 | - gen_op_POWER_div(); | |
4470 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4484 | + gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); | |
4471 | 4485 | if (unlikely(Rc(ctx->opcode) != 0)) |
4472 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4486 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4473 | 4487 | } |
4474 | 4488 | |
4475 | 4489 | /* divo - divo. */ |
4476 | 4490 | GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR) |
4477 | 4491 | { |
4478 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4479 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4480 | - gen_op_POWER_divo(); | |
4481 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4492 | + gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); | |
4482 | 4493 | if (unlikely(Rc(ctx->opcode) != 0)) |
4483 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4494 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4484 | 4495 | } |
4485 | 4496 | |
4486 | 4497 | /* divs - divs. */ |
4487 | 4498 | GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR) |
4488 | 4499 | { |
4489 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4490 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4491 | - gen_op_POWER_divs(); | |
4492 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4500 | + gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); | |
4493 | 4501 | if (unlikely(Rc(ctx->opcode) != 0)) |
4494 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4502 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4495 | 4503 | } |
4496 | 4504 | |
4497 | 4505 | /* divso - divso. */ |
4498 | 4506 | GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR) |
4499 | 4507 | { |
4500 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4501 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4502 | - gen_op_POWER_divso(); | |
4503 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4508 | + gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); | |
4504 | 4509 | if (unlikely(Rc(ctx->opcode) != 0)) |
4505 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4510 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4506 | 4511 | } |
4507 | 4512 | |
4508 | 4513 | /* doz - doz. */ |
4509 | 4514 | GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR) |
4510 | 4515 | { |
4511 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4512 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4513 | - gen_op_POWER_doz(); | |
4514 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4516 | + int l1 = gen_new_label(); | |
4517 | + int l2 = gen_new_label(); | |
4518 | + tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1); | |
4519 | + tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4520 | + tcg_gen_br(l2); | |
4521 | + gen_set_label(l1); | |
4522 | + tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0); | |
4523 | + gen_set_label(l2); | |
4515 | 4524 | if (unlikely(Rc(ctx->opcode) != 0)) |
4516 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4525 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4517 | 4526 | } |
4518 | 4527 | |
4519 | 4528 | /* dozo - dozo. */ |
4520 | 4529 | GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR) |
4521 | 4530 | { |
4522 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4523 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4524 | - gen_op_POWER_dozo(); | |
4525 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4531 | + int l1 = gen_new_label(); | |
4532 | + int l2 = gen_new_label(); | |
4533 | + TCGv t0 = tcg_temp_new(); | |
4534 | + TCGv t1 = tcg_temp_new(); | |
4535 | + TCGv t2 = tcg_temp_new(); | |
4536 | + /* Start with XER OV disabled, the most likely case */ | |
4537 | + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV)); | |
4538 | + tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1); | |
4539 | + tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4540 | + tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4541 | + tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0); | |
4542 | + tcg_gen_andc_tl(t1, t1, t2); | |
4543 | + tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0); | |
4544 | + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2); | |
4545 | + tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO)); | |
4546 | + tcg_gen_br(l2); | |
4547 | + gen_set_label(l1); | |
4548 | + tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0); | |
4549 | + gen_set_label(l2); | |
4550 | + tcg_temp_free(t0); | |
4551 | + tcg_temp_free(t1); | |
4552 | + tcg_temp_free(t2); | |
4526 | 4553 | if (unlikely(Rc(ctx->opcode) != 0)) |
4527 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4554 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4528 | 4555 | } |
4529 | 4556 | |
4530 | 4557 | /* dozi */ |
4531 | 4558 | GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR) |
4532 | 4559 | { |
4533 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4534 | - tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode)); | |
4535 | - gen_op_POWER_doz(); | |
4536 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4560 | + target_long simm = SIMM(ctx->opcode); | |
4561 | + int l1 = gen_new_label(); | |
4562 | + int l2 = gen_new_label(); | |
4563 | + tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1); | |
4564 | + tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]); | |
4565 | + tcg_gen_br(l2); | |
4566 | + gen_set_label(l1); | |
4567 | + tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0); | |
4568 | + gen_set_label(l2); | |
4569 | + if (unlikely(Rc(ctx->opcode) != 0)) | |
4570 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4537 | 4571 | } |
4538 | 4572 | |
4539 | 4573 | /* lscbx - lscbx. */ |
... | ... | @@ -4561,66 +4595,120 @@ GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR) |
4561 | 4595 | /* maskg - maskg. */ |
4562 | 4596 | GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR) |
4563 | 4597 | { |
4564 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); | |
4565 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4566 | - gen_op_POWER_maskg(); | |
4567 | - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); | |
4598 | + int l1 = gen_new_label(); | |
4599 | + TCGv t0 = tcg_temp_new(); | |
4600 | + TCGv t1 = tcg_temp_new(); | |
4601 | + TCGv t2 = tcg_temp_new(); | |
4602 | + TCGv t3 = tcg_temp_new(); | |
4603 | + tcg_gen_movi_tl(t3, 0xFFFFFFFF); | |
4604 | + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); | |
4605 | + tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F); | |
4606 | + tcg_gen_addi_tl(t2, t0, 1); | |
4607 | + tcg_gen_shr_tl(t2, t3, t2); | |
4608 | + tcg_gen_shr_tl(t3, t3, t1); | |
4609 | + tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3); | |
4610 | + tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1); | |
4611 | + tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4612 | + gen_set_label(l1); | |
4613 | + tcg_temp_free(t0); | |
4614 | + tcg_temp_free(t1); | |
4615 | + tcg_temp_free(t2); | |
4616 | + tcg_temp_free(t3); | |
4568 | 4617 | if (unlikely(Rc(ctx->opcode) != 0)) |
4569 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4618 | + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); | |
4570 | 4619 | } |
4571 | 4620 | |
4572 | 4621 | /* maskir - maskir. */ |
4573 | 4622 | GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR) |
4574 | 4623 | { |
4575 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4576 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); | |
4577 | - tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]); | |
4578 | - gen_op_POWER_maskir(); | |
4579 | - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); | |
4624 | + TCGv t0 = tcg_temp_new(); | |
4625 | + TCGv t1 = tcg_temp_new(); | |
4626 | + tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); | |
4627 | + tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); | |
4628 | + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); | |
4629 | + tcg_temp_free(t0); | |
4630 | + tcg_temp_free(t1); | |
4580 | 4631 | if (unlikely(Rc(ctx->opcode) != 0)) |
4581 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4632 | + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); | |
4582 | 4633 | } |
4583 | 4634 | |
4584 | 4635 | /* mul - mul. */ |
4585 | 4636 | GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR) |
4586 | 4637 | { |
4587 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4588 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4589 | - gen_op_POWER_mul(); | |
4590 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4638 | + TCGv_i64 t0 = tcg_temp_new_i64(); | |
4639 | + TCGv_i64 t1 = tcg_temp_new_i64(); | |
4640 | + TCGv t2 = tcg_temp_new(); | |
4641 | + tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]); | |
4642 | + tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]); | |
4643 | + tcg_gen_mul_i64(t0, t0, t1); | |
4644 | + tcg_gen_trunc_i64_tl(t2, t0); | |
4645 | + gen_store_spr(SPR_MQ, t2); | |
4646 | + tcg_gen_shri_i64(t1, t0, 32); | |
4647 | + tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1); | |
4648 | + tcg_temp_free_i64(t0); | |
4649 | + tcg_temp_free_i64(t1); | |
4650 | + tcg_temp_free(t2); | |
4591 | 4651 | if (unlikely(Rc(ctx->opcode) != 0)) |
4592 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4652 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4593 | 4653 | } |
4594 | 4654 | |
4595 | 4655 | /* mulo - mulo. */ |
4596 | 4656 | GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR) |
4597 | 4657 | { |
4598 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4599 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); | |
4600 | - gen_op_POWER_mulo(); | |
4601 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4658 | + int l1 = gen_new_label(); | |
4659 | + TCGv_i64 t0 = tcg_temp_new_i64(); | |
4660 | + TCGv_i64 t1 = tcg_temp_new_i64(); | |
4661 | + TCGv t2 = tcg_temp_new(); | |
4662 | + /* Start with XER OV disabled, the most likely case */ | |
4663 | + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV)); | |
4664 | + tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]); | |
4665 | + tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]); | |
4666 | + tcg_gen_mul_i64(t0, t0, t1); | |
4667 | + tcg_gen_trunc_i64_tl(t2, t0); | |
4668 | + gen_store_spr(SPR_MQ, t2); | |
4669 | + tcg_gen_shri_i64(t1, t0, 32); | |
4670 | + tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1); | |
4671 | + tcg_gen_ext32s_i64(t1, t0); | |
4672 | + tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1); | |
4673 | + tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO)); | |
4674 | + gen_set_label(l1); | |
4675 | + tcg_temp_free_i64(t0); | |
4676 | + tcg_temp_free_i64(t1); | |
4677 | + tcg_temp_free(t2); | |
4602 | 4678 | if (unlikely(Rc(ctx->opcode) != 0)) |
4603 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4679 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4604 | 4680 | } |
4605 | 4681 | |
4606 | 4682 | /* nabs - nabs. */ |
4607 | 4683 | GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR) |
4608 | 4684 | { |
4609 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4610 | - gen_op_POWER_nabs(); | |
4611 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4685 | + int l1 = gen_new_label(); | |
4686 | + int l2 = gen_new_label(); | |
4687 | + tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1); | |
4688 | + tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4689 | + tcg_gen_br(l2); | |
4690 | + gen_set_label(l1); | |
4691 | + tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4692 | + gen_set_label(l2); | |
4612 | 4693 | if (unlikely(Rc(ctx->opcode) != 0)) |
4613 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4694 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4614 | 4695 | } |
4615 | 4696 | |
4616 | 4697 | /* nabso - nabso. */ |
4617 | 4698 | GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR) |
4618 | 4699 | { |
4619 | - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); | |
4620 | - gen_op_POWER_nabso(); | |
4621 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
4700 | + int l1 = gen_new_label(); | |
4701 | + int l2 = gen_new_label(); | |
4702 | + tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1); | |
4703 | + tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4704 | + tcg_gen_br(l2); | |
4705 | + gen_set_label(l1); | |
4706 | + tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); | |
4707 | + gen_set_label(l2); | |
4708 | + /* nabs never overflows */ | |
4709 | + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV)); | |
4622 | 4710 | if (unlikely(Rc(ctx->opcode) != 0)) |
4623 | - gen_set_Rc0(ctx, cpu_T[0]); | |
4711 | + gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); | |
4624 | 4712 | } |
4625 | 4713 | |
4626 | 4714 | /* rlmi - rlmi. */ |
... | ... | @@ -5122,13 +5210,15 @@ GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER) |
5122 | 5210 | #if defined(CONFIG_USER_ONLY) |
5123 | 5211 | GEN_EXCP_PRIVOPC(ctx); |
5124 | 5212 | #else |
5213 | + TCGv t0; | |
5125 | 5214 | if (unlikely(!ctx->supervisor)) { |
5126 | 5215 | GEN_EXCP_PRIVOPC(ctx); |
5127 | 5216 | return; |
5128 | 5217 | } |
5129 | - gen_addr_reg_index(cpu_T[0], ctx); | |
5130 | - gen_op_POWER_rac(); | |
5131 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); | |
5218 | + t0 = tcg_temp_new(); | |
5219 | + gen_addr_reg_index(t0, ctx); | |
5220 | + gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0); | |
5221 | + tcg_temp_free(t0); | |
5132 | 5222 | #endif |
5133 | 5223 | } |
5134 | 5224 | ... | ... |