diff options
Diffstat (limited to 'src/lj_asm_ppc.h')
-rw-r--r-- | src/lj_asm_ppc.h | 232 |
1 files changed, 72 insertions, 160 deletions
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h index 9c9c3ea4..d9174e7d 100644 --- a/src/lj_asm_ppc.h +++ b/src/lj_asm_ppc.h | |||
@@ -840,7 +840,7 @@ static void asm_xload(ASMState *as, IRIns *ir) | |||
840 | asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0); | 840 | asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0); |
841 | } | 841 | } |
842 | 842 | ||
843 | static void asm_xstore(ASMState *as, IRIns *ir, int32_t ofs) | 843 | static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs) |
844 | { | 844 | { |
845 | IRIns *irb; | 845 | IRIns *irb; |
846 | if (ir->r == RID_SINK) | 846 | if (ir->r == RID_SINK) |
@@ -857,6 +857,8 @@ static void asm_xstore(ASMState *as, IRIns *ir, int32_t ofs) | |||
857 | } | 857 | } |
858 | } | 858 | } |
859 | 859 | ||
860 | #define asm_xstore(as, ir) asm_xstore_(as, ir, 0) | ||
861 | |||
860 | static void asm_ahuvload(ASMState *as, IRIns *ir) | 862 | static void asm_ahuvload(ASMState *as, IRIns *ir) |
861 | { | 863 | { |
862 | IRType1 t = ir->t; | 864 | IRType1 t = ir->t; |
@@ -1120,6 +1122,16 @@ static void asm_fpunary(ASMState *as, IRIns *ir, PPCIns pi) | |||
1120 | emit_fb(as, pi, dest, left); | 1122 | emit_fb(as, pi, dest, left); |
1121 | } | 1123 | } |
1122 | 1124 | ||
1125 | static void asm_fpmath(ASMState *as, IRIns *ir) | ||
1126 | { | ||
1127 | if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) | ||
1128 | return; | ||
1129 | if (ir->op2 == IRFPM_SQRT && (as->flags & JIT_F_SQRT)) | ||
1130 | asm_fpunary(as, ir, PPCI_FSQRT); | ||
1131 | else | ||
1132 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); | ||
1133 | } | ||
1134 | |||
1123 | static void asm_add(ASMState *as, IRIns *ir) | 1135 | static void asm_add(ASMState *as, IRIns *ir) |
1124 | { | 1136 | { |
1125 | if (irt_isnum(ir->t)) { | 1137 | if (irt_isnum(ir->t)) { |
@@ -1217,6 +1229,10 @@ static void asm_mul(ASMState *as, IRIns *ir) | |||
1217 | } | 1229 | } |
1218 | } | 1230 | } |
1219 | 1231 | ||
1232 | #define asm_div(as, ir) asm_fparith(as, ir, PPCI_FDIV) | ||
1233 | #define asm_mod(as, ir) asm_callid(as, ir, IRCALL_lj_vm_modi) | ||
1234 | #define asm_pow(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi) | ||
1235 | |||
1220 | static void asm_neg(ASMState *as, IRIns *ir) | 1236 | static void asm_neg(ASMState *as, IRIns *ir) |
1221 | { | 1237 | { |
1222 | if (irt_isnum(ir->t)) { | 1238 | if (irt_isnum(ir->t)) { |
@@ -1235,6 +1251,10 @@ static void asm_neg(ASMState *as, IRIns *ir) | |||
1235 | } | 1251 | } |
1236 | } | 1252 | } |
1237 | 1253 | ||
1254 | #define asm_abs(as, ir) asm_fpunary(as, ir, PPCI_FABS) | ||
1255 | #define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2) | ||
1256 | #define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp) | ||
1257 | |||
1238 | static void asm_arithov(ASMState *as, IRIns *ir, PPCIns pi) | 1258 | static void asm_arithov(ASMState *as, IRIns *ir, PPCIns pi) |
1239 | { | 1259 | { |
1240 | Reg dest, left, right; | 1260 | Reg dest, left, right; |
@@ -1250,6 +1270,10 @@ static void asm_arithov(ASMState *as, IRIns *ir, PPCIns pi) | |||
1250 | emit_tab(as, pi|PPCF_DOT, dest, left, right); | 1270 | emit_tab(as, pi|PPCF_DOT, dest, left, right); |
1251 | } | 1271 | } |
1252 | 1272 | ||
1273 | #define asm_addov(as, ir) asm_arithov(as, ir, PPCI_ADDO) | ||
1274 | #define asm_subov(as, ir) asm_arithov(as, ir, PPCI_SUBFO) | ||
1275 | #define asm_mulov(as, ir) asm_arithov(as, ir, PPCI_MULLWO) | ||
1276 | |||
1253 | #if LJ_HASFFI | 1277 | #if LJ_HASFFI |
1254 | static void asm_add64(ASMState *as, IRIns *ir) | 1278 | static void asm_add64(ASMState *as, IRIns *ir) |
1255 | { | 1279 | { |
@@ -1329,7 +1353,7 @@ static void asm_neg64(ASMState *as, IRIns *ir) | |||
1329 | } | 1353 | } |
1330 | #endif | 1354 | #endif |
1331 | 1355 | ||
1332 | static void asm_bitnot(ASMState *as, IRIns *ir) | 1356 | static void asm_bnot(ASMState *as, IRIns *ir) |
1333 | { | 1357 | { |
1334 | Reg dest, left, right; | 1358 | Reg dest, left, right; |
1335 | PPCIns pi = PPCI_NOR; | 1359 | PPCIns pi = PPCI_NOR; |
@@ -1356,7 +1380,7 @@ nofuse: | |||
1356 | emit_asb(as, pi, dest, left, right); | 1380 | emit_asb(as, pi, dest, left, right); |
1357 | } | 1381 | } |
1358 | 1382 | ||
1359 | static void asm_bitswap(ASMState *as, IRIns *ir) | 1383 | static void asm_bswap(ASMState *as, IRIns *ir) |
1360 | { | 1384 | { |
1361 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1385 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1362 | IRIns *irx; | 1386 | IRIns *irx; |
@@ -1377,32 +1401,6 @@ static void asm_bitswap(ASMState *as, IRIns *ir) | |||
1377 | } | 1401 | } |
1378 | } | 1402 | } |
1379 | 1403 | ||
1380 | static void asm_bitop(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pik) | ||
1381 | { | ||
1382 | Reg dest = ra_dest(as, ir, RSET_GPR); | ||
1383 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | ||
1384 | if (irref_isk(ir->op2)) { | ||
1385 | int32_t k = IR(ir->op2)->i; | ||
1386 | Reg tmp = left; | ||
1387 | if ((checku16(k) || (k & 0xffff) == 0) || (tmp = dest, !as->sectref)) { | ||
1388 | if (!checku16(k)) { | ||
1389 | emit_asi(as, pik ^ (PPCI_ORI ^ PPCI_ORIS), dest, tmp, (k >> 16)); | ||
1390 | if ((k & 0xffff) == 0) return; | ||
1391 | } | ||
1392 | emit_asi(as, pik, dest, left, k); | ||
1393 | return; | ||
1394 | } | ||
1395 | } | ||
1396 | /* May fail due to spills/restores above, but simplifies the logic. */ | ||
1397 | if (as->flagmcp == as->mcp) { | ||
1398 | as->flagmcp = NULL; | ||
1399 | as->mcp++; | ||
1400 | pi |= PPCF_DOT; | ||
1401 | } | ||
1402 | right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left)); | ||
1403 | emit_asb(as, pi, dest, left, right); | ||
1404 | } | ||
1405 | |||
1406 | /* Fuse BAND with contiguous bitmask and a shift to rlwinm. */ | 1404 | /* Fuse BAND with contiguous bitmask and a shift to rlwinm. */ |
1407 | static void asm_fuseandsh(ASMState *as, PPCIns pi, int32_t mask, IRRef ref) | 1405 | static void asm_fuseandsh(ASMState *as, PPCIns pi, int32_t mask, IRRef ref) |
1408 | { | 1406 | { |
@@ -1433,7 +1431,7 @@ nofuse: | |||
1433 | *--as->mcp = pi | PPCF_T(left); | 1431 | *--as->mcp = pi | PPCF_T(left); |
1434 | } | 1432 | } |
1435 | 1433 | ||
1436 | static void asm_bitand(ASMState *as, IRIns *ir) | 1434 | static void asm_band(ASMState *as, IRIns *ir) |
1437 | { | 1435 | { |
1438 | Reg dest, left, right; | 1436 | Reg dest, left, right; |
1439 | IRRef lref = ir->op1; | 1437 | IRRef lref = ir->op1; |
@@ -1488,6 +1486,35 @@ static void asm_bitand(ASMState *as, IRIns *ir) | |||
1488 | emit_asb(as, PPCI_AND ^ dot, dest, left, right); | 1486 | emit_asb(as, PPCI_AND ^ dot, dest, left, right); |
1489 | } | 1487 | } |
1490 | 1488 | ||
1489 | static void asm_bitop(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pik) | ||
1490 | { | ||
1491 | Reg dest = ra_dest(as, ir, RSET_GPR); | ||
1492 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | ||
1493 | if (irref_isk(ir->op2)) { | ||
1494 | int32_t k = IR(ir->op2)->i; | ||
1495 | Reg tmp = left; | ||
1496 | if ((checku16(k) || (k & 0xffff) == 0) || (tmp = dest, !as->sectref)) { | ||
1497 | if (!checku16(k)) { | ||
1498 | emit_asi(as, pik ^ (PPCI_ORI ^ PPCI_ORIS), dest, tmp, (k >> 16)); | ||
1499 | if ((k & 0xffff) == 0) return; | ||
1500 | } | ||
1501 | emit_asi(as, pik, dest, left, k); | ||
1502 | return; | ||
1503 | } | ||
1504 | } | ||
1505 | /* May fail due to spills/restores above, but simplifies the logic. */ | ||
1506 | if (as->flagmcp == as->mcp) { | ||
1507 | as->flagmcp = NULL; | ||
1508 | as->mcp++; | ||
1509 | pi |= PPCF_DOT; | ||
1510 | } | ||
1511 | right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left)); | ||
1512 | emit_asb(as, pi, dest, left, right); | ||
1513 | } | ||
1514 | |||
1515 | #define asm_bor(as, ir) asm_bitop(as, ir, PPCI_OR, PPCI_ORI) | ||
1516 | #define asm_bxor(as, ir) asm_bitop(as, ir, PPCI_XOR, PPCI_XORI) | ||
1517 | |||
1491 | static void asm_bitshift(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pik) | 1518 | static void asm_bitshift(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pik) |
1492 | { | 1519 | { |
1493 | Reg dest, left; | 1520 | Reg dest, left; |
@@ -1513,6 +1540,14 @@ static void asm_bitshift(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pik) | |||
1513 | } | 1540 | } |
1514 | } | 1541 | } |
1515 | 1542 | ||
1543 | #define asm_bshl(as, ir) asm_bitshift(as, ir, PPCI_SLW, 0) | ||
1544 | #define asm_bshr(as, ir) asm_bitshift(as, ir, PPCI_SRW, 1) | ||
1545 | #define asm_bsar(as, ir) asm_bitshift(as, ir, PPCI_SRAW, PPCI_SRAWI) | ||
1546 | #define asm_brol(as, ir) \ | ||
1547 | asm_bitshift(as, ir, PPCI_RLWNM|PPCF_MB(0)|PPCF_ME(31), \ | ||
1548 | PPCI_RLWINM|PPCF_MB(0)|PPCF_ME(31)) | ||
1549 | #define asm_bror(as, ir) lua_assert(0) | ||
1550 | |||
1516 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | 1551 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) |
1517 | { | 1552 | { |
1518 | if (irt_isnum(ir->t)) { | 1553 | if (irt_isnum(ir->t)) { |
@@ -1543,6 +1578,9 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | |||
1543 | } | 1578 | } |
1544 | } | 1579 | } |
1545 | 1580 | ||
1581 | #define asm_min(as, ir) asm_min_max(as, ir, 0) | ||
1582 | #define asm_max(as, ir) asm_min_max(as, ir, 1) | ||
1583 | |||
1546 | /* -- Comparisons --------------------------------------------------------- */ | 1584 | /* -- Comparisons --------------------------------------------------------- */ |
1547 | 1585 | ||
1548 | #define CC_UNSIGNED 0x08 /* Unsigned integer comparison. */ | 1586 | #define CC_UNSIGNED 0x08 /* Unsigned integer comparison. */ |
@@ -1619,6 +1657,8 @@ static void asm_comp(ASMState *as, IRIns *ir) | |||
1619 | } | 1657 | } |
1620 | } | 1658 | } |
1621 | 1659 | ||
1660 | #define asm_equal(as, ir) asm_comp(as, ir) | ||
1661 | |||
1622 | #if LJ_HASFFI | 1662 | #if LJ_HASFFI |
1623 | /* 64 bit integer comparisons. */ | 1663 | /* 64 bit integer comparisons. */ |
1624 | static void asm_comp64(ASMState *as, IRIns *ir) | 1664 | static void asm_comp64(ASMState *as, IRIns *ir) |
@@ -1664,8 +1704,8 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
1664 | } else if ((ir-1)->o == IR_XSTORE) { | 1704 | } else if ((ir-1)->o == IR_XSTORE) { |
1665 | as->curins--; /* Handle both stores here. */ | 1705 | as->curins--; /* Handle both stores here. */ |
1666 | if ((ir-1)->r != RID_SINK) { | 1706 | if ((ir-1)->r != RID_SINK) { |
1667 | asm_xstore(as, ir, 0); | 1707 | asm_xstore_(as, ir, 0); |
1668 | asm_xstore(as, ir-1, 4); | 1708 | asm_xstore_(as, ir-1, 4); |
1669 | } | 1709 | } |
1670 | return; | 1710 | return; |
1671 | } | 1711 | } |
@@ -1871,134 +1911,6 @@ static void asm_tail_prep(ASMState *as) | |||
1871 | } | 1911 | } |
1872 | } | 1912 | } |
1873 | 1913 | ||
1874 | /* -- Instruction dispatch ------------------------------------------------ */ | ||
1875 | |||
1876 | /* Assemble a single instruction. */ | ||
1877 | static void asm_ir(ASMState *as, IRIns *ir) | ||
1878 | { | ||
1879 | switch ((IROp)ir->o) { | ||
1880 | /* Miscellaneous ops. */ | ||
1881 | case IR_LOOP: asm_loop(as); break; | ||
1882 | case IR_NOP: case IR_XBAR: lua_assert(!ra_used(ir)); break; | ||
1883 | case IR_USE: | ||
1884 | ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break; | ||
1885 | case IR_PHI: asm_phi(as, ir); break; | ||
1886 | case IR_HIOP: asm_hiop(as, ir); break; | ||
1887 | case IR_GCSTEP: asm_gcstep(as, ir); break; | ||
1888 | |||
1889 | /* Guarded assertions. */ | ||
1890 | case IR_EQ: case IR_NE: | ||
1891 | if ((ir-1)->o == IR_HREF && ir->op1 == as->curins-1) { | ||
1892 | as->curins--; | ||
1893 | asm_href(as, ir-1, (IROp)ir->o); | ||
1894 | break; | ||
1895 | } | ||
1896 | /* fallthrough */ | ||
1897 | case IR_LT: case IR_GE: case IR_LE: case IR_GT: | ||
1898 | case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT: | ||
1899 | case IR_ABC: | ||
1900 | asm_comp(as, ir); | ||
1901 | break; | ||
1902 | |||
1903 | case IR_RETF: asm_retf(as, ir); break; | ||
1904 | |||
1905 | /* Bit ops. */ | ||
1906 | case IR_BNOT: asm_bitnot(as, ir); break; | ||
1907 | case IR_BSWAP: asm_bitswap(as, ir); break; | ||
1908 | |||
1909 | case IR_BAND: asm_bitand(as, ir); break; | ||
1910 | case IR_BOR: asm_bitop(as, ir, PPCI_OR, PPCI_ORI); break; | ||
1911 | case IR_BXOR: asm_bitop(as, ir, PPCI_XOR, PPCI_XORI); break; | ||
1912 | |||
1913 | case IR_BSHL: asm_bitshift(as, ir, PPCI_SLW, 0); break; | ||
1914 | case IR_BSHR: asm_bitshift(as, ir, PPCI_SRW, 1); break; | ||
1915 | case IR_BSAR: asm_bitshift(as, ir, PPCI_SRAW, PPCI_SRAWI); break; | ||
1916 | case IR_BROL: asm_bitshift(as, ir, PPCI_RLWNM|PPCF_MB(0)|PPCF_ME(31), | ||
1917 | PPCI_RLWINM|PPCF_MB(0)|PPCF_ME(31)); break; | ||
1918 | case IR_BROR: lua_assert(0); break; | ||
1919 | |||
1920 | /* Arithmetic ops. */ | ||
1921 | case IR_ADD: asm_add(as, ir); break; | ||
1922 | case IR_SUB: asm_sub(as, ir); break; | ||
1923 | case IR_MUL: asm_mul(as, ir); break; | ||
1924 | case IR_DIV: asm_fparith(as, ir, PPCI_FDIV); break; | ||
1925 | case IR_MOD: asm_callid(as, ir, IRCALL_lj_vm_modi); break; | ||
1926 | case IR_POW: asm_callid(as, ir, IRCALL_lj_vm_powi); break; | ||
1927 | case IR_NEG: asm_neg(as, ir); break; | ||
1928 | |||
1929 | case IR_ABS: asm_fpunary(as, ir, PPCI_FABS); break; | ||
1930 | case IR_ATAN2: asm_callid(as, ir, IRCALL_atan2); break; | ||
1931 | case IR_LDEXP: asm_callid(as, ir, IRCALL_ldexp); break; | ||
1932 | case IR_MIN: asm_min_max(as, ir, 0); break; | ||
1933 | case IR_MAX: asm_min_max(as, ir, 1); break; | ||
1934 | case IR_FPMATH: | ||
1935 | if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) | ||
1936 | break; | ||
1937 | if (ir->op2 == IRFPM_SQRT && (as->flags & JIT_F_SQRT)) | ||
1938 | asm_fpunary(as, ir, PPCI_FSQRT); | ||
1939 | else | ||
1940 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); | ||
1941 | break; | ||
1942 | |||
1943 | /* Overflow-checking arithmetic ops. */ | ||
1944 | case IR_ADDOV: asm_arithov(as, ir, PPCI_ADDO); break; | ||
1945 | case IR_SUBOV: asm_arithov(as, ir, PPCI_SUBFO); break; | ||
1946 | case IR_MULOV: asm_arithov(as, ir, PPCI_MULLWO); break; | ||
1947 | |||
1948 | /* Memory references. */ | ||
1949 | case IR_AREF: asm_aref(as, ir); break; | ||
1950 | case IR_HREF: asm_href(as, ir, 0); break; | ||
1951 | case IR_HREFK: asm_hrefk(as, ir); break; | ||
1952 | case IR_NEWREF: asm_newref(as, ir); break; | ||
1953 | case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; | ||
1954 | case IR_FREF: asm_fref(as, ir); break; | ||
1955 | case IR_STRREF: asm_strref(as, ir); break; | ||
1956 | |||
1957 | /* Loads and stores. */ | ||
1958 | case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: | ||
1959 | asm_ahuvload(as, ir); | ||
1960 | break; | ||
1961 | case IR_FLOAD: asm_fload(as, ir); break; | ||
1962 | case IR_XLOAD: asm_xload(as, ir); break; | ||
1963 | case IR_SLOAD: asm_sload(as, ir); break; | ||
1964 | |||
1965 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: asm_ahustore(as, ir); break; | ||
1966 | case IR_FSTORE: asm_fstore(as, ir); break; | ||
1967 | case IR_XSTORE: asm_xstore(as, ir, 0); break; | ||
1968 | |||
1969 | /* Allocations. */ | ||
1970 | case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break; | ||
1971 | case IR_TNEW: asm_tnew(as, ir); break; | ||
1972 | case IR_TDUP: asm_tdup(as, ir); break; | ||
1973 | case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break; | ||
1974 | |||
1975 | /* Buffer operations. */ | ||
1976 | case IR_BUFHDR: asm_bufhdr(as, ir); break; | ||
1977 | case IR_BUFPUT: asm_bufput(as, ir); break; | ||
1978 | case IR_BUFSTR: asm_bufstr(as, ir); break; | ||
1979 | |||
1980 | /* Write barriers. */ | ||
1981 | case IR_TBAR: asm_tbar(as, ir); break; | ||
1982 | case IR_OBAR: asm_obar(as, ir); break; | ||
1983 | |||
1984 | /* Type conversions. */ | ||
1985 | case IR_CONV: asm_conv(as, ir); break; | ||
1986 | case IR_TOBIT: asm_tobit(as, ir); break; | ||
1987 | case IR_TOSTR: asm_tostr(as, ir); break; | ||
1988 | case IR_STRTO: asm_strto(as, ir); break; | ||
1989 | |||
1990 | /* Calls. */ | ||
1991 | case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break; | ||
1992 | case IR_CALLXS: asm_callx(as, ir); break; | ||
1993 | case IR_CARG: break; | ||
1994 | |||
1995 | default: | ||
1996 | setintV(&as->J->errinfo, ir->o); | ||
1997 | lj_trace_err_info(as->J, LJ_TRERR_NYIIR); | ||
1998 | break; | ||
1999 | } | ||
2000 | } | ||
2001 | |||
2002 | /* -- Trace setup --------------------------------------------------------- */ | 1914 | /* -- Trace setup --------------------------------------------------------- */ |
2003 | 1915 | ||
2004 | /* Ensure there are enough stack slots for call arguments. */ | 1916 | /* Ensure there are enough stack slots for call arguments. */ |