Commit 33417e7025afa5ea1c38c3c2b2ea53d975b5648b

Authored by bellard
1 parent 4021dab0

soft mmu support - Memory I/O API - synthetize string instructions


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@354 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
... ... @@ -140,6 +140,7 @@ static inline void stfl(void *ptr, float v)
140 140 stl(ptr, u.i);
141 141 }
142 142  
  143 +
143 144 #if defined(__arm__) && !defined(WORDS_BIGENDIAN)
144 145  
145 146 /* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
... ... @@ -317,6 +318,17 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc);
317 318 int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
318 319 void cpu_single_step(CPUState *env, int enabled);
319 320  
  321 +/* memory API */
  322 +
  323 +typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value);
  324 +typedef uint32_t CPUReadMemoryFunc(uint32_t addr);
  325 +
  326 +void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
  327 + long phys_offset);
  328 +int cpu_register_io_memory(int io_index,
  329 + CPUReadMemoryFunc **mem_read,
  330 + CPUWriteMemoryFunc **mem_write);
  331 +
320 332 /* gdb stub API */
321 333 extern int gdbstub_fd;
322 334 CPUState *cpu_gdbstub_get_env(void *opaque);
... ...
cpu-arm.h
... ... @@ -20,12 +20,10 @@
20 20 #ifndef CPU_ARM_H
21 21 #define CPU_ARM_H
22 22  
23   -#include "config.h"
24   -#include <setjmp.h>
  23 +#include "cpu-defs.h"
25 24  
26 25 #define EXCP_UDEF 1 /* undefined instruction */
27 26 #define EXCP_SWI 2 /* software interrupt */
28   -#define EXCP_INTERRUPT 256 /* async interruption */
29 27  
30 28 typedef struct CPUARMState {
31 29 uint32_t regs[16];
... ...
cpu-i386.h
... ... @@ -20,8 +20,7 @@
20 20 #ifndef CPU_I386_H
21 21 #define CPU_I386_H
22 22  
23   -#include "config.h"
24   -#include <setjmp.h>
  23 +#include "cpu-defs.h"
25 24  
26 25 #define R_EAX 0
27 26 #define R_ECX 1
... ... @@ -153,12 +152,6 @@
153 152 #define EXCP11_ALGN 17
154 153 #define EXCP12_MCHK 18
155 154  
156   -#define EXCP_INTERRUPT 256 /* async interruption */
157   -#define EXCP_HLT 257 /* hlt instruction reached */
158   -#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */
159   -
160   -#define MAX_BREAKPOINTS 32
161   -
162 155 enum {
163 156 CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
164 157 CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
... ... @@ -257,7 +250,8 @@ typedef struct CPUX86State {
257 250 SegmentCache gdt; /* only base and limit are used */
258 251 SegmentCache idt; /* only base and limit are used */
259 252 int cpl; /* current cpl */
260   -
  253 + int soft_mmu; /* TRUE if soft mmu is being used */
  254 +
261 255 /* sysenter registers */
262 256 uint32_t sysenter_cs;
263 257 uint32_t sysenter_esp;
... ... @@ -275,10 +269,16 @@ typedef struct CPUX86State {
275 269 int interrupt_request;
276 270 int user_mode_only; /* user mode only simulation */
277 271  
  272 + /* soft mmu support */
  273 + /* 0 = kernel, 1 = user */
  274 + CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
  275 + CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
  276 +
  277 + /* ice debug support */
278 278 uint32_t breakpoints[MAX_BREAKPOINTS];
279 279 int nb_breakpoints;
280 280 int singlestep_enabled;
281   -
  281 +
282 282 /* user data */
283 283 void *opaque;
284 284 } CPUX86State;
... ...
exec-i386.h
... ... @@ -138,6 +138,7 @@ void cpu_x86_update_cr0(CPUX86State *env);
138 138 void cpu_x86_update_cr3(CPUX86State *env);
139 139 void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr);
140 140 int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write);
  141 +void tlb_fill(unsigned long addr, int is_write, void *retaddr);
141 142 void __hidden cpu_lock(void);
142 143 void __hidden cpu_unlock(void);
143 144 void do_interrupt(int intno, int is_int, int error_code,
... ... @@ -364,3 +365,52 @@ static inline void load_eflags(int eflags, int update_mask)
364 365 env->eflags = (env->eflags & ~update_mask) |
365 366 (eflags & update_mask);
366 367 }
  368 +
  369 +/* memory access macros */
  370 +
  371 +#define ldul ldl
  372 +#define lduq ldq
  373 +#define ldul_user ldl_user
  374 +#define ldul_kernel ldl_kernel
  375 +
  376 +#define ldub_raw ldub
  377 +#define ldsb_raw ldsb
  378 +#define lduw_raw lduw
  379 +#define ldsw_raw ldsw
  380 +#define ldl_raw ldl
  381 +#define ldq_raw ldq
  382 +
  383 +#define stb_raw stb
  384 +#define stw_raw stw
  385 +#define stl_raw stl
  386 +#define stq_raw stq
  387 +
  388 +#define MEMUSER 0
  389 +#define DATA_SIZE 1
  390 +#include "softmmu_header.h"
  391 +
  392 +#define DATA_SIZE 2
  393 +#include "softmmu_header.h"
  394 +
  395 +#define DATA_SIZE 4
  396 +#include "softmmu_header.h"
  397 +
  398 +#define DATA_SIZE 8
  399 +#include "softmmu_header.h"
  400 +
  401 +#undef MEMUSER
  402 +#define MEMUSER 1
  403 +#define DATA_SIZE 1
  404 +#include "softmmu_header.h"
  405 +
  406 +#define DATA_SIZE 2
  407 +#include "softmmu_header.h"
  408 +
  409 +#define DATA_SIZE 4
  410 +#include "softmmu_header.h"
  411 +
  412 +#define DATA_SIZE 8
  413 +#include "softmmu_header.h"
  414 +
  415 +#undef MEMUSER
  416 +
... ...
... ... @@ -68,6 +68,7 @@ typedef struct PageDesc {
68 68 #define L2_SIZE (1 << L2_BITS)
69 69  
70 70 static void tb_invalidate_page(unsigned long address);
  71 +static void io_mem_init(void);
71 72  
72 73 unsigned long real_host_page_size;
73 74 unsigned long host_page_bits;
... ... @@ -76,6 +77,12 @@ unsigned long host_page_mask;
76 77  
77 78 static PageDesc *l1_map[L1_SIZE];
78 79  
  80 +/* io memory support */
  81 +static unsigned long *l1_physmap[L1_SIZE];
  82 +CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
  83 +CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
  84 +static int io_mem_nb;
  85 +
79 86 static void page_init(void)
80 87 {
81 88 /* NOTE: we can always suppose that host_page_size >=
... ... @@ -201,6 +208,7 @@ void cpu_exec_init(void)
201 208 if (!code_gen_ptr) {
202 209 code_gen_ptr = code_gen_buffer;
203 210 page_init();
  211 + io_mem_init();
204 212 }
205 213 }
206 214  
... ... @@ -744,3 +752,133 @@ void page_unmap(void)
744 752 tb_flush();
745 753 }
746 754 #endif
  755 +
  756 +void tlb_flush(CPUState *env)
  757 +{
  758 +#if defined(TARGET_I386)
  759 + int i;
  760 + for(i = 0; i < CPU_TLB_SIZE; i++) {
  761 + env->tlb_read[0][i].address = -1;
  762 + env->tlb_write[0][i].address = -1;
  763 + env->tlb_read[1][i].address = -1;
  764 + env->tlb_write[1][i].address = -1;
  765 + }
  766 +#endif
  767 +}
  768 +
  769 +void tlb_flush_page(CPUState *env, uint32_t addr)
  770 +{
  771 +#if defined(TARGET_I386)
  772 + int i;
  773 +
  774 + i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  775 + env->tlb_read[0][i].address = -1;
  776 + env->tlb_write[0][i].address = -1;
  777 + env->tlb_read[1][i].address = -1;
  778 + env->tlb_write[1][i].address = -1;
  779 +#endif
  780 +}
  781 +
  782 +static inline unsigned long *physpage_find_alloc(unsigned int page)
  783 +{
  784 + unsigned long **lp, *p;
  785 + unsigned int index, i;
  786 +
  787 + index = page >> TARGET_PAGE_BITS;
  788 + lp = &l1_physmap[index >> L2_BITS];
  789 + p = *lp;
  790 + if (!p) {
  791 + /* allocate if not found */
  792 + p = malloc(sizeof(unsigned long) * L2_SIZE);
  793 + for(i = 0; i < L2_SIZE; i++)
  794 + p[i] = IO_MEM_UNASSIGNED;
  795 + *lp = p;
  796 + }
  797 + return p + (index & (L2_SIZE - 1));
  798 +}
  799 +
  800 +/* return NULL if no page defined (unused memory) */
  801 +unsigned long physpage_find(unsigned long page)
  802 +{
  803 + unsigned long *p;
  804 + unsigned int index;
  805 + index = page >> TARGET_PAGE_BITS;
  806 + p = l1_physmap[index >> L2_BITS];
  807 + if (!p)
  808 + return IO_MEM_UNASSIGNED;
  809 + return p[index & (L2_SIZE - 1)];
  810 +}
  811 +
  812 +/* register physical memory. 'size' must be a multiple of the target
  813 + page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
  814 + io memory page */
  815 +void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
  816 + long phys_offset)
  817 +{
  818 + unsigned long addr, end_addr;
  819 + unsigned long *p;
  820 +
  821 + end_addr = start_addr + size;
  822 + for(addr = start_addr; addr < end_addr; addr += TARGET_PAGE_SIZE) {
  823 + p = physpage_find_alloc(addr);
  824 + *p = phys_offset;
  825 + if ((phys_offset & ~TARGET_PAGE_MASK) == 0)
  826 + phys_offset += TARGET_PAGE_SIZE;
  827 + }
  828 +}
  829 +
  830 +static uint32_t unassigned_mem_readb(uint32_t addr)
  831 +{
  832 + return 0;
  833 +}
  834 +
  835 +static void unassigned_mem_writeb(uint32_t addr, uint32_t val)
  836 +{
  837 +}
  838 +
  839 +static CPUReadMemoryFunc *unassigned_mem_read[3] = {
  840 + unassigned_mem_readb,
  841 + unassigned_mem_readb,
  842 + unassigned_mem_readb,
  843 +};
  844 +
  845 +static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
  846 + unassigned_mem_writeb,
  847 + unassigned_mem_writeb,
  848 + unassigned_mem_writeb,
  849 +};
  850 +
  851 +
  852 +static void io_mem_init(void)
  853 +{
  854 + io_mem_nb = 1;
  855 + cpu_register_io_memory(0, unassigned_mem_read, unassigned_mem_write);
  856 +}
  857 +
  858 +/* mem_read and mem_write are arrays of functions containing the
  859 + function to access byte (index 0), word (index 1) and dword (index
  860 + 2). All functions must be supplied. If io_index is non zero, the
  861 + corresponding io zone is modified. If it is zero, a new io zone is
  862 + allocated. The return value can be used with
  863 + cpu_register_physical_memory(). (-1) is returned if error. */
  864 +int cpu_register_io_memory(int io_index,
  865 + CPUReadMemoryFunc **mem_read,
  866 + CPUWriteMemoryFunc **mem_write)
  867 +{
  868 + int i;
  869 +
  870 + if (io_index <= 0) {
  871 + if (io_index >= IO_MEM_NB_ENTRIES)
  872 + return -1;
  873 + io_index = io_mem_nb++;
  874 + } else {
  875 + if (io_index >= IO_MEM_NB_ENTRIES)
  876 + return -1;
  877 + }
  878 +
  879 + for(i = 0;i < 3; i++) {
  880 + io_mem_read[io_index][i] = mem_read[i];
  881 + io_mem_write[io_index][i] = mem_write[i];
  882 + }
  883 + return io_index << IO_MEM_SHIFT;
  884 +}
... ...
... ... @@ -21,6 +21,17 @@
21 21 /* allow to see translation results - the slowdown should be negligible, so we leave it */
22 22 #define DEBUG_DISAS
23 23  
  24 +#ifndef glue
  25 +#define xglue(x, y) x ## y
  26 +#define glue(x, y) xglue(x, y)
  27 +#define stringify(s) tostring(s)
  28 +#define tostring(s) #s
  29 +#endif
  30 +
  31 +#if GCC_MAJOR < 3
  32 +#define __builtin_expect(x, n) (x)
  33 +#endif
  34 +
24 35 /* is_jmp field values */
25 36 #define DISAS_NEXT 0 /* next instruction can be analyzed */
26 37 #define DISAS_JUMP 1 /* only pc was modified dynamically */
... ... @@ -44,14 +55,17 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
44 55  
45 56 #if defined(TARGET_I386)
46 57  
47   -#define GEN_FLAG_CODE32_SHIFT 0
48   -#define GEN_FLAG_ADDSEG_SHIFT 1
49   -#define GEN_FLAG_SS32_SHIFT 2
50   -#define GEN_FLAG_VM_SHIFT 3
51   -#define GEN_FLAG_ST_SHIFT 4
52   -#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */
53   -#define GEN_FLAG_CPL_SHIFT 9
54   -#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */
  58 +#define GEN_FLAG_CODE32_SHIFT 0
  59 +#define GEN_FLAG_ADDSEG_SHIFT 1
  60 +#define GEN_FLAG_SS32_SHIFT 2
  61 +#define GEN_FLAG_VM_SHIFT 3
  62 +#define GEN_FLAG_ST_SHIFT 4
  63 +#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */
  64 +#define GEN_FLAG_CPL_SHIFT 9
  65 +#define GEN_FLAG_SOFT_MMU_SHIFT 11
  66 +#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */
  67 +
  68 +void optimize_flags_init(void);
55 69  
56 70 #endif
57 71  
... ... @@ -68,6 +82,8 @@ int cpu_restore_state(struct TranslationBlock *tb,
68 82 void cpu_exec_init(void);
69 83 int page_unprotect(unsigned long address);
70 84 void page_unmap(void);
  85 +void tlb_flush_page(CPUState *env, uint32_t addr);
  86 +void tlb_flush(CPUState *env);
71 87  
72 88 #define CODE_GEN_MAX_SIZE 65536
73 89 #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
... ... @@ -230,6 +246,17 @@ dummy_label ## n:\
230 246  
231 247 #endif
232 248  
  249 +/* physical memory access */
  250 +#define IO_MEM_NB_ENTRIES 256
  251 +#define TLB_INVALID_MASK (1 << 3)
  252 +#define IO_MEM_SHIFT 4
  253 +#define IO_MEM_UNASSIGNED (1 << IO_MEM_SHIFT)
  254 +
  255 +unsigned long physpage_find(unsigned long page);
  256 +
  257 +extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
  258 +extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
  259 +
233 260 #ifdef __powerpc__
234 261 static inline int testandset (int *p)
235 262 {
... ...
helper-i386.c
... ... @@ -781,7 +781,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip)
781 781 int new_cs, new_eip;
782 782 uint32_t esp, esp_mask;
783 783 uint8_t *ssp;
784   -
  784 +
785 785 new_cs = T0;
786 786 new_eip = T1;
787 787 esp = env->regs[R_ESP];
... ... @@ -1741,3 +1741,34 @@ void helper_frstor(uint8_t *ptr, int data32)
1741 1741 }
1742 1742 }
1743 1743  
  1744 +#define SHIFT 0
  1745 +#include "softmmu_template.h"
  1746 +
  1747 +#define SHIFT 1
  1748 +#include "softmmu_template.h"
  1749 +
  1750 +#define SHIFT 2
  1751 +#include "softmmu_template.h"
  1752 +
  1753 +#define SHIFT 3
  1754 +#include "softmmu_template.h"
  1755 +
  1756 +/* try to fill the TLB and return an exception if error */
  1757 +void tlb_fill(unsigned long addr, int is_write, void *retaddr)
  1758 +{
  1759 + TranslationBlock *tb;
  1760 + int ret;
  1761 + unsigned long pc;
  1762 + ret = cpu_x86_handle_mmu_fault(env, addr, is_write);
  1763 + if (ret) {
  1764 + /* now we have a real cpu fault */
  1765 + pc = (unsigned long)retaddr;
  1766 + tb = tb_find_pc(pc);
  1767 + if (tb) {
  1768 + /* the PC is inside the translated code. It means that we have
  1769 + a virtual CPU fault */
  1770 + cpu_restore_state(tb, env, pc);
  1771 + }
  1772 + raise_exception_err(EXCP0E_PAGE, env->error_code);
  1773 + }
  1774 +}
... ...
op-i386.c
... ... @@ -376,70 +376,14 @@ void OPPROTO op_andl_A0_ffff(void)
376 376  
377 377 /* memory access */
378 378  
379   -void OPPROTO op_ldub_T0_A0(void)
380   -{
381   - T0 = ldub((uint8_t *)A0);
382   -}
383   -
384   -void OPPROTO op_ldsb_T0_A0(void)
385   -{
386   - T0 = ldsb((int8_t *)A0);
387   -}
388   -
389   -void OPPROTO op_lduw_T0_A0(void)
390   -{
391   - T0 = lduw((uint8_t *)A0);
392   -}
393   -
394   -void OPPROTO op_ldsw_T0_A0(void)
395   -{
396   - T0 = ldsw((int8_t *)A0);
397   -}
398   -
399   -void OPPROTO op_ldl_T0_A0(void)
400   -{
401   - T0 = ldl((uint8_t *)A0);
402   -}
  379 +#define MEMSUFFIX
  380 +#include "ops_mem.h"
403 381  
404   -void OPPROTO op_ldub_T1_A0(void)
405   -{
406   - T1 = ldub((uint8_t *)A0);
407   -}
408   -
409   -void OPPROTO op_ldsb_T1_A0(void)
410   -{
411   - T1 = ldsb((int8_t *)A0);
412   -}
413   -
414   -void OPPROTO op_lduw_T1_A0(void)
415   -{
416   - T1 = lduw((uint8_t *)A0);
417   -}
  382 +#define MEMSUFFIX _user
  383 +#include "ops_mem.h"
418 384  
419   -void OPPROTO op_ldsw_T1_A0(void)
420   -{
421   - T1 = ldsw((int8_t *)A0);
422   -}
423   -
424   -void OPPROTO op_ldl_T1_A0(void)
425   -{
426   - T1 = ldl((uint8_t *)A0);
427   -}
428   -
429   -void OPPROTO op_stb_T0_A0(void)
430   -{
431   - stb((uint8_t *)A0, T0);
432   -}
433   -
434   -void OPPROTO op_stw_T0_A0(void)
435   -{
436   - stw((uint8_t *)A0, T0);
437   -}
438   -
439   -void OPPROTO op_stl_T0_A0(void)
440   -{
441   - stl((uint8_t *)A0, T0);
442   -}
  385 +#define MEMSUFFIX _kernel
  386 +#include "ops_mem.h"
443 387  
444 388 /* used for bit operations */
445 389  
... ... @@ -635,6 +579,38 @@ void OPPROTO op_movswl_DX_AX(void)
635 579 EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
636 580 }
637 581  
  582 +/* string ops helpers */
  583 +
  584 +void OPPROTO op_addl_ESI_T0(void)
  585 +{
  586 + ESI += T0;
  587 +}
  588 +
  589 +void OPPROTO op_addw_ESI_T0(void)
  590 +{
  591 + ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
  592 +}
  593 +
  594 +void OPPROTO op_addl_EDI_T0(void)
  595 +{
  596 + EDI += T0;
  597 +}
  598 +
  599 +void OPPROTO op_addw_EDI_T0(void)
  600 +{
  601 + EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
  602 +}
  603 +
  604 +void OPPROTO op_decl_ECX(void)
  605 +{
  606 + ECX--;
  607 +}
  608 +
  609 +void OPPROTO op_decw_ECX(void)
  610 +{
  611 + ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
  612 +}
  613 +
638 614 /* push/pop */
639 615  
640 616 void op_pushl_T0(void)
... ...
op_string.h
1 1  
2   -void OPPROTO glue(glue(op_movs, SUFFIX), STRING_SUFFIX)(void)
3   -{
4   - int v, inc;
5   - v = glue(ldu, SUFFIX)(SI_ADDR);
6   - glue(st, SUFFIX)(DI_ADDR, v);
7   - inc = (DF << SHIFT);
8   - INC_SI();
9   - INC_DI();
10   -}
11   -
12   -void OPPROTO glue(glue(op_rep_movs, SUFFIX), STRING_SUFFIX)(void)
13   -{
14   - int v, inc;
15   - inc = (DF << SHIFT);
16   - while (CX != 0) {
17   - v = glue(ldu, SUFFIX)(SI_ADDR);
18   - glue(st, SUFFIX)(DI_ADDR, v);
19   - INC_SI();
20   - INC_DI();
21   - DEC_CX();
22   - }
23   - FORCE_RET();
24   -}
25   -
26   -void OPPROTO glue(glue(op_stos, SUFFIX), STRING_SUFFIX)(void)
27   -{
28   - int inc;
29   - glue(st, SUFFIX)(DI_ADDR, EAX);
30   - inc = (DF << SHIFT);
31   - INC_DI();
32   -}
33   -
34   -void OPPROTO glue(glue(op_rep_stos, SUFFIX), STRING_SUFFIX)(void)
35   -{
36   - int inc;
37   - inc = (DF << SHIFT);
38   - while (CX != 0) {
39   - glue(st, SUFFIX)(DI_ADDR, EAX);
40   - INC_DI();
41   - DEC_CX();
42   - }
43   - FORCE_RET();
44   -}
45   -
46   -void OPPROTO glue(glue(op_lods, SUFFIX), STRING_SUFFIX)(void)
47   -{
48   - int v, inc;
49   - v = glue(ldu, SUFFIX)(SI_ADDR);
50   -#if SHIFT == 0
51   - EAX = (EAX & ~0xff) | v;
52   -#elif SHIFT == 1
53   - EAX = (EAX & ~0xffff) | v;
54   -#else
55   - EAX = v;
56   -#endif
57   - inc = (DF << SHIFT);
58   - INC_SI();
59   -}
60   -
61   -/* don't know if it is used */
62   -void OPPROTO glue(glue(op_rep_lods, SUFFIX), STRING_SUFFIX)(void)
63   -{
64   - int v, inc;
65   - inc = (DF << SHIFT);
66   - while (CX != 0) {
67   - v = glue(ldu, SUFFIX)(SI_ADDR);
68   -#if SHIFT == 0
69   - EAX = (EAX & ~0xff) | v;
70   -#elif SHIFT == 1
71   - EAX = (EAX & ~0xffff) | v;
72   -#else
73   - EAX = v;
74   -#endif
75   - INC_SI();
76   - DEC_CX();
77   - }
78   - FORCE_RET();
79   -}
80   -
81   -void OPPROTO glue(glue(op_scas, SUFFIX), STRING_SUFFIX)(void)
82   -{
83   - int v, inc;
84   -
85   - v = glue(ldu, SUFFIX)(DI_ADDR);
86   - inc = (DF << SHIFT);
87   - INC_DI();
88   - CC_SRC = v;
89   - CC_DST = EAX - v;
90   -}
91   -
92 2 void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void)
93 3 {
94 4 int v1, v2, inc;
... ... @@ -133,18 +43,6 @@ void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void)
133 43 FORCE_RET();
134 44 }
135 45  
136   -void OPPROTO glue(glue(op_cmps, SUFFIX), STRING_SUFFIX)(void)
137   -{
138   - int v1, v2, inc;
139   - v1 = glue(ldu, SUFFIX)(SI_ADDR);
140   - v2 = glue(ldu, SUFFIX)(DI_ADDR);
141   - inc = (DF << SHIFT);
142   - INC_SI();
143   - INC_DI();
144   - CC_SRC = v2;
145   - CC_DST = v1 - v2;
146   -}
147   -
148 46 void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void)
149 47 {
150 48 int v1, v2, inc;
... ... @@ -187,54 +85,6 @@ void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void)
187 85 FORCE_RET();
188 86 }
189 87  
190   -void OPPROTO glue(glue(op_outs, SUFFIX), STRING_SUFFIX)(void)
191   -{
192   - int v, dx, inc;
193   - dx = EDX & 0xffff;
194   - v = glue(ldu, SUFFIX)(SI_ADDR);
195   - glue(cpu_x86_out, SUFFIX)(env, dx, v);
196   - inc = (DF << SHIFT);
197   - INC_SI();
198   -}
199   -
200   -void OPPROTO glue(glue(op_rep_outs, SUFFIX), STRING_SUFFIX)(void)
201   -{
202   - int v, dx, inc;
203   - inc = (DF << SHIFT);
204   - dx = EDX & 0xffff;
205   - while (CX != 0) {
206   - v = glue(ldu, SUFFIX)(SI_ADDR);
207   - glue(cpu_x86_out, SUFFIX)(env, dx, v);
208   - INC_SI();
209   - DEC_CX();
210   - }
211   - FORCE_RET();
212   -}
213   -
214   -void OPPROTO glue(glue(op_ins, SUFFIX), STRING_SUFFIX)(void)
215   -{
216   - int v, dx, inc;
217   - dx = EDX & 0xffff;
218   - v = glue(cpu_x86_in, SUFFIX)(env, dx);
219   - glue(st, SUFFIX)(DI_ADDR, v);
220   - inc = (DF << SHIFT);
221   - INC_DI();
222   -}
223   -
224   -void OPPROTO glue(glue(op_rep_ins, SUFFIX), STRING_SUFFIX)(void)
225   -{
226   - int v, dx, inc;
227   - inc = (DF << SHIFT);
228   - dx = EDX & 0xffff;
229   - while (CX != 0) {
230   - v = glue(cpu_x86_in, SUFFIX)(env, dx);
231   - glue(st, SUFFIX)(DI_ADDR, v);
232   - INC_DI();
233   - DEC_CX();
234   - }
235   - FORCE_RET();
236   -}
237   -
238 88 #undef STRING_SUFFIX
239 89 #undef SI_ADDR
240 90 #undef DI_ADDR
... ...
ops_template.h
... ... @@ -547,6 +547,31 @@ void OPPROTO op_update_bt_cc(void)
547 547 #define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff)
548 548 #include "op_string.h"
549 549  
  550 +void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
  551 +{
  552 + T0 = DF << SHIFT;
  553 +}
  554 +
  555 +void OPPROTO glue(op_string_jz_sub, SUFFIX)(void)
  556 +{
  557 + if ((DATA_TYPE)CC_DST == 0)
  558 + JUMP_TB(PARAM1, 1, PARAM2);
  559 +}
  560 +
  561 +void OPPROTO glue(op_string_jnz_sub, SUFFIX)(void)
  562 +{
  563 + if ((DATA_TYPE)CC_DST != 0)
  564 + JUMP_TB(PARAM1, 1, PARAM2);
  565 +}
  566 +
  567 +#if DATA_BITS >= 16
  568 +void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
  569 +{
  570 + if ((DATA_TYPE)ECX == 0)
  571 + JUMP_TB(PARAM1, 1, PARAM2);
  572 +}
  573 +#endif
  574 +
550 575 /* port I/O */
551 576  
552 577 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
... ... @@ -559,6 +584,16 @@ void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
559 584 T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff);
560 585 }
561 586  
  587 +void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
  588 +{
  589 + T0 = glue(cpu_x86_in, SUFFIX)(env, EDX & 0xffff);
  590 +}
  591 +
  592 +void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
  593 +{
  594 + glue(cpu_x86_out, SUFFIX)(env, EDX & 0xffff, T0);
  595 +}
  596 +
562 597 #undef DATA_BITS
563 598 #undef SHIFT_MASK
564 599 #undef SIGN_MASK
... ...