Commit 8aaca4c0b45c85f4108312232c9a7c4bdd641e8e

Authored by bellard
1 parent a4f81979

ARM singlestep support (Paul Brook)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1384 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 42 additions and 23 deletions
target-arm/translate.c
@@ -33,6 +33,7 @@ typedef struct DisasContext { @@ -33,6 +33,7 @@ typedef struct DisasContext {
33 target_ulong pc; 33 target_ulong pc;
34 int is_jmp; 34 int is_jmp;
35 struct TranslationBlock *tb; 35 struct TranslationBlock *tb;
  36 + int singlestep_enabled;
36 } DisasContext; 37 } DisasContext;
37 38
38 #define DISAS_JUMP_NEXT 4 39 #define DISAS_JUMP_NEXT 4
@@ -888,6 +889,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) @@ -888,6 +889,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
888 return 0; 889 return 0;
889 } 890 }
890 891
  892 +static inline void gen_jmp (DisasContext *s, uint32_t dest)
  893 +{
  894 + if (__builtin_expect(s->singlestep_enabled, 0)) {
  895 + /* An indirect jump so that we still trigger the debug exception. */
  896 + gen_op_movl_T0_im(dest);
  897 + gen_bx(s);
  898 + } else {
  899 + gen_op_jmp((long)s->tb, dest);
  900 + s->is_jmp = DISAS_TB_JUMP;
  901 + }
  902 +}
  903 +
891 static void disas_arm_insn(CPUState * env, DisasContext *s) 904 static void disas_arm_insn(CPUState * env, DisasContext *s)
892 { 905 {
893 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; 906 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) @@ -1469,8 +1482,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
1469 } 1482 }
1470 offset = (((int32_t)insn << 8) >> 8); 1483 offset = (((int32_t)insn << 8) >> 8);
1471 val += (offset << 2) + 4; 1484 val += (offset << 2) + 4;
1472 - gen_op_jmp((long)s->tb, val);  
1473 - s->is_jmp = DISAS_TB_JUMP; 1485 + gen_jmp(s, val);
1474 } 1486 }
1475 break; 1487 break;
1476 case 0xc: 1488 case 0xc:
@@ -1957,8 +1969,7 @@ static void disas_thumb_insn(DisasContext *s) @@ -1957,8 +1969,7 @@ static void disas_thumb_insn(DisasContext *s)
1957 val = (uint32_t)s->pc; 1969 val = (uint32_t)s->pc;
1958 offset = ((int32_t)insn << 24) >> 24; 1970 offset = ((int32_t)insn << 24) >> 24;
1959 val += (offset << 1) + 2; 1971 val += (offset << 1) + 2;
1960 - gen_op_jmp((long)s->tb, val);  
1961 - s->is_jmp = DISAS_TB_JUMP; 1972 + gen_jmp(s, val);
1962 break; 1973 break;
1963 1974
1964 case 14: 1975 case 14:
@@ -1968,8 +1979,7 @@ static void disas_thumb_insn(DisasContext *s) @@ -1968,8 +1979,7 @@ static void disas_thumb_insn(DisasContext *s)
1968 val = (uint32_t)s->pc; 1979 val = (uint32_t)s->pc;
1969 offset = ((int32_t)insn << 21) >> 21; 1980 offset = ((int32_t)insn << 21) >> 21;
1970 val += (offset << 1) + 2; 1981 val += (offset << 1) + 2;
1971 - gen_op_jmp((long)s->tb, val);  
1972 - s->is_jmp = DISAS_TB_JUMP; 1982 + gen_jmp(s, val);
1973 break; 1983 break;
1974 1984
1975 case 15: 1985 case 15:
@@ -1985,8 +1995,7 @@ static void disas_thumb_insn(DisasContext *s) @@ -1985,8 +1995,7 @@ static void disas_thumb_insn(DisasContext *s)
1985 val += offset; 1995 val += offset;
1986 if (insn & (1 << 11)) { 1996 if (insn & (1 << 11)) {
1987 /* bl */ 1997 /* bl */
1988 - gen_op_jmp((long)s->tb, val);  
1989 - s->is_jmp = DISAS_TB_JUMP; 1998 + gen_jmp(s, val);
1990 } else { 1999 } else {
1991 /* blx */ 2000 /* blx */
1992 gen_op_movl_T0_im(val); 2001 gen_op_movl_T0_im(val);
@@ -2024,6 +2033,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -2024,6 +2033,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2024 2033
2025 dc->is_jmp = DISAS_NEXT; 2034 dc->is_jmp = DISAS_NEXT;
2026 dc->pc = pc_start; 2035 dc->pc = pc_start;
  2036 + dc->singlestep_enabled = env->singlestep_enabled;
2027 lj = -1; 2037 lj = -1;
2028 do { 2038 do {
2029 if (env->nb_breakpoints > 0) { 2039 if (env->nb_breakpoints > 0) {
@@ -2054,21 +2064,30 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -2054,21 +2064,30 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2054 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 2064 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2055 !env->singlestep_enabled && 2065 !env->singlestep_enabled &&
2056 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); 2066 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2057 - switch(dc->is_jmp) {  
2058 - case DISAS_JUMP_NEXT:  
2059 - case DISAS_NEXT:  
2060 - gen_op_jmp((long)dc->tb, (long)dc->pc);  
2061 - break;  
2062 - default:  
2063 - case DISAS_JUMP:  
2064 - case DISAS_UPDATE:  
2065 - /* indicate that the hash table must be used to find the next TB */  
2066 - gen_op_movl_T0_0();  
2067 - gen_op_exit_tb();  
2068 - break;  
2069 - case DISAS_TB_JUMP:  
2070 - /* nothing more to generate */  
2071 - break; 2067 + if (__builtin_expect(env->singlestep_enabled, 0)) {
  2068 + /* Make sure the pc is updated, and raise a debug exception. */
  2069 + if (dc->is_jmp == DISAS_NEXT || dc->is_jmp == DISAS_JUMP_NEXT) {
  2070 + gen_op_movl_T0_im((long)dc->pc);
  2071 + gen_op_movl_reg_TN[0][15]();
  2072 + }
  2073 + gen_op_debug();
  2074 + } else {
  2075 + switch(dc->is_jmp) {
  2076 + case DISAS_JUMP_NEXT:
  2077 + case DISAS_NEXT:
  2078 + gen_op_jmp((long)dc->tb, (long)dc->pc);
  2079 + break;
  2080 + default:
  2081 + case DISAS_JUMP:
  2082 + case DISAS_UPDATE:
  2083 + /* indicate that the hash table must be used to find the next TB */
  2084 + gen_op_movl_T0_0();
  2085 + gen_op_exit_tb();
  2086 + break;
  2087 + case DISAS_TB_JUMP:
  2088 + /* nothing more to generate */
  2089 + break;
  2090 + }
2072 } 2091 }
2073 *gen_opc_ptr = INDEX_op_end; 2092 *gen_opc_ptr = INDEX_op_end;
2074 2093