Revision e98a6e40 target-ppc/translate.c
b/target-ppc/translate.c | ||
---|---|---|
1501 | 1501 |
} |
1502 | 1502 |
|
1503 | 1503 |
/*** Branch ***/ |
1504 |
#define GEN_BCOND(name, opc1, opc2, opc3, prologue, \ |
|
1505 |
bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, bl, \ |
|
1506 |
bl_ctr_true, b_ctr_true, bl_ctrz_true, b_ctrz_true, bl_true, b_true, \ |
|
1507 |
bl_ctr_false, b_ctr_false, bl_ctrz_false, b_ctrz_false, bl_false, b_false) \ |
|
1508 |
GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \ |
|
1509 |
{ \ |
|
1510 |
__attribute__ ((unused)) uint32_t target; \ |
|
1511 |
uint32_t bo = BO(ctx->opcode); \ |
|
1512 |
uint32_t bi = BI(ctx->opcode); \ |
|
1513 |
uint32_t mask; \ |
|
1514 |
gen_op_update_tb(ctx->tb_offset); \ |
|
1515 |
gen_op_update_decr(ctx->decr_offset); \ |
|
1516 |
gen_op_process_exceptions((uint32_t)ctx->nip - 4); \ |
|
1517 |
prologue; \ |
|
1518 |
/* gen_op_set_T1((uint32_t)ctx->tb);*/ \ |
|
1519 |
if ((bo & 0x4) == 0) \ |
|
1520 |
gen_op_dec_ctr(); \ |
|
1521 |
if (bo & 0x10) { \ |
|
1522 |
/* No CR condition */ \ |
|
1523 |
switch (bo & 0x6) { \ |
|
1524 |
case 0: \ |
|
1525 |
if (LK(ctx->opcode)) { \ |
|
1526 |
bl_ctr; \ |
|
1527 |
} else { \ |
|
1528 |
b_ctr; \ |
|
1529 |
} \ |
|
1530 |
break; \ |
|
1531 |
case 2: \ |
|
1532 |
if (LK(ctx->opcode)) { \ |
|
1533 |
bl_ctrz; \ |
|
1534 |
} else { \ |
|
1535 |
b_ctrz; \ |
|
1536 |
} \ |
|
1537 |
break; \ |
|
1538 |
case 4: \ |
|
1539 |
case 6: \ |
|
1540 |
if (LK(ctx->opcode)) { \ |
|
1541 |
bl; \ |
|
1542 |
} else { \ |
|
1543 |
b; \ |
|
1544 |
} \ |
|
1545 |
break; \ |
|
1546 |
default: \ |
|
1547 |
printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \ |
|
1548 |
RET_INVAL(); \ |
|
1549 |
break; \ |
|
1550 |
} \ |
|
1551 |
} else { \ |
|
1552 |
mask = 1 << (3 - (bi & 0x03)); \ |
|
1553 |
gen_op_load_crf_T0(bi >> 2); \ |
|
1554 |
if (bo & 0x8) { \ |
|
1555 |
switch (bo & 0x6) { \ |
|
1556 |
case 0: \ |
|
1557 |
if (LK(ctx->opcode)) { \ |
|
1558 |
bl_ctr_true; \ |
|
1559 |
} else { \ |
|
1560 |
b_ctr_true; \ |
|
1561 |
} \ |
|
1562 |
break; \ |
|
1563 |
case 2: \ |
|
1564 |
if (LK(ctx->opcode)) { \ |
|
1565 |
bl_ctrz_true; \ |
|
1566 |
} else { \ |
|
1567 |
b_ctrz_true; \ |
|
1568 |
} \ |
|
1569 |
break; \ |
|
1570 |
case 4: \ |
|
1571 |
case 6: \ |
|
1572 |
if (LK(ctx->opcode)) { \ |
|
1573 |
bl_true; \ |
|
1574 |
} else { \ |
|
1575 |
b_true; \ |
|
1576 |
} \ |
|
1577 |
break; \ |
|
1578 |
default: \ |
|
1579 |
printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \ |
|
1580 |
RET_INVAL(); \ |
|
1581 |
break; \ |
|
1582 |
} \ |
|
1583 |
} else { \ |
|
1584 |
switch (bo & 0x6) { \ |
|
1585 |
case 0: \ |
|
1586 |
if (LK(ctx->opcode)) { \ |
|
1587 |
bl_ctr_false; \ |
|
1588 |
} else { \ |
|
1589 |
b_ctr_false; \ |
|
1590 |
} \ |
|
1591 |
break; \ |
|
1592 |
case 2: \ |
|
1593 |
if (LK(ctx->opcode)) { \ |
|
1594 |
bl_ctrz_false; \ |
|
1595 |
} else { \ |
|
1596 |
b_ctrz_false; \ |
|
1597 |
} \ |
|
1598 |
break; \ |
|
1599 |
case 4: \ |
|
1600 |
case 6: \ |
|
1601 |
if (LK(ctx->opcode)) { \ |
|
1602 |
bl_false; \ |
|
1603 |
} else { \ |
|
1604 |
b_false; \ |
|
1605 |
} \ |
|
1606 |
break; \ |
|
1607 |
default: \ |
|
1608 |
printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \ |
|
1609 |
RET_INVAL(); \ |
|
1610 |
break; \ |
|
1611 |
} \ |
|
1612 |
} \ |
|
1613 |
} \ |
|
1614 |
ctx->exception = EXCP_BRANCH; \ |
|
1615 |
} |
|
1616 | 1504 |
|
1617 | 1505 |
/* b ba bl bla */ |
1618 | 1506 |
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
... | ... | |
1626 | 1514 |
target = (uint32_t)ctx->nip + li - 4; |
1627 | 1515 |
else |
1628 | 1516 |
target = li; |
1629 |
// gen_op_set_T1((uint32_t)ctx->tb); |
|
1630 | 1517 |
if (LK(ctx->opcode)) { |
1631 |
gen_op_bl(target, (uint32_t)ctx->nip); |
|
1632 |
} else { |
|
1633 |
gen_op_b(target); |
|
1518 |
gen_op_setlr((uint32_t)ctx->nip); |
|
1634 | 1519 |
} |
1520 |
gen_op_b((long)ctx->tb, target); |
|
1635 | 1521 |
ctx->exception = EXCP_BRANCH; |
1636 | 1522 |
} |
1637 | 1523 |
|
1638 |
/* bc bca bcl bcla */ |
|
1639 |
GEN_BCOND(bc, 0x10, 0xFF, 0xFF, |
|
1640 |
do { |
|
1641 |
uint32_t li = s_ext16(BD(ctx->opcode)); |
|
1642 |
if (AA(ctx->opcode) == 0) { |
|
1643 |
target = (uint32_t)ctx->nip + li - 4; |
|
1644 |
} else { |
|
1645 |
target = li; |
|
1646 |
} |
|
1647 |
} while (0), |
|
1648 |
gen_op_bl_ctr((uint32_t)ctx->nip, target), |
|
1649 |
gen_op_b_ctr((uint32_t)ctx->nip, target), |
|
1650 |
gen_op_bl_ctrz((uint32_t)ctx->nip, target), |
|
1651 |
gen_op_b_ctrz((uint32_t)ctx->nip, target), |
|
1652 |
gen_op_b(target), |
|
1653 |
gen_op_bl(target, (uint32_t)ctx->nip), |
|
1654 |
gen_op_bl_ctr_true((uint32_t)ctx->nip, target, mask), |
|
1655 |
gen_op_b_ctr_true((uint32_t)ctx->nip, target, mask), |
|
1656 |
gen_op_bl_ctrz_true((uint32_t)ctx->nip, target, mask), |
|
1657 |
gen_op_b_ctrz_true((uint32_t)ctx->nip, target, mask), |
|
1658 |
gen_op_bl_true((uint32_t)ctx->nip, target, mask), |
|
1659 |
gen_op_b_true((uint32_t)ctx->nip, target, mask), |
|
1660 |
gen_op_bl_ctr_false((uint32_t)ctx->nip, target, mask), |
|
1661 |
gen_op_b_ctr_false((uint32_t)ctx->nip, target, mask), |
|
1662 |
gen_op_bl_ctrz_false((uint32_t)ctx->nip, target, mask), |
|
1663 |
gen_op_b_ctrz_false((uint32_t)ctx->nip, target, mask), |
|
1664 |
gen_op_bl_false((uint32_t)ctx->nip, target, mask), |
|
1665 |
gen_op_b_false((uint32_t)ctx->nip, target, mask)); |
|
1666 |
|
|
1667 |
/* bcctr bcctrl */ |
|
1668 |
GEN_BCOND(bcctr, 0x13, 0x10, 0x10, do { } while (0), |
|
1669 |
gen_op_bctrl_ctr((uint32_t)ctx->nip), |
|
1670 |
gen_op_bctr_ctr((uint32_t)ctx->nip), |
|
1671 |
gen_op_bctrl_ctrz((uint32_t)ctx->nip), |
|
1672 |
gen_op_bctr_ctrz((uint32_t)ctx->nip), |
|
1673 |
gen_op_bctr(), |
|
1674 |
gen_op_bctrl((uint32_t)ctx->nip), |
|
1675 |
gen_op_bctrl_ctr_true((uint32_t)ctx->nip, mask), |
|
1676 |
gen_op_bctr_ctr_true((uint32_t)ctx->nip, mask), |
|
1677 |
gen_op_bctrl_ctrz_true((uint32_t)ctx->nip, mask), |
|
1678 |
gen_op_bctr_ctrz_true((uint32_t)ctx->nip, mask), |
|
1679 |
gen_op_bctrl_true((uint32_t)ctx->nip, mask), |
|
1680 |
gen_op_bctr_true((uint32_t)ctx->nip, mask), |
|
1681 |
gen_op_bctrl_ctr_false((uint32_t)ctx->nip, mask), |
|
1682 |
gen_op_bctr_ctr_false((uint32_t)ctx->nip, mask), |
|
1683 |
gen_op_bctrl_ctrz_false((uint32_t)ctx->nip, mask), |
|
1684 |
gen_op_bctr_ctrz_false((uint32_t)ctx->nip, mask), |
|
1685 |
gen_op_bctrl_false((uint32_t)ctx->nip, mask), |
|
1686 |
gen_op_bctr_false((uint32_t)ctx->nip, mask)) |
|
1687 |
|
|
1688 |
/* bclr bclrl */ |
|
1689 |
GEN_BCOND(bclr, 0x13, 0x10, 0x00, do { } while (0), |
|
1690 |
gen_op_blrl_ctr((uint32_t)ctx->nip), |
|
1691 |
gen_op_blr_ctr((uint32_t)ctx->nip), |
|
1692 |
gen_op_blrl_ctrz((uint32_t)ctx->nip), |
|
1693 |
gen_op_blr_ctrz((uint32_t)ctx->nip), |
|
1694 |
gen_op_blr(), |
|
1695 |
gen_op_blrl((uint32_t)ctx->nip), |
|
1696 |
gen_op_blrl_ctr_true((uint32_t)ctx->nip, mask), |
|
1697 |
gen_op_blr_ctr_true((uint32_t)ctx->nip, mask), |
|
1698 |
gen_op_blrl_ctrz_true((uint32_t)ctx->nip, mask), |
|
1699 |
gen_op_blr_ctrz_true((uint32_t)ctx->nip, mask), |
|
1700 |
gen_op_blrl_true((uint32_t)ctx->nip, mask), |
|
1701 |
gen_op_blr_true((uint32_t)ctx->nip, mask), |
|
1702 |
gen_op_blrl_ctr_false((uint32_t)ctx->nip, mask), |
|
1703 |
gen_op_blr_ctr_false((uint32_t)ctx->nip, mask), |
|
1704 |
gen_op_blrl_ctrz_false((uint32_t)ctx->nip, mask), |
|
1705 |
gen_op_blr_ctrz_false((uint32_t)ctx->nip, mask), |
|
1706 |
gen_op_blrl_false((uint32_t)ctx->nip, mask), |
|
1707 |
gen_op_blr_false((uint32_t)ctx->nip, mask)) |
|
1524 |
#define BCOND_IM 0 |
|
1525 |
#define BCOND_LR 1 |
|
1526 |
#define BCOND_CTR 2 |
|
1527 |
|
|
1528 |
static inline void gen_bcond(DisasContext *ctx, int type) |
|
1529 |
{ |
|
1530 |
uint32_t target = 0; |
|
1531 |
uint32_t bo = BO(ctx->opcode); |
|
1532 |
uint32_t bi = BI(ctx->opcode); |
|
1533 |
uint32_t mask; |
|
1534 |
uint32_t li; |
|
1535 |
|
|
1536 |
gen_op_update_tb(ctx->tb_offset); |
|
1537 |
gen_op_update_decr(ctx->decr_offset); |
|
1538 |
gen_op_process_exceptions((uint32_t)ctx->nip - 4); |
|
1539 |
|
|
1540 |
if ((bo & 0x4) == 0) |
|
1541 |
gen_op_dec_ctr(); |
|
1542 |
switch(type) { |
|
1543 |
case BCOND_IM: |
|
1544 |
li = s_ext16(BD(ctx->opcode)); |
|
1545 |
if (AA(ctx->opcode) == 0) { |
|
1546 |
target = (uint32_t)ctx->nip + li - 4; |
|
1547 |
} else { |
|
1548 |
target = li; |
|
1549 |
} |
|
1550 |
break; |
|
1551 |
case BCOND_CTR: |
|
1552 |
gen_op_movl_T1_ctr(); |
|
1553 |
break; |
|
1554 |
default: |
|
1555 |
case BCOND_LR: |
|
1556 |
gen_op_movl_T1_lr(); |
|
1557 |
break; |
|
1558 |
} |
|
1559 |
if (LK(ctx->opcode)) { |
|
1560 |
gen_op_setlr((uint32_t)ctx->nip); |
|
1561 |
} |
|
1562 |
if (bo & 0x10) { |
|
1563 |
/* No CR condition */ |
|
1564 |
switch (bo & 0x6) { |
|
1565 |
case 0: |
|
1566 |
gen_op_test_ctr(); |
|
1567 |
break; |
|
1568 |
case 2: |
|
1569 |
gen_op_test_ctrz(); |
|
1570 |
break; |
|
1571 |
default: |
|
1572 |
case 4: |
|
1573 |
case 6: |
|
1574 |
if (type == BCOND_IM) { |
|
1575 |
gen_op_b((long)ctx->tb, target); |
|
1576 |
} else { |
|
1577 |
gen_op_b_T1(); |
|
1578 |
break; |
|
1579 |
} |
|
1580 |
goto no_test; |
|
1581 |
} |
|
1582 |
} else { |
|
1583 |
mask = 1 << (3 - (bi & 0x03)); |
|
1584 |
gen_op_load_crf_T0(bi >> 2); |
|
1585 |
if (bo & 0x8) { |
|
1586 |
switch (bo & 0x6) { |
|
1587 |
case 0: |
|
1588 |
gen_op_test_ctr_true(mask); |
|
1589 |
break; |
|
1590 |
case 2: |
|
1591 |
gen_op_test_ctrz_true(mask); |
|
1592 |
break; |
|
1593 |
default: |
|
1594 |
case 4: |
|
1595 |
case 6: |
|
1596 |
gen_op_test_true(mask); |
|
1597 |
break; |
|
1598 |
} |
|
1599 |
} else { |
|
1600 |
switch (bo & 0x6) { |
|
1601 |
case 0: |
|
1602 |
gen_op_test_ctr_false(mask); |
|
1603 |
break; |
|
1604 |
case 2: |
|
1605 |
gen_op_test_ctrz_false(mask); |
|
1606 |
break; |
|
1607 |
default: |
|
1608 |
case 4: |
|
1609 |
case 6: |
|
1610 |
gen_op_test_false(mask); |
|
1611 |
break; |
|
1612 |
} |
|
1613 |
} |
|
1614 |
} |
|
1615 |
if (type == BCOND_IM) { |
|
1616 |
gen_op_btest((long)ctx->tb, target, (uint32_t)ctx->nip); |
|
1617 |
} else { |
|
1618 |
gen_op_btest_T1((uint32_t)ctx->nip); |
|
1619 |
} |
|
1620 |
no_test: |
|
1621 |
ctx->exception = EXCP_BRANCH; |
|
1622 |
} |
|
1623 |
|
|
1624 |
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
|
1625 |
{ |
|
1626 |
gen_bcond(ctx, BCOND_IM); |
|
1627 |
} |
|
1628 |
|
|
1629 |
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW) |
|
1630 |
{ |
|
1631 |
gen_bcond(ctx, BCOND_CTR); |
|
1632 |
} |
|
1633 |
|
|
1634 |
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW) |
|
1635 |
{ |
|
1636 |
gen_bcond(ctx, BCOND_LR); |
|
1637 |
} |
|
1708 | 1638 |
|
1709 | 1639 |
/*** Condition register logical ***/ |
1710 | 1640 |
#define GEN_CRLOGIC(op, opc) \ |
... | ... | |
3148 | 3078 |
if (gen_opc_ptr >= gen_opc_end || |
3149 | 3079 |
((uint32_t)ctx.nip - pc_start) >= (TARGET_PAGE_SIZE - 32)) { |
3150 | 3080 |
if (ctx.exception == EXCP_NONE) { |
3151 |
gen_op_b((uint32_t)ctx.nip); |
|
3081 |
gen_op_b((long)ctx.tb, (uint32_t)ctx.nip);
|
|
3152 | 3082 |
ctx.exception = EXCP_BRANCH; |
3153 | 3083 |
} |
3154 | 3084 |
} |
Also available in: Unified diff