[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 07/11] target-mips: split out delay slot handling
From: |
Nathan Froyd |
Subject: |
[Qemu-devel] [PATCH 07/11] target-mips: split out delay slot handling |
Date: |
Mon, 23 Nov 2009 12:50:05 -0800 |
Move delay slot handling to common code whose invocation can be
controlled from gen_intermediate_code_internal.
Signed-off-by: Nathan Froyd <address@hidden>
---
target-mips/translate.c | 134 +++++++++++++++++++++++++++-------------------
1 files changed, 79 insertions(+), 55 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index fece3c1..e7aee33 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -7548,6 +7548,56 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t
opc,
fregnames[fs], fregnames[ft]);
}
+static void handle_delay_slot (CPUState *env, DisasContext *ctx,
+ int insn_bytes)
+{
+ if (ctx->hflags & MIPS_HFLAG_BMASK) {
+ int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
+ /* Branches completion */
+ ctx->hflags &= ~MIPS_HFLAG_BMASK;
+ ctx->bstate = BS_BRANCH;
+ save_cpu_state(ctx, 0);
+ /* FIXME: Need to clear can_do_io. */
+ switch (hflags) {
+ case MIPS_HFLAG_B:
+ /* unconditional branch */
+ MIPS_DEBUG("unconditional branch");
+ gen_goto_tb(ctx, 0, ctx->btarget);
+ break;
+ case MIPS_HFLAG_BL:
+ /* blikely taken case */
+ MIPS_DEBUG("blikely branch taken");
+ gen_goto_tb(ctx, 0, ctx->btarget);
+ break;
+ case MIPS_HFLAG_BC:
+ /* Conditional branch */
+ MIPS_DEBUG("conditional branch");
+ {
+ int l1 = gen_new_label();
+
+ tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
+ gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
+ gen_set_label(l1);
+ gen_goto_tb(ctx, 0, ctx->btarget);
+ }
+ break;
+ case MIPS_HFLAG_BR:
+ /* unconditional branch to register */
+ MIPS_DEBUG("branch to register");
+ tcg_gen_mov_tl(cpu_PC, btarget);
+ if (ctx->singlestep_enabled) {
+ save_cpu_state(ctx, 0);
+ gen_helper_0i(raise_exception, EXCP_DEBUG);
+ }
+ tcg_gen_exit_tb(0);
+ break;
+ default:
+ MIPS_DEBUG("unknown branch");
+ break;
+ }
+ }
+}
+
/* ISA extensions (ASEs) */
/* MIPS16 extension to MIPS32 */
/* SmartMIPS extension to MIPS32 */
@@ -7558,7 +7608,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t
opc,
#endif
-static void decode_opc (CPUState *env, DisasContext *ctx)
+static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
{
int32_t offset;
int rs, rt, rd, sa;
@@ -7573,7 +7623,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
}
/* Handle blikely not taken case */
- if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
+ if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
int l1 = gen_new_label();
MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
@@ -7664,7 +7714,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
break;
case OPC_JR ... OPC_JALR:
gen_compute_branch(ctx, op1, 4, rs, rd, sa);
- return;
+ *is_branch = 1;
+ break;
case OPC_TGE ... OPC_TEQ: /* Traps */
case OPC_TNE:
gen_trap(ctx, op1, rs, rt, -1);
@@ -7953,7 +8004,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
case OPC_BLTZAL ... OPC_BGEZALL:
gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
- return;
+ *is_branch = 1;
+ break;
case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
case OPC_TNEI:
gen_trap(ctx, op1, rs, -1, imm);
@@ -8072,11 +8124,13 @@ static void decode_opc (CPUState *env, DisasContext
*ctx)
case OPC_J ... OPC_JAL: /* Jump */
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
gen_compute_branch(ctx, op, 4, rs, rt, offset);
- return;
+ *is_branch = 1;
+ break;
case OPC_BEQ ... OPC_BGTZ: /* Branch */
case OPC_BEQL ... OPC_BGTZL:
gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
- return;
+ *is_branch = 1;
+ break;
case OPC_LB ... OPC_LWR: /* Load and stores */
case OPC_SB ... OPC_SW:
case OPC_SWR:
@@ -8137,7 +8191,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
case OPC_BC1:
gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
(rt >> 2) & 0x7, imm << 2);
- return;
+ *is_branch = 1;
+ break;
case OPC_S_FMT:
case OPC_D_FMT:
case OPC_W_FMT:
@@ -8242,51 +8297,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
generate_exception(ctx, EXCP_RI);
break;
}
- if (ctx->hflags & MIPS_HFLAG_BMASK) {
- int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
- /* Branches completion */
- ctx->hflags &= ~MIPS_HFLAG_BMASK;
- ctx->bstate = BS_BRANCH;
- save_cpu_state(ctx, 0);
- /* FIXME: Need to clear can_do_io. */
- switch (hflags) {
- case MIPS_HFLAG_B:
- /* unconditional branch */
- MIPS_DEBUG("unconditional branch");
- gen_goto_tb(ctx, 0, ctx->btarget);
- break;
- case MIPS_HFLAG_BL:
- /* blikely taken case */
- MIPS_DEBUG("blikely branch taken");
- gen_goto_tb(ctx, 0, ctx->btarget);
- break;
- case MIPS_HFLAG_BC:
- /* Conditional branch */
- MIPS_DEBUG("conditional branch");
- {
- int l1 = gen_new_label();
-
- tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
- gen_goto_tb(ctx, 1, ctx->pc + 4);
- gen_set_label(l1);
- gen_goto_tb(ctx, 0, ctx->btarget);
- }
- break;
- case MIPS_HFLAG_BR:
- /* unconditional branch to register */
- MIPS_DEBUG("branch to register");
- tcg_gen_mov_tl(cpu_PC, btarget);
- if (ctx->singlestep_enabled) {
- save_cpu_state(ctx, 0);
- gen_helper_0i(raise_exception, EXCP_DEBUG);
- }
- tcg_gen_exit_tb(0);
- break;
- default:
- MIPS_DEBUG("unknown branch");
- break;
- }
- }
}
static inline void
@@ -8300,6 +8310,8 @@ gen_intermediate_code_internal (CPUState *env,
TranslationBlock *tb,
int j, lj = -1;
int num_insns;
int max_insns;
+ int insn_bytes;
+ int is_branch;
if (search_pc)
qemu_log("search pc %d\n", search_pc);
@@ -8360,9 +8372,21 @@ gen_intermediate_code_internal (CPUState *env,
TranslationBlock *tb,
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
- ctx.opcode = ldl_code(ctx.pc);
- decode_opc(env, &ctx);
- ctx.pc += 4;
+
+ is_branch = 0;
+ if (ctx.isa_mode == 0) {
+ ctx.opcode = ldl_code(ctx.pc);
+ insn_bytes = 4;
+ decode_opc(env, &ctx, &is_branch);
+ } else {
+ generate_exception(&ctx, EXCP_RI);
+ break;
+ }
+ if (!is_branch) {
+ handle_delay_slot(env, &ctx, insn_bytes);
+ }
+ ctx.pc += insn_bytes;
+
num_insns++;
/* Execute a branch and its delay slot as a single instruction.
--
1.6.3.2
- [Qemu-devel] [PATCH 00/11] target-mips: add mips16 support, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 04/11] target-mips: move ROTR and ROTRV inside gen_shift_{imm, }, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 09/11] target-mips: add mips16 instruction decoding, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 03/11] target-mips: change interrupt bits to be mips16-aware, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 07/11] target-mips: split out delay slot handling,
Nathan Froyd <=
- [Qemu-devel] [PATCH 01/11] target-mips: add ISAMode bits for mips16 execution, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 02/11] target-mips: add new HFLAGs for JALX and 16/32-bit delay slots, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 06/11] target-mips: add gen_base_offset_addr, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 11/11] target-mips: add copyright notice for mips16 work, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 08/11] target-mips: add enums for MIPS16 opcodes, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 05/11] target-mips: make gen_compute_branch 16/32-bit-aware, Nathan Froyd, 2009/11/23
- [Qemu-devel] [PATCH 10/11] gdbstub: add MIPS16 support, Nathan Froyd, 2009/11/23