soft mmu support - Memory I/O API - synthetize string instructions
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 10 Aug 2003 21:47:01 +0000 (21:47 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 10 Aug 2003 21:47:01 +0000 (21:47 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@354 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-all.h
cpu-arm.h
cpu-i386.h
exec-i386.h
exec.c
exec.h
helper-i386.c
op-i386.c
op_string.h
ops_template.h

index cde8451..6530492 100644 (file)
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -140,6 +140,7 @@ static inline void stfl(void *ptr, float v)
     stl(ptr, u.i);
 }
 
+
 #if defined(__arm__) && !defined(WORDS_BIGENDIAN)
 
 /* 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);
 int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
 void cpu_single_step(CPUState *env, int enabled);
 
+/* memory API */
+
+typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value);
+typedef uint32_t CPUReadMemoryFunc(uint32_t addr);
+
+void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
+                                  long phys_offset);
+int cpu_register_io_memory(int io_index,
+                           CPUReadMemoryFunc **mem_read,
+                           CPUWriteMemoryFunc **mem_write);
+
 /* gdb stub API */
 extern int gdbstub_fd;
 CPUState *cpu_gdbstub_get_env(void *opaque);
index 3b2e628..7f755a7 100644 (file)
--- a/cpu-arm.h
+++ b/cpu-arm.h
 #ifndef CPU_ARM_H
 #define CPU_ARM_H
 
-#include "config.h"
-#include <setjmp.h>
+#include "cpu-defs.h"
 
 #define EXCP_UDEF       1   /* undefined instruction */
 #define EXCP_SWI        2   /* software interrupt */
-#define EXCP_INTERRUPT         256 /* async interruption */
 
 typedef struct CPUARMState {
     uint32_t regs[16];
index 879ab1e..a60e959 100644 (file)
@@ -20,8 +20,7 @@
 #ifndef CPU_I386_H
 #define CPU_I386_H
 
-#include "config.h"
-#include <setjmp.h>
+#include "cpu-defs.h"
 
 #define R_EAX 0
 #define R_ECX 1
 #define EXCP11_ALGN    17
 #define EXCP12_MCHK    18
 
-#define EXCP_INTERRUPT         256 /* async interruption */
-#define EXCP_HLT        257 /* hlt instruction reached */
-#define EXCP_DEBUG      258 /* cpu stopped after a breakpoint or singlestep */
-
-#define MAX_BREAKPOINTS 32
-
 enum {
     CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
     CC_OP_EFLAGS,  /* all cc are explicitely computed, CC_SRC = flags */
@@ -257,7 +250,8 @@ typedef struct CPUX86State {
     SegmentCache gdt; /* only base and limit are used */
     SegmentCache idt; /* only base and limit are used */
     int cpl;          /* current cpl */
-
+    int soft_mmu;     /* TRUE if soft mmu is being used */
+    
     /* sysenter registers */
     uint32_t sysenter_cs;
     uint32_t sysenter_esp;
@@ -275,10 +269,16 @@ typedef struct CPUX86State {
     int interrupt_request; 
     int user_mode_only; /* user mode only simulation */
 
+    /* soft mmu support */
+    /* 0 = kernel, 1 = user */
+    CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
+    CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
+    
+    /* ice debug support */
     uint32_t breakpoints[MAX_BREAKPOINTS];
     int nb_breakpoints;
     int singlestep_enabled;
-    
+
     /* user data */
     void *opaque;
 } CPUX86State;
index 964abdd..03a547f 100644 (file)
@@ -138,6 +138,7 @@ void cpu_x86_update_cr0(CPUX86State *env);
 void cpu_x86_update_cr3(CPUX86State *env);
 void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr);
 int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write);
+void tlb_fill(unsigned long addr, int is_write, void *retaddr);
 void __hidden cpu_lock(void);
 void __hidden cpu_unlock(void);
 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)
     env->eflags = (env->eflags & ~update_mask) | 
         (eflags & update_mask);
 }
+
+/* memory access macros */
+
+#define ldul ldl
+#define lduq ldq
+#define ldul_user ldl_user
+#define ldul_kernel ldl_kernel
+
+#define ldub_raw ldub
+#define ldsb_raw ldsb
+#define lduw_raw lduw
+#define ldsw_raw ldsw
+#define ldl_raw ldl
+#define ldq_raw ldq
+
+#define stb_raw stb
+#define stw_raw stw
+#define stl_raw stl
+#define stq_raw stq
+
+#define MEMUSER 0
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+
+#undef MEMUSER
+#define MEMUSER 1
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+
+#undef MEMUSER
+
diff --git a/exec.c b/exec.c
index 5ea2163..cdc2a0b 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -68,6 +68,7 @@ typedef struct PageDesc {
 #define L2_SIZE (1 << L2_BITS)
 
 static void tb_invalidate_page(unsigned long address);
+static void io_mem_init(void);
 
 unsigned long real_host_page_size;
 unsigned long host_page_bits;
@@ -76,6 +77,12 @@ unsigned long host_page_mask;
 
 static PageDesc *l1_map[L1_SIZE];
 
+/* io memory support */
+static unsigned long *l1_physmap[L1_SIZE];
+CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
+CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+static int io_mem_nb;
+
 static void page_init(void)
 {
     /* NOTE: we can always suppose that host_page_size >=
@@ -201,6 +208,7 @@ void cpu_exec_init(void)
     if (!code_gen_ptr) {
         code_gen_ptr = code_gen_buffer;
         page_init();
+        io_mem_init();
     }
 }
 
@@ -744,3 +752,133 @@ void page_unmap(void)
     tb_flush();
 }
 #endif
+
+void tlb_flush(CPUState *env)
+{
+#if defined(TARGET_I386)
+    int i;
+    for(i = 0; i < CPU_TLB_SIZE; i++) {
+        env->tlb_read[0][i].address = -1;
+        env->tlb_write[0][i].address = -1;
+        env->tlb_read[1][i].address = -1;
+        env->tlb_write[1][i].address = -1;
+    }
+#endif
+}
+
+void tlb_flush_page(CPUState *env, uint32_t addr)
+{
+#if defined(TARGET_I386)
+    int i;
+
+    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    env->tlb_read[0][i].address = -1;
+    env->tlb_write[0][i].address = -1;
+    env->tlb_read[1][i].address = -1;
+    env->tlb_write[1][i].address = -1;
+#endif
+}
+
+static inline unsigned long *physpage_find_alloc(unsigned int page)
+{
+    unsigned long **lp, *p;
+    unsigned int index, i;
+
+    index = page >> TARGET_PAGE_BITS;
+    lp = &l1_physmap[index >> L2_BITS];
+    p = *lp;
+    if (!p) {
+        /* allocate if not found */
+        p = malloc(sizeof(unsigned long) * L2_SIZE);
+        for(i = 0; i < L2_SIZE; i++)
+            p[i] = IO_MEM_UNASSIGNED;
+        *lp = p;
+    }
+    return p + (index & (L2_SIZE - 1));
+}
+
+/* return NULL if no page defined (unused memory) */
+unsigned long physpage_find(unsigned long page)
+{
+    unsigned long *p;
+    unsigned int index;
+    index = page >> TARGET_PAGE_BITS;
+    p = l1_physmap[index >> L2_BITS];
+    if (!p)
+        return IO_MEM_UNASSIGNED;
+    return p[index & (L2_SIZE - 1)];
+}
+
+/* register physical memory. 'size' must be a multiple of the target
+   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
+   io memory page */
+void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
+                                  long phys_offset)
+{
+    unsigned long addr, end_addr;
+    unsigned long *p;
+
+    end_addr = start_addr + size;
+    for(addr = start_addr; addr < end_addr; addr += TARGET_PAGE_SIZE) {
+        p = physpage_find_alloc(addr);
+        *p = phys_offset;
+        if ((phys_offset & ~TARGET_PAGE_MASK) == 0)
+            phys_offset += TARGET_PAGE_SIZE;
+    }
+}
+
+static uint32_t unassigned_mem_readb(uint32_t addr)
+{
+    return 0;
+}
+
+static void unassigned_mem_writeb(uint32_t addr, uint32_t val)
+{
+}
+
+static CPUReadMemoryFunc *unassigned_mem_read[3] = {
+    unassigned_mem_readb,
+    unassigned_mem_readb,
+    unassigned_mem_readb,
+};
+
+static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
+    unassigned_mem_writeb,
+    unassigned_mem_writeb,
+    unassigned_mem_writeb,
+};
+
+
+static void io_mem_init(void)
+{
+    io_mem_nb = 1;
+    cpu_register_io_memory(0, unassigned_mem_read, unassigned_mem_write);
+}
+
+/* mem_read and mem_write are arrays of functions containing the
+   function to access byte (index 0), word (index 1) and dword (index
+   2). All functions must be supplied. If io_index is non zero, the
+   corresponding io zone is modified. If it is zero, a new io zone is
+   allocated. The return value can be used with
+   cpu_register_physical_memory(). (-1) is returned if error. */
+int cpu_register_io_memory(int io_index,
+                           CPUReadMemoryFunc **mem_read,
+                           CPUWriteMemoryFunc **mem_write)
+{
+    int i;
+
+    if (io_index <= 0) {
+        if (io_index >= IO_MEM_NB_ENTRIES)
+            return -1;
+        io_index = io_mem_nb++;
+    } else {
+        if (io_index >= IO_MEM_NB_ENTRIES)
+            return -1;
+    }
+    
+    for(i = 0;i < 3; i++) {
+        io_mem_read[io_index][i] = mem_read[i];
+        io_mem_write[io_index][i] = mem_write[i];
+    }
+    return io_index << IO_MEM_SHIFT;
+}
diff --git a/exec.h b/exec.h
index 9489c47..5c4e841 100644 (file)
--- a/exec.h
+++ b/exec.h
 /* allow to see translation results - the slowdown should be negligible, so we leave it */
 #define DEBUG_DISAS
 
+#ifndef glue
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s)   tostring(s)
+#define tostring(s)    #s
+#endif
+
+#if GCC_MAJOR < 3
+#define __builtin_expect(x, n) (x)
+#endif
+
 /* is_jmp field values */
 #define DISAS_NEXT    0 /* next instruction can be analyzed */
 #define DISAS_JUMP    1 /* only pc was modified dynamically */
@@ -44,14 +55,17 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
 
 #if defined(TARGET_I386)
 
-#define GEN_FLAG_CODE32_SHIFT 0
-#define GEN_FLAG_ADDSEG_SHIFT 1
-#define GEN_FLAG_SS32_SHIFT   2
-#define GEN_FLAG_VM_SHIFT     3
-#define GEN_FLAG_ST_SHIFT     4
-#define GEN_FLAG_TF_SHIFT     8 /* same position as eflags */
-#define GEN_FLAG_CPL_SHIFT    9
-#define GEN_FLAG_IOPL_SHIFT   12 /* same position as eflags */
+#define GEN_FLAG_CODE32_SHIFT    0
+#define GEN_FLAG_ADDSEG_SHIFT    1
+#define GEN_FLAG_SS32_SHIFT      2
+#define GEN_FLAG_VM_SHIFT        3
+#define GEN_FLAG_ST_SHIFT        4
+#define GEN_FLAG_TF_SHIFT        8 /* same position as eflags */
+#define GEN_FLAG_CPL_SHIFT       9
+#define GEN_FLAG_SOFT_MMU_SHIFT 11
+#define GEN_FLAG_IOPL_SHIFT     12 /* same position as eflags */
+
+void optimize_flags_init(void);
 
 #endif
 
@@ -68,6 +82,8 @@ int cpu_restore_state(struct TranslationBlock *tb,
 void cpu_exec_init(void);
 int page_unprotect(unsigned long address);
 void page_unmap(void);
+void tlb_flush_page(CPUState *env, uint32_t addr);
+void tlb_flush(CPUState *env);
 
 #define CODE_GEN_MAX_SIZE        65536
 #define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
@@ -230,6 +246,17 @@ dummy_label ## n:\
 
 #endif
 
+/* physical memory access */
+#define IO_MEM_NB_ENTRIES  256
+#define TLB_INVALID_MASK   (1 << 3)
+#define IO_MEM_SHIFT       4
+#define IO_MEM_UNASSIGNED  (1 << IO_MEM_SHIFT)
+
+unsigned long physpage_find(unsigned long page);
+
+extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
+extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+
 #ifdef __powerpc__
 static inline int testandset (int *p)
 {
index 0003fb4..01046ea 100644 (file)
@@ -781,7 +781,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip)
     int new_cs, new_eip;
     uint32_t esp, esp_mask;
     uint8_t *ssp;
-    
+
     new_cs = T0;
     new_eip = T1;
     esp = env->regs[R_ESP];
@@ -1741,3 +1741,34 @@ void helper_frstor(uint8_t *ptr, int data32)
     }
 }
 
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+/* try to fill the TLB and return an exception if error */
+void tlb_fill(unsigned long addr, int is_write, void *retaddr)
+{
+    TranslationBlock *tb;
+    int ret;
+    unsigned long pc;
+    ret = cpu_x86_handle_mmu_fault(env, addr, is_write);
+    if (ret) {
+        /* now we have a real cpu fault */
+        pc = (unsigned long)retaddr;
+        tb = tb_find_pc(pc);
+        if (tb) {
+            /* the PC is inside the translated code. It means that we have
+               a virtual CPU fault */
+            cpu_restore_state(tb, env, pc);
+        }
+        raise_exception_err(EXCP0E_PAGE, env->error_code);
+    }
+}
index fb062a0..60ae5e5 100644 (file)
--- a/op-i386.c
+++ b/op-i386.c
@@ -376,70 +376,14 @@ void OPPROTO op_andl_A0_ffff(void)
 
 /* memory access */
 
-void OPPROTO op_ldub_T0_A0(void)
-{
-    T0 = ldub((uint8_t *)A0);
-}
-
-void OPPROTO op_ldsb_T0_A0(void)
-{
-    T0 = ldsb((int8_t *)A0);
-}
-
-void OPPROTO op_lduw_T0_A0(void)
-{
-    T0 = lduw((uint8_t *)A0);
-}
-
-void OPPROTO op_ldsw_T0_A0(void)
-{
-    T0 = ldsw((int8_t *)A0);
-}
-
-void OPPROTO op_ldl_T0_A0(void)
-{
-    T0 = ldl((uint8_t *)A0);
-}
+#define MEMSUFFIX
+#include "ops_mem.h"
 
-void OPPROTO op_ldub_T1_A0(void)
-{
-    T1 = ldub((uint8_t *)A0);
-}
-
-void OPPROTO op_ldsb_T1_A0(void)
-{
-    T1 = ldsb((int8_t *)A0);
-}
-
-void OPPROTO op_lduw_T1_A0(void)
-{
-    T1 = lduw((uint8_t *)A0);
-}
+#define MEMSUFFIX _user
+#include "ops_mem.h"
 
-void OPPROTO op_ldsw_T1_A0(void)
-{
-    T1 = ldsw((int8_t *)A0);
-}
-
-void OPPROTO op_ldl_T1_A0(void)
-{
-    T1 = ldl((uint8_t *)A0);
-}
-
-void OPPROTO op_stb_T0_A0(void)
-{
-    stb((uint8_t *)A0, T0);
-}
-
-void OPPROTO op_stw_T0_A0(void)
-{
-    stw((uint8_t *)A0, T0);
-}
-
-void OPPROTO op_stl_T0_A0(void)
-{
-    stl((uint8_t *)A0, T0);
-}
+#define MEMSUFFIX _kernel
+#include "ops_mem.h"
 
 /* used for bit operations */
 
@@ -635,6 +579,38 @@ void OPPROTO op_movswl_DX_AX(void)
     EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
 }
 
+/* string ops helpers */
+
+void OPPROTO op_addl_ESI_T0(void)
+{
+    ESI += T0;
+}
+
+void OPPROTO op_addw_ESI_T0(void)
+{
+    ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
+}
+
+void OPPROTO op_addl_EDI_T0(void)
+{
+    EDI += T0;
+}
+
+void OPPROTO op_addw_EDI_T0(void)
+{
+    EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
+}
+
+void OPPROTO op_decl_ECX(void)
+{
+    ECX--;
+}
+
+void OPPROTO op_decw_ECX(void)
+{
+    ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
+}
+
 /* push/pop */
 
 void op_pushl_T0(void)
index 79bc11e..66b598b 100644 (file)
@@ -1,94 +1,4 @@
 
-void OPPROTO glue(glue(op_movs, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, inc;
-    v = glue(ldu, SUFFIX)(SI_ADDR);
-    glue(st, SUFFIX)(DI_ADDR, v);
-    inc = (DF << SHIFT);
-    INC_SI();
-    INC_DI();
-}
-
-void OPPROTO glue(glue(op_rep_movs, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, inc;
-    inc = (DF << SHIFT);
-    while (CX != 0) {
-        v = glue(ldu, SUFFIX)(SI_ADDR);
-        glue(st, SUFFIX)(DI_ADDR, v);
-        INC_SI();
-        INC_DI();
-        DEC_CX();
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_stos, SUFFIX), STRING_SUFFIX)(void)
-{
-    int inc;
-    glue(st, SUFFIX)(DI_ADDR, EAX);
-    inc = (DF << SHIFT);
-    INC_DI();
-}
-
-void OPPROTO glue(glue(op_rep_stos, SUFFIX), STRING_SUFFIX)(void)
-{
-    int inc;
-    inc = (DF << SHIFT);
-    while (CX != 0) {
-        glue(st, SUFFIX)(DI_ADDR, EAX);
-        INC_DI();
-        DEC_CX();
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_lods, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, inc;
-    v = glue(ldu, SUFFIX)(SI_ADDR);
-#if SHIFT == 0
-    EAX = (EAX & ~0xff) | v;
-#elif SHIFT == 1
-    EAX = (EAX & ~0xffff) | v;
-#else
-    EAX = v;
-#endif
-    inc = (DF << SHIFT);
-    INC_SI();
-}
-
-/* don't know if it is used */
-void OPPROTO glue(glue(op_rep_lods, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, inc;
-    inc = (DF << SHIFT);
-    while (CX != 0) {
-        v = glue(ldu, SUFFIX)(SI_ADDR);
-#if SHIFT == 0
-        EAX = (EAX & ~0xff) | v;
-#elif SHIFT == 1
-        EAX = (EAX & ~0xffff) | v;
-#else
-        EAX = v;
-#endif
-        INC_SI();
-        DEC_CX();
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_scas, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, inc;
-
-    v = glue(ldu, SUFFIX)(DI_ADDR);
-    inc = (DF << SHIFT);
-    INC_DI();
-    CC_SRC = v;
-    CC_DST = EAX - v;
-}
-
 void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void)
 {
     int v1, v2, inc;
@@ -133,18 +43,6 @@ void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void)
     FORCE_RET();
 }
 
-void OPPROTO glue(glue(op_cmps, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v1, v2, inc;
-    v1 = glue(ldu, SUFFIX)(SI_ADDR);
-    v2 = glue(ldu, SUFFIX)(DI_ADDR);
-    inc = (DF << SHIFT);
-    INC_SI();
-    INC_DI();
-    CC_SRC = v2;
-    CC_DST = v1 - v2;
-}
-
 void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void)
 {
     int v1, v2, inc;
@@ -187,54 +85,6 @@ void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void)
     FORCE_RET();
 }
 
-void OPPROTO glue(glue(op_outs, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, dx, inc;
-    dx = EDX & 0xffff;
-    v = glue(ldu, SUFFIX)(SI_ADDR);
-    glue(cpu_x86_out, SUFFIX)(env, dx, v);
-    inc = (DF << SHIFT);
-    INC_SI();
-}
-
-void OPPROTO glue(glue(op_rep_outs, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, dx, inc;
-    inc = (DF << SHIFT);
-    dx = EDX & 0xffff;
-    while (CX != 0) {
-        v = glue(ldu, SUFFIX)(SI_ADDR);
-        glue(cpu_x86_out, SUFFIX)(env, dx, v);
-        INC_SI();
-        DEC_CX();
-    }
-    FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_ins, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, dx, inc;
-    dx = EDX & 0xffff;
-    v = glue(cpu_x86_in, SUFFIX)(env, dx);
-    glue(st, SUFFIX)(DI_ADDR, v);
-    inc = (DF << SHIFT);
-    INC_DI();
-}
-
-void OPPROTO glue(glue(op_rep_ins, SUFFIX), STRING_SUFFIX)(void)
-{
-    int v, dx, inc;
-    inc = (DF << SHIFT);
-    dx = EDX & 0xffff;
-    while (CX != 0) {
-        v = glue(cpu_x86_in, SUFFIX)(env, dx);
-        glue(st, SUFFIX)(DI_ADDR, v);
-        INC_DI();
-        DEC_CX();
-    }
-    FORCE_RET();
-}
-
 #undef STRING_SUFFIX
 #undef SI_ADDR
 #undef DI_ADDR
index 4595291..89480dd 100644 (file)
@@ -547,6 +547,31 @@ void OPPROTO op_update_bt_cc(void)
 #define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff)
 #include "op_string.h"
 
+void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
+{
+    T0 = DF << SHIFT;
+}
+
+void OPPROTO glue(op_string_jz_sub, SUFFIX)(void)
+{
+    if ((DATA_TYPE)CC_DST == 0)
+        JUMP_TB(PARAM1, 1, PARAM2);
+}
+
+void OPPROTO glue(op_string_jnz_sub, SUFFIX)(void)
+{
+    if ((DATA_TYPE)CC_DST != 0)
+        JUMP_TB(PARAM1, 1, PARAM2);
+}
+
+#if DATA_BITS >= 16
+void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
+{
+    if ((DATA_TYPE)ECX == 0)
+        JUMP_TB(PARAM1, 1, PARAM2);
+}
+#endif
+
 /* port I/O */
 
 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
@@ -559,6 +584,16 @@ void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
     T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff);
 }
 
+void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
+{
+    T0 = glue(cpu_x86_in, SUFFIX)(env, EDX & 0xffff);
+}
+
+void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
+{
+    glue(cpu_x86_out, SUFFIX)(env, EDX & 0xffff, T0);
+}
+
 #undef DATA_BITS
 #undef SHIFT_MASK
 #undef SIGN_MASK