Revision 5fafdf24 target-i386/translate-copy.c
b/target-i386/translate-copy.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* i386 on i386 translation |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2003 Fabrice Bellard |
5 | 5 |
* |
6 | 6 |
* This library is free software; you can redistribute it and/or |
... | ... | |
42 | 42 |
enum { |
43 | 43 |
OT_BYTE = 0, |
44 | 44 |
OT_WORD, |
45 |
OT_LONG,
|
|
45 |
OT_LONG, |
|
46 | 46 |
OT_QUAD, |
47 | 47 |
}; |
48 | 48 |
|
... | ... | |
63 | 63 |
/* code output */ |
64 | 64 |
uint8_t *gen_code_ptr; |
65 | 65 |
uint8_t *gen_code_start; |
66 |
|
|
66 |
|
|
67 | 67 |
/* current block context */ |
68 | 68 |
target_ulong cs_base; /* base of CS segment */ |
69 | 69 |
int pe; /* protected mode */ |
... | ... | |
105 | 105 |
gl(s, val - (long)(s->gen_code_ptr + 4)); |
106 | 106 |
} |
107 | 107 |
|
108 |
static inline void gen_movl_addr_im(DisasContext *s,
|
|
108 |
static inline void gen_movl_addr_im(DisasContext *s, |
|
109 | 109 |
uint32_t addr, uint32_t val) |
110 | 110 |
{ |
111 | 111 |
gb(s, CPU_SEG); /* seg movl im, addr */ |
112 |
gb(s, 0xc7);
|
|
112 |
gb(s, 0xc7); |
|
113 | 113 |
gb(s, 0x05); |
114 | 114 |
gl(s, addr); |
115 | 115 |
gl(s, val); |
116 | 116 |
} |
117 | 117 |
|
118 |
static inline void gen_movw_addr_im(DisasContext *s,
|
|
118 |
static inline void gen_movw_addr_im(DisasContext *s, |
|
119 | 119 |
uint32_t addr, uint32_t val) |
120 | 120 |
{ |
121 | 121 |
gb(s, CPU_SEG); /* seg movl im, addr */ |
122 |
gb(s, 0x66);
|
|
123 |
gb(s, 0xc7);
|
|
122 |
gb(s, 0x66); |
|
123 |
gb(s, 0xc7); |
|
124 | 124 |
gb(s, 0x05); |
125 | 125 |
gl(s, addr); |
126 | 126 |
gw(s, val); |
... | ... | |
155 | 155 |
gb(s, 0xe9); /* jmp */ |
156 | 156 |
tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start; |
157 | 157 |
gl(s, 0); |
158 |
|
|
158 |
|
|
159 | 159 |
tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start; |
160 | 160 |
gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip); |
161 | 161 |
gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb); |
... | ... | |
194 | 194 |
base = rm; |
195 | 195 |
index = 0; |
196 | 196 |
scale = 0; |
197 |
|
|
197 |
|
|
198 | 198 |
if (base == 4) { |
199 | 199 |
havesib = 1; |
200 | 200 |
code = ldub_code(s->pc++); |
... | ... | |
222 | 222 |
s->pc += 4; |
223 | 223 |
break; |
224 | 224 |
} |
225 |
|
|
225 |
|
|
226 | 226 |
} else { |
227 | 227 |
switch (mod) { |
228 | 228 |
case 0: |
... | ... | |
248 | 248 |
static inline void parse_modrm(DisasContext *s, int modrm) |
249 | 249 |
{ |
250 | 250 |
if ((modrm & 0xc0) != 0xc0) |
251 |
gen_lea_modrm(s, modrm);
|
|
251 |
gen_lea_modrm(s, modrm); |
|
252 | 252 |
} |
253 | 253 |
|
254 | 254 |
static inline uint32_t insn_get(DisasContext *s, int ot) |
... | ... | |
351 | 351 |
/* extended op code */ |
352 | 352 |
b = ldub_code(s->pc++) | 0x100; |
353 | 353 |
goto reswitch; |
354 |
|
|
354 |
|
|
355 | 355 |
/**************************/ |
356 | 356 |
/* arith & logic */ |
357 | 357 |
case 0x00 ... 0x05: |
... | ... | |
370 | 370 |
ot = OT_BYTE; |
371 | 371 |
else |
372 | 372 |
ot = dflag ? OT_LONG : OT_WORD; |
373 |
|
|
373 |
|
|
374 | 374 |
switch(f) { |
375 | 375 |
case 0: /* OP Ev, Gv */ |
376 | 376 |
modrm = ldub_code(s->pc++); |
... | ... | |
396 | 396 |
ot = OT_BYTE; |
397 | 397 |
else |
398 | 398 |
ot = dflag ? OT_LONG : OT_WORD; |
399 |
|
|
399 |
|
|
400 | 400 |
modrm = ldub_code(s->pc++); |
401 | 401 |
parse_modrm(s, modrm); |
402 | 402 |
|
... | ... | |
475 | 475 |
break; |
476 | 476 |
case 2: /* call Ev */ |
477 | 477 |
/* XXX: optimize and handle MEM exceptions specifically |
478 |
fs movl %eax, regs[0]
|
|
479 |
movl Ev, %eax
|
|
478 |
fs movl %eax, regs[0] |
|
479 |
movl Ev, %eax |
|
480 | 480 |
pushl next_eip |
481 | 481 |
fs movl %eax, eip |
482 | 482 |
*/ |
... | ... | |
485 | 485 |
goto unsupported_op; |
486 | 486 |
case 4: /* jmp Ev */ |
487 | 487 |
/* XXX: optimize and handle MEM exceptions specifically |
488 |
fs movl %eax, regs[0]
|
|
489 |
movl Ev, %eax
|
|
488 |
fs movl %eax, regs[0] |
|
489 |
movl Ev, %eax |
|
490 | 490 |
fs movl %eax, eip |
491 | 491 |
*/ |
492 | 492 |
goto unsupported_op; |
... | ... | |
506 | 506 |
ot = dflag ? OT_LONG : OT_WORD; |
507 | 507 |
insn_get(s, ot); |
508 | 508 |
break; |
509 |
|
|
509 |
|
|
510 | 510 |
case 0x98: /* CWDE/CBW */ |
511 | 511 |
break; |
512 | 512 |
case 0x99: /* CDQ/CWD */ |
... | ... | |
526 | 526 |
break; |
527 | 527 |
|
528 | 528 |
case 0x84: /* test Ev, Gv */ |
529 |
case 0x85:
|
|
530 |
|
|
529 |
case 0x85: |
|
530 |
|
|
531 | 531 |
case 0x1c0: |
532 | 532 |
case 0x1c1: /* xadd Ev, Gv */ |
533 | 533 |
|
... | ... | |
583 | 583 |
goto illegal_op; |
584 | 584 |
parse_modrm(s, modrm); |
585 | 585 |
break; |
586 |
|
|
586 |
|
|
587 | 587 |
/**************************/ |
588 | 588 |
/* push/pop */ |
589 | 589 |
case 0x50 ... 0x57: /* push */ |
... | ... | |
654 | 654 |
goto unsupported_op; |
655 | 655 |
/************************/ |
656 | 656 |
/* floats */ |
657 |
case 0xd8 ... 0xdf:
|
|
657 |
case 0xd8 ... 0xdf: |
|
658 | 658 |
#if 1 |
659 | 659 |
/* currently not stable enough */ |
660 | 660 |
goto unsupported_op; |
... | ... | |
850 | 850 |
goto illegal_op; |
851 | 851 |
parse_modrm(s, modrm); |
852 | 852 |
break; |
853 |
|
|
853 |
|
|
854 | 854 |
case 0xa0: /* mov EAX, Ov */ |
855 | 855 |
case 0xa1: |
856 | 856 |
case 0xa2: /* mov Ov, EAX */ |
... | ... | |
888 | 888 |
parse_modrm(s, modrm); |
889 | 889 |
ldub_code(s->pc++); |
890 | 890 |
break; |
891 |
|
|
891 |
|
|
892 | 892 |
/************************/ |
893 | 893 |
/* string ops */ |
894 | 894 |
|
895 | 895 |
case 0xa4: /* movsS */ |
896 | 896 |
case 0xa5: |
897 | 897 |
break; |
898 |
|
|
898 |
|
|
899 | 899 |
case 0xaa: /* stosS */ |
900 | 900 |
case 0xab: |
901 | 901 |
break; |
... | ... | |
955 | 955 |
|
956 | 956 |
case 0xc3: /* ret */ |
957 | 957 |
gb(s, CPU_SEG); |
958 |
if (!s->dflag)
|
|
958 |
if (!s->dflag) |
|
959 | 959 |
gb(s, 0x66); /* d16 */ |
960 | 960 |
gb(s, 0x8f); /* pop addr */ |
961 | 961 |
gb(s, 0x05); |
... | ... | |
1011 | 1011 |
if (dflag) { |
1012 | 1012 |
val = insn_get(s, OT_LONG); |
1013 | 1013 |
} else { |
1014 |
val = (int16_t)insn_get(s, OT_WORD);
|
|
1014 |
val = (int16_t)insn_get(s, OT_WORD); |
|
1015 | 1015 |
} |
1016 | 1016 |
do_jcc: |
1017 | 1017 |
next_eip = s->pc - s->cs_base; |
... | ... | |
1071 | 1071 |
case 0x90: /* nop */ |
1072 | 1072 |
break; |
1073 | 1073 |
case 0x9b: /* fwait */ |
1074 |
if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
|
|
1074 |
if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == |
|
1075 | 1075 |
(HF_MP_MASK | HF_TS_MASK)) { |
1076 | 1076 |
goto unsupported_op; |
1077 | 1077 |
} |
... | ... | |
1171 | 1171 |
#define GEN_CODE_MAX_INSN_SIZE 512 |
1172 | 1172 |
|
1173 | 1173 |
static inline int gen_intermediate_code_internal(CPUState *env, |
1174 |
TranslationBlock *tb,
|
|
1174 |
TranslationBlock *tb, |
|
1175 | 1175 |
uint8_t *gen_code_ptr, |
1176 | 1176 |
int *gen_code_size_ptr, |
1177 | 1177 |
int search_pc, |
... | ... | |
1186 | 1186 |
env->singlestep_enabled) |
1187 | 1187 |
return -1; |
1188 | 1188 |
flags = tb->flags; |
1189 |
if (flags & (HF_TF_MASK | HF_ADDSEG_MASK |
|
|
1189 |
if (flags & (HF_TF_MASK | HF_ADDSEG_MASK | |
|
1190 | 1190 |
HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK)) |
1191 | 1191 |
return -1; |
1192 | 1192 |
if (!(flags & HF_SS32_MASK)) |
1193 | 1193 |
return -1; |
1194 | 1194 |
if (tb->cflags & CF_SINGLE_INSN) |
1195 | 1195 |
return -1; |
1196 |
gen_code_end = gen_code_ptr +
|
|
1196 |
gen_code_end = gen_code_ptr + |
|
1197 | 1197 |
GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE; |
1198 | 1198 |
dc->gen_code_ptr = gen_code_ptr; |
1199 | 1199 |
dc->gen_code_start = gen_code_ptr; |
... | ... | |
1244 | 1244 |
break; |
1245 | 1245 |
} |
1246 | 1246 |
} |
1247 |
|
|
1247 |
|
|
1248 | 1248 |
#ifdef DEBUG_DISAS |
1249 | 1249 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
1250 | 1250 |
fprintf(logfile, "----------------\n"); |
1251 |
fprintf(logfile, "IN: COPY: %s fpu=%d\n",
|
|
1251 |
fprintf(logfile, "IN: COPY: %s fpu=%d\n", |
|
1252 | 1252 |
lookup_symbol(pc_start), |
1253 | 1253 |
tb->cflags & CF_TB_FP_USED ? 1 : 0); |
1254 | 1254 |
target_disas(logfile, pc_start, dc->pc - pc_start, !dc->code32); |
... | ... | |
1279 | 1279 |
tb->tb_jmp_offset[2] = 0xffff; |
1280 | 1280 |
tb->tb_jmp_offset[3] = 0xffff; |
1281 | 1281 |
#endif |
1282 |
return gen_intermediate_code_internal(env, tb,
|
|
1282 |
return gen_intermediate_code_internal(env, tb, |
|
1283 | 1283 |
tb->tc_ptr, gen_code_size_ptr, |
1284 | 1284 |
0, NULL); |
1285 | 1285 |
} |
1286 | 1286 |
|
1287 | 1287 |
static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE]; |
1288 | 1288 |
|
1289 |
int cpu_restore_state_copy(TranslationBlock *tb,
|
|
1289 |
int cpu_restore_state_copy(TranslationBlock *tb, |
|
1290 | 1290 |
CPUState *env, unsigned long searched_pc, |
1291 | 1291 |
void *puc) |
1292 | 1292 |
{ |
... | ... | |
1297 | 1297 |
if (searched_pc < (unsigned long)tb->tc_ptr) |
1298 | 1298 |
return -1; |
1299 | 1299 |
searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf; |
1300 |
ret = gen_intermediate_code_internal(env, tb,
|
|
1300 |
ret = gen_intermediate_code_internal(env, tb, |
|
1301 | 1301 |
dummy_gen_code_buf, NULL, |
1302 | 1302 |
1, (uint8_t *)searched_pc); |
1303 | 1303 |
if (ret < 0) |
1304 | 1304 |
return ret; |
1305 | 1305 |
/* restore all the CPU state from the CPU context from the |
1306 | 1306 |
signal. The FPU context stays in the host CPU. */ |
1307 |
|
|
1307 |
|
|
1308 | 1308 |
env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX]; |
1309 | 1309 |
env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX]; |
1310 | 1310 |
env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX]; |
Also available in: Unified diff