Statistics
| Branch: | Revision:

root / exec-i386.c @ 7d13299d

History | View | Annotate | Download (5.8 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  i386 emulator main execution loop
3 7d13299d bellard
 * 
4 7d13299d bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 7d13299d bellard
 *
6 7d13299d bellard
 *  This program is free software; you can redistribute it and/or modify
7 7d13299d bellard
 *  it under the terms of the GNU General Public License as published by
8 7d13299d bellard
 *  the Free Software Foundation; either version 2 of the License, or
9 7d13299d bellard
 *  (at your option) any later version.
10 7d13299d bellard
 *
11 7d13299d bellard
 *  This program is distributed in the hope that it will be useful,
12 7d13299d bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 7d13299d bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 7d13299d bellard
 *  GNU General Public License for more details.
15 7d13299d bellard
 *
16 7d13299d bellard
 *  You should have received a copy of the GNU General Public License
17 7d13299d bellard
 *  along with this program; if not, write to the Free Software
18 7d13299d bellard
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 7d13299d bellard
 */
20 7d13299d bellard
#include "exec-i386.h"
21 7d13299d bellard
22 7d13299d bellard
#define DEBUG_EXEC
23 7d13299d bellard
#define DEBUG_FLUSH
24 7d13299d bellard
25 7d13299d bellard
/* main execution loop */
26 7d13299d bellard
27 7d13299d bellard
/* maximum total translate dcode allocated */
28 7d13299d bellard
#define CODE_GEN_BUFFER_SIZE     (2048 * 1024)
29 7d13299d bellard
//#define CODE_GEN_BUFFER_SIZE     (128 * 1024)
30 7d13299d bellard
#define CODE_GEN_MAX_SIZE        65536
31 7d13299d bellard
#define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
32 7d13299d bellard
33 7d13299d bellard
/* threshold to flush the translated code buffer */
34 7d13299d bellard
#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
35 7d13299d bellard
36 7d13299d bellard
#define CODE_GEN_MAX_BLOCKS    (CODE_GEN_BUFFER_SIZE / 64)
37 7d13299d bellard
#define CODE_GEN_HASH_BITS     15
38 7d13299d bellard
#define CODE_GEN_HASH_SIZE     (1 << CODE_GEN_HASH_BITS)
39 7d13299d bellard
typedef struct TranslationBlock {
40 7d13299d bellard
    unsigned long pc;   /* simulated PC corresponding to this block */
41 7d13299d bellard
    uint8_t *tc_ptr;    /* pointer to the translated code */
42 7d13299d bellard
    struct TranslationBlock *hash_next; /* next matching block */
43 7d13299d bellard
} TranslationBlock;
44 7d13299d bellard
45 7d13299d bellard
TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
46 7d13299d bellard
TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
47 7d13299d bellard
int nb_tbs;
48 7d13299d bellard
49 7d13299d bellard
uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
50 7d13299d bellard
uint8_t *code_gen_ptr;
51 7d13299d bellard
52 7d13299d bellard
#ifdef DEBUG_EXEC
53 7d13299d bellard
static const char *cc_op_str[] = {
54 7d13299d bellard
    "DYNAMIC",
55 7d13299d bellard
    "EFLAGS",
56 7d13299d bellard
    "MUL",
57 7d13299d bellard
    "ADDB",
58 7d13299d bellard
    "ADDW",
59 7d13299d bellard
    "ADDL",
60 7d13299d bellard
    "ADCB",
61 7d13299d bellard
    "ADCW",
62 7d13299d bellard
    "ADCL",
63 7d13299d bellard
    "SUBB",
64 7d13299d bellard
    "SUBW",
65 7d13299d bellard
    "SUBL",
66 7d13299d bellard
    "SBBB",
67 7d13299d bellard
    "SBBW",
68 7d13299d bellard
    "SBBL",
69 7d13299d bellard
    "LOGICB",
70 7d13299d bellard
    "LOGICW",
71 7d13299d bellard
    "LOGICL",
72 7d13299d bellard
    "INCB",
73 7d13299d bellard
    "INCW",
74 7d13299d bellard
    "INCL",
75 7d13299d bellard
    "DECB",
76 7d13299d bellard
    "DECW",
77 7d13299d bellard
    "DECL",
78 7d13299d bellard
    "SHLB",
79 7d13299d bellard
    "SHLW",
80 7d13299d bellard
    "SHLL",
81 7d13299d bellard
    "SARB",
82 7d13299d bellard
    "SARW",
83 7d13299d bellard
    "SARL",
84 7d13299d bellard
};
85 7d13299d bellard
86 7d13299d bellard
static void cpu_x86_dump_state(void)
87 7d13299d bellard
{
88 7d13299d bellard
    int eflags;
89 7d13299d bellard
    eflags = cc_table[CC_OP].compute_all();
90 7d13299d bellard
    eflags |= (DF & DIRECTION_FLAG);
91 7d13299d bellard
    fprintf(logfile, 
92 7d13299d bellard
            "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
93 7d13299d bellard
            "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
94 7d13299d bellard
            "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
95 7d13299d bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
96 7d13299d bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
97 7d13299d bellard
            env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
98 7d13299d bellard
            eflags & DIRECTION_FLAG ? 'D' : '-',
99 7d13299d bellard
            eflags & CC_O ? 'O' : '-',
100 7d13299d bellard
            eflags & CC_S ? 'S' : '-',
101 7d13299d bellard
            eflags & CC_Z ? 'Z' : '-',
102 7d13299d bellard
            eflags & CC_A ? 'A' : '-',
103 7d13299d bellard
            eflags & CC_P ? 'P' : '-',
104 7d13299d bellard
            eflags & CC_C ? 'C' : '-'
105 7d13299d bellard
            );
106 7d13299d bellard
#if 1
107 7d13299d bellard
    fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
108 7d13299d bellard
            (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
109 7d13299d bellard
#endif
110 7d13299d bellard
}
111 7d13299d bellard
112 7d13299d bellard
#endif
113 7d13299d bellard
114 7d13299d bellard
void cpu_x86_tblocks_init(void)
115 7d13299d bellard
{
116 7d13299d bellard
    if (!code_gen_ptr) {
117 7d13299d bellard
        code_gen_ptr = code_gen_buffer;
118 7d13299d bellard
    }
119 7d13299d bellard
}
120 7d13299d bellard
121 7d13299d bellard
/* flush all the translation blocks */
122 7d13299d bellard
static void tb_flush(void)
123 7d13299d bellard
{
124 7d13299d bellard
    int i;
125 7d13299d bellard
#ifdef DEBUG_FLUSH
126 7d13299d bellard
    printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", 
127 7d13299d bellard
           code_gen_ptr - code_gen_buffer, 
128 7d13299d bellard
           nb_tbs, 
129 7d13299d bellard
           (code_gen_ptr - code_gen_buffer) / nb_tbs);
130 7d13299d bellard
#endif
131 7d13299d bellard
    nb_tbs = 0;
132 7d13299d bellard
    for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
133 7d13299d bellard
        tb_hash[i] = NULL;
134 7d13299d bellard
    code_gen_ptr = code_gen_buffer;
135 7d13299d bellard
    /* XXX: flush processor icache at this point */
136 7d13299d bellard
}
137 7d13299d bellard
138 7d13299d bellard
/* find a translation block in the translation cache. If not found,
139 7d13299d bellard
   allocate a new one */
140 7d13299d bellard
static inline TranslationBlock *tb_find_and_alloc(unsigned long pc)
141 7d13299d bellard
{
142 7d13299d bellard
    TranslationBlock **ptb, *tb;
143 7d13299d bellard
    unsigned int h;
144 7d13299d bellard
 
145 7d13299d bellard
    h = pc & (CODE_GEN_HASH_SIZE - 1);
146 7d13299d bellard
    ptb = &tb_hash[h];
147 7d13299d bellard
    for(;;) {
148 7d13299d bellard
        tb = *ptb;
149 7d13299d bellard
        if (!tb)
150 7d13299d bellard
            break;
151 7d13299d bellard
        if (tb->pc == pc)
152 7d13299d bellard
            return tb;
153 7d13299d bellard
        ptb = &tb->hash_next;
154 7d13299d bellard
    }
155 7d13299d bellard
    if (nb_tbs >= CODE_GEN_MAX_BLOCKS || 
156 7d13299d bellard
        (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
157 7d13299d bellard
        tb_flush();
158 7d13299d bellard
    tb = &tbs[nb_tbs++];
159 7d13299d bellard
    *ptb = tb;
160 7d13299d bellard
    tb->pc = pc;
161 7d13299d bellard
    tb->tc_ptr = NULL;
162 7d13299d bellard
    tb->hash_next = NULL;
163 7d13299d bellard
    return tb;
164 7d13299d bellard
}
165 7d13299d bellard
166 7d13299d bellard
int cpu_x86_exec(CPUX86State *env1)
167 7d13299d bellard
{
168 7d13299d bellard
    int saved_T0, saved_T1, saved_A0;
169 7d13299d bellard
    CPUX86State *saved_env;
170 7d13299d bellard
    int code_gen_size, ret;
171 7d13299d bellard
    void (*gen_func)(void);
172 7d13299d bellard
    TranslationBlock *tb;
173 7d13299d bellard
    uint8_t *tc_ptr;
174 7d13299d bellard
    
175 7d13299d bellard
    /* first we save global registers */
176 7d13299d bellard
    saved_T0 = T0;
177 7d13299d bellard
    saved_T1 = T1;
178 7d13299d bellard
    saved_A0 = A0;
179 7d13299d bellard
    saved_env = env;
180 7d13299d bellard
    env = env1;
181 7d13299d bellard
    
182 7d13299d bellard
    /* prepare setjmp context for exception handling */
183 7d13299d bellard
    if (setjmp(env->jmp_env) == 0) {
184 7d13299d bellard
        for(;;) {
185 7d13299d bellard
#ifdef DEBUG_EXEC
186 7d13299d bellard
            if (loglevel) {
187 7d13299d bellard
                cpu_x86_dump_state();
188 7d13299d bellard
            }
189 7d13299d bellard
#endif
190 7d13299d bellard
            tb = tb_find_and_alloc((unsigned long)env->pc);
191 7d13299d bellard
            tc_ptr = tb->tc_ptr;
192 7d13299d bellard
            if (!tb->tc_ptr) {
193 7d13299d bellard
                /* if no translated code available, then translate it now */
194 7d13299d bellard
                tc_ptr = code_gen_ptr;
195 7d13299d bellard
                cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE, 
196 7d13299d bellard
                                 &code_gen_size, (uint8_t *)env->pc);
197 7d13299d bellard
                tb->tc_ptr = tc_ptr;
198 7d13299d bellard
                code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
199 7d13299d bellard
            }
200 7d13299d bellard
            /* execute the generated code */
201 7d13299d bellard
            gen_func = (void *)tc_ptr;
202 7d13299d bellard
            gen_func();
203 7d13299d bellard
        }
204 7d13299d bellard
    }
205 7d13299d bellard
    ret = env->exception_index;
206 7d13299d bellard
207 7d13299d bellard
    /* restore global registers */
208 7d13299d bellard
    T0 = saved_T0;
209 7d13299d bellard
    T1 = saved_T1;
210 7d13299d bellard
    A0 = saved_A0;
211 7d13299d bellard
    env = saved_env;
212 7d13299d bellard
    return ret;
213 7d13299d bellard
}