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