]> git.proxmox.com Git - mirror_qemu.git/blame - cpu-exec.c
Update OpenBIOS images to SVN revision 181. Changes:
[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 204#elif defined(TARGET_SH4)
823029f9
TS
205 flags = env->flags;
206 cs_base = 0;
fdf9b3e8 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 513#elif defined(TARGET_SH4)
e96e2044
TS
514 if (interrupt_request & CPU_INTERRUPT_HARD) {
515 do_interrupt(env);
516 BREAK_CHAIN;
517 }
eddf68a6
JM
518#elif defined(TARGET_ALPHA)
519 if (interrupt_request & CPU_INTERRUPT_HARD) {
520 do_interrupt(env);
497ad68c 521 BREAK_CHAIN;
eddf68a6 522 }
f1ccf904
TS
523#elif defined(TARGET_CRIS)
524 if (interrupt_request & CPU_INTERRUPT_HARD) {
525 do_interrupt(env);
526 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
497ad68c 527 BREAK_CHAIN;
f1ccf904 528 }
0633879f
PB
529#elif defined(TARGET_M68K)
530 if (interrupt_request & CPU_INTERRUPT_HARD
531 && ((env->sr & SR_I) >> SR_I_SHIFT)
532 < env->pending_level) {
533 /* Real hardware gets the interrupt vector via an
534 IACK cycle at this point. Current emulated
535 hardware doesn't rely on this, so we
536 provide/save the vector when the interrupt is
537 first signalled. */
538 env->exception_index = env->pending_vector;
539 do_interrupt(1);
497ad68c 540 BREAK_CHAIN;
0633879f 541 }
68a79315 542#endif
9d05095e
FB
543 /* Don't use the cached interupt_request value,
544 do_interrupt may have updated the EXITTB flag. */
b5ff1b31 545 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bf3e8bf1
FB
546 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
547 /* ensure that no TB jump will be modified as
548 the program flow was changed */
497ad68c 549 BREAK_CHAIN;
bf3e8bf1 550 }
68a79315
FB
551 if (interrupt_request & CPU_INTERRUPT_EXIT) {
552 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
553 env->exception_index = EXCP_INTERRUPT;
554 cpu_loop_exit();
555 }
3fb2ded1 556 }
7d13299d 557#ifdef DEBUG_EXEC
b5ff1b31 558 if ((loglevel & CPU_LOG_TB_CPU)) {
3fb2ded1 559 /* restore flags in standard format */
ecb644f4
TS
560 regs_to_env();
561#if defined(TARGET_I386)
3fb2ded1 562 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
7fe48483 563 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
3fb2ded1 564 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
e4533c7a 565#elif defined(TARGET_ARM)
7fe48483 566 cpu_dump_state(env, logfile, fprintf, 0);
93ac68bc 567#elif defined(TARGET_SPARC)
3475187d
FB
568 REGWPTR = env->regbase + (env->cwp * 16);
569 env->regwptr = REGWPTR;
570 cpu_dump_state(env, logfile, fprintf, 0);
67867308 571#elif defined(TARGET_PPC)
7fe48483 572 cpu_dump_state(env, logfile, fprintf, 0);
e6e5906b
PB
573#elif defined(TARGET_M68K)
574 cpu_m68k_flush_flags(env, env->cc_op);
575 env->cc_op = CC_OP_FLAGS;
576 env->sr = (env->sr & 0xffe0)
577 | env->cc_dest | (env->cc_x << 4);
578 cpu_dump_state(env, logfile, fprintf, 0);
6af0bf9c
FB
579#elif defined(TARGET_MIPS)
580 cpu_dump_state(env, logfile, fprintf, 0);
fdf9b3e8
FB
581#elif defined(TARGET_SH4)
582 cpu_dump_state(env, logfile, fprintf, 0);
eddf68a6
JM
583#elif defined(TARGET_ALPHA)
584 cpu_dump_state(env, logfile, fprintf, 0);
f1ccf904
TS
585#elif defined(TARGET_CRIS)
586 cpu_dump_state(env, logfile, fprintf, 0);
e4533c7a 587#else
5fafdf24 588#error unsupported target CPU
e4533c7a 589#endif
3fb2ded1 590 }
7d13299d 591#endif
8a40a180 592 tb = tb_find_fast();
9d27abd9 593#ifdef DEBUG_EXEC
c1135f61 594 if ((loglevel & CPU_LOG_EXEC)) {
c27004ec
FB
595 fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
596 (long)tb->tc_ptr, tb->pc,
597 lookup_symbol(tb->pc));
3fb2ded1 598 }
9d27abd9 599#endif
fdbb4691 600#if defined(__sparc__) && !defined(HOST_SOLARIS)
3fb2ded1 601 T0 = tmp_T0;
3b46e624 602#endif
8a40a180
FB
603 /* see if we can patch the calling TB. When the TB
604 spans two pages, we cannot safely do a direct
605 jump. */
c27004ec 606 {
8a40a180 607 if (T0 != 0 &&
f32fc648
FB
608#if USE_KQEMU
609 (env->kqemu_enabled != 2) &&
610#endif
ec6338ba 611 tb->page_addr[1] == -1) {
3fb2ded1 612 spin_lock(&tb_lock);
c27004ec 613 tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
3fb2ded1
FB
614 spin_unlock(&tb_lock);
615 }
c27004ec 616 }
3fb2ded1 617 tc_ptr = tb->tc_ptr;
83479e77 618 env->current_tb = tb;
3fb2ded1
FB
619 /* execute the generated code */
620 gen_func = (void *)tc_ptr;
8c6939c0 621#if defined(__sparc__)
3fb2ded1
FB
622 __asm__ __volatile__("call %0\n\t"
623 "mov %%o7,%%i0"
624 : /* no outputs */
5fafdf24 625 : "r" (gen_func)
fdbb4691 626 : "i0", "i1", "i2", "i3", "i4", "i5",
faab7592 627 "o0", "o1", "o2", "o3", "o4", "o5",
fdbb4691
FB
628 "l0", "l1", "l2", "l3", "l4", "l5",
629 "l6", "l7");
8c6939c0 630#elif defined(__arm__)
3fb2ded1
FB
631 asm volatile ("mov pc, %0\n\t"
632 ".global exec_loop\n\t"
633 "exec_loop:\n\t"
634 : /* no outputs */
635 : "r" (gen_func)
636 : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
b8076a74
FB
637#elif defined(__ia64)
638 struct fptr {
639 void *ip;
640 void *gp;
641 } fp;
642
643 fp.ip = tc_ptr;
644 fp.gp = code_gen_buffer + 2 * (1 << 20);
645 (*(void (*)(void)) &fp)();
ae228531 646#else
3fb2ded1 647 gen_func();
ae228531 648#endif
83479e77 649 env->current_tb = NULL;
4cbf74b6
FB
650 /* reset soft MMU for next block (it can currently
651 only be set by a memory fault) */
652#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
3f337316
FB
653 if (env->hflags & HF_SOFTMMU_MASK) {
654 env->hflags &= ~HF_SOFTMMU_MASK;
4cbf74b6
FB
655 /* do not allow linking to another block */
656 T0 = 0;
657 }
f32fc648
FB
658#endif
659#if defined(USE_KQEMU)
660#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
661 if (kqemu_is_ok(env) &&
662 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
663 cpu_loop_exit();
664 }
4cbf74b6 665#endif
50a518e3 666 } /* for(;;) */
3fb2ded1 667 } else {
0d1a29f9 668 env_to_regs();
7d13299d 669 }
3fb2ded1
FB
670 } /* for(;;) */
671
7d13299d 672
e4533c7a 673#if defined(TARGET_I386)
9de5e440 674 /* restore flags in standard format */
fc2b4c48 675 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
e4533c7a 676#elif defined(TARGET_ARM)
b7bcbe95 677 /* XXX: Save/restore host fpu exception state?. */
93ac68bc 678#elif defined(TARGET_SPARC)
3475187d
FB
679#if defined(reg_REGWPTR)
680 REGWPTR = saved_regwptr;
681#endif
67867308 682#elif defined(TARGET_PPC)
e6e5906b
PB
683#elif defined(TARGET_M68K)
684 cpu_m68k_flush_flags(env, env->cc_op);
685 env->cc_op = CC_OP_FLAGS;
686 env->sr = (env->sr & 0xffe0)
687 | env->cc_dest | (env->cc_x << 4);
6af0bf9c 688#elif defined(TARGET_MIPS)
fdf9b3e8 689#elif defined(TARGET_SH4)
eddf68a6 690#elif defined(TARGET_ALPHA)
f1ccf904 691#elif defined(TARGET_CRIS)
fdf9b3e8 692 /* XXXXX */
e4533c7a
FB
693#else
694#error unsupported target CPU
695#endif
1057eaa7
PB
696
697 /* restore global registers */
fdbb4691 698#if defined(__sparc__) && !defined(HOST_SOLARIS)
8c6939c0 699 asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
04369ff2 700#endif
1057eaa7
PB
701#include "hostregs_helper.h"
702
6a00d601 703 /* fail safe : never use cpu_single_env outside cpu_exec() */
5fafdf24 704 cpu_single_env = NULL;
7d13299d
FB
705 return ret;
706}
6dbad63e 707
fbf9eeb3
FB
708/* must only be called from the generated code as an exception can be
709 generated */
710void tb_invalidate_page_range(target_ulong start, target_ulong end)
711{
dc5d0b3d
FB
712 /* XXX: cannot enable it yet because it yields to MMU exception
713 where NIP != read address on PowerPC */
714#if 0
fbf9eeb3
FB
715 target_ulong phys_addr;
716 phys_addr = get_phys_addr_code(env, start);
717 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
dc5d0b3d 718#endif
fbf9eeb3
FB
719}
720
1a18c71b 721#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
e4533c7a 722
6dbad63e
FB
723void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
724{
725 CPUX86State *saved_env;
726
727 saved_env = env;
728 env = s;
a412ac57 729 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
a513fe19 730 selector &= 0xffff;
5fafdf24 731 cpu_x86_load_seg_cache(env, seg_reg, selector,
c27004ec 732 (selector << 4), 0xffff, 0);
a513fe19 733 } else {
b453b70b 734 load_seg(seg_reg, selector);
a513fe19 735 }
6dbad63e
FB
736 env = saved_env;
737}
9de5e440 738
6f12a2a6 739void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
d0a1ffc9
FB
740{
741 CPUX86State *saved_env;
742
743 saved_env = env;
744 env = s;
3b46e624 745
6f12a2a6 746 helper_fsave(ptr, data32);
d0a1ffc9
FB
747
748 env = saved_env;
749}
750
6f12a2a6 751void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
d0a1ffc9
FB
752{
753 CPUX86State *saved_env;
754
755 saved_env = env;
756 env = s;
3b46e624 757
6f12a2a6 758 helper_frstor(ptr, data32);
d0a1ffc9
FB
759
760 env = saved_env;
761}
762
e4533c7a
FB
763#endif /* TARGET_I386 */
764
67b915a5
FB
765#if !defined(CONFIG_SOFTMMU)
766
3fb2ded1
FB
767#if defined(TARGET_I386)
768
b56dad1c 769/* 'pc' is the host PC at which the exception was raised. 'address' is
fd6ce8f6
FB
770 the effective address of the memory exception. 'is_write' is 1 if a
771 write caused the exception and otherwise 0'. 'old_set' is the
772 signal set which should be restored */
2b413144 773static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
5fafdf24 774 int is_write, sigset_t *old_set,
bf3e8bf1 775 void *puc)
9de5e440 776{
a513fe19
FB
777 TranslationBlock *tb;
778 int ret;
68a79315 779
83479e77
FB
780 if (cpu_single_env)
781 env = cpu_single_env; /* XXX: find a correct solution for multithread */
fd6ce8f6 782#if defined(DEBUG_SIGNAL)
5fafdf24 783 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bf3e8bf1 784 pc, address, is_write, *(unsigned long *)old_set);
9de5e440 785#endif
25eb4484 786 /* XXX: locking issue */
53a5960a 787 if (is_write && page_unprotect(h2g(address), pc, puc)) {
fd6ce8f6
FB
788 return 1;
789 }
fbf9eeb3 790
3fb2ded1 791 /* see if it is an MMU fault */
6ebbf390 792 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
3fb2ded1
FB
793 if (ret < 0)
794 return 0; /* not an MMU fault */
795 if (ret == 0)
796 return 1; /* the MMU fault was handled without causing real CPU fault */
797 /* now we have a real cpu fault */
a513fe19
FB
798 tb = tb_find_pc(pc);
799 if (tb) {
9de5e440
FB
800 /* the PC is inside the translated code. It means that we have
801 a virtual CPU fault */
bf3e8bf1 802 cpu_restore_state(tb, env, pc, puc);
3fb2ded1 803 }
4cbf74b6 804 if (ret == 1) {
3fb2ded1 805#if 0
5fafdf24 806 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
4cbf74b6 807 env->eip, env->cr[2], env->error_code);
3fb2ded1 808#endif
4cbf74b6
FB
809 /* we restore the process signal mask as the sigreturn should
810 do it (XXX: use sigsetjmp) */
811 sigprocmask(SIG_SETMASK, old_set, NULL);
54ca9095 812 raise_exception_err(env->exception_index, env->error_code);
4cbf74b6
FB
813 } else {
814 /* activate soft MMU for this block */
3f337316 815 env->hflags |= HF_SOFTMMU_MASK;
fbf9eeb3 816 cpu_resume_from_signal(env, puc);
4cbf74b6 817 }
3fb2ded1
FB
818 /* never comes here */
819 return 1;
820}
821
e4533c7a 822#elif defined(TARGET_ARM)
3fb2ded1 823static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
824 int is_write, sigset_t *old_set,
825 void *puc)
3fb2ded1 826{
68016c62
FB
827 TranslationBlock *tb;
828 int ret;
829
830 if (cpu_single_env)
831 env = cpu_single_env; /* XXX: find a correct solution for multithread */
832#if defined(DEBUG_SIGNAL)
5fafdf24 833 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
68016c62
FB
834 pc, address, is_write, *(unsigned long *)old_set);
835#endif
9f0777ed 836 /* XXX: locking issue */
53a5960a 837 if (is_write && page_unprotect(h2g(address), pc, puc)) {
9f0777ed
FB
838 return 1;
839 }
68016c62 840 /* see if it is an MMU fault */
6ebbf390 841 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
68016c62
FB
842 if (ret < 0)
843 return 0; /* not an MMU fault */
844 if (ret == 0)
845 return 1; /* the MMU fault was handled without causing real CPU fault */
846 /* now we have a real cpu fault */
847 tb = tb_find_pc(pc);
848 if (tb) {
849 /* the PC is inside the translated code. It means that we have
850 a virtual CPU fault */
851 cpu_restore_state(tb, env, pc, puc);
852 }
853 /* we restore the process signal mask as the sigreturn should
854 do it (XXX: use sigsetjmp) */
855 sigprocmask(SIG_SETMASK, old_set, NULL);
856 cpu_loop_exit();
3fb2ded1 857}
93ac68bc
FB
858#elif defined(TARGET_SPARC)
859static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
860 int is_write, sigset_t *old_set,
861 void *puc)
93ac68bc 862{
68016c62
FB
863 TranslationBlock *tb;
864 int ret;
865
866 if (cpu_single_env)
867 env = cpu_single_env; /* XXX: find a correct solution for multithread */
868#if defined(DEBUG_SIGNAL)
5fafdf24 869 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
68016c62
FB
870 pc, address, is_write, *(unsigned long *)old_set);
871#endif
b453b70b 872 /* XXX: locking issue */
53a5960a 873 if (is_write && page_unprotect(h2g(address), pc, puc)) {
b453b70b
FB
874 return 1;
875 }
68016c62 876 /* see if it is an MMU fault */
6ebbf390 877 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
68016c62
FB
878 if (ret < 0)
879 return 0; /* not an MMU fault */
880 if (ret == 0)
881 return 1; /* the MMU fault was handled without causing real CPU fault */
882 /* now we have a real cpu fault */
883 tb = tb_find_pc(pc);
884 if (tb) {
885 /* the PC is inside the translated code. It means that we have
886 a virtual CPU fault */
887 cpu_restore_state(tb, env, pc, puc);
888 }
889 /* we restore the process signal mask as the sigreturn should
890 do it (XXX: use sigsetjmp) */
891 sigprocmask(SIG_SETMASK, old_set, NULL);
892 cpu_loop_exit();
93ac68bc 893}
67867308
FB
894#elif defined (TARGET_PPC)
895static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
896 int is_write, sigset_t *old_set,
897 void *puc)
67867308
FB
898{
899 TranslationBlock *tb;
ce09776b 900 int ret;
3b46e624 901
67867308
FB
902 if (cpu_single_env)
903 env = cpu_single_env; /* XXX: find a correct solution for multithread */
67867308 904#if defined(DEBUG_SIGNAL)
5fafdf24 905 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
67867308
FB
906 pc, address, is_write, *(unsigned long *)old_set);
907#endif
908 /* XXX: locking issue */
53a5960a 909 if (is_write && page_unprotect(h2g(address), pc, puc)) {
67867308
FB
910 return 1;
911 }
912
ce09776b 913 /* see if it is an MMU fault */
6ebbf390 914 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
ce09776b
FB
915 if (ret < 0)
916 return 0; /* not an MMU fault */
917 if (ret == 0)
918 return 1; /* the MMU fault was handled without causing real CPU fault */
919
67867308
FB
920 /* now we have a real cpu fault */
921 tb = tb_find_pc(pc);
922 if (tb) {
923 /* the PC is inside the translated code. It means that we have
924 a virtual CPU fault */
bf3e8bf1 925 cpu_restore_state(tb, env, pc, puc);
67867308 926 }
ce09776b 927 if (ret == 1) {
67867308 928#if 0
5fafdf24 929 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
ce09776b 930 env->nip, env->error_code, tb);
67867308
FB
931#endif
932 /* we restore the process signal mask as the sigreturn should
933 do it (XXX: use sigsetjmp) */
bf3e8bf1 934 sigprocmask(SIG_SETMASK, old_set, NULL);
9fddaa0c 935 do_raise_exception_err(env->exception_index, env->error_code);
ce09776b
FB
936 } else {
937 /* activate soft MMU for this block */
fbf9eeb3 938 cpu_resume_from_signal(env, puc);
ce09776b 939 }
67867308 940 /* never comes here */
e6e5906b
PB
941 return 1;
942}
943
944#elif defined(TARGET_M68K)
945static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
946 int is_write, sigset_t *old_set,
947 void *puc)
948{
949 TranslationBlock *tb;
950 int ret;
951
952 if (cpu_single_env)
953 env = cpu_single_env; /* XXX: find a correct solution for multithread */
954#if defined(DEBUG_SIGNAL)
5fafdf24 955 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
e6e5906b
PB
956 pc, address, is_write, *(unsigned long *)old_set);
957#endif
958 /* XXX: locking issue */
959 if (is_write && page_unprotect(address, pc, puc)) {
960 return 1;
961 }
962 /* see if it is an MMU fault */
6ebbf390 963 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
e6e5906b
PB
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 /* now we have a real cpu fault */
969 tb = tb_find_pc(pc);
970 if (tb) {
971 /* the PC is inside the translated code. It means that we have
972 a virtual CPU fault */
973 cpu_restore_state(tb, env, pc, puc);
974 }
975 /* we restore the process signal mask as the sigreturn should
976 do it (XXX: use sigsetjmp) */
977 sigprocmask(SIG_SETMASK, old_set, NULL);
978 cpu_loop_exit();
979 /* never comes here */
67867308
FB
980 return 1;
981}
6af0bf9c
FB
982
983#elif defined (TARGET_MIPS)
984static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
985 int is_write, sigset_t *old_set,
986 void *puc)
987{
988 TranslationBlock *tb;
989 int ret;
3b46e624 990
6af0bf9c
FB
991 if (cpu_single_env)
992 env = cpu_single_env; /* XXX: find a correct solution for multithread */
993#if defined(DEBUG_SIGNAL)
5fafdf24 994 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
6af0bf9c
FB
995 pc, address, is_write, *(unsigned long *)old_set);
996#endif
997 /* XXX: locking issue */
53a5960a 998 if (is_write && page_unprotect(h2g(address), pc, puc)) {
6af0bf9c
FB
999 return 1;
1000 }
1001
1002 /* see if it is an MMU fault */
6ebbf390 1003 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
6af0bf9c
FB
1004 if (ret < 0)
1005 return 0; /* not an MMU fault */
1006 if (ret == 0)
1007 return 1; /* the MMU fault was handled without causing real CPU fault */
1008
1009 /* now we have a real cpu fault */
1010 tb = tb_find_pc(pc);
1011 if (tb) {
1012 /* the PC is inside the translated code. It means that we have
1013 a virtual CPU fault */
1014 cpu_restore_state(tb, env, pc, puc);
1015 }
1016 if (ret == 1) {
1017#if 0
5fafdf24 1018 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1eb5207b 1019 env->PC, env->error_code, tb);
6af0bf9c
FB
1020#endif
1021 /* we restore the process signal mask as the sigreturn should
1022 do it (XXX: use sigsetjmp) */
1023 sigprocmask(SIG_SETMASK, old_set, NULL);
1024 do_raise_exception_err(env->exception_index, env->error_code);
1025 } else {
1026 /* activate soft MMU for this block */
1027 cpu_resume_from_signal(env, puc);
1028 }
1029 /* never comes here */
1030 return 1;
1031}
1032
fdf9b3e8
FB
1033#elif defined (TARGET_SH4)
1034static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1035 int is_write, sigset_t *old_set,
1036 void *puc)
1037{
1038 TranslationBlock *tb;
1039 int ret;
3b46e624 1040
fdf9b3e8
FB
1041 if (cpu_single_env)
1042 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1043#if defined(DEBUG_SIGNAL)
5fafdf24 1044 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
fdf9b3e8
FB
1045 pc, address, is_write, *(unsigned long *)old_set);
1046#endif
1047 /* XXX: locking issue */
1048 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1049 return 1;
1050 }
1051
1052 /* see if it is an MMU fault */
6ebbf390 1053 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
fdf9b3e8
FB
1054 if (ret < 0)
1055 return 0; /* not an MMU fault */
1056 if (ret == 0)
1057 return 1; /* the MMU fault was handled without causing real CPU fault */
1058
1059 /* now we have a real cpu fault */
eddf68a6
JM
1060 tb = tb_find_pc(pc);
1061 if (tb) {
1062 /* the PC is inside the translated code. It means that we have
1063 a virtual CPU fault */
1064 cpu_restore_state(tb, env, pc, puc);
1065 }
1066#if 0
5fafdf24 1067 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
eddf68a6
JM
1068 env->nip, env->error_code, tb);
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 cpu_loop_exit();
1074 /* never comes here */
1075 return 1;
1076}
1077
1078#elif defined (TARGET_ALPHA)
1079static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1080 int is_write, sigset_t *old_set,
1081 void *puc)
1082{
1083 TranslationBlock *tb;
1084 int ret;
3b46e624 1085
eddf68a6
JM
1086 if (cpu_single_env)
1087 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1088#if defined(DEBUG_SIGNAL)
5fafdf24 1089 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
eddf68a6
JM
1090 pc, address, is_write, *(unsigned long *)old_set);
1091#endif
1092 /* XXX: locking issue */
1093 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1094 return 1;
1095 }
1096
1097 /* see if it is an MMU fault */
6ebbf390 1098 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
eddf68a6
JM
1099 if (ret < 0)
1100 return 0; /* not an MMU fault */
1101 if (ret == 0)
1102 return 1; /* the MMU fault was handled without causing real CPU fault */
1103
1104 /* now we have a real cpu fault */
fdf9b3e8
FB
1105 tb = tb_find_pc(pc);
1106 if (tb) {
1107 /* the PC is inside the translated code. It means that we have
1108 a virtual CPU fault */
1109 cpu_restore_state(tb, env, pc, puc);
1110 }
fdf9b3e8 1111#if 0
5fafdf24 1112 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
fdf9b3e8
FB
1113 env->nip, env->error_code, tb);
1114#endif
1115 /* we restore the process signal mask as the sigreturn should
1116 do it (XXX: use sigsetjmp) */
355fb23d
PB
1117 sigprocmask(SIG_SETMASK, old_set, NULL);
1118 cpu_loop_exit();
fdf9b3e8
FB
1119 /* never comes here */
1120 return 1;
1121}
f1ccf904
TS
1122#elif defined (TARGET_CRIS)
1123static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1124 int is_write, sigset_t *old_set,
1125 void *puc)
1126{
1127 TranslationBlock *tb;
1128 int ret;
1129
1130 if (cpu_single_env)
1131 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1132#if defined(DEBUG_SIGNAL)
1133 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1134 pc, address, is_write, *(unsigned long *)old_set);
1135#endif
1136 /* XXX: locking issue */
1137 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1138 return 1;
1139 }
1140
1141 /* see if it is an MMU fault */
6ebbf390 1142 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
f1ccf904
TS
1143 if (ret < 0)
1144 return 0; /* not an MMU fault */
1145 if (ret == 0)
1146 return 1; /* the MMU fault was handled without causing real CPU fault */
1147
1148 /* now we have a real cpu fault */
1149 tb = tb_find_pc(pc);
1150 if (tb) {
1151 /* the PC is inside the translated code. It means that we have
1152 a virtual CPU fault */
1153 cpu_restore_state(tb, env, pc, puc);
1154 }
1155#if 0
1156 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1157 env->nip, env->error_code, tb);
1158#endif
1159 /* we restore the process signal mask as the sigreturn should
1160 do it (XXX: use sigsetjmp) */
1161 sigprocmask(SIG_SETMASK, old_set, NULL);
1162 cpu_loop_exit();
1163 /* never comes here */
1164 return 1;
1165}
1166
e4533c7a
FB
1167#else
1168#error unsupported target CPU
1169#endif
9de5e440 1170
2b413144
FB
1171#if defined(__i386__)
1172
d8ecc0b9
FB
1173#if defined(__APPLE__)
1174# include <sys/ucontext.h>
1175
1176# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1177# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1178# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
1179#else
1180# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1181# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1182# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1183#endif
1184
5fafdf24 1185int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1186 void *puc)
9de5e440 1187{
5a7b542b 1188 siginfo_t *info = pinfo;
9de5e440
FB
1189 struct ucontext *uc = puc;
1190 unsigned long pc;
bf3e8bf1 1191 int trapno;
97eb5b14 1192
d691f669
FB
1193#ifndef REG_EIP
1194/* for glibc 2.1 */
fd6ce8f6
FB
1195#define REG_EIP EIP
1196#define REG_ERR ERR
1197#define REG_TRAPNO TRAPNO
d691f669 1198#endif
d8ecc0b9
FB
1199 pc = EIP_sig(uc);
1200 trapno = TRAP_sig(uc);
ec6338ba
FB
1201 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1202 trapno == 0xe ?
1203 (ERROR_sig(uc) >> 1) & 1 : 0,
1204 &uc->uc_sigmask, puc);
2b413144
FB
1205}
1206
bc51c5c9
FB
1207#elif defined(__x86_64__)
1208
5a7b542b 1209int cpu_signal_handler(int host_signum, void *pinfo,
bc51c5c9
FB
1210 void *puc)
1211{
5a7b542b 1212 siginfo_t *info = pinfo;
bc51c5c9
FB
1213 struct ucontext *uc = puc;
1214 unsigned long pc;
1215
1216 pc = uc->uc_mcontext.gregs[REG_RIP];
5fafdf24
TS
1217 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1218 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
bc51c5c9
FB
1219 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1220 &uc->uc_sigmask, puc);
1221}
1222
83fb7adf 1223#elif defined(__powerpc__)
2b413144 1224
83fb7adf
FB
1225/***********************************************************************
1226 * signal context platform-specific definitions
1227 * From Wine
1228 */
1229#ifdef linux
1230/* All Registers access - only for local access */
1231# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1232/* Gpr Registers access */
1233# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1234# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1235# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1236# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1237# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1238# define LR_sig(context) REG_sig(link, context) /* Link register */
1239# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1240/* Float Registers access */
1241# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1242# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1243/* Exception Registers access */
1244# define DAR_sig(context) REG_sig(dar, context)
1245# define DSISR_sig(context) REG_sig(dsisr, context)
1246# define TRAP_sig(context) REG_sig(trap, context)
1247#endif /* linux */
1248
1249#ifdef __APPLE__
1250# include <sys/ucontext.h>
1251typedef struct ucontext SIGCONTEXT;
1252/* All Registers access - only for local access */
1253# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1254# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1255# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1256# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1257/* Gpr Registers access */
1258# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1259# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1260# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1261# define CTR_sig(context) REG_sig(ctr, context)
1262# define XER_sig(context) REG_sig(xer, context) /* Link register */
1263# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1264# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1265/* Float Registers access */
1266# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1267# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1268/* Exception Registers access */
1269# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1270# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1271# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1272#endif /* __APPLE__ */
1273
5fafdf24 1274int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1275 void *puc)
2b413144 1276{
5a7b542b 1277 siginfo_t *info = pinfo;
25eb4484 1278 struct ucontext *uc = puc;
25eb4484 1279 unsigned long pc;
25eb4484
FB
1280 int is_write;
1281
83fb7adf 1282 pc = IAR_sig(uc);
25eb4484
FB
1283 is_write = 0;
1284#if 0
1285 /* ppc 4xx case */
83fb7adf 1286 if (DSISR_sig(uc) & 0x00800000)
25eb4484
FB
1287 is_write = 1;
1288#else
83fb7adf 1289 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
25eb4484
FB
1290 is_write = 1;
1291#endif
5fafdf24 1292 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1293 is_write, &uc->uc_sigmask, puc);
2b413144
FB
1294}
1295
2f87c607
FB
1296#elif defined(__alpha__)
1297
5fafdf24 1298int cpu_signal_handler(int host_signum, void *pinfo,
2f87c607
FB
1299 void *puc)
1300{
5a7b542b 1301 siginfo_t *info = pinfo;
2f87c607
FB
1302 struct ucontext *uc = puc;
1303 uint32_t *pc = uc->uc_mcontext.sc_pc;
1304 uint32_t insn = *pc;
1305 int is_write = 0;
1306
8c6939c0 1307 /* XXX: need kernel patch to get write flag faster */
2f87c607
FB
1308 switch (insn >> 26) {
1309 case 0x0d: // stw
1310 case 0x0e: // stb
1311 case 0x0f: // stq_u
1312 case 0x24: // stf
1313 case 0x25: // stg
1314 case 0x26: // sts
1315 case 0x27: // stt
1316 case 0x2c: // stl
1317 case 0x2d: // stq
1318 case 0x2e: // stl_c
1319 case 0x2f: // stq_c
1320 is_write = 1;
1321 }
1322
5fafdf24 1323 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1324 is_write, &uc->uc_sigmask, puc);
2f87c607 1325}
8c6939c0
FB
1326#elif defined(__sparc__)
1327
5fafdf24 1328int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1329 void *puc)
8c6939c0 1330{
5a7b542b 1331 siginfo_t *info = pinfo;
8c6939c0
FB
1332 uint32_t *regs = (uint32_t *)(info + 1);
1333 void *sigmask = (regs + 20);
1334 unsigned long pc;
1335 int is_write;
1336 uint32_t insn;
3b46e624 1337
8c6939c0
FB
1338 /* XXX: is there a standard glibc define ? */
1339 pc = regs[1];
1340 /* XXX: need kernel patch to get write flag faster */
1341 is_write = 0;
1342 insn = *(uint32_t *)pc;
1343 if ((insn >> 30) == 3) {
1344 switch((insn >> 19) & 0x3f) {
1345 case 0x05: // stb
1346 case 0x06: // sth
1347 case 0x04: // st
1348 case 0x07: // std
1349 case 0x24: // stf
1350 case 0x27: // stdf
1351 case 0x25: // stfsr
1352 is_write = 1;
1353 break;
1354 }
1355 }
5fafdf24 1356 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1357 is_write, sigmask, NULL);
8c6939c0
FB
1358}
1359
1360#elif defined(__arm__)
1361
5fafdf24 1362int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1363 void *puc)
8c6939c0 1364{
5a7b542b 1365 siginfo_t *info = pinfo;
8c6939c0
FB
1366 struct ucontext *uc = puc;
1367 unsigned long pc;
1368 int is_write;
3b46e624 1369
8c6939c0
FB
1370 pc = uc->uc_mcontext.gregs[R15];
1371 /* XXX: compute is_write */
1372 is_write = 0;
5fafdf24 1373 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
8c6939c0 1374 is_write,
f3a9676a 1375 &uc->uc_sigmask, puc);
8c6939c0
FB
1376}
1377
38e584a0
FB
1378#elif defined(__mc68000)
1379
5fafdf24 1380int cpu_signal_handler(int host_signum, void *pinfo,
38e584a0
FB
1381 void *puc)
1382{
5a7b542b 1383 siginfo_t *info = pinfo;
38e584a0
FB
1384 struct ucontext *uc = puc;
1385 unsigned long pc;
1386 int is_write;
3b46e624 1387
38e584a0
FB
1388 pc = uc->uc_mcontext.gregs[16];
1389 /* XXX: compute is_write */
1390 is_write = 0;
5fafdf24 1391 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
38e584a0 1392 is_write,
bf3e8bf1 1393 &uc->uc_sigmask, puc);
38e584a0
FB
1394}
1395
b8076a74
FB
1396#elif defined(__ia64)
1397
1398#ifndef __ISR_VALID
1399 /* This ought to be in <bits/siginfo.h>... */
1400# define __ISR_VALID 1
b8076a74
FB
1401#endif
1402
5a7b542b 1403int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
b8076a74 1404{
5a7b542b 1405 siginfo_t *info = pinfo;
b8076a74
FB
1406 struct ucontext *uc = puc;
1407 unsigned long ip;
1408 int is_write = 0;
1409
1410 ip = uc->uc_mcontext.sc_ip;
1411 switch (host_signum) {
1412 case SIGILL:
1413 case SIGFPE:
1414 case SIGSEGV:
1415 case SIGBUS:
1416 case SIGTRAP:
fd4a43e4 1417 if (info->si_code && (info->si_segvflags & __ISR_VALID))
b8076a74
FB
1418 /* ISR.W (write-access) is bit 33: */
1419 is_write = (info->si_isr >> 33) & 1;
1420 break;
1421
1422 default:
1423 break;
1424 }
1425 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1426 is_write,
1427 &uc->uc_sigmask, puc);
1428}
1429
90cb9493
FB
1430#elif defined(__s390__)
1431
5fafdf24 1432int cpu_signal_handler(int host_signum, void *pinfo,
90cb9493
FB
1433 void *puc)
1434{
5a7b542b 1435 siginfo_t *info = pinfo;
90cb9493
FB
1436 struct ucontext *uc = puc;
1437 unsigned long pc;
1438 int is_write;
3b46e624 1439
90cb9493
FB
1440 pc = uc->uc_mcontext.psw.addr;
1441 /* XXX: compute is_write */
1442 is_write = 0;
5fafdf24 1443 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
c4b89d18
TS
1444 is_write, &uc->uc_sigmask, puc);
1445}
1446
1447#elif defined(__mips__)
1448
5fafdf24 1449int cpu_signal_handler(int host_signum, void *pinfo,
c4b89d18
TS
1450 void *puc)
1451{
9617efe8 1452 siginfo_t *info = pinfo;
c4b89d18
TS
1453 struct ucontext *uc = puc;
1454 greg_t pc = uc->uc_mcontext.pc;
1455 int is_write;
3b46e624 1456
c4b89d18
TS
1457 /* XXX: compute is_write */
1458 is_write = 0;
5fafdf24 1459 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
c4b89d18 1460 is_write, &uc->uc_sigmask, puc);
90cb9493
FB
1461}
1462
9de5e440 1463#else
2b413144 1464
3fb2ded1 1465#error host CPU specific signal handler needed
2b413144 1466
9de5e440 1467#endif
67b915a5
FB
1468
1469#endif /* !defined(CONFIG_SOFTMMU) */