Statistics
| Branch: | Revision:

root / linux-user / main.c @ 367e86e8

History | View | Annotate | Download (7.7 kB)

1
/*
2
 *  emu main
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program 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
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <stdarg.h>
23
#include <errno.h>
24

    
25
#include "gemu.h"
26

    
27
#include "i386/hsw_interp.h"
28

    
29
unsigned long x86_stack_size;
30
unsigned long stktop;
31

    
32
void gemu_log(const char *fmt, ...)
33
{
34
    va_list ap;
35

    
36
    va_start(ap, fmt);
37
    vfprintf(stderr, fmt, ap);
38
    va_end(ap);
39
}
40

    
41
/* virtual x86 CPU stuff */
42

    
43
extern int invoke_code16(Interp_ENV *, int, int);
44
extern int invoke_code32(Interp_ENV *, int);
45
extern char *e_print_cpuemu_regs(ENVPARAMS, int is32);
46
extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32);
47
extern void init_npu(void);
48

    
49
Interp_ENV env_global;
50
Interp_ENV *envp_global;
51

    
52
QWORD EMUtime = 0;
53

    
54
int CEmuStat = 0;
55

    
56
long instr_count;
57

    
58
/* who will initialize this? */
59
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
60

    
61
/* debug flag, 0=disable 1..9=level */
62
int d_emu = 0;
63

    
64
unsigned long CRs[5] =
65
{
66
        0x00000013,        /* valid bits: 0xe005003f */
67
        0x00000000,        /* invalid */
68
        0x00000000,
69
        0x00000000,
70
        0x00000000
71
};
72

    
73
/*
74
 * DR0-3 = linear address of breakpoint 0-3
75
 * DR4=5 = reserved
76
 * DR6        b0-b3 = BP active
77
 *        b13   = BD
78
 *        b14   = BS
79
 *        b15   = BT
80
 * DR7        b0-b1 = G:L bp#0
81
 *        b2-b3 = G:L bp#1
82
 *        b4-b5 = G:L bp#2
83
 *        b6-b7 = G:L bp#3
84
 *        b8-b9 = GE:LE
85
 *        b13   = GD
86
 *        b16-19= LLRW bp#0        LL=00(1),01(2),11(4)
87
 *        b20-23= LLRW bp#1        RW=00(x),01(w),11(rw)
88
 *        b24-27= LLRW bp#2
89
 *        b28-31= LLRW bp#3
90
 */
91
unsigned long DRs[8] =
92
{
93
        0x00000000,
94
        0x00000000,
95
        0x00000000,
96
        0x00000000,
97
        0xffff1ff0,
98
        0x00000400,
99
        0xffff1ff0,
100
        0x00000400
101
};
102

    
103
unsigned long TRs[2] =
104
{
105
        0x00000000,
106
        0x00000000
107
};
108

    
109
void FatalAppExit(UINT wAction, LPCSTR lpText)
110
{
111
    fprintf(stderr, "Fatal error '%s' in CPU\n", lpText);
112
    exit(1);
113
}
114

    
115
int e_debug_check(unsigned char *PC)
116
{
117
    register unsigned long d7 = DRs[7];
118

    
119
    if (d7&0x03) {
120
        if (d7&0x30000) return 0;        /* only execute(00) bkp */
121
        if ((long)PC==DRs[0]) {
122
            e_printf("DBRK: DR0 hit at %p\n",PC);
123
            DRs[6] |= 1;
124
            return 1;
125
        }
126
    }
127
    if (d7&0x0c) {
128
        if (d7&0x300000) return 0;
129
        if ((long)PC==DRs[1]) {
130
            e_printf("DBRK: DR1 hit at %p\n",PC);
131
            DRs[6] |= 2;
132
            return 1;
133
        }
134
    }
135
    if (d7&0x30) {
136
        if (d7&0x3000000) return 0;
137
        if ((long)PC==DRs[2]) {
138
            e_printf("DBRK: DR2 hit at %p\n",PC);
139
            DRs[6] |= 4;
140
            return 1;
141
        }
142
    }
143
    if (d7&0xc0) {
144
        if (d7&0x30000000) return 0;
145
        if ((long)PC==DRs[3]) {
146
            e_printf("DBRK: DR3 hit at %p\n",PC);
147
            DRs[6] |= 8;
148
            return 1;
149
        }
150
    }
151
    return 0;
152
}
153

    
154
/* Debug stuff */
155
void logstr(unsigned long mask, const char *fmt,...) 
156
{
157
    va_list ap;
158

    
159
    va_start(ap, fmt);
160
    vfprintf(stderr, fmt, ap);
161
    va_end(ap);
162
}
163

    
164
/* unconditional message into debug log and stderr */
165
#undef error
166
void error(const char *fmt, ...)
167
{
168
    va_list ap;
169

    
170
    va_start(ap, fmt);
171
    vfprintf(stderr, fmt, ap);
172
    va_end(ap);
173
    exit(1);
174
}
175

    
176
int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write)
177
{
178
    fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d",
179
            is_write ? "write" : "read", port, value, size);
180
    return value;
181
}
182

    
183
void LogProcName(WORD wSel, WORD wOff, WORD wAction)
184
{
185

    
186
}
187

    
188
void INT_handler(int num, void *env)
189
{
190
  fprintf(stderr, "EM86: int %d\n", num);
191
}
192

    
193
/***********************************************************/
194
/* new CPU core */
195

    
196
void port_outb(int addr, int val)
197
{
198
    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
199
}
200

    
201
void port_outw(int addr, int val)
202
{
203
    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
204
}
205

    
206
void port_outl(int addr, int val)
207
{
208
    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
209
}
210

    
211
int port_inb(int addr)
212
{
213
    fprintf(stderr, "inb: port=0x%04x\n", addr);
214
    return 0;
215
}
216

    
217
int port_inw(int addr)
218
{
219
    fprintf(stderr, "inw: port=0x%04x\n", addr);
220
    return 0;
221
}
222

    
223
int port_inl(int addr)
224
{
225
    fprintf(stderr, "inl: port=0x%04x\n", addr);
226
    return 0;
227
}
228

    
229

    
230
/* XXX: currently we use LDT entries */
231
#define __USER_CS        (0x23|4)
232
#define __USER_DS        (0x2B|4)
233

    
234
void usage(void)
235
{
236
    printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n"
237
           "usage: gemu program [arguments...]\n"
238
           "Linux x86 emulator\n"
239
           );
240
    exit(1);
241
}
242

    
243
int main(int argc, char **argv)
244
{
245
    const char *filename;
246
    struct target_pt_regs regs1, *regs = &regs1;
247
    struct image_info info1, *info = &info1;
248
    Interp_ENV *env;
249

    
250
    if (argc <= 1)
251
        usage();
252
    
253
    filename = argv[1];
254

    
255
    /* Zero out regs */
256
    memset(regs, 0, sizeof(struct target_pt_regs));
257

    
258
    /* Zero out image_info */
259
    memset(info, 0, sizeof(struct image_info));
260

    
261
    if(elf_exec(filename, argv+1, environ, regs, info) != 0) {
262
        printf("Error loading %s\n", filename);
263
        exit(1);
264
    }
265
    
266
#if 0
267
    printf("start_brk   0x%08lx\n" , info->start_brk);
268
    printf("end_code    0x%08lx\n" , info->end_code);
269
    printf("start_code  0x%08lx\n" , info->start_code);
270
    printf("end_data    0x%08lx\n" , info->end_data);
271
    printf("start_stack 0x%08lx\n" , info->start_stack);
272
    printf("brk         0x%08lx\n" , info->brk);
273
    printf("esp         0x%08lx\n" , regs->esp);
274
    printf("eip         0x%08lx\n" , regs->eip);
275
#endif
276

    
277
    target_set_brk((char *)info->brk);
278
    syscall_init();
279

    
280
    env = &env_global;
281
    envp_global = env;
282
    memset(env, 0, sizeof(Interp_ENV));
283

    
284
    env->rax.e   = regs->eax;
285
    env->rbx.e   = regs->ebx;
286
    env->rcx.e   = regs->ecx;
287
    env->rdx.e   = regs->edx;
288
    env->rsi.esi = regs->esi;
289
    env->rdi.edi = regs->edi;
290
    env->rbp.ebp = regs->ebp;
291
    env->rsp.esp = regs->esp;
292
    env->cs.cs   = __USER_CS;
293
    env->ds.ds   = __USER_DS;
294
    env->es.es   = __USER_DS;
295
    env->ss.ss   = __USER_DS;
296
    env->fs.fs   = __USER_DS;
297
    env->gs.gs   = __USER_DS;
298
    env->trans_addr = regs->eip;
299

    
300
    LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
301
    LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
302
    LDT[__USER_CS >> 3].lpSelBase = NULL;
303

    
304
    LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
305
    LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
306
    LDT[__USER_DS >> 3].lpSelBase = NULL;
307
    init_npu();
308
    build_decode_tables();
309

    
310
    for(;;) {
311
        int err;
312
        uint8_t *pc;
313

    
314
        err = invoke_code32(env, -1);
315
        env->trans_addr = env->return_addr;
316
        pc = env->seg_regs[0] + env->trans_addr;
317
        switch(err) {
318
        case EXCP0D_GPF:
319
            if (pc[0] == 0xcd && pc[1] == 0x80) {
320
                /* syscall */
321
                env->trans_addr += 2;
322
                env->rax.e = do_syscall(env->rax.e, 
323
                                        env->rbx.e,
324
                                        env->rcx.e,
325
                                        env->rdx.e,
326
                                        env->rsi.esi,
327
                                        env->rdi.edi,
328
                                        env->rbp.ebp);
329
            } else {
330
                goto trap_error;
331
            }
332
            break;
333
        default:
334
        trap_error:
335
            fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
336
#ifndef NO_TRACE_MSGS
337
            d_emu = 9;
338
            fprintf(stderr, "%s\n%s\n",
339
                    e_print_cpuemu_regs(env, 1), 
340
                    e_emu_disasm(env,pc,1));
341
#endif
342
            abort();
343
        }
344
    }
345
    return 0;
346
}