aboutsummaryrefslogtreecommitdiffstats
path: root/target-arm
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 (patch)
tree550ce922ea0e125ac6a9738210ce2939bf2fe901 /target-arm
parent413f05aaf54fa08c0ae7e997327a4f4a473c0a8d (diff)
downloadexternal_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.zip
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.gz
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.bz2
Initial Contribution
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/cpu.h14
-rw-r--r--target-arm/helper.c27
-rw-r--r--target-arm/op.c27
-rw-r--r--target-arm/op_helper.c126
-rw-r--r--target-arm/op_mem.h48
-rw-r--r--target-arm/translate.c181
6 files changed, 375 insertions, 48 deletions
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 <string.h>
+/*
+ * 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