[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2] target-mips: fix broken MIPS16 and microMIPS
From: |
James Hogan |
Subject: |
Re: [Qemu-devel] [PATCH v2] target-mips: fix broken MIPS16 and microMIPS |
Date: |
Wed, 3 Sep 2014 14:33:28 +0100 |
User-agent: |
Mutt/1.5.23 (2014-03-12) |
On Tue, Jul 01, 2014 at 05:43:05PM +0100, Yongbok Kim wrote:
> Commit 240ce26a broke MIPS16 and microMIPS support as it didn't
> care those branches and jumps don't have delay slot in
> MIPS16 and microMIPS.
>
> This patch introduces a new argument delayslot_size to the
> gen_compute_branch() indicating size of delay slot {0, 2, 4}.
> And the information is used to call handle_delay_slot() forcingly
> when no delay slot is required.
>
> There are some microMIPS branch and jump instructions that requires
> exact size of instruction in the delay slot. For indicating
> these instructions, MIPS_HFLAG_BDS_STRICT flag is introduced.
>
> Those fictional branch opcodes defined to support MIPS16 and
> microMIPS are no longer needed.
>
> Signed-off-by: Yongbok Kim <address@hidden>
Jonas hit this problem too with a mips16 enabled userland, and has
confirmed that this patch fixes it:
Tested-by: Jonas Gorski <address@hidden>
Cheers
James
> ---
> v2:
> * correct MIPS_HFLAG_TMASK
> ---
> target-mips/cpu.h | 13 +-
> target-mips/translate.c | 284
> ++++++++++++++++++-----------------------------
> 2 files changed, 117 insertions(+), 180 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 8b9a92e..c81dfac 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -431,7 +431,7 @@ struct CPUMIPSState {
> int error_code;
> uint32_t hflags; /* CPU State */
> /* TMASK defines different execution modes */
> -#define MIPS_HFLAG_TMASK 0xC07FF
> +#define MIPS_HFLAG_TMASK 0x1807FF
> #define MIPS_HFLAG_MODE 0x00007 /* execution modes */
> /* The KSU flags must be the lowest bits in hflags. The flag order
> must be the same as defined for CP0 Status. This allows to use
> @@ -463,17 +463,18 @@ struct CPUMIPSState {
> #define MIPS_HFLAG_BL 0x01800 /* Likely branch */
> #define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */
> /* Extra flags about the current pending branch. */
> -#define MIPS_HFLAG_BMASK_EXT 0x3C000
> +#define MIPS_HFLAG_BMASK_EXT 0x7C000
> #define MIPS_HFLAG_B16 0x04000 /* branch instruction was 16 bits */
> #define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */
> #define MIPS_HFLAG_BDS32 0x10000 /* branch requires 32-bit delay slot */
> -#define MIPS_HFLAG_BX 0x20000 /* branch exchanges execution mode */
> +#define MIPS_HFLAG_BDS_STRICT 0x20000 /* Strict delay slot size */
> +#define MIPS_HFLAG_BX 0x40000 /* branch exchanges execution mode */
> #define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
> /* MIPS DSP resources access. */
> -#define MIPS_HFLAG_DSP 0x40000 /* Enable access to MIPS DSP resources. */
> -#define MIPS_HFLAG_DSPR2 0x80000 /* Enable access to MIPS DSPR2 resources.
> */
> +#define MIPS_HFLAG_DSP 0x080000 /* Enable access to MIPS DSP resources. */
> +#define MIPS_HFLAG_DSPR2 0x100000 /* Enable access to MIPS DSPR2 resources.
> */
> /* Extra flag about HWREna register. */
> -#define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */
> +#define MIPS_HFLAG_HWRENA_ULR 0x200000 /* ULR bit from HWREna is set. */
> target_ulong btarget; /* Jump / branch target */
> target_ulong bcond; /* Branch condition (if needed) */
>
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 2f91959..a654ae8 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -61,7 +61,6 @@ enum {
> /* Jump and branches */
> OPC_J = (0x02 << 26),
> OPC_JAL = (0x03 << 26),
> - OPC_JALS = OPC_JAL | 0x5,
> OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
> OPC_BEQL = (0x14 << 26),
> OPC_BNE = (0x05 << 26),
> @@ -70,8 +69,7 @@ enum {
> OPC_BLEZL = (0x16 << 26),
> OPC_BGTZ = (0x07 << 26),
> OPC_BGTZL = (0x17 << 26),
> - OPC_JALX = (0x1D << 26), /* MIPS 16 only */
> - OPC_JALXS = OPC_JALX | 0x5,
> + OPC_JALX = (0x1D << 26),
> /* Load and stores */
> OPC_LDL = (0x1A << 26),
> OPC_LDR = (0x1B << 26),
> @@ -171,8 +169,6 @@ enum {
> /* Jumps */
> OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
> OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
> - OPC_JALRC = OPC_JALR | (0x5 << 6),
> - OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
> /* Traps */
> OPC_TGE = 0x30 | OPC_SPECIAL,
> OPC_TGEU = 0x31 | OPC_SPECIAL,
> @@ -236,10 +232,8 @@ enum {
> OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
> OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
> OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
> - OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
> OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
> OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
> - OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
> OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
> OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
> OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
> @@ -3597,7 +3591,8 @@ static inline void gen_goto_tb(DisasContext *ctx, int
> n, target_ulong dest)
> /* Branches (before delay slot) */
> static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
> int insn_bytes,
> - int rs, int rt, int32_t offset)
> + int rs, int rt, int32_t offset,
> + int delayslot_size)
> {
> target_ulong btgt = -1;
> int blink = 0;
> @@ -3629,7 +3624,6 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> break;
> case OPC_BGEZ:
> case OPC_BGEZAL:
> - case OPC_BGEZALS:
> case OPC_BGEZALL:
> case OPC_BGEZL:
> case OPC_BGTZ:
> @@ -3638,7 +3632,6 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> case OPC_BLEZL:
> case OPC_BLTZ:
> case OPC_BLTZAL:
> - case OPC_BLTZALS:
> case OPC_BLTZALL:
> case OPC_BLTZL:
> /* Compare to zero */
> @@ -3661,15 +3654,11 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> case OPC_J:
> case OPC_JAL:
> case OPC_JALX:
> - case OPC_JALS:
> - case OPC_JALXS:
> /* Jump to immediate */
> btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) |
> (uint32_t)offset;
> break;
> case OPC_JR:
> case OPC_JALR:
> - case OPC_JALRC:
> - case OPC_JALRS:
> /* Jump to register */
> if (offset != 0 && offset != 16) {
> /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
> @@ -3698,12 +3687,8 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> ctx->hflags |= MIPS_HFLAG_B;
> MIPS_DEBUG("balways");
> break;
> - case OPC_BGEZALS:
> case OPC_BGEZAL: /* 0 >= 0 */
> case OPC_BGEZALL: /* 0 >= 0 likely */
> - ctx->hflags |= (opc == OPC_BGEZALS
> - ? MIPS_HFLAG_BDS16
> - : MIPS_HFLAG_BDS32);
> /* Always take and link */
> blink = 31;
> ctx->hflags |= MIPS_HFLAG_B;
> @@ -3715,15 +3700,11 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> /* Treat as NOP. */
> MIPS_DEBUG("bnever (NOP)");
> goto out;
> - case OPC_BLTZALS:
> case OPC_BLTZAL: /* 0 < 0 */
> - ctx->hflags |= (opc == OPC_BLTZALS
> - ? MIPS_HFLAG_BDS16
> - : MIPS_HFLAG_BDS32);
> /* Handle as an unconditional branch to get correct delay
> slot checking. */
> blink = 31;
> - btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
> + btgt = ctx->pc + insn_bytes + delayslot_size;
> ctx->hflags |= MIPS_HFLAG_B;
> MIPS_DEBUG("bnever and link");
> break;
> @@ -3744,33 +3725,21 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> ctx->hflags |= MIPS_HFLAG_B;
> MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
> break;
> - case OPC_JALXS:
> case OPC_JALX:
> ctx->hflags |= MIPS_HFLAG_BX;
> /* Fallthrough */
> - case OPC_JALS:
> case OPC_JAL:
> blink = 31;
> ctx->hflags |= MIPS_HFLAG_B;
> - ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
> - ? MIPS_HFLAG_BDS16
> - : MIPS_HFLAG_BDS32);
> MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
> break;
> case OPC_JR:
> ctx->hflags |= MIPS_HFLAG_BR;
> - if (insn_bytes == 4)
> - ctx->hflags |= MIPS_HFLAG_BDS32;
> MIPS_DEBUG("jr %s", regnames[rs]);
> break;
> - case OPC_JALRS:
> case OPC_JALR:
> - case OPC_JALRC:
> blink = rt;
> ctx->hflags |= MIPS_HFLAG_BR;
> - ctx->hflags |= (opc == OPC_JALRS
> - ? MIPS_HFLAG_BDS16
> - : MIPS_HFLAG_BDS32);
> MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
> break;
> default:
> @@ -3808,11 +3777,7 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
> MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
> goto likely;
> - case OPC_BGEZALS:
> case OPC_BGEZAL:
> - ctx->hflags |= (opc == OPC_BGEZALS
> - ? MIPS_HFLAG_BDS16
> - : MIPS_HFLAG_BDS32);
> tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
> MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
> blink = 31;
> @@ -3856,11 +3821,7 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
> goto not_likely;
> #endif
> - case OPC_BLTZALS:
> case OPC_BLTZAL:
> - ctx->hflags |= (opc == OPC_BLTZALS
> - ? MIPS_HFLAG_BDS16
> - : MIPS_HFLAG_BDS32);
> tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
> blink = 31;
> MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
> @@ -3884,13 +3845,21 @@ static void gen_compute_branch (DisasContext *ctx,
> uint32_t opc,
> blink, ctx->hflags, btgt);
>
> ctx->btarget = btgt;
> +
> + switch (delayslot_size) {
> + case 2:
> + ctx->hflags |= MIPS_HFLAG_BDS16;
> + break;
> + case 4:
> + ctx->hflags |= MIPS_HFLAG_BDS32;
> + break;
> + }
> +
> if (blink > 0) {
> int post_delay = insn_bytes;
> int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
>
> - if (opc != OPC_JALRC)
> - post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
> -
> + post_delay += delayslot_size;
> tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
> }
>
> @@ -7124,7 +7093,7 @@ static void gen_compute_branch1(DisasContext *ctx,
> uint32_t op,
> MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
> ctx->hflags, btarget);
> ctx->btarget = btarget;
> -
> + ctx->hflags |= MIPS_HFLAG_BDS32;
> out:
> tcg_temp_free_i32(t0);
> }
> @@ -9667,15 +9636,15 @@ static int decode_extended_mips16_opc (CPUMIPSState
> *env, DisasContext *ctx)
> gen_addiupc(ctx, rx, imm, 0, 1);
> break;
> case M16_OPC_B:
> - gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
> + gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
> /* No delay slot, so just process as a normal instruction */
> break;
> case M16_OPC_BEQZ:
> - gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
> + gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
> /* No delay slot, so just process as a normal instruction */
> break;
> case M16_OPC_BNEQZ:
> - gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
> + gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
> /* No delay slot, so just process as a normal instruction */
> break;
> case M16_OPC_SHIFT:
> @@ -9733,10 +9702,10 @@ static int decode_extended_mips16_opc (CPUMIPSState
> *env, DisasContext *ctx)
> case M16_OPC_I8:
> switch (funct) {
> case I8_BTEQZ:
> - gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
> + gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
> break;
> case I8_BTNEZ:
> - gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
> + gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
> break;
> case I8_SWRASP:
> gen_st(ctx, OPC_SW, 31, 29, imm);
> @@ -9864,7 +9833,7 @@ static int decode_mips16_opc (CPUMIPSState *env,
> DisasContext *ctx)
> case M16_OPC_B:
> offset = (ctx->opcode & 0x7ff) << 1;
> offset = (int16_t)(offset << 4) >> 4;
> - gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
> + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
> /* No delay slot, so just process as a normal instruction */
> break;
> case M16_OPC_JAL:
> @@ -9872,16 +9841,18 @@ static int decode_mips16_opc (CPUMIPSState *env,
> DisasContext *ctx)
> offset = (((ctx->opcode & 0x1f) << 21)
> | ((ctx->opcode >> 5) & 0x1f) << 16
> | offset) << 2;
> - op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
> - gen_compute_branch(ctx, op, 4, rx, ry, offset);
> + op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
> + gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
> n_bytes = 4;
> break;
> case M16_OPC_BEQZ:
> - gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) <<
> 1);
> + gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
> + ((int8_t)ctx->opcode) << 1, 0);
> /* No delay slot, so just process as a normal instruction */
> break;
> case M16_OPC_BNEQZ:
> - gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) <<
> 1);
> + gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
> + ((int8_t)ctx->opcode) << 1, 0);
> /* No delay slot, so just process as a normal instruction */
> break;
> case M16_OPC_SHIFT:
> @@ -9954,11 +9925,11 @@ static int decode_mips16_opc (CPUMIPSState *env,
> DisasContext *ctx)
> switch (funct) {
> case I8_BTEQZ:
> gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
> - ((int8_t)ctx->opcode) << 1);
> + ((int8_t)ctx->opcode) << 1, 0);
> break;
> case I8_BTNEZ:
> gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
> - ((int8_t)ctx->opcode) << 1);
> + ((int8_t)ctx->opcode) << 1, 0);
> break;
> case I8_SWRASP:
> gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
> @@ -10107,12 +10078,13 @@ static int decode_mips16_opc (CPUMIPSState *env,
> DisasContext *ctx)
> int ra = (ctx->opcode >> 5) & 0x1;
>
> if (link) {
> - op = nd ? OPC_JALRC : OPC_JALRS;
> + op = OPC_JALR;
> } else {
> op = OPC_JR;
> }
>
> - gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
> + gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
> + (nd ? 0 : 2));
> }
> break;
> case RR_SDBBP:
> @@ -10870,7 +10842,6 @@ static void gen_pool16c_insn(DisasContext *ctx)
> {
> int rd = mmreg((ctx->opcode >> 3) & 0x7);
> int rs = mmreg(ctx->opcode & 0x7);
> - int opc;
>
> switch (((ctx->opcode) >> 4) & 0x3f) {
> case NOT16 + 0:
> @@ -10926,32 +10897,27 @@ static void gen_pool16c_insn(DisasContext *ctx)
> {
> int reg = ctx->opcode & 0x1f;
>
> - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
> + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
> }
> break;
> case JRC16 + 0:
> case JRC16 + 1:
> {
> int reg = ctx->opcode & 0x1f;
> -
> - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
> + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
> /* Let normal delay slot handling in our caller take us
> to the branch target. */
> }
> break;
> case JALR16 + 0:
> case JALR16 + 1:
> - opc = OPC_JALR;
> - goto do_jalr;
> + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> + break;
> case JALR16S + 0:
> case JALR16S + 1:
> - opc = OPC_JALRS;
> - do_jalr:
> - {
> - int reg = ctx->opcode & 0x1f;
> -
> - gen_compute_branch(ctx, opc, 2, reg, 31, 0);
> - }
> + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> break;
> case MFHI16 + 0:
> case MFHI16 + 1:
> @@ -10979,8 +10945,7 @@ static void gen_pool16c_insn(DisasContext *ctx)
> case JRADDIUSP + 1:
> {
> int imm = ZIMM(ctx->opcode, 0, 5);
> -
> - gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
> + gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
> gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
> /* Let normal delay slot handling in our caller take us
> to the branch target. */
> @@ -11237,11 +11202,13 @@ static void gen_pool32axf (CPUMIPSState *env,
> DisasContext *ctx, int rt, int rs)
> switch (minor) {
> case JALR:
> case JALR_HB:
> - gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
> + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> break;
> case JALRS:
> case JALRS_HB:
> - gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
> + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> break;
> default:
> goto pool32axf_invalid;
> @@ -12131,30 +12098,32 @@ static void decode_micromips32_opc (CPUMIPSState
> *env, DisasContext *ctx,
> minor = (ctx->opcode >> 21) & 0x1f;
> switch (minor) {
> case BLTZ:
> - mips32_op = OPC_BLTZ;
> - goto do_branch;
> + gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
> + break;
> case BLTZAL:
> - mips32_op = OPC_BLTZAL;
> - goto do_branch;
> + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> + break;
> case BLTZALS:
> - mips32_op = OPC_BLTZALS;
> - goto do_branch;
> + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> + break;
> case BGEZ:
> - mips32_op = OPC_BGEZ;
> - goto do_branch;
> + gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
> + break;
> case BGEZAL:
> - mips32_op = OPC_BGEZAL;
> - goto do_branch;
> + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> + break;
> case BGEZALS:
> - mips32_op = OPC_BGEZALS;
> - goto do_branch;
> + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> + break;
> case BLEZ:
> - mips32_op = OPC_BLEZ;
> - goto do_branch;
> + gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
> + break;
> case BGTZ:
> - mips32_op = OPC_BGTZ;
> - do_branch:
> - gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
> + gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
> break;
>
> /* Traps */
> @@ -12182,7 +12151,7 @@ static void decode_micromips32_opc (CPUMIPSState
> *env, DisasContext *ctx,
> case BNEZC:
> case BEQZC:
> gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
> - 4, rs, 0, imm << 1);
> + 4, rs, 0, imm << 1, 0);
> /* Compact branches don't have a delay slot, so just let
> the normal delay slot handling take us to the branch
> target. */
> @@ -12320,25 +12289,28 @@ static void decode_micromips32_opc (CPUMIPSState
> *env, DisasContext *ctx,
> break;
> case JALX32:
> offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
> - gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
> + gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> break;
> case JALS32:
> offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
> - gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
> + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> break;
> case BEQ32:
> - gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
> + gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
> break;
> case BNE32:
> - gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
> + gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
> break;
> case J32:
> gen_compute_branch(ctx, OPC_J, 4, rt, rs,
> - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
> + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
> break;
> case JAL32:
> gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
> - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
> + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
> + ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
> break;
> /* Floating point (COP1) */
> case LWC132:
> @@ -12422,84 +12394,41 @@ static int decode_micromips_opc (CPUMIPSState *env,
> DisasContext *ctx)
>
> op = (ctx->opcode >> 10) & 0x3f;
> /* Enforce properly-sized instructions in a delay slot */
> - if (ctx->hflags & MIPS_HFLAG_BMASK) {
> - int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
> -
> - switch (op) {
> - case POOL32A:
> - case POOL32B:
> - case POOL32I:
> - case POOL32C:
> - case ADDI32:
> - case ADDIU32:
> - case ORI32:
> - case XORI32:
> - case SLTI32:
> - case SLTIU32:
> - case ANDI32:
> - case JALX32:
> - case LBU32:
> - case LHU32:
> - case POOL32F:
> - case JALS32:
> - case BEQ32:
> - case BNE32:
> - case J32:
> - case JAL32:
> - case SB32:
> - case SH32:
> - case POOL32S:
> - case ADDIUPC:
> - case SWC132:
> - case SDC132:
> - case SD32:
> - case SW32:
> - case LB32:
> - case LH32:
> - case DADDIU32:
> - case LWC132:
> - case LDC132:
> - case LD32:
> - case LW32:
> - if (bits & MIPS_HFLAG_BDS16) {
> + if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
> + switch (op & 0x7) { /* MSB-3..MSB-5 */
> + case 0:
> + /* POOL31A, POOL32B, POOL32I, POOL32C */
> + case 4:
> + /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
> + case 5:
> + /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
> + case 6:
> + /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
> + case 7:
> + /* LB32, LH32, LWC132, LDC132, LW32 */
> + if (ctx->hflags & MIPS_HFLAG_BDS16) {
> generate_exception(ctx, EXCP_RI);
> /* Just stop translation; the user is confused. */
> ctx->bstate = BS_STOP;
> return 2;
> }
> break;
> - case POOL16A:
> - case POOL16B:
> - case POOL16C:
> - case LWGP16:
> - case POOL16F:
> - case LBU16:
> - case LHU16:
> - case LWSP16:
> - case LW16:
> - case SB16:
> - case SH16:
> - case SWSP16:
> - case SW16:
> - case MOVE16:
> - case ANDI16:
> - case POOL16D:
> - case POOL16E:
> - case BEQZ16:
> - case BNEZ16:
> - case B16:
> - case LI16:
> - if (bits & MIPS_HFLAG_BDS32) {
> + case 1:
> + /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
> + case 2:
> + /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
> + case 3:
> + /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
> + if (ctx->hflags & MIPS_HFLAG_BDS32) {
> generate_exception(ctx, EXCP_RI);
> /* Just stop translation; the user is confused. */
> ctx->bstate = BS_STOP;
> return 2;
> }
> break;
> - default:
> - break;
> }
> }
> +
> switch (op) {
> case POOL16A:
> {
> @@ -12680,13 +12609,13 @@ static int decode_micromips_opc (CPUMIPSState *env,
> DisasContext *ctx)
> break;
> case B16:
> gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
> - SIMM(ctx->opcode, 0, 10) << 1);
> + SIMM(ctx->opcode, 0, 10) << 1, 4);
> break;
> case BNEZ16:
> case BEQZ16:
> gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
> mmreg(uMIPS_RD(ctx->opcode)),
> - 0, SIMM(ctx->opcode, 0, 7) << 1);
> + 0, SIMM(ctx->opcode, 0, 7) << 1, 4);
> break;
> case LI16:
> {
> @@ -14556,7 +14485,7 @@ static void decode_opc (CPUMIPSState *env,
> DisasContext *ctx)
> gen_muldiv(ctx, op1, 0, rs, rt);
> break;
> case OPC_JR ... OPC_JALR:
> - gen_compute_branch(ctx, op1, 4, rs, rd, sa);
> + gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
> break;
> case OPC_TGE ... OPC_TEQ: /* Traps */
> case OPC_TNE:
> @@ -15322,7 +15251,7 @@ static void decode_opc (CPUMIPSState *env,
> DisasContext *ctx)
> switch (op1) {
> case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
> case OPC_BLTZAL ... OPC_BGEZALL:
> - gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
> + gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
> break;
> case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
> case OPC_TNEI:
> @@ -15337,7 +15266,7 @@ static void decode_opc (CPUMIPSState *env,
> DisasContext *ctx)
> case OPC_BPOSGE64:
> #endif
> check_dsp(ctx);
> - gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
> + gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
> break;
> default: /* Invalid */
> MIPS_INVAL("regimm");
> @@ -15448,11 +15377,11 @@ static void decode_opc (CPUMIPSState *env,
> DisasContext *ctx)
> break;
> case OPC_J ... OPC_JAL: /* Jump */
> offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
> - gen_compute_branch(ctx, op, 4, rs, rt, offset);
> + gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
> break;
> case OPC_BEQ ... OPC_BGTZ: /* Branch */
> case OPC_BEQL ... OPC_BGTZL:
> - gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
> + gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
> break;
> case OPC_LB ... OPC_LWR: /* Load and stores */
> case OPC_LL:
> @@ -15617,7 +15546,7 @@ static void decode_opc (CPUMIPSState *env,
> DisasContext *ctx)
> case OPC_JALX:
> check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
> offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
> - gen_compute_branch(ctx, op, 4, rs, rt, offset);
> + gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
> break;
> case OPC_MDMX:
> check_insn(ctx, ASE_MDMX);
> @@ -15719,6 +15648,13 @@ gen_intermediate_code_internal(MIPSCPU *cpu,
> TranslationBlock *tb,
> ctx.bstate = BS_STOP;
> break;
> }
> + if (ctx.hflags & MIPS_HFLAG_BMASK) {
> + if (!(ctx.hflags & MIPS_HFLAG_BDS16) &&
> + !(ctx.hflags & MIPS_HFLAG_BDS32)) {
> + is_delay = 1;
> + /* force to generate branch as no delay slot is required */
> + }
> + }
> if (is_delay) {
> handle_delay_slot(&ctx, insn_bytes);
> }
> --
> 1.7.4
>
>
- Re: [Qemu-devel] [PATCH v2] target-mips: fix broken MIPS16 and microMIPS,
James Hogan <=