Revision b5f1aa64
b/target-alpha/op_helper.c | ||
---|---|---|
32 | 32 |
cpu_loop_exit(); |
33 | 33 |
} |
34 | 34 |
|
35 |
static void QEMU_NORETURN arith_excp(int exc, uint64_t mask) |
|
36 |
{ |
|
37 |
env->exception_index = EXCP_ARITH; |
|
38 |
env->error_code = 0; |
|
39 |
env->trap_arg0 = exc; |
|
40 |
env->trap_arg1 = mask; |
|
41 |
cpu_loop_exit(); |
|
42 |
} |
|
43 |
|
|
35 | 44 |
uint64_t helper_load_pcc (void) |
36 | 45 |
{ |
37 | 46 |
/* ??? This isn't a timer for which we have any rate info. */ |
... | ... | |
53 | 62 |
uint64_t tmp = op1; |
54 | 63 |
op1 += op2; |
55 | 64 |
if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) { |
56 |
helper_excp(EXCP_ARITH, EXC_M_IOV);
|
|
65 |
arith_excp(EXC_M_IOV, 0);
|
|
57 | 66 |
} |
58 | 67 |
return op1; |
59 | 68 |
} |
... | ... | |
63 | 72 |
uint64_t tmp = op1; |
64 | 73 |
op1 = (uint32_t)(op1 + op2); |
65 | 74 |
if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) { |
66 |
helper_excp(EXCP_ARITH, EXC_M_IOV);
|
|
75 |
arith_excp(EXC_M_IOV, 0);
|
|
67 | 76 |
} |
68 | 77 |
return op1; |
69 | 78 |
} |
... | ... | |
73 | 82 |
uint64_t res; |
74 | 83 |
res = op1 - op2; |
75 | 84 |
if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) { |
76 |
helper_excp(EXCP_ARITH, EXC_M_IOV);
|
|
85 |
arith_excp(EXC_M_IOV, 0);
|
|
77 | 86 |
} |
78 | 87 |
return res; |
79 | 88 |
} |
... | ... | |
83 | 92 |
uint32_t res; |
84 | 93 |
res = op1 - op2; |
85 | 94 |
if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) { |
86 |
helper_excp(EXCP_ARITH, EXC_M_IOV);
|
|
95 |
arith_excp(EXC_M_IOV, 0);
|
|
87 | 96 |
} |
88 | 97 |
return res; |
89 | 98 |
} |
... | ... | |
93 | 102 |
int64_t res = (int64_t)op1 * (int64_t)op2; |
94 | 103 |
|
95 | 104 |
if (unlikely((int32_t)res != res)) { |
96 |
helper_excp(EXCP_ARITH, EXC_M_IOV);
|
|
105 |
arith_excp(EXC_M_IOV, 0);
|
|
97 | 106 |
} |
98 | 107 |
return (int64_t)((int32_t)res); |
99 | 108 |
} |
... | ... | |
105 | 114 |
muls64(&tl, &th, op1, op2); |
106 | 115 |
/* If th != 0 && th != -1, then we had an overflow */ |
107 | 116 |
if (unlikely((th + 1) > 1)) { |
108 |
helper_excp(EXCP_ARITH, EXC_M_IOV);
|
|
117 |
arith_excp(EXC_M_IOV, 0);
|
|
109 | 118 |
} |
110 | 119 |
return tl; |
111 | 120 |
} |
... | ... | |
373 | 382 |
if (exc) { |
374 | 383 |
uint32_t hw_exc = 0; |
375 | 384 |
|
376 |
env->trap_arg1 = 1ull << regno; |
|
377 |
|
|
378 | 385 |
if (exc & float_flag_invalid) { |
379 | 386 |
hw_exc |= EXC_M_INV; |
380 | 387 |
} |
... | ... | |
390 | 397 |
if (exc & float_flag_inexact) { |
391 | 398 |
hw_exc |= EXC_M_INE; |
392 | 399 |
} |
393 |
helper_excp(EXCP_ARITH, hw_exc); |
|
400 |
|
|
401 |
arith_excp(hw_exc, 1ull << regno); |
|
394 | 402 |
} |
395 | 403 |
} |
396 | 404 |
|
... | ... | |
420 | 428 |
if (env->fpcr_dnz) { |
421 | 429 |
val &= 1ull << 63; |
422 | 430 |
} else { |
423 |
helper_excp(EXCP_ARITH, EXC_M_UNF);
|
|
431 |
arith_excp(EXC_M_UNF, 0);
|
|
424 | 432 |
} |
425 | 433 |
} |
426 | 434 |
} else if (exp == 0x7ff) { |
... | ... | |
428 | 436 |
/* ??? I'm not sure these exception bit flags are correct. I do |
429 | 437 |
know that the Linux kernel, at least, doesn't rely on them and |
430 | 438 |
just emulates the insn to figure out what exception to use. */ |
431 |
helper_excp(EXCP_ARITH, frac ? EXC_M_INV : EXC_M_FOV);
|
|
439 |
arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
|
|
432 | 440 |
} |
433 | 441 |
return val; |
434 | 442 |
} |
... | ... | |
445 | 453 |
if (env->fpcr_dnz) { |
446 | 454 |
val &= 1ull << 63; |
447 | 455 |
} else { |
448 |
helper_excp(EXCP_ARITH, EXC_M_UNF);
|
|
456 |
arith_excp(EXC_M_UNF, 0);
|
|
449 | 457 |
} |
450 | 458 |
} |
451 | 459 |
} else if (exp == 0x7ff && frac) { |
452 | 460 |
/* NaN. */ |
453 |
helper_excp(EXCP_ARITH, EXC_M_INV);
|
|
461 |
arith_excp(EXC_M_INV, 0);
|
|
454 | 462 |
} |
455 | 463 |
return val; |
456 | 464 |
} |
Also available in: Unified diff