PAGE_EXEC support in TLBs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1676 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
5cf3839607
commit
84b7b8e778
10
cpu-defs.h
10
cpu-defs.h
@ -80,7 +80,8 @@ typedef unsigned long ram_addr_t;
|
||||
#define TB_JMP_CACHE_BITS 12
|
||||
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
|
||||
|
||||
#define CPU_TLB_SIZE 256
|
||||
#define CPU_TLB_BITS 8
|
||||
#define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
|
||||
|
||||
typedef struct CPUTLBEntry {
|
||||
/* bit 31 to TARGET_PAGE_BITS : virtual address
|
||||
@ -89,7 +90,9 @@ typedef struct CPUTLBEntry {
|
||||
bit 3 : indicates that the entry is invalid
|
||||
bit 2..0 : zero
|
||||
*/
|
||||
target_ulong address;
|
||||
target_ulong addr_read;
|
||||
target_ulong addr_write;
|
||||
target_ulong addr_code;
|
||||
/* addend to virtual address to get physical address */
|
||||
target_phys_addr_t addend;
|
||||
} CPUTLBEntry;
|
||||
@ -105,8 +108,7 @@ typedef struct CPUTLBEntry {
|
||||
target_ulong mem_write_vaddr; /* target virtual addr at which the \
|
||||
memory was written */ \
|
||||
/* 0 = kernel, 1 = user */ \
|
||||
CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; \
|
||||
CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; \
|
||||
CPUTLBEntry tlb_table[2][CPU_TLB_SIZE]; \
|
||||
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
|
||||
\
|
||||
/* from this point: preserved by CPU reset */ \
|
||||
|
20
exec-all.h
20
exec-all.h
@ -98,9 +98,17 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
|
||||
void tb_invalidate_page_range(target_ulong start, target_ulong end);
|
||||
void tlb_flush_page(CPUState *env, target_ulong addr);
|
||||
void tlb_flush(CPUState *env, int flush_global);
|
||||
int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
target_phys_addr_t paddr, int prot,
|
||||
int is_user, int is_softmmu);
|
||||
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
|
||||
target_phys_addr_t paddr, int prot,
|
||||
int is_user, int is_softmmu);
|
||||
static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
target_phys_addr_t paddr, int prot,
|
||||
int is_user, int is_softmmu)
|
||||
{
|
||||
if (prot & PAGE_READ)
|
||||
prot |= PAGE_EXEC;
|
||||
return tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
|
||||
}
|
||||
|
||||
#define CODE_GEN_MAX_SIZE 65536
|
||||
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
|
||||
@ -554,15 +562,15 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
|
||||
#else
|
||||
#error unimplemented CPU
|
||||
#endif
|
||||
if (__builtin_expect(env->tlb_read[is_user][index].address !=
|
||||
if (__builtin_expect(env->tlb_table[is_user][index].addr_code !=
|
||||
(addr & TARGET_PAGE_MASK), 0)) {
|
||||
ldub_code(addr);
|
||||
}
|
||||
pd = env->tlb_read[is_user][index].address & ~TARGET_PAGE_MASK;
|
||||
pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
|
||||
if (pd > IO_MEM_ROM) {
|
||||
cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr);
|
||||
}
|
||||
return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base;
|
||||
return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
142
exec.c
142
exec.c
@ -1209,10 +1209,12 @@ void tlb_flush(CPUState *env, int flush_global)
|
||||
env->current_tb = NULL;
|
||||
|
||||
for(i = 0; i < CPU_TLB_SIZE; i++) {
|
||||
env->tlb_read[0][i].address = -1;
|
||||
env->tlb_write[0][i].address = -1;
|
||||
env->tlb_read[1][i].address = -1;
|
||||
env->tlb_write[1][i].address = -1;
|
||||
env->tlb_table[0][i].addr_read = -1;
|
||||
env->tlb_table[0][i].addr_write = -1;
|
||||
env->tlb_table[0][i].addr_code = -1;
|
||||
env->tlb_table[1][i].addr_read = -1;
|
||||
env->tlb_table[1][i].addr_write = -1;
|
||||
env->tlb_table[1][i].addr_code = -1;
|
||||
}
|
||||
|
||||
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
|
||||
@ -1230,9 +1232,16 @@ void tlb_flush(CPUState *env, int flush_global)
|
||||
|
||||
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
|
||||
{
|
||||
if (addr == (tlb_entry->address &
|
||||
(TARGET_PAGE_MASK | TLB_INVALID_MASK)))
|
||||
tlb_entry->address = -1;
|
||||
if (addr == (tlb_entry->addr_read &
|
||||
(TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
|
||||
addr == (tlb_entry->addr_write &
|
||||
(TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
|
||||
addr == (tlb_entry->addr_code &
|
||||
(TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
tlb_entry->addr_read = -1;
|
||||
tlb_entry->addr_write = -1;
|
||||
tlb_entry->addr_code = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void tlb_flush_page(CPUState *env, target_ulong addr)
|
||||
@ -1249,10 +1258,8 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
|
||||
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
tlb_flush_entry(&env->tlb_read[0][i], addr);
|
||||
tlb_flush_entry(&env->tlb_write[0][i], addr);
|
||||
tlb_flush_entry(&env->tlb_read[1][i], addr);
|
||||
tlb_flush_entry(&env->tlb_write[1][i], addr);
|
||||
tlb_flush_entry(&env->tlb_table[0][i], addr);
|
||||
tlb_flush_entry(&env->tlb_table[1][i], addr);
|
||||
|
||||
for(i = 0; i < TB_JMP_CACHE_SIZE; i++) {
|
||||
tb = env->tb_jmp_cache[i];
|
||||
@ -1295,10 +1302,10 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
|
||||
unsigned long start, unsigned long length)
|
||||
{
|
||||
unsigned long addr;
|
||||
if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
|
||||
addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
|
||||
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
|
||||
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
|
||||
if ((addr - start) < length) {
|
||||
tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
|
||||
tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1340,9 +1347,9 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
|
||||
start1 = start + (unsigned long)phys_ram_base;
|
||||
for(env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
for(i = 0; i < CPU_TLB_SIZE; i++)
|
||||
tlb_reset_dirty_range(&env->tlb_write[0][i], start1, length);
|
||||
tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
|
||||
for(i = 0; i < CPU_TLB_SIZE; i++)
|
||||
tlb_reset_dirty_range(&env->tlb_write[1][i], start1, length);
|
||||
tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SOFTMMU)
|
||||
@ -1378,11 +1385,11 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
|
||||
{
|
||||
ram_addr_t ram_addr;
|
||||
|
||||
if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
|
||||
ram_addr = (tlb_entry->address & TARGET_PAGE_MASK) +
|
||||
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
|
||||
ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
|
||||
tlb_entry->addend - (unsigned long)phys_ram_base;
|
||||
if (!cpu_physical_memory_is_dirty(ram_addr)) {
|
||||
tlb_entry->address |= IO_MEM_NOTDIRTY;
|
||||
tlb_entry->addr_write |= IO_MEM_NOTDIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1392,19 +1399,19 @@ void cpu_tlb_update_dirty(CPUState *env)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < CPU_TLB_SIZE; i++)
|
||||
tlb_update_dirty(&env->tlb_write[0][i]);
|
||||
tlb_update_dirty(&env->tlb_table[0][i]);
|
||||
for(i = 0; i < CPU_TLB_SIZE; i++)
|
||||
tlb_update_dirty(&env->tlb_write[1][i]);
|
||||
tlb_update_dirty(&env->tlb_table[1][i]);
|
||||
}
|
||||
|
||||
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry,
|
||||
unsigned long start)
|
||||
{
|
||||
unsigned long addr;
|
||||
if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
|
||||
addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
|
||||
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
|
||||
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
|
||||
if (addr == start) {
|
||||
tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_RAM;
|
||||
tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_RAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1418,17 +1425,17 @@ static inline void tlb_set_dirty(CPUState *env,
|
||||
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
tlb_set_dirty1(&env->tlb_write[0][i], addr);
|
||||
tlb_set_dirty1(&env->tlb_write[1][i], addr);
|
||||
tlb_set_dirty1(&env->tlb_table[0][i], addr);
|
||||
tlb_set_dirty1(&env->tlb_table[1][i], addr);
|
||||
}
|
||||
|
||||
/* add a new TLB entry. At most one entry for a given virtual address
|
||||
is permitted. Return 0 if OK or 2 if the page could not be mapped
|
||||
(can only happen in non SOFTMMU mode for I/O pages or pages
|
||||
conflicting with the host address space). */
|
||||
int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
target_phys_addr_t paddr, int prot,
|
||||
int is_user, int is_softmmu)
|
||||
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
|
||||
target_phys_addr_t paddr, int prot,
|
||||
int is_user, int is_softmmu)
|
||||
{
|
||||
PhysPageDesc *p;
|
||||
unsigned long pd;
|
||||
@ -1436,6 +1443,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
target_ulong address;
|
||||
target_phys_addr_t addend;
|
||||
int ret;
|
||||
CPUTLBEntry *te;
|
||||
|
||||
p = phys_page_find(paddr >> TARGET_PAGE_BITS);
|
||||
if (!p) {
|
||||
@ -1445,7 +1453,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
}
|
||||
#if defined(DEBUG_TLB)
|
||||
printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
|
||||
vaddr, paddr, prot, is_user, is_softmmu, pd);
|
||||
vaddr, (int)paddr, prot, is_user, is_softmmu, pd);
|
||||
#endif
|
||||
|
||||
ret = 0;
|
||||
@ -1465,29 +1473,30 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
|
||||
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
addend -= vaddr;
|
||||
te = &env->tlb_table[is_user][index];
|
||||
te->addend = addend;
|
||||
if (prot & PAGE_READ) {
|
||||
env->tlb_read[is_user][index].address = address;
|
||||
env->tlb_read[is_user][index].addend = addend;
|
||||
te->addr_read = address;
|
||||
} else {
|
||||
env->tlb_read[is_user][index].address = -1;
|
||||
env->tlb_read[is_user][index].addend = -1;
|
||||
te->addr_read = -1;
|
||||
}
|
||||
if (prot & PAGE_EXEC) {
|
||||
te->addr_code = address;
|
||||
} else {
|
||||
te->addr_code = -1;
|
||||
}
|
||||
if (prot & PAGE_WRITE) {
|
||||
if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
|
||||
/* ROM: access is ignored (same as unassigned) */
|
||||
env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM;
|
||||
env->tlb_write[is_user][index].addend = addend;
|
||||
te->addr_write = vaddr | IO_MEM_ROM;
|
||||
} else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
|
||||
!cpu_physical_memory_is_dirty(pd)) {
|
||||
env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY;
|
||||
env->tlb_write[is_user][index].addend = addend;
|
||||
te->addr_write = vaddr | IO_MEM_NOTDIRTY;
|
||||
} else {
|
||||
env->tlb_write[is_user][index].address = address;
|
||||
env->tlb_write[is_user][index].addend = addend;
|
||||
te->addr_write = address;
|
||||
}
|
||||
} else {
|
||||
env->tlb_write[is_user][index].address = -1;
|
||||
env->tlb_write[is_user][index].addend = -1;
|
||||
te->addr_write = -1;
|
||||
}
|
||||
}
|
||||
#if !defined(CONFIG_SOFTMMU)
|
||||
@ -1586,9 +1595,9 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
|
||||
{
|
||||
}
|
||||
|
||||
int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
target_phys_addr_t paddr, int prot,
|
||||
int is_user, int is_softmmu)
|
||||
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
|
||||
target_phys_addr_t paddr, int prot,
|
||||
int is_user, int is_softmmu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -2052,6 +2061,41 @@ uint32_t ldl_phys(target_phys_addr_t addr)
|
||||
return val;
|
||||
}
|
||||
|
||||
/* warning: addr must be aligned */
|
||||
uint64_t ldq_phys(target_phys_addr_t addr)
|
||||
{
|
||||
int io_index;
|
||||
uint8_t *ptr;
|
||||
uint64_t val;
|
||||
unsigned long pd;
|
||||
PhysPageDesc *p;
|
||||
|
||||
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
||||
if (!p) {
|
||||
pd = IO_MEM_UNASSIGNED;
|
||||
} else {
|
||||
pd = p->phys_offset;
|
||||
}
|
||||
|
||||
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
|
||||
/* I/O case */
|
||||
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
|
||||
val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
|
||||
#else
|
||||
val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
|
||||
val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
|
||||
#endif
|
||||
} else {
|
||||
/* RAM case */
|
||||
ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
|
||||
(addr & ~TARGET_PAGE_MASK);
|
||||
val = ldq_p(ptr);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/* XXX: optimize */
|
||||
uint32_t ldub_phys(target_phys_addr_t addr)
|
||||
{
|
||||
@ -2068,14 +2112,6 @@ uint32_t lduw_phys(target_phys_addr_t addr)
|
||||
return tswap16(val);
|
||||
}
|
||||
|
||||
/* XXX: optimize */
|
||||
uint64_t ldq_phys(target_phys_addr_t addr)
|
||||
{
|
||||
uint64_t val;
|
||||
cpu_physical_memory_read(addr, (uint8_t *)&val, 8);
|
||||
return tswap64(val);
|
||||
}
|
||||
|
||||
/* warning: addr must be aligned. The ram page is not masked as dirty
|
||||
and the code inside is not invalidated. It is useful if the dirty
|
||||
bits are used to track modified PTEs */
|
||||
|
@ -93,6 +93,11 @@
|
||||
#define RES_TYPE int
|
||||
#endif
|
||||
|
||||
#if ACCESS_TYPE == 3
|
||||
#define ADDR_READ addr_code
|
||||
#else
|
||||
#define ADDR_READ addr_read
|
||||
#endif
|
||||
|
||||
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
int is_user);
|
||||
@ -101,6 +106,8 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE
|
||||
#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
|
||||
(ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
|
||||
|
||||
#define CPU_TLB_ENTRY_BITS 4
|
||||
|
||||
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
{
|
||||
int res;
|
||||
@ -120,7 +127,7 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
"movl %%eax, %0\n"
|
||||
"jmp 2f\n"
|
||||
"1:\n"
|
||||
"addl 4(%%edx), %%eax\n"
|
||||
"addl 12(%%edx), %%eax\n"
|
||||
#if DATA_SIZE == 1
|
||||
"movzbl (%%eax), %0\n"
|
||||
#elif DATA_SIZE == 2
|
||||
@ -133,10 +140,10 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
"2:\n"
|
||||
: "=r" (res)
|
||||
: "r" (ptr),
|
||||
"i" ((CPU_TLB_SIZE - 1) << 3),
|
||||
"i" (TARGET_PAGE_BITS - 3),
|
||||
"i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
|
||||
"i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
|
||||
"i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
|
||||
"m" (*(uint32_t *)offsetof(CPUState, tlb_read[CPU_MEM_INDEX][0].address)),
|
||||
"m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
|
||||
"i" (CPU_MEM_INDEX),
|
||||
"m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
|
||||
: "%eax", "%ecx", "%edx", "memory", "cc");
|
||||
@ -169,7 +176,7 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
#endif
|
||||
"jmp 2f\n"
|
||||
"1:\n"
|
||||
"addl 4(%%edx), %%eax\n"
|
||||
"addl 12(%%edx), %%eax\n"
|
||||
#if DATA_SIZE == 1
|
||||
"movsbl (%%eax), %0\n"
|
||||
#elif DATA_SIZE == 2
|
||||
@ -180,10 +187,10 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
"2:\n"
|
||||
: "=r" (res)
|
||||
: "r" (ptr),
|
||||
"i" ((CPU_TLB_SIZE - 1) << 3),
|
||||
"i" (TARGET_PAGE_BITS - 3),
|
||||
"i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
|
||||
"i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
|
||||
"i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
|
||||
"m" (*(uint32_t *)offsetof(CPUState, tlb_read[CPU_MEM_INDEX][0].address)),
|
||||
"m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
|
||||
"i" (CPU_MEM_INDEX),
|
||||
"m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
|
||||
: "%eax", "%ecx", "%edx", "memory", "cc");
|
||||
@ -216,7 +223,7 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
|
||||
"popl %%eax\n"
|
||||
"jmp 2f\n"
|
||||
"1:\n"
|
||||
"addl 4(%%edx), %%eax\n"
|
||||
"addl 8(%%edx), %%eax\n"
|
||||
#if DATA_SIZE == 1
|
||||
"movb %b1, (%%eax)\n"
|
||||
#elif DATA_SIZE == 2
|
||||
@ -232,10 +239,10 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
|
||||
/* NOTE: 'q' would be needed as constraint, but we could not use it
|
||||
with T1 ! */
|
||||
"r" (v),
|
||||
"i" ((CPU_TLB_SIZE - 1) << 3),
|
||||
"i" (TARGET_PAGE_BITS - 3),
|
||||
"i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
|
||||
"i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
|
||||
"i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
|
||||
"m" (*(uint32_t *)offsetof(CPUState, tlb_write[CPU_MEM_INDEX][0].address)),
|
||||
"m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
|
||||
"i" (CPU_MEM_INDEX),
|
||||
"m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
|
||||
: "%eax", "%ecx", "%edx", "memory", "cc");
|
||||
@ -256,11 +263,11 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
addr = ptr;
|
||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
is_user = CPU_MEM_INDEX;
|
||||
if (__builtin_expect(env->tlb_read[is_user][index].address !=
|
||||
if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
||||
res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
|
||||
} else {
|
||||
physaddr = addr + env->tlb_read[is_user][index].addend;
|
||||
physaddr = addr + env->tlb_table[is_user][index].addend;
|
||||
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
|
||||
}
|
||||
return res;
|
||||
@ -277,17 +284,19 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
addr = ptr;
|
||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
is_user = CPU_MEM_INDEX;
|
||||
if (__builtin_expect(env->tlb_read[is_user][index].address !=
|
||||
if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
||||
res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
|
||||
} else {
|
||||
physaddr = addr + env->tlb_read[is_user][index].addend;
|
||||
physaddr = addr + env->tlb_table[is_user][index].addend;
|
||||
res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ACCESS_TYPE != 3
|
||||
|
||||
/* generic store macro */
|
||||
|
||||
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
|
||||
@ -300,16 +309,20 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
|
||||
addr = ptr;
|
||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
is_user = CPU_MEM_INDEX;
|
||||
if (__builtin_expect(env->tlb_write[is_user][index].address !=
|
||||
if (__builtin_expect(env->tlb_table[is_user][index].addr_write !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
|
||||
glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
|
||||
} else {
|
||||
physaddr = addr + env->tlb_write[is_user][index].addend;
|
||||
physaddr = addr + env->tlb_table[is_user][index].addend;
|
||||
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* ACCESS_TYPE != 3 */
|
||||
|
||||
#endif /* !asm */
|
||||
|
||||
#if ACCESS_TYPE != 3
|
||||
|
||||
#if DATA_SIZE == 8
|
||||
static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
|
||||
@ -355,6 +368,8 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
|
||||
}
|
||||
#endif /* DATA_SIZE == 4 */
|
||||
|
||||
#endif /* ACCESS_TYPE != 3 */
|
||||
|
||||
#undef RES_TYPE
|
||||
#undef DATA_TYPE
|
||||
#undef DATA_STYPE
|
||||
@ -363,3 +378,4 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
|
||||
#undef DATA_SIZE
|
||||
#undef CPU_MEM_INDEX
|
||||
#undef MMUSUFFIX
|
||||
#undef ADDR_READ
|
||||
|
@ -41,8 +41,10 @@
|
||||
|
||||
#ifdef SOFTMMU_CODE_ACCESS
|
||||
#define READ_ACCESS_TYPE 2
|
||||
#define ADDR_READ addr_code
|
||||
#else
|
||||
#define READ_ACCESS_TYPE 0
|
||||
#define ADDR_READ addr_read
|
||||
#endif
|
||||
|
||||
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
@ -83,9 +85,9 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
/* XXX: could done more in memory macro in a non portable way */
|
||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
redo:
|
||||
tlb_addr = env->tlb_read[is_user][index].address;
|
||||
tlb_addr = env->tlb_table[is_user][index].ADDR_READ;
|
||||
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
physaddr = addr + env->tlb_read[is_user][index].addend;
|
||||
physaddr = addr + env->tlb_table[is_user][index].addend;
|
||||
if (tlb_addr & ~TARGET_PAGE_MASK) {
|
||||
/* IO access */
|
||||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
@ -122,9 +124,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
|
||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
redo:
|
||||
tlb_addr = env->tlb_read[is_user][index].address;
|
||||
tlb_addr = env->tlb_table[is_user][index].ADDR_READ;
|
||||
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
physaddr = addr + env->tlb_read[is_user][index].addend;
|
||||
physaddr = addr + env->tlb_table[is_user][index].addend;
|
||||
if (tlb_addr & ~TARGET_PAGE_MASK) {
|
||||
/* IO access */
|
||||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
@ -199,9 +201,9 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
|
||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
redo:
|
||||
tlb_addr = env->tlb_write[is_user][index].address;
|
||||
tlb_addr = env->tlb_table[is_user][index].addr_write;
|
||||
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
physaddr = addr + env->tlb_write[is_user][index].addend;
|
||||
physaddr = addr + env->tlb_table[is_user][index].addend;
|
||||
if (tlb_addr & ~TARGET_PAGE_MASK) {
|
||||
/* IO access */
|
||||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
@ -237,9 +239,9 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
|
||||
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
redo:
|
||||
tlb_addr = env->tlb_write[is_user][index].address;
|
||||
tlb_addr = env->tlb_table[is_user][index].addr_write;
|
||||
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
physaddr = addr + env->tlb_write[is_user][index].addend;
|
||||
physaddr = addr + env->tlb_table[is_user][index].addend;
|
||||
if (tlb_addr & ~TARGET_PAGE_MASK) {
|
||||
/* IO access */
|
||||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
@ -276,3 +278,4 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
#undef SUFFIX
|
||||
#undef USUFFIX
|
||||
#undef DATA_SIZE
|
||||
#undef ADDR_READ
|
||||
|
Loading…
x
Reference in New Issue
Block a user