From 55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 21 Oct 2008 07:00:00 -0700 Subject: Initial Contribution --- target-arm/cpu.h | 14 ++-- target-arm/helper.c | 27 ++++---- target-arm/op.c | 27 ++++++++ target-arm/op_helper.c | 126 ++++++++++++++++++++++++++++++++++ target-arm/op_mem.h | 48 +++++++++++++ target-arm/translate.c | 181 +++++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 375 insertions(+), 48 deletions(-) (limited to 'target-arm') diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 75a1f13..a613b77 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1,6 +1,6 @@ /* * ARM virtual CPU header - * + * * Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -26,6 +26,8 @@ #include "softfloat.h" +#define ARM_CPU_SAVE_VERSION 1 + #define TARGET_HAS_ICE 1 #define EXCP_UDEF 1 /* undefined instruction */ @@ -57,11 +59,11 @@ typedef struct CPUARMState { uint32_t banked_spsr[6]; uint32_t banked_r13[6]; uint32_t banked_r14[6]; - + /* These hold r8-r12. */ uint32_t usr_regs[5]; uint32_t fiq_regs[5]; - + /* cpsr flag cache for faster execution */ uint32_t CF; /* 0 or 1 */ uint32_t VF; /* V is the bit 31. All other bits are undefined */ @@ -109,7 +111,7 @@ typedef struct CPUARMState { /* Temporary variables if we don't have spare fp regs. */ float32 tmp0s, tmp1s; float64 tmp0d, tmp1d; - + float_status fp_status; } vfp; @@ -132,7 +134,7 @@ void switch_mode(CPUARMState *, int); signal handlers to inform the virtual CPU of exceptions. non zero is returned if the signal was handled by the virtual CPU. */ struct siginfo; -int cpu_arm_signal_handler(int host_signum, struct siginfo *info, +int cpu_arm_signal_handler(int host_signum, struct siginfo *info, void *puc); #define CPSR_M (0x1f) @@ -154,7 +156,7 @@ static inline uint32_t cpsr_read(CPUARMState *env) { int ZF; ZF = (env->NZF == 0); - return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) | + return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) | (env->thumb << 5); } diff --git a/target-arm/helper.c b/target-arm/helper.c index 2ed46a2..b78f7d1 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -4,6 +4,9 @@ #include "cpu.h" #include "exec-all.h" +#ifdef CONFIG_TRACE +#include "trace.h" +#endif void cpu_reset(CPUARMState *env) { @@ -60,7 +63,7 @@ void cpu_arm_close(CPUARMState *env) free(env); } -#if defined(CONFIG_USER_ONLY) +#if defined(CONFIG_USER_ONLY) void do_interrupt (CPUState *env) { @@ -163,6 +166,11 @@ void do_interrupt(CPUARMState *env) int new_mode; uint32_t offset; +#ifdef CONFIG_TRACE + if (tracing) + trace_exception(env->regs[15]); +#endif + /* TODO: Vectored interrupt controller. */ switch (env->exception_index) { case EXCP_UDEF: @@ -239,7 +247,7 @@ static inline int check_ap(CPUState *env, int ap, int domain, int access_type, switch (ap) { case 0: - if (access_type != 1) + if (access_type == 1) return 0; switch ((env->cp15.c1_sys >> 8) & 3) { case 1: @@ -420,6 +428,7 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val) break; case 3: /* MMU Domain access control. */ env->cp15.c3 = val; + tlb_flush(env, 1); break; case 4: /* Reserved. */ goto bad_reg; @@ -466,7 +475,7 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val) tlb_flush_page(env, val + 0x800); tlb_flush_page(env, val + 0xc00); #else - tlb_flush(env, 1); + //tlb_flush(env, 1); #endif break; default: @@ -494,18 +503,10 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val) case 13: /* Process ID. */ switch (op2) { case 0: - /* Unlike real hardware the qemu TLB uses virtual addresses, - not modified virtual addresses, so this causes a TLB flush. - */ - if (env->cp15.c13_fcse != val) - tlb_flush(env, 1); - env->cp15.c13_fcse = val; + env->cp15.c9_data = val; break; case 1: - /* This changes the ASID, so do a TLB flush. */ - if (env->cp15.c13_context != val) - tlb_flush(env, 0); - env->cp15.c13_context = val; + env->cp15.c9_insn = val; break; default: goto bad_reg; diff --git a/target-arm/op.c b/target-arm/op.c index f17b812..48a81de 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -19,6 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "exec.h" +#ifdef GEN_TRACE +#include "trace.h" +#endif #define REGNAME r0 #define REG (env->regs[0]) @@ -85,6 +88,30 @@ #define SET_REG(x) REG = x & ~(uint32_t)1 #include "op_template.h" +#ifdef GEN_TRACE +void OPPROTO op_shutdown(void) +{ + extern void qemu_system_shutdown_request(void); + qemu_system_shutdown_request(); + EXIT_TB(); +} + +void OPPROTO op_trace_bb(void) +{ + trace_bb_helper(PARAM1, (TranslationBlock *)PARAM2); +} + +void OPPROTO op_trace_insn(void) +{ + trace_insn_helper(); +} + +void OPPROTO op_add_to_sim_time(void) +{ + sim_time += PARAM1; +} +#endif + void OPPROTO op_bx_T0(void) { env->regs[15] = T0 & ~(uint32_t)1; diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index af5c61d..acc83ba 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -177,8 +177,11 @@ void do_vfp_get_fpscr(void) #if !defined(CONFIG_USER_ONLY) +static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr); + #define MMUSUFFIX _mmu #define GETPC() (__builtin_return_address(0)) +#define ALIGNED_ONLY 1 #define SHIFT 0 #include "softmmu_template.h" @@ -192,6 +195,19 @@ void do_vfp_get_fpscr(void) #define SHIFT 3 #include "softmmu_template.h" +static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr) +{ + //printf("::UNALIGNED:: addr=%lx is_write=%d is_user=%d retaddr=%p\n", addr, is_write, is_user, retaddr); + if (is_user) + { + env = cpu_single_env; + env->cp15.c5_data = 0x00000001; /* corresponds to an alignment fault */ + env->cp15.c6_data = addr; + env->exception_index = EXCP_DATA_ABORT; + cpu_loop_exit(); + } +} + /* 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) */ @@ -224,4 +240,114 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) env = saved_env; } +#if 1 +#include +/* + * The following functions are address translation helper functions + * for fast memory access in QEMU. + */ +static unsigned long v2p_mmu(target_ulong addr, int is_user) +{ + int index; + target_ulong tlb_addr; + target_phys_addr_t physaddr; + void *retaddr; + + index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); +redo: + 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_table[is_user][index].addend; + } else { + /* the page is not in the TLB : fill it */ + retaddr = GETPC(); + tlb_fill(addr, 0, is_user, retaddr); + goto redo; + } + return physaddr; +} + +/* + * translation from virtual address of simulated OS + * to the address of simulation host (not the physical + * address of simulated OS. + */ +unsigned long v2p(target_ulong ptr, int is_user) +{ + CPUState *saved_env; + int index; + target_ulong addr; + unsigned long physaddr; + + saved_env = env; + env = cpu_single_env; + addr = ptr; + index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); + if (__builtin_expect(env->tlb_table[is_user][index].addr_read != + (addr & TARGET_PAGE_MASK), 0)) { + return v2p_mmu(addr, is_user); + } else { + physaddr = addr + env->tlb_table[is_user][index].addend; + } + env = saved_env; + return physaddr; +} + +#define MINSIZE(x,y) ((x) < (y) ? (x) : (y)) +/* copy memory from the simulated virtual space to a buffer in QEMU */ +void vmemcpy(target_ulong ptr, char *buf, int size) +{ + if (buf == NULL) return; + while (size) { + int page_remain = TARGET_PAGE_SIZE - (ptr & ~TARGET_PAGE_MASK); + int to_copy = MINSIZE(size, page_remain); + char *phys = (char *)v2p(ptr, 0); + if (phys == NULL) return; + memcpy(buf, phys, to_copy); + ptr += to_copy; + buf += to_copy; + size -= to_copy; + } +} + +/* copy memory from the QEMU buffer to simulated virtual space */ +void pmemcpy(target_ulong ptr, char *buf, int size) +{ + if (buf == NULL) return; + while (size) { + int page_remain = TARGET_PAGE_SIZE - (ptr & ~TARGET_PAGE_MASK); + int to_copy = MINSIZE(size, page_remain); + char *phys = (char *)v2p(ptr, 0); + if (phys == NULL) return; + memcpy(phys, buf, to_copy); + ptr += to_copy; + buf += to_copy; + size -= to_copy; + } +} + +/* copy a string from the simulated virtual space to a buffer in QEMU */ +void vstrcpy(target_ulong ptr, char *buf, int max) +{ + char *phys = 0; + unsigned long page = 0; + + if (buf == NULL) return; + + while (max) { + if ((ptr & TARGET_PAGE_MASK) != page) { + phys = (char *)v2p(ptr, 0); + page = ptr & TARGET_PAGE_MASK; + } + *buf = *phys; + if (*phys == '\0') + return; + ptr ++; + buf ++; + phys ++; + max --; + } +} +#endif + #endif diff --git a/target-arm/op_mem.h b/target-arm/op_mem.h index 29fd85b..9d4d5c0 100644 --- a/target-arm/op_mem.h +++ b/target-arm/op_mem.h @@ -1,12 +1,26 @@ /* ARM memory operations. */ +#ifdef GEN_TRACE /* Load from address T1 into T0. */ #define MEM_LD_OP(name) \ void OPPROTO glue(op_ld##name,MEMSUFFIX)(void) \ { \ + extern int tracing; \ + extern void dcache_load(uint32_t addr); \ + if (tracing) \ + dcache_load(T1); \ T0 = glue(ld##name,MEMSUFFIX)(T1); \ FORCE_RET(); \ } +#else +/* Load from address T1 into T0. */ +#define MEM_LD_OP(name) \ +void OPPROTO glue(op_ld##name,MEMSUFFIX)(void) \ +{ \ + T0 = glue(ld##name,MEMSUFFIX)(T1); \ + FORCE_RET(); \ +} +#endif MEM_LD_OP(ub) MEM_LD_OP(sb) @@ -16,6 +30,19 @@ MEM_LD_OP(l) #undef MEM_LD_OP +#ifdef GEN_TRACE +/* Store T0 to address T1. */ +#define MEM_ST_OP(name) \ +void OPPROTO glue(op_st##name,MEMSUFFIX)(void) \ +{ \ + extern int tracing; \ + extern void dcache_store(uint32_t addr, uint32_t val); \ + if (tracing) \ + dcache_store(T1, T0); \ + glue(st##name,MEMSUFFIX)(T1, T0); \ + FORCE_RET(); \ +} +#else /* Store T0 to address T1. */ #define MEM_ST_OP(name) \ void OPPROTO glue(op_st##name,MEMSUFFIX)(void) \ @@ -23,6 +50,7 @@ void OPPROTO glue(op_st##name,MEMSUFFIX)(void) \ glue(st##name,MEMSUFFIX)(T1, T0); \ FORCE_RET(); \ } +#endif MEM_ST_OP(b) MEM_ST_OP(w) @@ -30,6 +58,25 @@ MEM_ST_OP(l) #undef MEM_ST_OP +#ifdef GEN_TRACE +/* Swap T0 with memory at address T1. */ +/* ??? Is this exception safe? */ +#define MEM_SWP_OP(name, lname) \ +void OPPROTO glue(op_swp##name,MEMSUFFIX)(void) \ +{ \ + extern int tracing; \ + extern void dcache_swp(uint32_t addr); \ + uint32_t tmp; \ + cpu_lock(); \ + if (tracing) \ + dcache_swp(T1); \ + tmp = glue(ld##lname,MEMSUFFIX)(T1); \ + glue(st##name,MEMSUFFIX)(T1, T0); \ + T0 = tmp; \ + cpu_unlock(); \ + FORCE_RET(); \ +} +#else /* Swap T0 with memory at address T1. */ /* ??? Is this exception safe? */ #define MEM_SWP_OP(name, lname) \ @@ -43,6 +90,7 @@ void OPPROTO glue(op_swp##name,MEMSUFFIX)(void) \ cpu_unlock(); \ FORCE_RET(); \ } +#endif MEM_SWP_OP(b, ub) MEM_SWP_OP(l, l) diff --git a/target-arm/translate.c b/target-arm/translate.c index fa7ad60..663a730 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -1,6 +1,6 @@ /* * ARM translation - * + * * Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2005 CodeSourcery, LLC * @@ -27,6 +27,14 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#ifdef GEN_TRACE +#include "trace.h" +#endif + +typedef int (*gen_intermediate_code_func)(CPUState *env, struct TranslationBlock *tb); + +extern gen_intermediate_code_func _gen_intermediate_code; +extern gen_intermediate_code_func _gen_intermediate_code_pc; #define ENABLE_ARCH_5J 0 #define ENABLE_ARCH_6 1 @@ -72,12 +80,20 @@ extern int loglevel; enum { #define DEF(s, n, copy_size) INDEX_op_ ## s, +#ifdef GEN_TRACE +#include "opc-trace.h" +#else #include "opc.h" +#endif #undef DEF NB_OPS, }; +#ifdef GEN_TRACE +#include "gen-op-trace.h" +#else #include "gen-op.h" +#endif static GenOpFunc1 *gen_test_cc[14] = { gen_op_test_eq, @@ -96,7 +112,7 @@ static GenOpFunc1 *gen_test_cc[14] = { gen_op_test_le, }; -const uint8_t table_logic_cc[16] = { +static const uint8_t table_logic_cc[16] = { 1, /* and */ 1, /* xor */ 0, /* sub */ @@ -114,7 +130,7 @@ const uint8_t table_logic_cc[16] = { 1, /* bic */ 1, /* mvn */ }; - + static GenOpFunc1 *gen_shift_T1_im[4] = { gen_op_shll_T1_im, gen_op_shrl_T1_im, @@ -387,13 +403,13 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, int extra) { int val, rm; - + if (insn & (1 << 22)) { /* immediate */ val = (insn & 0xf) | ((insn >> 4) & 0xf0); - val += extra; if (!(insn & (1 << 23))) val = -val; + val += extra; if (val != 0) gen_op_addl_T1_im(val); } else { @@ -687,7 +703,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) delta_m = 0; delta_d = 0; bank_mask = 0; - + if (veclen > 0) { if (dp) bank_mask = 0xc; @@ -1108,12 +1124,26 @@ static void gen_exception_return(DisasContext *s) static void disas_arm_insn(CPUState * env, DisasContext *s) { unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; - +#ifdef GEN_TRACE + int insn_ticks = 0; +#endif + insn = ldl_code(s->pc); +#ifdef GEN_TRACE + if (tracing) { + trace_add_insn(insn, 0 /* not thumb */); + insn_ticks = get_insn_ticks(insn); + gen_op_trace_insn(); + } +#endif s->pc += 4; - + cond = insn >> 28; if (cond == 0xf){ +#ifdef GEN_TRACE + if (tracing) + gen_op_add_to_sim_time(insn_ticks); +#endif /* Unconditional instructions. */ if ((insn & 0x0d70f000) == 0x0550f000) return; /* PLD */ @@ -1150,6 +1180,13 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) goto illegal_op; } if (cond != 0xe) { +#ifdef GEN_TRACE + if (tracing) { + /* a non-executed conditional instruction takes only 1 cycle */ + gen_op_add_to_sim_time(1); + insn_ticks -= 1; + } +#endif /* if not always execute, we generate a conditional jump to next instruction */ s->condlabel = gen_new_label(); @@ -1158,6 +1195,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); //s->is_jmp = DISAS_JUMP_NEXT; } +#ifdef GEN_TRACE + if (tracing) + gen_op_add_to_sim_time(insn_ticks); +#endif if ((insn & 0x0f900000) == 0x03000000) { if ((insn & 0x0fb0f000) != 0x0320f000) goto illegal_op; @@ -1299,7 +1340,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) (insn & 0x00000090) != 0x90) || ((insn & 0x0e000000) == (1 << 25))) { int set_cc, logic_cc, shiftop; - + op1 = (insn >> 21) & 0xf; set_cc = (insn >> 20) & 1; logic_cc = table_logic_cc[op1] & set_cc; @@ -1490,14 +1531,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_movl_T1_reg(s, rn); gen_op_addl_T0_T1(); } - if (insn & (1 << 20)) + if (insn & (1 << 20)) gen_op_logic_T0_cc(); gen_movl_reg_T0(s, rd); } else { /* 64 bit mul */ gen_movl_T0_reg(s, rs); gen_movl_T1_reg(s, rm); - if (insn & (1 << 22)) + if (insn & (1 << 22)) gen_op_imull_T0_T1(); else gen_op_mull_T0_T1(); @@ -1508,7 +1549,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_op_addq_lo_T0_T1(rn); gen_op_addq_lo_T0_T1(rd); } - if (insn & (1 << 20)) + if (insn & (1 << 20)) gen_op_logicq_cc(); gen_movl_reg_T0(s, rn); gen_movl_reg_T1(s, rd); @@ -1522,7 +1563,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } else { /* SWP instruction */ rm = (insn) & 0xf; - + gen_movl_T0_reg(s, rm); gen_movl_T1_reg(s, rn); if (insn & (1 << 22)) { @@ -1594,6 +1635,18 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) case 0x5: case 0x6: case 0x7: +#ifdef GEN_TRACE + /* Added a special undefined instruction to cause the + * simulator to exit. This allows us to write short assembly + * language tests that can exit the simulator. + */ +#define EXIT_SIMULATION 0xe6c00110 + if (insn == EXIT_SIMULATION) { + gen_op_shutdown(); + break; + } +#endif + /* Check for undefined extension instructions * per the ARM Bible IE: * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx @@ -1679,7 +1732,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } rn = (insn >> 16) & 0xf; gen_movl_T1_reg(s, rn); - + /* compute total size */ loaded_base = 0; n = 0; @@ -1724,8 +1777,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } else { /* store */ if (i == 15) { - /* special case: r15 = PC + 12 */ - val = (long)s->pc + 8; + /* special case: r15 = PC + 8 (was 12) */ + val = (long)s->pc + 4; gen_op_movl_TN_im[0](val); } else if (user) { gen_op_movl_T0_user(i); @@ -1777,7 +1830,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) case 0xb: { int32_t offset; - + /* branch (and link) */ val = (int32_t)s->pc; if (insn & (1 << 24)) { @@ -1834,6 +1887,16 @@ static void disas_thumb_insn(DisasContext *s) int i; insn = lduw_code(s->pc); +#ifdef GEN_TRACE + if (tracing) { + int insn_ticks; + + trace_add_insn( insn_wrap_thumb(insn), 1 /* thumb insn */ ); + insn_ticks = get_insn_ticks_thumb(insn); + gen_op_trace_insn(); + gen_op_add_to_sim_time(insn_ticks); + } +#endif s->pc += 2; switch (insn >> 12) { @@ -2357,12 +2420,22 @@ static void disas_thumb_insn(DisasContext *s) } offset = ((int32_t)insn << 21) >> 10; insn = lduw_code(s->pc); +#ifdef GEN_TRACE + if (tracing) { + int insn_ticks; + + trace_add_insn( insn_wrap_thumb(insn), 1 /* thumb insn */ ); + insn_ticks = get_insn_ticks_thumb(insn); + gen_op_trace_insn(); + gen_op_add_to_sim_time(insn_ticks); + } +#endif offset |= insn & 0x7ff; val = (uint32_t)s->pc + 2; gen_op_movl_T1_im(val | 1); gen_movl_reg_T1(s, 14); - + val += offset << 1; if (insn & (1 << 12)) { /* bl */ @@ -2385,8 +2458,8 @@ undef: /* generate intermediate code in gen_opc_buf and gen_opparam_buf for basic block 'tb'. If search_pc is TRUE, also generate PC information for each intermediate instruction. */ -static inline int gen_intermediate_code_internal(CPUState *env, - TranslationBlock *tb, +static inline int gen_intermediate_code_internal(CPUState *env, + TranslationBlock *tb, int search_pc) { DisasContext dc1, *dc = &dc1; @@ -2394,10 +2467,10 @@ static inline int gen_intermediate_code_internal(CPUState *env, int j, lj; target_ulong pc_start; uint32_t next_page_start; - + /* generate intermediate code */ pc_start = tb->pc; - + dc->tb = tb; gen_opc_ptr = gen_opc_buf; @@ -2415,6 +2488,12 @@ static inline int gen_intermediate_code_internal(CPUState *env, next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; nb_gen_labels = 0; lj = -1; +#ifdef GEN_TRACE + if (tracing) { + gen_op_trace_bb(trace_static.bb_num, (long) tb); + trace_bb_start(dc->pc); + } +#endif do { if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { @@ -2454,6 +2533,12 @@ static inline int gen_intermediate_code_internal(CPUState *env, } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && !env->singlestep_enabled && dc->pc < next_page_start); +#ifdef GEN_TRACE + if (tracing) { + trace_bb_end(); + } +#endif + /* At this stage dc->condjmp will only be set when the skipped * instruction was a conditional branch, and the PC has already been * written. */ @@ -2518,21 +2603,58 @@ static inline int gen_intermediate_code_internal(CPUState *env, return 0; } -int gen_intermediate_code(CPUState *env, TranslationBlock *tb) +#if defined(GEN_TRACE) +static int trace_gen_intermediate_code(CPUState *env, TranslationBlock *tb) { return gen_intermediate_code_internal(env, tb, 0); } -int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) +static int trace_gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) +{ + return gen_intermediate_code_internal(env, tb, 1); +} + +void qemu_trace_enable(void) +{ + _gen_intermediate_code = trace_gen_intermediate_code; + _gen_intermediate_code_pc = trace_gen_intermediate_code_pc; +} +#else + +static int default_gen_intermediate_code(CPUState *env, TranslationBlock *tb) +{ + return gen_intermediate_code_internal(env, tb, 0); +} + +static int default_gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) { return gen_intermediate_code_internal(env, tb, 1); } -static const char *cpu_mode_names[16] = { +gen_intermediate_code_func _gen_intermediate_code = default_gen_intermediate_code; +gen_intermediate_code_func _gen_intermediate_code_pc = default_gen_intermediate_code_pc; + +int gen_intermediate_code(CPUState *env, TranslationBlock *tb) +{ + return (*_gen_intermediate_code)(env, tb); +} + +int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) +{ + return (*_gen_intermediate_code_pc)(env, tb); +} + +void qemu_trace_disable( void ) +{ + _gen_intermediate_code = default_gen_intermediate_code; + _gen_intermediate_code_pc = default_gen_intermediate_code_pc; +} + +static const char * const cpu_mode_names[16] = { "usr", "fiq", "irq", "svc", "???", "???", "???", "abt", "???", "???", "???", "und", "???", "???", "???", "sys" }; -void cpu_dump_state(CPUState *env, FILE *f, +void cpu_dump_state(CPUState *env, FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...), int flags) { @@ -2552,13 +2674,13 @@ void cpu_dump_state(CPUState *env, FILE *f, cpu_fprintf(f, " "); } psr = cpsr_read(env); - cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d %x\n", - psr, + cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d %x\n", + psr, psr & (1 << 31) ? 'N' : '-', psr & (1 << 30) ? 'Z' : '-', psr & (1 << 29) ? 'C' : '-', psr & (1 << 28) ? 'V' : '-', - psr & CPSR_T ? 'T' : 'A', + psr & CPSR_T ? 'T' : 'A', cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26); for (i = 0; i < 16; i++) { @@ -2574,3 +2696,4 @@ void cpu_dump_state(CPUState *env, FILE *f, cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); } +#endif -- cgit v1.1