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