summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-08-10 21:47:01 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-08-10 21:47:01 +0000
commit33417e7025afa5ea1c38c3c2b2ea53d975b5648b (patch)
tree6c4ab68c228ac2eb8ec4a40559629fce57480b51
parent4021dab0594761c939b258cad67275c492b88e4d (diff)
downloadqemu-33417e7025afa5ea1c38c3c2b2ea53d975b5648b.tar.gz
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
-rw-r--r--cpu-all.h12
-rw-r--r--cpu-arm.h4
-rw-r--r--cpu-i386.h20
-rw-r--r--exec-i386.h50
-rw-r--r--exec.c138
-rw-r--r--exec.h43
-rw-r--r--helper-i386.c33
-rw-r--r--op-i386.c100
-rw-r--r--op_string.h150
-rw-r--r--ops_template.h35
10 files changed, 351 insertions, 234 deletions
diff --git a/cpu-all.h b/cpu-all.h
index cde8451dd0..65304927ee 100644
--- 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);
diff --git a/cpu-arm.h b/cpu-arm.h
index 3b2e628e97..7f755a7541 100644
--- a/cpu-arm.h
+++ b/cpu-arm.h
@@ -20,12 +20,10 @@
#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];
diff --git a/cpu-i386.h b/cpu-i386.h
index 879ab1eb8f..a60e959150 100644
--- a/cpu-i386.h
+++ b/cpu-i386.h
@@ -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
@@ -153,12 +152,6 @@
#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;
diff --git a/exec-i386.h b/exec-i386.h
index 964abddfa2..03a547fb18 100644
--- a/exec-i386.h
+++ b/exec-i386.h
@@ -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 5ea2163258..cdc2a0be36 100644
--- 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 9489c47773..5c4e841a72 100644
--- a/exec.h
+++ b/exec.h
@@ -21,6 +21,17 @@
/* 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)
{
diff --git a/helper-i386.c b/helper-i386.c
index 0003fb46a1..01046ea091 100644
--- a/helper-i386.c
+++ b/helper-i386.c
@@ -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);
+ }
+}
diff --git a/op-i386.c b/op-i386.c
index fb062a0fcc..60ae5e55f2 100644
--- 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)
diff --git a/op_string.h b/op_string.h
index 79bc11e1a7..66b598b23a 100644
--- a/op_string.h
+++ b/op_string.h
@@ -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
diff --git a/ops_template.h b/ops_template.h
index 4595291e78..89480dddbf 100644
--- a/ops_template.h
+++ b/ops_template.h
@@ -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