Commit 8aaca4c0b45c85f4108312232c9a7c4bdd641e8e
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 | 33 | target_ulong pc; |
34 | 34 | int is_jmp; |
35 | 35 | struct TranslationBlock *tb; |
36 | + int singlestep_enabled; | |
36 | 37 | } DisasContext; |
37 | 38 | |
38 | 39 | #define DISAS_JUMP_NEXT 4 |
... | ... | @@ -888,6 +889,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) |
888 | 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 | 904 | static void disas_arm_insn(CPUState * env, DisasContext *s) |
892 | 905 | { |
893 | 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 | 1482 | } |
1470 | 1483 | offset = (((int32_t)insn << 8) >> 8); |
1471 | 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 | 1487 | break; |
1476 | 1488 | case 0xc: |
... | ... | @@ -1957,8 +1969,7 @@ static void disas_thumb_insn(DisasContext *s) |
1957 | 1969 | val = (uint32_t)s->pc; |
1958 | 1970 | offset = ((int32_t)insn << 24) >> 24; |
1959 | 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 | 1973 | break; |
1963 | 1974 | |
1964 | 1975 | case 14: |
... | ... | @@ -1968,8 +1979,7 @@ static void disas_thumb_insn(DisasContext *s) |
1968 | 1979 | val = (uint32_t)s->pc; |
1969 | 1980 | offset = ((int32_t)insn << 21) >> 21; |
1970 | 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 | 1983 | break; |
1974 | 1984 | |
1975 | 1985 | case 15: |
... | ... | @@ -1985,8 +1995,7 @@ static void disas_thumb_insn(DisasContext *s) |
1985 | 1995 | val += offset; |
1986 | 1996 | if (insn & (1 << 11)) { |
1987 | 1997 | /* bl */ |
1988 | - gen_op_jmp((long)s->tb, val); | |
1989 | - s->is_jmp = DISAS_TB_JUMP; | |
1998 | + gen_jmp(s, val); | |
1990 | 1999 | } else { |
1991 | 2000 | /* blx */ |
1992 | 2001 | gen_op_movl_T0_im(val); |
... | ... | @@ -2024,6 +2033,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
2024 | 2033 | |
2025 | 2034 | dc->is_jmp = DISAS_NEXT; |
2026 | 2035 | dc->pc = pc_start; |
2036 | + dc->singlestep_enabled = env->singlestep_enabled; | |
2027 | 2037 | lj = -1; |
2028 | 2038 | do { |
2029 | 2039 | if (env->nb_breakpoints > 0) { |
... | ... | @@ -2054,21 +2064,30 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
2054 | 2064 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
2055 | 2065 | !env->singlestep_enabled && |
2056 | 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 | 2092 | *gen_opc_ptr = INDEX_op_end; |
2074 | 2093 | ... | ... |