Revision 2d9671d3
b/target-alpha/op_helper.c | ||
---|---|---|
25 | 25 |
|
26 | 26 |
/*****************************************************************************/ |
27 | 27 |
/* Exceptions processing helpers */ |
28 |
void QEMU_NORETURN helper_excp (int excp, int error) |
|
28 |
|
|
29 |
/* This should only be called from translate, via gen_excp. |
|
30 |
We expect that ENV->PC has already been updated. */ |
|
31 |
void QEMU_NORETURN helper_excp(int excp, int error) |
|
32 |
{ |
|
33 |
env->exception_index = excp; |
|
34 |
env->error_code = error; |
|
35 |
cpu_loop_exit(); |
|
36 |
} |
|
37 |
|
|
38 |
static void do_restore_state(void *retaddr) |
|
39 |
{ |
|
40 |
unsigned long pc = (unsigned long)retaddr; |
|
41 |
|
|
42 |
if (pc) { |
|
43 |
TranslationBlock *tb = tb_find_pc(pc); |
|
44 |
if (tb) { |
|
45 |
cpu_restore_state(tb, env, pc); |
|
46 |
} |
|
47 |
} |
|
48 |
} |
|
49 |
|
|
50 |
/* This may be called from any of the helpers to set up EXCEPTION_INDEX. */ |
|
51 |
static void QEMU_NORETURN dynamic_excp(int excp, int error) |
|
29 | 52 |
{ |
30 | 53 |
env->exception_index = excp; |
31 | 54 |
env->error_code = error; |
55 |
do_restore_state(GETPC()); |
|
32 | 56 |
cpu_loop_exit(); |
33 | 57 |
} |
34 | 58 |
|
35 | 59 |
static void QEMU_NORETURN arith_excp(int exc, uint64_t mask) |
36 | 60 |
{ |
37 |
env->exception_index = EXCP_ARITH; |
|
38 |
env->error_code = 0; |
|
39 | 61 |
env->trap_arg0 = exc; |
40 | 62 |
env->trap_arg1 = mask; |
41 |
cpu_loop_exit();
|
|
63 |
dynamic_excp(EXCP_ARITH, 0);
|
|
42 | 64 |
} |
43 | 65 |
|
44 | 66 |
uint64_t helper_load_pcc (void) |
... | ... | |
521 | 543 |
|
522 | 544 |
if (unlikely(!exp && mant_sig)) { |
523 | 545 |
/* Reserved operands / Dirty zero */ |
524 |
helper_excp(EXCP_OPCDEC, 0);
|
|
546 |
dynamic_excp(EXCP_OPCDEC, 0);
|
|
525 | 547 |
} |
526 | 548 |
|
527 | 549 |
if (exp < 3) { |
... | ... | |
651 | 673 |
|
652 | 674 |
if (!exp && mant_sig) { |
653 | 675 |
/* Reserved operands / Dirty zero */ |
654 |
helper_excp(EXCP_OPCDEC, 0);
|
|
676 |
dynamic_excp(EXCP_OPCDEC, 0);
|
|
655 | 677 |
} |
656 | 678 |
|
657 | 679 |
if (exp < 3) { |
... | ... | |
1260 | 1282 |
/* XXX: fix it to restore all registers */ |
1261 | 1283 |
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
1262 | 1284 |
{ |
1263 |
TranslationBlock *tb; |
|
1264 | 1285 |
CPUState *saved_env; |
1265 |
unsigned long pc; |
|
1266 | 1286 |
int ret; |
1267 | 1287 |
|
1268 | 1288 |
/* XXX: hack to restore env in all cases, even if not called from |
... | ... | |
1270 | 1290 |
saved_env = env; |
1271 | 1291 |
env = cpu_single_env; |
1272 | 1292 |
ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); |
1273 |
if (!likely(ret == 0)) { |
|
1274 |
if (likely(retaddr)) { |
|
1275 |
/* now we have a real cpu fault */ |
|
1276 |
pc = (unsigned long)retaddr; |
|
1277 |
tb = tb_find_pc(pc); |
|
1278 |
if (likely(tb)) { |
|
1279 |
/* the PC is inside the translated code. It means that we have |
|
1280 |
a virtual CPU fault */ |
|
1281 |
cpu_restore_state(tb, env, pc); |
|
1282 |
} |
|
1283 |
} |
|
1293 |
if (unlikely(ret != 0)) { |
|
1294 |
do_restore_state(retaddr); |
|
1284 | 1295 |
/* Exception index and error code are already set */ |
1285 | 1296 |
cpu_loop_exit(); |
1286 | 1297 |
} |
Also available in: Unified diff