Revision 77b73de6

b/tcg/ppc/tcg-target.c
23 23
 */
24 24

  
25 25
static uint8_t *tb_ret_addr;
26
static uint8_t *udiv_addr;
27
static uint8_t *div_addr;
28 26

  
29 27
#define FAST_PATH
30 28
#if TARGET_PHYS_ADDR_BITS <= 32
......
137 135
    TCG_REG_R31
138 136
};
139 137

  
140
static const int div_save_regs[] = {
141
    TCG_REG_R4,
142
    TCG_REG_R5,
143
    TCG_REG_R7,
144
    TCG_REG_R8,
145
    TCG_REG_R9,
146
    TCG_REG_R10,
147
    TCG_REG_R11,
148
    TCG_REG_R12,
149
    TCG_REG_R13,                /* should r13 be saved? */
150
    TCG_REG_R24,
151
    TCG_REG_R25,
152
    TCG_REG_R26,
153
    TCG_REG_R27,
154
};
155

  
156 138
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
157 139
{
158 140
    tcg_target_long disp;
......
817 799
#endif
818 800
}
819 801

  
820
static uint64_t ppc_udiv_helper (uint64_t a, uint32_t b)
821
{
822
    uint64_t rem, quo;
823
    quo = a / b;
824
    rem = a % b;
825
    return (rem << 32) | (uint32_t) quo;
826
}
827

  
828
static uint64_t ppc_div_helper (int64_t a, int32_t b)
829
{
830
    int64_t rem, quo;
831
    quo = a / b;
832
    rem = a % b;
833
    return (rem << 32) | (uint32_t) quo;
834
}
835

  
836 802
void tcg_target_qemu_prologue (TCGContext *s)
837 803
{
838 804
    int i, j, frame_size;
......
871 837
    tcg_out32 (s, MTSPR | RS (0) | LR);
872 838
    tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
873 839
    tcg_out32 (s, BCLR | BO_ALWAYS);
874

  
875
    /* div trampolines */
876
    for (j = 0; j < 2; ++j) {
877
        tcg_target_long target;
878

  
879
        frame_size = 8 + ARRAY_SIZE (div_save_regs) * 4;
880
        frame_size = (frame_size + 15) & ~15;
881

  
882
        if (j == 0) {
883
            target = (tcg_target_long) ppc_udiv_helper;
884
            udiv_addr = s->code_ptr;
885
        }
886
        else {
887
            target = (tcg_target_long) ppc_div_helper;
888
            div_addr = s->code_ptr;
889
        }
890

  
891
        tcg_out32 (s, MFSPR | RT (0) | LR);
892
        tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
893
        for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i)
894
            tcg_out32 (s, (STW
895
                           | RS (div_save_regs[i])
896
                           | RA (1)
897
                           | (i * 4 + 8)
898
                           )
899
                );
900
        tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size - 4));
901
        tcg_out_mov (s, 4, 6);
902
        tcg_out_b (s, LK, target);
903
        tcg_out_mov (s, 6, 4);
904

  
905
        for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i)
906
            tcg_out32 (s, (LWZ
907
                           | RT (div_save_regs[i])
908
                           | RA (1)
909
                           | (i * 4 + 8)
910
                           )
911
                );
912
        tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size - 4));
913
        tcg_out32 (s, MTSPR | RS (0) | LR);
914
        tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
915
        tcg_out32 (s, BCLR | BO_ALWAYS);
916
    }
917 840
}
918 841

  
919 842
static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
......
1095 1018
    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
1096 1019
}
1097 1020

  
1098
static void tcg_out_div2 (TCGContext *s, int uns)
1099
{
1100
    void *label1_ptr, *label2_ptr;
1101

  
1102
    if (uns)
1103
        tcg_out32 (s, CMPLI | BF (7) | RA (3));
1104
    else {
1105
        tcg_out32 (s, SRAWI | RS (4) | RA (0) | 31);
1106
        tcg_out32 (s, CMPL | BF (7) | RA (3) | RB (4));
1107
    }
1108

  
1109
    label1_ptr = s->code_ptr;
1110
    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
1111

  
1112
    tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_addr : div_addr));
1113

  
1114
    label2_ptr = s->code_ptr;
1115
    tcg_out32 (s, B);
1116

  
1117
    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
1118

  
1119
    tcg_out32 (s, (uns ? DIVWU : DIVW) | TAB (6, 4, 5));
1120
    tcg_out32 (s, MULLW | TAB (0, 6, 5));
1121
    tcg_out32 (s, SUBF | TAB (3, 0, 4));
1122

  
1123
    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
1124
}
1125

  
1126 1021
static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1127 1022
                       const int *const_args)
1128 1023
{
......
1301 1196
        else
1302 1197
            tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1303 1198
        break;
1199

  
1200
    case INDEX_op_div_i32:
1201
        tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1202
        break;
1203

  
1204
    case INDEX_op_divu_i32:
1205
        tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1206
        break;
1207

  
1208
    case INDEX_op_rem_i32:
1209
        tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1210
        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1211
        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1212
        break;
1213

  
1214
    case INDEX_op_remu_i32:
1215
        tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1216
        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1217
        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1218
        break;
1219

  
1304 1220
    case INDEX_op_mulu2_i32:
1305 1221
        if (args[0] == args[2] || args[0] == args[3]) {
1306 1222
            tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
......
1312 1228
            tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1313 1229
        }
1314 1230
        break;
1315
    case INDEX_op_div2_i32:
1316
        tcg_out_div2 (s, 0);
1317
        break;
1318
    case INDEX_op_divu2_i32:
1319
        tcg_out_div2 (s, 1);
1320
        break;
1321 1231

  
1322 1232
    case INDEX_op_shl_i32:
1323 1233
        if (const_args[2]) {
......
1458 1368

  
1459 1369
    { INDEX_op_add_i32, { "r", "r", "ri" } },
1460 1370
    { INDEX_op_mul_i32, { "r", "r", "ri" } },
1371
    { INDEX_op_div_i32, { "r", "r", "r" } },
1372
    { INDEX_op_divu_i32, { "r", "r", "r" } },
1373
    { INDEX_op_rem_i32, { "r", "r", "r" } },
1374
    { INDEX_op_remu_i32, { "r", "r", "r" } },
1461 1375
    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1462
    { INDEX_op_div2_i32, { "D", "A", "B", "1", "C" } },
1463
    { INDEX_op_divu2_i32, { "D", "A", "B", "1", "C" } },
1464 1376
    { INDEX_op_sub_i32, { "r", "r", "ri" } },
1465 1377
    { INDEX_op_and_i32, { "r", "r", "ri" } },
1466 1378
    { INDEX_op_or_i32, { "r", "r", "ri" } },
b/tcg/ppc/tcg-target.h
70 70

  
71 71
/* optional instructions */
72 72
#define TCG_TARGET_HAS_neg_i32
73
#define TCG_TARGET_HAS_div_i32
73 74

  
74 75
#define TCG_AREG0 TCG_REG_R27
75 76
#define TCG_AREG1 TCG_REG_R24

Also available in: Unified diff