mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 03:13:44 +08:00
full softmmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@410 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
3a51dee658
commit
61382a500a
133
cpu-all.h
133
cpu-all.h
@ -20,18 +20,19 @@
|
|||||||
#ifndef CPU_ALL_H
|
#ifndef CPU_ALL_H
|
||||||
#define CPU_ALL_H
|
#define CPU_ALL_H
|
||||||
|
|
||||||
/* all CPU memory access use these macros */
|
/* CPU memory access without any memory or io remapping */
|
||||||
static inline int ldub(void *ptr)
|
|
||||||
|
static inline int ldub_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(uint8_t *)ptr;
|
return *(uint8_t *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ldsb(void *ptr)
|
static inline int ldsb_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(int8_t *)ptr;
|
return *(int8_t *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stb(void *ptr, int v)
|
static inline void stb_raw(void *ptr, int v)
|
||||||
{
|
{
|
||||||
*(uint8_t *)ptr = v;
|
*(uint8_t *)ptr = v;
|
||||||
}
|
}
|
||||||
@ -42,7 +43,7 @@ static inline void stb(void *ptr, int v)
|
|||||||
#if defined(WORDS_BIGENDIAN) || defined(__arm__)
|
#if defined(WORDS_BIGENDIAN) || defined(__arm__)
|
||||||
|
|
||||||
/* conservative code for little endian unaligned accesses */
|
/* conservative code for little endian unaligned accesses */
|
||||||
static inline int lduw(void *ptr)
|
static inline int lduw_raw(void *ptr)
|
||||||
{
|
{
|
||||||
#ifdef __powerpc__
|
#ifdef __powerpc__
|
||||||
int val;
|
int val;
|
||||||
@ -54,7 +55,7 @@ static inline int lduw(void *ptr)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ldsw(void *ptr)
|
static inline int ldsw_raw(void *ptr)
|
||||||
{
|
{
|
||||||
#ifdef __powerpc__
|
#ifdef __powerpc__
|
||||||
int val;
|
int val;
|
||||||
@ -66,7 +67,7 @@ static inline int ldsw(void *ptr)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ldl(void *ptr)
|
static inline int ldl_raw(void *ptr)
|
||||||
{
|
{
|
||||||
#ifdef __powerpc__
|
#ifdef __powerpc__
|
||||||
int val;
|
int val;
|
||||||
@ -78,16 +79,16 @@ static inline int ldl(void *ptr)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t ldq(void *ptr)
|
static inline uint64_t ldq_raw(void *ptr)
|
||||||
{
|
{
|
||||||
uint8_t *p = ptr;
|
uint8_t *p = ptr;
|
||||||
uint32_t v1, v2;
|
uint32_t v1, v2;
|
||||||
v1 = ldl(p);
|
v1 = ldl_raw(p);
|
||||||
v2 = ldl(p + 4);
|
v2 = ldl_raw(p + 4);
|
||||||
return v1 | ((uint64_t)v2 << 32);
|
return v1 | ((uint64_t)v2 << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stw(void *ptr, int v)
|
static inline void stw_raw(void *ptr, int v)
|
||||||
{
|
{
|
||||||
#ifdef __powerpc__
|
#ifdef __powerpc__
|
||||||
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
|
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
|
||||||
@ -98,7 +99,7 @@ static inline void stw(void *ptr, int v)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stl(void *ptr, int v)
|
static inline void stl_raw(void *ptr, int v)
|
||||||
{
|
{
|
||||||
#ifdef __powerpc__
|
#ifdef __powerpc__
|
||||||
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
|
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
|
||||||
@ -111,104 +112,104 @@ static inline void stl(void *ptr, int v)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stq(void *ptr, uint64_t v)
|
static inline void stq_raw(void *ptr, uint64_t v)
|
||||||
{
|
{
|
||||||
uint8_t *p = ptr;
|
uint8_t *p = ptr;
|
||||||
stl(p, (uint32_t)v);
|
stl_raw(p, (uint32_t)v);
|
||||||
stl(p + 4, v >> 32);
|
stl_raw(p + 4, v >> 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* float access */
|
/* float access */
|
||||||
|
|
||||||
static inline float ldfl(void *ptr)
|
static inline float ldfl_raw(void *ptr)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
float f;
|
float f;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
} u;
|
} u;
|
||||||
u.i = ldl(ptr);
|
u.i = ldl_raw(ptr);
|
||||||
return u.f;
|
return u.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stfl(void *ptr, float v)
|
static inline void stfl_raw(void *ptr, float v)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
float f;
|
float f;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
} u;
|
} u;
|
||||||
u.f = v;
|
u.f = v;
|
||||||
stl(ptr, u.i);
|
stl_raw(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 ! */
|
||||||
static inline double ldfq(void *ptr)
|
static inline double ldfq_raw(void *ptr)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
uint32_t tab[2];
|
uint32_t tab[2];
|
||||||
} u;
|
} u;
|
||||||
u.tab[1] = ldl(ptr);
|
u.tab[1] = ldl_raw(ptr);
|
||||||
u.tab[0] = ldl(ptr + 4);
|
u.tab[0] = ldl_raw(ptr + 4);
|
||||||
return u.d;
|
return u.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stfq(void *ptr, double v)
|
static inline void stfq_raw(void *ptr, double v)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
uint32_t tab[2];
|
uint32_t tab[2];
|
||||||
} u;
|
} u;
|
||||||
u.d = v;
|
u.d = v;
|
||||||
stl(ptr, u.tab[1]);
|
stl_raw(ptr, u.tab[1]);
|
||||||
stl(ptr + 4, u.tab[0]);
|
stl_raw(ptr + 4, u.tab[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static inline double ldfq(void *ptr)
|
static inline double ldfq_raw(void *ptr)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
} u;
|
} u;
|
||||||
u.i = ldq(ptr);
|
u.i = ldq_raw(ptr);
|
||||||
return u.d;
|
return u.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stfq(void *ptr, double v)
|
static inline void stfq_raw(void *ptr, double v)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
} u;
|
} u;
|
||||||
u.d = v;
|
u.d = v;
|
||||||
stq(ptr, u.i);
|
stq_raw(ptr, u.i);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(TARGET_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN)
|
#elif defined(TARGET_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN)
|
||||||
|
|
||||||
static inline int lduw(void *ptr)
|
static inline int lduw_raw(void *ptr)
|
||||||
{
|
{
|
||||||
uint8_t *b = (uint8_t *) ptr;
|
uint8_t *b = (uint8_t *) ptr;
|
||||||
return (b[0]<<8|b[1]);
|
return (b[0]<<8|b[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ldsw(void *ptr)
|
static inline int ldsw_raw(void *ptr)
|
||||||
{
|
{
|
||||||
int8_t *b = (int8_t *) ptr;
|
int8_t *b = (int8_t *) ptr;
|
||||||
return (b[0]<<8|b[1]);
|
return (b[0]<<8|b[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ldl(void *ptr)
|
static inline int ldl_raw(void *ptr)
|
||||||
{
|
{
|
||||||
uint8_t *b = (uint8_t *) ptr;
|
uint8_t *b = (uint8_t *) ptr;
|
||||||
return (b[0]<<24|b[1]<<16|b[2]<<8|b[3]);
|
return (b[0]<<24|b[1]<<16|b[2]<<8|b[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t ldq(void *ptr)
|
static inline uint64_t ldq_raw(void *ptr)
|
||||||
{
|
{
|
||||||
uint32_t a,b;
|
uint32_t a,b;
|
||||||
a = ldl (ptr);
|
a = ldl (ptr);
|
||||||
@ -216,14 +217,14 @@ static inline uint64_t ldq(void *ptr)
|
|||||||
return (((uint64_t)a<<32)|b);
|
return (((uint64_t)a<<32)|b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stw(void *ptr, int v)
|
static inline void stw_raw(void *ptr, int v)
|
||||||
{
|
{
|
||||||
uint8_t *d = (uint8_t *) ptr;
|
uint8_t *d = (uint8_t *) ptr;
|
||||||
d[0] = v >> 8;
|
d[0] = v >> 8;
|
||||||
d[1] = v;
|
d[1] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stl(void *ptr, int v)
|
static inline void stl_raw(void *ptr, int v)
|
||||||
{
|
{
|
||||||
uint8_t *d = (uint8_t *) ptr;
|
uint8_t *d = (uint8_t *) ptr;
|
||||||
d[0] = v >> 24;
|
d[0] = v >> 24;
|
||||||
@ -232,7 +233,7 @@ static inline void stl(void *ptr, int v)
|
|||||||
d[3] = v;
|
d[3] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stq(void *ptr, uint64_t v)
|
static inline void stq_raw(void *ptr, uint64_t v)
|
||||||
{
|
{
|
||||||
stl (ptr, v);
|
stl (ptr, v);
|
||||||
stl (ptr+4, v >> 32);
|
stl (ptr+4, v >> 32);
|
||||||
@ -240,64 +241,102 @@ static inline void stq(void *ptr, uint64_t v)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline int lduw(void *ptr)
|
static inline int lduw_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(uint16_t *)ptr;
|
return *(uint16_t *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ldsw(void *ptr)
|
static inline int ldsw_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(int16_t *)ptr;
|
return *(int16_t *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ldl(void *ptr)
|
static inline int ldl_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(uint32_t *)ptr;
|
return *(uint32_t *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t ldq(void *ptr)
|
static inline uint64_t ldq_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(uint64_t *)ptr;
|
return *(uint64_t *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stw(void *ptr, int v)
|
static inline void stw_raw(void *ptr, int v)
|
||||||
{
|
{
|
||||||
*(uint16_t *)ptr = v;
|
*(uint16_t *)ptr = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stl(void *ptr, int v)
|
static inline void stl_raw(void *ptr, int v)
|
||||||
{
|
{
|
||||||
*(uint32_t *)ptr = v;
|
*(uint32_t *)ptr = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stq(void *ptr, uint64_t v)
|
static inline void stq_raw(void *ptr, uint64_t v)
|
||||||
{
|
{
|
||||||
*(uint64_t *)ptr = v;
|
*(uint64_t *)ptr = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* float access */
|
/* float access */
|
||||||
|
|
||||||
static inline float ldfl(void *ptr)
|
static inline float ldfl_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(float *)ptr;
|
return *(float *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double ldfq(void *ptr)
|
static inline double ldfq_raw(void *ptr)
|
||||||
{
|
{
|
||||||
return *(double *)ptr;
|
return *(double *)ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stfl(void *ptr, float v)
|
static inline void stfl_raw(void *ptr, float v)
|
||||||
{
|
{
|
||||||
*(float *)ptr = v;
|
*(float *)ptr = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stfq(void *ptr, double v)
|
static inline void stfq_raw(void *ptr, double v)
|
||||||
{
|
{
|
||||||
*(double *)ptr = v;
|
*(double *)ptr = v;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* MMU memory access macros */
|
||||||
|
|
||||||
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
|
/* if user mode, no other memory access functions */
|
||||||
|
#define ldub(p) ldub_raw(p)
|
||||||
|
#define ldsb(p) ldsb_raw(p)
|
||||||
|
#define lduw(p) lduw_raw(p)
|
||||||
|
#define ldsw(p) ldsw_raw(p)
|
||||||
|
#define ldl(p) ldl_raw(p)
|
||||||
|
#define ldq(p) ldq_raw(p)
|
||||||
|
#define ldfl(p) ldfl_raw(p)
|
||||||
|
#define ldfq(p) ldfq_raw(p)
|
||||||
|
#define stb(p, v) stb_raw(p, v)
|
||||||
|
#define stw(p, v) stw_raw(p, v)
|
||||||
|
#define stl(p, v) stl_raw(p, v)
|
||||||
|
#define stq(p, v) stq_raw(p, v)
|
||||||
|
#define stfl(p, v) stfl_raw(p, v)
|
||||||
|
#define stfq(p, v) stfq_raw(p, v)
|
||||||
|
|
||||||
|
#define ldub_code(p) ldub_raw(p)
|
||||||
|
#define ldsb_code(p) ldsb_raw(p)
|
||||||
|
#define lduw_code(p) lduw_raw(p)
|
||||||
|
#define ldsw_code(p) ldsw_raw(p)
|
||||||
|
#define ldl_code(p) ldl_raw(p)
|
||||||
|
|
||||||
|
#define ldub_kernel(p) ldub_raw(p)
|
||||||
|
#define ldsb_kernel(p) ldsb_raw(p)
|
||||||
|
#define lduw_kernel(p) lduw_raw(p)
|
||||||
|
#define ldsw_kernel(p) ldsw_raw(p)
|
||||||
|
#define ldl_kernel(p) ldl_raw(p)
|
||||||
|
#define stb_kernel(p, v) stb_raw(p, v)
|
||||||
|
#define stw_kernel(p, v) stw_raw(p, v)
|
||||||
|
#define stl_kernel(p, v) stl_raw(p, v)
|
||||||
|
#define stq_kernel(p, v) stq_raw(p, v)
|
||||||
|
|
||||||
|
#endif /* defined(CONFIG_USER_ONLY) */
|
||||||
|
|
||||||
/* page related stuff */
|
/* page related stuff */
|
||||||
|
|
||||||
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
|
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
|
||||||
|
105
exec.c
105
exec.c
@ -444,16 +444,20 @@ static inline void tb_alloc_page(TranslationBlock *tb, unsigned int page_index)
|
|||||||
prot = 0;
|
prot = 0;
|
||||||
for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)
|
for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)
|
||||||
prot |= page_get_flags(addr);
|
prot |= page_get_flags(addr);
|
||||||
|
#if !defined(CONFIG_SOFTMMU)
|
||||||
mprotect((void *)host_start, host_page_size,
|
mprotect((void *)host_start, host_page_size,
|
||||||
(prot & PAGE_BITS) & ~PAGE_WRITE);
|
(prot & PAGE_BITS) & ~PAGE_WRITE);
|
||||||
|
#endif
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
/* suppress soft TLB */
|
||||||
|
/* XXX: must flush on all processor with same address space */
|
||||||
|
tlb_flush_page_write(cpu_single_env, host_start);
|
||||||
|
#endif
|
||||||
#ifdef DEBUG_TB_INVALIDATE
|
#ifdef DEBUG_TB_INVALIDATE
|
||||||
printf("protecting code page: 0x%08lx\n",
|
printf("protecting code page: 0x%08lx\n",
|
||||||
host_start);
|
host_start);
|
||||||
#endif
|
#endif
|
||||||
p->flags &= ~PAGE_WRITE;
|
p->flags &= ~PAGE_WRITE;
|
||||||
#ifdef DEBUG_TB_CHECK
|
|
||||||
tb_page_check();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,6 +487,9 @@ void tb_link(TranslationBlock *tb)
|
|||||||
if (page_index2 != page_index1) {
|
if (page_index2 != page_index1) {
|
||||||
tb_alloc_page(tb, page_index2);
|
tb_alloc_page(tb, page_index2);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_TB_CHECK
|
||||||
|
tb_page_check();
|
||||||
|
#endif
|
||||||
tb->jmp_first = (TranslationBlock *)((long)tb | 2);
|
tb->jmp_first = (TranslationBlock *)((long)tb | 2);
|
||||||
tb->jmp_next[0] = NULL;
|
tb->jmp_next[0] = NULL;
|
||||||
tb->jmp_next[1] = NULL;
|
tb->jmp_next[1] = NULL;
|
||||||
@ -517,20 +524,23 @@ int page_unprotect(unsigned long address)
|
|||||||
/* if the page was really writable, then we change its
|
/* if the page was really writable, then we change its
|
||||||
protection back to writable */
|
protection back to writable */
|
||||||
if (prot & PAGE_WRITE_ORG) {
|
if (prot & PAGE_WRITE_ORG) {
|
||||||
mprotect((void *)host_start, host_page_size,
|
|
||||||
(prot & PAGE_BITS) | PAGE_WRITE);
|
|
||||||
pindex = (address - host_start) >> TARGET_PAGE_BITS;
|
pindex = (address - host_start) >> TARGET_PAGE_BITS;
|
||||||
p1[pindex].flags |= PAGE_WRITE;
|
if (!(p1[pindex].flags & PAGE_WRITE)) {
|
||||||
/* and since the content will be modified, we must invalidate
|
#if !defined(CONFIG_SOFTMMU)
|
||||||
the corresponding translated code. */
|
mprotect((void *)host_start, host_page_size,
|
||||||
tb_invalidate_page(address);
|
(prot & PAGE_BITS) | PAGE_WRITE);
|
||||||
#ifdef DEBUG_TB_CHECK
|
|
||||||
tb_invalidate_check(address);
|
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
p1[pindex].flags |= PAGE_WRITE;
|
||||||
} else {
|
/* and since the content will be modified, we must invalidate
|
||||||
return 0;
|
the corresponding translated code. */
|
||||||
|
tb_invalidate_page(address);
|
||||||
|
#ifdef DEBUG_TB_CHECK
|
||||||
|
tb_invalidate_check(address);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call this function when system calls directly modify a memory area */
|
/* call this function when system calls directly modify a memory area */
|
||||||
@ -734,13 +744,17 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
|
|||||||
/* unmap all maped pages and flush all associated code */
|
/* unmap all maped pages and flush all associated code */
|
||||||
void page_unmap(void)
|
void page_unmap(void)
|
||||||
{
|
{
|
||||||
PageDesc *p, *pmap;
|
PageDesc *pmap;
|
||||||
unsigned long addr;
|
int i;
|
||||||
int i, j, ret, j1;
|
|
||||||
|
|
||||||
for(i = 0; i < L1_SIZE; i++) {
|
for(i = 0; i < L1_SIZE; i++) {
|
||||||
pmap = l1_map[i];
|
pmap = l1_map[i];
|
||||||
if (pmap) {
|
if (pmap) {
|
||||||
|
#if !defined(CONFIG_SOFTMMU)
|
||||||
|
PageDesc *p;
|
||||||
|
unsigned long addr;
|
||||||
|
int j, ret, j1;
|
||||||
|
|
||||||
p = pmap;
|
p = pmap;
|
||||||
for(j = 0;j < L2_SIZE;) {
|
for(j = 0;j < L2_SIZE;) {
|
||||||
if (p->flags & PAGE_VALID) {
|
if (p->flags & PAGE_VALID) {
|
||||||
@ -763,6 +777,7 @@ void page_unmap(void)
|
|||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
free(pmap);
|
free(pmap);
|
||||||
l1_map[i] = NULL;
|
l1_map[i] = NULL;
|
||||||
}
|
}
|
||||||
@ -773,7 +788,7 @@ void page_unmap(void)
|
|||||||
|
|
||||||
void tlb_flush(CPUState *env)
|
void tlb_flush(CPUState *env)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_I386)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < CPU_TLB_SIZE; i++) {
|
for(i = 0; i < CPU_TLB_SIZE; i++) {
|
||||||
env->tlb_read[0][i].address = -1;
|
env->tlb_read[0][i].address = -1;
|
||||||
@ -784,16 +799,38 @@ void tlb_flush(CPUState *env)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr)
|
||||||
|
{
|
||||||
|
if (addr == (tlb_entry->address &
|
||||||
|
(TARGET_PAGE_MASK | TLB_INVALID_MASK)))
|
||||||
|
tlb_entry->address = -1;
|
||||||
|
}
|
||||||
|
|
||||||
void tlb_flush_page(CPUState *env, uint32_t addr)
|
void tlb_flush_page(CPUState *env, uint32_t addr)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_I386)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
addr &= TARGET_PAGE_MASK;
|
||||||
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
env->tlb_read[0][i].address = -1;
|
tlb_flush_entry(&env->tlb_read[0][i], addr);
|
||||||
env->tlb_write[0][i].address = -1;
|
tlb_flush_entry(&env->tlb_write[0][i], addr);
|
||||||
env->tlb_read[1][i].address = -1;
|
tlb_flush_entry(&env->tlb_read[1][i], addr);
|
||||||
env->tlb_write[1][i].address = -1;
|
tlb_flush_entry(&env->tlb_write[1][i], addr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make all write to page 'addr' trigger a TLB exception to detect
|
||||||
|
self modifying code */
|
||||||
|
void tlb_flush_page_write(CPUState *env, uint32_t addr)
|
||||||
|
{
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
int i;
|
||||||
|
|
||||||
|
addr &= TARGET_PAGE_MASK;
|
||||||
|
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
|
tlb_flush_entry(&env->tlb_write[0][i], addr);
|
||||||
|
tlb_flush_entry(&env->tlb_write[1][i], addr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,3 +937,25 @@ int cpu_register_io_memory(int io_index,
|
|||||||
}
|
}
|
||||||
return io_index << IO_MEM_SHIFT;
|
return io_index << IO_MEM_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
|
#define MMUSUFFIX _cmmu
|
||||||
|
#define GETPC() NULL
|
||||||
|
#define env cpu_single_env
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
#undef env
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -354,7 +354,7 @@ static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d,
|
|||||||
|
|
||||||
w = width;
|
w = width;
|
||||||
do {
|
do {
|
||||||
v = lduw((void *)s);
|
v = lduw_raw((void *)s);
|
||||||
r = (v >> 7) & 0xf8;
|
r = (v >> 7) & 0xf8;
|
||||||
g = (v >> 2) & 0xf8;
|
g = (v >> 2) & 0xf8;
|
||||||
b = (v << 3) & 0xf8;
|
b = (v << 3) & 0xf8;
|
||||||
@ -379,7 +379,7 @@ static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d,
|
|||||||
|
|
||||||
w = width;
|
w = width;
|
||||||
do {
|
do {
|
||||||
v = lduw((void *)s);
|
v = lduw_raw((void *)s);
|
||||||
r = (v >> 8) & 0xf8;
|
r = (v >> 8) & 0xf8;
|
||||||
g = (v >> 3) & 0xfc;
|
g = (v >> 3) & 0xfc;
|
||||||
b = (v << 3) & 0xf8;
|
b = (v << 3) & 0xf8;
|
||||||
|
@ -19,26 +19,48 @@
|
|||||||
*/
|
*/
|
||||||
#if DATA_SIZE == 8
|
#if DATA_SIZE == 8
|
||||||
#define SUFFIX q
|
#define SUFFIX q
|
||||||
|
#define USUFFIX q
|
||||||
#define DATA_TYPE uint64_t
|
#define DATA_TYPE uint64_t
|
||||||
#elif DATA_SIZE == 4
|
#elif DATA_SIZE == 4
|
||||||
#define SUFFIX l
|
#define SUFFIX l
|
||||||
|
#define USUFFIX l
|
||||||
#define DATA_TYPE uint32_t
|
#define DATA_TYPE uint32_t
|
||||||
#elif DATA_SIZE == 2
|
#elif DATA_SIZE == 2
|
||||||
#define SUFFIX w
|
#define SUFFIX w
|
||||||
|
#define USUFFIX uw
|
||||||
#define DATA_TYPE uint16_t
|
#define DATA_TYPE uint16_t
|
||||||
#define DATA_STYPE int16_t
|
#define DATA_STYPE int16_t
|
||||||
#elif DATA_SIZE == 1
|
#elif DATA_SIZE == 1
|
||||||
#define SUFFIX b
|
#define SUFFIX b
|
||||||
|
#define USUFFIX ub
|
||||||
#define DATA_TYPE uint8_t
|
#define DATA_TYPE uint8_t
|
||||||
#define DATA_STYPE int8_t
|
#define DATA_STYPE int8_t
|
||||||
#else
|
#else
|
||||||
#error unsupported data size
|
#error unsupported data size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MEMUSER == 0
|
#if ACCESS_TYPE == 0
|
||||||
#define MEMSUFFIX _kernel
|
|
||||||
|
#define CPU_MEM_INDEX 0
|
||||||
|
#define MMUSUFFIX _mmu
|
||||||
|
|
||||||
|
#elif ACCESS_TYPE == 1
|
||||||
|
|
||||||
|
#define CPU_MEM_INDEX 1
|
||||||
|
#define MMUSUFFIX _mmu
|
||||||
|
|
||||||
|
#elif ACCESS_TYPE == 2
|
||||||
|
|
||||||
|
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
|
||||||
|
#define MMUSUFFIX _mmu
|
||||||
|
|
||||||
|
#elif ACCESS_TYPE == 3
|
||||||
|
|
||||||
|
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
|
||||||
|
#define MMUSUFFIX _cmmu
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define MEMSUFFIX _user
|
#error invalid ACCESS_TYPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DATA_SIZE == 8
|
#if DATA_SIZE == 8
|
||||||
@ -48,24 +70,26 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if MEMUSER == 0
|
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(unsigned long addr,
|
||||||
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), _mmu)(unsigned long addr);
|
int is_user);
|
||||||
void REGPARM(2) glue(glue(__st, SUFFIX), _mmu)(unsigned long addr, DATA_TYPE v);
|
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(unsigned long addr, DATA_TYPE v, int is_user);
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int glue(glue(ldu, SUFFIX), MEMSUFFIX)(void *ptr)
|
static inline int glue(glue(ld, USUFFIX), MEMSUFFIX)(void *ptr)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
RES_TYPE res;
|
RES_TYPE res;
|
||||||
unsigned long addr, physaddr;
|
unsigned long addr, physaddr;
|
||||||
|
int is_user;
|
||||||
|
|
||||||
addr = (unsigned long)ptr;
|
addr = (unsigned long)ptr;
|
||||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
if (__builtin_expect(env->tlb_read[MEMUSER][index].address !=
|
is_user = CPU_MEM_INDEX;
|
||||||
|
if (__builtin_expect(env->tlb_read[is_user][index].address !=
|
||||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
||||||
res = glue(glue(__ld, SUFFIX), _mmu)(addr);
|
res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
|
||||||
} else {
|
} else {
|
||||||
physaddr = addr + env->tlb_read[MEMUSER][index].addend;
|
physaddr = addr + env->tlb_read[is_user][index].addend;
|
||||||
res = glue(glue(ldu, SUFFIX), _raw)((uint8_t *)physaddr);
|
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -75,13 +99,16 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(void *ptr)
|
|||||||
{
|
{
|
||||||
int res, index;
|
int res, index;
|
||||||
unsigned long addr, physaddr;
|
unsigned long addr, physaddr;
|
||||||
|
int is_user;
|
||||||
|
|
||||||
addr = (unsigned long)ptr;
|
addr = (unsigned long)ptr;
|
||||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
if (__builtin_expect(env->tlb_read[MEMUSER][index].address !=
|
is_user = CPU_MEM_INDEX;
|
||||||
|
if (__builtin_expect(env->tlb_read[is_user][index].address !=
|
||||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
||||||
res = (DATA_STYPE)glue(glue(__ld, SUFFIX), _mmu)(addr);
|
res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
|
||||||
} else {
|
} else {
|
||||||
physaddr = addr + env->tlb_read[MEMUSER][index].addend;
|
physaddr = addr + env->tlb_read[is_user][index].addend;
|
||||||
res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
|
res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@ -92,13 +119,16 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(void *ptr, RES_TYPE v)
|
|||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
unsigned long addr, physaddr;
|
unsigned long addr, physaddr;
|
||||||
|
int is_user;
|
||||||
|
|
||||||
addr = (unsigned long)ptr;
|
addr = (unsigned long)ptr;
|
||||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
if (__builtin_expect(env->tlb_write[MEMUSER][index].address !=
|
is_user = CPU_MEM_INDEX;
|
||||||
|
if (__builtin_expect(env->tlb_write[is_user][index].address !=
|
||||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
||||||
glue(glue(__st, SUFFIX), _mmu)(addr, v);
|
glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
|
||||||
} else {
|
} else {
|
||||||
physaddr = addr + env->tlb_write[MEMUSER][index].addend;
|
physaddr = addr + env->tlb_write[is_user][index].addend;
|
||||||
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
|
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,5 +137,7 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(void *ptr, RES_TYPE v)
|
|||||||
#undef DATA_TYPE
|
#undef DATA_TYPE
|
||||||
#undef DATA_STYPE
|
#undef DATA_STYPE
|
||||||
#undef SUFFIX
|
#undef SUFFIX
|
||||||
|
#undef USUFFIX
|
||||||
#undef DATA_SIZE
|
#undef DATA_SIZE
|
||||||
#undef MEMSUFFIX
|
#undef CPU_MEM_INDEX
|
||||||
|
#undef MMUSUFFIX
|
||||||
|
@ -21,23 +21,31 @@
|
|||||||
|
|
||||||
#if DATA_SIZE == 8
|
#if DATA_SIZE == 8
|
||||||
#define SUFFIX q
|
#define SUFFIX q
|
||||||
|
#define USUFFIX q
|
||||||
#define DATA_TYPE uint64_t
|
#define DATA_TYPE uint64_t
|
||||||
#elif DATA_SIZE == 4
|
#elif DATA_SIZE == 4
|
||||||
#define SUFFIX l
|
#define SUFFIX l
|
||||||
|
#define USUFFIX l
|
||||||
#define DATA_TYPE uint32_t
|
#define DATA_TYPE uint32_t
|
||||||
#elif DATA_SIZE == 2
|
#elif DATA_SIZE == 2
|
||||||
#define SUFFIX w
|
#define SUFFIX w
|
||||||
|
#define USUFFIX uw
|
||||||
#define DATA_TYPE uint16_t
|
#define DATA_TYPE uint16_t
|
||||||
#elif DATA_SIZE == 1
|
#elif DATA_SIZE == 1
|
||||||
#define SUFFIX b
|
#define SUFFIX b
|
||||||
|
#define USUFFIX ub
|
||||||
#define DATA_TYPE uint8_t
|
#define DATA_TYPE uint8_t
|
||||||
#else
|
#else
|
||||||
#error unsupported data size
|
#error unsupported data size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr);
|
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(unsigned long addr,
|
||||||
static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val,
|
int is_user,
|
||||||
void *retaddr);
|
void *retaddr);
|
||||||
|
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr,
|
||||||
|
DATA_TYPE val,
|
||||||
|
int is_user,
|
||||||
|
void *retaddr);
|
||||||
|
|
||||||
static inline DATA_TYPE glue(io_read, SUFFIX)(unsigned long physaddr,
|
static inline DATA_TYPE glue(io_read, SUFFIX)(unsigned long physaddr,
|
||||||
unsigned long tlb_addr)
|
unsigned long tlb_addr)
|
||||||
@ -81,16 +89,16 @@ static inline void glue(io_write, SUFFIX)(unsigned long physaddr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* handle all cases except unaligned access which span two pages */
|
/* handle all cases except unaligned access which span two pages */
|
||||||
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), _mmu)(unsigned long addr)
|
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(unsigned long addr,
|
||||||
|
int is_user)
|
||||||
{
|
{
|
||||||
DATA_TYPE res;
|
DATA_TYPE res;
|
||||||
int is_user, index;
|
int index;
|
||||||
unsigned long physaddr, tlb_addr;
|
unsigned long physaddr, tlb_addr;
|
||||||
void *retaddr;
|
void *retaddr;
|
||||||
|
|
||||||
/* test if there is match for unaligned or IO access */
|
/* test if there is match for unaligned or IO access */
|
||||||
/* XXX: could done more in memory macro in a non portable way */
|
/* XXX: could done more in memory macro in a non portable way */
|
||||||
is_user = ((env->hflags & HF_CPL_MASK) == 3);
|
|
||||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
redo:
|
redo:
|
||||||
tlb_addr = env->tlb_read[is_user][index].address;
|
tlb_addr = env->tlb_read[is_user][index].address;
|
||||||
@ -104,29 +112,31 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), _mmu)(unsigned long addr)
|
|||||||
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
||||||
/* slow unaligned access (it spans two pages or IO) */
|
/* slow unaligned access (it spans two pages or IO) */
|
||||||
do_unaligned_access:
|
do_unaligned_access:
|
||||||
retaddr = __builtin_return_address(0);
|
retaddr = GETPC();
|
||||||
res = glue(slow_ld, SUFFIX)(addr, retaddr);
|
res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
|
||||||
|
is_user, retaddr);
|
||||||
} else {
|
} else {
|
||||||
/* unaligned access in the same page */
|
/* unaligned access in the same page */
|
||||||
res = glue(glue(ldu, SUFFIX), _raw)((uint8_t *)physaddr);
|
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* the page is not in the TLB : fill it */
|
/* the page is not in the TLB : fill it */
|
||||||
retaddr = __builtin_return_address(0);
|
retaddr = GETPC();
|
||||||
tlb_fill(addr, 0, retaddr);
|
tlb_fill(addr, 0, is_user, retaddr);
|
||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle all unaligned cases */
|
/* handle all unaligned cases */
|
||||||
static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr)
|
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(unsigned long addr,
|
||||||
|
int is_user,
|
||||||
|
void *retaddr)
|
||||||
{
|
{
|
||||||
DATA_TYPE res, res1, res2;
|
DATA_TYPE res, res1, res2;
|
||||||
int is_user, index, shift;
|
int index, shift;
|
||||||
unsigned long physaddr, tlb_addr, addr1, addr2;
|
unsigned long physaddr, tlb_addr, addr1, addr2;
|
||||||
|
|
||||||
is_user = ((env->hflags & HF_CPL_MASK) == 3);
|
|
||||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
redo:
|
redo:
|
||||||
tlb_addr = env->tlb_read[is_user][index].address;
|
tlb_addr = env->tlb_read[is_user][index].address;
|
||||||
@ -142,8 +152,10 @@ static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr)
|
|||||||
/* slow unaligned access (it spans two pages) */
|
/* slow unaligned access (it spans two pages) */
|
||||||
addr1 = addr & ~(DATA_SIZE - 1);
|
addr1 = addr & ~(DATA_SIZE - 1);
|
||||||
addr2 = addr1 + DATA_SIZE;
|
addr2 = addr1 + DATA_SIZE;
|
||||||
res1 = glue(slow_ld, SUFFIX)(addr1, retaddr);
|
res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
|
||||||
res2 = glue(slow_ld, SUFFIX)(addr2, retaddr);
|
is_user, retaddr);
|
||||||
|
res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
|
||||||
|
is_user, retaddr);
|
||||||
shift = (addr & (DATA_SIZE - 1)) * 8;
|
shift = (addr & (DATA_SIZE - 1)) * 8;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
#ifdef TARGET_WORDS_BIGENDIAN
|
||||||
res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
|
res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
|
||||||
@ -152,24 +164,25 @@ static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr)
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* unaligned/aligned access in the same page */
|
/* unaligned/aligned access in the same page */
|
||||||
res = glue(glue(ldu, SUFFIX), _raw)((uint8_t *)physaddr);
|
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* the page is not in the TLB : fill it */
|
/* the page is not in the TLB : fill it */
|
||||||
tlb_fill(addr, 0, retaddr);
|
tlb_fill(addr, 0, is_user, retaddr);
|
||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void REGPARM(2) glue(glue(__st, SUFFIX), _mmu)(unsigned long addr, DATA_TYPE val)
|
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(unsigned long addr,
|
||||||
|
DATA_TYPE val,
|
||||||
|
int is_user)
|
||||||
{
|
{
|
||||||
unsigned long physaddr, tlb_addr;
|
unsigned long physaddr, tlb_addr;
|
||||||
void *retaddr;
|
void *retaddr;
|
||||||
int is_user, index;
|
int index;
|
||||||
|
|
||||||
is_user = ((env->hflags & HF_CPL_MASK) == 3);
|
|
||||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
redo:
|
redo:
|
||||||
tlb_addr = env->tlb_write[is_user][index].address;
|
tlb_addr = env->tlb_write[is_user][index].address;
|
||||||
@ -182,28 +195,30 @@ void REGPARM(2) glue(glue(__st, SUFFIX), _mmu)(unsigned long addr, DATA_TYPE val
|
|||||||
glue(io_write, SUFFIX)(physaddr, val, tlb_addr);
|
glue(io_write, SUFFIX)(physaddr, val, tlb_addr);
|
||||||
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
} else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
||||||
do_unaligned_access:
|
do_unaligned_access:
|
||||||
retaddr = __builtin_return_address(0);
|
retaddr = GETPC();
|
||||||
glue(slow_st, SUFFIX)(addr, val, retaddr);
|
glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
|
||||||
|
is_user, retaddr);
|
||||||
} else {
|
} else {
|
||||||
/* aligned/unaligned access in the same page */
|
/* aligned/unaligned access in the same page */
|
||||||
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, val);
|
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, val);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* the page is not in the TLB : fill it */
|
/* the page is not in the TLB : fill it */
|
||||||
retaddr = __builtin_return_address(0);
|
retaddr = GETPC();
|
||||||
tlb_fill(addr, 1, retaddr);
|
tlb_fill(addr, 1, is_user, retaddr);
|
||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handles all unaligned cases */
|
/* handles all unaligned cases */
|
||||||
static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val,
|
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr,
|
||||||
void *retaddr)
|
DATA_TYPE val,
|
||||||
|
int is_user,
|
||||||
|
void *retaddr)
|
||||||
{
|
{
|
||||||
unsigned long physaddr, tlb_addr;
|
unsigned long physaddr, tlb_addr;
|
||||||
int is_user, index, i;
|
int index, i;
|
||||||
|
|
||||||
is_user = ((env->hflags & HF_CPL_MASK) == 3);
|
|
||||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
redo:
|
redo:
|
||||||
tlb_addr = env->tlb_write[is_user][index].address;
|
tlb_addr = env->tlb_write[is_user][index].address;
|
||||||
@ -219,9 +234,11 @@ static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val,
|
|||||||
/* XXX: not efficient, but simple */
|
/* XXX: not efficient, but simple */
|
||||||
for(i = 0;i < DATA_SIZE; i++) {
|
for(i = 0;i < DATA_SIZE; i++) {
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
#ifdef TARGET_WORDS_BIGENDIAN
|
||||||
slow_stb(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)), retaddr);
|
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
|
||||||
|
is_user, retaddr);
|
||||||
#else
|
#else
|
||||||
slow_stb(addr + i, val >> (i * 8), retaddr);
|
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
|
||||||
|
is_user, retaddr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -230,7 +247,7 @@ static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* the page is not in the TLB : fill it */
|
/* the page is not in the TLB : fill it */
|
||||||
tlb_fill(addr, 1, retaddr);
|
tlb_fill(addr, 1, is_user, retaddr);
|
||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,4 +255,5 @@ static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val,
|
|||||||
#undef SHIFT
|
#undef SHIFT
|
||||||
#undef DATA_TYPE
|
#undef DATA_TYPE
|
||||||
#undef SUFFIX
|
#undef SUFFIX
|
||||||
|
#undef USUFFIX
|
||||||
#undef DATA_SIZE
|
#undef DATA_SIZE
|
||||||
|
@ -137,8 +137,10 @@ void helper_invlpg(unsigned int addr);
|
|||||||
void cpu_x86_update_cr0(CPUX86State *env);
|
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,
|
||||||
void tlb_fill(unsigned long addr, int is_write, void *retaddr);
|
int is_write, int is_user, int is_softmmu);
|
||||||
|
void tlb_fill(unsigned long addr, int is_write, int is_user,
|
||||||
|
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,
|
||||||
@ -366,26 +368,14 @@ static inline void load_eflags(int eflags, int update_mask)
|
|||||||
(eflags & update_mask);
|
(eflags & update_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* memory access macros */
|
/* XXX: move that to a generic header */
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
#define ldul ldl
|
|
||||||
#define lduq ldq
|
|
||||||
#define ldul_user ldl_user
|
#define ldul_user ldl_user
|
||||||
#define ldul_kernel ldl_kernel
|
#define ldul_kernel ldl_kernel
|
||||||
|
|
||||||
#define ldub_raw ldub
|
#define ACCESS_TYPE 0
|
||||||
#define ldsb_raw ldsb
|
#define MEMSUFFIX _kernel
|
||||||
#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
|
#define DATA_SIZE 1
|
||||||
#include "softmmu_header.h"
|
#include "softmmu_header.h"
|
||||||
|
|
||||||
@ -397,9 +387,11 @@ static inline void load_eflags(int eflags, int update_mask)
|
|||||||
|
|
||||||
#define DATA_SIZE 8
|
#define DATA_SIZE 8
|
||||||
#include "softmmu_header.h"
|
#include "softmmu_header.h"
|
||||||
|
#undef ACCESS_TYPE
|
||||||
|
#undef MEMSUFFIX
|
||||||
|
|
||||||
#undef MEMUSER
|
#define ACCESS_TYPE 1
|
||||||
#define MEMUSER 1
|
#define MEMSUFFIX _user
|
||||||
#define DATA_SIZE 1
|
#define DATA_SIZE 1
|
||||||
#include "softmmu_header.h"
|
#include "softmmu_header.h"
|
||||||
|
|
||||||
@ -411,6 +403,76 @@ static inline void load_eflags(int eflags, int update_mask)
|
|||||||
|
|
||||||
#define DATA_SIZE 8
|
#define DATA_SIZE 8
|
||||||
#include "softmmu_header.h"
|
#include "softmmu_header.h"
|
||||||
|
#undef ACCESS_TYPE
|
||||||
|
#undef MEMSUFFIX
|
||||||
|
|
||||||
#undef MEMUSER
|
/* these access are slower, they must be as rare as possible */
|
||||||
|
#define ACCESS_TYPE 2
|
||||||
|
#define MEMSUFFIX _data
|
||||||
|
#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 ACCESS_TYPE
|
||||||
|
#undef MEMSUFFIX
|
||||||
|
|
||||||
|
#define ldub(p) ldub_data(p)
|
||||||
|
#define ldsb(p) ldsb_data(p)
|
||||||
|
#define lduw(p) lduw_data(p)
|
||||||
|
#define ldsw(p) ldsw_data(p)
|
||||||
|
#define ldl(p) ldl_data(p)
|
||||||
|
#define ldq(p) ldq_data(p)
|
||||||
|
|
||||||
|
#define stb(p, v) stb_data(p, v)
|
||||||
|
#define stw(p, v) stw_data(p, v)
|
||||||
|
#define stl(p, v) stl_data(p, v)
|
||||||
|
#define stq(p, v) stq_data(p, v)
|
||||||
|
|
||||||
|
static inline double ldfq(void *ptr)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
double d;
|
||||||
|
uint64_t i;
|
||||||
|
} u;
|
||||||
|
u.i = ldq(ptr);
|
||||||
|
return u.d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void stfq(void *ptr, double v)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
double d;
|
||||||
|
uint64_t i;
|
||||||
|
} u;
|
||||||
|
u.d = v;
|
||||||
|
stq(ptr, u.i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float ldfl(void *ptr)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
} u;
|
||||||
|
u.i = ldl(ptr);
|
||||||
|
return u.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void stfl(void *ptr, float v)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
} u;
|
||||||
|
u.f = v;
|
||||||
|
stl(ptr, u.i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||||
|
@ -153,11 +153,11 @@ static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
|
|||||||
if (index + (4 << shift) - 1 > env->tr.limit)
|
if (index + (4 << shift) - 1 > env->tr.limit)
|
||||||
raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
|
raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
|
||||||
if (shift == 0) {
|
if (shift == 0) {
|
||||||
*esp_ptr = lduw(env->tr.base + index);
|
*esp_ptr = lduw_kernel(env->tr.base + index);
|
||||||
*ss_ptr = lduw(env->tr.base + index + 2);
|
*ss_ptr = lduw_kernel(env->tr.base + index + 2);
|
||||||
} else {
|
} else {
|
||||||
*esp_ptr = ldl(env->tr.base + index);
|
*esp_ptr = ldl_kernel(env->tr.base + index);
|
||||||
*ss_ptr = lduw(env->tr.base + index + 4);
|
*ss_ptr = lduw_kernel(env->tr.base + index + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,8 +177,8 @@ static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
|
|||||||
if ((index + 7) > dt->limit)
|
if ((index + 7) > dt->limit)
|
||||||
return -1;
|
return -1;
|
||||||
ptr = dt->base + index;
|
ptr = dt->base + index;
|
||||||
*e1_ptr = ldl(ptr);
|
*e1_ptr = ldl_kernel(ptr);
|
||||||
*e2_ptr = ldl(ptr + 4);
|
*e2_ptr = ldl_kernel(ptr + 4);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,8 +226,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
|
|||||||
if (intno * 8 + 7 > dt->limit)
|
if (intno * 8 + 7 > dt->limit)
|
||||||
raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
|
raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
|
||||||
ptr = dt->base + intno * 8;
|
ptr = dt->base + intno * 8;
|
||||||
e1 = ldl(ptr);
|
e1 = ldl_kernel(ptr);
|
||||||
e2 = ldl(ptr + 4);
|
e2 = ldl_kernel(ptr + 4);
|
||||||
/* check gate type */
|
/* check gate type */
|
||||||
type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
|
type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
|
||||||
switch(type) {
|
switch(type) {
|
||||||
@ -344,47 +344,47 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
|
|||||||
int old_eflags;
|
int old_eflags;
|
||||||
if (env->eflags & VM_MASK) {
|
if (env->eflags & VM_MASK) {
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, env->segs[R_GS].selector);
|
stl_kernel(ssp, env->segs[R_GS].selector);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, env->segs[R_FS].selector);
|
stl_kernel(ssp, env->segs[R_FS].selector);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, env->segs[R_DS].selector);
|
stl_kernel(ssp, env->segs[R_DS].selector);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, env->segs[R_ES].selector);
|
stl_kernel(ssp, env->segs[R_ES].selector);
|
||||||
}
|
}
|
||||||
if (new_stack) {
|
if (new_stack) {
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, old_ss);
|
stl_kernel(ssp, old_ss);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, old_esp);
|
stl_kernel(ssp, old_esp);
|
||||||
}
|
}
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
old_eflags = compute_eflags();
|
old_eflags = compute_eflags();
|
||||||
stl(ssp, old_eflags);
|
stl_kernel(ssp, old_eflags);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, old_cs);
|
stl_kernel(ssp, old_cs);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, old_eip);
|
stl_kernel(ssp, old_eip);
|
||||||
if (has_error_code) {
|
if (has_error_code) {
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, error_code);
|
stl_kernel(ssp, error_code);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (new_stack) {
|
if (new_stack) {
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, old_ss);
|
stw_kernel(ssp, old_ss);
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, old_esp);
|
stw_kernel(ssp, old_esp);
|
||||||
}
|
}
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, compute_eflags());
|
stw_kernel(ssp, compute_eflags());
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, old_cs);
|
stw_kernel(ssp, old_cs);
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, old_eip);
|
stw_kernel(ssp, old_eip);
|
||||||
if (has_error_code) {
|
if (has_error_code) {
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, error_code);
|
stw_kernel(ssp, error_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,8 +410,8 @@ static void do_interrupt_real(int intno, int is_int, int error_code,
|
|||||||
if (intno * 4 + 3 > dt->limit)
|
if (intno * 4 + 3 > dt->limit)
|
||||||
raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
|
raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
|
||||||
ptr = dt->base + intno * 4;
|
ptr = dt->base + intno * 4;
|
||||||
offset = lduw(ptr);
|
offset = lduw_kernel(ptr);
|
||||||
selector = lduw(ptr + 2);
|
selector = lduw_kernel(ptr + 2);
|
||||||
esp = ESP;
|
esp = ESP;
|
||||||
ssp = env->segs[R_SS].base;
|
ssp = env->segs[R_SS].base;
|
||||||
if (is_int)
|
if (is_int)
|
||||||
@ -420,11 +420,11 @@ static void do_interrupt_real(int intno, int is_int, int error_code,
|
|||||||
old_eip = env->eip;
|
old_eip = env->eip;
|
||||||
old_cs = env->segs[R_CS].selector;
|
old_cs = env->segs[R_CS].selector;
|
||||||
esp -= 2;
|
esp -= 2;
|
||||||
stw(ssp + (esp & 0xffff), compute_eflags());
|
stw_kernel(ssp + (esp & 0xffff), compute_eflags());
|
||||||
esp -= 2;
|
esp -= 2;
|
||||||
stw(ssp + (esp & 0xffff), old_cs);
|
stw_kernel(ssp + (esp & 0xffff), old_cs);
|
||||||
esp -= 2;
|
esp -= 2;
|
||||||
stw(ssp + (esp & 0xffff), old_eip);
|
stw_kernel(ssp + (esp & 0xffff), old_eip);
|
||||||
|
|
||||||
/* update processor state */
|
/* update processor state */
|
||||||
ESP = (ESP & ~0xffff) | (esp & 0xffff);
|
ESP = (ESP & ~0xffff) | (esp & 0xffff);
|
||||||
@ -445,7 +445,7 @@ void do_interrupt_user(int intno, int is_int, int error_code,
|
|||||||
|
|
||||||
dt = &env->idt;
|
dt = &env->idt;
|
||||||
ptr = dt->base + (intno * 8);
|
ptr = dt->base + (intno * 8);
|
||||||
e2 = ldl(ptr + 4);
|
e2 = ldl_kernel(ptr + 4);
|
||||||
|
|
||||||
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
|
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
|
||||||
cpl = env->hflags & HF_CPL_MASK;
|
cpl = env->hflags & HF_CPL_MASK;
|
||||||
@ -651,8 +651,8 @@ void helper_lldt_T0(void)
|
|||||||
if ((index + 7) > dt->limit)
|
if ((index + 7) > dt->limit)
|
||||||
raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
|
raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
|
||||||
ptr = dt->base + index;
|
ptr = dt->base + index;
|
||||||
e1 = ldl(ptr);
|
e1 = ldl_kernel(ptr);
|
||||||
e2 = ldl(ptr + 4);
|
e2 = ldl_kernel(ptr + 4);
|
||||||
if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
|
if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
|
||||||
raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
|
raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
|
||||||
if (!(e2 & DESC_P_MASK))
|
if (!(e2 & DESC_P_MASK))
|
||||||
@ -684,8 +684,8 @@ void helper_ltr_T0(void)
|
|||||||
if ((index + 7) > dt->limit)
|
if ((index + 7) > dt->limit)
|
||||||
raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
|
raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
|
||||||
ptr = dt->base + index;
|
ptr = dt->base + index;
|
||||||
e1 = ldl(ptr);
|
e1 = ldl_kernel(ptr);
|
||||||
e2 = ldl(ptr + 4);
|
e2 = ldl_kernel(ptr + 4);
|
||||||
type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
|
type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
|
||||||
if ((e2 & DESC_S_MASK) ||
|
if ((e2 & DESC_S_MASK) ||
|
||||||
(type != 2 && type != 9))
|
(type != 2 && type != 9))
|
||||||
@ -694,7 +694,7 @@ void helper_ltr_T0(void)
|
|||||||
raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
|
raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
|
||||||
load_seg_cache_raw_dt(&env->tr, e1, e2);
|
load_seg_cache_raw_dt(&env->tr, e1, e2);
|
||||||
e2 |= 0x00000200; /* set the busy bit */
|
e2 |= 0x00000200; /* set the busy bit */
|
||||||
stl(ptr + 4, e2);
|
stl_kernel(ptr + 4, e2);
|
||||||
}
|
}
|
||||||
env->tr.selector = selector;
|
env->tr.selector = selector;
|
||||||
}
|
}
|
||||||
@ -813,14 +813,14 @@ void helper_lcall_real_T0_T1(int shift, int next_eip)
|
|||||||
ssp = env->segs[R_SS].base;
|
ssp = env->segs[R_SS].base;
|
||||||
if (shift) {
|
if (shift) {
|
||||||
esp -= 4;
|
esp -= 4;
|
||||||
stl(ssp + (esp & esp_mask), env->segs[R_CS].selector);
|
stl_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector);
|
||||||
esp -= 4;
|
esp -= 4;
|
||||||
stl(ssp + (esp & esp_mask), next_eip);
|
stl_kernel(ssp + (esp & esp_mask), next_eip);
|
||||||
} else {
|
} else {
|
||||||
esp -= 2;
|
esp -= 2;
|
||||||
stw(ssp + (esp & esp_mask), env->segs[R_CS].selector);
|
stw_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector);
|
||||||
esp -= 2;
|
esp -= 2;
|
||||||
stw(ssp + (esp & esp_mask), next_eip);
|
stw_kernel(ssp + (esp & esp_mask), next_eip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(env->segs[R_SS].flags & DESC_B_MASK))
|
if (!(env->segs[R_SS].flags & DESC_B_MASK))
|
||||||
@ -873,14 +873,14 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip)
|
|||||||
ssp = env->segs[R_SS].base + sp;
|
ssp = env->segs[R_SS].base + sp;
|
||||||
if (shift) {
|
if (shift) {
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, env->segs[R_CS].selector);
|
stl_kernel(ssp, env->segs[R_CS].selector);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, next_eip);
|
stl_kernel(ssp, next_eip);
|
||||||
} else {
|
} else {
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, env->segs[R_CS].selector);
|
stw_kernel(ssp, env->segs[R_CS].selector);
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, next_eip);
|
stw_kernel(ssp, next_eip);
|
||||||
}
|
}
|
||||||
sp -= (4 << shift);
|
sp -= (4 << shift);
|
||||||
|
|
||||||
@ -975,23 +975,23 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip)
|
|||||||
ssp = env->segs[R_SS].base + sp;
|
ssp = env->segs[R_SS].base + sp;
|
||||||
if (shift) {
|
if (shift) {
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, old_ss);
|
stl_kernel(ssp, old_ss);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, old_esp);
|
stl_kernel(ssp, old_esp);
|
||||||
ssp -= 4 * param_count;
|
ssp -= 4 * param_count;
|
||||||
for(i = 0; i < param_count; i++) {
|
for(i = 0; i < param_count; i++) {
|
||||||
val = ldl(old_ssp + i * 4);
|
val = ldl_kernel(old_ssp + i * 4);
|
||||||
stl(ssp + i * 4, val);
|
stl_kernel(ssp + i * 4, val);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, old_ss);
|
stw_kernel(ssp, old_ss);
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, old_esp);
|
stw_kernel(ssp, old_esp);
|
||||||
ssp -= 2 * param_count;
|
ssp -= 2 * param_count;
|
||||||
for(i = 0; i < param_count; i++) {
|
for(i = 0; i < param_count; i++) {
|
||||||
val = lduw(old_ssp + i * 2);
|
val = lduw_kernel(old_ssp + i * 2);
|
||||||
stw(ssp + i * 2, val);
|
stw_kernel(ssp + i * 2, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1004,14 +1004,14 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip)
|
|||||||
|
|
||||||
if (shift) {
|
if (shift) {
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, env->segs[R_CS].selector);
|
stl_kernel(ssp, env->segs[R_CS].selector);
|
||||||
ssp -= 4;
|
ssp -= 4;
|
||||||
stl(ssp, next_eip);
|
stl_kernel(ssp, next_eip);
|
||||||
} else {
|
} else {
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, env->segs[R_CS].selector);
|
stw_kernel(ssp, env->segs[R_CS].selector);
|
||||||
ssp -= 2;
|
ssp -= 2;
|
||||||
stw(ssp, next_eip);
|
stw_kernel(ssp, next_eip);
|
||||||
}
|
}
|
||||||
|
|
||||||
sp -= push_size;
|
sp -= push_size;
|
||||||
@ -1042,14 +1042,14 @@ void helper_iret_real(int shift)
|
|||||||
ssp = env->segs[R_SS].base + sp;
|
ssp = env->segs[R_SS].base + sp;
|
||||||
if (shift == 1) {
|
if (shift == 1) {
|
||||||
/* 32 bits */
|
/* 32 bits */
|
||||||
new_eflags = ldl(ssp + 8);
|
new_eflags = ldl_kernel(ssp + 8);
|
||||||
new_cs = ldl(ssp + 4) & 0xffff;
|
new_cs = ldl_kernel(ssp + 4) & 0xffff;
|
||||||
new_eip = ldl(ssp) & 0xffff;
|
new_eip = ldl_kernel(ssp) & 0xffff;
|
||||||
} else {
|
} else {
|
||||||
/* 16 bits */
|
/* 16 bits */
|
||||||
new_eflags = lduw(ssp + 4);
|
new_eflags = lduw_kernel(ssp + 4);
|
||||||
new_cs = lduw(ssp + 2);
|
new_cs = lduw_kernel(ssp + 2);
|
||||||
new_eip = lduw(ssp);
|
new_eip = lduw_kernel(ssp);
|
||||||
}
|
}
|
||||||
new_esp = sp + (6 << shift);
|
new_esp = sp + (6 << shift);
|
||||||
ESP = (ESP & 0xffff0000) |
|
ESP = (ESP & 0xffff0000) |
|
||||||
@ -1078,17 +1078,17 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
|
|||||||
if (shift == 1) {
|
if (shift == 1) {
|
||||||
/* 32 bits */
|
/* 32 bits */
|
||||||
if (is_iret)
|
if (is_iret)
|
||||||
new_eflags = ldl(ssp + 8);
|
new_eflags = ldl_kernel(ssp + 8);
|
||||||
new_cs = ldl(ssp + 4) & 0xffff;
|
new_cs = ldl_kernel(ssp + 4) & 0xffff;
|
||||||
new_eip = ldl(ssp);
|
new_eip = ldl_kernel(ssp);
|
||||||
if (is_iret && (new_eflags & VM_MASK))
|
if (is_iret && (new_eflags & VM_MASK))
|
||||||
goto return_to_vm86;
|
goto return_to_vm86;
|
||||||
} else {
|
} else {
|
||||||
/* 16 bits */
|
/* 16 bits */
|
||||||
if (is_iret)
|
if (is_iret)
|
||||||
new_eflags = lduw(ssp + 4);
|
new_eflags = lduw_kernel(ssp + 4);
|
||||||
new_cs = lduw(ssp + 2);
|
new_cs = lduw_kernel(ssp + 2);
|
||||||
new_eip = lduw(ssp);
|
new_eip = lduw_kernel(ssp);
|
||||||
}
|
}
|
||||||
if ((new_cs & 0xfffc) == 0)
|
if ((new_cs & 0xfffc) == 0)
|
||||||
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
|
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
|
||||||
@ -1124,12 +1124,12 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
|
|||||||
ssp += (4 << shift) + ((2 * is_iret) << shift) + addend;
|
ssp += (4 << shift) + ((2 * is_iret) << shift) + addend;
|
||||||
if (shift == 1) {
|
if (shift == 1) {
|
||||||
/* 32 bits */
|
/* 32 bits */
|
||||||
new_esp = ldl(ssp);
|
new_esp = ldl_kernel(ssp);
|
||||||
new_ss = ldl(ssp + 4) & 0xffff;
|
new_ss = ldl_kernel(ssp + 4) & 0xffff;
|
||||||
} else {
|
} else {
|
||||||
/* 16 bits */
|
/* 16 bits */
|
||||||
new_esp = lduw(ssp);
|
new_esp = lduw_kernel(ssp);
|
||||||
new_ss = lduw(ssp + 2);
|
new_ss = lduw_kernel(ssp + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((new_ss & 3) != rpl)
|
if ((new_ss & 3) != rpl)
|
||||||
@ -1175,12 +1175,12 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
return_to_vm86:
|
return_to_vm86:
|
||||||
new_esp = ldl(ssp + 12);
|
new_esp = ldl_kernel(ssp + 12);
|
||||||
new_ss = ldl(ssp + 16);
|
new_ss = ldl_kernel(ssp + 16);
|
||||||
new_es = ldl(ssp + 20);
|
new_es = ldl_kernel(ssp + 20);
|
||||||
new_ds = ldl(ssp + 24);
|
new_ds = ldl_kernel(ssp + 24);
|
||||||
new_fs = ldl(ssp + 28);
|
new_fs = ldl_kernel(ssp + 28);
|
||||||
new_gs = ldl(ssp + 32);
|
new_gs = ldl_kernel(ssp + 32);
|
||||||
|
|
||||||
/* modify processor state */
|
/* modify processor state */
|
||||||
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK);
|
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK);
|
||||||
@ -1770,6 +1770,11 @@ void helper_frstor(uint8_t *ptr, int data32)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
|
#define MMUSUFFIX _mmu
|
||||||
|
#define GETPC() (__builtin_return_address(0))
|
||||||
|
|
||||||
#define SHIFT 0
|
#define SHIFT 0
|
||||||
#include "softmmu_template.h"
|
#include "softmmu_template.h"
|
||||||
|
|
||||||
@ -1782,22 +1787,41 @@ void helper_frstor(uint8_t *ptr, int data32)
|
|||||||
#define SHIFT 3
|
#define SHIFT 3
|
||||||
#include "softmmu_template.h"
|
#include "softmmu_template.h"
|
||||||
|
|
||||||
/* try to fill the TLB and return an exception if error */
|
#endif
|
||||||
void tlb_fill(unsigned long addr, int is_write, void *retaddr)
|
|
||||||
|
/* try to fill the TLB and return an exception if error. If retaddr is
|
||||||
|
NULL, it means that the function was called in C code (i.e. not
|
||||||
|
from generated code or from helper.c) */
|
||||||
|
/* XXX: fix it to restore all registers */
|
||||||
|
void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)
|
||||||
{
|
{
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long pc;
|
unsigned long pc;
|
||||||
ret = cpu_x86_handle_mmu_fault(env, addr, is_write);
|
CPUX86State *saved_env;
|
||||||
|
|
||||||
|
/* XXX: hack to restore env in all cases, even if not called from
|
||||||
|
generated code */
|
||||||
|
saved_env = env;
|
||||||
|
env = cpu_single_env;
|
||||||
|
if (is_write && page_unprotect(addr)) {
|
||||||
|
/* nothing more to do: the page was write protected because
|
||||||
|
there was code in it. page_unprotect() flushed the code. */
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* now we have a real cpu fault */
|
if (retaddr) {
|
||||||
pc = (unsigned long)retaddr;
|
/* now we have a real cpu fault */
|
||||||
tb = tb_find_pc(pc);
|
pc = (unsigned long)retaddr;
|
||||||
if (tb) {
|
tb = tb_find_pc(pc);
|
||||||
/* the PC is inside the translated code. It means that we have
|
if (tb) {
|
||||||
a virtual CPU fault */
|
/* the PC is inside the translated code. It means that we have
|
||||||
cpu_restore_state(tb, env, pc);
|
a virtual CPU fault */
|
||||||
|
cpu_restore_state(tb, env, pc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
raise_exception_err(EXCP0E_PAGE, env->error_code);
|
raise_exception_err(EXCP0E_PAGE, env->error_code);
|
||||||
}
|
}
|
||||||
|
env = saved_env;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,9 @@ void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
|
|||||||
flags = page_get_flags(addr);
|
flags = page_get_flags(addr);
|
||||||
if (flags & PAGE_VALID) {
|
if (flags & PAGE_VALID) {
|
||||||
virt_addr = addr & ~0xfff;
|
virt_addr = addr & ~0xfff;
|
||||||
|
#if !defined(CONFIG_SOFTMMU)
|
||||||
munmap((void *)virt_addr, 4096);
|
munmap((void *)virt_addr, 4096);
|
||||||
|
#endif
|
||||||
page_set_flags(virt_addr, virt_addr + 4096, 0);
|
page_set_flags(virt_addr, virt_addr + 4096, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,16 +223,14 @@ void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
|
|||||||
1 = generate PF fault
|
1 = generate PF fault
|
||||||
2 = soft MMU activation required for this block
|
2 = soft MMU activation required for this block
|
||||||
*/
|
*/
|
||||||
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, int is_user, int is_softmmu)
|
||||||
{
|
{
|
||||||
uint8_t *pde_ptr, *pte_ptr;
|
uint8_t *pde_ptr, *pte_ptr;
|
||||||
uint32_t pde, pte, virt_addr;
|
uint32_t pde, pte, virt_addr;
|
||||||
int cpl, error_code, is_dirty, is_user, prot, page_size, ret;
|
int error_code, is_dirty, prot, page_size, ret;
|
||||||
unsigned long pd;
|
unsigned long pd;
|
||||||
|
|
||||||
cpl = env->hflags & HF_CPL_MASK;
|
|
||||||
is_user = (cpl == 3);
|
|
||||||
|
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n",
|
printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n",
|
||||||
addr, is_write, is_user, env->eip);
|
addr, is_write, is_user, env->eip);
|
||||||
@ -252,7 +252,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
|
|||||||
|
|
||||||
/* page directory entry */
|
/* page directory entry */
|
||||||
pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
|
pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
|
||||||
pde = ldl(pde_ptr);
|
pde = ldl_raw(pde_ptr);
|
||||||
if (!(pde & PG_PRESENT_MASK)) {
|
if (!(pde & PG_PRESENT_MASK)) {
|
||||||
error_code = 0;
|
error_code = 0;
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
@ -274,7 +274,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
|
|||||||
pde |= PG_ACCESSED_MASK;
|
pde |= PG_ACCESSED_MASK;
|
||||||
if (is_dirty)
|
if (is_dirty)
|
||||||
pde |= PG_DIRTY_MASK;
|
pde |= PG_DIRTY_MASK;
|
||||||
stl(pde_ptr, pde);
|
stl_raw(pde_ptr, pde);
|
||||||
}
|
}
|
||||||
|
|
||||||
pte = pde & ~0x003ff000; /* align to 4MB */
|
pte = pde & ~0x003ff000; /* align to 4MB */
|
||||||
@ -283,12 +283,12 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
|
|||||||
} else {
|
} else {
|
||||||
if (!(pde & PG_ACCESSED_MASK)) {
|
if (!(pde & PG_ACCESSED_MASK)) {
|
||||||
pde |= PG_ACCESSED_MASK;
|
pde |= PG_ACCESSED_MASK;
|
||||||
stl(pde_ptr, pde);
|
stl_raw(pde_ptr, pde);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* page directory entry */
|
/* page directory entry */
|
||||||
pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
|
pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
|
||||||
pte = ldl(pte_ptr);
|
pte = ldl_raw(pte_ptr);
|
||||||
if (!(pte & PG_PRESENT_MASK)) {
|
if (!(pte & PG_PRESENT_MASK)) {
|
||||||
error_code = 0;
|
error_code = 0;
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
@ -308,7 +308,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
|
|||||||
pte |= PG_ACCESSED_MASK;
|
pte |= PG_ACCESSED_MASK;
|
||||||
if (is_dirty)
|
if (is_dirty)
|
||||||
pte |= PG_DIRTY_MASK;
|
pte |= PG_DIRTY_MASK;
|
||||||
stl(pte_ptr, pte);
|
stl_raw(pte_ptr, pte);
|
||||||
}
|
}
|
||||||
page_size = 4096;
|
page_size = 4096;
|
||||||
virt_addr = addr & ~0xfff;
|
virt_addr = addr & ~0xfff;
|
||||||
@ -325,7 +325,10 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
|
|||||||
}
|
}
|
||||||
|
|
||||||
do_mapping:
|
do_mapping:
|
||||||
if (env->hflags & HF_SOFTMMU_MASK) {
|
#if !defined(CONFIG_SOFTMMU)
|
||||||
|
if (is_softmmu)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
unsigned long paddr, vaddr, address, addend, page_offset;
|
unsigned long paddr, vaddr, address, addend, page_offset;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@ -352,32 +355,39 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
|
|||||||
env->tlb_write[is_user][index].address = address;
|
env->tlb_write[is_user][index].address = address;
|
||||||
env->tlb_write[is_user][index].addend = addend;
|
env->tlb_write[is_user][index].addend = addend;
|
||||||
}
|
}
|
||||||
}
|
page_set_flags(vaddr, vaddr + TARGET_PAGE_SIZE,
|
||||||
ret = 0;
|
|
||||||
/* XXX: incorrect for 4MB pages */
|
|
||||||
pd = physpage_find(pte & ~0xfff);
|
|
||||||
if ((pd & 0xfff) != 0) {
|
|
||||||
/* IO access: no mapping is done as it will be handled by the
|
|
||||||
soft MMU */
|
|
||||||
if (!(env->hflags & HF_SOFTMMU_MASK))
|
|
||||||
ret = 2;
|
|
||||||
} else {
|
|
||||||
void *map_addr;
|
|
||||||
map_addr = mmap((void *)virt_addr, page_size, prot,
|
|
||||||
MAP_SHARED | MAP_FIXED, phys_ram_fd, pd);
|
|
||||||
if (map_addr == MAP_FAILED) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
|
|
||||||
pte & ~0xfff, virt_addr);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_MMU
|
|
||||||
printf("mmaping 0x%08x to virt 0x%08x pse=%d\n",
|
|
||||||
pte & ~0xfff, virt_addr, (page_size != 4096));
|
|
||||||
#endif
|
|
||||||
page_set_flags(virt_addr, virt_addr + page_size,
|
|
||||||
PAGE_VALID | PAGE_EXEC | prot);
|
PAGE_VALID | PAGE_EXEC | prot);
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
#if !defined(CONFIG_SOFTMMU)
|
||||||
|
else {
|
||||||
|
ret = 0;
|
||||||
|
/* XXX: incorrect for 4MB pages */
|
||||||
|
pd = physpage_find(pte & ~0xfff);
|
||||||
|
if ((pd & 0xfff) != 0) {
|
||||||
|
/* IO access: no mapping is done as it will be handled by the
|
||||||
|
soft MMU */
|
||||||
|
if (!(env->hflags & HF_SOFTMMU_MASK))
|
||||||
|
ret = 2;
|
||||||
|
} else {
|
||||||
|
void *map_addr;
|
||||||
|
map_addr = mmap((void *)virt_addr, page_size, prot,
|
||||||
|
MAP_SHARED | MAP_FIXED, phys_ram_fd, pd);
|
||||||
|
if (map_addr == MAP_FAILED) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
|
||||||
|
pte & ~0xfff, virt_addr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_MMU
|
||||||
|
printf("mmaping 0x%08x to virt 0x%08x pse=%d\n",
|
||||||
|
pte & ~0xfff, virt_addr, (page_size != 4096));
|
||||||
|
#endif
|
||||||
|
page_set_flags(virt_addr, virt_addr + page_size,
|
||||||
|
PAGE_VALID | PAGE_EXEC | prot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
do_fault_protect:
|
do_fault_protect:
|
||||||
error_code = PG_ERROR_P_MASK;
|
error_code = PG_ERROR_P_MASK;
|
||||||
|
@ -376,14 +376,16 @@ void OPPROTO op_andl_A0_ffff(void)
|
|||||||
|
|
||||||
/* memory access */
|
/* memory access */
|
||||||
|
|
||||||
#define MEMSUFFIX
|
#define MEMSUFFIX _raw
|
||||||
#include "ops_mem.h"
|
#include "ops_mem.h"
|
||||||
|
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
#define MEMSUFFIX _user
|
#define MEMSUFFIX _user
|
||||||
#include "ops_mem.h"
|
#include "ops_mem.h"
|
||||||
|
|
||||||
#define MEMSUFFIX _kernel
|
#define MEMSUFFIX _kernel
|
||||||
#include "ops_mem.h"
|
#include "ops_mem.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* used for bit operations */
|
/* used for bit operations */
|
||||||
|
|
||||||
|
@ -570,10 +570,10 @@ static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = {
|
static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = {
|
||||||
gen_op_ldsb_T0_A0,
|
gen_op_ldsb_raw_T0_A0,
|
||||||
gen_op_ldsw_T0_A0,
|
gen_op_ldsw_raw_T0_A0,
|
||||||
NULL,
|
NULL,
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
gen_op_ldsb_kernel_T0_A0,
|
gen_op_ldsb_kernel_T0_A0,
|
||||||
gen_op_ldsw_kernel_T0_A0,
|
gen_op_ldsw_kernel_T0_A0,
|
||||||
NULL,
|
NULL,
|
||||||
@ -581,13 +581,15 @@ static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = {
|
|||||||
gen_op_ldsb_user_T0_A0,
|
gen_op_ldsb_user_T0_A0,
|
||||||
gen_op_ldsw_user_T0_A0,
|
gen_op_ldsw_user_T0_A0,
|
||||||
NULL,
|
NULL,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = {
|
static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = {
|
||||||
gen_op_ldub_T0_A0,
|
gen_op_ldub_raw_T0_A0,
|
||||||
gen_op_lduw_T0_A0,
|
gen_op_lduw_raw_T0_A0,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
gen_op_ldub_kernel_T0_A0,
|
gen_op_ldub_kernel_T0_A0,
|
||||||
gen_op_lduw_kernel_T0_A0,
|
gen_op_lduw_kernel_T0_A0,
|
||||||
NULL,
|
NULL,
|
||||||
@ -595,14 +597,16 @@ static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = {
|
|||||||
gen_op_ldub_user_T0_A0,
|
gen_op_ldub_user_T0_A0,
|
||||||
gen_op_lduw_user_T0_A0,
|
gen_op_lduw_user_T0_A0,
|
||||||
NULL,
|
NULL,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
|
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
|
||||||
static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = {
|
static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = {
|
||||||
gen_op_ldub_T0_A0,
|
gen_op_ldub_raw_T0_A0,
|
||||||
gen_op_lduw_T0_A0,
|
gen_op_lduw_raw_T0_A0,
|
||||||
gen_op_ldl_T0_A0,
|
gen_op_ldl_raw_T0_A0,
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
gen_op_ldub_kernel_T0_A0,
|
gen_op_ldub_kernel_T0_A0,
|
||||||
gen_op_lduw_kernel_T0_A0,
|
gen_op_lduw_kernel_T0_A0,
|
||||||
gen_op_ldl_kernel_T0_A0,
|
gen_op_ldl_kernel_T0_A0,
|
||||||
@ -610,13 +614,15 @@ static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = {
|
|||||||
gen_op_ldub_user_T0_A0,
|
gen_op_ldub_user_T0_A0,
|
||||||
gen_op_lduw_user_T0_A0,
|
gen_op_lduw_user_T0_A0,
|
||||||
gen_op_ldl_user_T0_A0,
|
gen_op_ldl_user_T0_A0,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = {
|
static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = {
|
||||||
gen_op_ldub_T1_A0,
|
gen_op_ldub_raw_T1_A0,
|
||||||
gen_op_lduw_T1_A0,
|
gen_op_lduw_raw_T1_A0,
|
||||||
gen_op_ldl_T1_A0,
|
gen_op_ldl_raw_T1_A0,
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
gen_op_ldub_kernel_T1_A0,
|
gen_op_ldub_kernel_T1_A0,
|
||||||
gen_op_lduw_kernel_T1_A0,
|
gen_op_lduw_kernel_T1_A0,
|
||||||
gen_op_ldl_kernel_T1_A0,
|
gen_op_ldl_kernel_T1_A0,
|
||||||
@ -624,13 +630,15 @@ static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = {
|
|||||||
gen_op_ldub_user_T1_A0,
|
gen_op_ldub_user_T1_A0,
|
||||||
gen_op_lduw_user_T1_A0,
|
gen_op_lduw_user_T1_A0,
|
||||||
gen_op_ldl_user_T1_A0,
|
gen_op_ldl_user_T1_A0,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
|
static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
|
||||||
gen_op_stb_T0_A0,
|
gen_op_stb_raw_T0_A0,
|
||||||
gen_op_stw_T0_A0,
|
gen_op_stw_raw_T0_A0,
|
||||||
gen_op_stl_T0_A0,
|
gen_op_stl_raw_T0_A0,
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
gen_op_stb_kernel_T0_A0,
|
gen_op_stb_kernel_T0_A0,
|
||||||
gen_op_stw_kernel_T0_A0,
|
gen_op_stw_kernel_T0_A0,
|
||||||
gen_op_stl_kernel_T0_A0,
|
gen_op_stl_kernel_T0_A0,
|
||||||
@ -638,6 +646,7 @@ static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
|
|||||||
gen_op_stb_user_T0_A0,
|
gen_op_stb_user_T0_A0,
|
||||||
gen_op_stw_user_T0_A0,
|
gen_op_stw_user_T0_A0,
|
||||||
gen_op_stl_user_T0_A0,
|
gen_op_stl_user_T0_A0,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void gen_string_movl_A0_ESI(DisasContext *s)
|
static inline void gen_string_movl_A0_ESI(DisasContext *s)
|
||||||
@ -1176,7 +1185,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
|
|||||||
|
|
||||||
if (base == 4) {
|
if (base == 4) {
|
||||||
havesib = 1;
|
havesib = 1;
|
||||||
code = ldub(s->pc++);
|
code = ldub_code(s->pc++);
|
||||||
scale = (code >> 6) & 3;
|
scale = (code >> 6) & 3;
|
||||||
index = (code >> 3) & 7;
|
index = (code >> 3) & 7;
|
||||||
base = code & 7;
|
base = code & 7;
|
||||||
@ -1186,18 +1195,18 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
|
|||||||
case 0:
|
case 0:
|
||||||
if (base == 5) {
|
if (base == 5) {
|
||||||
base = -1;
|
base = -1;
|
||||||
disp = ldl(s->pc);
|
disp = ldl_code(s->pc);
|
||||||
s->pc += 4;
|
s->pc += 4;
|
||||||
} else {
|
} else {
|
||||||
disp = 0;
|
disp = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
disp = (int8_t)ldub(s->pc++);
|
disp = (int8_t)ldub_code(s->pc++);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case 2:
|
case 2:
|
||||||
disp = ldl(s->pc);
|
disp = ldl_code(s->pc);
|
||||||
s->pc += 4;
|
s->pc += 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1229,7 +1238,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
|
|||||||
switch (mod) {
|
switch (mod) {
|
||||||
case 0:
|
case 0:
|
||||||
if (rm == 6) {
|
if (rm == 6) {
|
||||||
disp = lduw(s->pc);
|
disp = lduw_code(s->pc);
|
||||||
s->pc += 2;
|
s->pc += 2;
|
||||||
gen_op_movl_A0_im(disp);
|
gen_op_movl_A0_im(disp);
|
||||||
rm = 0; /* avoid SS override */
|
rm = 0; /* avoid SS override */
|
||||||
@ -1239,11 +1248,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
disp = (int8_t)ldub(s->pc++);
|
disp = (int8_t)ldub_code(s->pc++);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case 2:
|
case 2:
|
||||||
disp = lduw(s->pc);
|
disp = lduw_code(s->pc);
|
||||||
s->pc += 2;
|
s->pc += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1337,16 +1346,16 @@ static inline uint32_t insn_get(DisasContext *s, int ot)
|
|||||||
|
|
||||||
switch(ot) {
|
switch(ot) {
|
||||||
case OT_BYTE:
|
case OT_BYTE:
|
||||||
ret = ldub(s->pc);
|
ret = ldub_code(s->pc);
|
||||||
s->pc++;
|
s->pc++;
|
||||||
break;
|
break;
|
||||||
case OT_WORD:
|
case OT_WORD:
|
||||||
ret = lduw(s->pc);
|
ret = lduw_code(s->pc);
|
||||||
s->pc += 2;
|
s->pc += 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case OT_LONG:
|
case OT_LONG:
|
||||||
ret = ldl(s->pc);
|
ret = ldl_code(s->pc);
|
||||||
s->pc += 4;
|
s->pc += 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1756,7 +1765,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
dflag = s->code32;
|
dflag = s->code32;
|
||||||
s->override = -1;
|
s->override = -1;
|
||||||
next_byte:
|
next_byte:
|
||||||
b = ldub(s->pc);
|
b = ldub_code(s->pc);
|
||||||
s->pc++;
|
s->pc++;
|
||||||
/* check prefixes */
|
/* check prefixes */
|
||||||
switch (b) {
|
switch (b) {
|
||||||
@ -1814,7 +1823,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
case 0x0f:
|
case 0x0f:
|
||||||
/**************************/
|
/**************************/
|
||||||
/* extended op code */
|
/* extended op code */
|
||||||
b = ldub(s->pc++) | 0x100;
|
b = ldub_code(s->pc++) | 0x100;
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
@ -1839,7 +1848,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
|
|
||||||
switch(f) {
|
switch(f) {
|
||||||
case 0: /* OP Ev, Gv */
|
case 0: /* OP Ev, Gv */
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = ((modrm >> 3) & 7);
|
reg = ((modrm >> 3) & 7);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
@ -1861,7 +1870,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op(s, op, ot, opreg);
|
gen_op(s, op, ot, opreg);
|
||||||
break;
|
break;
|
||||||
case 1: /* OP Gv, Ev */
|
case 1: /* OP Gv, Ev */
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
reg = ((modrm >> 3) & 7);
|
reg = ((modrm >> 3) & 7);
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
@ -1895,7 +1904,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
@ -1939,7 +1948,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
@ -2045,7 +2054,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
@ -2085,10 +2094,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_push_T0(s);
|
gen_push_T0(s);
|
||||||
gen_eob(s);
|
gen_eob(s);
|
||||||
break;
|
break;
|
||||||
case 3: /*< lcall Ev */
|
case 3: /* lcall Ev */
|
||||||
gen_op_ld_T1_A0[ot + s->mem_index]();
|
gen_op_ld_T1_A0[ot + s->mem_index]();
|
||||||
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
|
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
|
||||||
gen_op_ld_T0_A0[OT_WORD + s->mem_index]();
|
gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
|
||||||
do_lcall:
|
do_lcall:
|
||||||
if (s->pe && !s->vm86) {
|
if (s->pe && !s->vm86) {
|
||||||
if (s->cc_op != CC_OP_DYNAMIC)
|
if (s->cc_op != CC_OP_DYNAMIC)
|
||||||
@ -2109,7 +2118,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
case 5: /* ljmp Ev */
|
case 5: /* ljmp Ev */
|
||||||
gen_op_ld_T1_A0[ot + s->mem_index]();
|
gen_op_ld_T1_A0[ot + s->mem_index]();
|
||||||
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
|
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
|
||||||
gen_op_lduw_T0_A0();
|
gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
|
||||||
do_ljmp:
|
do_ljmp:
|
||||||
if (s->pe && !s->vm86) {
|
if (s->pe && !s->vm86) {
|
||||||
if (s->cc_op != CC_OP_DYNAMIC)
|
if (s->cc_op != CC_OP_DYNAMIC)
|
||||||
@ -2138,7 +2147,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
@ -2179,7 +2188,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
case 0x69: /* imul Gv, Ev, I */
|
case 0x69: /* imul Gv, Ev, I */
|
||||||
case 0x6b:
|
case 0x6b:
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = ((modrm >> 3) & 7) + OR_EAX;
|
reg = ((modrm >> 3) & 7) + OR_EAX;
|
||||||
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
||||||
if (b == 0x69) {
|
if (b == 0x69) {
|
||||||
@ -2206,7 +2215,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (mod == 3) {
|
if (mod == 3) {
|
||||||
@ -2233,7 +2242,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
gen_op_mov_TN_reg[ot][1][reg]();
|
gen_op_mov_TN_reg[ot][1][reg]();
|
||||||
@ -2250,7 +2259,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
s->cc_op = CC_OP_SUBB + ot;
|
s->cc_op = CC_OP_SUBB + ot;
|
||||||
break;
|
break;
|
||||||
case 0x1c7: /* cmpxchg8b */
|
case 0x1c7: /* cmpxchg8b */
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (mod == 3)
|
if (mod == 3)
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
@ -2291,7 +2300,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
break;
|
break;
|
||||||
case 0x8f: /* pop Ev */
|
case 0x8f: /* pop Ev */
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
gen_pop_T0(s);
|
gen_pop_T0(s);
|
||||||
s->popl_esp_hack = 2 << dflag;
|
s->popl_esp_hack = 2 << dflag;
|
||||||
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
|
||||||
@ -2301,9 +2310,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
case 0xc8: /* enter */
|
case 0xc8: /* enter */
|
||||||
{
|
{
|
||||||
int level;
|
int level;
|
||||||
val = lduw(s->pc);
|
val = lduw_code(s->pc);
|
||||||
s->pc += 2;
|
s->pc += 2;
|
||||||
level = ldub(s->pc++);
|
level = ldub_code(s->pc++);
|
||||||
gen_enter(s, val, level);
|
gen_enter(s, val, level);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2369,7 +2378,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
|
|
||||||
/* generate a generic store */
|
/* generate a generic store */
|
||||||
@ -2381,7 +2390,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (mod != 3)
|
if (mod != 3)
|
||||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||||
@ -2398,14 +2407,14 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
|
|
||||||
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
||||||
gen_op_mov_reg_T0[ot][reg]();
|
gen_op_mov_reg_T0[ot][reg]();
|
||||||
break;
|
break;
|
||||||
case 0x8e: /* mov seg, Gv */
|
case 0x8e: /* mov seg, Gv */
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
if (reg >= 6 || reg == R_CS)
|
if (reg >= 6 || reg == R_CS)
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
@ -2422,7 +2431,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x8c: /* mov Gv, seg */
|
case 0x8c: /* mov Gv, seg */
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (reg >= 6)
|
if (reg >= 6)
|
||||||
@ -2444,7 +2453,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
d_ot = dflag + OT_WORD;
|
d_ot = dflag + OT_WORD;
|
||||||
/* ot is the size of source */
|
/* ot is the size of source */
|
||||||
ot = (b & 1) + OT_BYTE;
|
ot = (b & 1) + OT_BYTE;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = ((modrm >> 3) & 7) + OR_EAX;
|
reg = ((modrm >> 3) & 7) + OR_EAX;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
@ -2481,7 +2490,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
|
|
||||||
case 0x8d: /* lea */
|
case 0x8d: /* lea */
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
/* we must ensure that no segment is added */
|
/* we must ensure that no segment is added */
|
||||||
s->override = -1;
|
s->override = -1;
|
||||||
@ -2574,7 +2583,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (mod == 3) {
|
if (mod == 3) {
|
||||||
@ -2613,7 +2622,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
op = R_GS;
|
op = R_GS;
|
||||||
do_lxx:
|
do_lxx:
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (mod == 3)
|
if (mod == 3)
|
||||||
@ -2622,7 +2631,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_ld_T1_A0[ot + s->mem_index]();
|
gen_op_ld_T1_A0[ot + s->mem_index]();
|
||||||
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
|
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
|
||||||
/* load the segment first to handle exceptions properly */
|
/* load the segment first to handle exceptions properly */
|
||||||
gen_op_lduw_T0_A0();
|
gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
|
||||||
gen_movl_seg_T0(s, op, pc_start - s->cs_base);
|
gen_movl_seg_T0(s, op, pc_start - s->cs_base);
|
||||||
/* then put the data */
|
/* then put the data */
|
||||||
gen_op_mov_reg_T1[ot][reg]();
|
gen_op_mov_reg_T1[ot][reg]();
|
||||||
@ -2645,7 +2654,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
@ -2662,7 +2671,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_shift(s, op, ot, opreg, OR_ECX);
|
gen_shift(s, op, ot, opreg, OR_ECX);
|
||||||
} else {
|
} else {
|
||||||
if (shift == 2) {
|
if (shift == 2) {
|
||||||
shift = ldub(s->pc++);
|
shift = ldub_code(s->pc++);
|
||||||
}
|
}
|
||||||
gen_shifti(s, op, ot, opreg, shift);
|
gen_shifti(s, op, ot, opreg, shift);
|
||||||
}
|
}
|
||||||
@ -2696,7 +2705,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
shift = 0;
|
shift = 0;
|
||||||
do_shiftd:
|
do_shiftd:
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
@ -2710,7 +2719,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_mov_TN_reg[ot][1][reg]();
|
gen_op_mov_TN_reg[ot][1][reg]();
|
||||||
|
|
||||||
if (shift) {
|
if (shift) {
|
||||||
val = ldub(s->pc++);
|
val = ldub_code(s->pc++);
|
||||||
val &= 0x1f;
|
val &= 0x1f;
|
||||||
if (val) {
|
if (val) {
|
||||||
if (mod == 3)
|
if (mod == 3)
|
||||||
@ -2739,7 +2748,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
/************************/
|
/************************/
|
||||||
/* floats */
|
/* floats */
|
||||||
case 0xd8 ... 0xdf:
|
case 0xd8 ... 0xdf:
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
op = ((b & 7) << 3) | ((modrm >> 3) & 7);
|
op = ((b & 7) << 3) | ((modrm >> 3) & 7);
|
||||||
@ -3256,7 +3265,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
val = ldub(s->pc++);
|
val = ldub_code(s->pc++);
|
||||||
gen_op_movl_T0_im(val);
|
gen_op_movl_T0_im(val);
|
||||||
gen_op_in[ot]();
|
gen_op_in[ot]();
|
||||||
gen_op_mov_reg_T1[ot][R_EAX]();
|
gen_op_mov_reg_T1[ot][R_EAX]();
|
||||||
@ -3271,7 +3280,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = OT_BYTE;
|
ot = OT_BYTE;
|
||||||
else
|
else
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
val = ldub(s->pc++);
|
val = ldub_code(s->pc++);
|
||||||
gen_op_movl_T0_im(val);
|
gen_op_movl_T0_im(val);
|
||||||
gen_op_mov_TN_reg[ot][1][R_EAX]();
|
gen_op_mov_TN_reg[ot][1][R_EAX]();
|
||||||
gen_op_out[ot]();
|
gen_op_out[ot]();
|
||||||
@ -3309,7 +3318,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
/************************/
|
/************************/
|
||||||
/* control */
|
/* control */
|
||||||
case 0xc2: /* ret im */
|
case 0xc2: /* ret im */
|
||||||
val = ldsw(s->pc);
|
val = ldsw_code(s->pc);
|
||||||
s->pc += 2;
|
s->pc += 2;
|
||||||
gen_pop_T0(s);
|
gen_pop_T0(s);
|
||||||
gen_stack_update(s, val + (2 << s->dflag));
|
gen_stack_update(s, val + (2 << s->dflag));
|
||||||
@ -3327,7 +3336,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_eob(s);
|
gen_eob(s);
|
||||||
break;
|
break;
|
||||||
case 0xca: /* lret im */
|
case 0xca: /* lret im */
|
||||||
val = ldsw(s->pc);
|
val = ldsw_code(s->pc);
|
||||||
s->pc += 2;
|
s->pc += 2;
|
||||||
do_lret:
|
do_lret:
|
||||||
if (s->pe && !s->vm86) {
|
if (s->pe && !s->vm86) {
|
||||||
@ -3443,13 +3452,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x190 ... 0x19f: /* setcc Gv */
|
case 0x190 ... 0x19f: /* setcc Gv */
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
gen_setcc(s, b);
|
gen_setcc(s, b);
|
||||||
gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
|
gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
|
||||||
break;
|
break;
|
||||||
case 0x140 ... 0x14f: /* cmov Gv, Ev */
|
case 0x140 ... 0x14f: /* cmov Gv, Ev */
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
gen_setcc(s, b);
|
gen_setcc(s, b);
|
||||||
@ -3542,7 +3551,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
/* bit operations */
|
/* bit operations */
|
||||||
case 0x1ba: /* bt/bts/btr/btc Gv, im */
|
case 0x1ba: /* bt/bts/btr/btc Gv, im */
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
@ -3553,7 +3562,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_mov_TN_reg[ot][0][rm]();
|
gen_op_mov_TN_reg[ot][0][rm]();
|
||||||
}
|
}
|
||||||
/* load shift */
|
/* load shift */
|
||||||
val = ldub(s->pc++);
|
val = ldub_code(s->pc++);
|
||||||
gen_op_movl_T1_im(val);
|
gen_op_movl_T1_im(val);
|
||||||
if (op < 4)
|
if (op < 4)
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
@ -3581,7 +3590,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
op = 3;
|
op = 3;
|
||||||
do_btx:
|
do_btx:
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
@ -3610,7 +3619,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
case 0x1bc: /* bsf */
|
case 0x1bc: /* bsf */
|
||||||
case 0x1bd: /* bsr */
|
case 0x1bd: /* bsr */
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
||||||
gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
|
gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
|
||||||
@ -3646,12 +3655,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
s->cc_op = CC_OP_EFLAGS;
|
s->cc_op = CC_OP_EFLAGS;
|
||||||
break;
|
break;
|
||||||
case 0xd4: /* aam */
|
case 0xd4: /* aam */
|
||||||
val = ldub(s->pc++);
|
val = ldub_code(s->pc++);
|
||||||
gen_op_aam(val);
|
gen_op_aam(val);
|
||||||
s->cc_op = CC_OP_LOGICB;
|
s->cc_op = CC_OP_LOGICB;
|
||||||
break;
|
break;
|
||||||
case 0xd5: /* aad */
|
case 0xd5: /* aad */
|
||||||
val = ldub(s->pc++);
|
val = ldub_code(s->pc++);
|
||||||
gen_op_aad(val);
|
gen_op_aad(val);
|
||||||
s->cc_op = CC_OP_LOGICB;
|
s->cc_op = CC_OP_LOGICB;
|
||||||
break;
|
break;
|
||||||
@ -3665,7 +3674,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
|
gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
|
||||||
break;
|
break;
|
||||||
case 0xcd: /* int N */
|
case 0xcd: /* int N */
|
||||||
val = ldub(s->pc++);
|
val = ldub_code(s->pc++);
|
||||||
/* XXX: add error code for vm86 GPF */
|
/* XXX: add error code for vm86 GPF */
|
||||||
if (!s->vm86)
|
if (!s->vm86)
|
||||||
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
|
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
|
||||||
@ -3718,7 +3727,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
break;
|
break;
|
||||||
case 0x62: /* bound */
|
case 0x62: /* bound */
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (mod == 3)
|
if (mod == 3)
|
||||||
@ -3785,7 +3794,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x100:
|
case 0x100:
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
switch(op) {
|
switch(op) {
|
||||||
@ -3828,7 +3837,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x101:
|
case 0x101:
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
switch(op) {
|
switch(op) {
|
||||||
@ -3904,7 +3913,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
if (!s->pe || s->vm86)
|
if (!s->pe || s->vm86)
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
|
||||||
gen_op_mov_TN_reg[ot][1][reg]();
|
gen_op_mov_TN_reg[ot][1][reg]();
|
||||||
@ -3918,7 +3927,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_mov_reg_T1[ot][reg]();
|
gen_op_mov_reg_T1[ot][reg]();
|
||||||
break;
|
break;
|
||||||
case 0x118:
|
case 0x118:
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
switch(op) {
|
switch(op) {
|
||||||
@ -3940,7 +3949,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
if (s->cpl != 0) {
|
if (s->cpl != 0) {
|
||||||
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
||||||
} else {
|
} else {
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
if ((modrm & 0xc0) != 0xc0)
|
if ((modrm & 0xc0) != 0xc0)
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
@ -3970,7 +3979,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
if (s->cpl != 0) {
|
if (s->cpl != 0) {
|
||||||
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
||||||
} else {
|
} else {
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub_code(s->pc++);
|
||||||
if ((modrm & 0xc0) != 0xc0)
|
if ((modrm & 0xc0) != 0xc0)
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
|
Loading…
Reference in New Issue
Block a user