Commit 398ce98e4f4286370d97a7e51b01bf6334c3b65e

Authored by malc
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 198  
199 199 ct_str = *pct_str;
200 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 205 case 'r':
202 206 ct->ct |= TCG_CT_REG;
203 207 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
... ... @@ -1014,6 +1018,63 @@ static void tcg_out_brcond2(TCGContext *s,
1014 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 1078 static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1018 1079 const int *const_args)
1019 1080 {
... ... @@ -1204,32 +1265,10 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1204 1265 }
1205 1266 break;
1206 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 1269 break;
1220 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 1272 break;
1234 1273  
1235 1274 case INDEX_op_shl_i32:
... ... @@ -1372,8 +1411,8 @@ static const TCGTargetOpDef ppc_op_defs[] = {
1372 1411 { INDEX_op_add_i32, { "r", "r", "ri" } },
1373 1412 { INDEX_op_mul_i32, { "r", "r", "ri" } },
1374 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 1416 { INDEX_op_sub_i32, { "r", "r", "ri" } },
1378 1417 { INDEX_op_and_i32, { "r", "r", "ri" } },
1379 1418 { INDEX_op_or_i32, { "r", "r", "ri" } },
... ...