Revision ee924fa6 tcg/ppc64/tcg-target.c
b/tcg/ppc64/tcg-target.c | ||
---|---|---|
988 | 988 |
tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX); |
989 | 989 |
} |
990 | 990 |
|
991 |
static void ppc_addi32(TCGContext *s, TCGReg rt, TCGReg ra, tcg_target_long si) |
|
992 |
{ |
|
993 |
if (!si && rt == ra) |
|
994 |
return; |
|
995 |
|
|
996 |
if (si == (int16_t) si) |
|
997 |
tcg_out32(s, ADDI | TAI(rt, ra, si)); |
|
998 |
else { |
|
999 |
uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15); |
|
1000 |
tcg_out32(s, ADDIS | TAI(rt, ra, h)); |
|
1001 |
tcg_out32(s, ADDI | TAI(rt, rt, si)); |
|
1002 |
} |
|
1003 |
} |
|
1004 |
|
|
1005 |
static void ppc_addi64(TCGContext *s, TCGReg rt, TCGReg ra, tcg_target_long si) |
|
1006 |
{ |
|
1007 |
/* XXX: suboptimal */ |
|
1008 |
if (si == (int16_t) si |
|
1009 |
|| ((((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0)) |
|
1010 |
ppc_addi32 (s, rt, ra, si); |
|
1011 |
else { |
|
1012 |
tcg_out_movi (s, TCG_TYPE_I64, 0, si); |
|
1013 |
tcg_out32(s, ADD | TAB(rt, ra, 0)); |
|
1014 |
} |
|
1015 |
} |
|
1016 |
|
|
1017 | 991 |
static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2, |
1018 | 992 |
int const_arg2, int cr, int arch64) |
1019 | 993 |
{ |
... | ... | |
1232 | 1206 |
static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, |
1233 | 1207 |
const int *const_args) |
1234 | 1208 |
{ |
1209 |
TCGArg a0, a1, a2; |
|
1235 | 1210 |
int c; |
1236 | 1211 |
|
1237 | 1212 |
switch (opc) { |
... | ... | |
1320 | 1295 |
break; |
1321 | 1296 |
|
1322 | 1297 |
case INDEX_op_add_i32: |
1323 |
if (const_args[2]) |
|
1324 |
ppc_addi32 (s, args[0], args[1], args[2]); |
|
1325 |
else |
|
1326 |
tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); |
|
1298 |
a0 = args[0], a1 = args[1], a2 = args[2]; |
|
1299 |
if (const_args[2]) { |
|
1300 |
int32_t l, h; |
|
1301 |
do_addi_32: |
|
1302 |
l = (int16_t)a2; |
|
1303 |
h = a2 - l; |
|
1304 |
if (h) { |
|
1305 |
tcg_out32(s, ADDIS | TAI(a0, a1, h >> 16)); |
|
1306 |
a1 = a0; |
|
1307 |
} |
|
1308 |
if (l || a0 != a1) { |
|
1309 |
tcg_out32(s, ADDI | TAI(a0, a1, l)); |
|
1310 |
} |
|
1311 |
} else { |
|
1312 |
tcg_out32(s, ADD | TAB(a0, a1, a2)); |
|
1313 |
} |
|
1327 | 1314 |
break; |
1328 | 1315 |
case INDEX_op_sub_i32: |
1329 |
if (const_args[2]) |
|
1330 |
ppc_addi32 (s, args[0], args[1], -args[2]); |
|
1331 |
else |
|
1332 |
tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); |
|
1316 |
a0 = args[0], a1 = args[1], a2 = args[2]; |
|
1317 |
if (const_args[2]) { |
|
1318 |
a2 = -a2; |
|
1319 |
goto do_addi_32; |
|
1320 |
} else { |
|
1321 |
tcg_out32(s, SUBF | TAB(a0, a2, a1)); |
|
1322 |
} |
|
1333 | 1323 |
break; |
1334 | 1324 |
|
1335 | 1325 |
case INDEX_op_and_i64: |
... | ... | |
1459 | 1449 |
break; |
1460 | 1450 |
|
1461 | 1451 |
case INDEX_op_add_i64: |
1462 |
if (const_args[2]) |
|
1463 |
ppc_addi64 (s, args[0], args[1], args[2]); |
|
1464 |
else |
|
1465 |
tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); |
|
1452 |
a0 = args[0], a1 = args[1], a2 = args[2]; |
|
1453 |
if (const_args[2]) { |
|
1454 |
int32_t l0, h1, h2; |
|
1455 |
do_addi_64: |
|
1456 |
/* We can always split any 32-bit signed constant into 3 pieces. |
|
1457 |
Note the positive 0x80000000 coming from the sub_i64 path, |
|
1458 |
handled with the same code we need for eg 0x7fff8000. */ |
|
1459 |
assert(a2 == (int32_t)a2 || a2 == 0x80000000); |
|
1460 |
l0 = (int16_t)a2; |
|
1461 |
h1 = a2 - l0; |
|
1462 |
h2 = 0; |
|
1463 |
if (h1 < 0 && (int64_t)a2 > 0) { |
|
1464 |
h2 = 0x40000000; |
|
1465 |
h1 = a2 - h2 - l0; |
|
1466 |
} |
|
1467 |
assert((TCGArg)h2 + h1 + l0 == a2); |
|
1468 |
|
|
1469 |
if (h2) { |
|
1470 |
tcg_out32(s, ADDIS | TAI(a0, a1, h2 >> 16)); |
|
1471 |
a1 = a0; |
|
1472 |
} |
|
1473 |
if (h1) { |
|
1474 |
tcg_out32(s, ADDIS | TAI(a0, a1, h1 >> 16)); |
|
1475 |
a1 = a0; |
|
1476 |
} |
|
1477 |
if (l0 || a0 != a1) { |
|
1478 |
tcg_out32(s, ADDI | TAI(a0, a1, l0)); |
|
1479 |
} |
|
1480 |
} else { |
|
1481 |
tcg_out32(s, ADD | TAB(a0, a1, a2)); |
|
1482 |
} |
|
1466 | 1483 |
break; |
1467 | 1484 |
case INDEX_op_sub_i64: |
1468 |
if (const_args[2]) |
|
1469 |
ppc_addi64 (s, args[0], args[1], -args[2]); |
|
1470 |
else |
|
1471 |
tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); |
|
1485 |
a0 = args[0], a1 = args[1], a2 = args[2]; |
|
1486 |
if (const_args[2]) { |
|
1487 |
a2 = -a2; |
|
1488 |
goto do_addi_64; |
|
1489 |
} else { |
|
1490 |
tcg_out32(s, SUBF | TAB(a0, a2, a1)); |
|
1491 |
} |
|
1472 | 1492 |
break; |
1473 | 1493 |
|
1474 | 1494 |
case INDEX_op_shl_i64: |
... | ... | |
1634 | 1654 |
{ INDEX_op_neg_i32, { "r", "r" } }, |
1635 | 1655 |
{ INDEX_op_not_i32, { "r", "r" } }, |
1636 | 1656 |
|
1637 |
{ INDEX_op_add_i64, { "r", "r", "ri" } },
|
|
1638 |
{ INDEX_op_sub_i64, { "r", "r", "ri" } },
|
|
1657 |
{ INDEX_op_add_i64, { "r", "r", "rT" } },
|
|
1658 |
{ INDEX_op_sub_i64, { "r", "r", "rT" } },
|
|
1639 | 1659 |
{ INDEX_op_and_i64, { "r", "r", "rU" } }, |
1640 | 1660 |
{ INDEX_op_or_i64, { "r", "r", "rU" } }, |
1641 | 1661 |
{ INDEX_op_xor_i64, { "r", "r", "rU" } }, |
Also available in: Unified diff