]> git.proxmox.com Git - qemu.git/blame - cpu-exec.c
CRIS: Support RFN insn.
[qemu.git] / cpu-exec.c
CommitLineData
7d13299d
FB
1/*
2 * i386 emulator main execution loop
5fafdf24 3 *
66321a11 4 * Copyright (c) 2003-2005 Fabrice Bellard
7d13299d 5 *
3ef693a0
FB
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
7d13299d 10 *
3ef693a0
FB
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
7d13299d 15 *
3ef693a0
FB
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7d13299d 19 */
e4533c7a 20#include "config.h"
7cb69cae 21#define CPU_NO_GLOBAL_REGS
93ac68bc 22#include "exec.h"
956034d7 23#include "disas.h"
7cb69cae 24#include "tcg.h"
7d13299d 25
fbf9eeb3
FB
26#if !defined(CONFIG_SOFTMMU)
27#undef EAX
28#undef ECX
29#undef EDX
30#undef EBX
31#undef ESP
32#undef EBP
33#undef ESI
34#undef EDI
35#undef EIP
36#include <signal.h>
37#include <sys/ucontext.h>
38#endif
39
572a9d4a
BS
40#if defined(__sparc__) && !defined(HOST_SOLARIS)
41// Work around ugly bugs in glibc that mangle global register contents
42#undef env
43#define env cpu_single_env
44#endif
45
36bdbe54
FB
46int tb_invalidated_flag;
47
dc99065b 48//#define DEBUG_EXEC
9de5e440 49//#define DEBUG_SIGNAL
7d13299d 50
e4533c7a
FB
51void cpu_loop_exit(void)
52{
bfed01fc
TS
53 /* NOTE: the register at this point must be saved by hand because
54 longjmp restore them */
55 regs_to_env();
e4533c7a
FB
56 longjmp(env->jmp_env, 1);
57}
bfed01fc 58
e6e5906b 59#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
3475187d
FB
60#define reg_T2
61#endif
e4533c7a 62
fbf9eeb3
FB
63/* exit the current TB from a signal handler. The host registers are
64 restored in a state compatible with the CPU emulator
65 */
5fafdf24 66void cpu_resume_from_signal(CPUState *env1, void *puc)
fbf9eeb3
FB
67{
68#if !defined(CONFIG_SOFTMMU)
69 struct ucontext *uc = puc;
70#endif
71
72 env = env1;
73
74 /* XXX: restore cpu registers saved in host registers */
75
76#if !defined(CONFIG_SOFTMMU)
77 if (puc) {
78 /* XXX: use siglongjmp ? */
79 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
80 }
81#endif
82 longjmp(env->jmp_env, 1);
83}
84
8a40a180
FB
85static TranslationBlock *tb_find_slow(target_ulong pc,
86 target_ulong cs_base,
c068688b 87 uint64_t flags)
8a40a180
FB
88{
89 TranslationBlock *tb, **ptb1;
90 int code_gen_size;
91 unsigned int h;
92 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
93 uint8_t *tc_ptr;
3b46e624 94
8a40a180 95 tb_invalidated_flag = 0;
3b46e624 96
8a40a180 97 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
3b46e624 98
8a40a180
FB
99 /* find translated block using physical mappings */
100 phys_pc = get_phys_addr_code(env, pc);
101 phys_page1 = phys_pc & TARGET_PAGE_MASK;
102 phys_page2 = -1;
103 h = tb_phys_hash_func(phys_pc);
104 ptb1 = &tb_phys_hash[h];
105 for(;;) {
106 tb = *ptb1;
107 if (!tb)
108 goto not_found;
5fafdf24 109 if (tb->pc == pc &&
8a40a180 110 tb->page_addr[0] == phys_page1 &&
5fafdf24 111 tb->cs_base == cs_base &&
8a40a180
FB
112 tb->flags == flags) {
113 /* check next page if needed */
114 if (tb->page_addr[1] != -1) {
5fafdf24 115 virt_page2 = (pc & TARGET_PAGE_MASK) +
8a40a180
FB
116 TARGET_PAGE_SIZE;
117 phys_page2 = get_phys_addr_code(env, virt_page2);
118 if (tb->page_addr[1] == phys_page2)
119 goto found;
120 } else {
121 goto found;
122 }
123 }
124 ptb1 = &tb->phys_hash_next;
125 }
126 not_found:
127 /* if no translated code available, then translate it now */
128 tb = tb_alloc(pc);
129 if (!tb) {
130 /* flush must be done */
131 tb_flush(env);
132 /* cannot fail at this point */
133 tb = tb_alloc(pc);
134 /* don't forget to invalidate previous TB info */
15388002 135 tb_invalidated_flag = 1;
8a40a180
FB
136 }
137 tc_ptr = code_gen_ptr;
138 tb->tc_ptr = tc_ptr;
139 tb->cs_base = cs_base;
140 tb->flags = flags;
d07bde88 141 cpu_gen_code(env, tb, &code_gen_size);
8a40a180 142 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
3b46e624 143
8a40a180
FB
144 /* check next page if needed */
145 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
146 phys_page2 = -1;
147 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
148 phys_page2 = get_phys_addr_code(env, virt_page2);
149 }
150 tb_link_phys(tb, phys_pc, phys_page2);
3b46e624 151
8a40a180 152 found:
8a40a180
FB
153 /* we add the TB in the virtual pc hash table */
154 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
8a40a180
FB
155 return tb;
156}
157
158static inline TranslationBlock *tb_find_fast(void)
159{
160 TranslationBlock *tb;
161 target_ulong cs_base, pc;
c068688b 162 uint64_t flags;
8a40a180
FB
163
164 /* we record a subset of the CPU state. It will
165 always be the same before a given translated block
166 is executed. */
167#if defined(TARGET_I386)
168 flags = env->hflags;
169 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
170 cs_base = env->segs[R_CS].base;
171 pc = cs_base + env->eip;
172#elif defined(TARGET_ARM)
173 flags = env->thumb | (env->vfp.vec_len << 1)
b5ff1b31
FB
174 | (env->vfp.vec_stride << 4);
175 if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
176 flags |= (1 << 6);
40f137e1
PB
177 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
178 flags |= (1 << 7);
9ee6e8bb 179 flags |= (env->condexec_bits << 8);
8a40a180
FB
180 cs_base = 0;
181 pc = env->regs[15];
182#elif defined(TARGET_SPARC)
183#ifdef TARGET_SPARC64
a80dde08
FB
184 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
185 flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
186 | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
8a40a180 187#else
6d5f237a
BS
188 // FPU enable . Supervisor
189 flags = (env->psref << 4) | env->psrs;
8a40a180
FB
190#endif
191 cs_base = env->npc;
192 pc = env->pc;
193#elif defined(TARGET_PPC)
1527c87e 194 flags = env->hflags;
8a40a180
FB
195 cs_base = 0;
196 pc = env->nip;
197#elif defined(TARGET_MIPS)
56b19403 198 flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
cc9442b9 199 cs_base = 0;
ead9360e 200 pc = env->PC[env->current_tc];
e6e5906b 201#elif defined(TARGET_M68K)
acf930aa
PB
202 flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */
203 | (env->sr & SR_S) /* Bit 13 */
204 | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
e6e5906b
PB
205 cs_base = 0;
206 pc = env->pc;
fdf9b3e8 207#elif defined(TARGET_SH4)
823029f9
TS
208 flags = env->flags;
209 cs_base = 0;
fdf9b3e8 210 pc = env->pc;
eddf68a6
JM
211#elif defined(TARGET_ALPHA)
212 flags = env->ps;
213 cs_base = 0;
214 pc = env->pc;
f1ccf904 215#elif defined(TARGET_CRIS)
7e15e603 216 flags = env->pregs[PR_CCS] & (P_FLAG | U_FLAG | X_FLAG);
cf1d97f0 217 flags |= env->dslot;
f1ccf904
TS
218 cs_base = 0;
219 pc = env->pc;
8a40a180
FB
220#else
221#error unsupported CPU
222#endif
bce61846 223 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
8a40a180
FB
224 if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
225 tb->flags != flags, 0)) {
226 tb = tb_find_slow(pc, cs_base, flags);
227 }
228 return tb;
229}
230
7d13299d
FB
231/* main execution loop */
232
e4533c7a 233int cpu_exec(CPUState *env1)
7d13299d 234{
1057eaa7
PB
235#define DECLARE_HOST_REGS 1
236#include "hostregs_helper.h"
8a40a180 237 int ret, interrupt_request;
8a40a180 238 TranslationBlock *tb;
c27004ec 239 uint8_t *tc_ptr;
d5975363 240 unsigned long next_tb;
8c6939c0 241
bfed01fc
TS
242 if (cpu_halted(env1) == EXCP_HALTED)
243 return EXCP_HALTED;
5a1e3cfc 244
5fafdf24 245 cpu_single_env = env1;
6a00d601 246
7d13299d 247 /* first we save global registers */
1057eaa7
PB
248#define SAVE_HOST_REGS 1
249#include "hostregs_helper.h"
c27004ec 250 env = env1;
e4533c7a 251
0d1a29f9 252 env_to_regs();
ecb644f4 253#if defined(TARGET_I386)
9de5e440 254 /* put eflags in CPU temporary format */
fc2b4c48
FB
255 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
256 DF = 1 - (2 * ((env->eflags >> 10) & 1));
9de5e440 257 CC_OP = CC_OP_EFLAGS;
fc2b4c48 258 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
93ac68bc 259#elif defined(TARGET_SPARC)
e6e5906b
PB
260#elif defined(TARGET_M68K)
261 env->cc_op = CC_OP_FLAGS;
262 env->cc_dest = env->sr & 0xf;
263 env->cc_x = (env->sr >> 4) & 1;
ecb644f4
TS
264#elif defined(TARGET_ALPHA)
265#elif defined(TARGET_ARM)
266#elif defined(TARGET_PPC)
6af0bf9c 267#elif defined(TARGET_MIPS)
fdf9b3e8 268#elif defined(TARGET_SH4)
f1ccf904 269#elif defined(TARGET_CRIS)
fdf9b3e8 270 /* XXXXX */
e4533c7a
FB
271#else
272#error unsupported target CPU
273#endif
3fb2ded1 274 env->exception_index = -1;
9d27abd9 275
7d13299d 276 /* prepare setjmp context for exception handling */
3fb2ded1
FB
277 for(;;) {
278 if (setjmp(env->jmp_env) == 0) {
ee8b7021 279 env->current_tb = NULL;
3fb2ded1
FB
280 /* if an exception is pending, we execute it here */
281 if (env->exception_index >= 0) {
282 if (env->exception_index >= EXCP_INTERRUPT) {
283 /* exit request from the cpu execution loop */
284 ret = env->exception_index;
285 break;
286 } else if (env->user_mode_only) {
287 /* if user mode only, we simulate a fake exception
9f083493 288 which will be handled outside the cpu execution
3fb2ded1 289 loop */
83479e77 290#if defined(TARGET_I386)
5fafdf24
TS
291 do_interrupt_user(env->exception_index,
292 env->exception_is_int,
293 env->error_code,
3fb2ded1 294 env->exception_next_eip);
eba01623
FB
295 /* successfully delivered */
296 env->old_exception = -1;
83479e77 297#endif
3fb2ded1
FB
298 ret = env->exception_index;
299 break;
300 } else {
83479e77 301#if defined(TARGET_I386)
3fb2ded1
FB
302 /* simulate a real cpu exception. On i386, it can
303 trigger new exceptions, but we do not handle
304 double or triple faults yet. */
5fafdf24
TS
305 do_interrupt(env->exception_index,
306 env->exception_is_int,
307 env->error_code,
d05e66d2 308 env->exception_next_eip, 0);
678dde13
TS
309 /* successfully delivered */
310 env->old_exception = -1;
ce09776b
FB
311#elif defined(TARGET_PPC)
312 do_interrupt(env);
6af0bf9c
FB
313#elif defined(TARGET_MIPS)
314 do_interrupt(env);
e95c8d51 315#elif defined(TARGET_SPARC)
f2bc7e7f 316 do_interrupt(env);
b5ff1b31
FB
317#elif defined(TARGET_ARM)
318 do_interrupt(env);
fdf9b3e8
FB
319#elif defined(TARGET_SH4)
320 do_interrupt(env);
eddf68a6
JM
321#elif defined(TARGET_ALPHA)
322 do_interrupt(env);
f1ccf904
TS
323#elif defined(TARGET_CRIS)
324 do_interrupt(env);
0633879f
PB
325#elif defined(TARGET_M68K)
326 do_interrupt(0);
83479e77 327#endif
3fb2ded1
FB
328 }
329 env->exception_index = -1;
5fafdf24 330 }
9df217a3
FB
331#ifdef USE_KQEMU
332 if (kqemu_is_ok(env) && env->interrupt_request == 0) {
333 int ret;
334 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
335 ret = kqemu_cpu_exec(env);
336 /* put eflags in CPU temporary format */
337 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
338 DF = 1 - (2 * ((env->eflags >> 10) & 1));
339 CC_OP = CC_OP_EFLAGS;
340 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
341 if (ret == 1) {
342 /* exception */
343 longjmp(env->jmp_env, 1);
344 } else if (ret == 2) {
345 /* softmmu execution needed */
346 } else {
347 if (env->interrupt_request != 0) {
348 /* hardware interrupt will be executed just after */
349 } else {
350 /* otherwise, we restart */
351 longjmp(env->jmp_env, 1);
352 }
353 }
3fb2ded1 354 }
9df217a3
FB
355#endif
356
b5fc09ae 357 next_tb = 0; /* force lookup of first TB */
3fb2ded1 358 for(;;) {
68a79315 359 interrupt_request = env->interrupt_request;
db620f46
FB
360 if (__builtin_expect(interrupt_request, 0) &&
361 likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
6658ffb8
PB
362 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
363 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
364 env->exception_index = EXCP_DEBUG;
365 cpu_loop_exit();
366 }
a90b7318 367#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
f1ccf904 368 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
a90b7318
AZ
369 if (interrupt_request & CPU_INTERRUPT_HALT) {
370 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
371 env->halted = 1;
372 env->exception_index = EXCP_HLT;
373 cpu_loop_exit();
374 }
375#endif
68a79315 376#if defined(TARGET_I386)
db620f46
FB
377 if (env->hflags2 & HF2_GIF_MASK) {
378 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
379 !(env->hflags & HF_SMM_MASK)) {
380 svm_check_intercept(SVM_EXIT_SMI);
381 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
382 do_smm_enter();
383 next_tb = 0;
384 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
385 !(env->hflags2 & HF2_NMI_MASK)) {
386 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
387 env->hflags2 |= HF2_NMI_MASK;
388 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
389 next_tb = 0;
390 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
391 (((env->hflags2 & HF2_VINTR_MASK) &&
392 (env->hflags2 & HF2_HIF_MASK)) ||
393 (!(env->hflags2 & HF2_VINTR_MASK) &&
394 (env->eflags & IF_MASK &&
395 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
396 int intno;
397 svm_check_intercept(SVM_EXIT_INTR);
398 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
399 intno = cpu_get_pic_interrupt(env);
400 if (loglevel & CPU_LOG_TB_IN_ASM) {
401 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
402 }
403 do_interrupt(intno, 0, 0, 0, 1);
404 /* ensure that no TB jump will be modified as
405 the program flow was changed */
406 next_tb = 0;
0573fbfc 407#if !defined(CONFIG_USER_ONLY)
db620f46
FB
408 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
409 (env->eflags & IF_MASK) &&
410 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
411 int intno;
412 /* FIXME: this should respect TPR */
413 svm_check_intercept(SVM_EXIT_VINTR);
414 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
415 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
416 if (loglevel & CPU_LOG_TB_IN_ASM)
417 fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
418 do_interrupt(intno, 0, 0, 0, 1);
419 next_tb = 0;
907a5b26 420#endif
db620f46 421 }
68a79315 422 }
ce09776b 423#elif defined(TARGET_PPC)
9fddaa0c
FB
424#if 0
425 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
426 cpu_ppc_reset(env);
427 }
428#endif
47103572 429 if (interrupt_request & CPU_INTERRUPT_HARD) {
e9df014c
JM
430 ppc_hw_interrupt(env);
431 if (env->pending_interrupts == 0)
432 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
b5fc09ae 433 next_tb = 0;
ce09776b 434 }
6af0bf9c
FB
435#elif defined(TARGET_MIPS)
436 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
24c7b0e3 437 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
6af0bf9c 438 (env->CP0_Status & (1 << CP0St_IE)) &&
24c7b0e3
TS
439 !(env->CP0_Status & (1 << CP0St_EXL)) &&
440 !(env->CP0_Status & (1 << CP0St_ERL)) &&
6af0bf9c
FB
441 !(env->hflags & MIPS_HFLAG_DM)) {
442 /* Raise it */
443 env->exception_index = EXCP_EXT_INTERRUPT;
444 env->error_code = 0;
445 do_interrupt(env);
b5fc09ae 446 next_tb = 0;
6af0bf9c 447 }
e95c8d51 448#elif defined(TARGET_SPARC)
66321a11
FB
449 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
450 (env->psret != 0)) {
451 int pil = env->interrupt_index & 15;
452 int type = env->interrupt_index & 0xf0;
453
454 if (((type == TT_EXTINT) &&
455 (pil == 15 || pil > env->psrpil)) ||
456 type != TT_EXTINT) {
457 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
f2bc7e7f
BS
458 env->exception_index = env->interrupt_index;
459 do_interrupt(env);
66321a11 460 env->interrupt_index = 0;
327ac2e7
BS
461#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
462 cpu_check_irqs(env);
463#endif
b5fc09ae 464 next_tb = 0;
66321a11 465 }
e95c8d51
FB
466 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
467 //do_interrupt(0, 0, 0, 0, 0);
468 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
a90b7318 469 }
b5ff1b31
FB
470#elif defined(TARGET_ARM)
471 if (interrupt_request & CPU_INTERRUPT_FIQ
472 && !(env->uncached_cpsr & CPSR_F)) {
473 env->exception_index = EXCP_FIQ;
474 do_interrupt(env);
b5fc09ae 475 next_tb = 0;
b5ff1b31 476 }
9ee6e8bb
PB
477 /* ARMv7-M interrupt return works by loading a magic value
478 into the PC. On real hardware the load causes the
479 return to occur. The qemu implementation performs the
480 jump normally, then does the exception return when the
481 CPU tries to execute code at the magic address.
482 This will cause the magic PC value to be pushed to
483 the stack if an interrupt occured at the wrong time.
484 We avoid this by disabling interrupts when
485 pc contains a magic address. */
b5ff1b31 486 if (interrupt_request & CPU_INTERRUPT_HARD
9ee6e8bb
PB
487 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
488 || !(env->uncached_cpsr & CPSR_I))) {
b5ff1b31
FB
489 env->exception_index = EXCP_IRQ;
490 do_interrupt(env);
b5fc09ae 491 next_tb = 0;
b5ff1b31 492 }
fdf9b3e8 493#elif defined(TARGET_SH4)
e96e2044
TS
494 if (interrupt_request & CPU_INTERRUPT_HARD) {
495 do_interrupt(env);
b5fc09ae 496 next_tb = 0;
e96e2044 497 }
eddf68a6
JM
498#elif defined(TARGET_ALPHA)
499 if (interrupt_request & CPU_INTERRUPT_HARD) {
500 do_interrupt(env);
b5fc09ae 501 next_tb = 0;
eddf68a6 502 }
f1ccf904
TS
503#elif defined(TARGET_CRIS)
504 if (interrupt_request & CPU_INTERRUPT_HARD) {
505 do_interrupt(env);
b5fc09ae 506 next_tb = 0;
f1ccf904 507 }
0633879f
PB
508#elif defined(TARGET_M68K)
509 if (interrupt_request & CPU_INTERRUPT_HARD
510 && ((env->sr & SR_I) >> SR_I_SHIFT)
511 < env->pending_level) {
512 /* Real hardware gets the interrupt vector via an
513 IACK cycle at this point. Current emulated
514 hardware doesn't rely on this, so we
515 provide/save the vector when the interrupt is
516 first signalled. */
517 env->exception_index = env->pending_vector;
518 do_interrupt(1);
b5fc09ae 519 next_tb = 0;
0633879f 520 }
68a79315 521#endif
9d05095e
FB
522 /* Don't use the cached interupt_request value,
523 do_interrupt may have updated the EXITTB flag. */
b5ff1b31 524 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bf3e8bf1
FB
525 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
526 /* ensure that no TB jump will be modified as
527 the program flow was changed */
b5fc09ae 528 next_tb = 0;
bf3e8bf1 529 }
68a79315
FB
530 if (interrupt_request & CPU_INTERRUPT_EXIT) {
531 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
532 env->exception_index = EXCP_INTERRUPT;
533 cpu_loop_exit();
534 }
3fb2ded1 535 }
7d13299d 536#ifdef DEBUG_EXEC
b5ff1b31 537 if ((loglevel & CPU_LOG_TB_CPU)) {
3fb2ded1 538 /* restore flags in standard format */
ecb644f4
TS
539 regs_to_env();
540#if defined(TARGET_I386)
3fb2ded1 541 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
7fe48483 542 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
3fb2ded1 543 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
e4533c7a 544#elif defined(TARGET_ARM)
7fe48483 545 cpu_dump_state(env, logfile, fprintf, 0);
93ac68bc 546#elif defined(TARGET_SPARC)
3475187d 547 cpu_dump_state(env, logfile, fprintf, 0);
67867308 548#elif defined(TARGET_PPC)
7fe48483 549 cpu_dump_state(env, logfile, fprintf, 0);
e6e5906b
PB
550#elif defined(TARGET_M68K)
551 cpu_m68k_flush_flags(env, env->cc_op);
552 env->cc_op = CC_OP_FLAGS;
553 env->sr = (env->sr & 0xffe0)
554 | env->cc_dest | (env->cc_x << 4);
555 cpu_dump_state(env, logfile, fprintf, 0);
6af0bf9c
FB
556#elif defined(TARGET_MIPS)
557 cpu_dump_state(env, logfile, fprintf, 0);
fdf9b3e8
FB
558#elif defined(TARGET_SH4)
559 cpu_dump_state(env, logfile, fprintf, 0);
eddf68a6
JM
560#elif defined(TARGET_ALPHA)
561 cpu_dump_state(env, logfile, fprintf, 0);
f1ccf904
TS
562#elif defined(TARGET_CRIS)
563 cpu_dump_state(env, logfile, fprintf, 0);
e4533c7a 564#else
5fafdf24 565#error unsupported target CPU
e4533c7a 566#endif
3fb2ded1 567 }
7d13299d 568#endif
d5975363 569 spin_lock(&tb_lock);
8a40a180 570 tb = tb_find_fast();
d5975363
PB
571 /* Note: we do it here to avoid a gcc bug on Mac OS X when
572 doing it in tb_find_slow */
573 if (tb_invalidated_flag) {
574 /* as some TB could have been invalidated because
575 of memory exceptions while generating the code, we
576 must recompute the hash index here */
577 next_tb = 0;
578 }
9d27abd9 579#ifdef DEBUG_EXEC
c1135f61 580 if ((loglevel & CPU_LOG_EXEC)) {
c27004ec
FB
581 fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
582 (long)tb->tc_ptr, tb->pc,
583 lookup_symbol(tb->pc));
3fb2ded1 584 }
9d27abd9 585#endif
8a40a180
FB
586 /* see if we can patch the calling TB. When the TB
587 spans two pages, we cannot safely do a direct
588 jump. */
c27004ec 589 {
b5fc09ae 590 if (next_tb != 0 &&
4d7a0880 591#ifdef USE_KQEMU
f32fc648
FB
592 (env->kqemu_enabled != 2) &&
593#endif
ec6338ba 594 tb->page_addr[1] == -1) {
b5fc09ae 595 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
3fb2ded1 596 }
c27004ec 597 }
d5975363 598 spin_unlock(&tb_lock);
3fb2ded1 599 tc_ptr = tb->tc_ptr;
83479e77 600 env->current_tb = tb;
3fb2ded1 601 /* execute the generated code */
572a9d4a
BS
602#if defined(__sparc__) && !defined(HOST_SOLARIS)
603#undef env
604 env = cpu_single_env;
605#define env cpu_single_env
606#endif
7cb69cae 607 next_tb = tcg_qemu_tb_exec(tc_ptr);
83479e77 608 env->current_tb = NULL;
4cbf74b6
FB
609 /* reset soft MMU for next block (it can currently
610 only be set by a memory fault) */
f32fc648
FB
611#if defined(USE_KQEMU)
612#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
613 if (kqemu_is_ok(env) &&
614 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
615 cpu_loop_exit();
616 }
4cbf74b6 617#endif
50a518e3 618 } /* for(;;) */
3fb2ded1 619 } else {
0d1a29f9 620 env_to_regs();
7d13299d 621 }
3fb2ded1
FB
622 } /* for(;;) */
623
7d13299d 624
e4533c7a 625#if defined(TARGET_I386)
9de5e440 626 /* restore flags in standard format */
fc2b4c48 627 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
e4533c7a 628#elif defined(TARGET_ARM)
b7bcbe95 629 /* XXX: Save/restore host fpu exception state?. */
93ac68bc 630#elif defined(TARGET_SPARC)
67867308 631#elif defined(TARGET_PPC)
e6e5906b
PB
632#elif defined(TARGET_M68K)
633 cpu_m68k_flush_flags(env, env->cc_op);
634 env->cc_op = CC_OP_FLAGS;
635 env->sr = (env->sr & 0xffe0)
636 | env->cc_dest | (env->cc_x << 4);
6af0bf9c 637#elif defined(TARGET_MIPS)
fdf9b3e8 638#elif defined(TARGET_SH4)
eddf68a6 639#elif defined(TARGET_ALPHA)
f1ccf904 640#elif defined(TARGET_CRIS)
fdf9b3e8 641 /* XXXXX */
e4533c7a
FB
642#else
643#error unsupported target CPU
644#endif
1057eaa7
PB
645
646 /* restore global registers */
1057eaa7
PB
647#include "hostregs_helper.h"
648
6a00d601 649 /* fail safe : never use cpu_single_env outside cpu_exec() */
5fafdf24 650 cpu_single_env = NULL;
7d13299d
FB
651 return ret;
652}
6dbad63e 653
fbf9eeb3
FB
654/* must only be called from the generated code as an exception can be
655 generated */
656void tb_invalidate_page_range(target_ulong start, target_ulong end)
657{
dc5d0b3d
FB
658 /* XXX: cannot enable it yet because it yields to MMU exception
659 where NIP != read address on PowerPC */
660#if 0
fbf9eeb3
FB
661 target_ulong phys_addr;
662 phys_addr = get_phys_addr_code(env, start);
663 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
dc5d0b3d 664#endif
fbf9eeb3
FB
665}
666
1a18c71b 667#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
e4533c7a 668
6dbad63e
FB
669void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
670{
671 CPUX86State *saved_env;
672
673 saved_env = env;
674 env = s;
a412ac57 675 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
a513fe19 676 selector &= 0xffff;
5fafdf24 677 cpu_x86_load_seg_cache(env, seg_reg, selector,
c27004ec 678 (selector << 4), 0xffff, 0);
a513fe19 679 } else {
5d97559d 680 helper_load_seg(seg_reg, selector);
a513fe19 681 }
6dbad63e
FB
682 env = saved_env;
683}
9de5e440 684
6f12a2a6 685void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
d0a1ffc9
FB
686{
687 CPUX86State *saved_env;
688
689 saved_env = env;
690 env = s;
3b46e624 691
6f12a2a6 692 helper_fsave(ptr, data32);
d0a1ffc9
FB
693
694 env = saved_env;
695}
696
6f12a2a6 697void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
d0a1ffc9
FB
698{
699 CPUX86State *saved_env;
700
701 saved_env = env;
702 env = s;
3b46e624 703
6f12a2a6 704 helper_frstor(ptr, data32);
d0a1ffc9
FB
705
706 env = saved_env;
707}
708
e4533c7a
FB
709#endif /* TARGET_I386 */
710
67b915a5
FB
711#if !defined(CONFIG_SOFTMMU)
712
3fb2ded1
FB
713#if defined(TARGET_I386)
714
b56dad1c 715/* 'pc' is the host PC at which the exception was raised. 'address' is
fd6ce8f6
FB
716 the effective address of the memory exception. 'is_write' is 1 if a
717 write caused the exception and otherwise 0'. 'old_set' is the
718 signal set which should be restored */
2b413144 719static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
5fafdf24 720 int is_write, sigset_t *old_set,
bf3e8bf1 721 void *puc)
9de5e440 722{
a513fe19
FB
723 TranslationBlock *tb;
724 int ret;
68a79315 725
83479e77
FB
726 if (cpu_single_env)
727 env = cpu_single_env; /* XXX: find a correct solution for multithread */
fd6ce8f6 728#if defined(DEBUG_SIGNAL)
5fafdf24 729 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bf3e8bf1 730 pc, address, is_write, *(unsigned long *)old_set);
9de5e440 731#endif
25eb4484 732 /* XXX: locking issue */
53a5960a 733 if (is_write && page_unprotect(h2g(address), pc, puc)) {
fd6ce8f6
FB
734 return 1;
735 }
fbf9eeb3 736
3fb2ded1 737 /* see if it is an MMU fault */
6ebbf390 738 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
3fb2ded1
FB
739 if (ret < 0)
740 return 0; /* not an MMU fault */
741 if (ret == 0)
742 return 1; /* the MMU fault was handled without causing real CPU fault */
743 /* now we have a real cpu fault */
a513fe19
FB
744 tb = tb_find_pc(pc);
745 if (tb) {
9de5e440
FB
746 /* the PC is inside the translated code. It means that we have
747 a virtual CPU fault */
bf3e8bf1 748 cpu_restore_state(tb, env, pc, puc);
3fb2ded1 749 }
4cbf74b6 750 if (ret == 1) {
3fb2ded1 751#if 0
5fafdf24 752 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
4cbf74b6 753 env->eip, env->cr[2], env->error_code);
3fb2ded1 754#endif
4cbf74b6
FB
755 /* we restore the process signal mask as the sigreturn should
756 do it (XXX: use sigsetjmp) */
757 sigprocmask(SIG_SETMASK, old_set, NULL);
54ca9095 758 raise_exception_err(env->exception_index, env->error_code);
4cbf74b6
FB
759 } else {
760 /* activate soft MMU for this block */
3f337316 761 env->hflags |= HF_SOFTMMU_MASK;
fbf9eeb3 762 cpu_resume_from_signal(env, puc);
4cbf74b6 763 }
3fb2ded1
FB
764 /* never comes here */
765 return 1;
766}
767
e4533c7a 768#elif defined(TARGET_ARM)
3fb2ded1 769static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
770 int is_write, sigset_t *old_set,
771 void *puc)
3fb2ded1 772{
68016c62
FB
773 TranslationBlock *tb;
774 int ret;
775
776 if (cpu_single_env)
777 env = cpu_single_env; /* XXX: find a correct solution for multithread */
778#if defined(DEBUG_SIGNAL)
5fafdf24 779 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
68016c62
FB
780 pc, address, is_write, *(unsigned long *)old_set);
781#endif
9f0777ed 782 /* XXX: locking issue */
53a5960a 783 if (is_write && page_unprotect(h2g(address), pc, puc)) {
9f0777ed
FB
784 return 1;
785 }
68016c62 786 /* see if it is an MMU fault */
6ebbf390 787 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
68016c62
FB
788 if (ret < 0)
789 return 0; /* not an MMU fault */
790 if (ret == 0)
791 return 1; /* the MMU fault was handled without causing real CPU fault */
792 /* now we have a real cpu fault */
793 tb = tb_find_pc(pc);
794 if (tb) {
795 /* the PC is inside the translated code. It means that we have
796 a virtual CPU fault */
797 cpu_restore_state(tb, env, pc, puc);
798 }
799 /* we restore the process signal mask as the sigreturn should
800 do it (XXX: use sigsetjmp) */
801 sigprocmask(SIG_SETMASK, old_set, NULL);
802 cpu_loop_exit();
968c74da
AJ
803 /* never comes here */
804 return 1;
3fb2ded1 805}
93ac68bc
FB
806#elif defined(TARGET_SPARC)
807static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
808 int is_write, sigset_t *old_set,
809 void *puc)
93ac68bc 810{
68016c62
FB
811 TranslationBlock *tb;
812 int ret;
813
814 if (cpu_single_env)
815 env = cpu_single_env; /* XXX: find a correct solution for multithread */
816#if defined(DEBUG_SIGNAL)
5fafdf24 817 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
68016c62
FB
818 pc, address, is_write, *(unsigned long *)old_set);
819#endif
b453b70b 820 /* XXX: locking issue */
53a5960a 821 if (is_write && page_unprotect(h2g(address), pc, puc)) {
b453b70b
FB
822 return 1;
823 }
68016c62 824 /* see if it is an MMU fault */
6ebbf390 825 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
68016c62
FB
826 if (ret < 0)
827 return 0; /* not an MMU fault */
828 if (ret == 0)
829 return 1; /* the MMU fault was handled without causing real CPU fault */
830 /* now we have a real cpu fault */
831 tb = tb_find_pc(pc);
832 if (tb) {
833 /* the PC is inside the translated code. It means that we have
834 a virtual CPU fault */
835 cpu_restore_state(tb, env, pc, puc);
836 }
837 /* we restore the process signal mask as the sigreturn should
838 do it (XXX: use sigsetjmp) */
839 sigprocmask(SIG_SETMASK, old_set, NULL);
840 cpu_loop_exit();
968c74da
AJ
841 /* never comes here */
842 return 1;
93ac68bc 843}
67867308
FB
844#elif defined (TARGET_PPC)
845static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
846 int is_write, sigset_t *old_set,
847 void *puc)
67867308
FB
848{
849 TranslationBlock *tb;
ce09776b 850 int ret;
3b46e624 851
67867308
FB
852 if (cpu_single_env)
853 env = cpu_single_env; /* XXX: find a correct solution for multithread */
67867308 854#if defined(DEBUG_SIGNAL)
5fafdf24 855 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
67867308
FB
856 pc, address, is_write, *(unsigned long *)old_set);
857#endif
858 /* XXX: locking issue */
53a5960a 859 if (is_write && page_unprotect(h2g(address), pc, puc)) {
67867308
FB
860 return 1;
861 }
862
ce09776b 863 /* see if it is an MMU fault */
6ebbf390 864 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
ce09776b
FB
865 if (ret < 0)
866 return 0; /* not an MMU fault */
867 if (ret == 0)
868 return 1; /* the MMU fault was handled without causing real CPU fault */
869
67867308
FB
870 /* now we have a real cpu fault */
871 tb = tb_find_pc(pc);
872 if (tb) {
873 /* the PC is inside the translated code. It means that we have
874 a virtual CPU fault */
bf3e8bf1 875 cpu_restore_state(tb, env, pc, puc);
67867308 876 }
ce09776b 877 if (ret == 1) {
67867308 878#if 0
5fafdf24 879 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
ce09776b 880 env->nip, env->error_code, tb);
67867308
FB
881#endif
882 /* we restore the process signal mask as the sigreturn should
883 do it (XXX: use sigsetjmp) */
bf3e8bf1 884 sigprocmask(SIG_SETMASK, old_set, NULL);
9fddaa0c 885 do_raise_exception_err(env->exception_index, env->error_code);
ce09776b
FB
886 } else {
887 /* activate soft MMU for this block */
fbf9eeb3 888 cpu_resume_from_signal(env, puc);
ce09776b 889 }
67867308 890 /* never comes here */
e6e5906b
PB
891 return 1;
892}
893
894#elif defined(TARGET_M68K)
895static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
896 int is_write, sigset_t *old_set,
897 void *puc)
898{
899 TranslationBlock *tb;
900 int ret;
901
902 if (cpu_single_env)
903 env = cpu_single_env; /* XXX: find a correct solution for multithread */
904#if defined(DEBUG_SIGNAL)
5fafdf24 905 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
e6e5906b
PB
906 pc, address, is_write, *(unsigned long *)old_set);
907#endif
908 /* XXX: locking issue */
909 if (is_write && page_unprotect(address, pc, puc)) {
910 return 1;
911 }
912 /* see if it is an MMU fault */
6ebbf390 913 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
e6e5906b
PB
914 if (ret < 0)
915 return 0; /* not an MMU fault */
916 if (ret == 0)
917 return 1; /* the MMU fault was handled without causing real CPU fault */
918 /* now we have a real cpu fault */
919 tb = tb_find_pc(pc);
920 if (tb) {
921 /* the PC is inside the translated code. It means that we have
922 a virtual CPU fault */
923 cpu_restore_state(tb, env, pc, puc);
924 }
925 /* we restore the process signal mask as the sigreturn should
926 do it (XXX: use sigsetjmp) */
927 sigprocmask(SIG_SETMASK, old_set, NULL);
928 cpu_loop_exit();
929 /* never comes here */
67867308
FB
930 return 1;
931}
6af0bf9c
FB
932
933#elif defined (TARGET_MIPS)
934static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
935 int is_write, sigset_t *old_set,
936 void *puc)
937{
938 TranslationBlock *tb;
939 int ret;
3b46e624 940
6af0bf9c
FB
941 if (cpu_single_env)
942 env = cpu_single_env; /* XXX: find a correct solution for multithread */
943#if defined(DEBUG_SIGNAL)
5fafdf24 944 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
6af0bf9c
FB
945 pc, address, is_write, *(unsigned long *)old_set);
946#endif
947 /* XXX: locking issue */
53a5960a 948 if (is_write && page_unprotect(h2g(address), pc, puc)) {
6af0bf9c
FB
949 return 1;
950 }
951
952 /* see if it is an MMU fault */
6ebbf390 953 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
6af0bf9c
FB
954 if (ret < 0)
955 return 0; /* not an MMU fault */
956 if (ret == 0)
957 return 1; /* the MMU fault was handled without causing real CPU fault */
958
959 /* now we have a real cpu fault */
960 tb = tb_find_pc(pc);
961 if (tb) {
962 /* the PC is inside the translated code. It means that we have
963 a virtual CPU fault */
964 cpu_restore_state(tb, env, pc, puc);
965 }
966 if (ret == 1) {
967#if 0
5fafdf24 968 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1eb5207b 969 env->PC, env->error_code, tb);
6af0bf9c
FB
970#endif
971 /* we restore the process signal mask as the sigreturn should
972 do it (XXX: use sigsetjmp) */
973 sigprocmask(SIG_SETMASK, old_set, NULL);
974 do_raise_exception_err(env->exception_index, env->error_code);
975 } else {
976 /* activate soft MMU for this block */
977 cpu_resume_from_signal(env, puc);
978 }
979 /* never comes here */
980 return 1;
981}
982
fdf9b3e8
FB
983#elif defined (TARGET_SH4)
984static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
985 int is_write, sigset_t *old_set,
986 void *puc)
987{
988 TranslationBlock *tb;
989 int ret;
3b46e624 990
fdf9b3e8
FB
991 if (cpu_single_env)
992 env = cpu_single_env; /* XXX: find a correct solution for multithread */
993#if defined(DEBUG_SIGNAL)
5fafdf24 994 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
fdf9b3e8
FB
995 pc, address, is_write, *(unsigned long *)old_set);
996#endif
997 /* XXX: locking issue */
998 if (is_write && page_unprotect(h2g(address), pc, puc)) {
999 return 1;
1000 }
1001
1002 /* see if it is an MMU fault */
6ebbf390 1003 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
fdf9b3e8
FB
1004 if (ret < 0)
1005 return 0; /* not an MMU fault */
1006 if (ret == 0)
1007 return 1; /* the MMU fault was handled without causing real CPU fault */
1008
1009 /* now we have a real cpu fault */
eddf68a6
JM
1010 tb = tb_find_pc(pc);
1011 if (tb) {
1012 /* the PC is inside the translated code. It means that we have
1013 a virtual CPU fault */
1014 cpu_restore_state(tb, env, pc, puc);
1015 }
1016#if 0
5fafdf24 1017 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
eddf68a6
JM
1018 env->nip, env->error_code, tb);
1019#endif
1020 /* we restore the process signal mask as the sigreturn should
1021 do it (XXX: use sigsetjmp) */
1022 sigprocmask(SIG_SETMASK, old_set, NULL);
1023 cpu_loop_exit();
1024 /* never comes here */
1025 return 1;
1026}
1027
1028#elif defined (TARGET_ALPHA)
1029static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1030 int is_write, sigset_t *old_set,
1031 void *puc)
1032{
1033 TranslationBlock *tb;
1034 int ret;
3b46e624 1035
eddf68a6
JM
1036 if (cpu_single_env)
1037 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1038#if defined(DEBUG_SIGNAL)
5fafdf24 1039 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
eddf68a6
JM
1040 pc, address, is_write, *(unsigned long *)old_set);
1041#endif
1042 /* XXX: locking issue */
1043 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1044 return 1;
1045 }
1046
1047 /* see if it is an MMU fault */
6ebbf390 1048 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
eddf68a6
JM
1049 if (ret < 0)
1050 return 0; /* not an MMU fault */
1051 if (ret == 0)
1052 return 1; /* the MMU fault was handled without causing real CPU fault */
1053
1054 /* now we have a real cpu fault */
fdf9b3e8
FB
1055 tb = tb_find_pc(pc);
1056 if (tb) {
1057 /* the PC is inside the translated code. It means that we have
1058 a virtual CPU fault */
1059 cpu_restore_state(tb, env, pc, puc);
1060 }
fdf9b3e8 1061#if 0
5fafdf24 1062 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
fdf9b3e8
FB
1063 env->nip, env->error_code, tb);
1064#endif
1065 /* we restore the process signal mask as the sigreturn should
1066 do it (XXX: use sigsetjmp) */
355fb23d
PB
1067 sigprocmask(SIG_SETMASK, old_set, NULL);
1068 cpu_loop_exit();
fdf9b3e8
FB
1069 /* never comes here */
1070 return 1;
1071}
f1ccf904
TS
1072#elif defined (TARGET_CRIS)
1073static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1074 int is_write, sigset_t *old_set,
1075 void *puc)
1076{
1077 TranslationBlock *tb;
1078 int ret;
1079
1080 if (cpu_single_env)
1081 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1082#if defined(DEBUG_SIGNAL)
1083 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1084 pc, address, is_write, *(unsigned long *)old_set);
1085#endif
1086 /* XXX: locking issue */
1087 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1088 return 1;
1089 }
1090
1091 /* see if it is an MMU fault */
6ebbf390 1092 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
f1ccf904
TS
1093 if (ret < 0)
1094 return 0; /* not an MMU fault */
1095 if (ret == 0)
1096 return 1; /* the MMU fault was handled without causing real CPU fault */
1097
1098 /* now we have a real cpu fault */
1099 tb = tb_find_pc(pc);
1100 if (tb) {
1101 /* the PC is inside the translated code. It means that we have
1102 a virtual CPU fault */
1103 cpu_restore_state(tb, env, pc, puc);
1104 }
f1ccf904
TS
1105 /* we restore the process signal mask as the sigreturn should
1106 do it (XXX: use sigsetjmp) */
1107 sigprocmask(SIG_SETMASK, old_set, NULL);
1108 cpu_loop_exit();
1109 /* never comes here */
1110 return 1;
1111}
1112
e4533c7a
FB
1113#else
1114#error unsupported target CPU
1115#endif
9de5e440 1116
2b413144
FB
1117#if defined(__i386__)
1118
d8ecc0b9
FB
1119#if defined(__APPLE__)
1120# include <sys/ucontext.h>
1121
1122# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1123# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1124# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
1125#else
1126# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1127# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1128# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1129#endif
1130
5fafdf24 1131int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1132 void *puc)
9de5e440 1133{
5a7b542b 1134 siginfo_t *info = pinfo;
9de5e440
FB
1135 struct ucontext *uc = puc;
1136 unsigned long pc;
bf3e8bf1 1137 int trapno;
97eb5b14 1138
d691f669
FB
1139#ifndef REG_EIP
1140/* for glibc 2.1 */
fd6ce8f6
FB
1141#define REG_EIP EIP
1142#define REG_ERR ERR
1143#define REG_TRAPNO TRAPNO
d691f669 1144#endif
d8ecc0b9
FB
1145 pc = EIP_sig(uc);
1146 trapno = TRAP_sig(uc);
ec6338ba
FB
1147 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1148 trapno == 0xe ?
1149 (ERROR_sig(uc) >> 1) & 1 : 0,
1150 &uc->uc_sigmask, puc);
2b413144
FB
1151}
1152
bc51c5c9
FB
1153#elif defined(__x86_64__)
1154
5a7b542b 1155int cpu_signal_handler(int host_signum, void *pinfo,
bc51c5c9
FB
1156 void *puc)
1157{
5a7b542b 1158 siginfo_t *info = pinfo;
bc51c5c9
FB
1159 struct ucontext *uc = puc;
1160 unsigned long pc;
1161
1162 pc = uc->uc_mcontext.gregs[REG_RIP];
5fafdf24
TS
1163 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1164 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
bc51c5c9
FB
1165 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1166 &uc->uc_sigmask, puc);
1167}
1168
83fb7adf 1169#elif defined(__powerpc__)
2b413144 1170
83fb7adf
FB
1171/***********************************************************************
1172 * signal context platform-specific definitions
1173 * From Wine
1174 */
1175#ifdef linux
1176/* All Registers access - only for local access */
1177# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1178/* Gpr Registers access */
1179# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1180# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1181# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1182# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1183# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1184# define LR_sig(context) REG_sig(link, context) /* Link register */
1185# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1186/* Float Registers access */
1187# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1188# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1189/* Exception Registers access */
1190# define DAR_sig(context) REG_sig(dar, context)
1191# define DSISR_sig(context) REG_sig(dsisr, context)
1192# define TRAP_sig(context) REG_sig(trap, context)
1193#endif /* linux */
1194
1195#ifdef __APPLE__
1196# include <sys/ucontext.h>
1197typedef struct ucontext SIGCONTEXT;
1198/* All Registers access - only for local access */
1199# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1200# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1201# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1202# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1203/* Gpr Registers access */
1204# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1205# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1206# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1207# define CTR_sig(context) REG_sig(ctr, context)
1208# define XER_sig(context) REG_sig(xer, context) /* Link register */
1209# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1210# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1211/* Float Registers access */
1212# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1213# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1214/* Exception Registers access */
1215# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1216# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1217# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1218#endif /* __APPLE__ */
1219
5fafdf24 1220int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1221 void *puc)
2b413144 1222{
5a7b542b 1223 siginfo_t *info = pinfo;
25eb4484 1224 struct ucontext *uc = puc;
25eb4484 1225 unsigned long pc;
25eb4484
FB
1226 int is_write;
1227
83fb7adf 1228 pc = IAR_sig(uc);
25eb4484
FB
1229 is_write = 0;
1230#if 0
1231 /* ppc 4xx case */
83fb7adf 1232 if (DSISR_sig(uc) & 0x00800000)
25eb4484
FB
1233 is_write = 1;
1234#else
83fb7adf 1235 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
25eb4484
FB
1236 is_write = 1;
1237#endif
5fafdf24 1238 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1239 is_write, &uc->uc_sigmask, puc);
2b413144
FB
1240}
1241
2f87c607
FB
1242#elif defined(__alpha__)
1243
5fafdf24 1244int cpu_signal_handler(int host_signum, void *pinfo,
2f87c607
FB
1245 void *puc)
1246{
5a7b542b 1247 siginfo_t *info = pinfo;
2f87c607
FB
1248 struct ucontext *uc = puc;
1249 uint32_t *pc = uc->uc_mcontext.sc_pc;
1250 uint32_t insn = *pc;
1251 int is_write = 0;
1252
8c6939c0 1253 /* XXX: need kernel patch to get write flag faster */
2f87c607
FB
1254 switch (insn >> 26) {
1255 case 0x0d: // stw
1256 case 0x0e: // stb
1257 case 0x0f: // stq_u
1258 case 0x24: // stf
1259 case 0x25: // stg
1260 case 0x26: // sts
1261 case 0x27: // stt
1262 case 0x2c: // stl
1263 case 0x2d: // stq
1264 case 0x2e: // stl_c
1265 case 0x2f: // stq_c
1266 is_write = 1;
1267 }
1268
5fafdf24 1269 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1270 is_write, &uc->uc_sigmask, puc);
2f87c607 1271}
8c6939c0
FB
1272#elif defined(__sparc__)
1273
5fafdf24 1274int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1275 void *puc)
8c6939c0 1276{
5a7b542b 1277 siginfo_t *info = pinfo;
8c6939c0
FB
1278 int is_write;
1279 uint32_t insn;
6b4c11cd 1280#if !defined(__arch64__) || defined(HOST_SOLARIS)
c9e1e2b0
BS
1281 uint32_t *regs = (uint32_t *)(info + 1);
1282 void *sigmask = (regs + 20);
8c6939c0 1283 /* XXX: is there a standard glibc define ? */
c9e1e2b0
BS
1284 unsigned long pc = regs[1];
1285#else
1286 struct sigcontext *sc = puc;
1287 unsigned long pc = sc->sigc_regs.tpc;
1288 void *sigmask = (void *)sc->sigc_mask;
1289#endif
1290
8c6939c0
FB
1291 /* XXX: need kernel patch to get write flag faster */
1292 is_write = 0;
1293 insn = *(uint32_t *)pc;
1294 if ((insn >> 30) == 3) {
1295 switch((insn >> 19) & 0x3f) {
1296 case 0x05: // stb
1297 case 0x06: // sth
1298 case 0x04: // st
1299 case 0x07: // std
1300 case 0x24: // stf
1301 case 0x27: // stdf
1302 case 0x25: // stfsr
1303 is_write = 1;
1304 break;
1305 }
1306 }
5fafdf24 1307 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1308 is_write, sigmask, NULL);
8c6939c0
FB
1309}
1310
1311#elif defined(__arm__)
1312
5fafdf24 1313int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1314 void *puc)
8c6939c0 1315{
5a7b542b 1316 siginfo_t *info = pinfo;
8c6939c0
FB
1317 struct ucontext *uc = puc;
1318 unsigned long pc;
1319 int is_write;
3b46e624 1320
5c49b363
AZ
1321#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ =< 3))
1322 pc = uc->uc_mcontext.gregs[R15];
1323#else
4eee57f5 1324 pc = uc->uc_mcontext.arm_pc;
5c49b363 1325#endif
8c6939c0
FB
1326 /* XXX: compute is_write */
1327 is_write = 0;
5fafdf24 1328 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
8c6939c0 1329 is_write,
f3a9676a 1330 &uc->uc_sigmask, puc);
8c6939c0
FB
1331}
1332
38e584a0
FB
1333#elif defined(__mc68000)
1334
5fafdf24 1335int cpu_signal_handler(int host_signum, void *pinfo,
38e584a0
FB
1336 void *puc)
1337{
5a7b542b 1338 siginfo_t *info = pinfo;
38e584a0
FB
1339 struct ucontext *uc = puc;
1340 unsigned long pc;
1341 int is_write;
3b46e624 1342
38e584a0
FB
1343 pc = uc->uc_mcontext.gregs[16];
1344 /* XXX: compute is_write */
1345 is_write = 0;
5fafdf24 1346 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
38e584a0 1347 is_write,
bf3e8bf1 1348 &uc->uc_sigmask, puc);
38e584a0
FB
1349}
1350
b8076a74
FB
1351#elif defined(__ia64)
1352
1353#ifndef __ISR_VALID
1354 /* This ought to be in <bits/siginfo.h>... */
1355# define __ISR_VALID 1
b8076a74
FB
1356#endif
1357
5a7b542b 1358int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
b8076a74 1359{
5a7b542b 1360 siginfo_t *info = pinfo;
b8076a74
FB
1361 struct ucontext *uc = puc;
1362 unsigned long ip;
1363 int is_write = 0;
1364
1365 ip = uc->uc_mcontext.sc_ip;
1366 switch (host_signum) {
1367 case SIGILL:
1368 case SIGFPE:
1369 case SIGSEGV:
1370 case SIGBUS:
1371 case SIGTRAP:
fd4a43e4 1372 if (info->si_code && (info->si_segvflags & __ISR_VALID))
b8076a74
FB
1373 /* ISR.W (write-access) is bit 33: */
1374 is_write = (info->si_isr >> 33) & 1;
1375 break;
1376
1377 default:
1378 break;
1379 }
1380 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1381 is_write,
1382 &uc->uc_sigmask, puc);
1383}
1384
90cb9493
FB
1385#elif defined(__s390__)
1386
5fafdf24 1387int cpu_signal_handler(int host_signum, void *pinfo,
90cb9493
FB
1388 void *puc)
1389{
5a7b542b 1390 siginfo_t *info = pinfo;
90cb9493
FB
1391 struct ucontext *uc = puc;
1392 unsigned long pc;
1393 int is_write;
3b46e624 1394
90cb9493
FB
1395 pc = uc->uc_mcontext.psw.addr;
1396 /* XXX: compute is_write */
1397 is_write = 0;
5fafdf24 1398 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
c4b89d18
TS
1399 is_write, &uc->uc_sigmask, puc);
1400}
1401
1402#elif defined(__mips__)
1403
5fafdf24 1404int cpu_signal_handler(int host_signum, void *pinfo,
c4b89d18
TS
1405 void *puc)
1406{
9617efe8 1407 siginfo_t *info = pinfo;
c4b89d18
TS
1408 struct ucontext *uc = puc;
1409 greg_t pc = uc->uc_mcontext.pc;
1410 int is_write;
3b46e624 1411
c4b89d18
TS
1412 /* XXX: compute is_write */
1413 is_write = 0;
5fafdf24 1414 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
c4b89d18 1415 is_write, &uc->uc_sigmask, puc);
90cb9493
FB
1416}
1417
f54b3f92
AJ
1418#elif defined(__hppa__)
1419
1420int cpu_signal_handler(int host_signum, void *pinfo,
1421 void *puc)
1422{
1423 struct siginfo *info = pinfo;
1424 struct ucontext *uc = puc;
1425 unsigned long pc;
1426 int is_write;
1427
1428 pc = uc->uc_mcontext.sc_iaoq[0];
1429 /* FIXME: compute is_write */
1430 is_write = 0;
1431 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1432 is_write,
1433 &uc->uc_sigmask, puc);
1434}
1435
9de5e440 1436#else
2b413144 1437
3fb2ded1 1438#error host CPU specific signal handler needed
2b413144 1439
9de5e440 1440#endif
67b915a5
FB
1441
1442#endif /* !defined(CONFIG_SOFTMMU) */