Revision e44259b6

b/include/qemu/host-utils.h
57 57
        return result > UINT64_MAX;
58 58
    }
59 59
}
60

  
61
static inline int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
62
{
63
    if (divisor == 0) {
64
        return 1;
65
    } else {
66
        __int128_t dividend = ((__int128_t)*phigh << 64) | *plow;
67
        __int128_t result = dividend / divisor;
68
        *plow = result;
69
        *phigh = dividend % divisor;
70
        return result != *plow;
71
    }
72
}
60 73
#else
61 74
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
62 75
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
63 76
int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
77
int divs128(int64_t *plow, int64_t *phigh, int64_t divisor);
64 78
#endif
65 79

  
66 80
/**
b/target-ppc/helper.h
32 32
#if defined(TARGET_PPC64)
33 33
DEF_HELPER_3(mulldo, i64, env, i64, i64)
34 34
DEF_HELPER_4(divdeu, i64, env, i64, i64, i32)
35
DEF_HELPER_4(divde, i64, env, i64, i64, i32)
35 36
#endif
36 37

  
37 38
DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl)
b/target-ppc/int_helper.c
65 65
    return rt;
66 66
}
67 67

  
68
uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
69
{
70
    int64_t rt = 0;
71
    int64_t ra = (int64_t)rau;
72
    int64_t rb = (int64_t)rbu;
73
    int overflow = divs128(&rt, &ra, rb);
74

  
75
    if (unlikely(overflow)) {
76
        rt = 0; /* Undefined */
77
    }
78

  
79
    if (oe) {
80

  
81
        if (unlikely(overflow)) {
82
            env->so = env->ov = 1;
83
        } else {
84
            env->ov = 0;
85
        }
86
    }
87

  
88
    return rt;
89
}
90

  
68 91
#endif
69 92

  
70 93

  
b/target-ppc/translate.c
1049 1049

  
1050 1050
GEN_DIVE(divdeu, divdeu, 0);
1051 1051
GEN_DIVE(divdeuo, divdeu, 1);
1052

  
1052
GEN_DIVE(divde, divde, 0);
1053
GEN_DIVE(divdeo, divde, 1);
1053 1054
#endif
1054 1055

  
1055 1056
/* mulhw  mulhw. */
......
9727 9728

  
9728 9729
GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
9729 9730
GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
9731
GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
9732
GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
9730 9733

  
9731 9734
#undef GEN_INT_ARITH_MUL_HELPER
9732 9735
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
b/util/host-utils.c
124 124
        return 0;
125 125
    }
126 126
}
127

  
128
int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
129
{
130
    int sgn_dvdnd = *phigh < 0;
131
    int sgn_divsr = divisor < 0;
132
    int overflow = 0;
133

  
134
    if (sgn_dvdnd) {
135
        *plow = ~(*plow);
136
        *phigh = ~(*phigh);
137
        if (*plow == (int64_t)-1) {
138
            *plow = 0;
139
            (*phigh)++;
140
         } else {
141
            (*plow)++;
142
         }
143
    }
144

  
145
    if (sgn_divsr) {
146
        divisor = 0 - divisor;
147
    }
148

  
149
    overflow = divu128((uint64_t *)plow, (uint64_t *)phigh, (uint64_t)divisor);
150

  
151
    if (sgn_dvdnd  ^ sgn_divsr) {
152
        *plow = 0 - *plow;
153
    }
154

  
155
    if (!overflow) {
156
        if ((*plow < 0) ^ (sgn_dvdnd ^ sgn_divsr)) {
157
            overflow = 1;
158
        }
159
    }
160

  
161
    return overflow;
162
}
163

  
127 164
#endif /* !CONFIG_INT128 */

Also available in: Unified diff