Commit 510ff0b730d1ba25a382ac3f6f73571ea731b8e5

Authored by pbrook
1 parent e6dbd3b3

Generate m68k address faults.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2871 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 88 additions and 43 deletions
target-m68k/translate.c
... ... @@ -43,6 +43,7 @@ static inline void qemu_assert(int cond, const char *msg)
43 43 /* internal defines */
44 44 typedef struct DisasContext {
45 45 CPUM68KState *env;
  46 + target_ulong insn_pc; /* Start of the current instruction. */
46 47 target_ulong pc;
47 48 int is_jmp;
48 49 int cc_op;
... ... @@ -437,8 +438,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
437 438 switch ((insn >> 3) & 7) {
438 439 case 0: /* Data register direct. */
439 440 case 1: /* Address register direct. */
440   - /* ??? generate bad addressing mode fault. */
441   - qemu_assert(0, "invalid addressing mode");
  441 + return -1;
442 442 case 2: /* Indirect register */
443 443 case 3: /* Indirect postincrement. */
444 444 reg += QREG_A0;
... ... @@ -477,8 +477,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
477 477 return gen_lea_indexed(s, opsize, -1);
478 478 case 4: /* Immediate. */
479 479 default:
480   - /* ??? generate bad addressing mode fault. */
481   - qemu_assert(0, "invalid addressing mode");
  480 + return -1;
482 481 }
483 482 }
484 483 /* Should never happen. */
... ... @@ -496,6 +495,8 @@ static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
496 495 tmp = *addrp;
497 496 } else {
498 497 tmp = gen_lea(s, insn, opsize);
  498 + if (tmp == -1)
  499 + return -1;
499 500 if (addrp)
500 501 *addrp = tmp;
501 502 }
... ... @@ -548,6 +549,8 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
548 549 tmp = *addrp;
549 550 } else {
550 551 tmp = gen_lea(s, insn, opsize);
  552 + if (tmp == -1)
  553 + return -1;
551 554 if (addrp)
552 555 *addrp = tmp;
553 556 }
... ... @@ -595,7 +598,7 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
595 598 }
596 599 return gen_im32(offset);
597 600 default:
598   - qemu_assert(0, "invalid addressing mode");
  601 + return -1;
599 602 }
600 603 }
601 604 /* Should never happen. */
... ... @@ -753,6 +756,27 @@ static void gen_exception(DisasContext *s, uint32_t where, int nr)
753 756 gen_op_raise_exception(nr);
754 757 }
755 758  
  759 +static inline void gen_addr_fault(DisasContext *s)
  760 +{
  761 + gen_exception(s, s->insn_pc, EXCP_ADDRESS);
  762 +}
  763 +
  764 +#define SRC_EA(result, opsize, val, addrp) do { \
  765 + result = gen_ea(s, insn, opsize, val, addrp); \
  766 + if (result == -1) { \
  767 + gen_addr_fault(s); \
  768 + return; \
  769 + } \
  770 + } while (0)
  771 +
  772 +#define DEST_EA(insn, opsize, val, addrp) do { \
  773 + int ea_result = gen_ea(s, insn, opsize, val, addrp); \
  774 + if (ea_result == -1) { \
  775 + gen_addr_fault(s); \
  776 + return; \
  777 + } \
  778 + } while (0)
  779 +
756 780 /* Generate a jump to an immediate address. */
757 781 static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
758 782 {
... ... @@ -806,7 +830,7 @@ DISAS_INSN(mulw)
806 830 gen_op_ext16s32(tmp, reg);
807 831 else
808 832 gen_op_ext16u32(tmp, reg);
809   - src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
  833 + SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL);
810 834 gen_op_mul32(tmp, tmp, src);
811 835 gen_op_mov32(reg, tmp);
812 836 /* Unlike m68k, coldfire always clears the overflow bit. */
... ... @@ -827,7 +851,7 @@ DISAS_INSN(divw)
827 851 } else {
828 852 gen_op_ext16u32(QREG_DIV1, reg);
829 853 }
830   - src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
  854 + SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL);
831 855 gen_op_mov32(QREG_DIV2, src);
832 856 if (sign) {
833 857 gen_op_divs(1);
... ... @@ -860,7 +884,7 @@ DISAS_INSN(divl)
860 884 num = DREG(ext, 12);
861 885 reg = DREG(ext, 0);
862 886 gen_op_mov32(QREG_DIV1, num);
863   - den = gen_ea(s, insn, OS_LONG, 0, NULL);
  887 + SRC_EA(den, OS_LONG, 0, NULL);
864 888 gen_op_mov32(QREG_DIV2, den);
865 889 if (ext & 0x0800) {
866 890 gen_op_divs(2);
... ... @@ -891,11 +915,11 @@ DISAS_INSN(addsub)
891 915 reg = DREG(insn, 9);
892 916 dest = gen_new_qreg(QMODE_I32);
893 917 if (insn & 0x100) {
894   - tmp = gen_ea(s, insn, OS_LONG, 0, &addr);
  918 + SRC_EA(tmp, OS_LONG, 0, &addr);
895 919 src = reg;
896 920 } else {
897 921 tmp = reg;
898   - src = gen_ea(s, insn, OS_LONG, 0, NULL);
  922 + SRC_EA(src, OS_LONG, 0, NULL);
899 923 }
900 924 if (add) {
901 925 gen_op_add32(dest, tmp, src);
... ... @@ -908,7 +932,7 @@ DISAS_INSN(addsub)
908 932 }
909 933 gen_op_update_cc_add(dest, src);
910 934 if (insn & 0x100) {
911   - gen_ea(s, insn, OS_LONG, dest, &addr);
  935 + DEST_EA(insn, OS_LONG, dest, &addr);
912 936 } else {
913 937 gen_op_mov32(reg, dest);
914 938 }
... ... @@ -966,7 +990,7 @@ DISAS_INSN(bitop_reg)
966 990 else
967 991 opsize = OS_LONG;
968 992 op = (insn >> 6) & 3;
969   - src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
  993 + SRC_EA(src1, opsize, 0, op ? &addr: NULL);
970 994 src2 = DREG(insn, 9);
971 995 dest = gen_new_qreg(QMODE_I32);
972 996  
... ... @@ -996,7 +1020,7 @@ DISAS_INSN(bitop_reg)
996 1020 break;
997 1021 }
998 1022 if (op)
999   - gen_ea(s, insn, opsize, dest, &addr);
  1023 + DEST_EA(insn, opsize, dest, &addr);
1000 1024 }
1001 1025  
1002 1026 DISAS_INSN(sats)
... ... @@ -1041,6 +1065,10 @@ DISAS_INSN(movem)
1041 1065 mask = lduw_code(s->pc);
1042 1066 s->pc += 2;
1043 1067 tmp = gen_lea(s, insn, OS_LONG);
  1068 + if (tmp == -1) {
  1069 + gen_addr_fault(s);
  1070 + return;
  1071 + }
1044 1072 addr = gen_new_qreg(QMODE_I32);
1045 1073 gen_op_mov32(addr, tmp);
1046 1074 is_load = ((insn & 0x0400) != 0);
... ... @@ -1086,7 +1114,7 @@ DISAS_INSN(bitop_im)
1086 1114 return;
1087 1115 }
1088 1116  
1089   - src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
  1117 + SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1090 1118  
1091 1119 gen_flush_flags(s);
1092 1120 tmp = gen_new_qreg(QMODE_I32);
... ... @@ -1116,7 +1144,7 @@ DISAS_INSN(bitop_im)
1116 1144 break;
1117 1145 }
1118 1146 if (op)
1119   - gen_ea(s, insn, opsize, dest, &addr);
  1147 + DEST_EA(insn, opsize, dest, &addr);
1120 1148 }
1121 1149  
1122 1150 DISAS_INSN(arith_im)
... ... @@ -1128,7 +1156,7 @@ DISAS_INSN(arith_im)
1128 1156 int addr;
1129 1157  
1130 1158 op = (insn >> 9) & 7;
1131   - src1 = gen_ea(s, insn, OS_LONG, 0, (op == 6) ? NULL : &addr);
  1159 + SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
1132 1160 src2 = gen_im32(read_im32(s));
1133 1161 dest = gen_new_qreg(QMODE_I32);
1134 1162 switch (op) {
... ... @@ -1168,7 +1196,7 @@ DISAS_INSN(arith_im)
1168 1196 abort();
1169 1197 }
1170 1198 if (op != 6) {
1171   - gen_ea(s, insn, OS_LONG, dest, &addr);
  1199 + DEST_EA(insn, OS_LONG, dest, &addr);
1172 1200 }
1173 1201 }
1174 1202  
... ... @@ -1200,7 +1228,7 @@ DISAS_INSN(move)
1200 1228 default:
1201 1229 abort();
1202 1230 }
1203   - src = gen_ea(s, insn, opsize, -1, NULL);
  1231 + SRC_EA(src, opsize, -1, NULL);
1204 1232 op = (insn >> 6) & 7;
1205 1233 if (op == 1) {
1206 1234 /* movea */
... ... @@ -1211,7 +1239,7 @@ DISAS_INSN(move)
1211 1239 /* normal move */
1212 1240 uint16_t dest_ea;
1213 1241 dest_ea = ((insn >> 9) & 7) | (op << 3);
1214   - gen_ea(s, dest_ea, opsize, src, NULL);
  1242 + DEST_EA(dest_ea, opsize, src, NULL);
1215 1243 /* This will be correct because loads sign extend. */
1216 1244 gen_logic_cc(s, src);
1217 1245 }
... ... @@ -1247,6 +1275,10 @@ DISAS_INSN(lea)
1247 1275  
1248 1276 reg = AREG(insn, 9);
1249 1277 tmp = gen_lea(s, insn, OS_LONG);
  1278 + if (tmp == -1) {
  1279 + gen_addr_fault(s);
  1280 + return;
  1281 + }
1250 1282 gen_op_mov32(reg, tmp);
1251 1283 }
1252 1284  
... ... @@ -1267,7 +1299,7 @@ DISAS_INSN(clr)
1267 1299 default:
1268 1300 abort();
1269 1301 }
1270   - gen_ea (s, insn, opsize, gen_im32(0), NULL);
  1302 + DEST_EA(insn, opsize, gen_im32(0), NULL);
1271 1303 gen_logic_cc(s, gen_im32(0));
1272 1304 }
1273 1305  
... ... @@ -1384,6 +1416,10 @@ DISAS_INSN(pea)
1384 1416 int tmp;
1385 1417  
1386 1418 tmp = gen_lea(s, insn, OS_LONG);
  1419 + if (tmp == -1) {
  1420 + gen_addr_fault(s);
  1421 + return;
  1422 + }
1387 1423 gen_push(s, tmp);
1388 1424 }
1389 1425  
... ... @@ -1425,7 +1461,7 @@ DISAS_INSN(tst)
1425 1461 default:
1426 1462 abort();
1427 1463 }
1428   - tmp = gen_ea(s, insn, opsize, -1, NULL);
  1464 + SRC_EA(tmp, opsize, -1, NULL);
1429 1465 gen_logic_cc(s, tmp);
1430 1466 }
1431 1467  
... ... @@ -1447,10 +1483,10 @@ DISAS_INSN(tas)
1447 1483 int addr;
1448 1484  
1449 1485 dest = gen_new_qreg(QMODE_I32);
1450   - src1 = gen_ea(s, insn, OS_BYTE, -1, &addr);
  1486 + SRC_EA(src1, OS_BYTE, -1, &addr);
1451 1487 gen_logic_cc(s, src1);
1452 1488 gen_op_or32(dest, src1, gen_im32(0x80));
1453   - gen_ea(s, insn, OS_BYTE, dest, &addr);
  1489 + DEST_EA(insn, OS_BYTE, dest, &addr);
1454 1490 }
1455 1491  
1456 1492 DISAS_INSN(mull)
... ... @@ -1469,7 +1505,7 @@ DISAS_INSN(mull)
1469 1505 return;
1470 1506 }
1471 1507 reg = DREG(ext, 12);
1472   - src1 = gen_ea(s, insn, OS_LONG, 0, NULL);
  1508 + SRC_EA(src1, OS_LONG, 0, NULL);
1473 1509 dest = gen_new_qreg(QMODE_I32);
1474 1510 gen_op_mul32(dest, src1, reg);
1475 1511 gen_op_mov32(reg, dest);
... ... @@ -1528,6 +1564,10 @@ DISAS_INSN(jump)
1528 1564 /* Load the target address first to ensure correct exception
1529 1565 behavior. */
1530 1566 tmp = gen_lea(s, insn, OS_LONG);
  1567 + if (tmp == -1) {
  1568 + gen_addr_fault(s);
  1569 + return;
  1570 + }
1531 1571 if ((insn & 0x40) == 0) {
1532 1572 /* jsr */
1533 1573 gen_push(s, gen_im32(s->pc));
... ... @@ -1543,7 +1583,7 @@ DISAS_INSN(addsubq)
1543 1583 int val;
1544 1584 int addr;
1545 1585  
1546   - src1 = gen_ea(s, insn, OS_LONG, 0, &addr);
  1586 + SRC_EA(src1, OS_LONG, 0, &addr);
1547 1587 val = (insn >> 9) & 7;
1548 1588 if (val == 0)
1549 1589 val = 8;
... ... @@ -1570,7 +1610,7 @@ DISAS_INSN(addsubq)
1570 1610 }
1571 1611 gen_op_update_cc_add(dest, src2);
1572 1612 }
1573   - gen_ea(s, insn, OS_LONG, dest, &addr);
  1613 + DEST_EA(insn, OS_LONG, dest, &addr);
1574 1614 }
1575 1615  
1576 1616 DISAS_INSN(tpf)
... ... @@ -1642,7 +1682,7 @@ DISAS_INSN(mvzs)
1642 1682 opsize = OS_WORD;
1643 1683 else
1644 1684 opsize = OS_BYTE;
1645   - src = gen_ea(s, insn, opsize, (insn & 0x80) ? 0 : -1, NULL);
  1685 + SRC_EA(src, opsize, (insn & 0x80) ? 0 : -1, NULL);
1646 1686 reg = DREG(insn, 9);
1647 1687 gen_op_mov32(reg, src);
1648 1688 gen_logic_cc(s, src);
... ... @@ -1658,11 +1698,11 @@ DISAS_INSN(or)
1658 1698 reg = DREG(insn, 9);
1659 1699 dest = gen_new_qreg(QMODE_I32);
1660 1700 if (insn & 0x100) {
1661   - src = gen_ea(s, insn, OS_LONG, 0, &addr);
  1701 + SRC_EA(src, OS_LONG, 0, &addr);
1662 1702 gen_op_or32(dest, src, reg);
1663   - gen_ea(s, insn, OS_LONG, dest, &addr);
  1703 + DEST_EA(insn, OS_LONG, dest, &addr);
1664 1704 } else {
1665   - src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1705 + SRC_EA(src, OS_LONG, 0, NULL);
1666 1706 gen_op_or32(dest, src, reg);
1667 1707 gen_op_mov32(reg, dest);
1668 1708 }
... ... @@ -1674,7 +1714,7 @@ DISAS_INSN(suba)
1674 1714 int src;
1675 1715 int reg;
1676 1716  
1677   - src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1717 + SRC_EA(src, OS_LONG, 0, NULL);
1678 1718 reg = AREG(insn, 9);
1679 1719 gen_op_sub32(reg, reg, src);
1680 1720 }
... ... @@ -1714,7 +1754,7 @@ DISAS_INSN(mov3q)
1714 1754 val = -1;
1715 1755 src = gen_im32(val);
1716 1756 gen_logic_cc(s, src);
1717   - gen_ea(s, insn, OS_LONG, src, NULL);
  1757 + DEST_EA(insn, OS_LONG, src, NULL);
1718 1758 }
1719 1759  
1720 1760 DISAS_INSN(cmp)
... ... @@ -1742,7 +1782,7 @@ DISAS_INSN(cmp)
1742 1782 default:
1743 1783 abort();
1744 1784 }
1745   - src = gen_ea(s, insn, opsize, -1, NULL);
  1785 + SRC_EA(src, opsize, -1, NULL);
1746 1786 reg = DREG(insn, 9);
1747 1787 dest = gen_new_qreg(QMODE_I32);
1748 1788 gen_op_sub32(dest, reg, src);
... ... @@ -1761,7 +1801,7 @@ DISAS_INSN(cmpa)
1761 1801 } else {
1762 1802 opsize = OS_WORD;
1763 1803 }
1764   - src = gen_ea(s, insn, opsize, -1, NULL);
  1804 + SRC_EA(src, opsize, -1, NULL);
1765 1805 reg = AREG(insn, 9);
1766 1806 dest = gen_new_qreg(QMODE_I32);
1767 1807 gen_op_sub32(dest, reg, src);
... ... @@ -1776,12 +1816,12 @@ DISAS_INSN(eor)
1776 1816 int dest;
1777 1817 int addr;
1778 1818  
1779   - src = gen_ea(s, insn, OS_LONG, 0, &addr);
  1819 + SRC_EA(src, OS_LONG, 0, &addr);
1780 1820 reg = DREG(insn, 9);
1781 1821 dest = gen_new_qreg(QMODE_I32);
1782 1822 gen_op_xor32(dest, src, reg);
1783 1823 gen_logic_cc(s, dest);
1784   - gen_ea(s, insn, OS_LONG, dest, &addr);
  1824 + DEST_EA(insn, OS_LONG, dest, &addr);
1785 1825 }
1786 1826  
1787 1827 DISAS_INSN(and)
... ... @@ -1794,11 +1834,11 @@ DISAS_INSN(and)
1794 1834 reg = DREG(insn, 9);
1795 1835 dest = gen_new_qreg(QMODE_I32);
1796 1836 if (insn & 0x100) {
1797   - src = gen_ea(s, insn, OS_LONG, 0, &addr);
  1837 + SRC_EA(src, OS_LONG, 0, &addr);
1798 1838 gen_op_and32(dest, src, reg);
1799   - gen_ea(s, insn, OS_LONG, dest, &addr);
  1839 + DEST_EA(insn, OS_LONG, dest, &addr);
1800 1840 } else {
1801   - src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1841 + SRC_EA(src, OS_LONG, 0, NULL);
1802 1842 gen_op_and32(dest, src, reg);
1803 1843 gen_op_mov32(reg, dest);
1804 1844 }
... ... @@ -1810,7 +1850,7 @@ DISAS_INSN(adda)
1810 1850 int src;
1811 1851 int reg;
1812 1852  
1813   - src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1853 + SRC_EA(src, OS_LONG, 0, NULL);
1814 1854 reg = AREG(insn, 9);
1815 1855 gen_op_add32(reg, reg, src);
1816 1856 }
... ... @@ -2114,7 +2154,7 @@ DISAS_INSN(fpu)
2114 2154 default:
2115 2155 goto undef;
2116 2156 }
2117   - gen_ea(s, insn, opsize, res, NULL);
  2157 + DEST_EA(insn, opsize, res, NULL);
2118 2158 return;
2119 2159 case 4: /* fmove to control register. */
2120 2160 switch ((ext >> 10) & 7) {
... ... @@ -2141,7 +2181,7 @@ DISAS_INSN(fpu)
2141 2181 (ext >> 10) & 7);
2142 2182 goto undef;
2143 2183 }
2144   - gen_ea(s, insn, OS_LONG, res, NULL);
  2184 + DEST_EA(insn, OS_LONG, res, NULL);
2145 2185 break;
2146 2186 case 6: /* fmovem */
2147 2187 case 7:
... ... @@ -2151,6 +2191,10 @@ DISAS_INSN(fpu)
2151 2191 if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
2152 2192 goto undef;
2153 2193 src = gen_lea(s, insn, OS_LONG);
  2194 + if (src == -1) {
  2195 + gen_addr_fault(s);
  2196 + return;
  2197 + }
2154 2198 addr = gen_new_qreg(QMODE_I32);
2155 2199 gen_op_mov32(addr, src);
2156 2200 mask = 0x80;
... ... @@ -2186,7 +2230,7 @@ DISAS_INSN(fpu)
2186 2230 default:
2187 2231 goto undef;
2188 2232 }
2189   - tmp = gen_ea(s, insn, opsize, -1, NULL);
  2233 + SRC_EA(tmp, opsize, -1, NULL);
2190 2234 if (opsize == OS_DOUBLE) {
2191 2235 src = tmp;
2192 2236 } else {
... ... @@ -2846,6 +2890,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2846 2890 gen_opc_instr_start[lj] = 1;
2847 2891 }
2848 2892 last_cc_op = dc->cc_op;
  2893 + dc->insn_pc = dc->pc;
2849 2894 disas_m68k_insn(env, dc);
2850 2895 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2851 2896 !env->singlestep_enabled &&
... ...