diff mbox series

[PULL,17/29] target/riscv: Convert quadrant 1 of RVXC insns to decodetree

Message ID 20190313143705.29129-18-palmer@sifive.com (mailing list archive)
State New, archived
Headers show
Series [PULL,01/29] target/riscv: Activate decodetree and implemnt LUI & AUIPC | expand

Commit Message

Palmer Dabbelt March 13, 2019, 2:36 p.m. UTC
From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
---
 target/riscv/insn16.decode              |  43 +++++++
 target/riscv/insn_trans/trans_rvc.inc.c | 151 ++++++++++++++++++++++++
 target/riscv/translate.c                | 118 +-----------------
 3 files changed, 195 insertions(+), 117 deletions(-)

Comments

Alistair Francis March 14, 2019, 8:28 p.m. UTC | #1
On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com> wrote:
>
> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>

This commit is the first bad commit in breaking 32-bit boot.

It looks like the jal doesn't jump to the correct address:

----------------
IN:
0x80000022:  00050433          add             s0,a0,zero
0x80000026:  000584b3          add             s1,a1,zero
0x8000002a:  2c79              jal             ra,670          # 0x800002c8

----------------
IN:
0x800002c8:  00000533          add             a0,zero,zero
0x800002cc:  8082              ret


Alistair

> ---
>  target/riscv/insn16.decode              |  43 +++++++
>  target/riscv/insn_trans/trans_rvc.inc.c | 151 ++++++++++++++++++++++++
>  target/riscv/translate.c                | 118 +-----------------
>  3 files changed, 195 insertions(+), 117 deletions(-)
>
> diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
> index 558c0c41f0b5..45109301c6d4 100644
> --- a/target/riscv/insn16.decode
> +++ b/target/riscv/insn16.decode
> @@ -22,28 +22,53 @@
>  %rs2_3     2:3                !function=ex_rvc_register
>
>  # Immediates:
> +%imm_ci        12:s1 2:5
>  %nzuimm_ciw    7:4 11:2 5:1 6:1   !function=ex_shift_2
>  %uimm_cl_d     5:2 10:3           !function=ex_shift_3
>  %uimm_cl_w     5:1 10:3 6:1       !function=ex_shift_2
> +%imm_cb        12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
> +%imm_cj        12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
> +
> +%nzuimm_6bit   12:1 2:5
> +
> +%imm_addi16sp  12:s1 3:2 5:1 2:1 6:1 !function=ex_shift_4
> +%imm_lui       12:s1 2:5             !function=ex_shift_12
> +
>
>
>  # Argument sets:
>  &cl               rs1 rd
>  &cl_dw     uimm   rs1 rd
> +&ci        imm        rd
>  &ciw       nzuimm     rd
>  &cs               rs1 rs2
>  &cs_dw     uimm   rs1 rs2
> +&cb        imm    rs1
> +&cr               rd  rs2
> +&cj       imm
> +&c_shift   shamt      rd
> +
>
> +&caddi16sp_lui  imm_lui imm_addi16sp rd
>
>  # Formats 16:
> +@ci        ... . ..... .....  .. &ci     imm=%imm_ci                  %rd
>  @ciw       ...   ........ ... .. &ciw    nzuimm=%nzuimm_ciw           rd=%rs2_3
>  @cl_d      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rd=%rs2_3
>  @cl_w      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rd=%rs2_3
>  @cl        ... ... ... .. ... .. &cl                      rs1=%rs1_3  rd=%rs2_3
>  @cs        ... ... ... .. ... .. &cs                      rs1=%rs1_3  rs2=%rs2_3
> +@cs_2      ... ... ... .. ... .. &cr                      rd=%rs1_3   rs2=%rs2_3
>  @cs_d      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rs2=%rs2_3
>  @cs_w      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rs2=%rs2_3
> +@cb        ... ... ... .. ... .. &cb     imm=%imm_cb      rs1=%rs1_3
> +@cj        ...    ........... .. &cj     imm=%imm_cj
>
> +@c_addi16sp_lui ... .  ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd
> +
> +@c_shift        ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit
> +
> +@c_andi         ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3
>
>  # *** RV64C Standard Extension (Quadrant 0) ***
>  c_addi4spn        000    ........ ... 00 @ciw
> @@ -53,3 +78,21 @@ c_flw_ld          011  --- ... -- ... 00 @cl    #Note: Must parse uimm manually
>  c_fsd             101  ... ... .. ... 00 @cs_d
>  c_sw              110  ... ... .. ... 00 @cs_w
>  c_fsw_sd          111  --- ... -- ... 00 @cs    #Note: Must parse uimm manually
> +
> +# *** RV64C Standard Extension (Quadrant 1) ***
> +c_addi            000 .  .....  ..... 01 @ci
> +c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm manually
> +c_li              010 .  .....  ..... 01 @ci
> +c_addi16sp_lui    011 .  .....  ..... 01 @c_addi16sp_lui # shares opc with C.LUI
> +c_srli            100 . 00 ...  ..... 01 @c_shift
> +c_srai            100 . 01 ...  ..... 01 @c_shift
> +c_andi            100 . 10 ...  ..... 01 @c_andi
> +c_sub             100 0 11 ... 00 ... 01 @cs_2
> +c_xor             100 0 11 ... 01 ... 01 @cs_2
> +c_or              100 0 11 ... 10 ... 01 @cs_2
> +c_and             100 0 11 ... 11 ... 01 @cs_2
> +c_subw            100 1 11 ... 00 ... 01 @cs_2
> +c_addw            100 1 11 ... 01 ... 01 @cs_2
> +c_j               101     ........... 01 @cj
> +c_beqz            110  ... ...  ..... 01 @cb
> +c_bnez            111  ... ...  ..... 01 @cb
> diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c
> index 93ec8aa30b95..b06c435c9800 100644
> --- a/target/riscv/insn_trans/trans_rvc.inc.c
> +++ b/target/riscv/insn_trans/trans_rvc.inc.c
> @@ -73,3 +73,154 @@ static bool trans_c_fsw_sd(DisasContext *ctx, arg_c_fsw_sd *a)
>      return false;
>  #endif
>  }
> +
> +static bool trans_c_addi(DisasContext *ctx, arg_c_addi *a)
> +{
> +    if (a->imm == 0) {
> +        /* Hint: insn is valid but does not affect state */
> +        return true;
> +    }
> +    arg_addi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
> +    return trans_addi(ctx, &arg);
> +}
> +
> +static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a)
> +{
> +#ifdef TARGET_RISCV32
> +    /* C.JAL */
> +    arg_jal arg = { .rd = 1, .imm = a->imm };
> +    return trans_jal(ctx, &arg);
> +#else
> +    /* C.ADDIW */
> +    arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
> +    return trans_addiw(ctx, &arg);
> +#endif
> +}
> +
> +static bool trans_c_li(DisasContext *ctx, arg_c_li *a)
> +{
> +    if (a->rd == 0) {
> +        /* Hint: insn is valid but does not affect state */
> +        return true;
> +    }
> +    arg_addi arg = { .rd = a->rd, .rs1 = 0, .imm = a->imm };
> +    return trans_addi(ctx, &arg);
> +}
> +
> +static bool trans_c_addi16sp_lui(DisasContext *ctx, arg_c_addi16sp_lui *a)
> +{
> +    if (a->rd == 2) {
> +        /* C.ADDI16SP */
> +        arg_addi arg = { .rd = 2, .rs1 = 2, .imm = a->imm_addi16sp };
> +        return trans_addi(ctx, &arg);
> +    } else if (a->imm_lui != 0) {
> +        /* C.LUI */
> +        if (a->rd == 0) {
> +            /* Hint: insn is valid but does not affect state */
> +            return true;
> +        }
> +        arg_lui arg = { .rd = a->rd, .imm = a->imm_lui };
> +        return trans_lui(ctx, &arg);
> +    }
> +    return false;
> +}
> +
> +static bool trans_c_srli(DisasContext *ctx, arg_c_srli *a)
> +{
> +    int shamt = a->shamt;
> +    if (shamt == 0) {
> +        /* For RV128 a shamt of 0 means a shift by 64 */
> +        shamt = 64;
> +    }
> +    /* Ensure, that shamt[5] is zero for RV32 */
> +    if (shamt >= TARGET_LONG_BITS) {
> +        return false;
> +    }
> +
> +    arg_srli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
> +    return trans_srli(ctx, &arg);
> +}
> +
> +static bool trans_c_srai(DisasContext *ctx, arg_c_srai *a)
> +{
> +    int shamt = a->shamt;
> +    if (shamt == 0) {
> +        /* For RV128 a shamt of 0 means a shift by 64 */
> +        shamt = 64;
> +    }
> +    /* Ensure, that shamt[5] is zero for RV32 */
> +    if (shamt >= TARGET_LONG_BITS) {
> +        return false;
> +    }
> +
> +    arg_srai arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
> +    return trans_srai(ctx, &arg);
> +}
> +
> +static bool trans_c_andi(DisasContext *ctx, arg_c_andi *a)
> +{
> +    arg_andi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
> +    return trans_andi(ctx, &arg);
> +}
> +
> +static bool trans_c_sub(DisasContext *ctx, arg_c_sub *a)
> +{
> +    arg_sub arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> +    return trans_sub(ctx, &arg);
> +}
> +
> +static bool trans_c_xor(DisasContext *ctx, arg_c_xor *a)
> +{
> +    arg_xor arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> +    return trans_xor(ctx, &arg);
> +}
> +
> +static bool trans_c_or(DisasContext *ctx, arg_c_or *a)
> +{
> +    arg_or arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> +    return trans_or(ctx, &arg);
> +}
> +
> +static bool trans_c_and(DisasContext *ctx, arg_c_and *a)
> +{
> +    arg_and arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> +    return trans_and(ctx, &arg);
> +}
> +
> +static bool trans_c_subw(DisasContext *ctx, arg_c_subw *a)
> +{
> +#ifdef TARGET_RISCV64
> +    arg_subw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> +    return trans_subw(ctx, &arg);
> +#else
> +    return false;
> +#endif
> +}
> +
> +static bool trans_c_addw(DisasContext *ctx, arg_c_addw *a)
> +{
> +#ifdef TARGET_RISCV64
> +    arg_addw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> +    return trans_addw(ctx, &arg);
> +#else
> +    return false;
> +#endif
> +}
> +
> +static bool trans_c_j(DisasContext *ctx, arg_c_j *a)
> +{
> +    arg_jal arg = { .rd = 0, .imm = a->imm };
> +    return trans_jal(ctx, &arg);
> +}
> +
> +static bool trans_c_beqz(DisasContext *ctx, arg_c_beqz *a)
> +{
> +    arg_beq arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
> +    return trans_beq(ctx, &arg);
> +}
> +
> +static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a)
> +{
> +    arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
> +    return trans_bne(ctx, &arg);
> +}
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 0106fa8d51b3..a584c24fbf6b 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -828,120 +828,6 @@ static void decode_RV32_64C0(DisasContext *ctx)
>      }
>  }
>
> -static void decode_RV32_64C1(DisasContext *ctx)
> -{
> -    uint8_t funct3 = extract32(ctx->opcode, 13, 3);
> -    uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
> -    uint8_t rs1s, rs2s;
> -    uint8_t funct2;
> -
> -    switch (funct3) {
> -    case 0:
> -        /* C.ADDI -> addi rd, rd, nzimm[5:0] */
> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, rd_rs1,
> -                      GET_C_IMM(ctx->opcode));
> -        break;
> -    case 1:
> -#if defined(TARGET_RISCV64)
> -        /* C.ADDIW (RV64/128) -> addiw rd, rd, imm[5:0]*/
> -        gen_arith_imm(ctx, OPC_RISC_ADDIW, rd_rs1, rd_rs1,
> -                      GET_C_IMM(ctx->opcode));
> -#else
> -        /* C.JAL(RV32) -> jal x1, offset[11:1] */
> -        gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
> -#endif
> -        break;
> -    case 2:
> -        /* C.LI -> addi rd, x0, imm[5:0]*/
> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, 0, GET_C_IMM(ctx->opcode));
> -        break;
> -    case 3:
> -        if (rd_rs1 == 2) {
> -            /* C.ADDI16SP -> addi x2, x2, nzimm[9:4]*/
> -            gen_arith_imm(ctx, OPC_RISC_ADDI, 2, 2,
> -                          GET_C_ADDI16SP_IMM(ctx->opcode));
> -        } else if (rd_rs1 != 0) {
> -            /* C.LUI (rs1/rd =/= {0,2}) -> lui rd, nzimm[17:12]*/
> -            tcg_gen_movi_tl(cpu_gpr[rd_rs1],
> -                            GET_C_IMM(ctx->opcode) << 12);
> -        }
> -        break;
> -    case 4:
> -        funct2 = extract32(ctx->opcode, 10, 2);
> -        rs1s = GET_C_RS1S(ctx->opcode);
> -        switch (funct2) {
> -        case 0: /* C.SRLI(RV32) -> srli rd', rd', shamt[5:0] */
> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
> -                               GET_C_ZIMM(ctx->opcode));
> -            /* C.SRLI64(RV128) */
> -            break;
> -        case 1:
> -            /* C.SRAI -> srai rd', rd', shamt[5:0]*/
> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
> -                            GET_C_ZIMM(ctx->opcode) | 0x400);
> -            /* C.SRAI64(RV128) */
> -            break;
> -        case 2:
> -            /* C.ANDI -> andi rd', rd', imm[5:0]*/
> -            gen_arith_imm(ctx, OPC_RISC_ANDI, rs1s, rs1s,
> -                          GET_C_IMM(ctx->opcode));
> -            break;
> -        case 3:
> -            funct2 = extract32(ctx->opcode, 5, 2);
> -            rs2s = GET_C_RS2S(ctx->opcode);
> -            switch (funct2) {
> -            case 0:
> -                /* C.SUB -> sub rd', rd', rs2' */
> -                if (extract32(ctx->opcode, 12, 1) == 0) {
> -                    gen_arith(ctx, OPC_RISC_SUB, rs1s, rs1s, rs2s);
> -                }
> -#if defined(TARGET_RISCV64)
> -                else {
> -                    gen_arith(ctx, OPC_RISC_SUBW, rs1s, rs1s, rs2s);
> -                }
> -#endif
> -                break;
> -            case 1:
> -                /* C.XOR -> xor rs1', rs1', rs2' */
> -                if (extract32(ctx->opcode, 12, 1) == 0) {
> -                    gen_arith(ctx, OPC_RISC_XOR, rs1s, rs1s, rs2s);
> -                }
> -#if defined(TARGET_RISCV64)
> -                else {
> -                    /* C.ADDW (RV64/128) */
> -                    gen_arith(ctx, OPC_RISC_ADDW, rs1s, rs1s, rs2s);
> -                }
> -#endif
> -                break;
> -            case 2:
> -                /* C.OR -> or rs1', rs1', rs2' */
> -                gen_arith(ctx, OPC_RISC_OR, rs1s, rs1s, rs2s);
> -                break;
> -            case 3:
> -                /* C.AND -> and rs1', rs1', rs2' */
> -                gen_arith(ctx, OPC_RISC_AND, rs1s, rs1s, rs2s);
> -                break;
> -            }
> -            break;
> -        }
> -        break;
> -    case 5:
> -        /* C.J -> jal x0, offset[11:1]*/
> -        gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
> -        break;
> -    case 6:
> -        /* C.BEQZ -> beq rs1', x0, offset[8:1]*/
> -        rs1s = GET_C_RS1S(ctx->opcode);
> -        gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
> -        break;
> -    case 7:
> -        /* C.BNEZ -> bne rs1', x0, offset[8:1]*/
> -        rs1s = GET_C_RS1S(ctx->opcode);
> -        gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
> -        break;
> -    }
> -}
> -
>  static void decode_RV32_64C2(DisasContext *ctx)
>  {
>      uint8_t rd, rs2;
> @@ -1028,9 +914,6 @@ static void decode_RV32_64C(DisasContext *ctx)
>      case 0:
>          decode_RV32_64C0(ctx);
>          break;
> -    case 1:
> -        decode_RV32_64C1(ctx);
> -        break;
>      case 2:
>          decode_RV32_64C2(ctx);
>          break;
> @@ -1045,6 +928,7 @@ static void decode_RV32_64C(DisasContext *ctx)
>  EX_SH(1)
>  EX_SH(2)
>  EX_SH(3)
> +EX_SH(4)
>  EX_SH(12)
>
>  #define REQUIRE_EXT(ctx, ext) do { \
> --
> 2.19.2
>
>
Palmer Dabbelt March 15, 2019, 3:59 a.m. UTC | #2
On Thu, 14 Mar 2019 13:28:37 PDT (-0700), alistair23@gmail.com wrote:
> On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com> wrote:
>>
>> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
>
> This commit is the first bad commit in breaking 32-bit boot.
>
> It looks like the jal doesn't jump to the correct address:
>
> ----------------
> IN:
> 0x80000022:  00050433          add             s0,a0,zero
> 0x80000026:  000584b3          add             s1,a1,zero
> 0x8000002a:  2c79              jal             ra,670          # 0x800002c8
>
> ----------------
> IN:
> 0x800002c8:  00000533          add             a0,zero,zero
> 0x800002cc:  8082              ret


Sorry, for some reason I thought you'd tested this on 32-bit?  Do you have a 
workflow that I can use to reproduce the bug?

>
>
> Alistair
>
>> ---
>>  target/riscv/insn16.decode              |  43 +++++++
>>  target/riscv/insn_trans/trans_rvc.inc.c | 151 ++++++++++++++++++++++++
>>  target/riscv/translate.c                | 118 +-----------------
>>  3 files changed, 195 insertions(+), 117 deletions(-)
>>
>> diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
>> index 558c0c41f0b5..45109301c6d4 100644
>> --- a/target/riscv/insn16.decode
>> +++ b/target/riscv/insn16.decode
>> @@ -22,28 +22,53 @@
>>  %rs2_3     2:3                !function=ex_rvc_register
>>
>>  # Immediates:
>> +%imm_ci        12:s1 2:5
>>  %nzuimm_ciw    7:4 11:2 5:1 6:1   !function=ex_shift_2
>>  %uimm_cl_d     5:2 10:3           !function=ex_shift_3
>>  %uimm_cl_w     5:1 10:3 6:1       !function=ex_shift_2
>> +%imm_cb        12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
>> +%imm_cj        12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
>> +
>> +%nzuimm_6bit   12:1 2:5
>> +
>> +%imm_addi16sp  12:s1 3:2 5:1 2:1 6:1 !function=ex_shift_4
>> +%imm_lui       12:s1 2:5             !function=ex_shift_12
>> +
>>
>>
>>  # Argument sets:
>>  &cl               rs1 rd
>>  &cl_dw     uimm   rs1 rd
>> +&ci        imm        rd
>>  &ciw       nzuimm     rd
>>  &cs               rs1 rs2
>>  &cs_dw     uimm   rs1 rs2
>> +&cb        imm    rs1
>> +&cr               rd  rs2
>> +&cj       imm
>> +&c_shift   shamt      rd
>> +
>>
>> +&caddi16sp_lui  imm_lui imm_addi16sp rd
>>
>>  # Formats 16:
>> +@ci        ... . ..... .....  .. &ci     imm=%imm_ci                  %rd
>>  @ciw       ...   ........ ... .. &ciw    nzuimm=%nzuimm_ciw           rd=%rs2_3
>>  @cl_d      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rd=%rs2_3
>>  @cl_w      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rd=%rs2_3
>>  @cl        ... ... ... .. ... .. &cl                      rs1=%rs1_3  rd=%rs2_3
>>  @cs        ... ... ... .. ... .. &cs                      rs1=%rs1_3  rs2=%rs2_3
>> +@cs_2      ... ... ... .. ... .. &cr                      rd=%rs1_3   rs2=%rs2_3
>>  @cs_d      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rs2=%rs2_3
>>  @cs_w      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rs2=%rs2_3
>> +@cb        ... ... ... .. ... .. &cb     imm=%imm_cb      rs1=%rs1_3
>> +@cj        ...    ........... .. &cj     imm=%imm_cj
>>
>> +@c_addi16sp_lui ... .  ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd
>> +
>> +@c_shift        ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit
>> +
>> +@c_andi         ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3
>>
>>  # *** RV64C Standard Extension (Quadrant 0) ***
>>  c_addi4spn        000    ........ ... 00 @ciw
>> @@ -53,3 +78,21 @@ c_flw_ld          011  --- ... -- ... 00 @cl    #Note: Must parse uimm manually
>>  c_fsd             101  ... ... .. ... 00 @cs_d
>>  c_sw              110  ... ... .. ... 00 @cs_w
>>  c_fsw_sd          111  --- ... -- ... 00 @cs    #Note: Must parse uimm manually
>> +
>> +# *** RV64C Standard Extension (Quadrant 1) ***
>> +c_addi            000 .  .....  ..... 01 @ci
>> +c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm manually
>> +c_li              010 .  .....  ..... 01 @ci
>> +c_addi16sp_lui    011 .  .....  ..... 01 @c_addi16sp_lui # shares opc with C.LUI
>> +c_srli            100 . 00 ...  ..... 01 @c_shift
>> +c_srai            100 . 01 ...  ..... 01 @c_shift
>> +c_andi            100 . 10 ...  ..... 01 @c_andi
>> +c_sub             100 0 11 ... 00 ... 01 @cs_2
>> +c_xor             100 0 11 ... 01 ... 01 @cs_2
>> +c_or              100 0 11 ... 10 ... 01 @cs_2
>> +c_and             100 0 11 ... 11 ... 01 @cs_2
>> +c_subw            100 1 11 ... 00 ... 01 @cs_2
>> +c_addw            100 1 11 ... 01 ... 01 @cs_2
>> +c_j               101     ........... 01 @cj
>> +c_beqz            110  ... ...  ..... 01 @cb
>> +c_bnez            111  ... ...  ..... 01 @cb
>> diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c
>> index 93ec8aa30b95..b06c435c9800 100644
>> --- a/target/riscv/insn_trans/trans_rvc.inc.c
>> +++ b/target/riscv/insn_trans/trans_rvc.inc.c
>> @@ -73,3 +73,154 @@ static bool trans_c_fsw_sd(DisasContext *ctx, arg_c_fsw_sd *a)
>>      return false;
>>  #endif
>>  }
>> +
>> +static bool trans_c_addi(DisasContext *ctx, arg_c_addi *a)
>> +{
>> +    if (a->imm == 0) {
>> +        /* Hint: insn is valid but does not affect state */
>> +        return true;
>> +    }
>> +    arg_addi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
>> +    return trans_addi(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a)
>> +{
>> +#ifdef TARGET_RISCV32
>> +    /* C.JAL */
>> +    arg_jal arg = { .rd = 1, .imm = a->imm };
>> +    return trans_jal(ctx, &arg);
>> +#else
>> +    /* C.ADDIW */
>> +    arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
>> +    return trans_addiw(ctx, &arg);
>> +#endif
>> +}
>> +
>> +static bool trans_c_li(DisasContext *ctx, arg_c_li *a)
>> +{
>> +    if (a->rd == 0) {
>> +        /* Hint: insn is valid but does not affect state */
>> +        return true;
>> +    }
>> +    arg_addi arg = { .rd = a->rd, .rs1 = 0, .imm = a->imm };
>> +    return trans_addi(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_addi16sp_lui(DisasContext *ctx, arg_c_addi16sp_lui *a)
>> +{
>> +    if (a->rd == 2) {
>> +        /* C.ADDI16SP */
>> +        arg_addi arg = { .rd = 2, .rs1 = 2, .imm = a->imm_addi16sp };
>> +        return trans_addi(ctx, &arg);
>> +    } else if (a->imm_lui != 0) {
>> +        /* C.LUI */
>> +        if (a->rd == 0) {
>> +            /* Hint: insn is valid but does not affect state */
>> +            return true;
>> +        }
>> +        arg_lui arg = { .rd = a->rd, .imm = a->imm_lui };
>> +        return trans_lui(ctx, &arg);
>> +    }
>> +    return false;
>> +}
>> +
>> +static bool trans_c_srli(DisasContext *ctx, arg_c_srli *a)
>> +{
>> +    int shamt = a->shamt;
>> +    if (shamt == 0) {
>> +        /* For RV128 a shamt of 0 means a shift by 64 */
>> +        shamt = 64;
>> +    }
>> +    /* Ensure, that shamt[5] is zero for RV32 */
>> +    if (shamt >= TARGET_LONG_BITS) {
>> +        return false;
>> +    }
>> +
>> +    arg_srli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
>> +    return trans_srli(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_srai(DisasContext *ctx, arg_c_srai *a)
>> +{
>> +    int shamt = a->shamt;
>> +    if (shamt == 0) {
>> +        /* For RV128 a shamt of 0 means a shift by 64 */
>> +        shamt = 64;
>> +    }
>> +    /* Ensure, that shamt[5] is zero for RV32 */
>> +    if (shamt >= TARGET_LONG_BITS) {
>> +        return false;
>> +    }
>> +
>> +    arg_srai arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
>> +    return trans_srai(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_andi(DisasContext *ctx, arg_c_andi *a)
>> +{
>> +    arg_andi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
>> +    return trans_andi(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_sub(DisasContext *ctx, arg_c_sub *a)
>> +{
>> +    arg_sub arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> +    return trans_sub(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_xor(DisasContext *ctx, arg_c_xor *a)
>> +{
>> +    arg_xor arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> +    return trans_xor(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_or(DisasContext *ctx, arg_c_or *a)
>> +{
>> +    arg_or arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> +    return trans_or(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_and(DisasContext *ctx, arg_c_and *a)
>> +{
>> +    arg_and arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> +    return trans_and(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_subw(DisasContext *ctx, arg_c_subw *a)
>> +{
>> +#ifdef TARGET_RISCV64
>> +    arg_subw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> +    return trans_subw(ctx, &arg);
>> +#else
>> +    return false;
>> +#endif
>> +}
>> +
>> +static bool trans_c_addw(DisasContext *ctx, arg_c_addw *a)
>> +{
>> +#ifdef TARGET_RISCV64
>> +    arg_addw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> +    return trans_addw(ctx, &arg);
>> +#else
>> +    return false;
>> +#endif
>> +}
>> +
>> +static bool trans_c_j(DisasContext *ctx, arg_c_j *a)
>> +{
>> +    arg_jal arg = { .rd = 0, .imm = a->imm };
>> +    return trans_jal(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_beqz(DisasContext *ctx, arg_c_beqz *a)
>> +{
>> +    arg_beq arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
>> +    return trans_beq(ctx, &arg);
>> +}
>> +
>> +static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a)
>> +{
>> +    arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
>> +    return trans_bne(ctx, &arg);
>> +}
>> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
>> index 0106fa8d51b3..a584c24fbf6b 100644
>> --- a/target/riscv/translate.c
>> +++ b/target/riscv/translate.c
>> @@ -828,120 +828,6 @@ static void decode_RV32_64C0(DisasContext *ctx)
>>      }
>>  }
>>
>> -static void decode_RV32_64C1(DisasContext *ctx)
>> -{
>> -    uint8_t funct3 = extract32(ctx->opcode, 13, 3);
>> -    uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
>> -    uint8_t rs1s, rs2s;
>> -    uint8_t funct2;
>> -
>> -    switch (funct3) {
>> -    case 0:
>> -        /* C.ADDI -> addi rd, rd, nzimm[5:0] */
>> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, rd_rs1,
>> -                      GET_C_IMM(ctx->opcode));
>> -        break;
>> -    case 1:
>> -#if defined(TARGET_RISCV64)
>> -        /* C.ADDIW (RV64/128) -> addiw rd, rd, imm[5:0]*/
>> -        gen_arith_imm(ctx, OPC_RISC_ADDIW, rd_rs1, rd_rs1,
>> -                      GET_C_IMM(ctx->opcode));
>> -#else
>> -        /* C.JAL(RV32) -> jal x1, offset[11:1] */
>> -        gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
>> -#endif
>> -        break;
>> -    case 2:
>> -        /* C.LI -> addi rd, x0, imm[5:0]*/
>> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, 0, GET_C_IMM(ctx->opcode));
>> -        break;
>> -    case 3:
>> -        if (rd_rs1 == 2) {
>> -            /* C.ADDI16SP -> addi x2, x2, nzimm[9:4]*/
>> -            gen_arith_imm(ctx, OPC_RISC_ADDI, 2, 2,
>> -                          GET_C_ADDI16SP_IMM(ctx->opcode));
>> -        } else if (rd_rs1 != 0) {
>> -            /* C.LUI (rs1/rd =/= {0,2}) -> lui rd, nzimm[17:12]*/
>> -            tcg_gen_movi_tl(cpu_gpr[rd_rs1],
>> -                            GET_C_IMM(ctx->opcode) << 12);
>> -        }
>> -        break;
>> -    case 4:
>> -        funct2 = extract32(ctx->opcode, 10, 2);
>> -        rs1s = GET_C_RS1S(ctx->opcode);
>> -        switch (funct2) {
>> -        case 0: /* C.SRLI(RV32) -> srli rd', rd', shamt[5:0] */
>> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
>> -                               GET_C_ZIMM(ctx->opcode));
>> -            /* C.SRLI64(RV128) */
>> -            break;
>> -        case 1:
>> -            /* C.SRAI -> srai rd', rd', shamt[5:0]*/
>> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
>> -                            GET_C_ZIMM(ctx->opcode) | 0x400);
>> -            /* C.SRAI64(RV128) */
>> -            break;
>> -        case 2:
>> -            /* C.ANDI -> andi rd', rd', imm[5:0]*/
>> -            gen_arith_imm(ctx, OPC_RISC_ANDI, rs1s, rs1s,
>> -                          GET_C_IMM(ctx->opcode));
>> -            break;
>> -        case 3:
>> -            funct2 = extract32(ctx->opcode, 5, 2);
>> -            rs2s = GET_C_RS2S(ctx->opcode);
>> -            switch (funct2) {
>> -            case 0:
>> -                /* C.SUB -> sub rd', rd', rs2' */
>> -                if (extract32(ctx->opcode, 12, 1) == 0) {
>> -                    gen_arith(ctx, OPC_RISC_SUB, rs1s, rs1s, rs2s);
>> -                }
>> -#if defined(TARGET_RISCV64)
>> -                else {
>> -                    gen_arith(ctx, OPC_RISC_SUBW, rs1s, rs1s, rs2s);
>> -                }
>> -#endif
>> -                break;
>> -            case 1:
>> -                /* C.XOR -> xor rs1', rs1', rs2' */
>> -                if (extract32(ctx->opcode, 12, 1) == 0) {
>> -                    gen_arith(ctx, OPC_RISC_XOR, rs1s, rs1s, rs2s);
>> -                }
>> -#if defined(TARGET_RISCV64)
>> -                else {
>> -                    /* C.ADDW (RV64/128) */
>> -                    gen_arith(ctx, OPC_RISC_ADDW, rs1s, rs1s, rs2s);
>> -                }
>> -#endif
>> -                break;
>> -            case 2:
>> -                /* C.OR -> or rs1', rs1', rs2' */
>> -                gen_arith(ctx, OPC_RISC_OR, rs1s, rs1s, rs2s);
>> -                break;
>> -            case 3:
>> -                /* C.AND -> and rs1', rs1', rs2' */
>> -                gen_arith(ctx, OPC_RISC_AND, rs1s, rs1s, rs2s);
>> -                break;
>> -            }
>> -            break;
>> -        }
>> -        break;
>> -    case 5:
>> -        /* C.J -> jal x0, offset[11:1]*/
>> -        gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
>> -        break;
>> -    case 6:
>> -        /* C.BEQZ -> beq rs1', x0, offset[8:1]*/
>> -        rs1s = GET_C_RS1S(ctx->opcode);
>> -        gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
>> -        break;
>> -    case 7:
>> -        /* C.BNEZ -> bne rs1', x0, offset[8:1]*/
>> -        rs1s = GET_C_RS1S(ctx->opcode);
>> -        gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
>> -        break;
>> -    }
>> -}
>> -
>>  static void decode_RV32_64C2(DisasContext *ctx)
>>  {
>>      uint8_t rd, rs2;
>> @@ -1028,9 +914,6 @@ static void decode_RV32_64C(DisasContext *ctx)
>>      case 0:
>>          decode_RV32_64C0(ctx);
>>          break;
>> -    case 1:
>> -        decode_RV32_64C1(ctx);
>> -        break;
>>      case 2:
>>          decode_RV32_64C2(ctx);
>>          break;
>> @@ -1045,6 +928,7 @@ static void decode_RV32_64C(DisasContext *ctx)
>>  EX_SH(1)
>>  EX_SH(2)
>>  EX_SH(3)
>> +EX_SH(4)
>>  EX_SH(12)
>>
>>  #define REQUIRE_EXT(ctx, ext) do { \
>> --
>> 2.19.2
>>
>>
Alistair Francis March 15, 2019, 4:57 a.m. UTC | #3
On Thu, Mar 14, 2019 at 8:59 PM Palmer Dabbelt <palmer@sifive.com> wrote:
>
> On Thu, 14 Mar 2019 13:28:37 PDT (-0700), alistair23@gmail.com wrote:
> > On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com> wrote:
> >>
> >> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> >>
> >> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> >> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> >> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
> >
> > This commit is the first bad commit in breaking 32-bit boot.
> >
> > It looks like the jal doesn't jump to the correct address:
> >
> > ----------------
> > IN:
> > 0x80000022:  00050433          add             s0,a0,zero
> > 0x80000026:  000584b3          add             s1,a1,zero
> > 0x8000002a:  2c79              jal             ra,670          # 0x800002c8
> >
> > ----------------
> > IN:
> > 0x800002c8:  00000533          add             a0,zero,zero
> > 0x800002cc:  8082              ret
>
>
> Sorry, for some reason I thought you'd tested this on 32-bit?  Do you have a
> workflow that I can use to reproduce the bug?

I did! Not sure what happened there. Maybe something changed between
what I tested and what was merged or somehow I tested the wrong thing.

Just booting 32-bit OpenSBI fails. It seems that the imm for jal is
wrong. I'll keep digging into it.

Alistair

>
> >
> >
> > Alistair
> >
> >> ---
> >>  target/riscv/insn16.decode              |  43 +++++++
> >>  target/riscv/insn_trans/trans_rvc.inc.c | 151 ++++++++++++++++++++++++
> >>  target/riscv/translate.c                | 118 +-----------------
> >>  3 files changed, 195 insertions(+), 117 deletions(-)
> >>
> >> diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
> >> index 558c0c41f0b5..45109301c6d4 100644
> >> --- a/target/riscv/insn16.decode
> >> +++ b/target/riscv/insn16.decode
> >> @@ -22,28 +22,53 @@
> >>  %rs2_3     2:3                !function=ex_rvc_register
> >>
> >>  # Immediates:
> >> +%imm_ci        12:s1 2:5
> >>  %nzuimm_ciw    7:4 11:2 5:1 6:1   !function=ex_shift_2
> >>  %uimm_cl_d     5:2 10:3           !function=ex_shift_3
> >>  %uimm_cl_w     5:1 10:3 6:1       !function=ex_shift_2
> >> +%imm_cb        12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
> >> +%imm_cj        12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
> >> +
> >> +%nzuimm_6bit   12:1 2:5
> >> +
> >> +%imm_addi16sp  12:s1 3:2 5:1 2:1 6:1 !function=ex_shift_4
> >> +%imm_lui       12:s1 2:5             !function=ex_shift_12
> >> +
> >>
> >>
> >>  # Argument sets:
> >>  &cl               rs1 rd
> >>  &cl_dw     uimm   rs1 rd
> >> +&ci        imm        rd
> >>  &ciw       nzuimm     rd
> >>  &cs               rs1 rs2
> >>  &cs_dw     uimm   rs1 rs2
> >> +&cb        imm    rs1
> >> +&cr               rd  rs2
> >> +&cj       imm
> >> +&c_shift   shamt      rd
> >> +
> >>
> >> +&caddi16sp_lui  imm_lui imm_addi16sp rd
> >>
> >>  # Formats 16:
> >> +@ci        ... . ..... .....  .. &ci     imm=%imm_ci                  %rd
> >>  @ciw       ...   ........ ... .. &ciw    nzuimm=%nzuimm_ciw           rd=%rs2_3
> >>  @cl_d      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rd=%rs2_3
> >>  @cl_w      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rd=%rs2_3
> >>  @cl        ... ... ... .. ... .. &cl                      rs1=%rs1_3  rd=%rs2_3
> >>  @cs        ... ... ... .. ... .. &cs                      rs1=%rs1_3  rs2=%rs2_3
> >> +@cs_2      ... ... ... .. ... .. &cr                      rd=%rs1_3   rs2=%rs2_3
> >>  @cs_d      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rs2=%rs2_3
> >>  @cs_w      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rs2=%rs2_3
> >> +@cb        ... ... ... .. ... .. &cb     imm=%imm_cb      rs1=%rs1_3
> >> +@cj        ...    ........... .. &cj     imm=%imm_cj
> >>
> >> +@c_addi16sp_lui ... .  ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd
> >> +
> >> +@c_shift        ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit
> >> +
> >> +@c_andi         ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3
> >>
> >>  # *** RV64C Standard Extension (Quadrant 0) ***
> >>  c_addi4spn        000    ........ ... 00 @ciw
> >> @@ -53,3 +78,21 @@ c_flw_ld          011  --- ... -- ... 00 @cl    #Note: Must parse uimm manually
> >>  c_fsd             101  ... ... .. ... 00 @cs_d
> >>  c_sw              110  ... ... .. ... 00 @cs_w
> >>  c_fsw_sd          111  --- ... -- ... 00 @cs    #Note: Must parse uimm manually
> >> +
> >> +# *** RV64C Standard Extension (Quadrant 1) ***
> >> +c_addi            000 .  .....  ..... 01 @ci
> >> +c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm manually
> >> +c_li              010 .  .....  ..... 01 @ci
> >> +c_addi16sp_lui    011 .  .....  ..... 01 @c_addi16sp_lui # shares opc with C.LUI
> >> +c_srli            100 . 00 ...  ..... 01 @c_shift
> >> +c_srai            100 . 01 ...  ..... 01 @c_shift
> >> +c_andi            100 . 10 ...  ..... 01 @c_andi
> >> +c_sub             100 0 11 ... 00 ... 01 @cs_2
> >> +c_xor             100 0 11 ... 01 ... 01 @cs_2
> >> +c_or              100 0 11 ... 10 ... 01 @cs_2
> >> +c_and             100 0 11 ... 11 ... 01 @cs_2
> >> +c_subw            100 1 11 ... 00 ... 01 @cs_2
> >> +c_addw            100 1 11 ... 01 ... 01 @cs_2
> >> +c_j               101     ........... 01 @cj
> >> +c_beqz            110  ... ...  ..... 01 @cb
> >> +c_bnez            111  ... ...  ..... 01 @cb
> >> diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c
> >> index 93ec8aa30b95..b06c435c9800 100644
> >> --- a/target/riscv/insn_trans/trans_rvc.inc.c
> >> +++ b/target/riscv/insn_trans/trans_rvc.inc.c
> >> @@ -73,3 +73,154 @@ static bool trans_c_fsw_sd(DisasContext *ctx, arg_c_fsw_sd *a)
> >>      return false;
> >>  #endif
> >>  }
> >> +
> >> +static bool trans_c_addi(DisasContext *ctx, arg_c_addi *a)
> >> +{
> >> +    if (a->imm == 0) {
> >> +        /* Hint: insn is valid but does not affect state */
> >> +        return true;
> >> +    }
> >> +    arg_addi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
> >> +    return trans_addi(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a)
> >> +{
> >> +#ifdef TARGET_RISCV32
> >> +    /* C.JAL */
> >> +    arg_jal arg = { .rd = 1, .imm = a->imm };
> >> +    return trans_jal(ctx, &arg);
> >> +#else
> >> +    /* C.ADDIW */
> >> +    arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
> >> +    return trans_addiw(ctx, &arg);
> >> +#endif
> >> +}
> >> +
> >> +static bool trans_c_li(DisasContext *ctx, arg_c_li *a)
> >> +{
> >> +    if (a->rd == 0) {
> >> +        /* Hint: insn is valid but does not affect state */
> >> +        return true;
> >> +    }
> >> +    arg_addi arg = { .rd = a->rd, .rs1 = 0, .imm = a->imm };
> >> +    return trans_addi(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_addi16sp_lui(DisasContext *ctx, arg_c_addi16sp_lui *a)
> >> +{
> >> +    if (a->rd == 2) {
> >> +        /* C.ADDI16SP */
> >> +        arg_addi arg = { .rd = 2, .rs1 = 2, .imm = a->imm_addi16sp };
> >> +        return trans_addi(ctx, &arg);
> >> +    } else if (a->imm_lui != 0) {
> >> +        /* C.LUI */
> >> +        if (a->rd == 0) {
> >> +            /* Hint: insn is valid but does not affect state */
> >> +            return true;
> >> +        }
> >> +        arg_lui arg = { .rd = a->rd, .imm = a->imm_lui };
> >> +        return trans_lui(ctx, &arg);
> >> +    }
> >> +    return false;
> >> +}
> >> +
> >> +static bool trans_c_srli(DisasContext *ctx, arg_c_srli *a)
> >> +{
> >> +    int shamt = a->shamt;
> >> +    if (shamt == 0) {
> >> +        /* For RV128 a shamt of 0 means a shift by 64 */
> >> +        shamt = 64;
> >> +    }
> >> +    /* Ensure, that shamt[5] is zero for RV32 */
> >> +    if (shamt >= TARGET_LONG_BITS) {
> >> +        return false;
> >> +    }
> >> +
> >> +    arg_srli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
> >> +    return trans_srli(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_srai(DisasContext *ctx, arg_c_srai *a)
> >> +{
> >> +    int shamt = a->shamt;
> >> +    if (shamt == 0) {
> >> +        /* For RV128 a shamt of 0 means a shift by 64 */
> >> +        shamt = 64;
> >> +    }
> >> +    /* Ensure, that shamt[5] is zero for RV32 */
> >> +    if (shamt >= TARGET_LONG_BITS) {
> >> +        return false;
> >> +    }
> >> +
> >> +    arg_srai arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
> >> +    return trans_srai(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_andi(DisasContext *ctx, arg_c_andi *a)
> >> +{
> >> +    arg_andi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
> >> +    return trans_andi(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_sub(DisasContext *ctx, arg_c_sub *a)
> >> +{
> >> +    arg_sub arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> >> +    return trans_sub(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_xor(DisasContext *ctx, arg_c_xor *a)
> >> +{
> >> +    arg_xor arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> >> +    return trans_xor(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_or(DisasContext *ctx, arg_c_or *a)
> >> +{
> >> +    arg_or arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> >> +    return trans_or(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_and(DisasContext *ctx, arg_c_and *a)
> >> +{
> >> +    arg_and arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> >> +    return trans_and(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_subw(DisasContext *ctx, arg_c_subw *a)
> >> +{
> >> +#ifdef TARGET_RISCV64
> >> +    arg_subw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> >> +    return trans_subw(ctx, &arg);
> >> +#else
> >> +    return false;
> >> +#endif
> >> +}
> >> +
> >> +static bool trans_c_addw(DisasContext *ctx, arg_c_addw *a)
> >> +{
> >> +#ifdef TARGET_RISCV64
> >> +    arg_addw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
> >> +    return trans_addw(ctx, &arg);
> >> +#else
> >> +    return false;
> >> +#endif
> >> +}
> >> +
> >> +static bool trans_c_j(DisasContext *ctx, arg_c_j *a)
> >> +{
> >> +    arg_jal arg = { .rd = 0, .imm = a->imm };
> >> +    return trans_jal(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_beqz(DisasContext *ctx, arg_c_beqz *a)
> >> +{
> >> +    arg_beq arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
> >> +    return trans_beq(ctx, &arg);
> >> +}
> >> +
> >> +static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a)
> >> +{
> >> +    arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
> >> +    return trans_bne(ctx, &arg);
> >> +}
> >> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> >> index 0106fa8d51b3..a584c24fbf6b 100644
> >> --- a/target/riscv/translate.c
> >> +++ b/target/riscv/translate.c
> >> @@ -828,120 +828,6 @@ static void decode_RV32_64C0(DisasContext *ctx)
> >>      }
> >>  }
> >>
> >> -static void decode_RV32_64C1(DisasContext *ctx)
> >> -{
> >> -    uint8_t funct3 = extract32(ctx->opcode, 13, 3);
> >> -    uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
> >> -    uint8_t rs1s, rs2s;
> >> -    uint8_t funct2;
> >> -
> >> -    switch (funct3) {
> >> -    case 0:
> >> -        /* C.ADDI -> addi rd, rd, nzimm[5:0] */
> >> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, rd_rs1,
> >> -                      GET_C_IMM(ctx->opcode));
> >> -        break;
> >> -    case 1:
> >> -#if defined(TARGET_RISCV64)
> >> -        /* C.ADDIW (RV64/128) -> addiw rd, rd, imm[5:0]*/
> >> -        gen_arith_imm(ctx, OPC_RISC_ADDIW, rd_rs1, rd_rs1,
> >> -                      GET_C_IMM(ctx->opcode));
> >> -#else
> >> -        /* C.JAL(RV32) -> jal x1, offset[11:1] */
> >> -        gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
> >> -#endif
> >> -        break;
> >> -    case 2:
> >> -        /* C.LI -> addi rd, x0, imm[5:0]*/
> >> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, 0, GET_C_IMM(ctx->opcode));
> >> -        break;
> >> -    case 3:
> >> -        if (rd_rs1 == 2) {
> >> -            /* C.ADDI16SP -> addi x2, x2, nzimm[9:4]*/
> >> -            gen_arith_imm(ctx, OPC_RISC_ADDI, 2, 2,
> >> -                          GET_C_ADDI16SP_IMM(ctx->opcode));
> >> -        } else if (rd_rs1 != 0) {
> >> -            /* C.LUI (rs1/rd =/= {0,2}) -> lui rd, nzimm[17:12]*/
> >> -            tcg_gen_movi_tl(cpu_gpr[rd_rs1],
> >> -                            GET_C_IMM(ctx->opcode) << 12);
> >> -        }
> >> -        break;
> >> -    case 4:
> >> -        funct2 = extract32(ctx->opcode, 10, 2);
> >> -        rs1s = GET_C_RS1S(ctx->opcode);
> >> -        switch (funct2) {
> >> -        case 0: /* C.SRLI(RV32) -> srli rd', rd', shamt[5:0] */
> >> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
> >> -                               GET_C_ZIMM(ctx->opcode));
> >> -            /* C.SRLI64(RV128) */
> >> -            break;
> >> -        case 1:
> >> -            /* C.SRAI -> srai rd', rd', shamt[5:0]*/
> >> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
> >> -                            GET_C_ZIMM(ctx->opcode) | 0x400);
> >> -            /* C.SRAI64(RV128) */
> >> -            break;
> >> -        case 2:
> >> -            /* C.ANDI -> andi rd', rd', imm[5:0]*/
> >> -            gen_arith_imm(ctx, OPC_RISC_ANDI, rs1s, rs1s,
> >> -                          GET_C_IMM(ctx->opcode));
> >> -            break;
> >> -        case 3:
> >> -            funct2 = extract32(ctx->opcode, 5, 2);
> >> -            rs2s = GET_C_RS2S(ctx->opcode);
> >> -            switch (funct2) {
> >> -            case 0:
> >> -                /* C.SUB -> sub rd', rd', rs2' */
> >> -                if (extract32(ctx->opcode, 12, 1) == 0) {
> >> -                    gen_arith(ctx, OPC_RISC_SUB, rs1s, rs1s, rs2s);
> >> -                }
> >> -#if defined(TARGET_RISCV64)
> >> -                else {
> >> -                    gen_arith(ctx, OPC_RISC_SUBW, rs1s, rs1s, rs2s);
> >> -                }
> >> -#endif
> >> -                break;
> >> -            case 1:
> >> -                /* C.XOR -> xor rs1', rs1', rs2' */
> >> -                if (extract32(ctx->opcode, 12, 1) == 0) {
> >> -                    gen_arith(ctx, OPC_RISC_XOR, rs1s, rs1s, rs2s);
> >> -                }
> >> -#if defined(TARGET_RISCV64)
> >> -                else {
> >> -                    /* C.ADDW (RV64/128) */
> >> -                    gen_arith(ctx, OPC_RISC_ADDW, rs1s, rs1s, rs2s);
> >> -                }
> >> -#endif
> >> -                break;
> >> -            case 2:
> >> -                /* C.OR -> or rs1', rs1', rs2' */
> >> -                gen_arith(ctx, OPC_RISC_OR, rs1s, rs1s, rs2s);
> >> -                break;
> >> -            case 3:
> >> -                /* C.AND -> and rs1', rs1', rs2' */
> >> -                gen_arith(ctx, OPC_RISC_AND, rs1s, rs1s, rs2s);
> >> -                break;
> >> -            }
> >> -            break;
> >> -        }
> >> -        break;
> >> -    case 5:
> >> -        /* C.J -> jal x0, offset[11:1]*/
> >> -        gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
> >> -        break;
> >> -    case 6:
> >> -        /* C.BEQZ -> beq rs1', x0, offset[8:1]*/
> >> -        rs1s = GET_C_RS1S(ctx->opcode);
> >> -        gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
> >> -        break;
> >> -    case 7:
> >> -        /* C.BNEZ -> bne rs1', x0, offset[8:1]*/
> >> -        rs1s = GET_C_RS1S(ctx->opcode);
> >> -        gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
> >> -        break;
> >> -    }
> >> -}
> >> -
> >>  static void decode_RV32_64C2(DisasContext *ctx)
> >>  {
> >>      uint8_t rd, rs2;
> >> @@ -1028,9 +914,6 @@ static void decode_RV32_64C(DisasContext *ctx)
> >>      case 0:
> >>          decode_RV32_64C0(ctx);
> >>          break;
> >> -    case 1:
> >> -        decode_RV32_64C1(ctx);
> >> -        break;
> >>      case 2:
> >>          decode_RV32_64C2(ctx);
> >>          break;
> >> @@ -1045,6 +928,7 @@ static void decode_RV32_64C(DisasContext *ctx)
> >>  EX_SH(1)
> >>  EX_SH(2)
> >>  EX_SH(3)
> >> +EX_SH(4)
> >>  EX_SH(12)
> >>
> >>  #define REQUIRE_EXT(ctx, ext) do { \
> >> --
> >> 2.19.2
> >>
> >>
Palmer Dabbelt March 15, 2019, 5:26 a.m. UTC | #4
On Thu, 14 Mar 2019 21:57:37 PDT (-0700), alistair23@gmail.com wrote:
> On Thu, Mar 14, 2019 at 8:59 PM Palmer Dabbelt <palmer@sifive.com> wrote:
>>
>> On Thu, 14 Mar 2019 13:28:37 PDT (-0700), alistair23@gmail.com wrote:
>> > On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com> wrote:
>> >>
>> >> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>> >>
>> >> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> >> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>> >> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
>> >
>> > This commit is the first bad commit in breaking 32-bit boot.
>> >
>> > It looks like the jal doesn't jump to the correct address:
>> >
>> > ----------------
>> > IN:
>> > 0x80000022:  00050433          add             s0,a0,zero
>> > 0x80000026:  000584b3          add             s1,a1,zero
>> > 0x8000002a:  2c79              jal             ra,670          # 0x800002c8
>> >
>> > ----------------
>> > IN:
>> > 0x800002c8:  00000533          add             a0,zero,zero
>> > 0x800002cc:  8082              ret
>>
>>
>> Sorry, for some reason I thought you'd tested this on 32-bit?  Do you have a
>> workflow that I can use to reproduce the bug?
>
> I did! Not sure what happened there. Maybe something changed between
> what I tested and what was merged or somehow I tested the wrong thing.
>
> Just booting 32-bit OpenSBI fails. It seems that the imm for jal is
> wrong. I'll keep digging into it.

OK, thanks.  There was some jiggling around of the patch due to OSX build 
issues, maybe that broke something in 32-bit land?

>
> Alistair
>
>>
>> >
>> >
>> > Alistair
>> >
>> >> ---
>> >>  target/riscv/insn16.decode              |  43 +++++++
>> >>  target/riscv/insn_trans/trans_rvc.inc.c | 151 ++++++++++++++++++++++++
>> >>  target/riscv/translate.c                | 118 +-----------------
>> >>  3 files changed, 195 insertions(+), 117 deletions(-)
>> >>
>> >> diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
>> >> index 558c0c41f0b5..45109301c6d4 100644
>> >> --- a/target/riscv/insn16.decode
>> >> +++ b/target/riscv/insn16.decode
>> >> @@ -22,28 +22,53 @@
>> >>  %rs2_3     2:3                !function=ex_rvc_register
>> >>
>> >>  # Immediates:
>> >> +%imm_ci        12:s1 2:5
>> >>  %nzuimm_ciw    7:4 11:2 5:1 6:1   !function=ex_shift_2
>> >>  %uimm_cl_d     5:2 10:3           !function=ex_shift_3
>> >>  %uimm_cl_w     5:1 10:3 6:1       !function=ex_shift_2
>> >> +%imm_cb        12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
>> >> +%imm_cj        12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
>> >> +
>> >> +%nzuimm_6bit   12:1 2:5
>> >> +
>> >> +%imm_addi16sp  12:s1 3:2 5:1 2:1 6:1 !function=ex_shift_4
>> >> +%imm_lui       12:s1 2:5             !function=ex_shift_12
>> >> +
>> >>
>> >>
>> >>  # Argument sets:
>> >>  &cl               rs1 rd
>> >>  &cl_dw     uimm   rs1 rd
>> >> +&ci        imm        rd
>> >>  &ciw       nzuimm     rd
>> >>  &cs               rs1 rs2
>> >>  &cs_dw     uimm   rs1 rs2
>> >> +&cb        imm    rs1
>> >> +&cr               rd  rs2
>> >> +&cj       imm
>> >> +&c_shift   shamt      rd
>> >> +
>> >>
>> >> +&caddi16sp_lui  imm_lui imm_addi16sp rd
>> >>
>> >>  # Formats 16:
>> >> +@ci        ... . ..... .....  .. &ci     imm=%imm_ci                  %rd
>> >>  @ciw       ...   ........ ... .. &ciw    nzuimm=%nzuimm_ciw           rd=%rs2_3
>> >>  @cl_d      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rd=%rs2_3
>> >>  @cl_w      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rd=%rs2_3
>> >>  @cl        ... ... ... .. ... .. &cl                      rs1=%rs1_3  rd=%rs2_3
>> >>  @cs        ... ... ... .. ... .. &cs                      rs1=%rs1_3  rs2=%rs2_3
>> >> +@cs_2      ... ... ... .. ... .. &cr                      rd=%rs1_3   rs2=%rs2_3
>> >>  @cs_d      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rs2=%rs2_3
>> >>  @cs_w      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rs2=%rs2_3
>> >> +@cb        ... ... ... .. ... .. &cb     imm=%imm_cb      rs1=%rs1_3
>> >> +@cj        ...    ........... .. &cj     imm=%imm_cj
>> >>
>> >> +@c_addi16sp_lui ... .  ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd
>> >> +
>> >> +@c_shift        ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit
>> >> +
>> >> +@c_andi         ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3
>> >>
>> >>  # *** RV64C Standard Extension (Quadrant 0) ***
>> >>  c_addi4spn        000    ........ ... 00 @ciw
>> >> @@ -53,3 +78,21 @@ c_flw_ld          011  --- ... -- ... 00 @cl    #Note: Must parse uimm manually
>> >>  c_fsd             101  ... ... .. ... 00 @cs_d
>> >>  c_sw              110  ... ... .. ... 00 @cs_w
>> >>  c_fsw_sd          111  --- ... -- ... 00 @cs    #Note: Must parse uimm manually
>> >> +
>> >> +# *** RV64C Standard Extension (Quadrant 1) ***
>> >> +c_addi            000 .  .....  ..... 01 @ci
>> >> +c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm manually
>> >> +c_li              010 .  .....  ..... 01 @ci
>> >> +c_addi16sp_lui    011 .  .....  ..... 01 @c_addi16sp_lui # shares opc with C.LUI
>> >> +c_srli            100 . 00 ...  ..... 01 @c_shift
>> >> +c_srai            100 . 01 ...  ..... 01 @c_shift
>> >> +c_andi            100 . 10 ...  ..... 01 @c_andi
>> >> +c_sub             100 0 11 ... 00 ... 01 @cs_2
>> >> +c_xor             100 0 11 ... 01 ... 01 @cs_2
>> >> +c_or              100 0 11 ... 10 ... 01 @cs_2
>> >> +c_and             100 0 11 ... 11 ... 01 @cs_2
>> >> +c_subw            100 1 11 ... 00 ... 01 @cs_2
>> >> +c_addw            100 1 11 ... 01 ... 01 @cs_2
>> >> +c_j               101     ........... 01 @cj
>> >> +c_beqz            110  ... ...  ..... 01 @cb
>> >> +c_bnez            111  ... ...  ..... 01 @cb
>> >> diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c
>> >> index 93ec8aa30b95..b06c435c9800 100644
>> >> --- a/target/riscv/insn_trans/trans_rvc.inc.c
>> >> +++ b/target/riscv/insn_trans/trans_rvc.inc.c
>> >> @@ -73,3 +73,154 @@ static bool trans_c_fsw_sd(DisasContext *ctx, arg_c_fsw_sd *a)
>> >>      return false;
>> >>  #endif
>> >>  }
>> >> +
>> >> +static bool trans_c_addi(DisasContext *ctx, arg_c_addi *a)
>> >> +{
>> >> +    if (a->imm == 0) {
>> >> +        /* Hint: insn is valid but does not affect state */
>> >> +        return true;
>> >> +    }
>> >> +    arg_addi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
>> >> +    return trans_addi(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a)
>> >> +{
>> >> +#ifdef TARGET_RISCV32
>> >> +    /* C.JAL */
>> >> +    arg_jal arg = { .rd = 1, .imm = a->imm };
>> >> +    return trans_jal(ctx, &arg);
>> >> +#else
>> >> +    /* C.ADDIW */
>> >> +    arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
>> >> +    return trans_addiw(ctx, &arg);
>> >> +#endif
>> >> +}
>> >> +
>> >> +static bool trans_c_li(DisasContext *ctx, arg_c_li *a)
>> >> +{
>> >> +    if (a->rd == 0) {
>> >> +        /* Hint: insn is valid but does not affect state */
>> >> +        return true;
>> >> +    }
>> >> +    arg_addi arg = { .rd = a->rd, .rs1 = 0, .imm = a->imm };
>> >> +    return trans_addi(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_addi16sp_lui(DisasContext *ctx, arg_c_addi16sp_lui *a)
>> >> +{
>> >> +    if (a->rd == 2) {
>> >> +        /* C.ADDI16SP */
>> >> +        arg_addi arg = { .rd = 2, .rs1 = 2, .imm = a->imm_addi16sp };
>> >> +        return trans_addi(ctx, &arg);
>> >> +    } else if (a->imm_lui != 0) {
>> >> +        /* C.LUI */
>> >> +        if (a->rd == 0) {
>> >> +            /* Hint: insn is valid but does not affect state */
>> >> +            return true;
>> >> +        }
>> >> +        arg_lui arg = { .rd = a->rd, .imm = a->imm_lui };
>> >> +        return trans_lui(ctx, &arg);
>> >> +    }
>> >> +    return false;
>> >> +}
>> >> +
>> >> +static bool trans_c_srli(DisasContext *ctx, arg_c_srli *a)
>> >> +{
>> >> +    int shamt = a->shamt;
>> >> +    if (shamt == 0) {
>> >> +        /* For RV128 a shamt of 0 means a shift by 64 */
>> >> +        shamt = 64;
>> >> +    }
>> >> +    /* Ensure, that shamt[5] is zero for RV32 */
>> >> +    if (shamt >= TARGET_LONG_BITS) {
>> >> +        return false;
>> >> +    }
>> >> +
>> >> +    arg_srli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
>> >> +    return trans_srli(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_srai(DisasContext *ctx, arg_c_srai *a)
>> >> +{
>> >> +    int shamt = a->shamt;
>> >> +    if (shamt == 0) {
>> >> +        /* For RV128 a shamt of 0 means a shift by 64 */
>> >> +        shamt = 64;
>> >> +    }
>> >> +    /* Ensure, that shamt[5] is zero for RV32 */
>> >> +    if (shamt >= TARGET_LONG_BITS) {
>> >> +        return false;
>> >> +    }
>> >> +
>> >> +    arg_srai arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
>> >> +    return trans_srai(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_andi(DisasContext *ctx, arg_c_andi *a)
>> >> +{
>> >> +    arg_andi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
>> >> +    return trans_andi(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_sub(DisasContext *ctx, arg_c_sub *a)
>> >> +{
>> >> +    arg_sub arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> >> +    return trans_sub(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_xor(DisasContext *ctx, arg_c_xor *a)
>> >> +{
>> >> +    arg_xor arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> >> +    return trans_xor(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_or(DisasContext *ctx, arg_c_or *a)
>> >> +{
>> >> +    arg_or arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> >> +    return trans_or(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_and(DisasContext *ctx, arg_c_and *a)
>> >> +{
>> >> +    arg_and arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> >> +    return trans_and(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_subw(DisasContext *ctx, arg_c_subw *a)
>> >> +{
>> >> +#ifdef TARGET_RISCV64
>> >> +    arg_subw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> >> +    return trans_subw(ctx, &arg);
>> >> +#else
>> >> +    return false;
>> >> +#endif
>> >> +}
>> >> +
>> >> +static bool trans_c_addw(DisasContext *ctx, arg_c_addw *a)
>> >> +{
>> >> +#ifdef TARGET_RISCV64
>> >> +    arg_addw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
>> >> +    return trans_addw(ctx, &arg);
>> >> +#else
>> >> +    return false;
>> >> +#endif
>> >> +}
>> >> +
>> >> +static bool trans_c_j(DisasContext *ctx, arg_c_j *a)
>> >> +{
>> >> +    arg_jal arg = { .rd = 0, .imm = a->imm };
>> >> +    return trans_jal(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_beqz(DisasContext *ctx, arg_c_beqz *a)
>> >> +{
>> >> +    arg_beq arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
>> >> +    return trans_beq(ctx, &arg);
>> >> +}
>> >> +
>> >> +static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a)
>> >> +{
>> >> +    arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
>> >> +    return trans_bne(ctx, &arg);
>> >> +}
>> >> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
>> >> index 0106fa8d51b3..a584c24fbf6b 100644
>> >> --- a/target/riscv/translate.c
>> >> +++ b/target/riscv/translate.c
>> >> @@ -828,120 +828,6 @@ static void decode_RV32_64C0(DisasContext *ctx)
>> >>      }
>> >>  }
>> >>
>> >> -static void decode_RV32_64C1(DisasContext *ctx)
>> >> -{
>> >> -    uint8_t funct3 = extract32(ctx->opcode, 13, 3);
>> >> -    uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
>> >> -    uint8_t rs1s, rs2s;
>> >> -    uint8_t funct2;
>> >> -
>> >> -    switch (funct3) {
>> >> -    case 0:
>> >> -        /* C.ADDI -> addi rd, rd, nzimm[5:0] */
>> >> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, rd_rs1,
>> >> -                      GET_C_IMM(ctx->opcode));
>> >> -        break;
>> >> -    case 1:
>> >> -#if defined(TARGET_RISCV64)
>> >> -        /* C.ADDIW (RV64/128) -> addiw rd, rd, imm[5:0]*/
>> >> -        gen_arith_imm(ctx, OPC_RISC_ADDIW, rd_rs1, rd_rs1,
>> >> -                      GET_C_IMM(ctx->opcode));
>> >> -#else
>> >> -        /* C.JAL(RV32) -> jal x1, offset[11:1] */
>> >> -        gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
>> >> -#endif
>> >> -        break;
>> >> -    case 2:
>> >> -        /* C.LI -> addi rd, x0, imm[5:0]*/
>> >> -        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, 0, GET_C_IMM(ctx->opcode));
>> >> -        break;
>> >> -    case 3:
>> >> -        if (rd_rs1 == 2) {
>> >> -            /* C.ADDI16SP -> addi x2, x2, nzimm[9:4]*/
>> >> -            gen_arith_imm(ctx, OPC_RISC_ADDI, 2, 2,
>> >> -                          GET_C_ADDI16SP_IMM(ctx->opcode));
>> >> -        } else if (rd_rs1 != 0) {
>> >> -            /* C.LUI (rs1/rd =/= {0,2}) -> lui rd, nzimm[17:12]*/
>> >> -            tcg_gen_movi_tl(cpu_gpr[rd_rs1],
>> >> -                            GET_C_IMM(ctx->opcode) << 12);
>> >> -        }
>> >> -        break;
>> >> -    case 4:
>> >> -        funct2 = extract32(ctx->opcode, 10, 2);
>> >> -        rs1s = GET_C_RS1S(ctx->opcode);
>> >> -        switch (funct2) {
>> >> -        case 0: /* C.SRLI(RV32) -> srli rd', rd', shamt[5:0] */
>> >> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
>> >> -                               GET_C_ZIMM(ctx->opcode));
>> >> -            /* C.SRLI64(RV128) */
>> >> -            break;
>> >> -        case 1:
>> >> -            /* C.SRAI -> srai rd', rd', shamt[5:0]*/
>> >> -            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
>> >> -                            GET_C_ZIMM(ctx->opcode) | 0x400);
>> >> -            /* C.SRAI64(RV128) */
>> >> -            break;
>> >> -        case 2:
>> >> -            /* C.ANDI -> andi rd', rd', imm[5:0]*/
>> >> -            gen_arith_imm(ctx, OPC_RISC_ANDI, rs1s, rs1s,
>> >> -                          GET_C_IMM(ctx->opcode));
>> >> -            break;
>> >> -        case 3:
>> >> -            funct2 = extract32(ctx->opcode, 5, 2);
>> >> -            rs2s = GET_C_RS2S(ctx->opcode);
>> >> -            switch (funct2) {
>> >> -            case 0:
>> >> -                /* C.SUB -> sub rd', rd', rs2' */
>> >> -                if (extract32(ctx->opcode, 12, 1) == 0) {
>> >> -                    gen_arith(ctx, OPC_RISC_SUB, rs1s, rs1s, rs2s);
>> >> -                }
>> >> -#if defined(TARGET_RISCV64)
>> >> -                else {
>> >> -                    gen_arith(ctx, OPC_RISC_SUBW, rs1s, rs1s, rs2s);
>> >> -                }
>> >> -#endif
>> >> -                break;
>> >> -            case 1:
>> >> -                /* C.XOR -> xor rs1', rs1', rs2' */
>> >> -                if (extract32(ctx->opcode, 12, 1) == 0) {
>> >> -                    gen_arith(ctx, OPC_RISC_XOR, rs1s, rs1s, rs2s);
>> >> -                }
>> >> -#if defined(TARGET_RISCV64)
>> >> -                else {
>> >> -                    /* C.ADDW (RV64/128) */
>> >> -                    gen_arith(ctx, OPC_RISC_ADDW, rs1s, rs1s, rs2s);
>> >> -                }
>> >> -#endif
>> >> -                break;
>> >> -            case 2:
>> >> -                /* C.OR -> or rs1', rs1', rs2' */
>> >> -                gen_arith(ctx, OPC_RISC_OR, rs1s, rs1s, rs2s);
>> >> -                break;
>> >> -            case 3:
>> >> -                /* C.AND -> and rs1', rs1', rs2' */
>> >> -                gen_arith(ctx, OPC_RISC_AND, rs1s, rs1s, rs2s);
>> >> -                break;
>> >> -            }
>> >> -            break;
>> >> -        }
>> >> -        break;
>> >> -    case 5:
>> >> -        /* C.J -> jal x0, offset[11:1]*/
>> >> -        gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
>> >> -        break;
>> >> -    case 6:
>> >> -        /* C.BEQZ -> beq rs1', x0, offset[8:1]*/
>> >> -        rs1s = GET_C_RS1S(ctx->opcode);
>> >> -        gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
>> >> -        break;
>> >> -    case 7:
>> >> -        /* C.BNEZ -> bne rs1', x0, offset[8:1]*/
>> >> -        rs1s = GET_C_RS1S(ctx->opcode);
>> >> -        gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
>> >> -        break;
>> >> -    }
>> >> -}
>> >> -
>> >>  static void decode_RV32_64C2(DisasContext *ctx)
>> >>  {
>> >>      uint8_t rd, rs2;
>> >> @@ -1028,9 +914,6 @@ static void decode_RV32_64C(DisasContext *ctx)
>> >>      case 0:
>> >>          decode_RV32_64C0(ctx);
>> >>          break;
>> >> -    case 1:
>> >> -        decode_RV32_64C1(ctx);
>> >> -        break;
>> >>      case 2:
>> >>          decode_RV32_64C2(ctx);
>> >>          break;
>> >> @@ -1045,6 +928,7 @@ static void decode_RV32_64C(DisasContext *ctx)
>> >>  EX_SH(1)
>> >>  EX_SH(2)
>> >>  EX_SH(3)
>> >> +EX_SH(4)
>> >>  EX_SH(12)
>> >>
>> >>  #define REQUIRE_EXT(ctx, ext) do { \
>> >> --
>> >> 2.19.2
>> >>
>> >>
Bastian Koppelmann March 15, 2019, 9:06 a.m. UTC | #5
Hi Alistair

On 3/14/19 9:28 PM, Alistair Francis wrote:
> On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com> wrote:
>> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
> This commit is the first bad commit in breaking 32-bit boot.
>
> It looks like the jal doesn't jump to the correct address:
>
> ----------------
> IN:
> 0x80000022:  00050433          add             s0,a0,zero
> 0x80000026:  000584b3          add             s1,a1,zero
> 0x8000002a:  2c79              jal             ra,670          # 0x800002c8
>
> ----------------
> IN:
> 0x800002c8:  00000533          add             a0,zero,zero
> 0x800002cc:  8082              ret


Oops! Can you point me to the binary to reproduce this?

Cheers,

Bastian
Palmer Dabbelt March 15, 2019, 11:19 a.m. UTC | #6
On Fri, 15 Mar 2019 02:06:07 PDT (-0700), Bastian Koppelmann wrote:
> Hi Alistair
>
> On 3/14/19 9:28 PM, Alistair Francis wrote:
>> On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com> wrote:
>>> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>>
>>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>>> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
>> This commit is the first bad commit in breaking 32-bit boot.
>>
>> It looks like the jal doesn't jump to the correct address:
>>
>> ----------------
>> IN:
>> 0x80000022:  00050433          add             s0,a0,zero
>> 0x80000026:  000584b3          add             s1,a1,zero
>> 0x8000002a:  2c79              jal             ra,670          # 0x800002c8
>>
>> ----------------
>> IN:
>> 0x800002c8:  00000533          add             a0,zero,zero
>> 0x800002cc:  8082              ret
>
>
> Oops! Can you point me to the binary to reproduce this?

I think I've traced it down to something simple: in my hello world binary I see

    20401a8c:       2a45                    jal     20401c3c <atexit>

in the objdump, and I see

    IN: _start
    0x20401a8c:  2a45              jal             ra,432          # 0x20401c3c

but then QEMU jumps to 0x20401a9d.  I have a feeling it's something wrong with 
gen_jal() that disappeared during the cleanups that we dropped in order to fix 
the build issues.

I'm running

    ./riscv32-softmmu/qemu-system-riscv32 -machine sifive_e -kernel ~/work/sifive/freedom-e-sdk/software/hello/hello -nographic -d in_asm,out_asm,exec,cpu -singlestep |& tee out.log

on the "hifive1" branch of github.com/palmer-dabbelt/qemu, which just has a 
PRCI fixup that I forgot about and haven't sent upstream yet (I'll do that 
after this issue).  The binary should be at

    http://www.dabbelt.com/~palmer/hello.elf

and the debug log at 

    http://www.dabbelt.com/~palmer/out.log

You can build the binary from github.com/sifive/freedom-e-sdk via

   make software PROGRAM=hello TARGET=sifive-hifive1

using the riscv64-unknown-elf-gcc-20181127-x86_64-linux-ubuntu14 toolchain 
binaries from our website (newer ones should work, but probably won't produce 
exactly the same output).

I'll poke around after grabbing some dinner...
Palmer Dabbelt March 15, 2019, 12:07 p.m. UTC | #7
On Fri, Mar 15, 2019 at 4:19 AM Palmer Dabbelt <palmer@sifive.com> wrote:

> On Fri, 15 Mar 2019 02:06:07 PDT (-0700), Bastian Koppelmann wrote:
> > Hi Alistair
> >
> > On 3/14/19 9:28 PM, Alistair Francis wrote:
> >> On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com>
> wrote:
> >>> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> >>>
> >>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> >>> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> >>> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
> >> This commit is the first bad commit in breaking 32-bit boot.
> >>
> >> It looks like the jal doesn't jump to the correct address:
> >>
> >> ----------------
> >> IN:
> >> 0x80000022:  00050433          add             s0,a0,zero
> >> 0x80000026:  000584b3          add             s1,a1,zero
> >> 0x8000002a:  2c79              jal             ra,670          #
> 0x800002c8
> >>
> >> ----------------
> >> IN:
> >> 0x800002c8:  00000533          add             a0,zero,zero
> >> 0x800002cc:  8082              ret
> >
> >
> > Oops! Can you point me to the binary to reproduce this?
>
> I think I've traced it down to something simple: in my hello world binary
> I see
>
>     20401a8c:       2a45                    jal     20401c3c <atexit>
>
> in the objdump, and I see
>
>     IN: _start
>     0x20401a8c:  2a45              jal             ra,432          #
> 0x20401c3c
>
> but then QEMU jumps to 0x20401a9d.  I have a feeling it's something wrong
> with
> gen_jal() that disappeared during the cleanups that we dropped in order to
> fix
> the build issues.
>
> I'm running
>
>     ./riscv32-softmmu/qemu-system-riscv32 -machine sifive_e -kernel
> ~/work/sifive/freedom-e-sdk/software/hello/hello -nographic -d
> in_asm,out_asm,exec,cpu -singlestep |& tee out.log
>
> on the "hifive1" branch of github.com/palmer-dabbelt/qemu, which just has
> a
> PRCI fixup that I forgot about and haven't sent upstream yet (I'll do that
> after this issue).  The binary should be at
>
>     http://www.dabbelt.com/~palmer/hello.elf
>
> and the debug log at
>
>     http://www.dabbelt.com/~palmer/out.log
>
> You can build the binary from github.com/sifive/freedom-e-sdk via
>
>    make software PROGRAM=hello TARGET=sifive-hifive1
>
> using the riscv64-unknown-elf-gcc-20181127-x86_64-linux-ubuntu14 toolchain
> binaries from our website (newer ones should work, but probably won't
> produce
> exactly the same output).
>
> I'll poke around after grabbing some dinner...
>

OK, I'm pretty sure this is it:

c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm
manually

static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a)
{
#ifdef TARGET_RISCV32
    /* C.JAL */
    arg_jal arg = { .rd = 1, .imm = a->imm };
    return trans_jal(ctx, &arg);
#else
    /* C.ADDIW */
    arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
    return trans_addiw(ctx, &arg);
#endif
}

It parses RD manually, but not IMM :)  I'm actually going to eat now...
Bastian Koppelmann March 15, 2019, 12:44 p.m. UTC | #8
On 3/15/19 1:07 PM, Palmer Dabbelt wrote:
> On Fri, Mar 15, 2019 at 4:19 AM Palmer Dabbelt <palmer@sifive.com> wrote:
>
>> On Fri, 15 Mar 2019 02:06:07 PDT (-0700), Bastian Koppelmann wrote:
>>> Hi Alistair
>>>
>>> On 3/14/19 9:28 PM, Alistair Francis wrote:
>>>> On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com>
>> wrote:
>>>>> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>>>>
>>>>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>>>>> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>>>> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
>>>> This commit is the first bad commit in breaking 32-bit boot.
>>>>
>>>> It looks like the jal doesn't jump to the correct address:
>>>>
>>>> ----------------
>>>> IN:
>>>> 0x80000022:  00050433          add             s0,a0,zero
>>>> 0x80000026:  000584b3          add             s1,a1,zero
>>>> 0x8000002a:  2c79              jal             ra,670          #
>> 0x800002c8
>>>> ----------------
>>>> IN:
>>>> 0x800002c8:  00000533          add             a0,zero,zero
>>>> 0x800002cc:  8082              ret
>>>
>>> Oops! Can you point me to the binary to reproduce this?
>> I think I've traced it down to something simple: in my hello world binary
>> I see
>>
>>      20401a8c:       2a45                    jal     20401c3c <atexit>
>>
>> in the objdump, and I see
>>
>>      IN: _start
>>      0x20401a8c:  2a45              jal             ra,432          #
>> 0x20401c3c
>>
>> but then QEMU jumps to 0x20401a9d.  I have a feeling it's something wrong
>> with
>> gen_jal() that disappeared during the cleanups that we dropped in order to
>> fix
>> the build issues.
>>
>> I'm running
>>
>>      ./riscv32-softmmu/qemu-system-riscv32 -machine sifive_e -kernel
>> ~/work/sifive/freedom-e-sdk/software/hello/hello -nographic -d
>> in_asm,out_asm,exec,cpu -singlestep |& tee out.log
>>
>> on the "hifive1" branch of github.com/palmer-dabbelt/qemu, which just has
>> a
>> PRCI fixup that I forgot about and haven't sent upstream yet (I'll do that
>> after this issue).  The binary should be at
>>
>>      http://www.dabbelt.com/~palmer/hello.elf
>>
>> and the debug log at
>>
>>      http://www.dabbelt.com/~palmer/out.log
>>
>> You can build the binary from github.com/sifive/freedom-e-sdk via
>>
>>     make software PROGRAM=hello TARGET=sifive-hifive1
>>
>> using the riscv64-unknown-elf-gcc-20181127-x86_64-linux-ubuntu14 toolchain
>> binaries from our website (newer ones should work, but probably won't
>> produce
>> exactly the same output).
>>
>> I'll poke around after grabbing some dinner...
>>
> OK, I'm pretty sure this is it:
>
> c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm
> manually

Thanks for the digging. Yes this bug was fixed in the patches we dropped 
:/. Heres the fix:

diff --git a/target/riscv/insn_trans/trans_rvc.inc.c 
b/target/riscv/insn_trans/trans_rvc.inc.c
index bcdf64d3b7..5241a8414e 100644
--- a/target/riscv/insn_trans/trans_rvc.inc.c
+++ b/target/riscv/insn_trans/trans_rvc.inc.c
@@ -88,7 +88,9 @@ static bool trans_c_jal_addiw(DisasContext *ctx, 
arg_c_jal_addiw *a)
  {
  #ifdef TARGET_RISCV32
      /* C.JAL */
-    arg_jal arg = { .rd = 1, .imm = a->imm };
+    arg_c_j tmp;
+    extract_cj(&tmp, ctx->opcode);
+    arg_jal arg = { .rd = 1, .imm = tmp.imm };
      return trans_jal(ctx, &arg);
  #else
      /* C.ADDIW */

I'll send a patch as soon as I have checked the other cases that require 
manual parsing.

Cheers,

Bastian
Bastian Koppelmann March 15, 2019, 12:48 p.m. UTC | #9
On 3/15/19 1:44 PM, Bastian Koppelmann wrote:
>
> On 3/15/19 1:07 PM, Palmer Dabbelt wrote:
>> On Fri, Mar 15, 2019 at 4:19 AM Palmer Dabbelt <palmer@sifive.com> 
>> wrote:
>>
>>> On Fri, 15 Mar 2019 02:06:07 PDT (-0700), Bastian Koppelmann wrote:
>>>> Hi Alistair
>>>>
>>>> On 3/14/19 9:28 PM, Alistair Francis wrote:
>>>>> On Wed, Mar 13, 2019 at 7:53 AM Palmer Dabbelt <palmer@sifive.com>
>>> wrote:
>>>>>> From: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>>>>>
>>>>>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>>>>>> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
>>>>>> Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
>>>>> This commit is the first bad commit in breaking 32-bit boot.
>>>>>
>>>>> It looks like the jal doesn't jump to the correct address:
>>>>>
>>>>> ----------------
>>>>> IN:
>>>>> 0x80000022:  00050433          add             s0,a0,zero
>>>>> 0x80000026:  000584b3          add             s1,a1,zero
>>>>> 0x8000002a:  2c79              jal ra,670          #
>>> 0x800002c8
>>>>> ----------------
>>>>> IN:
>>>>> 0x800002c8:  00000533          add a0,zero,zero
>>>>> 0x800002cc:  8082              ret
>>>>
>>>> Oops! Can you point me to the binary to reproduce this?
>>> I think I've traced it down to something simple: in my hello world 
>>> binary
>>> I see
>>>
>>>      20401a8c:       2a45                    jal     20401c3c <atexit>
>>>
>>> in the objdump, and I see
>>>
>>>      IN: _start
>>>      0x20401a8c:  2a45              jal ra,432          #
>>> 0x20401c3c
>>>
>>> but then QEMU jumps to 0x20401a9d.  I have a feeling it's something 
>>> wrong
>>> with
>>> gen_jal() that disappeared during the cleanups that we dropped in 
>>> order to
>>> fix
>>> the build issues.
>>>
>>> I'm running
>>>
>>>      ./riscv32-softmmu/qemu-system-riscv32 -machine sifive_e -kernel
>>> ~/work/sifive/freedom-e-sdk/software/hello/hello -nographic -d
>>> in_asm,out_asm,exec,cpu -singlestep |& tee out.log
>>>
>>> on the "hifive1" branch of github.com/palmer-dabbelt/qemu, which 
>>> just has
>>> a
>>> PRCI fixup that I forgot about and haven't sent upstream yet (I'll 
>>> do that
>>> after this issue).  The binary should be at
>>>
>>>      http://www.dabbelt.com/~palmer/hello.elf
>>>
>>> and the debug log at
>>>
>>>      http://www.dabbelt.com/~palmer/out.log
>>>
>>> You can build the binary from github.com/sifive/freedom-e-sdk via
>>>
>>>     make software PROGRAM=hello TARGET=sifive-hifive1
>>>
>>> using the riscv64-unknown-elf-gcc-20181127-x86_64-linux-ubuntu14 
>>> toolchain
>>> binaries from our website (newer ones should work, but probably won't
>>> produce
>>> exactly the same output).
>>>
>>> I'll poke around after grabbing some dinner...
>>>
>> OK, I'm pretty sure this is it:
>>
>> c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm
>> manually
>
> Thanks for the digging. Yes this bug was fixed in the patches we 
> dropped :/. Heres the fix:
>
> diff --git a/target/riscv/insn_trans/trans_rvc.inc.c 
> b/target/riscv/insn_trans/trans_rvc.inc.c
> index bcdf64d3b7..5241a8414e 100644
> --- a/target/riscv/insn_trans/trans_rvc.inc.c
> +++ b/target/riscv/insn_trans/trans_rvc.inc.c
> @@ -88,7 +88,9 @@ static bool trans_c_jal_addiw(DisasContext *ctx, 
> arg_c_jal_addiw *a)
>  {
>  #ifdef TARGET_RISCV32
>      /* C.JAL */
> -    arg_jal arg = { .rd = 1, .imm = a->imm };
> +    arg_c_j tmp;
> +    extract_cj(&tmp, ctx->opcode);
Sorry, it's decode_insn16_extract_cj()
diff mbox series

Patch

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 558c0c41f0b5..45109301c6d4 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -22,28 +22,53 @@ 
 %rs2_3     2:3                !function=ex_rvc_register
 
 # Immediates:
+%imm_ci        12:s1 2:5
 %nzuimm_ciw    7:4 11:2 5:1 6:1   !function=ex_shift_2
 %uimm_cl_d     5:2 10:3           !function=ex_shift_3
 %uimm_cl_w     5:1 10:3 6:1       !function=ex_shift_2
+%imm_cb        12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
+%imm_cj        12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
+
+%nzuimm_6bit   12:1 2:5
+
+%imm_addi16sp  12:s1 3:2 5:1 2:1 6:1 !function=ex_shift_4
+%imm_lui       12:s1 2:5             !function=ex_shift_12
+
 
 
 # Argument sets:
 &cl               rs1 rd
 &cl_dw     uimm   rs1 rd
+&ci        imm        rd
 &ciw       nzuimm     rd
 &cs               rs1 rs2
 &cs_dw     uimm   rs1 rs2
+&cb        imm    rs1
+&cr               rd  rs2
+&cj       imm
+&c_shift   shamt      rd
+
 
+&caddi16sp_lui  imm_lui imm_addi16sp rd
 
 # Formats 16:
+@ci        ... . ..... .....  .. &ci     imm=%imm_ci                  %rd
 @ciw       ...   ........ ... .. &ciw    nzuimm=%nzuimm_ciw           rd=%rs2_3
 @cl_d      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rd=%rs2_3
 @cl_w      ... ... ... .. ... .. &cl_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rd=%rs2_3
 @cl        ... ... ... .. ... .. &cl                      rs1=%rs1_3  rd=%rs2_3
 @cs        ... ... ... .. ... .. &cs                      rs1=%rs1_3  rs2=%rs2_3
+@cs_2      ... ... ... .. ... .. &cr                      rd=%rs1_3   rs2=%rs2_3
 @cs_d      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_d  rs1=%rs1_3  rs2=%rs2_3
 @cs_w      ... ... ... .. ... .. &cs_dw  uimm=%uimm_cl_w  rs1=%rs1_3  rs2=%rs2_3
+@cb        ... ... ... .. ... .. &cb     imm=%imm_cb      rs1=%rs1_3
+@cj        ...    ........... .. &cj     imm=%imm_cj
 
+@c_addi16sp_lui ... .  ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd
+
+@c_shift        ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit
+
+@c_andi         ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3
 
 # *** RV64C Standard Extension (Quadrant 0) ***
 c_addi4spn        000    ........ ... 00 @ciw
@@ -53,3 +78,21 @@  c_flw_ld          011  --- ... -- ... 00 @cl    #Note: Must parse uimm manually
 c_fsd             101  ... ... .. ... 00 @cs_d
 c_sw              110  ... ... .. ... 00 @cs_w
 c_fsw_sd          111  --- ... -- ... 00 @cs    #Note: Must parse uimm manually
+
+# *** RV64C Standard Extension (Quadrant 1) ***
+c_addi            000 .  .....  ..... 01 @ci
+c_jal_addiw       001 .  .....  ..... 01 @ci #Note: parse rd and/or imm manually
+c_li              010 .  .....  ..... 01 @ci
+c_addi16sp_lui    011 .  .....  ..... 01 @c_addi16sp_lui # shares opc with C.LUI
+c_srli            100 . 00 ...  ..... 01 @c_shift
+c_srai            100 . 01 ...  ..... 01 @c_shift
+c_andi            100 . 10 ...  ..... 01 @c_andi
+c_sub             100 0 11 ... 00 ... 01 @cs_2
+c_xor             100 0 11 ... 01 ... 01 @cs_2
+c_or              100 0 11 ... 10 ... 01 @cs_2
+c_and             100 0 11 ... 11 ... 01 @cs_2
+c_subw            100 1 11 ... 00 ... 01 @cs_2
+c_addw            100 1 11 ... 01 ... 01 @cs_2
+c_j               101     ........... 01 @cj
+c_beqz            110  ... ...  ..... 01 @cb
+c_bnez            111  ... ...  ..... 01 @cb
diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c
index 93ec8aa30b95..b06c435c9800 100644
--- a/target/riscv/insn_trans/trans_rvc.inc.c
+++ b/target/riscv/insn_trans/trans_rvc.inc.c
@@ -73,3 +73,154 @@  static bool trans_c_fsw_sd(DisasContext *ctx, arg_c_fsw_sd *a)
     return false;
 #endif
 }
+
+static bool trans_c_addi(DisasContext *ctx, arg_c_addi *a)
+{
+    if (a->imm == 0) {
+        /* Hint: insn is valid but does not affect state */
+        return true;
+    }
+    arg_addi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
+    return trans_addi(ctx, &arg);
+}
+
+static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a)
+{
+#ifdef TARGET_RISCV32
+    /* C.JAL */
+    arg_jal arg = { .rd = 1, .imm = a->imm };
+    return trans_jal(ctx, &arg);
+#else
+    /* C.ADDIW */
+    arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
+    return trans_addiw(ctx, &arg);
+#endif
+}
+
+static bool trans_c_li(DisasContext *ctx, arg_c_li *a)
+{
+    if (a->rd == 0) {
+        /* Hint: insn is valid but does not affect state */
+        return true;
+    }
+    arg_addi arg = { .rd = a->rd, .rs1 = 0, .imm = a->imm };
+    return trans_addi(ctx, &arg);
+}
+
+static bool trans_c_addi16sp_lui(DisasContext *ctx, arg_c_addi16sp_lui *a)
+{
+    if (a->rd == 2) {
+        /* C.ADDI16SP */
+        arg_addi arg = { .rd = 2, .rs1 = 2, .imm = a->imm_addi16sp };
+        return trans_addi(ctx, &arg);
+    } else if (a->imm_lui != 0) {
+        /* C.LUI */
+        if (a->rd == 0) {
+            /* Hint: insn is valid but does not affect state */
+            return true;
+        }
+        arg_lui arg = { .rd = a->rd, .imm = a->imm_lui };
+        return trans_lui(ctx, &arg);
+    }
+    return false;
+}
+
+static bool trans_c_srli(DisasContext *ctx, arg_c_srli *a)
+{
+    int shamt = a->shamt;
+    if (shamt == 0) {
+        /* For RV128 a shamt of 0 means a shift by 64 */
+        shamt = 64;
+    }
+    /* Ensure, that shamt[5] is zero for RV32 */
+    if (shamt >= TARGET_LONG_BITS) {
+        return false;
+    }
+
+    arg_srli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
+    return trans_srli(ctx, &arg);
+}
+
+static bool trans_c_srai(DisasContext *ctx, arg_c_srai *a)
+{
+    int shamt = a->shamt;
+    if (shamt == 0) {
+        /* For RV128 a shamt of 0 means a shift by 64 */
+        shamt = 64;
+    }
+    /* Ensure, that shamt[5] is zero for RV32 */
+    if (shamt >= TARGET_LONG_BITS) {
+        return false;
+    }
+
+    arg_srai arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
+    return trans_srai(ctx, &arg);
+}
+
+static bool trans_c_andi(DisasContext *ctx, arg_c_andi *a)
+{
+    arg_andi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
+    return trans_andi(ctx, &arg);
+}
+
+static bool trans_c_sub(DisasContext *ctx, arg_c_sub *a)
+{
+    arg_sub arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
+    return trans_sub(ctx, &arg);
+}
+
+static bool trans_c_xor(DisasContext *ctx, arg_c_xor *a)
+{
+    arg_xor arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
+    return trans_xor(ctx, &arg);
+}
+
+static bool trans_c_or(DisasContext *ctx, arg_c_or *a)
+{
+    arg_or arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
+    return trans_or(ctx, &arg);
+}
+
+static bool trans_c_and(DisasContext *ctx, arg_c_and *a)
+{
+    arg_and arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
+    return trans_and(ctx, &arg);
+}
+
+static bool trans_c_subw(DisasContext *ctx, arg_c_subw *a)
+{
+#ifdef TARGET_RISCV64
+    arg_subw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
+    return trans_subw(ctx, &arg);
+#else
+    return false;
+#endif
+}
+
+static bool trans_c_addw(DisasContext *ctx, arg_c_addw *a)
+{
+#ifdef TARGET_RISCV64
+    arg_addw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
+    return trans_addw(ctx, &arg);
+#else
+    return false;
+#endif
+}
+
+static bool trans_c_j(DisasContext *ctx, arg_c_j *a)
+{
+    arg_jal arg = { .rd = 0, .imm = a->imm };
+    return trans_jal(ctx, &arg);
+}
+
+static bool trans_c_beqz(DisasContext *ctx, arg_c_beqz *a)
+{
+    arg_beq arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
+    return trans_beq(ctx, &arg);
+}
+
+static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a)
+{
+    arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
+    return trans_bne(ctx, &arg);
+}
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0106fa8d51b3..a584c24fbf6b 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -828,120 +828,6 @@  static void decode_RV32_64C0(DisasContext *ctx)
     }
 }
 
-static void decode_RV32_64C1(DisasContext *ctx)
-{
-    uint8_t funct3 = extract32(ctx->opcode, 13, 3);
-    uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
-    uint8_t rs1s, rs2s;
-    uint8_t funct2;
-
-    switch (funct3) {
-    case 0:
-        /* C.ADDI -> addi rd, rd, nzimm[5:0] */
-        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, rd_rs1,
-                      GET_C_IMM(ctx->opcode));
-        break;
-    case 1:
-#if defined(TARGET_RISCV64)
-        /* C.ADDIW (RV64/128) -> addiw rd, rd, imm[5:0]*/
-        gen_arith_imm(ctx, OPC_RISC_ADDIW, rd_rs1, rd_rs1,
-                      GET_C_IMM(ctx->opcode));
-#else
-        /* C.JAL(RV32) -> jal x1, offset[11:1] */
-        gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
-#endif
-        break;
-    case 2:
-        /* C.LI -> addi rd, x0, imm[5:0]*/
-        gen_arith_imm(ctx, OPC_RISC_ADDI, rd_rs1, 0, GET_C_IMM(ctx->opcode));
-        break;
-    case 3:
-        if (rd_rs1 == 2) {
-            /* C.ADDI16SP -> addi x2, x2, nzimm[9:4]*/
-            gen_arith_imm(ctx, OPC_RISC_ADDI, 2, 2,
-                          GET_C_ADDI16SP_IMM(ctx->opcode));
-        } else if (rd_rs1 != 0) {
-            /* C.LUI (rs1/rd =/= {0,2}) -> lui rd, nzimm[17:12]*/
-            tcg_gen_movi_tl(cpu_gpr[rd_rs1],
-                            GET_C_IMM(ctx->opcode) << 12);
-        }
-        break;
-    case 4:
-        funct2 = extract32(ctx->opcode, 10, 2);
-        rs1s = GET_C_RS1S(ctx->opcode);
-        switch (funct2) {
-        case 0: /* C.SRLI(RV32) -> srli rd', rd', shamt[5:0] */
-            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
-                               GET_C_ZIMM(ctx->opcode));
-            /* C.SRLI64(RV128) */
-            break;
-        case 1:
-            /* C.SRAI -> srai rd', rd', shamt[5:0]*/
-            gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, rs1s, rs1s,
-                            GET_C_ZIMM(ctx->opcode) | 0x400);
-            /* C.SRAI64(RV128) */
-            break;
-        case 2:
-            /* C.ANDI -> andi rd', rd', imm[5:0]*/
-            gen_arith_imm(ctx, OPC_RISC_ANDI, rs1s, rs1s,
-                          GET_C_IMM(ctx->opcode));
-            break;
-        case 3:
-            funct2 = extract32(ctx->opcode, 5, 2);
-            rs2s = GET_C_RS2S(ctx->opcode);
-            switch (funct2) {
-            case 0:
-                /* C.SUB -> sub rd', rd', rs2' */
-                if (extract32(ctx->opcode, 12, 1) == 0) {
-                    gen_arith(ctx, OPC_RISC_SUB, rs1s, rs1s, rs2s);
-                }
-#if defined(TARGET_RISCV64)
-                else {
-                    gen_arith(ctx, OPC_RISC_SUBW, rs1s, rs1s, rs2s);
-                }
-#endif
-                break;
-            case 1:
-                /* C.XOR -> xor rs1', rs1', rs2' */
-                if (extract32(ctx->opcode, 12, 1) == 0) {
-                    gen_arith(ctx, OPC_RISC_XOR, rs1s, rs1s, rs2s);
-                }
-#if defined(TARGET_RISCV64)
-                else {
-                    /* C.ADDW (RV64/128) */
-                    gen_arith(ctx, OPC_RISC_ADDW, rs1s, rs1s, rs2s);
-                }
-#endif
-                break;
-            case 2:
-                /* C.OR -> or rs1', rs1', rs2' */
-                gen_arith(ctx, OPC_RISC_OR, rs1s, rs1s, rs2s);
-                break;
-            case 3:
-                /* C.AND -> and rs1', rs1', rs2' */
-                gen_arith(ctx, OPC_RISC_AND, rs1s, rs1s, rs2s);
-                break;
-            }
-            break;
-        }
-        break;
-    case 5:
-        /* C.J -> jal x0, offset[11:1]*/
-        gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
-        break;
-    case 6:
-        /* C.BEQZ -> beq rs1', x0, offset[8:1]*/
-        rs1s = GET_C_RS1S(ctx->opcode);
-        gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
-        break;
-    case 7:
-        /* C.BNEZ -> bne rs1', x0, offset[8:1]*/
-        rs1s = GET_C_RS1S(ctx->opcode);
-        gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
-        break;
-    }
-}
-
 static void decode_RV32_64C2(DisasContext *ctx)
 {
     uint8_t rd, rs2;
@@ -1028,9 +914,6 @@  static void decode_RV32_64C(DisasContext *ctx)
     case 0:
         decode_RV32_64C0(ctx);
         break;
-    case 1:
-        decode_RV32_64C1(ctx);
-        break;
     case 2:
         decode_RV32_64C2(ctx);
         break;
@@ -1045,6 +928,7 @@  static void decode_RV32_64C(DisasContext *ctx)
 EX_SH(1)
 EX_SH(2)
 EX_SH(3)
+EX_SH(4)
 EX_SH(12)
 
 #define REQUIRE_EXT(ctx, ext) do { \