/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS
+/* Page tracking code uses ram addresses in system mode, and virtual
+ addresses in userspace mode. Define tb_page_addr_t to be an appropriate
+ type. */
+#if defined(CONFIG_USER_ONLY)
+typedef abi_ulong tb_page_addr_t;
+#else
+typedef ram_addr_t tb_page_addr_t;
+#endif
+
/* is_jmp field values */
#define DISAS_NEXT 0 /* next instruction can be analyzed */
#define DISAS_JUMP 1 /* only pc was modified dynamically */
typedef struct TranslationBlock TranslationBlock;
/* XXX: make safe guess about sizes */
-#define MAX_OP_PER_INSTR 64
+#define MAX_OP_PER_INSTR 96
/* A Call op needs up to 6 + 2N parameters (N = number of arguments). */
#define MAX_OPC_PARAM 10
-#define OPC_BUF_SIZE 512
+#define OPC_BUF_SIZE 640
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
/* Maximum size a TCG op can expand to. This is complicated because a
- single op may require several host instructions and regirster reloads.
- For now take a wild guess at 128 bytes, which should allow at least
+ single op may require several host instructions and register reloads.
+ For now take a wild guess at 192 bytes, which should allow at least
a couple of fixup instructions per argument. */
-#define TCG_MAX_OP_SIZE 128
+#define TCG_MAX_OP_SIZE 192
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)
void cpu_exec_init(CPUState *env);
void QEMU_NORETURN cpu_loop_exit(void);
int page_unprotect(target_ulong address, unsigned long pc, void *puc);
-void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access);
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);
+#if !defined(CONFIG_USER_ONLY)
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
int mmu_idx, int is_softmmu);
prot |= PAGE_EXEC;
return tlb_set_page_exec(env1, vaddr, paddr, prot, mmu_idx, is_softmmu);
}
+#endif
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
/* first and second physical page containing code. The lower bit
of the pointer tells the index in page_next[] */
struct TranslationBlock *page_next[2];
- target_ulong page_addr[2];
+ tb_page_addr_t page_addr[2];
/* the following data are used to directly call another TB from
the code of this one. */
| (tmp & TB_JMP_ADDR_MASK));
}
-static inline unsigned int tb_phys_hash_func(unsigned long pc)
+static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
{
return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
}
TranslationBlock *tb_alloc(target_ulong pc);
void tb_free(TranslationBlock *tb);
void tb_flush(CPUState *env);
-void tb_link_phys(TranslationBlock *tb,
- target_ulong phys_pc, target_ulong phys_page2);
-void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr);
+void tb_link_page(TranslationBlock *tb,
+ tb_page_addr_t phys_pc, tb_page_addr_t phys_page2);
+void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
extern uint8_t *code_gen_ptr;
#endif
/* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
- *(uint32_t *)jmp_addr |= ((addr - (jmp_addr + 8)) >> 2) & 0xffffff;
+ *(uint32_t *)jmp_addr =
+ (*(uint32_t *)jmp_addr & ~0xffffff)
+ | (((addr - (jmp_addr + 8)) >> 2) & 0xffffff);
#if QEMU_GNUC_PREREQ(4, 1)
__clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
TranslationBlock *tb_find_pc(unsigned long pc_ptr);
-extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
-extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
-extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
-
#include "qemu-lock.h"
extern spinlock_t tb_lock;
#if !defined(CONFIG_USER_ONLY)
+extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
+extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
+
void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
void *retaddr);
#endif
#if defined(CONFIG_USER_ONLY)
-static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
+static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
{
return addr;
}
/* NOTE: this function can trigger an exception */
/* NOTE2: the returned address is not exactly the physical address: it
is the offset relative to phys_ram_base */
-static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
+static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
{
int mmu_idx, page_index, pd;
void *p;