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