extern FILE *logfile;
extern int loglevel;
+void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b);
+void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
+
int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
void *puc);
void cpu_resume_from_signal(CPUState *env1, void *puc);
void cpu_exec_init(CPUState *env);
-int page_unprotect(unsigned long address, unsigned long pc, void *puc);
+int page_unprotect(target_ulong address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
int is_cpu_write_access);
void tb_invalidate_page_range(target_ulong start, target_ulong end);
struct TranslationBlock *jmp_first;
} TranslationBlock;
+static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
+{
+ target_ulong tmp;
+ tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
+ return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK;
+}
+
static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
{
- return (pc ^ (pc >> TB_JMP_CACHE_BITS)) & (TB_JMP_CACHE_SIZE - 1);
+ target_ulong tmp;
+ tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
+ return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) |
+ (tmp & TB_JMP_ADDR_MASK));
}
static inline unsigned int tb_phys_hash_func(unsigned long pc)
"1:\n");\
} while (0)
+#elif defined(__s390__)
+/* GCC spills R13, so we have to restore it before branching away */
+
+#define GOTO_TB(opname, tbparam, n)\
+do {\
+ static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\
+ static void __attribute__((used)) *__op_label ## n \
+ __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
+ __asm__ __volatile__ ( \
+ "l %%r13,52(%%r15)\n" \
+ "br %0\n" \
+ : : "r" (((TranslationBlock*)tbparam)->tb_next[n]));\
+ \
+ for(;*((int*)0);); /* just to keep GCC busy */ \
+label ## n: ;\
+dummy_label ## n: ;\
+} while(0)
+
#else
/* jump to next block operations (more portable code, does not need
cache flushing, but slower because of indirect jump) */
#define GOTO_TB(opname, tbparam, n)\
do {\
- static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
- static void __attribute__((unused)) *__op_label ## n \
+ static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\
+ static void __attribute__((used)) *__op_label ## n \
__asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n: ;\
extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
-#ifdef __powerpc__
+#if defined(__powerpc__)
static inline int testandset (int *p)
{
int ret;
: "cr0", "memory");
return ret;
}
-#endif
-
-#ifdef __i386__
+#elif defined(__i386__)
static inline int testandset (int *p)
{
long int readval = 0;
: "cc");
return readval;
}
-#endif
-
-#ifdef __x86_64__
+#elif defined(__x86_64__)
static inline int testandset (int *p)
{
long int readval = 0;
: "cc");
return readval;
}
-#endif
-
-#ifdef __s390__
+#elif defined(__s390__)
static inline int testandset (int *p)
{
int ret;
: "cc", "memory" );
return ret;
}
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
static inline int testandset (int *p)
{
int ret;
: "m" (*p));
return ret;
}
-#endif
-
-#ifdef __sparc__
+#elif defined(__sparc__)
static inline int testandset (int *p)
{
int ret;
return (ret ? 1 : 0);
}
-#endif
-
-#ifdef __arm__
+#elif defined(__arm__)
static inline int testandset (int *spinlock)
{
register unsigned int ret;
return ret;
}
-#endif
-
-#ifdef __mc68000
+#elif defined(__mc68000)
static inline int testandset (int *p)
{
char ret;
: "cc","memory");
return ret;
}
-#endif
+#elif defined(__ia64)
-#ifdef __ia64
#include <ia64intrin.h>
static inline int testandset (int *p)
{
return __sync_lock_test_and_set (p, 1);
}
+#elif defined(__mips__)
+static inline int testandset (int *p)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set noat \n"
+ " .set mips2 \n"
+ "1: li $1, 1 \n"
+ " ll %0, %1 \n"
+ " sc $1, %1 \n"
+ " beqz $1, 1b \n"
+ " .set pop "
+ : "=r" (ret), "+R" (*p)
+ :
+ : "memory");
+
+ return ret;
+}
+#else
+#error unimplemented CPU support
#endif
typedef int spinlock_t;
is_user = (env->psrs == 0);
#elif defined (TARGET_ARM)
is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
+#elif defined (TARGET_SH4)
+ is_user = ((env->sr & SR_MD) == 0);
+#elif defined (TARGET_ALPHA)
+ is_user = ((env->ps >> 3) & 3);
+#elif defined (TARGET_M68K)
+ is_user = ((env->sr & SR_S) == 0);
#else
#error unimplemented CPU
#endif
ldub_code(addr);
}
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);
+ if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
+#ifdef TARGET_SPARC
+ do_unassigned_access(addr, 0, 1, 0);
+#else
+ cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
+#endif
}
return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
}
#endif
-
#ifdef USE_KQEMU
+#define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
+
int kqemu_init(CPUState *env);
int kqemu_cpu_exec(CPUState *env);
void kqemu_flush_page(CPUState *env, target_ulong addr);
void kqemu_flush(CPUState *env, int global);
void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
+void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr);
void kqemu_cpu_interrupt(CPUState *env);
+void kqemu_record_dump(void);
static inline int kqemu_is_ok(CPUState *env)
{
return(env->kqemu_enabled &&
- (env->hflags & HF_CPL_MASK) == 3 &&
- (env->eflags & IOPL_MASK) != IOPL_MASK &&
(env->cr[0] & CR0_PE_MASK) &&
+ !(env->hflags & HF_INHIBIT_IRQ_MASK) &&
(env->eflags & IF_MASK) &&
- !(env->eflags & VM_MASK));
+ !(env->eflags & VM_MASK) &&
+ (env->kqemu_enabled == 2 ||
+ ((env->hflags & HF_CPL_MASK) == 3 &&
+ (env->eflags & IOPL_MASK) != IOPL_MASK)));
}
#endif