Revision 398ce98e

b/tcg/ppc/tcg-target.c
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 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 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 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" } },

Also available in: Unified diff