Revision ba1c6e37
b/cpu-i386.h | ||
---|---|---|
85 | 85 |
typedef double CPU86_LDouble; |
86 | 86 |
#endif |
87 | 87 |
|
88 |
typedef struct CPU86State { |
|
88 |
typedef struct CPUX86State {
|
|
89 | 89 |
/* standard registers */ |
90 | 90 |
uint32_t regs[8]; |
91 | 91 |
uint32_t pc; /* cs_case + eip value */ |
... | ... | |
109 | 109 |
unsigned int fpuc; |
110 | 110 |
|
111 | 111 |
/* emulator internal variables */ |
112 |
uint32_t t0; /* temporary t0 storage */ |
|
113 |
uint32_t t1; /* temporary t1 storage */ |
|
114 |
uint32_t a0; /* temporary a0 storage (address) */ |
|
115 | 112 |
CPU86_LDouble ft0; |
116 |
} CPU86State; |
|
113 |
} CPUX86State;
|
|
117 | 114 |
|
118 | 115 |
static inline int ldub(void *ptr) |
119 | 116 |
{ |
... | ... | |
188 | 185 |
} |
189 | 186 |
|
190 | 187 |
#ifndef IN_OP_I386 |
191 |
void port_outb(int addr, int val);
|
|
192 |
void port_outw(int addr, int val);
|
|
193 |
void port_outl(int addr, int val);
|
|
194 |
int port_inb(int addr);
|
|
195 |
int port_inw(int addr);
|
|
196 |
int port_inl(int addr);
|
|
188 |
void cpu_x86_outb(int addr, int val);
|
|
189 |
void cpu_x86_outw(int addr, int val);
|
|
190 |
void cpu_x86_outl(int addr, int val);
|
|
191 |
int cpu_x86_inb(int addr);
|
|
192 |
int cpu_x86_inw(int addr);
|
|
193 |
int cpu_x86_inl(int addr);
|
|
197 | 194 |
#endif |
198 | 195 |
|
196 |
CPUX86State *cpu_x86_init(void); |
|
197 |
int cpu_x86_exec(CPUX86State *s); |
|
198 |
void cpu_x86_close(CPUX86State *s); |
|
199 |
|
|
200 |
/* internal functions */ |
|
201 |
int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, |
|
202 |
uint8_t *pc_start); |
|
203 |
|
|
199 | 204 |
#endif /* CPU_I386_H */ |
b/linux-user/main.c | ||
---|---|---|
193 | 193 |
/***********************************************************/ |
194 | 194 |
/* new CPU core */ |
195 | 195 |
|
196 |
void port_outb(int addr, int val)
|
|
196 |
void cpu_x86_outb(int addr, int val)
|
|
197 | 197 |
{ |
198 | 198 |
fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val); |
199 | 199 |
} |
200 | 200 |
|
201 |
void port_outw(int addr, int val)
|
|
201 |
void cpu_x86_outw(int addr, int val)
|
|
202 | 202 |
{ |
203 | 203 |
fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val); |
204 | 204 |
} |
205 | 205 |
|
206 |
void port_outl(int addr, int val)
|
|
206 |
void cpu_x86_outl(int addr, int val)
|
|
207 | 207 |
{ |
208 | 208 |
fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val); |
209 | 209 |
} |
210 | 210 |
|
211 |
int port_inb(int addr)
|
|
211 |
int cpu_x86_inb(int addr)
|
|
212 | 212 |
{ |
213 | 213 |
fprintf(stderr, "inb: port=0x%04x\n", addr); |
214 | 214 |
return 0; |
215 | 215 |
} |
216 | 216 |
|
217 |
int port_inw(int addr)
|
|
217 |
int cpu_x86_inw(int addr)
|
|
218 | 218 |
{ |
219 | 219 |
fprintf(stderr, "inw: port=0x%04x\n", addr); |
220 | 220 |
return 0; |
221 | 221 |
} |
222 | 222 |
|
223 |
int port_inl(int addr)
|
|
223 |
int cpu_x86_inl(int addr)
|
|
224 | 224 |
{ |
225 | 225 |
fprintf(stderr, "inl: port=0x%04x\n", addr); |
226 | 226 |
return 0; |
b/op-i386.c | ||
---|---|---|
10 | 10 |
|
11 | 11 |
#define NULL 0 |
12 | 12 |
|
13 |
typedef struct FILE FILE; |
|
14 |
|
|
15 |
extern FILE *stderr; |
|
16 |
extern int fprintf(FILE *, const char *, ...); |
|
17 |
|
|
13 | 18 |
#ifdef __i386__ |
14 | 19 |
register int T0 asm("esi"); |
15 | 20 |
register int T1 asm("ebx"); |
16 | 21 |
register int A0 asm("edi"); |
17 |
register struct CPU86State *env asm("ebp"); |
|
22 |
register struct CPUX86State *env asm("ebp");
|
|
18 | 23 |
#define FORCE_RET() asm volatile ("ret"); |
19 | 24 |
#endif |
20 | 25 |
#ifdef __powerpc__ |
21 | 26 |
register int T0 asm("r24"); |
22 | 27 |
register int T1 asm("r25"); |
23 | 28 |
register int A0 asm("r26"); |
24 |
register struct CPU86State *env asm("r27"); |
|
29 |
register struct CPUX86State *env asm("r27");
|
|
25 | 30 |
#define FORCE_RET() asm volatile ("blr"); |
26 | 31 |
#endif |
27 | 32 |
#ifdef __arm__ |
28 | 33 |
register int T0 asm("r4"); |
29 | 34 |
register int T1 asm("r5"); |
30 | 35 |
register int A0 asm("r6"); |
31 |
register struct CPU86State *env asm("r7"); |
|
36 |
register struct CPUX86State *env asm("r7");
|
|
32 | 37 |
#define FORCE_RET() asm volatile ("mov pc, lr"); |
33 | 38 |
#endif |
34 | 39 |
#ifdef __mips__ |
35 | 40 |
register int T0 asm("s0"); |
36 | 41 |
register int T1 asm("s1"); |
37 | 42 |
register int A0 asm("s2"); |
38 |
register struct CPU86State *env asm("s3"); |
|
43 |
register struct CPUX86State *env asm("s3");
|
|
39 | 44 |
#define FORCE_RET() asm volatile ("jr $31"); |
40 | 45 |
#endif |
41 | 46 |
#ifdef __sparc__ |
42 | 47 |
register int T0 asm("l0"); |
43 | 48 |
register int T1 asm("l1"); |
44 | 49 |
register int A0 asm("l2"); |
45 |
register struct CPU86State *env asm("l3"); |
|
50 |
register struct CPUX86State *env asm("l3");
|
|
46 | 51 |
#define FORCE_RET() asm volatile ("retl ; nop"); |
47 | 52 |
#endif |
48 | 53 |
|
... | ... | |
465 | 470 |
|
466 | 471 |
/* constant load */ |
467 | 472 |
|
468 |
void OPPROTO op1_movl_T0_im(void)
|
|
473 |
void OPPROTO op_movl_T0_im(void) |
|
469 | 474 |
{ |
470 | 475 |
T0 = PARAM1; |
471 | 476 |
} |
472 | 477 |
|
473 |
void OPPROTO op1_movl_T1_im(void)
|
|
478 |
void OPPROTO op_movl_T1_im(void) |
|
474 | 479 |
{ |
475 | 480 |
T1 = PARAM1; |
476 | 481 |
} |
477 | 482 |
|
478 |
void OPPROTO op1_movl_A0_im(void)
|
|
483 |
void OPPROTO op_movl_A0_im(void) |
|
479 | 484 |
{ |
480 | 485 |
A0 = PARAM1; |
481 | 486 |
} |
... | ... | |
1592 | 1597 |
helper_fcos(); |
1593 | 1598 |
} |
1594 | 1599 |
|
1600 |
/* main execution loop */ |
|
1601 |
uint8_t code_gen_buffer[65536]; |
|
1602 |
|
|
1603 |
|
|
1604 |
int cpu_x86_exec(CPUX86State *env1) |
|
1605 |
{ |
|
1606 |
int saved_T0, saved_T1, saved_A0; |
|
1607 |
CPUX86State *saved_env; |
|
1608 |
int code_gen_size; |
|
1609 |
void (*gen_func)(void); |
|
1610 |
|
|
1611 |
/* first we save global registers */ |
|
1612 |
saved_T0 = T0; |
|
1613 |
saved_T1 = T1; |
|
1614 |
saved_A0 = A0; |
|
1615 |
saved_env = env; |
|
1616 |
env = env1; |
|
1617 |
|
|
1618 |
for(;;) { |
|
1619 |
cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); |
|
1620 |
/* execute the generated code */ |
|
1621 |
gen_func = (void *)code_gen_buffer; |
|
1622 |
gen_func(); |
|
1623 |
} |
|
1624 |
|
|
1625 |
/* restore global registers */ |
|
1626 |
T0 = saved_T0; |
|
1627 |
T1 = saved_T1; |
|
1628 |
A0 = saved_A0; |
|
1629 |
env = saved_env; |
|
1630 |
return 0; |
|
1631 |
} |
b/ops_template.h | ||
---|---|---|
575 | 575 |
} |
576 | 576 |
} |
577 | 577 |
|
578 |
/* port I/O */ |
|
579 |
|
|
578 | 580 |
void OPPROTO glue(op_outs, SUFFIX)(void) |
579 | 581 |
{ |
580 | 582 |
int v, dx; |
581 | 583 |
dx = EDX & 0xffff; |
582 | 584 |
v = glue(ldu, SUFFIX)((void *)ESI); |
583 |
glue(port_out, SUFFIX)(dx, v);
|
|
585 |
glue(cpu_x86_out, SUFFIX)(dx, v);
|
|
584 | 586 |
ESI += (DF << SHIFT); |
585 | 587 |
} |
586 | 588 |
|
... | ... | |
591 | 593 |
dx = EDX & 0xffff; |
592 | 594 |
while (ECX != 0) { |
593 | 595 |
v = glue(ldu, SUFFIX)((void *)ESI); |
594 |
glue(port_out, SUFFIX)(dx, v);
|
|
596 |
glue(cpu_x86_out, SUFFIX)(dx, v);
|
|
595 | 597 |
ESI += inc; |
596 | 598 |
ECX--; |
597 | 599 |
} |
... | ... | |
601 | 603 |
{ |
602 | 604 |
int v, dx; |
603 | 605 |
dx = EDX & 0xffff; |
604 |
v = glue(port_in, SUFFIX)(dx);
|
|
606 |
v = glue(cpu_x86_in, SUFFIX)(dx);
|
|
605 | 607 |
glue(st, SUFFIX)((void *)EDI, v); |
606 | 608 |
EDI += (DF << SHIFT); |
607 | 609 |
} |
... | ... | |
612 | 614 |
inc = (DF << SHIFT); |
613 | 615 |
dx = EDX & 0xffff; |
614 | 616 |
while (ECX != 0) { |
615 |
v = glue(port_in, SUFFIX)(dx);
|
|
617 |
v = glue(cpu_x86_in, SUFFIX)(dx);
|
|
616 | 618 |
glue(st, SUFFIX)((void *)EDI, v); |
617 | 619 |
EDI += (DF << SHIFT); |
618 | 620 |
ECX--; |
619 | 621 |
} |
620 | 622 |
} |
621 | 623 |
|
624 |
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void) |
|
625 |
{ |
|
626 |
glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK); |
|
627 |
} |
|
628 |
|
|
629 |
void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void) |
|
630 |
{ |
|
631 |
T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff); |
|
632 |
} |
|
633 |
|
|
622 | 634 |
#undef DATA_BITS |
623 | 635 |
#undef SHIFT_MASK |
624 | 636 |
#undef SIGN_MASK |
b/translate-i386.c | ||
---|---|---|
495 | 495 |
gen_op_rep_outsl, |
496 | 496 |
}; |
497 | 497 |
|
498 |
static GenOpFunc *gen_op_in[3] = { |
|
499 |
gen_op_inb_T0_T1, |
|
500 |
gen_op_inw_T0_T1, |
|
501 |
gen_op_inl_T0_T1, |
|
502 |
}; |
|
503 |
|
|
504 |
static GenOpFunc *gen_op_out[3] = { |
|
505 |
gen_op_outb_T0_T1, |
|
506 |
gen_op_outw_T0_T1, |
|
507 |
gen_op_outl_T0_T1, |
|
508 |
}; |
|
509 |
|
|
498 | 510 |
enum { |
499 | 511 |
JCC_O, |
500 | 512 |
JCC_B, |
... | ... | |
632 | 644 |
|
633 | 645 |
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c) |
634 | 646 |
{ |
635 |
gen_op1_movl_T1_im(c);
|
|
647 |
gen_op_movl_T1_im(c); |
|
636 | 648 |
gen_op(s1, op, ot, d, OR_TMP0); |
637 | 649 |
} |
638 | 650 |
|
... | ... | |
678 | 690 |
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c) |
679 | 691 |
{ |
680 | 692 |
/* currently not optimized */ |
681 |
gen_op1_movl_T1_im(c);
|
|
693 |
gen_op_movl_T1_im(c); |
|
682 | 694 |
gen_shift(s1, op, ot, d, OR_TMP1); |
683 | 695 |
} |
684 | 696 |
|
... | ... | |
746 | 758 |
if (reg2 == OR_ZERO) { |
747 | 759 |
/* op: disp + (reg1 << scale) */ |
748 | 760 |
if (reg1 == OR_ZERO) { |
749 |
gen_op1_movl_A0_im(disp);
|
|
761 |
gen_op_movl_A0_im(disp); |
|
750 | 762 |
} else if (scale == 0 && disp == 0) { |
751 | 763 |
gen_op_movl_A0_reg[reg1](); |
752 | 764 |
} else { |
... | ... | |
755 | 767 |
} else { |
756 | 768 |
/* op: disp + reg1 + (reg2 << scale) */ |
757 | 769 |
if (disp != 0) { |
758 |
gen_op1_movl_A0_im(disp);
|
|
770 |
gen_op_movl_A0_im(disp); |
|
759 | 771 |
gen_op_addl_A0_reg_sN[0][reg1](); |
760 | 772 |
} else { |
761 | 773 |
gen_op_movl_A0_reg[reg1](); |
... | ... | |
1149 | 1161 |
switch(op) { |
1150 | 1162 |
case 0: /* test */ |
1151 | 1163 |
val = insn_get(s, ot); |
1152 |
gen_op1_movl_T1_im(val);
|
|
1164 |
gen_op_movl_T1_im(val); |
|
1153 | 1165 |
gen_op_testl_T0_T1_cc(); |
1154 | 1166 |
s->cc_op = CC_OP_LOGICB + ot; |
1155 | 1167 |
break; |
... | ... | |
1266 | 1278 |
gen_op_st_T0_A0[ot](); |
1267 | 1279 |
break; |
1268 | 1280 |
case 2: /* call Ev */ |
1269 |
gen_op1_movl_T1_im((long)s->pc);
|
|
1281 |
gen_op_movl_T1_im((long)s->pc); |
|
1270 | 1282 |
gen_op_pushl_T1(); |
1271 | 1283 |
gen_op_jmp_T0(); |
1272 | 1284 |
break; |
... | ... | |
1309 | 1321 |
val = insn_get(s, ot); |
1310 | 1322 |
|
1311 | 1323 |
gen_op_mov_TN_reg[ot][0][OR_EAX](); |
1312 |
gen_op1_movl_T1_im(val);
|
|
1324 |
gen_op_movl_T1_im(val); |
|
1313 | 1325 |
gen_op_testl_T0_T1_cc(); |
1314 | 1326 |
s->cc_op = CC_OP_LOGICB + ot; |
1315 | 1327 |
break; |
... | ... | |
1336 | 1348 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
1337 | 1349 |
if (b == 0x69) { |
1338 | 1350 |
val = insn_get(s, ot); |
1339 |
gen_op1_movl_T1_im(val);
|
|
1351 |
gen_op_movl_T1_im(val); |
|
1340 | 1352 |
} else if (b == 0x6b) { |
1341 | 1353 |
val = insn_get(s, OT_BYTE); |
1342 |
gen_op1_movl_T1_im(val);
|
|
1354 |
gen_op_movl_T1_im(val); |
|
1343 | 1355 |
} else { |
1344 | 1356 |
gen_op_mov_TN_reg[ot][1][reg](); |
1345 | 1357 |
} |
... | ... | |
1369 | 1381 |
val = insn_get(s, ot); |
1370 | 1382 |
else |
1371 | 1383 |
val = (int8_t)insn_get(s, OT_BYTE); |
1372 |
gen_op1_movl_T0_im(val);
|
|
1384 |
gen_op_movl_T0_im(val); |
|
1373 | 1385 |
gen_op_pushl_T0(); |
1374 | 1386 |
break; |
1375 | 1387 |
case 0x8f: /* pop Ev */ |
... | ... | |
1408 | 1420 |
mod = (modrm >> 6) & 3; |
1409 | 1421 |
|
1410 | 1422 |
val = insn_get(s, ot); |
1411 |
gen_op1_movl_T0_im(val);
|
|
1423 |
gen_op_movl_T0_im(val); |
|
1412 | 1424 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
1413 | 1425 |
break; |
1414 | 1426 |
case 0x8a: |
... | ... | |
1502 | 1514 |
|
1503 | 1515 |
case 0xb0 ... 0xb7: /* mov R, Ib */ |
1504 | 1516 |
val = insn_get(s, OT_BYTE); |
1505 |
gen_op1_movl_T0_im(val);
|
|
1517 |
gen_op_movl_T0_im(val); |
|
1506 | 1518 |
gen_op_mov_reg_T0[OT_BYTE][b & 7](); |
1507 | 1519 |
break; |
1508 | 1520 |
case 0xb8 ... 0xbf: /* mov R, Iv */ |
1509 | 1521 |
ot = dflag ? OT_LONG : OT_WORD; |
1510 | 1522 |
val = insn_get(s, ot); |
1511 | 1523 |
reg = OR_EAX + (b & 7); |
1512 |
gen_op1_movl_T0_im(val);
|
|
1524 |
gen_op_movl_T0_im(val); |
|
1513 | 1525 |
gen_op_mov_reg_T0[ot][reg](); |
1514 | 1526 |
break; |
1515 | 1527 |
|
... | ... | |
1978 | 1990 |
} |
1979 | 1991 |
break; |
1980 | 1992 |
|
1993 |
/************************/ |
|
1994 |
/* port I/O */ |
|
1981 | 1995 |
case 0x6c: /* insS */ |
1982 | 1996 |
case 0x6d: |
1983 | 1997 |
if ((b & 1) == 0) |
... | ... | |
2002 | 2016 |
gen_op_outs[ot](); |
2003 | 2017 |
} |
2004 | 2018 |
break; |
2019 |
case 0xe4: |
|
2020 |
case 0xe5: |
|
2021 |
if ((b & 1) == 0) |
|
2022 |
ot = OT_BYTE; |
|
2023 |
else |
|
2024 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2025 |
val = ldub(s->pc++); |
|
2026 |
gen_op_movl_T0_im(val); |
|
2027 |
gen_op_in[ot](); |
|
2028 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
2029 |
break; |
|
2030 |
case 0xe6: |
|
2031 |
case 0xe7: |
|
2032 |
if ((b & 1) == 0) |
|
2033 |
ot = OT_BYTE; |
|
2034 |
else |
|
2035 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2036 |
val = ldub(s->pc++); |
|
2037 |
gen_op_movl_T0_im(val); |
|
2038 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
2039 |
gen_op_out[ot](); |
|
2040 |
break; |
|
2041 |
case 0xec: |
|
2042 |
case 0xed: |
|
2043 |
if ((b & 1) == 0) |
|
2044 |
ot = OT_BYTE; |
|
2045 |
else |
|
2046 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2047 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
2048 |
gen_op_in[ot](); |
|
2049 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
2050 |
break; |
|
2051 |
case 0xee: |
|
2052 |
case 0xef: |
|
2053 |
if ((b & 1) == 0) |
|
2054 |
ot = OT_BYTE; |
|
2055 |
else |
|
2056 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2057 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
2058 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
2059 |
gen_op_out[ot](); |
|
2060 |
break; |
|
2005 | 2061 |
|
2006 | 2062 |
/************************/ |
2007 | 2063 |
/* control */ |
... | ... | |
2020 | 2076 |
case 0xe8: /* call */ |
2021 | 2077 |
val = insn_get(s, OT_LONG); |
2022 | 2078 |
val += (long)s->pc; |
2023 |
gen_op1_movl_T1_im((long)s->pc);
|
|
2079 |
gen_op_movl_T1_im((long)s->pc); |
|
2024 | 2080 |
gen_op_pushl_T1(); |
2025 | 2081 |
gen_op_jmp_im(val); |
2026 | 2082 |
break; |
... | ... | |
2121 | 2177 |
return (long)s->pc; |
2122 | 2178 |
} |
2123 | 2179 |
|
2180 |
/* return the next pc */ |
|
2181 |
int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, |
|
2182 |
uint8_t *pc_start) |
|
2183 |
{ |
|
2184 |
DisasContext dc1, *dc = &dc1; |
|
2185 |
long ret; |
|
2186 |
dc->cc_op = CC_OP_DYNAMIC; |
|
2187 |
gen_code_ptr = gen_code_buf; |
|
2188 |
gen_start(); |
|
2189 |
ret = disas_insn(dc, pc_start); |
|
2190 |
if (ret == -1) |
|
2191 |
error("unknown instruction at PC=0x%x", pc_start); |
|
2192 |
gen_end(); |
|
2193 |
*gen_code_size_ptr = gen_code_ptr - gen_code_buf; |
|
2194 |
printf("0x%08lx: code_size = %d\n", (long)pc_start, *gen_code_size_ptr); |
|
2195 |
return 0; |
|
2196 |
} |
|
2197 |
|
|
2198 |
CPUX86State *cpu_x86_init(void) |
|
2199 |
{ |
|
2200 |
CPUX86State *env; |
|
2201 |
int i; |
|
2202 |
|
|
2203 |
env = malloc(sizeof(CPUX86State)); |
|
2204 |
if (!env) |
|
2205 |
return NULL; |
|
2206 |
memset(env, 0, sizeof(CPUX86State)); |
|
2207 |
/* basic FPU init */ |
|
2208 |
for(i = 0;i < 8; i++) |
|
2209 |
env->fptags[i] = 1; |
|
2210 |
env->fpuc = 0x37f; |
|
2211 |
/* flags setup */ |
|
2212 |
env->cc_op = CC_OP_EFLAGS; |
|
2213 |
env->df = 1; |
|
2214 |
return env; |
|
2215 |
} |
|
2216 |
|
|
2217 |
void cpu_x86_close(CPUX86State *env) |
|
2218 |
{ |
|
2219 |
free(env); |
|
2220 |
} |
Also available in: Unified diff