1209 |
#ifdef BUGGY_GCC_DIV64 |
#ifdef BUGGY_GCC_DIV64 |
1210 |
/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we |
/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we |
1211 |
call it from another function */ |
call it from another function */ |
1212 |
uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den) |
uint32_t div32(uint64_t *q_ptr, uint64_t num, uint32_t den) |
1213 |
{ |
{ |
1214 |
*q_ptr = num / den; |
*q_ptr = num / den; |
1215 |
return num % den; |
return num % den; |
1216 |
} |
} |
1217 |
|
|
1218 |
int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den) |
int32_t idiv32(int64_t *q_ptr, int64_t num, int32_t den) |
1219 |
{ |
{ |
1220 |
*q_ptr = num / den; |
*q_ptr = num / den; |
1221 |
return num % den; |
return num % den; |
1224 |
|
|
1225 |
void helper_divl_EAX_T0(void) |
void helper_divl_EAX_T0(void) |
1226 |
{ |
{ |
1227 |
unsigned int den, q, r; |
unsigned int den, r; |
1228 |
uint64_t num; |
uint64_t num, q; |
1229 |
|
|
1230 |
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); |
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); |
1231 |
den = T0; |
den = T0; |
1238 |
q = (num / den); |
q = (num / den); |
1239 |
r = (num % den); |
r = (num % den); |
1240 |
#endif |
#endif |
1241 |
|
if (q > 0xffffffff) |
1242 |
|
raise_exception(EXCP00_DIVZ); |
1243 |
EAX = (uint32_t)q; |
EAX = (uint32_t)q; |
1244 |
EDX = (uint32_t)r; |
EDX = (uint32_t)r; |
1245 |
} |
} |
1246 |
|
|
1247 |
void helper_idivl_EAX_T0(void) |
void helper_idivl_EAX_T0(void) |
1248 |
{ |
{ |
1249 |
int den, q, r; |
int den, r; |
1250 |
int64_t num; |
int64_t num, q; |
1251 |
|
|
1252 |
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); |
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); |
1253 |
den = T0; |
den = T0; |
1260 |
q = (num / den); |
q = (num / den); |
1261 |
r = (num % den); |
r = (num % den); |
1262 |
#endif |
#endif |
1263 |
|
if (q != (int32_t)q) |
1264 |
|
raise_exception(EXCP00_DIVZ); |
1265 |
EAX = (uint32_t)q; |
EAX = (uint32_t)q; |
1266 |
EDX = (uint32_t)r; |
EDX = (uint32_t)r; |
1267 |
} |
} |
3258 |
} |
} |
3259 |
} |
} |
3260 |
|
|
3261 |
/* XXX: overflow support */ |
/* return TRUE if overflow */ |
3262 |
static void div64(uint64_t *plow, uint64_t *phigh, uint64_t b) |
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b) |
3263 |
{ |
{ |
3264 |
uint64_t q, r, a1, a0; |
uint64_t q, r, a1, a0; |
3265 |
int i, qb; |
int i, qb; |
3272 |
*plow = q; |
*plow = q; |
3273 |
*phigh = r; |
*phigh = r; |
3274 |
} else { |
} else { |
3275 |
|
if (a1 >= b) |
3276 |
|
return 1; |
3277 |
/* XXX: use a better algorithm */ |
/* XXX: use a better algorithm */ |
3278 |
for(i = 0; i < 64; i++) { |
for(i = 0; i < 64; i++) { |
3279 |
a1 = (a1 << 1) | (a0 >> 63); |
a1 = (a1 << 1) | (a0 >> 63); |
3292 |
*plow = a0; |
*plow = a0; |
3293 |
*phigh = a1; |
*phigh = a1; |
3294 |
} |
} |
3295 |
|
return 0; |
3296 |
} |
} |
3297 |
|
|
3298 |
static void idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) |
/* return TRUE if overflow */ |
3299 |
|
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) |
3300 |
{ |
{ |
3301 |
int sa, sb; |
int sa, sb; |
3302 |
sa = ((int64_t)*phigh < 0); |
sa = ((int64_t)*phigh < 0); |
3305 |
sb = (b < 0); |
sb = (b < 0); |
3306 |
if (sb) |
if (sb) |
3307 |
b = -b; |
b = -b; |
3308 |
div64(plow, phigh, b); |
if (div64(plow, phigh, b) != 0) |
3309 |
if (sa ^ sb) |
return 1; |
3310 |
|
if (sa ^ sb) { |
3311 |
|
if (*plow > (1ULL << 63)) |
3312 |
|
return 1; |
3313 |
*plow = - *plow; |
*plow = - *plow; |
3314 |
|
} else { |
3315 |
|
if (*plow >= (1ULL << 63)) |
3316 |
|
return 1; |
3317 |
|
} |
3318 |
if (sa) |
if (sa) |
3319 |
*phigh = - *phigh; |
*phigh = - *phigh; |
3320 |
|
return 0; |
3321 |
} |
} |
3322 |
|
|
3323 |
void helper_mulq_EAX_T0(void) |
void helper_mulq_EAX_T0(void) |
3360 |
} |
} |
3361 |
r0 = EAX; |
r0 = EAX; |
3362 |
r1 = EDX; |
r1 = EDX; |
3363 |
div64(&r0, &r1, T0); |
if (div64(&r0, &r1, T0)) |
3364 |
|
raise_exception(EXCP00_DIVZ); |
3365 |
EAX = r0; |
EAX = r0; |
3366 |
EDX = r1; |
EDX = r1; |
3367 |
} |
} |
3374 |
} |
} |
3375 |
r0 = EAX; |
r0 = EAX; |
3376 |
r1 = EDX; |
r1 = EDX; |
3377 |
idiv64(&r0, &r1, T0); |
if (idiv64(&r0, &r1, T0)) |
3378 |
|
raise_exception(EXCP00_DIVZ); |
3379 |
EAX = r0; |
EAX = r0; |
3380 |
EDX = r1; |
EDX = r1; |
3381 |
} |
} |