From 06c949e62a098f97bd68a7382eb1953898a11e09 Mon Sep 17 00:00:00 2001 From: pbrook Date: Sat, 4 Feb 2006 19:35:26 +0000 Subject: [PATCH] Implement Arm BKPT instruction. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1740 c046a42c-6fe2-441c-8c8c-71466251a162 --- linux-user/main.c | 23 ++++++++++++++++++----- target-arm/cpu.h | 1 + target-arm/helper.c | 1 + target-arm/op.c | 6 ++++++ target-arm/translate.c | 13 +++++++++++++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index ef3a171166..56accfbb52 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -358,14 +358,27 @@ void cpu_loop(CPUARMState *env) } break; case EXCP_SWI: + case EXCP_BKPT: { /* system call */ - if (env->thumb) { - insn = lduw((void *)(env->regs[15] - 2)); - n = insn & 0xff; + if (trapnr == EXCP_BKPT) { + if (env->thumb) { + insn = lduw((void *)(env->regs[15])); + n = insn & 0xff; + env->regs[15] += 2; + } else { + insn = ldl((void *)(env->regs[15])); + n = (insn & 0xf) | ((insn >> 4) & 0xff0); + env->regs[15] += 4; + } } else { - insn = ldl((void *)(env->regs[15] - 4)); - n = insn & 0xffffff; + if (env->thumb) { + insn = lduw((void *)(env->regs[15] - 2)); + n = insn & 0xff; + } else { + insn = ldl((void *)(env->regs[15] - 4)); + n = insn & 0xffffff; + } } if (n == ARM_NR_cacheflush) { diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 3b36839e4b..7cc7da60e9 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -34,6 +34,7 @@ #define EXCP_DATA_ABORT 4 #define EXCP_IRQ 5 #define EXCP_FIQ 6 +#define EXCP_BKPT 7 /* We currently assume float and double are IEEE single and double precision respectively. diff --git a/target-arm/helper.c b/target-arm/helper.c index 538e17a35c..5804df8264 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -127,6 +127,7 @@ void do_interrupt(CPUARMState *env) offset = 0; break; case EXCP_PREFETCH_ABORT: + case EXCP_BKPT: new_mode = ARM_CPU_MODE_ABT; addr = 0x0c; mask = CPSR_A | CPSR_I; diff --git a/target-arm/op.c b/target-arm/op.c index 35419a1b71..acac2394a6 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -885,6 +885,12 @@ void OPPROTO op_wfi(void) cpu_loop_exit(); } +void OPPROTO op_bkpt(void) +{ + env->exception_index = EXCP_BKPT; + cpu_loop_exit(); +} + /* VFP support. We follow the convention used for VFP instrunctions: Single precition routines have a "s" suffix, double precision a "d" suffix. */ diff --git a/target-arm/translate.c b/target-arm/translate.c index 089fbf2fd9..5f817080f8 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -1217,6 +1217,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_op_addl_T0_T1_saturate(); gen_movl_reg_T0(s, rd); break; + case 7: /* bkpt */ + gen_op_movl_T0_im((long)s->pc - 4); + gen_op_movl_reg_TN[0][15](); + gen_op_bkpt(); + s->is_jmp = DISAS_JUMP; + break; case 0x8: /* signed multiply */ case 0xa: case 0xc: @@ -2183,6 +2189,13 @@ static void disas_thumb_insn(DisasContext *s) gen_bx(s); break; + case 0xe: /* bkpt */ + gen_op_movl_T0_im((long)s->pc - 2); + gen_op_movl_reg_TN[0][15](); + gen_op_bkpt(); + s->is_jmp = DISAS_JUMP; + break; + default: goto undef; }