target/riscv: accessors to registers upper part and 128-bit load/store

Get function to retrieve the 64 top bits of a register, stored in the gprh
field of the cpu state. Set function that writes the 128-bit value at once.
The access to the gprh field can not be protected at compile time to make
sure it is accessed only in the 128-bit version of the processor because we
have no way to indicate that the misa_mxl_max field is const.

The 128-bit ISA adds ldu, lq and sq. We provide support for these
instructions. Note that (a) we compute only 64-bit addresses to actually
access memory, cowardly utilizing the existing address translation mechanism
of QEMU, and (b) we assume for now little-endian memory accesses.

Signed-off-by: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
Co-authored-by: Fabien Portas <fabien.portas@grenoble-inp.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20220106210108.138226-10-frederic.petrot@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Frédéric Pétrot 2022-01-06 22:00:59 +01:00 committed by Alistair Francis
parent 76a361066f
commit a2f827ff4f
4 changed files with 163 additions and 10 deletions

View file

@ -134,7 +134,7 @@ static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a)
return gen_branch(ctx, a, TCG_COND_GEU);
}
static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
static bool gen_load_tl(DisasContext *ctx, arg_lb *a, MemOp memop)
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@ -151,6 +151,45 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
return true;
}
/* Compute only 64-bit addresses to use the address translation mechanism */
static bool gen_load_i128(DisasContext *ctx, arg_lb *a, MemOp memop)
{
TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv destl = dest_gpr(ctx, a->rd);
TCGv desth = dest_gprh(ctx, a->rd);
TCGv addrl = tcg_temp_new();
tcg_gen_addi_tl(addrl, src1l, a->imm);
if ((memop & MO_SIZE) <= MO_64) {
tcg_gen_qemu_ld_tl(destl, addrl, ctx->mem_idx, memop);
if (memop & MO_SIGN) {
tcg_gen_sari_tl(desth, destl, 63);
} else {
tcg_gen_movi_tl(desth, 0);
}
} else {
/* assume little-endian memory access for now */
tcg_gen_qemu_ld_tl(destl, addrl, ctx->mem_idx, MO_TEUQ);
tcg_gen_addi_tl(addrl, addrl, 8);
tcg_gen_qemu_ld_tl(desth, addrl, ctx->mem_idx, MO_TEUQ);
}
gen_set_gpr128(ctx, a->rd, destl, desth);
tcg_temp_free(addrl);
return true;
}
static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
{
if (get_xl(ctx) == MXL_RV128) {
return gen_load_i128(ctx, a, memop);
} else {
return gen_load_tl(ctx, a, memop);
}
}
static bool trans_lb(DisasContext *ctx, arg_lb *a)
{
return gen_load(ctx, a, MO_SB);
@ -166,6 +205,18 @@ static bool trans_lw(DisasContext *ctx, arg_lw *a)
return gen_load(ctx, a, MO_TESL);
}
static bool trans_ld(DisasContext *ctx, arg_ld *a)
{
REQUIRE_64_OR_128BIT(ctx);
return gen_load(ctx, a, MO_TESQ);
}
static bool trans_lq(DisasContext *ctx, arg_lq *a)
{
REQUIRE_128BIT(ctx);
return gen_load(ctx, a, MO_TEUO);
}
static bool trans_lbu(DisasContext *ctx, arg_lbu *a)
{
return gen_load(ctx, a, MO_UB);
@ -178,17 +229,17 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
return gen_load(ctx, a, MO_TEUL);
}
static bool trans_ld(DisasContext *ctx, arg_ld *a)
static bool trans_ldu(DisasContext *ctx, arg_ldu *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_128BIT(ctx);
return gen_load(ctx, a, MO_TEUQ);
}
static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
static bool gen_store_tl(DisasContext *ctx, arg_sb *a, MemOp memop)
{
TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
@ -204,6 +255,37 @@ static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
return true;
}
static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop)
{
TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv src2l = get_gpr(ctx, a->rs2, EXT_NONE);
TCGv src2h = get_gprh(ctx, a->rs2);
TCGv addrl = tcg_temp_new();
tcg_gen_addi_tl(addrl, src1l, a->imm);
if ((memop & MO_SIZE) <= MO_64) {
tcg_gen_qemu_st_tl(src2l, addrl, ctx->mem_idx, memop);
} else {
/* little-endian memory access assumed for now */
tcg_gen_qemu_st_tl(src2l, addrl, ctx->mem_idx, MO_TEUQ);
tcg_gen_addi_tl(addrl, addrl, 8);
tcg_gen_qemu_st_tl(src2h, addrl, ctx->mem_idx, MO_TEUQ);
}
tcg_temp_free(addrl);
return true;
}
static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
{
if (get_xl(ctx) == MXL_RV128) {
return gen_store_i128(ctx, a, memop);
} else {
return gen_store_tl(ctx, a, memop);
}
}
static bool trans_sb(DisasContext *ctx, arg_sb *a)
{
return gen_store(ctx, a, MO_SB);
@ -221,10 +303,16 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
static bool trans_sd(DisasContext *ctx, arg_sd *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
return gen_store(ctx, a, MO_TEUQ);
}
static bool trans_sq(DisasContext *ctx, arg_sq *a)
{
REQUIRE_128BIT(ctx);
return gen_store(ctx, a, MO_TEUO);
}
static bool trans_addi(DisasContext *ctx, arg_addi *a)
{
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl);