summary refs log tree commit diff stats
path: root/linux-user/main.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-02-18 22:55:36 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-02-18 22:55:36 +0000
commit31e31b8a248ffa216223dad49f75efbdfca5df23 (patch)
tree7a2e4a2e20da5bd5d61f906f6d75dab2d3418e5f /linux-user/main.c
parente63c3dc74bfb90e4522d075d0d5a7600c5145745 (diff)
downloadfocaccia-qemu-31e31b8a248ffa216223dad49f75efbdfca5df23.tar.gz
focaccia-qemu-31e31b8a248ffa216223dad49f75efbdfca5df23.zip
This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/main.c')
-rw-r--r--linux-user/main.c310
1 files changed, 310 insertions, 0 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
new file mode 100644
index 0000000000..e3950835e3
--- /dev/null
+++ b/linux-user/main.c
@@ -0,0 +1,310 @@
+/*
+ *  emu main
+ * 
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <elf.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "gemu.h"
+
+#include "i386/hsw_interp.h"
+
+unsigned long x86_stack_size;
+unsigned long stktop;
+
+void gemu_log(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+
+/* virtual x86 CPU stuff */
+
+extern int invoke_code16(Interp_ENV *, int, int);
+extern int invoke_code32(Interp_ENV *, int);
+extern char *e_print_cpuemu_regs(ENVPARAMS, int is32);
+extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32);
+extern void init_npu(void);
+
+Interp_ENV env_global;
+Interp_ENV *envp_global;
+
+QWORD EMUtime = 0;
+
+int CEmuStat = 0;
+
+long instr_count;
+
+/* who will initialize this? */
+unsigned long io_bitmap[IO_BITMAP_SIZE+1];
+
+/* debug flag, 0=disable 1..9=level */
+int d_emu = 0;
+
+unsigned long CRs[5] =
+{
+	0x00000013,	/* valid bits: 0xe005003f */
+	0x00000000,	/* invalid */
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+/*
+ * DR0-3 = linear address of breakpoint 0-3
+ * DR4=5 = reserved
+ * DR6	b0-b3 = BP active
+ *	b13   = BD
+ *	b14   = BS
+ *	b15   = BT
+ * DR7	b0-b1 = G:L bp#0
+ *	b2-b3 = G:L bp#1
+ *	b4-b5 = G:L bp#2
+ *	b6-b7 = G:L bp#3
+ *	b8-b9 = GE:LE
+ *	b13   = GD
+ *	b16-19= LLRW bp#0	LL=00(1),01(2),11(4)
+ *	b20-23= LLRW bp#1	RW=00(x),01(w),11(rw)
+ *	b24-27= LLRW bp#2
+ *	b28-31= LLRW bp#3
+ */
+unsigned long DRs[8] =
+{
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0xffff1ff0,
+	0x00000400,
+	0xffff1ff0,
+	0x00000400
+};
+
+unsigned long TRs[2] =
+{
+	0x00000000,
+	0x00000000
+};
+
+void FatalAppExit(UINT wAction, LPCSTR lpText)
+{
+    fprintf(stderr, "Fatal error '%s' in CPU\n", lpText);
+    exit(1);
+}
+
+int e_debug_check(unsigned char *PC)
+{
+    register unsigned long d7 = DRs[7];
+
+    if (d7&0x03) {
+	if (d7&0x30000) return 0;	/* only execute(00) bkp */
+	if ((long)PC==DRs[0]) {
+	    e_printf("DBRK: DR0 hit at %p\n",PC);
+	    DRs[6] |= 1;
+	    return 1;
+	}
+    }
+    if (d7&0x0c) {
+	if (d7&0x300000) return 0;
+	if ((long)PC==DRs[1]) {
+	    e_printf("DBRK: DR1 hit at %p\n",PC);
+	    DRs[6] |= 2;
+	    return 1;
+	}
+    }
+    if (d7&0x30) {
+	if (d7&0x3000000) return 0;
+	if ((long)PC==DRs[2]) {
+	    e_printf("DBRK: DR2 hit at %p\n",PC);
+	    DRs[6] |= 4;
+	    return 1;
+	}
+    }
+    if (d7&0xc0) {
+	if (d7&0x30000000) return 0;
+	if ((long)PC==DRs[3]) {
+	    e_printf("DBRK: DR3 hit at %p\n",PC);
+	    DRs[6] |= 8;
+	    return 1;
+	}
+    }
+    return 0;
+}
+
+/* Debug stuff */
+void logstr(unsigned long mask, const char *fmt,...) 
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+
+/* unconditional message into debug log and stderr */
+#undef error
+void error(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    exit(1);
+}
+
+int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write)
+{
+    fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d",
+            is_write ? "write" : "read", port, value, size);
+    return value;
+}
+
+void LogProcName(WORD wSel, WORD wOff, WORD wAction)
+{
+
+}
+
+void INT_handler(int num, void *env)
+{
+  fprintf(stderr, "EM86: int %d\n", num);
+}
+
+/***********************************************************/
+
+/* XXX: currently we use LDT entries */
+#define __USER_CS	(0x23|4)
+#define __USER_DS	(0x2B|4)
+
+void usage(void)
+{
+    printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n"
+           "usage: gemu program [arguments...]\n"
+           "Linux x86 emulator\n"
+           );
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    const char *filename;
+    struct pt_regs regs1, *regs = &regs1;
+    struct image_info info1, *info = &info1;
+    Interp_ENV *env;
+
+    if (argc <= 1)
+        usage();
+    
+    filename = argv[1];
+
+    /* Zero out regs */
+    memset(regs, 0, sizeof(struct pt_regs));
+
+    /* Zero out image_info */
+    memset(info, 0, sizeof(struct image_info));
+
+    if(elf_exec(filename, argv+1, __environ, regs, info) != 0) {
+	printf("Error loading %s\n", filename);
+	exit(1);
+    }
+    
+#if 0
+    printf("start_brk   0x%08lx\n" , info->start_brk);
+    printf("end_code    0x%08lx\n" , info->end_code);
+    printf("start_code  0x%08lx\n" , info->start_code);
+    printf("end_data    0x%08lx\n" , info->end_data);
+    printf("start_stack 0x%08lx\n" , info->start_stack);
+    printf("brk         0x%08lx\n" , info->brk);
+    printf("esp         0x%08lx\n" , regs->esp);
+    printf("eip         0x%08lx\n" , regs->eip);
+#endif
+
+    target_set_brk((char *)info->brk);
+    syscall_init();
+
+    env = &env_global;
+    envp_global = env;
+    memset(env, 0, sizeof(Interp_ENV));
+
+    env->rax.e   = regs->eax;
+    env->rbx.e   = regs->ebx;
+    env->rcx.e   = regs->ecx;
+    env->rdx.e   = regs->edx;
+    env->rsi.esi = regs->esi;
+    env->rdi.edi = regs->edi;
+    env->rbp.ebp = regs->ebp;
+    env->rsp.esp = regs->esp;
+    env->cs.cs   = __USER_CS;
+    env->ds.ds   = __USER_DS;
+    env->es.es   = __USER_DS;
+    env->ss.ss   = __USER_DS;
+    env->fs.fs   = __USER_DS;
+    env->gs.gs   = __USER_DS;
+    env->trans_addr = regs->eip;
+
+    LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
+    LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
+    LDT[__USER_CS >> 3].lpSelBase = NULL;
+
+    LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
+    LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
+    LDT[__USER_DS >> 3].lpSelBase = NULL;
+    init_npu();
+
+    for(;;) {
+        int err;
+        uint8_t *pc;
+
+        err = invoke_code32(env, -1);
+        env->trans_addr = env->return_addr;
+        pc = env->seg_regs[0] + env->trans_addr;
+        switch(err) {
+        case EXCP0D_GPF:
+            if (pc[0] == 0xcd && pc[1] == 0x80) {
+                /* syscall */
+                env->trans_addr += 2;
+                env->rax.e = do_syscall(env->rax.e, 
+                                        env->rbx.e,
+                                        env->rcx.e,
+                                        env->rdx.e,
+                                        env->rsi.esi,
+                                        env->rdi.edi,
+                                        env->rbp.ebp);
+            } else {
+                goto trap_error;
+            }
+            break;
+        default:
+        trap_error:
+            fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
+            d_emu = 9;
+            fprintf(stderr, "%s\n%s\n",
+                    e_print_cpuemu_regs(env, 1), 
+                    e_emu_disasm(env,pc,1));
+            abort();
+        }
+    }
+    return 0;
+}