Commit 398ce98e4f4286370d97a7e51b01bf6334c3b65e
1 parent
0f459d16
Fix div[u]2.
Previous code assummed 32 by 32 bit divmod operation, and survived x86_64 test only by sheer luck. MIPS wasn't so forgiving. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4705 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
65 additions
and
26 deletions
tcg/ppc/tcg-target.c
@@ -198,6 +198,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) | @@ -198,6 +198,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) | ||
198 | 198 | ||
199 | ct_str = *pct_str; | 199 | ct_str = *pct_str; |
200 | switch (ct_str[0]) { | 200 | switch (ct_str[0]) { |
201 | + case 'A': case 'B': case 'C': case 'D': | ||
202 | + ct->ct |= TCG_CT_REG; | ||
203 | + tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A'); | ||
204 | + break; | ||
201 | case 'r': | 205 | case 'r': |
202 | ct->ct |= TCG_CT_REG; | 206 | ct->ct |= TCG_CT_REG; |
203 | tcg_regset_set32(ct->u.regs, 0, 0xffffffff); | 207 | tcg_regset_set32(ct->u.regs, 0, 0xffffffff); |
@@ -1014,6 +1018,63 @@ static void tcg_out_brcond2(TCGContext *s, | @@ -1014,6 +1018,63 @@ static void tcg_out_brcond2(TCGContext *s, | ||
1014 | tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); | 1018 | tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); |
1015 | } | 1019 | } |
1016 | 1020 | ||
1021 | +static uint64_t __attribute ((used)) ppc_udiv_helper (uint64_t a, uint32_t b) | ||
1022 | +{ | ||
1023 | + uint64_t rem, quo; | ||
1024 | + quo = a / b; | ||
1025 | + rem = a % b; | ||
1026 | + return (rem << 32) | (uint32_t) quo; | ||
1027 | +} | ||
1028 | + | ||
1029 | +static uint64_t __attribute ((used)) ppc_div_helper (int64_t a, int32_t b) | ||
1030 | +{ | ||
1031 | + int64_t rem, quo; | ||
1032 | + quo = a / b; | ||
1033 | + rem = a % b; | ||
1034 | + return (rem << 32) | (uint32_t) quo; | ||
1035 | +} | ||
1036 | + | ||
1037 | +#define MAKE_TRAMPOLINE(name) \ | ||
1038 | +extern void name##_trampoline (void); \ | ||
1039 | +asm (#name "_trampoline:\n" \ | ||
1040 | + " mflr 0\n" \ | ||
1041 | + " addi 1,1,-112\n" \ | ||
1042 | + " mr 4,6\n" \ | ||
1043 | + " stmw 7,0(1)\n" \ | ||
1044 | + " stw 0,108(0)\n" \ | ||
1045 | + " bl ppc_" #name "_helper\n" \ | ||
1046 | + " lmw 7,0(1)\n" \ | ||
1047 | + " lwz 0,108(0)\n" \ | ||
1048 | + " addi 1,1,112\n" \ | ||
1049 | + " mtlr 0\n" \ | ||
1050 | + " blr\n" \ | ||
1051 | + ) | ||
1052 | + | ||
1053 | +MAKE_TRAMPOLINE (div); | ||
1054 | +MAKE_TRAMPOLINE (udiv); | ||
1055 | + | ||
1056 | +static void tcg_out_div2 (TCGContext *s, int uns) | ||
1057 | +{ | ||
1058 | + void *label1_ptr, *label2_ptr; | ||
1059 | + | ||
1060 | + tcg_out32 (s, CMPLI | BF (7) | RA (3)); | ||
1061 | + label1_ptr = s->code_ptr; | ||
1062 | + tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); | ||
1063 | + | ||
1064 | + tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_trampoline : div_trampoline)); | ||
1065 | + | ||
1066 | + label2_ptr = s->code_ptr; | ||
1067 | + tcg_out32 (s, B); | ||
1068 | + | ||
1069 | + reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); | ||
1070 | + | ||
1071 | + tcg_out32 (s, (uns ? DIVWU : DIVW) | TAB (6, 4, 5)); | ||
1072 | + tcg_out32 (s, MULLW | TAB (0, 6, 5)); | ||
1073 | + tcg_out32 (s, SUBF | TAB (3, 0, 4)); | ||
1074 | + | ||
1075 | + reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); | ||
1076 | +} | ||
1077 | + | ||
1017 | static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | 1078 | static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1018 | const int *const_args) | 1079 | const int *const_args) |
1019 | { | 1080 | { |
@@ -1204,32 +1265,10 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -1204,32 +1265,10 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
1204 | } | 1265 | } |
1205 | break; | 1266 | break; |
1206 | case INDEX_op_div2_i32: | 1267 | case INDEX_op_div2_i32: |
1207 | - if (args[0] == args[2] || args[0] == args[3]) { | ||
1208 | - tcg_out32 (s, DIVW | TAB (0, args[2], args[3])); | ||
1209 | - tcg_out32 (s, MTSPR | RS (0) | CTR); | ||
1210 | - tcg_out32 (s, MULLW | TAB (0, 0, args[3])); | ||
1211 | - tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); | ||
1212 | - tcg_out32 (s, MFSPR | RT (args[0]) | CTR); | ||
1213 | - } | ||
1214 | - else { | ||
1215 | - tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3])); | ||
1216 | - tcg_out32 (s, MULLW | TAB (0, args[0], args[3])); | ||
1217 | - tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); | ||
1218 | - } | 1268 | + tcg_out_div2 (s, 0); |
1219 | break; | 1269 | break; |
1220 | case INDEX_op_divu2_i32: | 1270 | case INDEX_op_divu2_i32: |
1221 | - if (args[0] == args[2] || args[0] == args[3]) { | ||
1222 | - tcg_out32 (s, DIVWU | TAB (0, args[2], args[3])); | ||
1223 | - tcg_out32 (s, MTSPR | RS (0) | CTR); | ||
1224 | - tcg_out32 (s, MULLW | TAB (0, 0, args[3])); | ||
1225 | - tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); | ||
1226 | - tcg_out32 (s, MFSPR | RT (args[0]) | CTR); | ||
1227 | - } | ||
1228 | - else { | ||
1229 | - tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3])); | ||
1230 | - tcg_out32 (s, MULLW | TAB (0, args[0], args[3])); | ||
1231 | - tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); | ||
1232 | - } | 1271 | + tcg_out_div2 (s, 1); |
1233 | break; | 1272 | break; |
1234 | 1273 | ||
1235 | case INDEX_op_shl_i32: | 1274 | case INDEX_op_shl_i32: |
@@ -1372,8 +1411,8 @@ static const TCGTargetOpDef ppc_op_defs[] = { | @@ -1372,8 +1411,8 @@ static const TCGTargetOpDef ppc_op_defs[] = { | ||
1372 | { INDEX_op_add_i32, { "r", "r", "ri" } }, | 1411 | { INDEX_op_add_i32, { "r", "r", "ri" } }, |
1373 | { INDEX_op_mul_i32, { "r", "r", "ri" } }, | 1412 | { INDEX_op_mul_i32, { "r", "r", "ri" } }, |
1374 | { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } }, | 1413 | { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } }, |
1375 | - { INDEX_op_div2_i32, { "r", "r", "r", "r", "r" } }, | ||
1376 | - { INDEX_op_divu2_i32, { "r", "r", "r", "r", "r" } }, | 1414 | + { INDEX_op_div2_i32, { "D", "A", "B", "1", "C" } }, |
1415 | + { INDEX_op_divu2_i32, { "D", "A", "B", "1", "C" } }, | ||
1377 | { INDEX_op_sub_i32, { "r", "r", "ri" } }, | 1416 | { INDEX_op_sub_i32, { "r", "r", "ri" } }, |
1378 | { INDEX_op_and_i32, { "r", "r", "ri" } }, | 1417 | { INDEX_op_and_i32, { "r", "r", "ri" } }, |
1379 | { INDEX_op_or_i32, { "r", "r", "ri" } }, | 1418 | { INDEX_op_or_i32, { "r", "r", "ri" } }, |