Statistics
| Branch: | Revision:

root / linux-user / main.c @ 5147f5aa

History | View | Annotate | Download (7.1 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

    
195
/* XXX: currently we use LDT entries */
196
#define __USER_CS        (0x23|4)
197
#define __USER_DS        (0x2B|4)
198

    
199
void usage(void)
200
{
201
    printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n"
202
           "usage: gemu program [arguments...]\n"
203
           "Linux x86 emulator\n"
204
           );
205
    exit(1);
206
}
207

    
208
int main(int argc, char **argv)
209
{
210
    const char *filename;
211
    struct target_pt_regs regs1, *regs = &regs1;
212
    struct image_info info1, *info = &info1;
213
    Interp_ENV *env;
214

    
215
    if (argc <= 1)
216
        usage();
217
    
218
    filename = argv[1];
219

    
220
    /* Zero out regs */
221
    memset(regs, 0, sizeof(struct target_pt_regs));
222

    
223
    /* Zero out image_info */
224
    memset(info, 0, sizeof(struct image_info));
225

    
226
    if(elf_exec(filename, argv+1, environ, regs, info) != 0) {
227
        printf("Error loading %s\n", filename);
228
        exit(1);
229
    }
230
    
231
#if 0
232
    printf("start_brk   0x%08lx\n" , info->start_brk);
233
    printf("end_code    0x%08lx\n" , info->end_code);
234
    printf("start_code  0x%08lx\n" , info->start_code);
235
    printf("end_data    0x%08lx\n" , info->end_data);
236
    printf("start_stack 0x%08lx\n" , info->start_stack);
237
    printf("brk         0x%08lx\n" , info->brk);
238
    printf("esp         0x%08lx\n" , regs->esp);
239
    printf("eip         0x%08lx\n" , regs->eip);
240
#endif
241

    
242
    target_set_brk((char *)info->brk);
243
    syscall_init();
244

    
245
    env = &env_global;
246
    envp_global = env;
247
    memset(env, 0, sizeof(Interp_ENV));
248

    
249
    env->rax.e   = regs->eax;
250
    env->rbx.e   = regs->ebx;
251
    env->rcx.e   = regs->ecx;
252
    env->rdx.e   = regs->edx;
253
    env->rsi.esi = regs->esi;
254
    env->rdi.edi = regs->edi;
255
    env->rbp.ebp = regs->ebp;
256
    env->rsp.esp = regs->esp;
257
    env->cs.cs   = __USER_CS;
258
    env->ds.ds   = __USER_DS;
259
    env->es.es   = __USER_DS;
260
    env->ss.ss   = __USER_DS;
261
    env->fs.fs   = __USER_DS;
262
    env->gs.gs   = __USER_DS;
263
    env->trans_addr = regs->eip;
264

    
265
    LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
266
    LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
267
    LDT[__USER_CS >> 3].lpSelBase = NULL;
268

    
269
    LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
270
    LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
271
    LDT[__USER_DS >> 3].lpSelBase = NULL;
272
    init_npu();
273

    
274
    for(;;) {
275
        int err;
276
        uint8_t *pc;
277

    
278
        err = invoke_code32(env, -1);
279
        env->trans_addr = env->return_addr;
280
        pc = env->seg_regs[0] + env->trans_addr;
281
        switch(err) {
282
        case EXCP0D_GPF:
283
            if (pc[0] == 0xcd && pc[1] == 0x80) {
284
                /* syscall */
285
                env->trans_addr += 2;
286
                env->rax.e = do_syscall(env->rax.e, 
287
                                        env->rbx.e,
288
                                        env->rcx.e,
289
                                        env->rdx.e,
290
                                        env->rsi.esi,
291
                                        env->rdi.edi,
292
                                        env->rbp.ebp);
293
            } else {
294
                goto trap_error;
295
            }
296
            break;
297
        default:
298
        trap_error:
299
            fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
300
#ifndef NO_TRACE_MSGS
301
            d_emu = 9;
302
            fprintf(stderr, "%s\n%s\n",
303
                    e_print_cpuemu_regs(env, 1), 
304
                    e_emu_disasm(env,pc,1));
305
#endif
306
            abort();
307
        }
308
    }
309
    return 0;
310
}