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