提交 72cbca10 编写于 作者: B bellard

direct chaining support for SPARC


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@607 c046a42c-6fe2-441c-8c8c-71466251a162
上级 34f715e7
...@@ -643,24 +643,43 @@ void OPPROTO op_next_insn(void) ...@@ -643,24 +643,43 @@ void OPPROTO op_next_insn(void)
env->npc = env->npc + 4; env->npc = env->npc + 4;
} }
void OPPROTO op_generic_branch(void) void OPPROTO op_branch(void)
{
env->npc = PARAM3; /* XXX: optimize */
JUMP_TB(op_branch, PARAM1, 0, PARAM2);
}
void OPPROTO op_branch2(void)
{ {
if (T2) { if (T2) {
env->npc = PARAM1; env->npc = PARAM2 + 4;
JUMP_TB(op_branch2, PARAM1, 0, PARAM2);
} else { } else {
env->npc = PARAM2; env->npc = PARAM3 + 4;
JUMP_TB(op_branch2, PARAM1, 1, PARAM3);
}
FORCE_RET();
}
void OPPROTO op_branch_a(void)
{
if (T2) {
env->npc = PARAM2; /* XXX: optimize */
JUMP_TB(op_generic_branch_a, PARAM1, 0, PARAM3);
} else {
env->npc = PARAM3 + 8; /* XXX: optimize */
JUMP_TB(op_generic_branch_a, PARAM1, 1, PARAM3 + 4);
} }
FORCE_RET(); FORCE_RET();
} }
void OPPROTO op_generic_branch_a(void) void OPPROTO op_generic_branch(void)
{ {
if (T2) { if (T2) {
env->pc = PARAM2;
env->npc = PARAM1; env->npc = PARAM1;
} else { } else {
env->pc = PARAM2 + 4; env->npc = PARAM2;
env->npc = PARAM2 + 8;
} }
FORCE_RET(); FORCE_RET();
} }
...@@ -42,9 +42,14 @@ ...@@ -42,9 +42,14 @@
#define DEBUG_DISAS #define DEBUG_DISAS
#define DYNAMIC_PC 1 /* dynamic pc value */
#define JUMP_PC 2 /* dynamic pc value which takes only two values
according to jump_pc[T2] */
typedef struct DisasContext { typedef struct DisasContext {
uint8_t *pc; /* NULL means dynamic value */ target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
uint8_t *npc; /* NULL means dynamic value */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
int is_br; int is_br;
struct TranslationBlock *tb; struct TranslationBlock *tb;
} DisasContext; } DisasContext;
...@@ -306,6 +311,31 @@ static inline void gen_movl_T1_reg(int reg) ...@@ -306,6 +311,31 @@ static inline void gen_movl_T1_reg(int reg)
gen_movl_TN_reg(reg, 1); gen_movl_TN_reg(reg, 1);
} }
/* call this function before using T2 as it may have been set for a jump */
static inline void flush_T2(DisasContext * dc)
{
if (dc->npc == JUMP_PC) {
gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
dc->npc = DYNAMIC_PC;
}
}
static inline void save_npc(DisasContext * dc)
{
if (dc->npc == JUMP_PC) {
gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
dc->npc = DYNAMIC_PC;
} else if (dc->npc != DYNAMIC_PC) {
gen_op_movl_npc_im(dc->npc);
}
}
static inline void save_state(DisasContext * dc)
{
gen_op_jmp_im((uint32_t)dc->pc);
save_npc(dc);
}
static void gen_cond(int cond) static void gen_cond(int cond)
{ {
switch (cond) { switch (cond) {
...@@ -378,25 +408,23 @@ static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn) ...@@ -378,25 +408,23 @@ static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
} else if (cond == 0x8) { } else if (cond == 0x8) {
/* unconditional taken */ /* unconditional taken */
if (a) { if (a) {
dc->pc = (uint8_t *) target; dc->pc = target;
dc->npc = dc->pc + 4; dc->npc = dc->pc + 4;
} else { } else {
dc->pc = dc->npc; dc->pc = dc->npc;
dc->npc = (uint8_t *) target; dc->npc = target;
} }
} else { } else {
flush_T2(dc);
gen_cond(cond); gen_cond(cond);
if (a) { if (a) {
gen_op_generic_branch_a((uint32_t) target, gen_op_branch_a((long)dc->tb, target, dc->npc);
(uint32_t) (dc->npc));
dc->is_br = 1; dc->is_br = 1;
dc->pc = NULL;
dc->npc = NULL;
} else { } else {
dc->pc = dc->npc; dc->pc = dc->npc;
gen_op_generic_branch((uint32_t) target, dc->jump_pc[0] = target;
(uint32_t) (dc->npc + 4)); dc->jump_pc[1] = dc->npc + 4;
dc->npc = NULL; dc->npc = JUMP_PC;
} }
} }
} }
...@@ -409,18 +437,11 @@ static int sign_extend(int x, int len) ...@@ -409,18 +437,11 @@ static int sign_extend(int x, int len)
return (x << len) >> len; return (x << len) >> len;
} }
static inline void save_state(DisasContext * dc)
{
gen_op_jmp_im((uint32_t)dc->pc);
if (dc->npc != NULL)
gen_op_movl_npc_im((long) dc->npc);
}
static void disas_sparc_insn(DisasContext * dc) static void disas_sparc_insn(DisasContext * dc)
{ {
unsigned int insn, opc, rs1, rs2, rd; unsigned int insn, opc, rs1, rs2, rd;
insn = ldl_code(dc->pc); insn = ldl_code((uint8_t *)dc->pc);
opc = GET_FIELD(insn, 0, 1); opc = GET_FIELD(insn, 0, 1);
rd = GET_FIELD(insn, 2, 6); rd = GET_FIELD(insn, 2, 6);
...@@ -458,9 +479,9 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -458,9 +479,9 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_movl_T0_im((long) (dc->pc)); gen_op_movl_T0_im((long) (dc->pc));
gen_movl_T0_reg(15); gen_movl_T0_reg(15);
target = (long) dc->pc + target; target = dc->pc + target;
dc->pc = dc->npc; dc->pc = dc->npc;
dc->npc = (uint8_t *) target; dc->npc = target;
} }
goto jmp_insn; goto jmp_insn;
case 2: /* FPU & Logical Operations */ case 2: /* FPU & Logical Operations */
...@@ -625,7 +646,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -625,7 +646,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_movl_T0_reg(rd); gen_movl_T0_reg(rd);
} }
dc->pc = dc->npc; dc->pc = dc->npc;
dc->npc = NULL; dc->npc = DYNAMIC_PC;
} }
goto jmp_insn; goto jmp_insn;
case 0x3b: /* flush */ case 0x3b: /* flush */
...@@ -705,6 +726,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -705,6 +726,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_sth(); gen_op_sth();
break; break;
case 0x7: case 0x7:
flush_T2(dc);
gen_movl_reg_T2(rd + 1); gen_movl_reg_T2(rd + 1);
gen_op_std(); gen_op_std();
break; break;
...@@ -713,19 +735,21 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -713,19 +735,21 @@ static void disas_sparc_insn(DisasContext * dc)
} }
} }
/* default case for non jump instructions */ /* default case for non jump instructions */
if (dc->npc != NULL) { if (dc->npc == DYNAMIC_PC) {
dc->pc = DYNAMIC_PC;
gen_op_next_insn();
} else if (dc->npc == JUMP_PC) {
/* we can do a static jump */
gen_op_branch2((long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
dc->is_br = 1;
} else {
dc->pc = dc->npc; dc->pc = dc->npc;
dc->npc = dc->npc + 4; dc->npc = dc->npc + 4;
} else {
dc->pc = NULL;
gen_op_next_insn();
} }
jmp_insn:; jmp_insn:;
return; return;
illegal_insn: illegal_insn:
gen_op_jmp_im((uint32_t)dc->pc); save_state(dc);
if (dc->npc != NULL)
gen_op_movl_npc_im((long) dc->npc);
gen_op_exception(TT_ILL_INSN); gen_op_exception(TT_ILL_INSN);
dc->is_br = 1; dc->is_br = 1;
} }
...@@ -733,7 +757,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -733,7 +757,7 @@ static void disas_sparc_insn(DisasContext * dc)
static inline int gen_intermediate_code_internal(TranslationBlock * tb, static inline int gen_intermediate_code_internal(TranslationBlock * tb,
int spc) int spc)
{ {
uint8_t *pc_start, *last_pc; target_ulong pc_start, last_pc;
uint16_t *gen_opc_end; uint16_t *gen_opc_end;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
...@@ -743,9 +767,9 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, ...@@ -743,9 +767,9 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
exit(0); exit(0);
} }
dc->tb = tb; dc->tb = tb;
pc_start = (uint8_t *) tb->pc; pc_start = tb->pc;
dc->pc = pc_start; dc->pc = pc_start;
dc->npc = (uint8_t *) tb->cs_base; dc->npc = (target_ulong) tb->cs_base;
gen_opc_ptr = gen_opc_buf; gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
...@@ -761,19 +785,25 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, ...@@ -761,19 +785,25 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
break; break;
} while ((gen_opc_ptr < gen_opc_end) && } while ((gen_opc_ptr < gen_opc_end) &&
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
if (dc->pc != NULL) if (!dc->is_br) {
gen_op_jmp_im((long) dc->pc); if (dc->pc != DYNAMIC_PC &&
if (dc->npc != NULL) (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
gen_op_movl_npc_im((long) dc->npc); /* static PC and NPC: we can use direct chaining */
gen_op_branch((long)tb, dc->pc, dc->npc);
} else {
if (dc->pc != DYNAMIC_PC)
gen_op_jmp_im(dc->pc);
save_npc(dc);
gen_op_movl_T0_0(); gen_op_movl_T0_0();
gen_op_exit_tb(); gen_op_exit_tb();
}
}
*gen_opc_ptr = INDEX_op_end; *gen_opc_ptr = INDEX_op_end;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (loglevel) { if (loglevel) {
fprintf(logfile, "--------------\n"); fprintf(logfile, "--------------\n");
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); fprintf(logfile, "IN: %s\n", lookup_symbol((uint8_t *)pc_start));
disas(logfile, pc_start, last_pc + 4 - pc_start, 0, 0); disas(logfile, (uint8_t *)pc_start, last_pc + 4 - pc_start, 0, 0);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
fprintf(logfile, "OP:\n"); fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf); dump_ops(gen_opc_buf, gen_opparam_buf);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册