32 |
typedef struct DisasContext { |
typedef struct DisasContext { |
33 |
target_ulong pc; |
target_ulong pc; |
34 |
int is_jmp; |
int is_jmp; |
35 |
|
/* Nonzero if this instruction has been conditionally skipped. */ |
36 |
|
int condjmp; |
37 |
|
/* The label that will be jumped to when the instruction is skipped. */ |
38 |
|
int condlabel; |
39 |
struct TranslationBlock *tb; |
struct TranslationBlock *tb; |
40 |
int singlestep_enabled; |
int singlestep_enabled; |
41 |
} DisasContext; |
} DisasContext; |
57 |
|
|
58 |
#include "gen-op.h" |
#include "gen-op.h" |
59 |
|
|
60 |
static GenOpFunc2 *gen_test_cc[14] = { |
static GenOpFunc1 *gen_test_cc[14] = { |
61 |
gen_op_test_eq, |
gen_op_test_eq, |
62 |
gen_op_test_ne, |
gen_op_test_ne, |
63 |
gen_op_test_cs, |
gen_op_test_cs, |
900 |
gen_op_movl_T0_im(dest); |
gen_op_movl_T0_im(dest); |
901 |
gen_bx(s); |
gen_bx(s); |
902 |
} else { |
} else { |
903 |
gen_op_jmp((long)s->tb, dest); |
gen_op_jmp0((long)s->tb, dest); |
904 |
s->is_jmp = DISAS_TB_JUMP; |
s->is_jmp = DISAS_TB_JUMP; |
905 |
} |
} |
906 |
} |
} |
943 |
if (cond != 0xe) { |
if (cond != 0xe) { |
944 |
/* if not always execute, we generate a conditional jump to |
/* if not always execute, we generate a conditional jump to |
945 |
next instruction */ |
next instruction */ |
946 |
gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); |
s->condlabel = gen_new_label(); |
947 |
s->is_jmp = DISAS_JUMP_NEXT; |
gen_test_cc[cond ^ 1](s->condlabel); |
948 |
|
s->condjmp = 1; |
949 |
|
//gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); |
950 |
|
//s->is_jmp = DISAS_JUMP_NEXT; |
951 |
} |
} |
952 |
if ((insn & 0x0f900000) == 0x03000000) { |
if ((insn & 0x0f900000) == 0x03000000) { |
953 |
if ((insn & 0x0ff0f000) != 0x0360f000) |
if ((insn & 0x0ff0f000) != 0x0360f000) |
1968 |
break; |
break; |
1969 |
} |
} |
1970 |
/* generate a conditional jump to next instruction */ |
/* generate a conditional jump to next instruction */ |
1971 |
gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); |
s->condlabel = gen_new_label(); |
1972 |
s->is_jmp = DISAS_JUMP_NEXT; |
gen_test_cc[cond ^ 1](s->condlabel); |
1973 |
|
s->condjmp = 1; |
1974 |
|
//gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); |
1975 |
|
//s->is_jmp = DISAS_JUMP_NEXT; |
1976 |
gen_movl_T1_reg(s, 15); |
gen_movl_T1_reg(s, 15); |
1977 |
|
|
1978 |
/* jump to the offset */ |
/* jump to the offset */ |
2044 |
dc->is_jmp = DISAS_NEXT; |
dc->is_jmp = DISAS_NEXT; |
2045 |
dc->pc = pc_start; |
dc->pc = pc_start; |
2046 |
dc->singlestep_enabled = env->singlestep_enabled; |
dc->singlestep_enabled = env->singlestep_enabled; |
2047 |
|
dc->condjmp = 0; |
2048 |
|
nb_gen_labels = 0; |
2049 |
lj = -1; |
lj = -1; |
2050 |
do { |
do { |
2051 |
if (env->nb_breakpoints > 0) { |
if (env->nb_breakpoints > 0) { |
2069 |
gen_opc_pc[lj] = dc->pc; |
gen_opc_pc[lj] = dc->pc; |
2070 |
gen_opc_instr_start[lj] = 1; |
gen_opc_instr_start[lj] = 1; |
2071 |
} |
} |
2072 |
|
|
2073 |
if (env->thumb) |
if (env->thumb) |
2074 |
disas_thumb_insn(dc); |
disas_thumb_insn(dc); |
2075 |
else |
else |
2076 |
disas_arm_insn(env, dc); |
disas_arm_insn(env, dc); |
2077 |
|
|
2078 |
|
if (dc->condjmp && !dc->is_jmp) { |
2079 |
|
gen_set_label(dc->condlabel); |
2080 |
|
dc->condjmp = 0; |
2081 |
|
} |
2082 |
|
/* Translation stops when a conditional branch is enoutered. |
2083 |
|
* Otherwise the subsequent code could get translated several times. |
2084 |
|
*/ |
2085 |
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
2086 |
!env->singlestep_enabled && |
!env->singlestep_enabled && |
2087 |
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); |
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); |
2088 |
|
/* It this stage dc->condjmp will only be set when the skipped |
2089 |
|
* instruction was a conditional branch, and teh PC has already been |
2090 |
|
* written. */ |
2091 |
if (__builtin_expect(env->singlestep_enabled, 0)) { |
if (__builtin_expect(env->singlestep_enabled, 0)) { |
2092 |
/* Make sure the pc is updated, and raise a debug exception. */ |
/* Make sure the pc is updated, and raise a debug exception. */ |
2093 |
if (dc->is_jmp == DISAS_NEXT || dc->is_jmp == DISAS_JUMP_NEXT) { |
if (dc->condjmp) { |
2094 |
|
gen_op_debug(); |
2095 |
|
gen_set_label(dc->condlabel); |
2096 |
|
} |
2097 |
|
if (dc->condjmp || !dc->is_jmp) { |
2098 |
gen_op_movl_T0_im((long)dc->pc); |
gen_op_movl_T0_im((long)dc->pc); |
2099 |
gen_op_movl_reg_TN[0][15](); |
gen_op_movl_reg_TN[0][15](); |
2100 |
|
dc->condjmp = 0; |
2101 |
} |
} |
2102 |
gen_op_debug(); |
gen_op_debug(); |
2103 |
} else { |
} else { |
2104 |
switch(dc->is_jmp) { |
switch(dc->is_jmp) { |
|
case DISAS_JUMP_NEXT: |
|
2105 |
case DISAS_NEXT: |
case DISAS_NEXT: |
2106 |
gen_op_jmp((long)dc->tb, (long)dc->pc); |
gen_op_jmp1((long)dc->tb, (long)dc->pc); |
2107 |
break; |
break; |
2108 |
default: |
default: |
2109 |
case DISAS_JUMP: |
case DISAS_JUMP: |
2116 |
/* nothing more to generate */ |
/* nothing more to generate */ |
2117 |
break; |
break; |
2118 |
} |
} |
2119 |
|
if (dc->condjmp) { |
2120 |
|
gen_set_label(dc->condlabel); |
2121 |
|
gen_op_jmp1((long)dc->tb, (long)dc->pc); |
2122 |
|
dc->condjmp = 0; |
2123 |
|
} |
2124 |
} |
} |
2125 |
*gen_opc_ptr = INDEX_op_end; |
*gen_opc_ptr = INDEX_op_end; |
2126 |
|
|