mirror of
https://github.com/qemu/qemu.git
synced 2025-08-09 01:50:43 +00:00
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
This commit is contained in:
parent
4021dab059
commit
33417e7025
12
cpu-all.h
12
cpu-all.h
@ -140,6 +140,7 @@ static inline void stfl(void *ptr, float v)
|
|||||||
stl(ptr, u.i);
|
stl(ptr, u.i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(__arm__) && !defined(WORDS_BIGENDIAN)
|
#if defined(__arm__) && !defined(WORDS_BIGENDIAN)
|
||||||
|
|
||||||
/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
|
/* 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);
|
int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
|
||||||
void cpu_single_step(CPUState *env, int enabled);
|
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 */
|
/* gdb stub API */
|
||||||
extern int gdbstub_fd;
|
extern int gdbstub_fd;
|
||||||
CPUState *cpu_gdbstub_get_env(void *opaque);
|
CPUState *cpu_gdbstub_get_env(void *opaque);
|
||||||
|
@ -20,12 +20,10 @@
|
|||||||
#ifndef CPU_ARM_H
|
#ifndef CPU_ARM_H
|
||||||
#define CPU_ARM_H
|
#define CPU_ARM_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "cpu-defs.h"
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
#define EXCP_UDEF 1 /* undefined instruction */
|
#define EXCP_UDEF 1 /* undefined instruction */
|
||||||
#define EXCP_SWI 2 /* software interrupt */
|
#define EXCP_SWI 2 /* software interrupt */
|
||||||
#define EXCP_INTERRUPT 256 /* async interruption */
|
|
||||||
|
|
||||||
typedef struct CPUARMState {
|
typedef struct CPUARMState {
|
||||||
uint32_t regs[16];
|
uint32_t regs[16];
|
||||||
|
20
cpu-i386.h
20
cpu-i386.h
@ -20,8 +20,7 @@
|
|||||||
#ifndef CPU_I386_H
|
#ifndef CPU_I386_H
|
||||||
#define CPU_I386_H
|
#define CPU_I386_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "cpu-defs.h"
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
#define R_EAX 0
|
#define R_EAX 0
|
||||||
#define R_ECX 1
|
#define R_ECX 1
|
||||||
@ -153,12 +152,6 @@
|
|||||||
#define EXCP11_ALGN 17
|
#define EXCP11_ALGN 17
|
||||||
#define EXCP12_MCHK 18
|
#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 {
|
enum {
|
||||||
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
|
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
|
||||||
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
|
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 gdt; /* only base and limit are used */
|
||||||
SegmentCache idt; /* only base and limit are used */
|
SegmentCache idt; /* only base and limit are used */
|
||||||
int cpl; /* current cpl */
|
int cpl; /* current cpl */
|
||||||
|
int soft_mmu; /* TRUE if soft mmu is being used */
|
||||||
|
|
||||||
/* sysenter registers */
|
/* sysenter registers */
|
||||||
uint32_t sysenter_cs;
|
uint32_t sysenter_cs;
|
||||||
uint32_t sysenter_esp;
|
uint32_t sysenter_esp;
|
||||||
@ -275,10 +269,16 @@ typedef struct CPUX86State {
|
|||||||
int interrupt_request;
|
int interrupt_request;
|
||||||
int user_mode_only; /* user mode only simulation */
|
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];
|
uint32_t breakpoints[MAX_BREAKPOINTS];
|
||||||
int nb_breakpoints;
|
int nb_breakpoints;
|
||||||
int singlestep_enabled;
|
int singlestep_enabled;
|
||||||
|
|
||||||
/* user data */
|
/* user data */
|
||||||
void *opaque;
|
void *opaque;
|
||||||
} CPUX86State;
|
} CPUX86State;
|
||||||
|
50
exec-i386.h
50
exec-i386.h
@ -138,6 +138,7 @@ void cpu_x86_update_cr0(CPUX86State *env);
|
|||||||
void cpu_x86_update_cr3(CPUX86State *env);
|
void cpu_x86_update_cr3(CPUX86State *env);
|
||||||
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr);
|
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr);
|
||||||
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write);
|
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_lock(void);
|
||||||
void __hidden cpu_unlock(void);
|
void __hidden cpu_unlock(void);
|
||||||
void do_interrupt(int intno, int is_int, int error_code,
|
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) |
|
env->eflags = (env->eflags & ~update_mask) |
|
||||||
(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
|
||||||
|
|
||||||
|
138
exec.c
138
exec.c
@ -68,6 +68,7 @@ typedef struct PageDesc {
|
|||||||
#define L2_SIZE (1 << L2_BITS)
|
#define L2_SIZE (1 << L2_BITS)
|
||||||
|
|
||||||
static void tb_invalidate_page(unsigned long address);
|
static void tb_invalidate_page(unsigned long address);
|
||||||
|
static void io_mem_init(void);
|
||||||
|
|
||||||
unsigned long real_host_page_size;
|
unsigned long real_host_page_size;
|
||||||
unsigned long host_page_bits;
|
unsigned long host_page_bits;
|
||||||
@ -76,6 +77,12 @@ unsigned long host_page_mask;
|
|||||||
|
|
||||||
static PageDesc *l1_map[L1_SIZE];
|
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)
|
static void page_init(void)
|
||||||
{
|
{
|
||||||
/* NOTE: we can always suppose that host_page_size >=
|
/* NOTE: we can always suppose that host_page_size >=
|
||||||
@ -201,6 +208,7 @@ void cpu_exec_init(void)
|
|||||||
if (!code_gen_ptr) {
|
if (!code_gen_ptr) {
|
||||||
code_gen_ptr = code_gen_buffer;
|
code_gen_ptr = code_gen_buffer;
|
||||||
page_init();
|
page_init();
|
||||||
|
io_mem_init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,3 +752,133 @@ void page_unmap(void)
|
|||||||
tb_flush();
|
tb_flush();
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
43
exec.h
43
exec.h
@ -21,6 +21,17 @@
|
|||||||
/* allow to see translation results - the slowdown should be negligible, so we leave it */
|
/* allow to see translation results - the slowdown should be negligible, so we leave it */
|
||||||
#define DEBUG_DISAS
|
#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 */
|
/* is_jmp field values */
|
||||||
#define DISAS_NEXT 0 /* next instruction can be analyzed */
|
#define DISAS_NEXT 0 /* next instruction can be analyzed */
|
||||||
#define DISAS_JUMP 1 /* only pc was modified dynamically */
|
#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)
|
#if defined(TARGET_I386)
|
||||||
|
|
||||||
#define GEN_FLAG_CODE32_SHIFT 0
|
#define GEN_FLAG_CODE32_SHIFT 0
|
||||||
#define GEN_FLAG_ADDSEG_SHIFT 1
|
#define GEN_FLAG_ADDSEG_SHIFT 1
|
||||||
#define GEN_FLAG_SS32_SHIFT 2
|
#define GEN_FLAG_SS32_SHIFT 2
|
||||||
#define GEN_FLAG_VM_SHIFT 3
|
#define GEN_FLAG_VM_SHIFT 3
|
||||||
#define GEN_FLAG_ST_SHIFT 4
|
#define GEN_FLAG_ST_SHIFT 4
|
||||||
#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */
|
#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */
|
||||||
#define GEN_FLAG_CPL_SHIFT 9
|
#define GEN_FLAG_CPL_SHIFT 9
|
||||||
#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */
|
#define GEN_FLAG_SOFT_MMU_SHIFT 11
|
||||||
|
#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */
|
||||||
|
|
||||||
|
void optimize_flags_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -68,6 +82,8 @@ int cpu_restore_state(struct TranslationBlock *tb,
|
|||||||
void cpu_exec_init(void);
|
void cpu_exec_init(void);
|
||||||
int page_unprotect(unsigned long address);
|
int page_unprotect(unsigned long address);
|
||||||
void page_unmap(void);
|
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_MAX_SIZE 65536
|
||||||
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
|
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
|
||||||
@ -230,6 +246,17 @@ dummy_label ## n:\
|
|||||||
|
|
||||||
#endif
|
#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__
|
#ifdef __powerpc__
|
||||||
static inline int testandset (int *p)
|
static inline int testandset (int *p)
|
||||||
{
|
{
|
||||||
|
@ -781,7 +781,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip)
|
|||||||
int new_cs, new_eip;
|
int new_cs, new_eip;
|
||||||
uint32_t esp, esp_mask;
|
uint32_t esp, esp_mask;
|
||||||
uint8_t *ssp;
|
uint8_t *ssp;
|
||||||
|
|
||||||
new_cs = T0;
|
new_cs = T0;
|
||||||
new_eip = T1;
|
new_eip = T1;
|
||||||
esp = env->regs[R_ESP];
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
100
op-i386.c
100
op-i386.c
@ -376,70 +376,14 @@ void OPPROTO op_andl_A0_ffff(void)
|
|||||||
|
|
||||||
/* memory access */
|
/* memory access */
|
||||||
|
|
||||||
void OPPROTO op_ldub_T0_A0(void)
|
#define MEMSUFFIX
|
||||||
{
|
#include "ops_mem.h"
|
||||||
T0 = ldub((uint8_t *)A0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ldsb_T0_A0(void)
|
#define MEMSUFFIX _user
|
||||||
{
|
#include "ops_mem.h"
|
||||||
T0 = ldsb((int8_t *)A0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_lduw_T0_A0(void)
|
#define MEMSUFFIX _kernel
|
||||||
{
|
#include "ops_mem.h"
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* used for bit operations */
|
/* used for bit operations */
|
||||||
|
|
||||||
@ -635,6 +579,38 @@ void OPPROTO op_movswl_DX_AX(void)
|
|||||||
EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
|
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 */
|
/* push/pop */
|
||||||
|
|
||||||
void op_pushl_T0(void)
|
void op_pushl_T0(void)
|
||||||
|
150
op_string.h
150
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)
|
void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void)
|
||||||
{
|
{
|
||||||
int v1, v2, inc;
|
int v1, v2, inc;
|
||||||
@ -133,18 +43,6 @@ void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void)
|
|||||||
FORCE_RET();
|
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)
|
void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void)
|
||||||
{
|
{
|
||||||
int v1, v2, inc;
|
int v1, v2, inc;
|
||||||
@ -187,54 +85,6 @@ void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void)
|
|||||||
FORCE_RET();
|
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 STRING_SUFFIX
|
||||||
#undef SI_ADDR
|
#undef SI_ADDR
|
||||||
#undef DI_ADDR
|
#undef DI_ADDR
|
||||||
|
@ -547,6 +547,31 @@ void OPPROTO op_update_bt_cc(void)
|
|||||||
#define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff)
|
#define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff)
|
||||||
#include "op_string.h"
|
#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 */
|
/* port I/O */
|
||||||
|
|
||||||
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
|
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);
|
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 DATA_BITS
|
||||||
#undef SHIFT_MASK
|
#undef SHIFT_MASK
|
||||||
#undef SIGN_MASK
|
#undef SIGN_MASK
|
||||||
|
Loading…
Reference in New Issue
Block a user