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