mirror of https://gitee.com/openkylin/qemu.git
ARM singlestep support (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1384 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
a4f81979e8
commit
8aaca4c0b4
|
@ -33,6 +33,7 @@ typedef struct DisasContext {
|
||||||
target_ulong pc;
|
target_ulong pc;
|
||||||
int is_jmp;
|
int is_jmp;
|
||||||
struct TranslationBlock *tb;
|
struct TranslationBlock *tb;
|
||||||
|
int singlestep_enabled;
|
||||||
} DisasContext;
|
} DisasContext;
|
||||||
|
|
||||||
#define DISAS_JUMP_NEXT 4
|
#define DISAS_JUMP_NEXT 4
|
||||||
|
@ -888,6 +889,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void gen_jmp (DisasContext *s, uint32_t dest)
|
||||||
|
{
|
||||||
|
if (__builtin_expect(s->singlestep_enabled, 0)) {
|
||||||
|
/* An indirect jump so that we still trigger the debug exception. */
|
||||||
|
gen_op_movl_T0_im(dest);
|
||||||
|
gen_bx(s);
|
||||||
|
} else {
|
||||||
|
gen_op_jmp((long)s->tb, dest);
|
||||||
|
s->is_jmp = DISAS_TB_JUMP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void disas_arm_insn(CPUState * env, DisasContext *s)
|
static void disas_arm_insn(CPUState * env, DisasContext *s)
|
||||||
{
|
{
|
||||||
unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
|
unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
|
||||||
|
@ -1469,8 +1482,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
|
||||||
}
|
}
|
||||||
offset = (((int32_t)insn << 8) >> 8);
|
offset = (((int32_t)insn << 8) >> 8);
|
||||||
val += (offset << 2) + 4;
|
val += (offset << 2) + 4;
|
||||||
gen_op_jmp((long)s->tb, val);
|
gen_jmp(s, val);
|
||||||
s->is_jmp = DISAS_TB_JUMP;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xc:
|
case 0xc:
|
||||||
|
@ -1957,8 +1969,7 @@ static void disas_thumb_insn(DisasContext *s)
|
||||||
val = (uint32_t)s->pc;
|
val = (uint32_t)s->pc;
|
||||||
offset = ((int32_t)insn << 24) >> 24;
|
offset = ((int32_t)insn << 24) >> 24;
|
||||||
val += (offset << 1) + 2;
|
val += (offset << 1) + 2;
|
||||||
gen_op_jmp((long)s->tb, val);
|
gen_jmp(s, val);
|
||||||
s->is_jmp = DISAS_TB_JUMP;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 14:
|
case 14:
|
||||||
|
@ -1968,8 +1979,7 @@ static void disas_thumb_insn(DisasContext *s)
|
||||||
val = (uint32_t)s->pc;
|
val = (uint32_t)s->pc;
|
||||||
offset = ((int32_t)insn << 21) >> 21;
|
offset = ((int32_t)insn << 21) >> 21;
|
||||||
val += (offset << 1) + 2;
|
val += (offset << 1) + 2;
|
||||||
gen_op_jmp((long)s->tb, val);
|
gen_jmp(s, val);
|
||||||
s->is_jmp = DISAS_TB_JUMP;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 15:
|
case 15:
|
||||||
|
@ -1985,8 +1995,7 @@ static void disas_thumb_insn(DisasContext *s)
|
||||||
val += offset;
|
val += offset;
|
||||||
if (insn & (1 << 11)) {
|
if (insn & (1 << 11)) {
|
||||||
/* bl */
|
/* bl */
|
||||||
gen_op_jmp((long)s->tb, val);
|
gen_jmp(s, val);
|
||||||
s->is_jmp = DISAS_TB_JUMP;
|
|
||||||
} else {
|
} else {
|
||||||
/* blx */
|
/* blx */
|
||||||
gen_op_movl_T0_im(val);
|
gen_op_movl_T0_im(val);
|
||||||
|
@ -2024,6 +2033,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
|
||||||
|
|
||||||
dc->is_jmp = DISAS_NEXT;
|
dc->is_jmp = DISAS_NEXT;
|
||||||
dc->pc = pc_start;
|
dc->pc = pc_start;
|
||||||
|
dc->singlestep_enabled = env->singlestep_enabled;
|
||||||
lj = -1;
|
lj = -1;
|
||||||
do {
|
do {
|
||||||
if (env->nb_breakpoints > 0) {
|
if (env->nb_breakpoints > 0) {
|
||||||
|
@ -2054,21 +2064,30 @@ static inline int gen_intermediate_code_internal(CPUState *env,
|
||||||
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
|
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
|
||||||
!env->singlestep_enabled &&
|
!env->singlestep_enabled &&
|
||||||
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
|
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
|
||||||
switch(dc->is_jmp) {
|
if (__builtin_expect(env->singlestep_enabled, 0)) {
|
||||||
case DISAS_JUMP_NEXT:
|
/* Make sure the pc is updated, and raise a debug exception. */
|
||||||
case DISAS_NEXT:
|
if (dc->is_jmp == DISAS_NEXT || dc->is_jmp == DISAS_JUMP_NEXT) {
|
||||||
gen_op_jmp((long)dc->tb, (long)dc->pc);
|
gen_op_movl_T0_im((long)dc->pc);
|
||||||
break;
|
gen_op_movl_reg_TN[0][15]();
|
||||||
default:
|
}
|
||||||
case DISAS_JUMP:
|
gen_op_debug();
|
||||||
case DISAS_UPDATE:
|
} else {
|
||||||
/* indicate that the hash table must be used to find the next TB */
|
switch(dc->is_jmp) {
|
||||||
gen_op_movl_T0_0();
|
case DISAS_JUMP_NEXT:
|
||||||
gen_op_exit_tb();
|
case DISAS_NEXT:
|
||||||
break;
|
gen_op_jmp((long)dc->tb, (long)dc->pc);
|
||||||
case DISAS_TB_JUMP:
|
break;
|
||||||
/* nothing more to generate */
|
default:
|
||||||
break;
|
case DISAS_JUMP:
|
||||||
|
case DISAS_UPDATE:
|
||||||
|
/* indicate that the hash table must be used to find the next TB */
|
||||||
|
gen_op_movl_T0_0();
|
||||||
|
gen_op_exit_tb();
|
||||||
|
break;
|
||||||
|
case DISAS_TB_JUMP:
|
||||||
|
/* nothing more to generate */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*gen_opc_ptr = INDEX_op_end;
|
*gen_opc_ptr = INDEX_op_end;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue