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:
bellard 2005-04-23 18:27:52 +00:00
parent a4f81979e8
commit 8aaca4c0b4
1 changed files with 42 additions and 23 deletions

View File

@ -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;