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,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 |