blob: fb31b4386190cb7605fe99e98eed3826b53fdc1f [file] [log] [blame]
bellard7d132992003-03-06 23:23:54 +00001/*
2 * i386 emulator main execution loop
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard66321a12005-04-06 20:47:48 +00004 * Copyright (c) 2003-2005 Fabrice Bellard
bellard7d132992003-03-06 23:23:54 +00005 *
bellard3ef693a2003-03-23 20:17:16 +00006 * 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.
bellard7d132992003-03-06 23:23:54 +000010 *
bellard3ef693a2003-03-23 20:17:16 +000011 * 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.
bellard7d132992003-03-06 23:23:54 +000015 *
bellard3ef693a2003-03-23 20:17:16 +000016 * 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
bellard7d132992003-03-06 23:23:54 +000019 */
bellarde4533c72003-06-15 19:51:39 +000020#include "config.h"
bellard93ac68b2003-09-30 20:57:29 +000021#include "exec.h"
bellard956034d2003-04-29 20:40:53 +000022#include "disas.h"
bellard7d132992003-03-06 23:23:54 +000023
bellardfbf9eeb2004-04-25 21:21:33 +000024#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
bellard36bdbe52003-11-19 22:12:02 +000038int tb_invalidated_flag;
blueswir1b5fc09a2008-05-04 06:38:18 +000039static unsigned long next_tb;
bellard36bdbe52003-11-19 22:12:02 +000040
bellarddc990652003-03-19 00:00:28 +000041//#define DEBUG_EXEC
bellard9de5e442003-03-23 16:49:39 +000042//#define DEBUG_SIGNAL
bellard7d132992003-03-06 23:23:54 +000043
blueswir166f1cdb2007-12-11 19:39:25 +000044#define SAVE_GLOBALS()
45#define RESTORE_GLOBALS()
46
47#if defined(__sparc__) && !defined(HOST_SOLARIS)
48#include <features.h>
49#if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
50 ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
51// Work around ugly bugs in glibc that mangle global register contents
52
53static volatile void *saved_env;
54static volatile unsigned long saved_t0, saved_i7;
55#undef SAVE_GLOBALS
56#define SAVE_GLOBALS() do { \
57 saved_env = env; \
58 saved_t0 = T0; \
59 asm volatile ("st %%i7, [%0]" : : "r" (&saved_i7)); \
60 } while(0)
61
62#undef RESTORE_GLOBALS
63#define RESTORE_GLOBALS() do { \
64 env = (void *)saved_env; \
65 T0 = saved_t0; \
66 asm volatile ("ld [%0], %%i7" : : "r" (&saved_i7)); \
67 } while(0)
68
69static int sparc_setjmp(jmp_buf buf)
70{
71 int ret;
72
73 SAVE_GLOBALS();
74 ret = setjmp(buf);
75 RESTORE_GLOBALS();
76 return ret;
77}
78#undef setjmp
79#define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
80
81static void sparc_longjmp(jmp_buf buf, int val)
82{
83 SAVE_GLOBALS();
84 longjmp(buf, val);
85}
86#define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
87#endif
88#endif
89
bellarde4533c72003-06-15 19:51:39 +000090void cpu_loop_exit(void)
91{
thsbfed01f2007-06-03 17:44:37 +000092 /* NOTE: the register at this point must be saved by hand because
93 longjmp restore them */
94 regs_to_env();
bellarde4533c72003-06-15 19:51:39 +000095 longjmp(env->jmp_env, 1);
96}
thsbfed01f2007-06-03 17:44:37 +000097
pbrooke6e59062006-10-22 00:18:54 +000098#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
bellard34751872005-07-02 14:31:34 +000099#define reg_T2
100#endif
bellarde4533c72003-06-15 19:51:39 +0000101
bellardfbf9eeb2004-04-25 21:21:33 +0000102/* exit the current TB from a signal handler. The host registers are
103 restored in a state compatible with the CPU emulator
104 */
ths5fafdf22007-09-16 21:08:06 +0000105void cpu_resume_from_signal(CPUState *env1, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +0000106{
107#if !defined(CONFIG_SOFTMMU)
108 struct ucontext *uc = puc;
109#endif
110
111 env = env1;
112
113 /* XXX: restore cpu registers saved in host registers */
114
115#if !defined(CONFIG_SOFTMMU)
116 if (puc) {
117 /* XXX: use siglongjmp ? */
118 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
119 }
120#endif
121 longjmp(env->jmp_env, 1);
122}
123
bellard8a40a182005-11-20 10:35:40 +0000124static TranslationBlock *tb_find_slow(target_ulong pc,
125 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +0000126 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +0000127{
128 TranslationBlock *tb, **ptb1;
129 int code_gen_size;
130 unsigned int h;
131 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
132 uint8_t *tc_ptr;
ths3b46e622007-09-17 08:09:54 +0000133
bellard8a40a182005-11-20 10:35:40 +0000134 spin_lock(&tb_lock);
135
136 tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +0000137
bellard8a40a182005-11-20 10:35:40 +0000138 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
ths3b46e622007-09-17 08:09:54 +0000139
bellard8a40a182005-11-20 10:35:40 +0000140 /* find translated block using physical mappings */
141 phys_pc = get_phys_addr_code(env, pc);
142 phys_page1 = phys_pc & TARGET_PAGE_MASK;
143 phys_page2 = -1;
144 h = tb_phys_hash_func(phys_pc);
145 ptb1 = &tb_phys_hash[h];
146 for(;;) {
147 tb = *ptb1;
148 if (!tb)
149 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000150 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000151 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000152 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000153 tb->flags == flags) {
154 /* check next page if needed */
155 if (tb->page_addr[1] != -1) {
ths5fafdf22007-09-16 21:08:06 +0000156 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000157 TARGET_PAGE_SIZE;
158 phys_page2 = get_phys_addr_code(env, virt_page2);
159 if (tb->page_addr[1] == phys_page2)
160 goto found;
161 } else {
162 goto found;
163 }
164 }
165 ptb1 = &tb->phys_hash_next;
166 }
167 not_found:
168 /* if no translated code available, then translate it now */
169 tb = tb_alloc(pc);
170 if (!tb) {
171 /* flush must be done */
172 tb_flush(env);
173 /* cannot fail at this point */
174 tb = tb_alloc(pc);
175 /* don't forget to invalidate previous TB info */
bellard15388002005-12-19 01:42:32 +0000176 tb_invalidated_flag = 1;
bellard8a40a182005-11-20 10:35:40 +0000177 }
178 tc_ptr = code_gen_ptr;
179 tb->tc_ptr = tc_ptr;
180 tb->cs_base = cs_base;
181 tb->flags = flags;
blueswir166f1cdb2007-12-11 19:39:25 +0000182 SAVE_GLOBALS();
blueswir1d07bde82007-12-11 19:35:45 +0000183 cpu_gen_code(env, tb, &code_gen_size);
blueswir166f1cdb2007-12-11 19:39:25 +0000184 RESTORE_GLOBALS();
bellard8a40a182005-11-20 10:35:40 +0000185 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
ths3b46e622007-09-17 08:09:54 +0000186
bellard8a40a182005-11-20 10:35:40 +0000187 /* check next page if needed */
188 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
189 phys_page2 = -1;
190 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
191 phys_page2 = get_phys_addr_code(env, virt_page2);
192 }
193 tb_link_phys(tb, phys_pc, phys_page2);
ths3b46e622007-09-17 08:09:54 +0000194
bellard8a40a182005-11-20 10:35:40 +0000195 found:
bellard8a40a182005-11-20 10:35:40 +0000196 /* we add the TB in the virtual pc hash table */
197 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
198 spin_unlock(&tb_lock);
199 return tb;
200}
201
202static inline TranslationBlock *tb_find_fast(void)
203{
204 TranslationBlock *tb;
205 target_ulong cs_base, pc;
j_mayerc0686882007-09-20 22:47:42 +0000206 uint64_t flags;
bellard8a40a182005-11-20 10:35:40 +0000207
208 /* we record a subset of the CPU state. It will
209 always be the same before a given translated block
210 is executed. */
211#if defined(TARGET_I386)
212 flags = env->hflags;
213 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
ths0573fbf2007-09-23 15:28:04 +0000214 flags |= env->intercept;
bellard8a40a182005-11-20 10:35:40 +0000215 cs_base = env->segs[R_CS].base;
216 pc = cs_base + env->eip;
217#elif defined(TARGET_ARM)
218 flags = env->thumb | (env->vfp.vec_len << 1)
bellardb5ff1b32005-11-26 10:38:39 +0000219 | (env->vfp.vec_stride << 4);
220 if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
221 flags |= (1 << 6);
pbrook40f137e2006-02-20 00:33:36 +0000222 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
223 flags |= (1 << 7);
pbrook9ee6e8b2007-11-11 00:04:49 +0000224 flags |= (env->condexec_bits << 8);
bellard8a40a182005-11-20 10:35:40 +0000225 cs_base = 0;
226 pc = env->regs[15];
227#elif defined(TARGET_SPARC)
228#ifdef TARGET_SPARC64
bellarda80dde02006-06-26 19:53:29 +0000229 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
230 flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
231 | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
bellard8a40a182005-11-20 10:35:40 +0000232#else
blueswir16d5f2372007-11-07 17:03:37 +0000233 // FPU enable . Supervisor
234 flags = (env->psref << 4) | env->psrs;
bellard8a40a182005-11-20 10:35:40 +0000235#endif
236 cs_base = env->npc;
237 pc = env->pc;
238#elif defined(TARGET_PPC)
j_mayer1527c872007-09-19 05:37:56 +0000239 flags = env->hflags;
bellard8a40a182005-11-20 10:35:40 +0000240 cs_base = 0;
241 pc = env->nip;
242#elif defined(TARGET_MIPS)
pbrook56b19402006-03-11 16:23:39 +0000243 flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
bellardcc9442b2005-11-26 18:43:28 +0000244 cs_base = 0;
thsead93602007-09-06 00:18:15 +0000245 pc = env->PC[env->current_tc];
pbrooke6e59062006-10-22 00:18:54 +0000246#elif defined(TARGET_M68K)
pbrookacf930a2007-05-29 14:57:59 +0000247 flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */
248 | (env->sr & SR_S) /* Bit 13 */
249 | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
pbrooke6e59062006-10-22 00:18:54 +0000250 cs_base = 0;
251 pc = env->pc;
bellardfdf9b3e2006-04-27 21:07:38 +0000252#elif defined(TARGET_SH4)
ths823029f2007-12-02 06:10:04 +0000253 flags = env->flags;
254 cs_base = 0;
bellardfdf9b3e2006-04-27 21:07:38 +0000255 pc = env->pc;
j_mayereddf68a2007-04-05 07:22:49 +0000256#elif defined(TARGET_ALPHA)
257 flags = env->ps;
258 cs_base = 0;
259 pc = env->pc;
thsf1ccf902007-10-08 13:16:14 +0000260#elif defined(TARGET_CRIS)
edgar_igl17a594d2008-05-07 15:27:14 +0000261 flags = env->pregs[PR_CCS] & U_FLAG;
thsf1ccf902007-10-08 13:16:14 +0000262 cs_base = 0;
263 pc = env->pc;
bellard8a40a182005-11-20 10:35:40 +0000264#else
265#error unsupported CPU
266#endif
bellardbce61842008-02-01 22:18:51 +0000267 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
bellard8a40a182005-11-20 10:35:40 +0000268 if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
269 tb->flags != flags, 0)) {
270 tb = tb_find_slow(pc, cs_base, flags);
bellard15388002005-12-19 01:42:32 +0000271 /* Note: we do it here to avoid a gcc bug on Mac OS X when
272 doing it in tb_find_slow */
273 if (tb_invalidated_flag) {
274 /* as some TB could have been invalidated because
275 of memory exceptions while generating the code, we
276 must recompute the hash index here */
blueswir1b5fc09a2008-05-04 06:38:18 +0000277 next_tb = 0;
bellard15388002005-12-19 01:42:32 +0000278 }
bellard8a40a182005-11-20 10:35:40 +0000279 }
280 return tb;
281}
282
bellard7d132992003-03-06 23:23:54 +0000283/* main execution loop */
284
bellarde4533c72003-06-15 19:51:39 +0000285int cpu_exec(CPUState *env1)
bellard7d132992003-03-06 23:23:54 +0000286{
pbrook1057eaa2007-02-04 13:37:44 +0000287#define DECLARE_HOST_REGS 1
288#include "hostregs_helper.h"
289#if defined(TARGET_SPARC)
bellard34751872005-07-02 14:31:34 +0000290#if defined(reg_REGWPTR)
291 uint32_t *saved_regwptr;
292#endif
293#endif
bellard8a40a182005-11-20 10:35:40 +0000294 int ret, interrupt_request;
blueswir1b5fc09a2008-05-04 06:38:18 +0000295 unsigned long (*gen_func)(void);
bellard8a40a182005-11-20 10:35:40 +0000296 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000297 uint8_t *tc_ptr;
bellard8c6939c2003-06-09 15:28:00 +0000298
thsbfed01f2007-06-03 17:44:37 +0000299 if (cpu_halted(env1) == EXCP_HALTED)
300 return EXCP_HALTED;
bellard5a1e3cf2005-11-23 21:02:53 +0000301
ths5fafdf22007-09-16 21:08:06 +0000302 cpu_single_env = env1;
bellard6a00d602005-11-21 23:25:50 +0000303
bellard7d132992003-03-06 23:23:54 +0000304 /* first we save global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000305#define SAVE_HOST_REGS 1
306#include "hostregs_helper.h"
bellardc27004e2005-01-03 23:35:10 +0000307 env = env1;
blueswir166f1cdb2007-12-11 19:39:25 +0000308 SAVE_GLOBALS();
bellarde4533c72003-06-15 19:51:39 +0000309
bellard0d1a29f2004-10-12 22:01:28 +0000310 env_to_regs();
thsecb644f2007-06-03 18:45:53 +0000311#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000312 /* put eflags in CPU temporary format */
bellardfc2b4c42003-03-29 16:52:44 +0000313 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
314 DF = 1 - (2 * ((env->eflags >> 10) & 1));
bellard9de5e442003-03-23 16:49:39 +0000315 CC_OP = CC_OP_EFLAGS;
bellardfc2b4c42003-03-29 16:52:44 +0000316 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000317#elif defined(TARGET_SPARC)
bellard34751872005-07-02 14:31:34 +0000318#if defined(reg_REGWPTR)
319 saved_regwptr = REGWPTR;
320#endif
pbrooke6e59062006-10-22 00:18:54 +0000321#elif defined(TARGET_M68K)
322 env->cc_op = CC_OP_FLAGS;
323 env->cc_dest = env->sr & 0xf;
324 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000325#elif defined(TARGET_ALPHA)
326#elif defined(TARGET_ARM)
327#elif defined(TARGET_PPC)
bellard6af0bf92005-07-02 14:58:51 +0000328#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000329#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000330#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000331 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000332#else
333#error unsupported target CPU
334#endif
bellard3fb2ded2003-06-24 13:22:59 +0000335 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000336
bellard7d132992003-03-06 23:23:54 +0000337 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000338 for(;;) {
339 if (setjmp(env->jmp_env) == 0) {
bellardee8b7022004-02-03 23:35:10 +0000340 env->current_tb = NULL;
bellard3fb2ded2003-06-24 13:22:59 +0000341 /* if an exception is pending, we execute it here */
342 if (env->exception_index >= 0) {
343 if (env->exception_index >= EXCP_INTERRUPT) {
344 /* exit request from the cpu execution loop */
345 ret = env->exception_index;
346 break;
347 } else if (env->user_mode_only) {
348 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000349 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000350 loop */
bellard83479e72003-06-25 16:12:37 +0000351#if defined(TARGET_I386)
ths5fafdf22007-09-16 21:08:06 +0000352 do_interrupt_user(env->exception_index,
353 env->exception_is_int,
354 env->error_code,
bellard3fb2ded2003-06-24 13:22:59 +0000355 env->exception_next_eip);
bellard83479e72003-06-25 16:12:37 +0000356#endif
bellard3fb2ded2003-06-24 13:22:59 +0000357 ret = env->exception_index;
358 break;
359 } else {
bellard83479e72003-06-25 16:12:37 +0000360#if defined(TARGET_I386)
bellard3fb2ded2003-06-24 13:22:59 +0000361 /* simulate a real cpu exception. On i386, it can
362 trigger new exceptions, but we do not handle
363 double or triple faults yet. */
ths5fafdf22007-09-16 21:08:06 +0000364 do_interrupt(env->exception_index,
365 env->exception_is_int,
366 env->error_code,
bellardd05e66d2003-08-20 21:34:35 +0000367 env->exception_next_eip, 0);
ths678dde12007-03-31 20:28:52 +0000368 /* successfully delivered */
369 env->old_exception = -1;
bellardce097762004-01-04 23:53:18 +0000370#elif defined(TARGET_PPC)
371 do_interrupt(env);
bellard6af0bf92005-07-02 14:58:51 +0000372#elif defined(TARGET_MIPS)
373 do_interrupt(env);
bellarde95c8d52004-09-30 22:22:08 +0000374#elif defined(TARGET_SPARC)
bellard1a0c3292005-02-13 19:02:07 +0000375 do_interrupt(env->exception_index);
bellardb5ff1b32005-11-26 10:38:39 +0000376#elif defined(TARGET_ARM)
377 do_interrupt(env);
bellardfdf9b3e2006-04-27 21:07:38 +0000378#elif defined(TARGET_SH4)
379 do_interrupt(env);
j_mayereddf68a2007-04-05 07:22:49 +0000380#elif defined(TARGET_ALPHA)
381 do_interrupt(env);
thsf1ccf902007-10-08 13:16:14 +0000382#elif defined(TARGET_CRIS)
383 do_interrupt(env);
pbrook06338792007-05-23 19:58:11 +0000384#elif defined(TARGET_M68K)
385 do_interrupt(0);
bellard83479e72003-06-25 16:12:37 +0000386#endif
bellard3fb2ded2003-06-24 13:22:59 +0000387 }
388 env->exception_index = -1;
ths5fafdf22007-09-16 21:08:06 +0000389 }
bellard9df217a2005-02-10 22:05:51 +0000390#ifdef USE_KQEMU
391 if (kqemu_is_ok(env) && env->interrupt_request == 0) {
392 int ret;
393 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
394 ret = kqemu_cpu_exec(env);
395 /* put eflags in CPU temporary format */
396 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
397 DF = 1 - (2 * ((env->eflags >> 10) & 1));
398 CC_OP = CC_OP_EFLAGS;
399 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
400 if (ret == 1) {
401 /* exception */
402 longjmp(env->jmp_env, 1);
403 } else if (ret == 2) {
404 /* softmmu execution needed */
405 } else {
406 if (env->interrupt_request != 0) {
407 /* hardware interrupt will be executed just after */
408 } else {
409 /* otherwise, we restart */
410 longjmp(env->jmp_env, 1);
411 }
412 }
bellard9de5e442003-03-23 16:49:39 +0000413 }
bellard9df217a2005-02-10 22:05:51 +0000414#endif
415
blueswir1b5fc09a2008-05-04 06:38:18 +0000416 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000417 for(;;) {
blueswir166f1cdb2007-12-11 19:39:25 +0000418 SAVE_GLOBALS();
bellard68a79312003-06-30 13:12:32 +0000419 interrupt_request = env->interrupt_request;
ths0573fbf2007-09-23 15:28:04 +0000420 if (__builtin_expect(interrupt_request, 0)
421#if defined(TARGET_I386)
422 && env->hflags & HF_GIF_MASK
423#endif
424 ) {
pbrook6658ffb2007-03-16 23:58:11 +0000425 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
426 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
427 env->exception_index = EXCP_DEBUG;
428 cpu_loop_exit();
429 }
balroga90b7312007-05-01 01:28:01 +0000430#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
thsf1ccf902007-10-08 13:16:14 +0000431 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
balroga90b7312007-05-01 01:28:01 +0000432 if (interrupt_request & CPU_INTERRUPT_HALT) {
433 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
434 env->halted = 1;
435 env->exception_index = EXCP_HLT;
436 cpu_loop_exit();
437 }
438#endif
bellard68a79312003-06-30 13:12:32 +0000439#if defined(TARGET_I386)
bellard3b21e032006-09-24 18:41:56 +0000440 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
441 !(env->hflags & HF_SMM_MASK)) {
ths0573fbf2007-09-23 15:28:04 +0000442 svm_check_intercept(SVM_EXIT_SMI);
bellard3b21e032006-09-24 18:41:56 +0000443 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
444 do_smm_enter();
blueswir1b5fc09a2008-05-04 06:38:18 +0000445 next_tb = 0;
aurel32474ea842008-04-13 16:08:15 +0000446 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
447 !(env->hflags & HF_NMI_MASK)) {
448 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
449 env->hflags |= HF_NMI_MASK;
450 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000451 next_tb = 0;
bellard3b21e032006-09-24 18:41:56 +0000452 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
ths0573fbf2007-09-23 15:28:04 +0000453 (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
bellard3f337312003-08-20 23:02:09 +0000454 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
bellard68a79312003-06-30 13:12:32 +0000455 int intno;
ths0573fbf2007-09-23 15:28:04 +0000456 svm_check_intercept(SVM_EXIT_INTR);
ths52621682007-09-27 01:52:00 +0000457 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
bellarda541f292004-04-12 20:39:29 +0000458 intno = cpu_get_pic_interrupt(env);
bellardf193c792004-03-21 17:06:25 +0000459 if (loglevel & CPU_LOG_TB_IN_ASM) {
bellard68a79312003-06-30 13:12:32 +0000460 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
461 }
bellardd05e66d2003-08-20 21:34:35 +0000462 do_interrupt(intno, 0, 0, 0, 1);
bellard907a5b22003-06-30 23:18:22 +0000463 /* ensure that no TB jump will be modified as
464 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000465 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000466#if !defined(CONFIG_USER_ONLY)
467 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
468 (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
469 int intno;
470 /* FIXME: this should respect TPR */
471 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
ths52621682007-09-27 01:52:00 +0000472 svm_check_intercept(SVM_EXIT_VINTR);
ths0573fbf2007-09-23 15:28:04 +0000473 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
474 if (loglevel & CPU_LOG_TB_IN_ASM)
475 fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
476 do_interrupt(intno, 0, 0, -1, 1);
ths52621682007-09-27 01:52:00 +0000477 stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
478 ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
blueswir1b5fc09a2008-05-04 06:38:18 +0000479 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000480#endif
bellard68a79312003-06-30 13:12:32 +0000481 }
bellardce097762004-01-04 23:53:18 +0000482#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000483#if 0
484 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
485 cpu_ppc_reset(env);
486 }
487#endif
j_mayer47103572007-03-30 09:38:04 +0000488 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000489 ppc_hw_interrupt(env);
490 if (env->pending_interrupts == 0)
491 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000492 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000493 }
bellard6af0bf92005-07-02 14:58:51 +0000494#elif defined(TARGET_MIPS)
495 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
ths24c7b0e2007-03-30 16:44:54 +0000496 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
bellard6af0bf92005-07-02 14:58:51 +0000497 (env->CP0_Status & (1 << CP0St_IE)) &&
ths24c7b0e2007-03-30 16:44:54 +0000498 !(env->CP0_Status & (1 << CP0St_EXL)) &&
499 !(env->CP0_Status & (1 << CP0St_ERL)) &&
bellard6af0bf92005-07-02 14:58:51 +0000500 !(env->hflags & MIPS_HFLAG_DM)) {
501 /* Raise it */
502 env->exception_index = EXCP_EXT_INTERRUPT;
503 env->error_code = 0;
504 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000505 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000506 }
bellarde95c8d52004-09-30 22:22:08 +0000507#elif defined(TARGET_SPARC)
bellard66321a12005-04-06 20:47:48 +0000508 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
509 (env->psret != 0)) {
510 int pil = env->interrupt_index & 15;
511 int type = env->interrupt_index & 0xf0;
512
513 if (((type == TT_EXTINT) &&
514 (pil == 15 || pil > env->psrpil)) ||
515 type != TT_EXTINT) {
516 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
517 do_interrupt(env->interrupt_index);
518 env->interrupt_index = 0;
blueswir1327ac2e2007-08-04 10:50:30 +0000519#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
520 cpu_check_irqs(env);
521#endif
blueswir1b5fc09a2008-05-04 06:38:18 +0000522 next_tb = 0;
bellard66321a12005-04-06 20:47:48 +0000523 }
bellarde95c8d52004-09-30 22:22:08 +0000524 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
525 //do_interrupt(0, 0, 0, 0, 0);
526 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
balroga90b7312007-05-01 01:28:01 +0000527 }
bellardb5ff1b32005-11-26 10:38:39 +0000528#elif defined(TARGET_ARM)
529 if (interrupt_request & CPU_INTERRUPT_FIQ
530 && !(env->uncached_cpsr & CPSR_F)) {
531 env->exception_index = EXCP_FIQ;
532 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000533 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000534 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000535 /* ARMv7-M interrupt return works by loading a magic value
536 into the PC. On real hardware the load causes the
537 return to occur. The qemu implementation performs the
538 jump normally, then does the exception return when the
539 CPU tries to execute code at the magic address.
540 This will cause the magic PC value to be pushed to
541 the stack if an interrupt occured at the wrong time.
542 We avoid this by disabling interrupts when
543 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000544 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000545 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
546 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000547 env->exception_index = EXCP_IRQ;
548 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000549 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000550 }
bellardfdf9b3e2006-04-27 21:07:38 +0000551#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000552 if (interrupt_request & CPU_INTERRUPT_HARD) {
553 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000554 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000555 }
j_mayereddf68a2007-04-05 07:22:49 +0000556#elif defined(TARGET_ALPHA)
557 if (interrupt_request & CPU_INTERRUPT_HARD) {
558 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000559 next_tb = 0;
j_mayereddf68a2007-04-05 07:22:49 +0000560 }
thsf1ccf902007-10-08 13:16:14 +0000561#elif defined(TARGET_CRIS)
562 if (interrupt_request & CPU_INTERRUPT_HARD) {
563 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000564 next_tb = 0;
thsf1ccf902007-10-08 13:16:14 +0000565 }
pbrook06338792007-05-23 19:58:11 +0000566#elif defined(TARGET_M68K)
567 if (interrupt_request & CPU_INTERRUPT_HARD
568 && ((env->sr & SR_I) >> SR_I_SHIFT)
569 < env->pending_level) {
570 /* Real hardware gets the interrupt vector via an
571 IACK cycle at this point. Current emulated
572 hardware doesn't rely on this, so we
573 provide/save the vector when the interrupt is
574 first signalled. */
575 env->exception_index = env->pending_vector;
576 do_interrupt(1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000577 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000578 }
bellard68a79312003-06-30 13:12:32 +0000579#endif
bellard9d050952006-05-22 22:03:52 +0000580 /* Don't use the cached interupt_request value,
581 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000582 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000583 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
584 /* ensure that no TB jump will be modified as
585 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000586 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000587 }
bellard68a79312003-06-30 13:12:32 +0000588 if (interrupt_request & CPU_INTERRUPT_EXIT) {
589 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
590 env->exception_index = EXCP_INTERRUPT;
591 cpu_loop_exit();
592 }
bellard3fb2ded2003-06-24 13:22:59 +0000593 }
594#ifdef DEBUG_EXEC
bellardb5ff1b32005-11-26 10:38:39 +0000595 if ((loglevel & CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000596 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000597 regs_to_env();
598#if defined(TARGET_I386)
bellard3fb2ded2003-06-24 13:22:59 +0000599 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
bellard7fe48482004-10-09 18:08:01 +0000600 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000601 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellarde4533c72003-06-15 19:51:39 +0000602#elif defined(TARGET_ARM)
bellard7fe48482004-10-09 18:08:01 +0000603 cpu_dump_state(env, logfile, fprintf, 0);
bellard93ac68b2003-09-30 20:57:29 +0000604#elif defined(TARGET_SPARC)
bellard34751872005-07-02 14:31:34 +0000605 REGWPTR = env->regbase + (env->cwp * 16);
606 env->regwptr = REGWPTR;
607 cpu_dump_state(env, logfile, fprintf, 0);
bellard67867302003-11-23 17:05:30 +0000608#elif defined(TARGET_PPC)
bellard7fe48482004-10-09 18:08:01 +0000609 cpu_dump_state(env, logfile, fprintf, 0);
pbrooke6e59062006-10-22 00:18:54 +0000610#elif defined(TARGET_M68K)
611 cpu_m68k_flush_flags(env, env->cc_op);
612 env->cc_op = CC_OP_FLAGS;
613 env->sr = (env->sr & 0xffe0)
614 | env->cc_dest | (env->cc_x << 4);
615 cpu_dump_state(env, logfile, fprintf, 0);
bellard6af0bf92005-07-02 14:58:51 +0000616#elif defined(TARGET_MIPS)
617 cpu_dump_state(env, logfile, fprintf, 0);
bellardfdf9b3e2006-04-27 21:07:38 +0000618#elif defined(TARGET_SH4)
619 cpu_dump_state(env, logfile, fprintf, 0);
j_mayereddf68a2007-04-05 07:22:49 +0000620#elif defined(TARGET_ALPHA)
621 cpu_dump_state(env, logfile, fprintf, 0);
thsf1ccf902007-10-08 13:16:14 +0000622#elif defined(TARGET_CRIS)
623 cpu_dump_state(env, logfile, fprintf, 0);
bellarde4533c72003-06-15 19:51:39 +0000624#else
ths5fafdf22007-09-16 21:08:06 +0000625#error unsupported target CPU
bellarde4533c72003-06-15 19:51:39 +0000626#endif
bellard3fb2ded2003-06-24 13:22:59 +0000627 }
bellard7d132992003-03-06 23:23:54 +0000628#endif
bellard8a40a182005-11-20 10:35:40 +0000629 tb = tb_find_fast();
bellard9d27abd2003-05-10 13:13:54 +0000630#ifdef DEBUG_EXEC
bellardc1135f62005-01-30 22:41:54 +0000631 if ((loglevel & CPU_LOG_EXEC)) {
bellardc27004e2005-01-03 23:35:10 +0000632 fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
633 (long)tb->tc_ptr, tb->pc,
634 lookup_symbol(tb->pc));
bellard3fb2ded2003-06-24 13:22:59 +0000635 }
bellard9d27abd2003-05-10 13:13:54 +0000636#endif
blueswir166f1cdb2007-12-11 19:39:25 +0000637 RESTORE_GLOBALS();
bellard8a40a182005-11-20 10:35:40 +0000638 /* see if we can patch the calling TB. When the TB
639 spans two pages, we cannot safely do a direct
640 jump. */
bellardc27004e2005-01-03 23:35:10 +0000641 {
blueswir1b5fc09a2008-05-04 06:38:18 +0000642 if (next_tb != 0 &&
bellardf32fc642006-02-08 22:43:39 +0000643#if USE_KQEMU
644 (env->kqemu_enabled != 2) &&
645#endif
bellardec6338b2007-11-08 14:25:03 +0000646 tb->page_addr[1] == -1) {
bellard3fb2ded2003-06-24 13:22:59 +0000647 spin_lock(&tb_lock);
blueswir1b5fc09a2008-05-04 06:38:18 +0000648 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000649 spin_unlock(&tb_lock);
650 }
bellardc27004e2005-01-03 23:35:10 +0000651 }
bellard3fb2ded2003-06-24 13:22:59 +0000652 tc_ptr = tb->tc_ptr;
bellard83479e72003-06-25 16:12:37 +0000653 env->current_tb = tb;
bellard3fb2ded2003-06-24 13:22:59 +0000654 /* execute the generated code */
655 gen_func = (void *)tc_ptr;
656#if defined(__sparc__)
657 __asm__ __volatile__("call %0\n\t"
658 "mov %%o7,%%i0"
659 : /* no outputs */
ths5fafdf22007-09-16 21:08:06 +0000660 : "r" (gen_func)
bellardfdbb4692006-06-14 17:32:25 +0000661 : "i0", "i1", "i2", "i3", "i4", "i5",
thsfaab7592007-03-19 20:39:49 +0000662 "o0", "o1", "o2", "o3", "o4", "o5",
bellardfdbb4692006-06-14 17:32:25 +0000663 "l0", "l1", "l2", "l3", "l4", "l5",
664 "l6", "l7");
aurel32f54b3f92008-04-12 20:14:54 +0000665#elif defined(__hppa__)
666 asm volatile ("ble 0(%%sr4,%1)\n"
667 "copy %%r31,%%r18\n"
668 "copy %%r28,%0\n"
blueswir1b5fc09a2008-05-04 06:38:18 +0000669 : "=r" (next_tb)
aurel32f54b3f92008-04-12 20:14:54 +0000670 : "r" (gen_func)
671 : "r1", "r2", "r3", "r4", "r5", "r6", "r7",
672 "r8", "r9", "r10", "r11", "r12", "r13",
673 "r18", "r19", "r20", "r21", "r22", "r23",
674 "r24", "r25", "r26", "r27", "r28", "r29",
675 "r30", "r31");
bellard3fb2ded2003-06-24 13:22:59 +0000676#elif defined(__arm__)
677 asm volatile ("mov pc, %0\n\t"
678 ".global exec_loop\n\t"
679 "exec_loop:\n\t"
680 : /* no outputs */
681 : "r" (gen_func)
682 : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
bellardb8076a72005-04-07 22:20:31 +0000683#elif defined(__ia64)
684 struct fptr {
685 void *ip;
686 void *gp;
687 } fp;
688
689 fp.ip = tc_ptr;
690 fp.gp = code_gen_buffer + 2 * (1 << 20);
691 (*(void (*)(void)) &fp)();
blueswir1b5fc09a2008-05-04 06:38:18 +0000692#elif defined(__i386)
693 asm volatile ("sub $12, %%esp\n\t"
694 "push %%ebp\n\t"
695 "call *%1\n\t"
696 "pop %%ebp\n\t"
697 "add $12, %%esp\n\t"
698 : "=a" (next_tb)
699 : "a" (gen_func)
700 : "ebx", "ecx", "edx", "esi", "edi", "cc",
701 "memory");
702#elif defined(__x86_64__)
703 asm volatile ("sub $8, %%rsp\n\t"
704 "push %%rbp\n\t"
705 "call *%1\n\t"
706 "pop %%rbp\n\t"
707 "add $8, %%rsp\n\t"
708 : "=a" (next_tb)
709 : "a" (gen_func)
710 : "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9",
711 "r10", "r11", "r12", "r13", "r14", "r15", "cc",
712 "memory");
bellard3fb2ded2003-06-24 13:22:59 +0000713#else
blueswir1b5fc09a2008-05-04 06:38:18 +0000714 next_tb = gen_func();
bellard3fb2ded2003-06-24 13:22:59 +0000715#endif
bellard83479e72003-06-25 16:12:37 +0000716 env->current_tb = NULL;
bellard4cbf74b2003-08-10 21:48:43 +0000717 /* reset soft MMU for next block (it can currently
718 only be set by a memory fault) */
719#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
bellard3f337312003-08-20 23:02:09 +0000720 if (env->hflags & HF_SOFTMMU_MASK) {
721 env->hflags &= ~HF_SOFTMMU_MASK;
bellard4cbf74b2003-08-10 21:48:43 +0000722 /* do not allow linking to another block */
blueswir1b5fc09a2008-05-04 06:38:18 +0000723 next_tb = 0;
bellard4cbf74b2003-08-10 21:48:43 +0000724 }
725#endif
bellardf32fc642006-02-08 22:43:39 +0000726#if defined(USE_KQEMU)
727#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
728 if (kqemu_is_ok(env) &&
729 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
730 cpu_loop_exit();
731 }
732#endif
ths50a518e2007-06-03 18:52:15 +0000733 } /* for(;;) */
bellard3fb2ded2003-06-24 13:22:59 +0000734 } else {
bellard0d1a29f2004-10-12 22:01:28 +0000735 env_to_regs();
bellard7d132992003-03-06 23:23:54 +0000736 }
bellard3fb2ded2003-06-24 13:22:59 +0000737 } /* for(;;) */
738
bellard7d132992003-03-06 23:23:54 +0000739
bellarde4533c72003-06-15 19:51:39 +0000740#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000741 /* restore flags in standard format */
bellardfc2b4c42003-03-29 16:52:44 +0000742 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000743#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000744 /* XXX: Save/restore host fpu exception state?. */
bellard93ac68b2003-09-30 20:57:29 +0000745#elif defined(TARGET_SPARC)
bellard34751872005-07-02 14:31:34 +0000746#if defined(reg_REGWPTR)
747 REGWPTR = saved_regwptr;
748#endif
bellard67867302003-11-23 17:05:30 +0000749#elif defined(TARGET_PPC)
pbrooke6e59062006-10-22 00:18:54 +0000750#elif defined(TARGET_M68K)
751 cpu_m68k_flush_flags(env, env->cc_op);
752 env->cc_op = CC_OP_FLAGS;
753 env->sr = (env->sr & 0xffe0)
754 | env->cc_dest | (env->cc_x << 4);
bellard6af0bf92005-07-02 14:58:51 +0000755#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000756#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000757#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000758#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000759 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000760#else
761#error unsupported target CPU
762#endif
pbrook1057eaa2007-02-04 13:37:44 +0000763
764 /* restore global registers */
blueswir166f1cdb2007-12-11 19:39:25 +0000765 RESTORE_GLOBALS();
pbrook1057eaa2007-02-04 13:37:44 +0000766#include "hostregs_helper.h"
767
bellard6a00d602005-11-21 23:25:50 +0000768 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000769 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000770 return ret;
771}
bellard6dbad632003-03-16 18:05:05 +0000772
bellardfbf9eeb2004-04-25 21:21:33 +0000773/* must only be called from the generated code as an exception can be
774 generated */
775void tb_invalidate_page_range(target_ulong start, target_ulong end)
776{
bellarddc5d0b32004-06-22 18:43:30 +0000777 /* XXX: cannot enable it yet because it yields to MMU exception
778 where NIP != read address on PowerPC */
779#if 0
bellardfbf9eeb2004-04-25 21:21:33 +0000780 target_ulong phys_addr;
781 phys_addr = get_phys_addr_code(env, start);
782 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
bellarddc5d0b32004-06-22 18:43:30 +0000783#endif
bellardfbf9eeb2004-04-25 21:21:33 +0000784}
785
bellard1a18c712003-10-30 01:07:51 +0000786#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
bellarde4533c72003-06-15 19:51:39 +0000787
bellard6dbad632003-03-16 18:05:05 +0000788void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
789{
790 CPUX86State *saved_env;
791
792 saved_env = env;
793 env = s;
bellarda412ac52003-07-26 18:01:40 +0000794 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
bellarda513fe12003-05-27 23:29:48 +0000795 selector &= 0xffff;
ths5fafdf22007-09-16 21:08:06 +0000796 cpu_x86_load_seg_cache(env, seg_reg, selector,
bellardc27004e2005-01-03 23:35:10 +0000797 (selector << 4), 0xffff, 0);
bellarda513fe12003-05-27 23:29:48 +0000798 } else {
bellardb453b702004-01-04 15:45:21 +0000799 load_seg(seg_reg, selector);
bellarda513fe12003-05-27 23:29:48 +0000800 }
bellard6dbad632003-03-16 18:05:05 +0000801 env = saved_env;
802}
bellard9de5e442003-03-23 16:49:39 +0000803
bellard6f12a2a2007-11-11 22:16:56 +0000804void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000805{
806 CPUX86State *saved_env;
807
808 saved_env = env;
809 env = s;
ths3b46e622007-09-17 08:09:54 +0000810
bellard6f12a2a2007-11-11 22:16:56 +0000811 helper_fsave(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000812
813 env = saved_env;
814}
815
bellard6f12a2a2007-11-11 22:16:56 +0000816void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000817{
818 CPUX86State *saved_env;
819
820 saved_env = env;
821 env = s;
ths3b46e622007-09-17 08:09:54 +0000822
bellard6f12a2a2007-11-11 22:16:56 +0000823 helper_frstor(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000824
825 env = saved_env;
826}
827
bellarde4533c72003-06-15 19:51:39 +0000828#endif /* TARGET_I386 */
829
bellard67b915a2004-03-31 23:37:16 +0000830#if !defined(CONFIG_SOFTMMU)
831
bellard3fb2ded2003-06-24 13:22:59 +0000832#if defined(TARGET_I386)
833
bellardb56dad12003-05-08 15:38:04 +0000834/* 'pc' is the host PC at which the exception was raised. 'address' is
bellardfd6ce8f2003-05-14 19:00:11 +0000835 the effective address of the memory exception. 'is_write' is 1 if a
836 write caused the exception and otherwise 0'. 'old_set' is the
837 signal set which should be restored */
bellard2b413142003-05-14 23:01:10 +0000838static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
ths5fafdf22007-09-16 21:08:06 +0000839 int is_write, sigset_t *old_set,
bellardbf3e8bf2004-02-16 21:58:54 +0000840 void *puc)
bellard9de5e442003-03-23 16:49:39 +0000841{
bellarda513fe12003-05-27 23:29:48 +0000842 TranslationBlock *tb;
843 int ret;
bellard68a79312003-06-30 13:12:32 +0000844
bellard83479e72003-06-25 16:12:37 +0000845 if (cpu_single_env)
846 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellardfd6ce8f2003-05-14 19:00:11 +0000847#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000848 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardbf3e8bf2004-02-16 21:58:54 +0000849 pc, address, is_write, *(unsigned long *)old_set);
bellard9de5e442003-03-23 16:49:39 +0000850#endif
bellard25eb4482003-05-14 21:50:54 +0000851 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000852 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardfd6ce8f2003-05-14 19:00:11 +0000853 return 1;
854 }
bellardfbf9eeb2004-04-25 21:21:33 +0000855
bellard3fb2ded2003-06-24 13:22:59 +0000856 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000857 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard3fb2ded2003-06-24 13:22:59 +0000858 if (ret < 0)
859 return 0; /* not an MMU fault */
860 if (ret == 0)
861 return 1; /* the MMU fault was handled without causing real CPU fault */
862 /* now we have a real cpu fault */
bellarda513fe12003-05-27 23:29:48 +0000863 tb = tb_find_pc(pc);
864 if (tb) {
bellard9de5e442003-03-23 16:49:39 +0000865 /* the PC is inside the translated code. It means that we have
866 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000867 cpu_restore_state(tb, env, pc, puc);
bellard3fb2ded2003-06-24 13:22:59 +0000868 }
bellard4cbf74b2003-08-10 21:48:43 +0000869 if (ret == 1) {
bellard3fb2ded2003-06-24 13:22:59 +0000870#if 0
ths5fafdf22007-09-16 21:08:06 +0000871 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
bellard4cbf74b2003-08-10 21:48:43 +0000872 env->eip, env->cr[2], env->error_code);
bellard3fb2ded2003-06-24 13:22:59 +0000873#endif
bellard4cbf74b2003-08-10 21:48:43 +0000874 /* we restore the process signal mask as the sigreturn should
875 do it (XXX: use sigsetjmp) */
876 sigprocmask(SIG_SETMASK, old_set, NULL);
bellard54ca9092005-12-04 18:46:06 +0000877 raise_exception_err(env->exception_index, env->error_code);
bellard4cbf74b2003-08-10 21:48:43 +0000878 } else {
879 /* activate soft MMU for this block */
bellard3f337312003-08-20 23:02:09 +0000880 env->hflags |= HF_SOFTMMU_MASK;
bellardfbf9eeb2004-04-25 21:21:33 +0000881 cpu_resume_from_signal(env, puc);
bellard4cbf74b2003-08-10 21:48:43 +0000882 }
bellard3fb2ded2003-06-24 13:22:59 +0000883 /* never comes here */
884 return 1;
885}
886
bellarde4533c72003-06-15 19:51:39 +0000887#elif defined(TARGET_ARM)
bellard3fb2ded2003-06-24 13:22:59 +0000888static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000889 int is_write, sigset_t *old_set,
890 void *puc)
bellard3fb2ded2003-06-24 13:22:59 +0000891{
bellard68016c62005-02-07 23:12:27 +0000892 TranslationBlock *tb;
893 int ret;
894
895 if (cpu_single_env)
896 env = cpu_single_env; /* XXX: find a correct solution for multithread */
897#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000898 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000899 pc, address, is_write, *(unsigned long *)old_set);
900#endif
bellard9f0777e2005-02-02 20:42:01 +0000901 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000902 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard9f0777e2005-02-02 20:42:01 +0000903 return 1;
904 }
bellard68016c62005-02-07 23:12:27 +0000905 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000906 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000907 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 /* now we have a real cpu fault */
912 tb = tb_find_pc(pc);
913 if (tb) {
914 /* the PC is inside the translated code. It means that we have
915 a virtual CPU fault */
916 cpu_restore_state(tb, env, pc, puc);
917 }
918 /* we restore the process signal mask as the sigreturn should
919 do it (XXX: use sigsetjmp) */
920 sigprocmask(SIG_SETMASK, old_set, NULL);
921 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000922 /* never comes here */
923 return 1;
bellard3fb2ded2003-06-24 13:22:59 +0000924}
bellard93ac68b2003-09-30 20:57:29 +0000925#elif defined(TARGET_SPARC)
926static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000927 int is_write, sigset_t *old_set,
928 void *puc)
bellard93ac68b2003-09-30 20:57:29 +0000929{
bellard68016c62005-02-07 23:12:27 +0000930 TranslationBlock *tb;
931 int ret;
932
933 if (cpu_single_env)
934 env = cpu_single_env; /* XXX: find a correct solution for multithread */
935#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000936 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000937 pc, address, is_write, *(unsigned long *)old_set);
938#endif
bellardb453b702004-01-04 15:45:21 +0000939 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000940 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardb453b702004-01-04 15:45:21 +0000941 return 1;
942 }
bellard68016c62005-02-07 23:12:27 +0000943 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000944 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000945 if (ret < 0)
946 return 0; /* not an MMU fault */
947 if (ret == 0)
948 return 1; /* the MMU fault was handled without causing real CPU fault */
949 /* now we have a real cpu fault */
950 tb = tb_find_pc(pc);
951 if (tb) {
952 /* the PC is inside the translated code. It means that we have
953 a virtual CPU fault */
954 cpu_restore_state(tb, env, pc, puc);
955 }
956 /* we restore the process signal mask as the sigreturn should
957 do it (XXX: use sigsetjmp) */
958 sigprocmask(SIG_SETMASK, old_set, NULL);
959 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000960 /* never comes here */
961 return 1;
bellard93ac68b2003-09-30 20:57:29 +0000962}
bellard67867302003-11-23 17:05:30 +0000963#elif defined (TARGET_PPC)
964static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000965 int is_write, sigset_t *old_set,
966 void *puc)
bellard67867302003-11-23 17:05:30 +0000967{
968 TranslationBlock *tb;
bellardce097762004-01-04 23:53:18 +0000969 int ret;
ths3b46e622007-09-17 08:09:54 +0000970
bellard67867302003-11-23 17:05:30 +0000971 if (cpu_single_env)
972 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellard67867302003-11-23 17:05:30 +0000973#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000974 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard67867302003-11-23 17:05:30 +0000975 pc, address, is_write, *(unsigned long *)old_set);
976#endif
977 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000978 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard67867302003-11-23 17:05:30 +0000979 return 1;
980 }
981
bellardce097762004-01-04 23:53:18 +0000982 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000983 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardce097762004-01-04 23:53:18 +0000984 if (ret < 0)
985 return 0; /* not an MMU fault */
986 if (ret == 0)
987 return 1; /* the MMU fault was handled without causing real CPU fault */
988
bellard67867302003-11-23 17:05:30 +0000989 /* now we have a real cpu fault */
990 tb = tb_find_pc(pc);
991 if (tb) {
992 /* the PC is inside the translated code. It means that we have
993 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000994 cpu_restore_state(tb, env, pc, puc);
bellard67867302003-11-23 17:05:30 +0000995 }
bellardce097762004-01-04 23:53:18 +0000996 if (ret == 1) {
bellard67867302003-11-23 17:05:30 +0000997#if 0
ths5fafdf22007-09-16 21:08:06 +0000998 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardce097762004-01-04 23:53:18 +0000999 env->nip, env->error_code, tb);
bellard67867302003-11-23 17:05:30 +00001000#endif
1001 /* we restore the process signal mask as the sigreturn should
1002 do it (XXX: use sigsetjmp) */
bellardbf3e8bf2004-02-16 21:58:54 +00001003 sigprocmask(SIG_SETMASK, old_set, NULL);
bellard9fddaa02004-05-21 12:59:32 +00001004 do_raise_exception_err(env->exception_index, env->error_code);
bellardce097762004-01-04 23:53:18 +00001005 } else {
1006 /* activate soft MMU for this block */
bellardfbf9eeb2004-04-25 21:21:33 +00001007 cpu_resume_from_signal(env, puc);
bellardce097762004-01-04 23:53:18 +00001008 }
bellard67867302003-11-23 17:05:30 +00001009 /* never comes here */
1010 return 1;
1011}
bellard6af0bf92005-07-02 14:58:51 +00001012
pbrooke6e59062006-10-22 00:18:54 +00001013#elif defined(TARGET_M68K)
1014static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1015 int is_write, sigset_t *old_set,
1016 void *puc)
1017{
1018 TranslationBlock *tb;
1019 int ret;
1020
1021 if (cpu_single_env)
1022 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1023#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001024 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pbrooke6e59062006-10-22 00:18:54 +00001025 pc, address, is_write, *(unsigned long *)old_set);
1026#endif
1027 /* XXX: locking issue */
1028 if (is_write && page_unprotect(address, pc, puc)) {
1029 return 1;
1030 }
1031 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001032 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
pbrooke6e59062006-10-22 00:18:54 +00001033 if (ret < 0)
1034 return 0; /* not an MMU fault */
1035 if (ret == 0)
1036 return 1; /* the MMU fault was handled without causing real CPU fault */
1037 /* now we have a real cpu fault */
1038 tb = tb_find_pc(pc);
1039 if (tb) {
1040 /* the PC is inside the translated code. It means that we have
1041 a virtual CPU fault */
1042 cpu_restore_state(tb, env, pc, puc);
1043 }
1044 /* we restore the process signal mask as the sigreturn should
1045 do it (XXX: use sigsetjmp) */
1046 sigprocmask(SIG_SETMASK, old_set, NULL);
1047 cpu_loop_exit();
1048 /* never comes here */
1049 return 1;
1050}
1051
bellard6af0bf92005-07-02 14:58:51 +00001052#elif defined (TARGET_MIPS)
1053static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1054 int is_write, sigset_t *old_set,
1055 void *puc)
1056{
1057 TranslationBlock *tb;
1058 int ret;
ths3b46e622007-09-17 08:09:54 +00001059
bellard6af0bf92005-07-02 14:58:51 +00001060 if (cpu_single_env)
1061 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1062#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001063 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard6af0bf92005-07-02 14:58:51 +00001064 pc, address, is_write, *(unsigned long *)old_set);
1065#endif
1066 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +00001067 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard6af0bf92005-07-02 14:58:51 +00001068 return 1;
1069 }
1070
1071 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001072 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard6af0bf92005-07-02 14:58:51 +00001073 if (ret < 0)
1074 return 0; /* not an MMU fault */
1075 if (ret == 0)
1076 return 1; /* the MMU fault was handled without causing real CPU fault */
1077
1078 /* now we have a real cpu fault */
1079 tb = tb_find_pc(pc);
1080 if (tb) {
1081 /* the PC is inside the translated code. It means that we have
1082 a virtual CPU fault */
1083 cpu_restore_state(tb, env, pc, puc);
1084 }
1085 if (ret == 1) {
1086#if 0
ths5fafdf22007-09-16 21:08:06 +00001087 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
ths1eb52072007-05-12 16:57:42 +00001088 env->PC, env->error_code, tb);
bellard6af0bf92005-07-02 14:58:51 +00001089#endif
1090 /* we restore the process signal mask as the sigreturn should
1091 do it (XXX: use sigsetjmp) */
1092 sigprocmask(SIG_SETMASK, old_set, NULL);
1093 do_raise_exception_err(env->exception_index, env->error_code);
1094 } else {
1095 /* activate soft MMU for this block */
1096 cpu_resume_from_signal(env, puc);
1097 }
1098 /* never comes here */
1099 return 1;
1100}
1101
bellardfdf9b3e2006-04-27 21:07:38 +00001102#elif defined (TARGET_SH4)
1103static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1104 int is_write, sigset_t *old_set,
1105 void *puc)
1106{
1107 TranslationBlock *tb;
1108 int ret;
ths3b46e622007-09-17 08:09:54 +00001109
bellardfdf9b3e2006-04-27 21:07:38 +00001110 if (cpu_single_env)
1111 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1112#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001113 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001114 pc, address, is_write, *(unsigned long *)old_set);
1115#endif
1116 /* XXX: locking issue */
1117 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1118 return 1;
1119 }
1120
1121 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001122 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00001123 if (ret < 0)
1124 return 0; /* not an MMU fault */
1125 if (ret == 0)
1126 return 1; /* the MMU fault was handled without causing real CPU fault */
1127
1128 /* now we have a real cpu fault */
1129 tb = tb_find_pc(pc);
1130 if (tb) {
1131 /* the PC is inside the translated code. It means that we have
1132 a virtual CPU fault */
1133 cpu_restore_state(tb, env, pc, puc);
1134 }
bellardfdf9b3e2006-04-27 21:07:38 +00001135#if 0
ths5fafdf22007-09-16 21:08:06 +00001136 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001137 env->nip, env->error_code, tb);
1138#endif
1139 /* we restore the process signal mask as the sigreturn should
1140 do it (XXX: use sigsetjmp) */
pbrook355fb232006-06-17 19:58:25 +00001141 sigprocmask(SIG_SETMASK, old_set, NULL);
1142 cpu_loop_exit();
bellardfdf9b3e2006-04-27 21:07:38 +00001143 /* never comes here */
1144 return 1;
1145}
j_mayereddf68a2007-04-05 07:22:49 +00001146
1147#elif defined (TARGET_ALPHA)
1148static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1149 int is_write, sigset_t *old_set,
1150 void *puc)
1151{
1152 TranslationBlock *tb;
1153 int ret;
ths3b46e622007-09-17 08:09:54 +00001154
j_mayereddf68a2007-04-05 07:22:49 +00001155 if (cpu_single_env)
1156 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1157#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001158 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
j_mayereddf68a2007-04-05 07:22:49 +00001159 pc, address, is_write, *(unsigned long *)old_set);
1160#endif
1161 /* XXX: locking issue */
1162 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1163 return 1;
1164 }
1165
1166 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001167 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
j_mayereddf68a2007-04-05 07:22:49 +00001168 if (ret < 0)
1169 return 0; /* not an MMU fault */
1170 if (ret == 0)
1171 return 1; /* the MMU fault was handled without causing real CPU fault */
1172
1173 /* now we have a real cpu fault */
1174 tb = tb_find_pc(pc);
1175 if (tb) {
1176 /* the PC is inside the translated code. It means that we have
1177 a virtual CPU fault */
1178 cpu_restore_state(tb, env, pc, puc);
1179 }
1180#if 0
ths5fafdf22007-09-16 21:08:06 +00001181 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
j_mayereddf68a2007-04-05 07:22:49 +00001182 env->nip, env->error_code, tb);
1183#endif
1184 /* we restore the process signal mask as the sigreturn should
1185 do it (XXX: use sigsetjmp) */
1186 sigprocmask(SIG_SETMASK, old_set, NULL);
1187 cpu_loop_exit();
1188 /* never comes here */
1189 return 1;
1190}
thsf1ccf902007-10-08 13:16:14 +00001191#elif defined (TARGET_CRIS)
1192static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1193 int is_write, sigset_t *old_set,
1194 void *puc)
1195{
1196 TranslationBlock *tb;
1197 int ret;
1198
1199 if (cpu_single_env)
1200 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1201#if defined(DEBUG_SIGNAL)
1202 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1203 pc, address, is_write, *(unsigned long *)old_set);
1204#endif
1205 /* XXX: locking issue */
1206 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1207 return 1;
1208 }
1209
1210 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001211 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
thsf1ccf902007-10-08 13:16:14 +00001212 if (ret < 0)
1213 return 0; /* not an MMU fault */
1214 if (ret == 0)
1215 return 1; /* the MMU fault was handled without causing real CPU fault */
1216
1217 /* now we have a real cpu fault */
1218 tb = tb_find_pc(pc);
1219 if (tb) {
1220 /* the PC is inside the translated code. It means that we have
1221 a virtual CPU fault */
1222 cpu_restore_state(tb, env, pc, puc);
1223 }
thsf1ccf902007-10-08 13:16:14 +00001224 /* we restore the process signal mask as the sigreturn should
1225 do it (XXX: use sigsetjmp) */
1226 sigprocmask(SIG_SETMASK, old_set, NULL);
1227 cpu_loop_exit();
1228 /* never comes here */
1229 return 1;
1230}
1231
bellarde4533c72003-06-15 19:51:39 +00001232#else
1233#error unsupported target CPU
1234#endif
bellard9de5e442003-03-23 16:49:39 +00001235
bellard2b413142003-05-14 23:01:10 +00001236#if defined(__i386__)
1237
bellardd8ecc0b2007-02-05 21:41:46 +00001238#if defined(__APPLE__)
1239# include <sys/ucontext.h>
1240
1241# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1242# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1243# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
1244#else
1245# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1246# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1247# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1248#endif
1249
ths5fafdf22007-09-16 21:08:06 +00001250int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001251 void *puc)
bellard9de5e442003-03-23 16:49:39 +00001252{
ths5a7b5422007-01-31 12:16:51 +00001253 siginfo_t *info = pinfo;
bellard9de5e442003-03-23 16:49:39 +00001254 struct ucontext *uc = puc;
1255 unsigned long pc;
bellardbf3e8bf2004-02-16 21:58:54 +00001256 int trapno;
bellard97eb5b12004-02-25 23:19:55 +00001257
bellardd691f662003-03-24 21:58:34 +00001258#ifndef REG_EIP
1259/* for glibc 2.1 */
bellardfd6ce8f2003-05-14 19:00:11 +00001260#define REG_EIP EIP
1261#define REG_ERR ERR
1262#define REG_TRAPNO TRAPNO
bellardd691f662003-03-24 21:58:34 +00001263#endif
bellardd8ecc0b2007-02-05 21:41:46 +00001264 pc = EIP_sig(uc);
1265 trapno = TRAP_sig(uc);
bellardec6338b2007-11-08 14:25:03 +00001266 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1267 trapno == 0xe ?
1268 (ERROR_sig(uc) >> 1) & 1 : 0,
1269 &uc->uc_sigmask, puc);
bellard2b413142003-05-14 23:01:10 +00001270}
1271
bellardbc51c5c2004-03-17 23:46:04 +00001272#elif defined(__x86_64__)
1273
ths5a7b5422007-01-31 12:16:51 +00001274int cpu_signal_handler(int host_signum, void *pinfo,
bellardbc51c5c2004-03-17 23:46:04 +00001275 void *puc)
1276{
ths5a7b5422007-01-31 12:16:51 +00001277 siginfo_t *info = pinfo;
bellardbc51c5c2004-03-17 23:46:04 +00001278 struct ucontext *uc = puc;
1279 unsigned long pc;
1280
1281 pc = uc->uc_mcontext.gregs[REG_RIP];
ths5fafdf22007-09-16 21:08:06 +00001282 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1283 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
bellardbc51c5c2004-03-17 23:46:04 +00001284 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1285 &uc->uc_sigmask, puc);
1286}
1287
bellard83fb7ad2004-07-05 21:25:26 +00001288#elif defined(__powerpc__)
bellard2b413142003-05-14 23:01:10 +00001289
bellard83fb7ad2004-07-05 21:25:26 +00001290/***********************************************************************
1291 * signal context platform-specific definitions
1292 * From Wine
1293 */
1294#ifdef linux
1295/* All Registers access - only for local access */
1296# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1297/* Gpr Registers access */
1298# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1299# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1300# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1301# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1302# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1303# define LR_sig(context) REG_sig(link, context) /* Link register */
1304# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1305/* Float Registers access */
1306# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1307# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1308/* Exception Registers access */
1309# define DAR_sig(context) REG_sig(dar, context)
1310# define DSISR_sig(context) REG_sig(dsisr, context)
1311# define TRAP_sig(context) REG_sig(trap, context)
1312#endif /* linux */
1313
1314#ifdef __APPLE__
1315# include <sys/ucontext.h>
1316typedef struct ucontext SIGCONTEXT;
1317/* All Registers access - only for local access */
1318# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1319# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1320# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1321# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1322/* Gpr Registers access */
1323# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1324# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1325# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1326# define CTR_sig(context) REG_sig(ctr, context)
1327# define XER_sig(context) REG_sig(xer, context) /* Link register */
1328# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1329# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1330/* Float Registers access */
1331# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1332# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1333/* Exception Registers access */
1334# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1335# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1336# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1337#endif /* __APPLE__ */
1338
ths5fafdf22007-09-16 21:08:06 +00001339int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001340 void *puc)
bellard2b413142003-05-14 23:01:10 +00001341{
ths5a7b5422007-01-31 12:16:51 +00001342 siginfo_t *info = pinfo;
bellard25eb4482003-05-14 21:50:54 +00001343 struct ucontext *uc = puc;
bellard25eb4482003-05-14 21:50:54 +00001344 unsigned long pc;
bellard25eb4482003-05-14 21:50:54 +00001345 int is_write;
1346
bellard83fb7ad2004-07-05 21:25:26 +00001347 pc = IAR_sig(uc);
bellard25eb4482003-05-14 21:50:54 +00001348 is_write = 0;
1349#if 0
1350 /* ppc 4xx case */
bellard83fb7ad2004-07-05 21:25:26 +00001351 if (DSISR_sig(uc) & 0x00800000)
bellard25eb4482003-05-14 21:50:54 +00001352 is_write = 1;
bellard9de5e442003-03-23 16:49:39 +00001353#else
bellard83fb7ad2004-07-05 21:25:26 +00001354 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
bellard25eb4482003-05-14 21:50:54 +00001355 is_write = 1;
1356#endif
ths5fafdf22007-09-16 21:08:06 +00001357 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001358 is_write, &uc->uc_sigmask, puc);
bellard9de5e442003-03-23 16:49:39 +00001359}
bellard2b413142003-05-14 23:01:10 +00001360
bellard2f87c602003-06-02 20:38:09 +00001361#elif defined(__alpha__)
1362
ths5fafdf22007-09-16 21:08:06 +00001363int cpu_signal_handler(int host_signum, void *pinfo,
bellard2f87c602003-06-02 20:38:09 +00001364 void *puc)
1365{
ths5a7b5422007-01-31 12:16:51 +00001366 siginfo_t *info = pinfo;
bellard2f87c602003-06-02 20:38:09 +00001367 struct ucontext *uc = puc;
1368 uint32_t *pc = uc->uc_mcontext.sc_pc;
1369 uint32_t insn = *pc;
1370 int is_write = 0;
1371
bellard8c6939c2003-06-09 15:28:00 +00001372 /* XXX: need kernel patch to get write flag faster */
bellard2f87c602003-06-02 20:38:09 +00001373 switch (insn >> 26) {
1374 case 0x0d: // stw
1375 case 0x0e: // stb
1376 case 0x0f: // stq_u
1377 case 0x24: // stf
1378 case 0x25: // stg
1379 case 0x26: // sts
1380 case 0x27: // stt
1381 case 0x2c: // stl
1382 case 0x2d: // stq
1383 case 0x2e: // stl_c
1384 case 0x2f: // stq_c
1385 is_write = 1;
1386 }
1387
ths5fafdf22007-09-16 21:08:06 +00001388 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001389 is_write, &uc->uc_sigmask, puc);
bellard2f87c602003-06-02 20:38:09 +00001390}
bellard8c6939c2003-06-09 15:28:00 +00001391#elif defined(__sparc__)
1392
ths5fafdf22007-09-16 21:08:06 +00001393int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001394 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001395{
ths5a7b5422007-01-31 12:16:51 +00001396 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001397 uint32_t *regs = (uint32_t *)(info + 1);
1398 void *sigmask = (regs + 20);
1399 unsigned long pc;
1400 int is_write;
1401 uint32_t insn;
ths3b46e622007-09-17 08:09:54 +00001402
bellard8c6939c2003-06-09 15:28:00 +00001403 /* XXX: is there a standard glibc define ? */
1404 pc = regs[1];
1405 /* XXX: need kernel patch to get write flag faster */
1406 is_write = 0;
1407 insn = *(uint32_t *)pc;
1408 if ((insn >> 30) == 3) {
1409 switch((insn >> 19) & 0x3f) {
1410 case 0x05: // stb
1411 case 0x06: // sth
1412 case 0x04: // st
1413 case 0x07: // std
1414 case 0x24: // stf
1415 case 0x27: // stdf
1416 case 0x25: // stfsr
1417 is_write = 1;
1418 break;
1419 }
1420 }
ths5fafdf22007-09-16 21:08:06 +00001421 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001422 is_write, sigmask, NULL);
bellard8c6939c2003-06-09 15:28:00 +00001423}
1424
1425#elif defined(__arm__)
1426
ths5fafdf22007-09-16 21:08:06 +00001427int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001428 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001429{
ths5a7b5422007-01-31 12:16:51 +00001430 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001431 struct ucontext *uc = puc;
1432 unsigned long pc;
1433 int is_write;
ths3b46e622007-09-17 08:09:54 +00001434
balrog4eee57f2008-05-06 14:47:19 +00001435 pc = uc->uc_mcontext.arm_pc;
bellard8c6939c2003-06-09 15:28:00 +00001436 /* XXX: compute is_write */
1437 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001438 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard8c6939c2003-06-09 15:28:00 +00001439 is_write,
pbrookf3a96762006-07-29 19:09:31 +00001440 &uc->uc_sigmask, puc);
bellard8c6939c2003-06-09 15:28:00 +00001441}
1442
bellard38e584a2003-08-10 22:14:22 +00001443#elif defined(__mc68000)
1444
ths5fafdf22007-09-16 21:08:06 +00001445int cpu_signal_handler(int host_signum, void *pinfo,
bellard38e584a2003-08-10 22:14:22 +00001446 void *puc)
1447{
ths5a7b5422007-01-31 12:16:51 +00001448 siginfo_t *info = pinfo;
bellard38e584a2003-08-10 22:14:22 +00001449 struct ucontext *uc = puc;
1450 unsigned long pc;
1451 int is_write;
ths3b46e622007-09-17 08:09:54 +00001452
bellard38e584a2003-08-10 22:14:22 +00001453 pc = uc->uc_mcontext.gregs[16];
1454 /* XXX: compute is_write */
1455 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001456 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard38e584a2003-08-10 22:14:22 +00001457 is_write,
bellardbf3e8bf2004-02-16 21:58:54 +00001458 &uc->uc_sigmask, puc);
bellard38e584a2003-08-10 22:14:22 +00001459}
1460
bellardb8076a72005-04-07 22:20:31 +00001461#elif defined(__ia64)
1462
1463#ifndef __ISR_VALID
1464 /* This ought to be in <bits/siginfo.h>... */
1465# define __ISR_VALID 1
bellardb8076a72005-04-07 22:20:31 +00001466#endif
1467
ths5a7b5422007-01-31 12:16:51 +00001468int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
bellardb8076a72005-04-07 22:20:31 +00001469{
ths5a7b5422007-01-31 12:16:51 +00001470 siginfo_t *info = pinfo;
bellardb8076a72005-04-07 22:20:31 +00001471 struct ucontext *uc = puc;
1472 unsigned long ip;
1473 int is_write = 0;
1474
1475 ip = uc->uc_mcontext.sc_ip;
1476 switch (host_signum) {
1477 case SIGILL:
1478 case SIGFPE:
1479 case SIGSEGV:
1480 case SIGBUS:
1481 case SIGTRAP:
bellardfd4a43e2006-04-24 20:32:17 +00001482 if (info->si_code && (info->si_segvflags & __ISR_VALID))
bellardb8076a72005-04-07 22:20:31 +00001483 /* ISR.W (write-access) is bit 33: */
1484 is_write = (info->si_isr >> 33) & 1;
1485 break;
1486
1487 default:
1488 break;
1489 }
1490 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1491 is_write,
1492 &uc->uc_sigmask, puc);
1493}
1494
bellard90cb9492005-07-24 15:11:38 +00001495#elif defined(__s390__)
1496
ths5fafdf22007-09-16 21:08:06 +00001497int cpu_signal_handler(int host_signum, void *pinfo,
bellard90cb9492005-07-24 15:11:38 +00001498 void *puc)
1499{
ths5a7b5422007-01-31 12:16:51 +00001500 siginfo_t *info = pinfo;
bellard90cb9492005-07-24 15:11:38 +00001501 struct ucontext *uc = puc;
1502 unsigned long pc;
1503 int is_write;
ths3b46e622007-09-17 08:09:54 +00001504
bellard90cb9492005-07-24 15:11:38 +00001505 pc = uc->uc_mcontext.psw.addr;
1506 /* XXX: compute is_write */
1507 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001508 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001509 is_write, &uc->uc_sigmask, puc);
1510}
1511
1512#elif defined(__mips__)
1513
ths5fafdf22007-09-16 21:08:06 +00001514int cpu_signal_handler(int host_signum, void *pinfo,
thsc4b89d12007-05-05 19:23:11 +00001515 void *puc)
1516{
ths9617efe2007-05-08 21:05:55 +00001517 siginfo_t *info = pinfo;
thsc4b89d12007-05-05 19:23:11 +00001518 struct ucontext *uc = puc;
1519 greg_t pc = uc->uc_mcontext.pc;
1520 int is_write;
ths3b46e622007-09-17 08:09:54 +00001521
thsc4b89d12007-05-05 19:23:11 +00001522 /* XXX: compute is_write */
1523 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001524 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001525 is_write, &uc->uc_sigmask, puc);
bellard90cb9492005-07-24 15:11:38 +00001526}
1527
aurel32f54b3f92008-04-12 20:14:54 +00001528#elif defined(__hppa__)
1529
1530int cpu_signal_handler(int host_signum, void *pinfo,
1531 void *puc)
1532{
1533 struct siginfo *info = pinfo;
1534 struct ucontext *uc = puc;
1535 unsigned long pc;
1536 int is_write;
1537
1538 pc = uc->uc_mcontext.sc_iaoq[0];
1539 /* FIXME: compute is_write */
1540 is_write = 0;
1541 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1542 is_write,
1543 &uc->uc_sigmask, puc);
1544}
1545
bellard2b413142003-05-14 23:01:10 +00001546#else
1547
bellard3fb2ded2003-06-24 13:22:59 +00001548#error host CPU specific signal handler needed
bellard2b413142003-05-14 23:01:10 +00001549
1550#endif
bellard67b915a2004-03-31 23:37:16 +00001551
1552#endif /* !defined(CONFIG_SOFTMMU) */