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,5 +171,13 @@ DEF_HELPER_1(602_mfrom, tl, tl)
171 #endif 171 #endif
172 172
173 DEF_HELPER_3(dlmzb, tl, tl, tl, i32) 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 #include "def-helper.h" 183 #include "def-helper.h"
target-ppc/op.c
@@ -370,112 +370,6 @@ void OPPROTO op_store_601_batu (void) @@ -370,112 +370,6 @@ void OPPROTO op_store_601_batu (void)
370 } 370 }
371 #endif /* !defined(CONFIG_USER_ONLY) */ 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 /* POWER instructions not implemented in PowerPC 601 */ 373 /* POWER instructions not implemented in PowerPC 601 */
480 #if !defined(CONFIG_USER_ONLY) 374 #if !defined(CONFIG_USER_ONLY)
481 void OPPROTO op_POWER_mfsri (void) 375 void OPPROTO op_POWER_mfsri (void)
@@ -484,12 +378,6 @@ void OPPROTO op_POWER_mfsri (void) @@ -484,12 +378,6 @@ void OPPROTO op_POWER_mfsri (void)
484 T0 = env->sr[T1]; 378 T0 = env->sr[T1];
485 RETURN(); 379 RETURN();
486 } 380 }
487 -  
488 -void OPPROTO op_POWER_rac (void)  
489 -{  
490 - do_POWER_rac();  
491 - RETURN();  
492 -}  
493 #endif 381 #endif
494 382
495 /* PowerPC 4xx specific micro-ops */ 383 /* PowerPC 4xx specific micro-ops */
target-ppc/op_helper.c
@@ -1587,147 +1587,101 @@ void do_POWER_abso (void) @@ -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 case 0x0CUL: 1593 case 0x0CUL:
1594 /* Instruction cache line size */ 1594 /* Instruction cache line size */
1595 - T0 = env->icache_line_size; 1595 + return env->icache_line_size;
1596 break; 1596 break;
1597 case 0x0DUL: 1597 case 0x0DUL:
1598 /* Data cache line size */ 1598 /* Data cache line size */
1599 - T0 = env->dcache_line_size; 1599 + return env->dcache_line_size;
1600 break; 1600 break;
1601 case 0x0EUL: 1601 case 0x0EUL:
1602 /* Minimum cache line size */ 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 break; 1605 break;
1606 case 0x0FUL: 1606 case 0x0FUL:
1607 /* Maximum cache line size */ 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 break; 1610 break;
1611 default: 1611 default:
1612 /* Undefined */ 1612 /* Undefined */
  1613 + return 0;
1613 break; 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 env->spr[SPR_MQ] = 0; 1624 env->spr[SPR_MQ] = 0;
  1625 + return INT32_MIN;
1625 } else { 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 env->xer |= (1 << XER_OV) | (1 << XER_SO); 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 env->spr[SPR_MQ] = 0; 1639 env->spr[SPR_MQ] = 0;
1672 - env->xer |= (1 << XER_OV) | (1 << XER_SO); 1640 + return INT32_MIN;
1673 } else { 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 env->xer |= (1 << XER_OV) | (1 << XER_SO); 1645 env->xer |= (1 << XER_OV) | (1 << XER_SO);
1688 } else { 1646 } else {
1689 env->xer &= ~(1 << XER_OV); 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 } else { 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 env->xer |= (1 << XER_OV) | (1 << XER_SO); 1669 env->xer |= (1 << XER_OV) | (1 << XER_SO);
  1670 + env->spr[SPR_MQ] = 0;
  1671 + return INT32_MIN;
1721 } else { 1672 } else {
1722 env->xer &= ~(1 << XER_OV); 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 #if !defined (CONFIG_USER_ONLY) 1679 #if !defined (CONFIG_USER_ONLY)
1727 -void do_POWER_rac (void) 1680 +target_ulong helper_rac (target_ulong addr)
1728 { 1681 {
1729 mmu_ctx_t ctx; 1682 mmu_ctx_t ctx;
1730 int nb_BATs; 1683 int nb_BATs;
  1684 + target_ulong ret = 0;
1731 1685
1732 /* We don't have to generate many instances of this instruction, 1686 /* We don't have to generate many instances of this instruction,
1733 * as rac is supervisor only. 1687 * as rac is supervisor only.
@@ -1735,9 +1689,10 @@ void do_POWER_rac (void) @@ -1735,9 +1689,10 @@ void do_POWER_rac (void)
1735 /* XXX: FIX THIS: Pretend we have no BAT */ 1689 /* XXX: FIX THIS: Pretend we have no BAT */
1736 nb_BATs = env->nb_BATs; 1690 nb_BATs = env->nb_BATs;
1737 env->nb_BATs = 0; 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 env->nb_BATs = nb_BATs; 1694 env->nb_BATs = nb_BATs;
  1695 + return ret;
1741 } 1696 }
1742 1697
1743 void helper_rfsvc (void) 1698 void helper_rfsvc (void)
target-ppc/op_helper.h
@@ -33,15 +33,6 @@ void do_store_msr (void); @@ -33,15 +33,6 @@ void do_store_msr (void);
33 #endif 33 #endif
34 34
35 /* POWER / PowerPC 601 specific helpers */ 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 #if !defined(CONFIG_USER_ONLY) 36 #if !defined(CONFIG_USER_ONLY)
46 void do_POWER_rac (void); 37 void do_POWER_rac (void);
47 void do_store_hid0_601 (void); 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,105 +4435,139 @@ GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
4435 /* abs - abs. */ 4435 /* abs - abs. */
4436 GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* abso - abso. */ 4450 /* abso - abso. */
4446 GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* clcs */ 4472 /* clcs */
4456 GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR) 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 /* Rc=1 sets CR0 to an undefined state */ 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 /* div - div. */ 4481 /* div - div. */
4465 GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* divo - divo. */ 4489 /* divo - divo. */
4476 GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* divs - divs. */ 4497 /* divs - divs. */
4487 GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* divso - divso. */ 4505 /* divso - divso. */
4498 GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* doz - doz. */ 4513 /* doz - doz. */
4509 GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* dozo - dozo. */ 4528 /* dozo - dozo. */
4520 GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* dozi */ 4557 /* dozi */
4531 GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR) 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 /* lscbx - lscbx. */ 4573 /* lscbx - lscbx. */
@@ -4561,66 +4595,120 @@ GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR) @@ -4561,66 +4595,120 @@ GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4561 /* maskg - maskg. */ 4595 /* maskg - maskg. */
4562 GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* maskir - maskir. */ 4621 /* maskir - maskir. */
4573 GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* mul - mul. */ 4635 /* mul - mul. */
4585 GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* mulo - mulo. */ 4655 /* mulo - mulo. */
4596 GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* nabs - nabs. */ 4682 /* nabs - nabs. */
4607 GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* nabso - nabso. */ 4697 /* nabso - nabso. */
4617 GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR) 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 if (unlikely(Rc(ctx->opcode) != 0)) 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 /* rlmi - rlmi. */ 4714 /* rlmi - rlmi. */
@@ -5122,13 +5210,15 @@ GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER) @@ -5122,13 +5210,15 @@ GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
5122 #if defined(CONFIG_USER_ONLY) 5210 #if defined(CONFIG_USER_ONLY)
5123 GEN_EXCP_PRIVOPC(ctx); 5211 GEN_EXCP_PRIVOPC(ctx);
5124 #else 5212 #else
  5213 + TCGv t0;
5125 if (unlikely(!ctx->supervisor)) { 5214 if (unlikely(!ctx->supervisor)) {
5126 GEN_EXCP_PRIVOPC(ctx); 5215 GEN_EXCP_PRIVOPC(ctx);
5127 return; 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 #endif 5222 #endif
5133 } 5223 }
5134 5224