VirtualBox

source: vbox/trunk/src/recompiler/new/cpu-exec.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
File size: 71.4 KB
Line 
1/*
2 * i386 emulator main execution loop
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
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.
10 *
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.
15 *
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
19 */
20#include "config.h"
21#include "exec.h"
22#include "disas.h"
23
24#if !defined(CONFIG_SOFTMMU)
25#undef EAX
26#undef ECX
27#undef EDX
28#undef EBX
29#undef ESP
30#undef EBP
31#undef ESI
32#undef EDI
33#undef EIP
34#include <signal.h>
35#include <sys/ucontext.h>
36#endif
37
38int tb_invalidated_flag;
39
40//#define DEBUG_EXEC
41//#define DEBUG_SIGNAL
42
43#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
44/* XXX: unify with i386 target */
45void cpu_loop_exit(void)
46{
47 longjmp(env->jmp_env, 1);
48}
49#endif
50#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
51#define reg_T2
52#endif
53
54/* exit the current TB from a signal handler. The host registers are
55 restored in a state compatible with the CPU emulator
56 */
57void cpu_resume_from_signal(CPUState *env1, void *puc)
58{
59#if !defined(CONFIG_SOFTMMU)
60 struct ucontext *uc = puc;
61#endif
62
63 env = env1;
64
65 /* XXX: restore cpu registers saved in host registers */
66
67#if !defined(CONFIG_SOFTMMU)
68 if (puc) {
69 /* XXX: use siglongjmp ? */
70 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
71 }
72#endif
73 longjmp(env->jmp_env, 1);
74}
75
76
77static TranslationBlock *tb_find_slow(target_ulong pc,
78 target_ulong cs_base,
79 unsigned int flags)
80{
81 TranslationBlock *tb, **ptb1;
82 int code_gen_size;
83 unsigned int h;
84 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
85 uint8_t *tc_ptr;
86
87 spin_lock(&tb_lock);
88
89 tb_invalidated_flag = 0;
90
91 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
92
93 /* find translated block using physical mappings */
94 phys_pc = get_phys_addr_code(env, pc);
95 phys_page1 = phys_pc & TARGET_PAGE_MASK;
96 phys_page2 = -1;
97 h = tb_phys_hash_func(phys_pc);
98 ptb1 = &tb_phys_hash[h];
99 for(;;) {
100 tb = *ptb1;
101 if (!tb)
102 goto not_found;
103 if (tb->pc == pc &&
104 tb->page_addr[0] == phys_page1 &&
105 tb->cs_base == cs_base &&
106 tb->flags == flags) {
107 /* check next page if needed */
108 if (tb->page_addr[1] != -1) {
109 virt_page2 = (pc & TARGET_PAGE_MASK) +
110 TARGET_PAGE_SIZE;
111 phys_page2 = get_phys_addr_code(env, virt_page2);
112 if (tb->page_addr[1] == phys_page2)
113 goto found;
114 } else {
115 goto found;
116 }
117 }
118 ptb1 = &tb->phys_hash_next;
119 }
120 not_found:
121 /* if no translated code available, then translate it now */
122 tb = tb_alloc(pc);
123 if (!tb) {
124 /* flush must be done */
125 tb_flush(env);
126 /* cannot fail at this point */
127 tb = tb_alloc(pc);
128 /* don't forget to invalidate previous TB info */
129 tb_invalidated_flag = 1;
130 }
131 tc_ptr = code_gen_ptr;
132 tb->tc_ptr = tc_ptr;
133 tb->cs_base = cs_base;
134 tb->flags = flags;
135 cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
136 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
137
138 /* check next page if needed */
139 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
140 phys_page2 = -1;
141 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
142 phys_page2 = get_phys_addr_code(env, virt_page2);
143 }
144 tb_link_phys(tb, phys_pc, phys_page2);
145
146 found:
147 /* we add the TB in the virtual pc hash table */
148 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
149 spin_unlock(&tb_lock);
150 return tb;
151}
152
153static inline TranslationBlock *tb_find_fast(void)
154{
155 TranslationBlock *tb;
156 target_ulong cs_base, pc;
157 unsigned int flags;
158
159 /* we record a subset of the CPU state. It will
160 always be the same before a given translated block
161 is executed. */
162#if defined(TARGET_I386)
163 flags = env->hflags;
164 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
165 cs_base = env->segs[R_CS].base;
166 pc = cs_base + env->eip;
167#elif defined(TARGET_ARM)
168 flags = env->thumb | (env->vfp.vec_len << 1)
169 | (env->vfp.vec_stride << 4);
170 if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
171 flags |= (1 << 6);
172 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
173 flags |= (1 << 7);
174 cs_base = 0;
175 pc = env->regs[15];
176#elif defined(TARGET_SPARC)
177#ifdef TARGET_SPARC64
178 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
179 flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
180 | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
181#else
182 // FPU enable . MMU enabled . MMU no-fault . Supervisor
183 flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
184 | env->psrs;
185#endif
186 cs_base = env->npc;
187 pc = env->pc;
188#elif defined(TARGET_PPC)
189 flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
190 (msr_se << MSR_SE) | (msr_le << MSR_LE);
191 cs_base = 0;
192 pc = env->nip;
193#elif defined(TARGET_MIPS)
194 flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
195 cs_base = 0;
196 pc = env->PC;
197#elif defined(TARGET_M68K)
198 flags = env->fpcr & M68K_FPCR_PREC;
199 cs_base = 0;
200 pc = env->pc;
201#elif defined(TARGET_SH4)
202 flags = env->sr & (SR_MD | SR_RB);
203 cs_base = 0; /* XXXXX */
204 pc = env->pc;
205#else
206#error unsupported CPU
207#endif
208 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
209 if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
210 tb->flags != flags, 0)) {
211 tb = tb_find_slow(pc, cs_base, flags);
212 /* Note: we do it here to avoid a gcc bug on Mac OS X when
213 doing it in tb_find_slow */
214 if (tb_invalidated_flag) {
215 /* as some TB could have been invalidated because
216 of memory exceptions while generating the code, we
217 must recompute the hash index here */
218 T0 = 0;
219 }
220 }
221 return tb;
222}
223
224
225/* main execution loop */
226
227#ifdef VBOX
228
229int cpu_exec(CPUState *env1)
230{
231 int saved_T0, saved_T1, saved_T2;
232 CPUState *saved_env;
233#ifdef reg_EAX
234 int saved_EAX;
235#endif
236#ifdef reg_ECX
237 int saved_ECX;
238#endif
239#ifdef reg_EDX
240 int saved_EDX;
241#endif
242#ifdef reg_EBX
243 int saved_EBX;
244#endif
245#ifdef reg_ESP
246 int saved_ESP;
247#endif
248#ifdef reg_EBP
249 int saved_EBP;
250#endif
251#ifdef reg_ESI
252 int saved_ESI;
253#endif
254#ifdef reg_EDI
255 int saved_EDI;
256#endif
257#if defined(__sparc__) && !defined(HOST_SOLARIS)
258 int saved_i7, tmp_T0;
259#endif
260 int ret, interrupt_request;
261 void (*gen_func)(void);
262 TranslationBlock *tb;
263 uint8_t *tc_ptr;
264
265#if defined(TARGET_I386)
266 /* handle exit of HALTED state */
267 if (env1->hflags & HF_HALTED_MASK) {
268 /* disable halt condition */
269 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
270 (env1->eflags & IF_MASK)) {
271 env1->hflags &= ~HF_HALTED_MASK;
272 } else {
273 return EXCP_HALTED;
274 }
275 }
276#elif defined(TARGET_PPC)
277 if (env1->halted) {
278 if (env1->msr[MSR_EE] &&
279 (env1->interrupt_request &
280 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
281 env1->halted = 0;
282 } else {
283 return EXCP_HALTED;
284 }
285 }
286#elif defined(TARGET_SPARC)
287 if (env1->halted) {
288 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
289 (env1->psret != 0)) {
290 env1->halted = 0;
291 } else {
292 return EXCP_HALTED;
293 }
294 }
295#elif defined(TARGET_ARM)
296 if (env1->halted) {
297 /* An interrupt wakes the CPU even if the I and F CPSR bits are
298 set. */
299 if (env1->interrupt_request
300 & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
301 env1->halted = 0;
302 } else {
303 return EXCP_HALTED;
304 }
305 }
306#elif defined(TARGET_MIPS)
307 if (env1->halted) {
308 if (env1->interrupt_request &
309 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
310 env1->halted = 0;
311 } else {
312 return EXCP_HALTED;
313 }
314 }
315#endif
316
317 cpu_single_env = env1;
318
319 /* first we save global registers */
320 saved_env = env;
321 env = env1;
322 saved_T0 = T0;
323 saved_T1 = T1;
324#if defined(reg_T2)
325 saved_T2 = T2;
326#endif
327#if defined(__sparc__) && !defined(HOST_SOLARIS)
328 /* we also save i7 because longjmp may not restore it */
329 asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
330#endif
331
332#if defined(TARGET_I386)
333#ifdef reg_EAX
334 saved_EAX = EAX;
335#endif
336#ifdef reg_ECX
337 saved_ECX = ECX;
338#endif
339#ifdef reg_EDX
340 saved_EDX = EDX;
341#endif
342#ifdef reg_EBX
343 saved_EBX = EBX;
344#endif
345#ifdef reg_ESP
346 saved_ESP = ESP;
347#endif
348#ifdef reg_EBP
349 saved_EBP = EBP;
350#endif
351#ifdef reg_ESI
352 saved_ESI = ESI;
353#endif
354#ifdef reg_EDI
355 saved_EDI = EDI;
356#endif
357
358 env_to_regs();
359 /* put eflags in CPU temporary format */
360 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
361 DF = 1 - (2 * ((env->eflags >> 10) & 1));
362 CC_OP = CC_OP_EFLAGS;
363 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
364#elif defined(TARGET_ARM)
365#elif defined(TARGET_SPARC)
366#if defined(reg_REGWPTR)
367 saved_regwptr = REGWPTR;
368#endif
369#elif defined(TARGET_PPC)
370#elif defined(TARGET_MIPS)
371#elif defined(TARGET_SH4)
372 /* XXXXX */
373#else
374#error unsupported target CPU
375#endif
376#ifndef VBOX /* VBOX: We need to raise traps and suchlike from the outside. */
377 env->exception_index = -1;
378#endif
379
380 /* prepare setjmp context for exception handling */
381 for(;;) {
382 if (setjmp(env->jmp_env) == 0)
383 {
384 env->current_tb = NULL;
385 VMMR3Unlock(env->pVM);
386 VMMR3Lock(env->pVM);
387
388 /*
389 * Check for fatal errors first
390 */
391 if (env->interrupt_request & CPU_INTERRUPT_RC) {
392 env->exception_index = EXCP_RC;
393 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC);
394 ret = env->exception_index;
395 cpu_loop_exit();
396 }
397
398 /* if an exception is pending, we execute it here */
399 if (env->exception_index >= 0) {
400 Assert(!env->user_mode_only);
401 if (env->exception_index >= EXCP_INTERRUPT) {
402 /* exit request from the cpu execution loop */
403 ret = env->exception_index;
404 break;
405 } else {
406 /* simulate a real cpu exception. On i386, it can
407 trigger new exceptions, but we do not handle
408 double or triple faults yet. */
409 RAWEx_ProfileStart(env, STATS_IRQ_HANDLING);
410 Log(("do_interrupt %d %d %08x\n", env->exception_index, env->exception_is_int, env->exception_next_eip));
411 do_interrupt(env->exception_index,
412 env->exception_is_int,
413 env->error_code,
414 env->exception_next_eip, 0);
415 RAWEx_ProfileStop(env, STATS_IRQ_HANDLING);
416 }
417 env->exception_index = -1;
418 }
419
420 T0 = 0; /* force lookup of first TB */
421 for(;;)
422 {
423 interrupt_request = env->interrupt_request;
424 if (__builtin_expect(interrupt_request, 0))
425 {
426 /* Single instruction exec request, we execute it and return (one way or the other).
427 The caller will always reschedule after doing this operation! */
428 if (interrupt_request & CPU_INTERRUPT_SINGLE_INSTR)
429 {
430 /* not in flight are we? (if we are, we trapped) */
431 if (!(env->interrupt_request & CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT))
432 {
433 ASMAtomicOrS32(&env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT);
434 env->exception_index = EXCP_SINGLE_INSTR;
435 if (emulate_single_instr(env) == -1)
436 AssertMsgFailed(("REM: emulate_single_instr failed for EIP=%08x!!\n", env->eip));
437
438 /* When we receive an external interrupt during execution of this single
439 instruction, then we should stay here. We will leave when we're ready
440 for raw-mode or when interrupted by pending EMT requests. */
441 interrupt_request = env->interrupt_request; /* reload this! */
442 if ( !(interrupt_request & CPU_INTERRUPT_HARD)
443 || !(env->eflags & IF_MASK)
444 || (env->hflags & HF_INHIBIT_IRQ_MASK)
445 || (env->state & CPU_RAW_HWACC)
446 )
447 {
448 env->exception_index = ret = EXCP_SINGLE_INSTR;
449 cpu_loop_exit();
450 }
451 }
452 /* Clear CPU_INTERRUPT_SINGLE_INSTR and leave CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT set. */
453 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_SINGLE_INSTR);
454 }
455
456 RAWEx_ProfileStart(env, STATS_IRQ_HANDLING);
457 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
458 !(env->hflags & HF_SMM_MASK)) {
459 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
460 do_smm_enter();
461 T0 = 0;
462 }
463 else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
464 (env->eflags & IF_MASK) &&
465 !(env->hflags & HF_INHIBIT_IRQ_MASK))
466 {
467 /* if hardware interrupt pending, we execute it */
468 int intno;
469 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_HARD);
470 intno = cpu_get_pic_interrupt(env);
471 if (intno >= 0)
472 {
473 Log(("do_interrupt %d\n", intno));
474 do_interrupt(intno, 0, 0, 0, 1);
475 }
476 /* ensure that no TB jump will be modified as
477 the program flow was changed */
478 T0 = 0;
479 }
480 if (env->interrupt_request & CPU_INTERRUPT_EXITTB)
481 {
482 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_EXITTB);
483 /* ensure that no TB jump will be modified as
484 the program flow was changed */
485 T0 = 0;
486 }
487 RAWEx_ProfileStop(env, STATS_IRQ_HANDLING);
488 if (interrupt_request & CPU_INTERRUPT_EXIT)
489 {
490 env->exception_index = EXCP_INTERRUPT;
491 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_EXIT);
492 ret = env->exception_index;
493 cpu_loop_exit();
494 }
495 if (interrupt_request & CPU_INTERRUPT_RC)
496 {
497 env->exception_index = EXCP_RC;
498 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC);
499 ret = env->exception_index;
500 cpu_loop_exit();
501 }
502 }
503
504 /*
505 * Check if we the CPU state allows us to execute the code in raw-mode.
506 */
507 RAWEx_ProfileStart(env, STATS_RAW_CHECK);
508 if (remR3CanExecuteRaw(env,
509 env->eip + env->segs[R_CS].base,
510 env->hflags | (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)),
511 &env->exception_index))
512 {
513 RAWEx_ProfileStop(env, STATS_RAW_CHECK);
514 ret = env->exception_index;
515 cpu_loop_exit();
516 }
517 RAWEx_ProfileStop(env, STATS_RAW_CHECK);
518
519 RAWEx_ProfileStart(env, STATS_TLB_LOOKUP);
520 tb = tb_find_fast();
521
522 /* see if we can patch the calling TB. When the TB
523 spans two pages, we cannot safely do a direct
524 jump. */
525 if (T0 != 0
526 && !(tb->cflags & CF_RAW_MODE)
527 && tb->page_addr[1] == -1)
528 {
529 spin_lock(&tb_lock);
530 tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
531 spin_unlock(&tb_lock);
532 }
533 tc_ptr = tb->tc_ptr;
534 env->current_tb = tb;
535 /* execute the generated code */
536 gen_func = (void *)tc_ptr;
537 RAWEx_ProfileStop(env, STATS_TLB_LOOKUP);
538
539#if defined(DEBUG) && defined(VBOX) && !defined(DEBUG_dmik)
540#if !defined(DEBUG_bird)
541 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 0 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK))
542 {
543 if(!(env->state & CPU_EMULATE_SINGLE_STEP))
544 {
545 Log(("EMR0: %08X ESP=%08X IF=%d TF=%d CPL=%d\n", env->eip, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3));
546 }
547 }
548 else
549 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 3 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK))
550 {
551 if(!(env->state & CPU_EMULATE_SINGLE_STEP))
552 {
553 if(env->eflags & VM_MASK)
554 {
555 Log(("EMV86: %08X IF=%d TF=%d CPL=%d CR0=%08X\n", env->eip, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, env->cr[0]));
556 }
557 else
558 {
559 Log(("EMR3: %08X ESP=%08X IF=%d TF=%d CPL=%d IOPL=%d CR0=%08X\n", env->eip, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, ((env->eflags >> IOPL_SHIFT) & 3), env->cr[0]));
560 }
561 }
562 }
563 else
564 {
565 Log(("EMRM: %04X:%08X SS:ESP=%04X:%08X IF=%d TF=%d CPL=%d PE=%d PG=%d\n", env->segs[R_CS].selector, env->eip, env->segs[R_SS].selector, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, env->cr[0] & X86_CR0_PE, env->cr[0] & X86_CR0_PG));
566 }
567#endif /* !DEBUG_bird */
568 if(env->state & CPU_EMULATE_SINGLE_STEP)
569 {
570#ifdef DEBUG_bird
571 static int s_cTimes = 0;
572 if (s_cTimes++ > 1000000)
573 {
574 RTLogPrintf("Enough stepping!\n");
575 #if 0
576 env->exception_index = EXCP_DEBUG;
577 ret = env->exception_index;
578 cpu_loop_exit();
579 #else
580 env->state &= ~CPU_EMULATE_SINGLE_STEP;
581 #endif
582 }
583#endif
584 TMCpuTickPause(env->pVM);
585 remR3DisasInstr(env, -1, NULL);
586 TMCpuTickResume(env->pVM);
587 if(emulate_single_instr(env) == -1)
588 {
589 Log(("emulate_single_instr failed for EIP=%08X!!\n", env->eip));
590 }
591 }
592 else
593 {
594 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE);
595 gen_func();
596 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE);
597 }
598#else /* !DEBUG || !VBOX || DEBUG_dmik */
599
600 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE);
601 gen_func();
602 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE);
603
604#endif /* !DEBUG || !VBOX || DEBUG_dmik */
605 env->current_tb = NULL;
606 /* reset soft MMU for next block (it can currently
607 only be set by a memory fault) */
608#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
609 if (env->hflags & HF_SOFTMMU_MASK) {
610 env->hflags &= ~HF_SOFTMMU_MASK;
611 /* do not allow linking to another block */
612 T0 = 0;
613 }
614#endif
615 }
616 } else {
617 env_to_regs();
618 }
619#ifdef VBOX_HIGH_RES_TIMERS_HACK
620 /* NULL the current_tb here so cpu_interrupt() doesn't do
621 anything unnecessary (like crashing during emulate single instruction). */
622 env->current_tb = NULL;
623 TMTimerPoll(env1->pVM);
624#endif
625 } /* for(;;) */
626
627#if defined(TARGET_I386)
628 /* restore flags in standard format */
629 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
630
631 /* restore global registers */
632#ifdef reg_EAX
633 EAX = saved_EAX;
634#endif
635#ifdef reg_ECX
636 ECX = saved_ECX;
637#endif
638#ifdef reg_EDX
639 EDX = saved_EDX;
640#endif
641#ifdef reg_EBX
642 EBX = saved_EBX;
643#endif
644#ifdef reg_ESP
645 ESP = saved_ESP;
646#endif
647#ifdef reg_EBP
648 EBP = saved_EBP;
649#endif
650#ifdef reg_ESI
651 ESI = saved_ESI;
652#endif
653#ifdef reg_EDI
654 EDI = saved_EDI;
655#endif
656#else
657#error unsupported target CPU
658#endif
659 T0 = saved_T0;
660 T1 = saved_T1;
661 T2 = saved_T2;
662 env = saved_env;
663 return ret;
664}
665
666
667#else /* !VBOX */
668
669
670int cpu_exec(CPUState *env1)
671{
672 int saved_T0, saved_T1, saved_T2;
673 CPUState *saved_env;
674#ifdef reg_EAX
675 int saved_EAX;
676#endif
677#ifdef reg_ECX
678 int saved_ECX;
679#endif
680#ifdef reg_EDX
681 int saved_EDX;
682#endif
683#ifdef reg_EBX
684 int saved_EBX;
685#endif
686#ifdef reg_ESP
687 int saved_ESP;
688#endif
689#ifdef reg_EBP
690 int saved_EBP;
691#endif
692#ifdef reg_ESI
693 int saved_ESI;
694#endif
695#ifdef reg_EDI
696 int saved_EDI;
697#endif
698#if defined(__sparc__) && !defined(HOST_SOLARIS)
699 int saved_i7, tmp_T0;
700#endif
701 int ret, interrupt_request;
702 void (*gen_func)(void);
703 TranslationBlock *tb;
704 uint8_t *tc_ptr;
705
706#if defined(TARGET_I386)
707 /* handle exit of HALTED state */
708 if (env1->hflags & HF_HALTED_MASK) {
709 /* disable halt condition */
710 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
711 (env1->eflags & IF_MASK)) {
712 env1->hflags &= ~HF_HALTED_MASK;
713 } else {
714 return EXCP_HALTED;
715 }
716 }
717#elif defined(TARGET_PPC)
718 if (env1->halted) {
719 if (env1->msr[MSR_EE] &&
720 (env1->interrupt_request &
721 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
722 env1->halted = 0;
723 } else {
724 return EXCP_HALTED;
725 }
726 }
727#elif defined(TARGET_SPARC)
728 if (env1->halted) {
729 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
730 (env1->psret != 0)) {
731 env1->halted = 0;
732 } else {
733 return EXCP_HALTED;
734 }
735 }
736#elif defined(TARGET_ARM)
737 if (env1->halted) {
738 /* An interrupt wakes the CPU even if the I and F CPSR bits are
739 set. */
740 if (env1->interrupt_request
741 & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
742 env1->halted = 0;
743 } else {
744 return EXCP_HALTED;
745 }
746 }
747#elif defined(TARGET_MIPS)
748 if (env1->halted) {
749 if (env1->interrupt_request &
750 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
751 env1->halted = 0;
752 } else {
753 return EXCP_HALTED;
754 }
755 }
756#endif
757
758 cpu_single_env = env1;
759
760 /* first we save global registers */
761 saved_env = env;
762 env = env1;
763 saved_T0 = T0;
764 saved_T1 = T1;
765#if defined(reg_T2)
766 saved_T2 = T2;
767#endif
768#if defined(__sparc__) && !defined(HOST_SOLARIS)
769 /* we also save i7 because longjmp may not restore it */
770 asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
771#endif
772
773#if defined(TARGET_I386)
774#ifdef reg_EAX
775 saved_EAX = EAX;
776#endif
777#ifdef reg_ECX
778 saved_ECX = ECX;
779#endif
780#ifdef reg_EDX
781 saved_EDX = EDX;
782#endif
783#ifdef reg_EBX
784 saved_EBX = EBX;
785#endif
786#ifdef reg_ESP
787 saved_ESP = ESP;
788#endif
789#ifdef reg_EBP
790 saved_EBP = EBP;
791#endif
792#ifdef reg_ESI
793 saved_ESI = ESI;
794#endif
795#ifdef reg_EDI
796 saved_EDI = EDI;
797#endif
798
799 env_to_regs();
800 /* put eflags in CPU temporary format */
801 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
802 DF = 1 - (2 * ((env->eflags >> 10) & 1));
803 CC_OP = CC_OP_EFLAGS;
804 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
805#elif defined(TARGET_ARM)
806#elif defined(TARGET_SPARC)
807#if defined(reg_REGWPTR)
808 saved_regwptr = REGWPTR;
809#endif
810#elif defined(TARGET_PPC)
811#elif defined(TARGET_M68K)
812 env->cc_op = CC_OP_FLAGS;
813 env->cc_dest = env->sr & 0xf;
814 env->cc_x = (env->sr >> 4) & 1;
815#elif defined(TARGET_MIPS)
816#elif defined(TARGET_SH4)
817 /* XXXXX */
818#else
819#error unsupported target CPU
820#endif
821#ifndef VBOX /* VBOX: We need to raise traps and suchlike from the outside. */
822 env->exception_index = -1;
823#endif
824
825 /* prepare setjmp context for exception handling */
826 for(;;) {
827 if (setjmp(env->jmp_env) == 0) {
828 env->current_tb = NULL;
829#ifdef VBOX
830 VMMR3Unlock(env->pVM);
831 VMMR3Lock(env->pVM);
832
833 /* Check for high priority requests first (like fatal
834 errors). */
835 if (env->interrupt_request & CPU_INTERRUPT_RC) {
836 env->exception_index = EXCP_RC;
837 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC);
838 ret = env->exception_index;
839 cpu_loop_exit();
840 }
841#endif /* VBOX */
842
843
844 /* if an exception is pending, we execute it here */
845 if (env->exception_index >= 0) {
846 if (env->exception_index >= EXCP_INTERRUPT) {
847 /* exit request from the cpu execution loop */
848 ret = env->exception_index;
849 break;
850 } else if (env->user_mode_only) {
851 /* if user mode only, we simulate a fake exception
852 which will be handled outside the cpu execution
853 loop */
854#if defined(TARGET_I386)
855 do_interrupt_user(env->exception_index,
856 env->exception_is_int,
857 env->error_code,
858 env->exception_next_eip);
859#endif
860 ret = env->exception_index;
861 break;
862 } else {
863#if defined(TARGET_I386)
864 /* simulate a real cpu exception. On i386, it can
865 trigger new exceptions, but we do not handle
866 double or triple faults yet. */
867 do_interrupt(env->exception_index,
868 env->exception_is_int,
869 env->error_code,
870 env->exception_next_eip, 0);
871#elif defined(TARGET_PPC)
872 do_interrupt(env);
873#elif defined(TARGET_MIPS)
874 do_interrupt(env);
875#elif defined(TARGET_SPARC)
876 do_interrupt(env->exception_index);
877#elif defined(TARGET_ARM)
878 do_interrupt(env);
879#elif defined(TARGET_SH4)
880 do_interrupt(env);
881#endif
882 }
883 env->exception_index = -1;
884 }
885#ifdef USE_KQEMU
886 if (kqemu_is_ok(env) && env->interrupt_request == 0) {
887 int ret;
888 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
889 ret = kqemu_cpu_exec(env);
890 /* put eflags in CPU temporary format */
891 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
892 DF = 1 - (2 * ((env->eflags >> 10) & 1));
893 CC_OP = CC_OP_EFLAGS;
894 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
895 if (ret == 1) {
896 /* exception */
897 longjmp(env->jmp_env, 1);
898 } else if (ret == 2) {
899 /* softmmu execution needed */
900 } else {
901 if (env->interrupt_request != 0) {
902 /* hardware interrupt will be executed just after */
903 } else {
904 /* otherwise, we restart */
905 longjmp(env->jmp_env, 1);
906 }
907 }
908 }
909#endif
910
911 T0 = 0; /* force lookup of first TB */
912 for(;;) {
913#if defined(__sparc__) && !defined(HOST_SOLARIS)
914 /* g1 can be modified by some libc? functions */
915 tmp_T0 = T0;
916#endif
917 interrupt_request = env->interrupt_request;
918 if (__builtin_expect(interrupt_request, 0)) {
919#ifdef VBOX
920 /* Single instruction exec request, we execute it and return (one way or the other).
921 The caller will always reschedule after doing this operation! */
922 if (interrupt_request & CPU_INTERRUPT_SINGLE_INSTR)
923 {
924 /* not in flight are we? */
925 if (!(env->interrupt_request & CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT))
926 {
927 ASMAtomicOrS32(&env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT);
928 env->exception_index = EXCP_SINGLE_INSTR;
929 if (emulate_single_instr(env) == -1)
930 AssertMsgFailed(("REM: emulate_single_instr failed for EIP=%08x!!\n", env->eip));
931
932 /* When we receive an external interrupt during execution of this single
933 instruction, then we should stay here. We will leave when we're ready
934 for raw-mode or when interrupted by pending EMT requests. */
935 interrupt_request = env->interrupt_request; /* reload this! */
936 if ( !(interrupt_request & CPU_INTERRUPT_HARD)
937 || !(env->eflags & IF_MASK)
938 || (env->hflags & HF_INHIBIT_IRQ_MASK)
939 )
940 {
941 env->exception_index = ret = EXCP_SINGLE_INSTR;
942 cpu_loop_exit();
943 }
944 }
945 env->exception_index = EXCP_SINGLE_INSTR;
946 cpu_loop_exit();
947 }
948
949 RAWEx_ProfileStart(env, STATS_IRQ_HANDLING);
950#endif /* VBOX */
951#if defined(TARGET_I386)
952 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
953 !(env->hflags & HF_SMM_MASK)) {
954 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
955 do_smm_enter();
956#if defined(__sparc__) && !defined(HOST_SOLARIS)
957 tmp_T0 = 0;
958#else
959 T0 = 0;
960#endif
961 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
962 (env->eflags & IF_MASK) &&
963 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
964 int intno;
965#if defined(VBOX)
966 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_HARD);
967#else
968 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
969#endif
970 intno = cpu_get_pic_interrupt(env);
971 if (loglevel & CPU_LOG_TB_IN_ASM) {
972 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
973 }
974#if defined(VBOX)
975 if (intno >= 0)
976#endif
977 do_interrupt(intno, 0, 0, 0, 1);
978 /* ensure that no TB jump will be modified as
979 the program flow was changed */
980#if defined(__sparc__) && !defined(HOST_SOLARIS)
981 tmp_T0 = 0;
982#else
983 T0 = 0;
984#endif
985 }
986#elif defined(TARGET_PPC)
987#if 0
988 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
989 cpu_ppc_reset(env);
990 }
991#endif
992 if (msr_ee != 0) {
993 if ((interrupt_request & CPU_INTERRUPT_HARD)) {
994 /* Raise it */
995 env->exception_index = EXCP_EXTERNAL;
996 env->error_code = 0;
997 do_interrupt(env);
998 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
999#if defined(__sparc__) && !defined(HOST_SOLARIS)
1000 tmp_T0 = 0;
1001#else
1002 T0 = 0;
1003#endif
1004 } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
1005 /* Raise it */
1006 env->exception_index = EXCP_DECR;
1007 env->error_code = 0;
1008 do_interrupt(env);
1009 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
1010#if defined(__sparc__) && !defined(HOST_SOLARIS)
1011 tmp_T0 = 0;
1012#else
1013 T0 = 0;
1014#endif
1015 }
1016 }
1017#elif defined(TARGET_MIPS)
1018 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
1019 (env->CP0_Status & (1 << CP0St_IE)) &&
1020 (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
1021 !(env->hflags & MIPS_HFLAG_EXL) &&
1022 !(env->hflags & MIPS_HFLAG_ERL) &&
1023 !(env->hflags & MIPS_HFLAG_DM)) {
1024 /* Raise it */
1025 env->exception_index = EXCP_EXT_INTERRUPT;
1026 env->error_code = 0;
1027 do_interrupt(env);
1028 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1029#if defined(__sparc__) && !defined(HOST_SOLARIS)
1030 tmp_T0 = 0;
1031#else
1032 T0 = 0;
1033#endif
1034 }
1035#elif defined(TARGET_SPARC)
1036 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
1037 (env->psret != 0)) {
1038 int pil = env->interrupt_index & 15;
1039 int type = env->interrupt_index & 0xf0;
1040
1041 if (((type == TT_EXTINT) &&
1042 (pil == 15 || pil > env->psrpil)) ||
1043 type != TT_EXTINT) {
1044 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1045 do_interrupt(env->interrupt_index);
1046 env->interrupt_index = 0;
1047#if defined(__sparc__) && !defined(HOST_SOLARIS)
1048 tmp_T0 = 0;
1049#else
1050 T0 = 0;
1051#endif
1052 }
1053 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
1054 //do_interrupt(0, 0, 0, 0, 0);
1055 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
1056 } else if (interrupt_request & CPU_INTERRUPT_HALT) {
1057 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
1058 env->halted = 1;
1059 env->exception_index = EXCP_HLT;
1060 cpu_loop_exit();
1061 }
1062#elif defined(TARGET_ARM)
1063 if (interrupt_request & CPU_INTERRUPT_FIQ
1064 && !(env->uncached_cpsr & CPSR_F)) {
1065 env->exception_index = EXCP_FIQ;
1066 do_interrupt(env);
1067 }
1068 if (interrupt_request & CPU_INTERRUPT_HARD
1069 && !(env->uncached_cpsr & CPSR_I)) {
1070 env->exception_index = EXCP_IRQ;
1071 do_interrupt(env);
1072 }
1073#elif defined(TARGET_SH4)
1074 /* XXXXX */
1075#endif
1076 /* Don't use the cached interupt_request value,
1077 do_interrupt may have updated the EXITTB flag. */
1078 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
1079#if defined(VBOX)
1080 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_EXITTB);
1081#else
1082 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
1083#endif
1084 /* ensure that no TB jump will be modified as
1085 the program flow was changed */
1086#if defined(__sparc__) && !defined(HOST_SOLARIS)
1087 tmp_T0 = 0;
1088#else
1089 T0 = 0;
1090#endif
1091 }
1092#ifdef VBOX
1093 RAWEx_ProfileStop(env, STATS_IRQ_HANDLING);
1094#endif
1095 if (interrupt_request & CPU_INTERRUPT_EXIT) {
1096#if defined(VBOX)
1097 env->exception_index = EXCP_INTERRUPT;
1098 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_EXIT);
1099#else
1100 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
1101 env->exception_index = EXCP_INTERRUPT;
1102#endif
1103 cpu_loop_exit();
1104 }
1105#if defined(VBOX)
1106 if (interrupt_request & CPU_INTERRUPT_RC) {
1107 env->exception_index = EXCP_RC;
1108 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC);
1109 cpu_loop_exit();
1110 }
1111#endif
1112 }
1113#ifdef DEBUG_EXEC
1114 if ((loglevel & CPU_LOG_TB_CPU)) {
1115#if defined(TARGET_I386)
1116 /* restore flags in standard format */
1117#ifdef reg_EAX
1118 env->regs[R_EAX] = EAX;
1119#endif
1120#ifdef reg_EBX
1121 env->regs[R_EBX] = EBX;
1122#endif
1123#ifdef reg_ECX
1124 env->regs[R_ECX] = ECX;
1125#endif
1126#ifdef reg_EDX
1127 env->regs[R_EDX] = EDX;
1128#endif
1129#ifdef reg_ESI
1130 env->regs[R_ESI] = ESI;
1131#endif
1132#ifdef reg_EDI
1133 env->regs[R_EDI] = EDI;
1134#endif
1135#ifdef reg_EBP
1136 env->regs[R_EBP] = EBP;
1137#endif
1138#ifdef reg_ESP
1139 env->regs[R_ESP] = ESP;
1140#endif
1141 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
1142 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1143 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1144#elif defined(TARGET_ARM)
1145 cpu_dump_state(env, logfile, fprintf, 0);
1146#elif defined(TARGET_SPARC)
1147 REGWPTR = env->regbase + (env->cwp * 16);
1148 env->regwptr = REGWPTR;
1149 cpu_dump_state(env, logfile, fprintf, 0);
1150#elif defined(TARGET_PPC)
1151 cpu_dump_state(env, logfile, fprintf, 0);
1152#elif defined(TARGET_M68K)
1153 cpu_m68k_flush_flags(env, env->cc_op);
1154 env->cc_op = CC_OP_FLAGS;
1155 env->sr = (env->sr & 0xffe0)
1156 | env->cc_dest | (env->cc_x << 4);
1157 cpu_dump_state(env, logfile, fprintf, 0);
1158#elif defined(TARGET_MIPS)
1159 cpu_dump_state(env, logfile, fprintf, 0);
1160#elif defined(TARGET_SH4)
1161 cpu_dump_state(env, logfile, fprintf, 0);
1162#else
1163#error unsupported target CPU
1164#endif
1165 }
1166#endif
1167#ifdef VBOX
1168 /*
1169 * Check if we the CPU state allows us to execute the code in raw-mode.
1170 */
1171 RAWEx_ProfileStart(env, STATS_RAW_CHECK);
1172 if (remR3CanExecuteRaw(env,
1173 env->eip + env->segs[R_CS].base,
1174 env->hflags | (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK))
1175 flags, &env->exception_index))
1176 {
1177 RAWEx_ProfileStop(env, STATS_RAW_CHECK);
1178 ret = env->exception_index;
1179 cpu_loop_exit();
1180 }
1181 RAWEx_ProfileStop(env, STATS_RAW_CHECK);
1182#endif /* VBOX */
1183 tb = tb_find_fast();
1184#ifdef DEBUG_EXEC
1185 if ((loglevel & CPU_LOG_EXEC)) {
1186 fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
1187 (long)tb->tc_ptr, tb->pc,
1188 lookup_symbol(tb->pc));
1189 }
1190#endif
1191#if defined(__sparc__) && !defined(HOST_SOLARIS)
1192 T0 = tmp_T0;
1193#endif
1194 /* see if we can patch the calling TB. When the TB
1195 spans two pages, we cannot safely do a direct
1196 jump. */
1197 {
1198 if (T0 != 0 &&
1199#if USE_KQEMU
1200 (env->kqemu_enabled != 2) &&
1201#endif
1202#ifdef VBOX
1203 !(tb->cflags & CF_RAW_MODE) &&
1204#endif
1205 tb->page_addr[1] == -1
1206#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1207 && (tb->cflags & CF_CODE_COPY) ==
1208 (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
1209#endif
1210 ) {
1211 spin_lock(&tb_lock);
1212 tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
1213#if defined(USE_CODE_COPY)
1214 /* propagates the FP use info */
1215 ((TranslationBlock *)(T0 & ~3))->cflags |=
1216 (tb->cflags & CF_FP_USED);
1217#endif
1218 spin_unlock(&tb_lock);
1219 }
1220 }
1221 tc_ptr = tb->tc_ptr;
1222 env->current_tb = tb;
1223 /* execute the generated code */
1224 gen_func = (void *)tc_ptr;
1225#if defined(__sparc__)
1226 __asm__ __volatile__("call %0\n\t"
1227 "mov %%o7,%%i0"
1228 : /* no outputs */
1229 : "r" (gen_func)
1230 : "i0", "i1", "i2", "i3", "i4", "i5",
1231 "l0", "l1", "l2", "l3", "l4", "l5",
1232 "l6", "l7");
1233#elif defined(__arm__)
1234 asm volatile ("mov pc, %0\n\t"
1235 ".global exec_loop\n\t"
1236 "exec_loop:\n\t"
1237 : /* no outputs */
1238 : "r" (gen_func)
1239 : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
1240#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
1241{
1242 if (!(tb->cflags & CF_CODE_COPY)) {
1243 if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
1244 save_native_fp_state(env);
1245 }
1246 gen_func();
1247 } else {
1248 if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
1249 restore_native_fp_state(env);
1250 }
1251 /* we work with native eflags */
1252 CC_SRC = cc_table[CC_OP].compute_all();
1253 CC_OP = CC_OP_EFLAGS;
1254 asm(".globl exec_loop\n"
1255 "\n"
1256 "debug1:\n"
1257 " pushl %%ebp\n"
1258 " fs movl %10, %9\n"
1259 " fs movl %11, %%eax\n"
1260 " andl $0x400, %%eax\n"
1261 " fs orl %8, %%eax\n"
1262 " pushl %%eax\n"
1263 " popf\n"
1264 " fs movl %%esp, %12\n"
1265 " fs movl %0, %%eax\n"
1266 " fs movl %1, %%ecx\n"
1267 " fs movl %2, %%edx\n"
1268 " fs movl %3, %%ebx\n"
1269 " fs movl %4, %%esp\n"
1270 " fs movl %5, %%ebp\n"
1271 " fs movl %6, %%esi\n"
1272 " fs movl %7, %%edi\n"
1273 " fs jmp *%9\n"
1274 "exec_loop:\n"
1275 " fs movl %%esp, %4\n"
1276 " fs movl %12, %%esp\n"
1277 " fs movl %%eax, %0\n"
1278 " fs movl %%ecx, %1\n"
1279 " fs movl %%edx, %2\n"
1280 " fs movl %%ebx, %3\n"
1281 " fs movl %%ebp, %5\n"
1282 " fs movl %%esi, %6\n"
1283 " fs movl %%edi, %7\n"
1284 " pushf\n"
1285 " popl %%eax\n"
1286 " movl %%eax, %%ecx\n"
1287 " andl $0x400, %%ecx\n"
1288 " shrl $9, %%ecx\n"
1289 " andl $0x8d5, %%eax\n"
1290 " fs movl %%eax, %8\n"
1291 " movl $1, %%eax\n"
1292 " subl %%ecx, %%eax\n"
1293 " fs movl %%eax, %11\n"
1294 " fs movl %9, %%ebx\n" /* get T0 value */
1295 " popl %%ebp\n"
1296 :
1297 : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
1298 "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
1299 "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
1300 "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
1301 "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
1302 "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
1303 "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
1304 "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
1305 "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
1306 "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
1307 "a" (gen_func),
1308 "m" (*(uint8_t *)offsetof(CPUState, df)),
1309 "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
1310 : "%ecx", "%edx"
1311 );
1312 }
1313}
1314#elif defined(__ia64)
1315 struct fptr {
1316 void *ip;
1317 void *gp;
1318 } fp;
1319
1320 fp.ip = tc_ptr;
1321 fp.gp = code_gen_buffer + 2 * (1 << 20);
1322 (*(void (*)(void)) &fp)();
1323#else
1324#if defined(DEBUG) && defined(VBOX) && !defined(DEBUG_dmik)
1325#if !defined(DEBUG_bird)
1326 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 0 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK))
1327 {
1328 if(!(env->state & CPU_EMULATE_SINGLE_STEP))
1329 {
1330 Log(("EMR0: %08X IF=%d TF=%d CPL=%d\n", env->eip, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3));
1331 }
1332 }
1333 else
1334 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 3 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK))
1335 {
1336 if(!(env->state & CPU_EMULATE_SINGLE_STEP))
1337 {
1338 if(env->eflags & VM_MASK)
1339 {
1340 Log(("EMV86: %08X IF=%d TF=%d CPL=%d flags=%08X CR0=%08X\n", env->eip, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, flags, env->cr[0]));
1341 }
1342 else
1343 {
1344 Log(("EMR3: %08X IF=%d TF=%d CPL=%d IOPL=%d flags=%08X CR0=%08X\n", env->eip, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, ((env->eflags >> IOPL_SHIFT) & 3), flags, env->cr[0]));
1345 }
1346 }
1347 }
1348#endif /* !DEBUG_bird */
1349 if(env->state & CPU_EMULATE_SINGLE_STEP)
1350 {
1351#ifdef DEBUG_bird
1352 static int s_cTimes = 0;
1353 if (s_cTimes++ > 1000000) /* 1 million */
1354 {
1355 RTLogPrintf("Enough stepping!\n");
1356 #if 0
1357 env->exception_index = EXCP_DEBUG;
1358 cpu_loop_exit();
1359 #else
1360 env->state &= ~CPU_EMULATE_SINGLE_STEP;
1361 #endif
1362 }
1363#endif
1364 TMCpuTickPause(env->pVM);
1365 remR3DisasInstr(env, -1, NULL);
1366 TMCpuTickResume(env->pVM);
1367 if(emulate_single_instr(env) == -1)
1368 {
1369 printf("emulate_single_instr failed for EIP=%08X!!\n", env->eip);
1370 }
1371 }
1372 else
1373 {
1374 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE);
1375 gen_func();
1376 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE);
1377 }
1378#else /* !DEBUG || !VBOX || DEBUG_dmik */
1379
1380#ifdef VBOX
1381 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE);
1382 gen_func();
1383 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE);
1384#else /* !VBOX */
1385 gen_func();
1386#endif /* !VBOX */
1387
1388#endif /* !DEBUG || !VBOX || DEBUG_dmik */
1389#endif
1390 env->current_tb = NULL;
1391 /* reset soft MMU for next block (it can currently
1392 only be set by a memory fault) */
1393#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
1394 if (env->hflags & HF_SOFTMMU_MASK) {
1395 env->hflags &= ~HF_SOFTMMU_MASK;
1396 /* do not allow linking to another block */
1397 T0 = 0;
1398 }
1399#endif
1400#if defined(USE_KQEMU)
1401#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
1402 if (kqemu_is_ok(env) &&
1403 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
1404 cpu_loop_exit();
1405 }
1406#endif
1407 }
1408 } else {
1409 env_to_regs();
1410 }
1411 } /* for(;;) */
1412
1413
1414#if defined(TARGET_I386)
1415#if defined(USE_CODE_COPY)
1416 if (env->native_fp_regs) {
1417 save_native_fp_state(env);
1418 }
1419#endif
1420 /* restore flags in standard format */
1421 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
1422
1423 /* restore global registers */
1424#ifdef reg_EAX
1425 EAX = saved_EAX;
1426#endif
1427#ifdef reg_ECX
1428 ECX = saved_ECX;
1429#endif
1430#ifdef reg_EDX
1431 EDX = saved_EDX;
1432#endif
1433#ifdef reg_EBX
1434 EBX = saved_EBX;
1435#endif
1436#ifdef reg_ESP
1437 ESP = saved_ESP;
1438#endif
1439#ifdef reg_EBP
1440 EBP = saved_EBP;
1441#endif
1442#ifdef reg_ESI
1443 ESI = saved_ESI;
1444#endif
1445#ifdef reg_EDI
1446 EDI = saved_EDI;
1447#endif
1448#elif defined(TARGET_ARM)
1449 /* XXX: Save/restore host fpu exception state?. */
1450#elif defined(TARGET_SPARC)
1451#if defined(reg_REGWPTR)
1452 REGWPTR = saved_regwptr;
1453#endif
1454#elif defined(TARGET_PPC)
1455#elif defined(TARGET_M68K)
1456 cpu_m68k_flush_flags(env, env->cc_op);
1457 env->cc_op = CC_OP_FLAGS;
1458 env->sr = (env->sr & 0xffe0)
1459 | env->cc_dest | (env->cc_x << 4);
1460#elif defined(TARGET_MIPS)
1461#elif defined(TARGET_SH4)
1462 /* XXXXX */
1463#else
1464#error unsupported target CPU
1465#endif
1466#if defined(__sparc__) && !defined(HOST_SOLARIS)
1467 asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
1468#endif
1469 T0 = saved_T0;
1470 T1 = saved_T1;
1471#if defined(reg_T2)
1472 T2 = saved_T2;
1473#endif
1474 env = saved_env;
1475 /* fail safe : never use cpu_single_env outside cpu_exec() */
1476 cpu_single_env = NULL;
1477 return ret;
1478}
1479
1480#endif /* !VBOX */
1481
1482/* must only be called from the generated code as an exception can be
1483 generated */
1484void tb_invalidate_page_range(target_ulong start, target_ulong end)
1485{
1486 /* XXX: cannot enable it yet because it yields to MMU exception
1487 where NIP != read address on PowerPC */
1488#if 0
1489 target_ulong phys_addr;
1490 phys_addr = get_phys_addr_code(env, start);
1491 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
1492#endif
1493}
1494
1495#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
1496
1497void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
1498{
1499 CPUX86State *saved_env;
1500
1501 saved_env = env;
1502 env = s;
1503 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
1504 selector &= 0xffff;
1505 cpu_x86_load_seg_cache(env, seg_reg, selector,
1506 (selector << 4), 0xffff, 0);
1507 } else {
1508 load_seg(seg_reg, selector);
1509 }
1510 env = saved_env;
1511}
1512
1513void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
1514{
1515 CPUX86State *saved_env;
1516
1517 saved_env = env;
1518 env = s;
1519
1520 helper_fsave((target_ulong)ptr, data32);
1521
1522 env = saved_env;
1523}
1524
1525void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
1526{
1527 CPUX86State *saved_env;
1528
1529 saved_env = env;
1530 env = s;
1531
1532 helper_frstor((target_ulong)ptr, data32);
1533
1534 env = saved_env;
1535}
1536
1537#endif /* TARGET_I386 */
1538
1539#if !defined(CONFIG_SOFTMMU)
1540
1541#if defined(TARGET_I386)
1542
1543/* 'pc' is the host PC at which the exception was raised. 'address' is
1544 the effective address of the memory exception. 'is_write' is 1 if a
1545 write caused the exception and otherwise 0'. 'old_set' is the
1546 signal set which should be restored */
1547static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1548 int is_write, sigset_t *old_set,
1549 void *puc)
1550{
1551 TranslationBlock *tb;
1552 int ret;
1553
1554 if (cpu_single_env)
1555 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1556#if defined(DEBUG_SIGNAL)
1557 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1558 pc, address, is_write, *(unsigned long *)old_set);
1559#endif
1560 /* XXX: locking issue */
1561 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1562 return 1;
1563 }
1564
1565 /* see if it is an MMU fault */
1566 ret = cpu_x86_handle_mmu_fault(env, address, is_write,
1567 ((env->hflags & HF_CPL_MASK) == 3), 0);
1568 if (ret < 0)
1569 return 0; /* not an MMU fault */
1570 if (ret == 0)
1571 return 1; /* the MMU fault was handled without causing real CPU fault */
1572 /* now we have a real cpu fault */
1573 tb = tb_find_pc(pc);
1574 if (tb) {
1575 /* the PC is inside the translated code. It means that we have
1576 a virtual CPU fault */
1577 cpu_restore_state(tb, env, pc, puc);
1578 }
1579 if (ret == 1) {
1580#if 0
1581 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
1582 env->eip, env->cr[2], env->error_code);
1583#endif
1584 /* we restore the process signal mask as the sigreturn should
1585 do it (XXX: use sigsetjmp) */
1586 sigprocmask(SIG_SETMASK, old_set, NULL);
1587 raise_exception_err(env->exception_index, env->error_code);
1588 } else {
1589 /* activate soft MMU for this block */
1590 env->hflags |= HF_SOFTMMU_MASK;
1591 cpu_resume_from_signal(env, puc);
1592 }
1593 /* never comes here */
1594 return 1;
1595}
1596
1597#elif defined(TARGET_ARM)
1598static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1599 int is_write, sigset_t *old_set,
1600 void *puc)
1601{
1602 TranslationBlock *tb;
1603 int ret;
1604
1605 if (cpu_single_env)
1606 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1607#if defined(DEBUG_SIGNAL)
1608 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1609 pc, address, is_write, *(unsigned long *)old_set);
1610#endif
1611 /* XXX: locking issue */
1612 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1613 return 1;
1614 }
1615 /* see if it is an MMU fault */
1616 ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
1617 if (ret < 0)
1618 return 0; /* not an MMU fault */
1619 if (ret == 0)
1620 return 1; /* the MMU fault was handled without causing real CPU fault */
1621 /* now we have a real cpu fault */
1622 tb = tb_find_pc(pc);
1623 if (tb) {
1624 /* the PC is inside the translated code. It means that we have
1625 a virtual CPU fault */
1626 cpu_restore_state(tb, env, pc, puc);
1627 }
1628 /* we restore the process signal mask as the sigreturn should
1629 do it (XXX: use sigsetjmp) */
1630 sigprocmask(SIG_SETMASK, old_set, NULL);
1631 cpu_loop_exit();
1632}
1633#elif defined(TARGET_SPARC)
1634static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1635 int is_write, sigset_t *old_set,
1636 void *puc)
1637{
1638 TranslationBlock *tb;
1639 int ret;
1640
1641 if (cpu_single_env)
1642 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1643#if defined(DEBUG_SIGNAL)
1644 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1645 pc, address, is_write, *(unsigned long *)old_set);
1646#endif
1647 /* XXX: locking issue */
1648 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1649 return 1;
1650 }
1651 /* see if it is an MMU fault */
1652 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
1653 if (ret < 0)
1654 return 0; /* not an MMU fault */
1655 if (ret == 0)
1656 return 1; /* the MMU fault was handled without causing real CPU fault */
1657 /* now we have a real cpu fault */
1658 tb = tb_find_pc(pc);
1659 if (tb) {
1660 /* the PC is inside the translated code. It means that we have
1661 a virtual CPU fault */
1662 cpu_restore_state(tb, env, pc, puc);
1663 }
1664 /* we restore the process signal mask as the sigreturn should
1665 do it (XXX: use sigsetjmp) */
1666 sigprocmask(SIG_SETMASK, old_set, NULL);
1667 cpu_loop_exit();
1668}
1669#elif defined (TARGET_PPC)
1670static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1671 int is_write, sigset_t *old_set,
1672 void *puc)
1673{
1674 TranslationBlock *tb;
1675 int ret;
1676
1677 if (cpu_single_env)
1678 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1679#if defined(DEBUG_SIGNAL)
1680 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1681 pc, address, is_write, *(unsigned long *)old_set);
1682#endif
1683 /* XXX: locking issue */
1684 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1685 return 1;
1686 }
1687
1688 /* see if it is an MMU fault */
1689 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
1690 if (ret < 0)
1691 return 0; /* not an MMU fault */
1692 if (ret == 0)
1693 return 1; /* the MMU fault was handled without causing real CPU fault */
1694
1695 /* now we have a real cpu fault */
1696 tb = tb_find_pc(pc);
1697 if (tb) {
1698 /* the PC is inside the translated code. It means that we have
1699 a virtual CPU fault */
1700 cpu_restore_state(tb, env, pc, puc);
1701 }
1702 if (ret == 1) {
1703#if 0
1704 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1705 env->nip, env->error_code, tb);
1706#endif
1707 /* we restore the process signal mask as the sigreturn should
1708 do it (XXX: use sigsetjmp) */
1709 sigprocmask(SIG_SETMASK, old_set, NULL);
1710 do_raise_exception_err(env->exception_index, env->error_code);
1711 } else {
1712 /* activate soft MMU for this block */
1713 cpu_resume_from_signal(env, puc);
1714 }
1715 /* never comes here */
1716 return 1;
1717}
1718
1719#elif defined(TARGET_M68K)
1720static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1721 int is_write, sigset_t *old_set,
1722 void *puc)
1723{
1724 TranslationBlock *tb;
1725 int ret;
1726
1727 if (cpu_single_env)
1728 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1729#if defined(DEBUG_SIGNAL)
1730 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1731 pc, address, is_write, *(unsigned long *)old_set);
1732#endif
1733 /* XXX: locking issue */
1734 if (is_write && page_unprotect(address, pc, puc)) {
1735 return 1;
1736 }
1737 /* see if it is an MMU fault */
1738 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
1739 if (ret < 0)
1740 return 0; /* not an MMU fault */
1741 if (ret == 0)
1742 return 1; /* the MMU fault was handled without causing real CPU fault */
1743 /* now we have a real cpu fault */
1744 tb = tb_find_pc(pc);
1745 if (tb) {
1746 /* the PC is inside the translated code. It means that we have
1747 a virtual CPU fault */
1748 cpu_restore_state(tb, env, pc, puc);
1749 }
1750 /* we restore the process signal mask as the sigreturn should
1751 do it (XXX: use sigsetjmp) */
1752 sigprocmask(SIG_SETMASK, old_set, NULL);
1753 cpu_loop_exit();
1754 /* never comes here */
1755 return 1;
1756}
1757
1758#elif defined (TARGET_MIPS)
1759static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1760 int is_write, sigset_t *old_set,
1761 void *puc)
1762{
1763 TranslationBlock *tb;
1764 int ret;
1765
1766 if (cpu_single_env)
1767 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1768#if defined(DEBUG_SIGNAL)
1769 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1770 pc, address, is_write, *(unsigned long *)old_set);
1771#endif
1772 /* XXX: locking issue */
1773 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1774 return 1;
1775 }
1776
1777 /* see if it is an MMU fault */
1778 ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0);
1779 if (ret < 0)
1780 return 0; /* not an MMU fault */
1781 if (ret == 0)
1782 return 1; /* the MMU fault was handled without causing real CPU fault */
1783
1784 /* now we have a real cpu fault */
1785 tb = tb_find_pc(pc);
1786 if (tb) {
1787 /* the PC is inside the translated code. It means that we have
1788 a virtual CPU fault */
1789 cpu_restore_state(tb, env, pc, puc);
1790 }
1791 if (ret == 1) {
1792#if 0
1793 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1794 env->nip, env->error_code, tb);
1795#endif
1796 /* we restore the process signal mask as the sigreturn should
1797 do it (XXX: use sigsetjmp) */
1798 sigprocmask(SIG_SETMASK, old_set, NULL);
1799 do_raise_exception_err(env->exception_index, env->error_code);
1800 } else {
1801 /* activate soft MMU for this block */
1802 cpu_resume_from_signal(env, puc);
1803 }
1804 /* never comes here */
1805 return 1;
1806}
1807
1808#elif defined (TARGET_SH4)
1809static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1810 int is_write, sigset_t *old_set,
1811 void *puc)
1812{
1813 TranslationBlock *tb;
1814 int ret;
1815
1816 if (cpu_single_env)
1817 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1818#if defined(DEBUG_SIGNAL)
1819 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1820 pc, address, is_write, *(unsigned long *)old_set);
1821#endif
1822 /* XXX: locking issue */
1823 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1824 return 1;
1825 }
1826
1827 /* see if it is an MMU fault */
1828 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
1829 if (ret < 0)
1830 return 0; /* not an MMU fault */
1831 if (ret == 0)
1832 return 1; /* the MMU fault was handled without causing real CPU fault */
1833
1834 /* now we have a real cpu fault */
1835 tb = tb_find_pc(pc);
1836 if (tb) {
1837 /* the PC is inside the translated code. It means that we have
1838 a virtual CPU fault */
1839 cpu_restore_state(tb, env, pc, puc);
1840 }
1841#if 0
1842 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1843 env->nip, env->error_code, tb);
1844#endif
1845 /* we restore the process signal mask as the sigreturn should
1846 do it (XXX: use sigsetjmp) */
1847 sigprocmask(SIG_SETMASK, old_set, NULL);
1848 cpu_loop_exit();
1849 /* never comes here */
1850 return 1;
1851}
1852#else
1853#error unsupported target CPU
1854#endif
1855
1856#if defined(__i386__)
1857
1858#if defined(USE_CODE_COPY)
1859static void cpu_send_trap(unsigned long pc, int trap,
1860 struct ucontext *uc)
1861{
1862 TranslationBlock *tb;
1863
1864 if (cpu_single_env)
1865 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1866 /* now we have a real cpu fault */
1867 tb = tb_find_pc(pc);
1868 if (tb) {
1869 /* the PC is inside the translated code. It means that we have
1870 a virtual CPU fault */
1871 cpu_restore_state(tb, env, pc, uc);
1872 }
1873 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
1874 raise_exception_err(trap, env->error_code);
1875}
1876#endif
1877
1878int cpu_signal_handler(int host_signum, struct siginfo *info,
1879 void *puc)
1880{
1881 struct ucontext *uc = puc;
1882 unsigned long pc;
1883 int trapno;
1884
1885#ifndef REG_EIP
1886/* for glibc 2.1 */
1887#define REG_EIP EIP
1888#define REG_ERR ERR
1889#define REG_TRAPNO TRAPNO
1890#endif
1891 pc = uc->uc_mcontext.gregs[REG_EIP];
1892 trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
1893#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1894 if (trapno == 0x00 || trapno == 0x05) {
1895 /* send division by zero or bound exception */
1896 cpu_send_trap(pc, trapno, uc);
1897 return 1;
1898 } else
1899#endif
1900 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1901 trapno == 0xe ?
1902 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1903 &uc->uc_sigmask, puc);
1904}
1905
1906#elif defined(__x86_64__)
1907
1908int cpu_signal_handler(int host_signum, struct siginfo *info,
1909 void *puc)
1910{
1911 struct ucontext *uc = puc;
1912 unsigned long pc;
1913
1914 pc = uc->uc_mcontext.gregs[REG_RIP];
1915 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1916 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1917 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1918 &uc->uc_sigmask, puc);
1919}
1920
1921#elif defined(__powerpc__)
1922
1923/***********************************************************************
1924 * signal context platform-specific definitions
1925 * From Wine
1926 */
1927#ifdef linux
1928/* All Registers access - only for local access */
1929# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1930/* Gpr Registers access */
1931# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1932# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1933# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1934# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1935# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1936# define LR_sig(context) REG_sig(link, context) /* Link register */
1937# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1938/* Float Registers access */
1939# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1940# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1941/* Exception Registers access */
1942# define DAR_sig(context) REG_sig(dar, context)
1943# define DSISR_sig(context) REG_sig(dsisr, context)
1944# define TRAP_sig(context) REG_sig(trap, context)
1945#endif /* linux */
1946
1947#ifdef __APPLE__
1948# include <sys/ucontext.h>
1949typedef struct ucontext SIGCONTEXT;
1950/* All Registers access - only for local access */
1951# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1952# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1953# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1954# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1955/* Gpr Registers access */
1956# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1957# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1958# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1959# define CTR_sig(context) REG_sig(ctr, context)
1960# define XER_sig(context) REG_sig(xer, context) /* Link register */
1961# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1962# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1963/* Float Registers access */
1964# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1965# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1966/* Exception Registers access */
1967# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1968# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1969# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1970#endif /* __APPLE__ */
1971
1972int cpu_signal_handler(int host_signum, struct siginfo *info,
1973 void *puc)
1974{
1975 struct ucontext *uc = puc;
1976 unsigned long pc;
1977 int is_write;
1978
1979 pc = IAR_sig(uc);
1980 is_write = 0;
1981#if 0
1982 /* ppc 4xx case */
1983 if (DSISR_sig(uc) & 0x00800000)
1984 is_write = 1;
1985#else
1986 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1987 is_write = 1;
1988#endif
1989 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1990 is_write, &uc->uc_sigmask, puc);
1991}
1992
1993#elif defined(__alpha__)
1994
1995int cpu_signal_handler(int host_signum, struct siginfo *info,
1996 void *puc)
1997{
1998 struct ucontext *uc = puc;
1999 uint32_t *pc = uc->uc_mcontext.sc_pc;
2000 uint32_t insn = *pc;
2001 int is_write = 0;
2002
2003 /* XXX: need kernel patch to get write flag faster */
2004 switch (insn >> 26) {
2005 case 0x0d: // stw
2006 case 0x0e: // stb
2007 case 0x0f: // stq_u
2008 case 0x24: // stf
2009 case 0x25: // stg
2010 case 0x26: // sts
2011 case 0x27: // stt
2012 case 0x2c: // stl
2013 case 0x2d: // stq
2014 case 0x2e: // stl_c
2015 case 0x2f: // stq_c
2016 is_write = 1;
2017 }
2018
2019 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
2020 is_write, &uc->uc_sigmask, puc);
2021}
2022#elif defined(__sparc__)
2023
2024int cpu_signal_handler(int host_signum, struct siginfo *info,
2025 void *puc)
2026{
2027 uint32_t *regs = (uint32_t *)(info + 1);
2028 void *sigmask = (regs + 20);
2029 unsigned long pc;
2030 int is_write;
2031 uint32_t insn;
2032
2033 /* XXX: is there a standard glibc define ? */
2034 pc = regs[1];
2035 /* XXX: need kernel patch to get write flag faster */
2036 is_write = 0;
2037 insn = *(uint32_t *)pc;
2038 if ((insn >> 30) == 3) {
2039 switch((insn >> 19) & 0x3f) {
2040 case 0x05: // stb
2041 case 0x06: // sth
2042 case 0x04: // st
2043 case 0x07: // std
2044 case 0x24: // stf
2045 case 0x27: // stdf
2046 case 0x25: // stfsr
2047 is_write = 1;
2048 break;
2049 }
2050 }
2051 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
2052 is_write, sigmask, NULL);
2053}
2054
2055#elif defined(__arm__)
2056
2057int cpu_signal_handler(int host_signum, struct siginfo *info,
2058 void *puc)
2059{
2060 struct ucontext *uc = puc;
2061 unsigned long pc;
2062 int is_write;
2063
2064 pc = uc->uc_mcontext.gregs[R15];
2065 /* XXX: compute is_write */
2066 is_write = 0;
2067 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
2068 is_write,
2069 &uc->uc_sigmask, puc);
2070}
2071
2072#elif defined(__mc68000)
2073
2074int cpu_signal_handler(int host_signum, struct siginfo *info,
2075 void *puc)
2076{
2077 struct ucontext *uc = puc;
2078 unsigned long pc;
2079 int is_write;
2080
2081 pc = uc->uc_mcontext.gregs[16];
2082 /* XXX: compute is_write */
2083 is_write = 0;
2084 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
2085 is_write,
2086 &uc->uc_sigmask, puc);
2087}
2088
2089#elif defined(__ia64)
2090
2091#ifndef __ISR_VALID
2092 /* This ought to be in <bits/siginfo.h>... */
2093# define __ISR_VALID 1
2094#endif
2095
2096int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
2097{
2098 struct ucontext *uc = puc;
2099 unsigned long ip;
2100 int is_write = 0;
2101
2102 ip = uc->uc_mcontext.sc_ip;
2103 switch (host_signum) {
2104 case SIGILL:
2105 case SIGFPE:
2106 case SIGSEGV:
2107 case SIGBUS:
2108 case SIGTRAP:
2109 if (info->si_code && (info->si_segvflags & __ISR_VALID))
2110 /* ISR.W (write-access) is bit 33: */
2111 is_write = (info->si_isr >> 33) & 1;
2112 break;
2113
2114 default:
2115 break;
2116 }
2117 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
2118 is_write,
2119 &uc->uc_sigmask, puc);
2120}
2121
2122#elif defined(__s390__)
2123
2124int cpu_signal_handler(int host_signum, struct siginfo *info,
2125 void *puc)
2126{
2127 struct ucontext *uc = puc;
2128 unsigned long pc;
2129 int is_write;
2130
2131 pc = uc->uc_mcontext.psw.addr;
2132 /* XXX: compute is_write */
2133 is_write = 0;
2134 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
2135 is_write,
2136 &uc->uc_sigmask, puc);
2137}
2138
2139#else
2140
2141#error host CPU specific signal handler needed
2142
2143#endif
2144
2145#endif /* !defined(CONFIG_SOFTMMU) */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette