Commit 22e0e173376d702bdd9757d308924b6df7cd6529

Authored by aurel32
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
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  
... ...