qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v11 08/46] target/mips: Add emulation of nanoMIPS 16-bit bran


From: Philippe Mathieu-Daudé
Subject: Re: [PATCH v11 08/46] target/mips: Add emulation of nanoMIPS 16-bit branch instructions
Date: Sat, 29 May 2021 16:20:57 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.1

On 5/29/21 3:52 PM, Philippe Mathieu-Daudé wrote:
> On Mon, Aug 20, 2018 at 8:17 PM Aleksandar Markovic
> <aleksandar.markovic@rt-rk.com> wrote:
>>
>> From: Stefan Markovic <smarkovic@wavecomp.com>
>>
>> Add emulation of nanoMIPS 16-bit branch instructions.
>>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
>> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
>> Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
>> ---
>>  target/mips/translate.c | 158 
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 158 insertions(+)
>>
>> diff --git a/target/mips/translate.c b/target/mips/translate.c
>> index 261680e..b0bbf4c 100644
>> --- a/target/mips/translate.c
>> +++ b/target/mips/translate.c
>> @@ -4564,6 +4564,128 @@ static void gen_compute_branch (DisasContext *ctx, 
>> uint32_t opc,
>>      tcg_temp_free(t1);
>>  }
>>
>> +
>> +/* nanoMIPS Branches */
>> +static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
>> +                                int insn_bytes,
>> +                                int rs, int rt, int32_t offset)
>> +{
>> +    target_ulong btgt = -1;
>> +    int bcond_compute = 0;
>> +    TCGv t0 = tcg_temp_new();
>> +    TCGv t1 = tcg_temp_new();
>> +
>> +    /* Load needed operands */
>> +    switch (opc) {
>> +    case OPC_BEQ:
>> +    case OPC_BNE:
>> +        /* Compare two registers */
>> +        if (rs != rt) {
>> +            gen_load_gpr(t0, rs);
>> +            gen_load_gpr(t1, rt);
>> +            bcond_compute = 1;
>> +        }
>> +        btgt = ctx->base.pc_next + insn_bytes + offset;
>> +        break;
>> +    case OPC_BGEZAL:
>> +        /* Compare to zero */
>> +        if (rs != 0) {
>> +            gen_load_gpr(t0, rs);
>> +            bcond_compute = 1;
>> +        }
>> +        btgt = ctx->base.pc_next + insn_bytes + offset;
>> +        break;
>> +    case OPC_BPOSGE32:
>> +        tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
>> +        bcond_compute = 1;
>> +        btgt = ctx->base.pc_next + insn_bytes + offset;

I think this opcode never worked correctly.

Per the "MIPS® Architecture Extension: nanoMIPS32 DSP Technical
Reference Manual — Revision 0.04" p. 88 "BPOSGE32C":

  "First, the offset argument is left-shifted by one bit to form
   a 17-bit signed integer value."

The caller, decode_nanomips_32_48_opc(), doesn't shift the offset:

    case NM_BPOSGE32C:
        check_dsp_r3(ctx);
        {
            int32_t imm = extract32(ctx->opcode, 1, 13) |
                          extract32(ctx->opcode, 0, 1) << 13;

            gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
                                  imm);
        }
        break;

>> +        break;
>> +    case OPC_JR:
>> +    case OPC_JALR:
>> +        /* Jump to register */
>> +        if (offset != 0 && offset != 16) {
>> +            /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
>> +               others are reserved. */
>> +            MIPS_INVAL("jump hint");
>> +            generate_exception_end(ctx, EXCP_RI);
>> +            goto out;
>> +        }
>> +        gen_load_gpr(btarget, rs);
>> +        break;
>> +    default:
>> +        MIPS_INVAL("branch/jump");
>> +        generate_exception_end(ctx, EXCP_RI);
>> +        goto out;
>> +    }
>> +    if (bcond_compute == 0) {
>> +        /* No condition to be computed */
>> +        switch (opc) {
>> +        case OPC_BEQ:     /* rx == rx        */
>> +            /* Always take */
>> +            ctx->hflags |= MIPS_HFLAG_B;
>> +            break;
>> +        case OPC_BGEZAL:  /* 0 >= 0          */
>> +            /* Always take and link */
>> +            tcg_gen_movi_tl(cpu_gpr[31],
>> +                            ctx->base.pc_next + insn_bytes);
>> +            ctx->hflags |= MIPS_HFLAG_B;
>> +            break;
>> +        case OPC_BNE:     /* rx != rx        */
>> +            tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
>> +            /* Skip the instruction in the delay slot */
>> +            ctx->base.pc_next += 4;
>> +            goto out;
>> +        case OPC_JR:
>> +            ctx->hflags |= MIPS_HFLAG_BR;
>> +            break;
>> +        case OPC_JALR:
>> +            if (rt > 0) {
>> +                tcg_gen_movi_tl(cpu_gpr[rt],
>> +                                ctx->base.pc_next + insn_bytes);
>> +            }
>> +            ctx->hflags |= MIPS_HFLAG_BR;
>> +            break;
>> +        default:
>> +            MIPS_INVAL("branch/jump");
>> +            generate_exception_end(ctx, EXCP_RI);
>> +            goto out;
>> +        }
>> +    } else {
>> +        switch (opc) {
>> +        case OPC_BEQ:
>> +            tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
>> +            goto not_likely;
>> +        case OPC_BNE:
>> +            tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
>> +            goto not_likely;
>> +        case OPC_BGEZAL:
>> +            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
>> +            tcg_gen_movi_tl(cpu_gpr[31],
>> +                            ctx->base.pc_next + insn_bytes);
>> +            goto not_likely;
>> +        case OPC_BPOSGE32:
>> +            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
> 
> This opcode implementation seems incomplete, per the ISA manual:
> 
> If a control transfer instruction (CTI) is executed in the forbidden
> slot of a branch or jump, Release 6 implementations are required to
> signal a Reserved Instruction Exception. A CTI is considered to be one
> of the following instructions: branch, jump, NAL (Release 6), ERET,
> ERETNC (Release 5), DERET, WAIT, or PAUSE (Release 2). An instruction
> is in the forbidden slot if it is the instruction following the
> branch.
> 
>> +        not_likely:
>> +            ctx->hflags |= MIPS_HFLAG_BC;
>> +            break;
>> +        default:
>> +            MIPS_INVAL("conditional branch/jump");
>> +            generate_exception_end(ctx, EXCP_RI);
>> +            goto out;
>> +        }
>> +    }
>> +
>> +    ctx->btarget = btgt;
>> +
>> + out:
>> +    if (insn_bytes == 2) {
>> +        ctx->hflags |= MIPS_HFLAG_B16;
>> +    }
>> +    tcg_temp_free(t0);
>> +    tcg_temp_free(t1);
>> +}
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]