aboutsummaryrefslogtreecommitdiff
path: root/exec-i386.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-09 15:28:00 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-09 15:28:00 +0000
commit8c6939c0b010003cd3e66a240c3d5867ebd8044e (patch)
tree3fc6249698028f32c1d2e8deedd17a11be3fe6b1 /exec-i386.c
parent2d0e9143e2d6fc705cba6c27c221c5c9a7c81a29 (diff)
downloadqemu-8c6939c0b010003cd3e66a240c3d5867ebd8044e.zip
qemu-8c6939c0b010003cd3e66a240c3d5867ebd8044e.tar.gz
qemu-8c6939c0b010003cd3e66a240c3d5867ebd8044e.tar.bz2
arm support - modified sparc to work with direct chaining
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@218 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'exec-i386.c')
-rw-r--r--exec-i386.c134
1 files changed, 78 insertions, 56 deletions
diff --git a/exec-i386.c b/exec-i386.c
index 5bd69d4..c285eb4 100644
--- a/exec-i386.c
+++ b/exec-i386.c
@@ -25,58 +25,6 @@
/* main execution loop */
-/* thread support */
-
-spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-void cpu_lock(void)
-{
- spin_lock(&global_cpu_lock);
-}
-
-void cpu_unlock(void)
-{
- spin_unlock(&global_cpu_lock);
-}
-
-void cpu_loop_exit(void)
-{
- /* NOTE: the register at this point must be saved by hand because
- longjmp restore them */
-#ifdef __sparc__
- /* We have to stay in the same register window as our caller,
- * thus this trick.
- */
- __asm__ __volatile__("restore\n\t"
- "mov\t%o0, %i0");
-#endif
-#ifdef reg_EAX
- env->regs[R_EAX] = EAX;
-#endif
-#ifdef reg_ECX
- env->regs[R_ECX] = ECX;
-#endif
-#ifdef reg_EDX
- env->regs[R_EDX] = EDX;
-#endif
-#ifdef reg_EBX
- env->regs[R_EBX] = EBX;
-#endif
-#ifdef reg_ESP
- env->regs[R_ESP] = ESP;
-#endif
-#ifdef reg_EBP
- env->regs[R_EBP] = EBP;
-#endif
-#ifdef reg_ESI
- env->regs[R_ESI] = ESI;
-#endif
-#ifdef reg_EDI
- env->regs[R_EDI] = EDI;
-#endif
- longjmp(env->jmp_env, 1);
-}
-
int cpu_x86_exec(CPUX86State *env1)
{
int saved_T0, saved_T1, saved_A0;
@@ -105,12 +53,15 @@ int cpu_x86_exec(CPUX86State *env1)
#ifdef reg_EDI
int saved_EDI;
#endif
+#ifdef __sparc__
+ int saved_i7, tmp_T0;
+#endif
int code_gen_size, ret;
void (*gen_func)(void);
TranslationBlock *tb, **ptb;
uint8_t *tc_ptr, *cs_base, *pc;
unsigned int flags;
-
+
/* first we save global registers */
saved_T0 = T0;
saved_T1 = T1;
@@ -149,6 +100,10 @@ int cpu_x86_exec(CPUX86State *env1)
saved_EDI = EDI;
EDI = env->regs[R_EDI];
#endif
+#ifdef __sparc__
+ /* we also save i7 because longjmp may not restore it */
+ asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
+#endif
/* put eflags in CPU temporary format */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -161,6 +116,10 @@ int cpu_x86_exec(CPUX86State *env1)
if (setjmp(env->jmp_env) == 0) {
T0 = 0; /* force lookup of first TB */
for(;;) {
+#ifdef __sparc__
+ /* g1 can be modified by some libc? functions */
+ tmp_T0 = T0;
+#endif
if (env->interrupt_request) {
env->exception_index = EXCP_INTERRUPT;
cpu_loop_exit();
@@ -240,23 +199,32 @@ int cpu_x86_exec(CPUX86State *env1)
lookup_symbol((void *)tb->pc));
}
#endif
+#ifdef __sparc__
+ T0 = tmp_T0;
+#endif
/* see if we can patch the calling TB */
if (T0 != 0 && !(env->eflags & TF_MASK)) {
spin_lock(&tb_lock);
tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
spin_unlock(&tb_lock);
}
-
tc_ptr = tb->tc_ptr;
/* execute the generated code */
gen_func = (void *)tc_ptr;
-#ifdef __sparc__
+#if defined(__sparc__)
__asm__ __volatile__("call %0\n\t"
- " mov %%o7,%%i0"
+ "mov %%o7,%%i0"
: /* no outputs */
: "r" (gen_func)
: "i0", "i1", "i2", "i3", "i4", "i5");
+#elif defined(__arm__)
+ asm volatile ("mov pc, %0\n\t"
+ ".global exec_loop\n\t"
+ "exec_loop:\n\t"
+ : /* no outputs */
+ : "r" (gen_func)
+ : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
#else
gen_func();
#endif
@@ -292,6 +260,9 @@ int cpu_x86_exec(CPUX86State *env1)
#ifdef reg_EDI
EDI = saved_EDI;
#endif
+#ifdef __sparc__
+ asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
+#endif
T0 = saved_T0;
T1 = saved_T1;
A0 = saved_A0;
@@ -457,6 +428,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
uint32_t insn = *pc;
int is_write = 0;
+ /* XXX: need kernel patch to get write flag faster */
switch (insn >> 26) {
case 0x0d: // stw
case 0x0e: // stb
@@ -475,6 +447,56 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask);
}
+#elif defined(__sparc__)
+
+int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
+ void *puc)
+{
+ uint32_t *regs = (uint32_t *)(info + 1);
+ void *sigmask = (regs + 20);
+ unsigned long pc;
+ int is_write;
+ uint32_t insn;
+
+ /* XXX: is there a standard glibc define ? */
+ pc = regs[1];
+ /* XXX: need kernel patch to get write flag faster */
+ is_write = 0;
+ insn = *(uint32_t *)pc;
+ if ((insn >> 30) == 3) {
+ switch((insn >> 19) & 0x3f) {
+ case 0x05: // stb
+ case 0x06: // sth
+ case 0x04: // st
+ case 0x07: // std
+ case 0x24: // stf
+ case 0x27: // stdf
+ case 0x25: // stfsr
+ is_write = 1;
+ break;
+ }
+ }
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ is_write, sigmask);
+}
+
+#elif defined(__arm__)
+
+int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
+ void *puc)
+{
+ struct ucontext *uc = puc;
+ unsigned long pc;
+ int is_write;
+
+ pc = uc->uc_mcontext.gregs[R15];
+ /* XXX: compute is_write */
+ is_write = 0;
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ is_write,
+ &uc->uc_sigmask);
+}
+
#else
#error CPU specific signal handler needed