Commit ba1c6e37fc5efc0f3d1e50d0760f9f4a1061187b
1 parent
927f621e
test infrastructure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@16 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
194 additions
and
43 deletions
cpu-i386.h
@@ -85,7 +85,7 @@ typedef long double CPU86_LDouble; | @@ -85,7 +85,7 @@ typedef long double CPU86_LDouble; | ||
85 | typedef double CPU86_LDouble; | 85 | typedef double CPU86_LDouble; |
86 | #endif | 86 | #endif |
87 | 87 | ||
88 | -typedef struct CPU86State { | 88 | +typedef struct CPUX86State { |
89 | /* standard registers */ | 89 | /* standard registers */ |
90 | uint32_t regs[8]; | 90 | uint32_t regs[8]; |
91 | uint32_t pc; /* cs_case + eip value */ | 91 | uint32_t pc; /* cs_case + eip value */ |
@@ -109,11 +109,8 @@ typedef struct CPU86State { | @@ -109,11 +109,8 @@ typedef struct CPU86State { | ||
109 | unsigned int fpuc; | 109 | unsigned int fpuc; |
110 | 110 | ||
111 | /* emulator internal variables */ | 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 | CPU86_LDouble ft0; | 112 | CPU86_LDouble ft0; |
116 | -} CPU86State; | 113 | +} CPUX86State; |
117 | 114 | ||
118 | static inline int ldub(void *ptr) | 115 | static inline int ldub(void *ptr) |
119 | { | 116 | { |
@@ -188,12 +185,20 @@ static inline void stfq(void *ptr, double v) | @@ -188,12 +185,20 @@ static inline void stfq(void *ptr, double v) | ||
188 | } | 185 | } |
189 | 186 | ||
190 | #ifndef IN_OP_I386 | 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 | #endif | 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 | #endif /* CPU_I386_H */ | 204 | #endif /* CPU_I386_H */ |
linux-user/main.c
@@ -193,34 +193,34 @@ void INT_handler(int num, void *env) | @@ -193,34 +193,34 @@ void INT_handler(int num, void *env) | ||
193 | /***********************************************************/ | 193 | /***********************************************************/ |
194 | /* new CPU core */ | 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 | fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val); | 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 | fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val); | 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 | fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val); | 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 | fprintf(stderr, "inb: port=0x%04x\n", addr); | 213 | fprintf(stderr, "inb: port=0x%04x\n", addr); |
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | 216 | ||
217 | -int port_inw(int addr) | 217 | +int cpu_x86_inw(int addr) |
218 | { | 218 | { |
219 | fprintf(stderr, "inw: port=0x%04x\n", addr); | 219 | fprintf(stderr, "inw: port=0x%04x\n", addr); |
220 | return 0; | 220 | return 0; |
221 | } | 221 | } |
222 | 222 | ||
223 | -int port_inl(int addr) | 223 | +int cpu_x86_inl(int addr) |
224 | { | 224 | { |
225 | fprintf(stderr, "inl: port=0x%04x\n", addr); | 225 | fprintf(stderr, "inl: port=0x%04x\n", addr); |
226 | return 0; | 226 | return 0; |
op-i386.c
@@ -10,39 +10,44 @@ typedef signed long long int64_t; | @@ -10,39 +10,44 @@ typedef signed long long int64_t; | ||
10 | 10 | ||
11 | #define NULL 0 | 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 | #ifdef __i386__ | 18 | #ifdef __i386__ |
14 | register int T0 asm("esi"); | 19 | register int T0 asm("esi"); |
15 | register int T1 asm("ebx"); | 20 | register int T1 asm("ebx"); |
16 | register int A0 asm("edi"); | 21 | register int A0 asm("edi"); |
17 | -register struct CPU86State *env asm("ebp"); | 22 | +register struct CPUX86State *env asm("ebp"); |
18 | #define FORCE_RET() asm volatile ("ret"); | 23 | #define FORCE_RET() asm volatile ("ret"); |
19 | #endif | 24 | #endif |
20 | #ifdef __powerpc__ | 25 | #ifdef __powerpc__ |
21 | register int T0 asm("r24"); | 26 | register int T0 asm("r24"); |
22 | register int T1 asm("r25"); | 27 | register int T1 asm("r25"); |
23 | register int A0 asm("r26"); | 28 | register int A0 asm("r26"); |
24 | -register struct CPU86State *env asm("r27"); | 29 | +register struct CPUX86State *env asm("r27"); |
25 | #define FORCE_RET() asm volatile ("blr"); | 30 | #define FORCE_RET() asm volatile ("blr"); |
26 | #endif | 31 | #endif |
27 | #ifdef __arm__ | 32 | #ifdef __arm__ |
28 | register int T0 asm("r4"); | 33 | register int T0 asm("r4"); |
29 | register int T1 asm("r5"); | 34 | register int T1 asm("r5"); |
30 | register int A0 asm("r6"); | 35 | register int A0 asm("r6"); |
31 | -register struct CPU86State *env asm("r7"); | 36 | +register struct CPUX86State *env asm("r7"); |
32 | #define FORCE_RET() asm volatile ("mov pc, lr"); | 37 | #define FORCE_RET() asm volatile ("mov pc, lr"); |
33 | #endif | 38 | #endif |
34 | #ifdef __mips__ | 39 | #ifdef __mips__ |
35 | register int T0 asm("s0"); | 40 | register int T0 asm("s0"); |
36 | register int T1 asm("s1"); | 41 | register int T1 asm("s1"); |
37 | register int A0 asm("s2"); | 42 | register int A0 asm("s2"); |
38 | -register struct CPU86State *env asm("s3"); | 43 | +register struct CPUX86State *env asm("s3"); |
39 | #define FORCE_RET() asm volatile ("jr $31"); | 44 | #define FORCE_RET() asm volatile ("jr $31"); |
40 | #endif | 45 | #endif |
41 | #ifdef __sparc__ | 46 | #ifdef __sparc__ |
42 | register int T0 asm("l0"); | 47 | register int T0 asm("l0"); |
43 | register int T1 asm("l1"); | 48 | register int T1 asm("l1"); |
44 | register int A0 asm("l2"); | 49 | register int A0 asm("l2"); |
45 | -register struct CPU86State *env asm("l3"); | 50 | +register struct CPUX86State *env asm("l3"); |
46 | #define FORCE_RET() asm volatile ("retl ; nop"); | 51 | #define FORCE_RET() asm volatile ("retl ; nop"); |
47 | #endif | 52 | #endif |
48 | 53 | ||
@@ -465,17 +470,17 @@ void OPPROTO op_idivl_EAX_T0(void) | @@ -465,17 +470,17 @@ void OPPROTO op_idivl_EAX_T0(void) | ||
465 | 470 | ||
466 | /* constant load */ | 471 | /* constant load */ |
467 | 472 | ||
468 | -void OPPROTO op1_movl_T0_im(void) | 473 | +void OPPROTO op_movl_T0_im(void) |
469 | { | 474 | { |
470 | T0 = PARAM1; | 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 | T1 = PARAM1; | 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 | A0 = PARAM1; | 485 | A0 = PARAM1; |
481 | } | 486 | } |
@@ -1592,3 +1597,35 @@ void OPPROTO op_fcos(void) | @@ -1592,3 +1597,35 @@ void OPPROTO op_fcos(void) | ||
1592 | helper_fcos(); | 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 | +} |
ops_template.h
@@ -575,12 +575,14 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) | @@ -575,12 +575,14 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) | ||
575 | } | 575 | } |
576 | } | 576 | } |
577 | 577 | ||
578 | +/* port I/O */ | ||
579 | + | ||
578 | void OPPROTO glue(op_outs, SUFFIX)(void) | 580 | void OPPROTO glue(op_outs, SUFFIX)(void) |
579 | { | 581 | { |
580 | int v, dx; | 582 | int v, dx; |
581 | dx = EDX & 0xffff; | 583 | dx = EDX & 0xffff; |
582 | v = glue(ldu, SUFFIX)((void *)ESI); | 584 | v = glue(ldu, SUFFIX)((void *)ESI); |
583 | - glue(port_out, SUFFIX)(dx, v); | 585 | + glue(cpu_x86_out, SUFFIX)(dx, v); |
584 | ESI += (DF << SHIFT); | 586 | ESI += (DF << SHIFT); |
585 | } | 587 | } |
586 | 588 | ||
@@ -591,7 +593,7 @@ void OPPROTO glue(op_rep_outs, SUFFIX)(void) | @@ -591,7 +593,7 @@ void OPPROTO glue(op_rep_outs, SUFFIX)(void) | ||
591 | dx = EDX & 0xffff; | 593 | dx = EDX & 0xffff; |
592 | while (ECX != 0) { | 594 | while (ECX != 0) { |
593 | v = glue(ldu, SUFFIX)((void *)ESI); | 595 | v = glue(ldu, SUFFIX)((void *)ESI); |
594 | - glue(port_out, SUFFIX)(dx, v); | 596 | + glue(cpu_x86_out, SUFFIX)(dx, v); |
595 | ESI += inc; | 597 | ESI += inc; |
596 | ECX--; | 598 | ECX--; |
597 | } | 599 | } |
@@ -601,7 +603,7 @@ void OPPROTO glue(op_ins, SUFFIX)(void) | @@ -601,7 +603,7 @@ void OPPROTO glue(op_ins, SUFFIX)(void) | ||
601 | { | 603 | { |
602 | int v, dx; | 604 | int v, dx; |
603 | dx = EDX & 0xffff; | 605 | dx = EDX & 0xffff; |
604 | - v = glue(port_in, SUFFIX)(dx); | 606 | + v = glue(cpu_x86_in, SUFFIX)(dx); |
605 | glue(st, SUFFIX)((void *)EDI, v); | 607 | glue(st, SUFFIX)((void *)EDI, v); |
606 | EDI += (DF << SHIFT); | 608 | EDI += (DF << SHIFT); |
607 | } | 609 | } |
@@ -612,13 +614,23 @@ void OPPROTO glue(op_rep_ins, SUFFIX)(void) | @@ -612,13 +614,23 @@ void OPPROTO glue(op_rep_ins, SUFFIX)(void) | ||
612 | inc = (DF << SHIFT); | 614 | inc = (DF << SHIFT); |
613 | dx = EDX & 0xffff; | 615 | dx = EDX & 0xffff; |
614 | while (ECX != 0) { | 616 | while (ECX != 0) { |
615 | - v = glue(port_in, SUFFIX)(dx); | 617 | + v = glue(cpu_x86_in, SUFFIX)(dx); |
616 | glue(st, SUFFIX)((void *)EDI, v); | 618 | glue(st, SUFFIX)((void *)EDI, v); |
617 | EDI += (DF << SHIFT); | 619 | EDI += (DF << SHIFT); |
618 | ECX--; | 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 | #undef DATA_BITS | 634 | #undef DATA_BITS |
623 | #undef SHIFT_MASK | 635 | #undef SHIFT_MASK |
624 | #undef SIGN_MASK | 636 | #undef SIGN_MASK |
translate-i386.c
@@ -495,6 +495,18 @@ static GenOpFunc *gen_op_outs[6] = { | @@ -495,6 +495,18 @@ static GenOpFunc *gen_op_outs[6] = { | ||
495 | gen_op_rep_outsl, | 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 | enum { | 510 | enum { |
499 | JCC_O, | 511 | JCC_O, |
500 | JCC_B, | 512 | JCC_B, |
@@ -632,7 +644,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d, int s) | @@ -632,7 +644,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d, int s) | ||
632 | 644 | ||
633 | static void gen_opi(DisasContext *s1, int op, int ot, int d, int c) | 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 | gen_op(s1, op, ot, d, OR_TMP0); | 648 | gen_op(s1, op, ot, d, OR_TMP0); |
637 | } | 649 | } |
638 | 650 | ||
@@ -678,7 +690,7 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) | @@ -678,7 +690,7 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) | ||
678 | static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c) | 690 | static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c) |
679 | { | 691 | { |
680 | /* currently not optimized */ | 692 | /* currently not optimized */ |
681 | - gen_op1_movl_T1_im(c); | 693 | + gen_op_movl_T1_im(c); |
682 | gen_shift(s1, op, ot, d, OR_TMP1); | 694 | gen_shift(s1, op, ot, d, OR_TMP1); |
683 | } | 695 | } |
684 | 696 | ||
@@ -746,7 +758,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -746,7 +758,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
746 | if (reg2 == OR_ZERO) { | 758 | if (reg2 == OR_ZERO) { |
747 | /* op: disp + (reg1 << scale) */ | 759 | /* op: disp + (reg1 << scale) */ |
748 | if (reg1 == OR_ZERO) { | 760 | if (reg1 == OR_ZERO) { |
749 | - gen_op1_movl_A0_im(disp); | 761 | + gen_op_movl_A0_im(disp); |
750 | } else if (scale == 0 && disp == 0) { | 762 | } else if (scale == 0 && disp == 0) { |
751 | gen_op_movl_A0_reg[reg1](); | 763 | gen_op_movl_A0_reg[reg1](); |
752 | } else { | 764 | } else { |
@@ -755,7 +767,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -755,7 +767,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
755 | } else { | 767 | } else { |
756 | /* op: disp + reg1 + (reg2 << scale) */ | 768 | /* op: disp + reg1 + (reg2 << scale) */ |
757 | if (disp != 0) { | 769 | if (disp != 0) { |
758 | - gen_op1_movl_A0_im(disp); | 770 | + gen_op_movl_A0_im(disp); |
759 | gen_op_addl_A0_reg_sN[0][reg1](); | 771 | gen_op_addl_A0_reg_sN[0][reg1](); |
760 | } else { | 772 | } else { |
761 | gen_op_movl_A0_reg[reg1](); | 773 | gen_op_movl_A0_reg[reg1](); |
@@ -1149,7 +1161,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1149,7 +1161,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1149 | switch(op) { | 1161 | switch(op) { |
1150 | case 0: /* test */ | 1162 | case 0: /* test */ |
1151 | val = insn_get(s, ot); | 1163 | val = insn_get(s, ot); |
1152 | - gen_op1_movl_T1_im(val); | 1164 | + gen_op_movl_T1_im(val); |
1153 | gen_op_testl_T0_T1_cc(); | 1165 | gen_op_testl_T0_T1_cc(); |
1154 | s->cc_op = CC_OP_LOGICB + ot; | 1166 | s->cc_op = CC_OP_LOGICB + ot; |
1155 | break; | 1167 | break; |
@@ -1266,7 +1278,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1266,7 +1278,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1266 | gen_op_st_T0_A0[ot](); | 1278 | gen_op_st_T0_A0[ot](); |
1267 | break; | 1279 | break; |
1268 | case 2: /* call Ev */ | 1280 | case 2: /* call Ev */ |
1269 | - gen_op1_movl_T1_im((long)s->pc); | 1281 | + gen_op_movl_T1_im((long)s->pc); |
1270 | gen_op_pushl_T1(); | 1282 | gen_op_pushl_T1(); |
1271 | gen_op_jmp_T0(); | 1283 | gen_op_jmp_T0(); |
1272 | break; | 1284 | break; |
@@ -1309,7 +1321,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1309,7 +1321,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1309 | val = insn_get(s, ot); | 1321 | val = insn_get(s, ot); |
1310 | 1322 | ||
1311 | gen_op_mov_TN_reg[ot][0][OR_EAX](); | 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 | gen_op_testl_T0_T1_cc(); | 1325 | gen_op_testl_T0_T1_cc(); |
1314 | s->cc_op = CC_OP_LOGICB + ot; | 1326 | s->cc_op = CC_OP_LOGICB + ot; |
1315 | break; | 1327 | break; |
@@ -1336,10 +1348,10 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1336,10 +1348,10 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1336 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); | 1348 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
1337 | if (b == 0x69) { | 1349 | if (b == 0x69) { |
1338 | val = insn_get(s, ot); | 1350 | val = insn_get(s, ot); |
1339 | - gen_op1_movl_T1_im(val); | 1351 | + gen_op_movl_T1_im(val); |
1340 | } else if (b == 0x6b) { | 1352 | } else if (b == 0x6b) { |
1341 | val = insn_get(s, OT_BYTE); | 1353 | val = insn_get(s, OT_BYTE); |
1342 | - gen_op1_movl_T1_im(val); | 1354 | + gen_op_movl_T1_im(val); |
1343 | } else { | 1355 | } else { |
1344 | gen_op_mov_TN_reg[ot][1][reg](); | 1356 | gen_op_mov_TN_reg[ot][1][reg](); |
1345 | } | 1357 | } |
@@ -1369,7 +1381,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1369,7 +1381,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1369 | val = insn_get(s, ot); | 1381 | val = insn_get(s, ot); |
1370 | else | 1382 | else |
1371 | val = (int8_t)insn_get(s, OT_BYTE); | 1383 | val = (int8_t)insn_get(s, OT_BYTE); |
1372 | - gen_op1_movl_T0_im(val); | 1384 | + gen_op_movl_T0_im(val); |
1373 | gen_op_pushl_T0(); | 1385 | gen_op_pushl_T0(); |
1374 | break; | 1386 | break; |
1375 | case 0x8f: /* pop Ev */ | 1387 | case 0x8f: /* pop Ev */ |
@@ -1408,7 +1420,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1408,7 +1420,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1408 | mod = (modrm >> 6) & 3; | 1420 | mod = (modrm >> 6) & 3; |
1409 | 1421 | ||
1410 | val = insn_get(s, ot); | 1422 | val = insn_get(s, ot); |
1411 | - gen_op1_movl_T0_im(val); | 1423 | + gen_op_movl_T0_im(val); |
1412 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); | 1424 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
1413 | break; | 1425 | break; |
1414 | case 0x8a: | 1426 | case 0x8a: |
@@ -1502,14 +1514,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1502,14 +1514,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1502 | 1514 | ||
1503 | case 0xb0 ... 0xb7: /* mov R, Ib */ | 1515 | case 0xb0 ... 0xb7: /* mov R, Ib */ |
1504 | val = insn_get(s, OT_BYTE); | 1516 | val = insn_get(s, OT_BYTE); |
1505 | - gen_op1_movl_T0_im(val); | 1517 | + gen_op_movl_T0_im(val); |
1506 | gen_op_mov_reg_T0[OT_BYTE][b & 7](); | 1518 | gen_op_mov_reg_T0[OT_BYTE][b & 7](); |
1507 | break; | 1519 | break; |
1508 | case 0xb8 ... 0xbf: /* mov R, Iv */ | 1520 | case 0xb8 ... 0xbf: /* mov R, Iv */ |
1509 | ot = dflag ? OT_LONG : OT_WORD; | 1521 | ot = dflag ? OT_LONG : OT_WORD; |
1510 | val = insn_get(s, ot); | 1522 | val = insn_get(s, ot); |
1511 | reg = OR_EAX + (b & 7); | 1523 | reg = OR_EAX + (b & 7); |
1512 | - gen_op1_movl_T0_im(val); | 1524 | + gen_op_movl_T0_im(val); |
1513 | gen_op_mov_reg_T0[ot][reg](); | 1525 | gen_op_mov_reg_T0[ot][reg](); |
1514 | break; | 1526 | break; |
1515 | 1527 | ||
@@ -1978,6 +1990,8 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1978,6 +1990,8 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
1978 | } | 1990 | } |
1979 | break; | 1991 | break; |
1980 | 1992 | ||
1993 | + /************************/ | ||
1994 | + /* port I/O */ | ||
1981 | case 0x6c: /* insS */ | 1995 | case 0x6c: /* insS */ |
1982 | case 0x6d: | 1996 | case 0x6d: |
1983 | if ((b & 1) == 0) | 1997 | if ((b & 1) == 0) |
@@ -2002,6 +2016,48 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2002,6 +2016,48 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2002 | gen_op_outs[ot](); | 2016 | gen_op_outs[ot](); |
2003 | } | 2017 | } |
2004 | break; | 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 | /* control */ | 2063 | /* control */ |
@@ -2020,7 +2076,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2020,7 +2076,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2020 | case 0xe8: /* call */ | 2076 | case 0xe8: /* call */ |
2021 | val = insn_get(s, OT_LONG); | 2077 | val = insn_get(s, OT_LONG); |
2022 | val += (long)s->pc; | 2078 | val += (long)s->pc; |
2023 | - gen_op1_movl_T1_im((long)s->pc); | 2079 | + gen_op_movl_T1_im((long)s->pc); |
2024 | gen_op_pushl_T1(); | 2080 | gen_op_pushl_T1(); |
2025 | gen_op_jmp_im(val); | 2081 | gen_op_jmp_im(val); |
2026 | break; | 2082 | break; |
@@ -2121,3 +2177,44 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2121,3 +2177,44 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2121 | return (long)s->pc; | 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 | +} |