target/riscv: rvb: generalized reverse

Signed-off-by: Frank Chang <frank.chang@sifive.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210505160620.15723-13-frank.chang@sifive.com
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Frank Chang 2021-05-06 00:06:13 +08:00 committed by Alistair Francis
parent e58529a8d0
commit 831ec7f3d1
6 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1,64 @@
/*
* RISC-V Bitmanip Extension Helpers for QEMU.
*
* Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com
* Copyright (c) 2020 Frank Chang, frank.chang@sifive.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
#include "tcg/tcg.h"
static const uint64_t adjacent_masks[] = {
dup_const(MO_8, 0x55),
dup_const(MO_8, 0x33),
dup_const(MO_8, 0x0f),
dup_const(MO_16, 0xff),
dup_const(MO_32, 0xffff),
UINT32_MAX
};
static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift)
{
return ((x & mask) << shift) | ((x & ~mask) >> shift);
}
static target_ulong do_grev(target_ulong rs1,
target_ulong rs2,
int bits)
{
target_ulong x = rs1;
int i, shift;
for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) {
if (rs2 & shift) {
x = do_swap(x, adjacent_masks[i], shift);
}
}
return x;
}
target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2)
{
return do_grev(rs1, rs2, TARGET_LONG_BITS);
}
target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2)
{
return do_grev(rs1, rs2, 32);
}

View File

@ -58,6 +58,10 @@ DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64)
/* Bitmanip */
DEF_HELPER_FLAGS_2(grev, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(grevw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
/* Special functions */
DEF_HELPER_3(csrrw, tl, env, tl, tl)
DEF_HELPER_4(csrrs, tl, env, tl, tl, tl)

View File

@ -684,6 +684,7 @@ slo 0010000 .......... 001 ..... 0110011 @r
sro 0010000 .......... 101 ..... 0110011 @r
ror 0110000 .......... 101 ..... 0110011 @r
rol 0110000 .......... 001 ..... 0110011 @r
grev 0110100 .......... 101 ..... 0110011 @r
bseti 00101. ........... 001 ..... 0010011 @sh
bclri 01001. ........... 001 ..... 0010011 @sh
@ -692,6 +693,7 @@ bexti 01001. ........... 101 ..... 0010011 @sh
sloi 00100. ........... 001 ..... 0010011 @sh
sroi 00100. ........... 101 ..... 0010011 @sh
rori 01100. ........... 101 ..... 0010011 @sh
grevi 01101. ........... 101 ..... 0010011 @sh
# *** RV64B Standard Extension (in addition to RV32B) ***
clzw 0110000 00000 ..... 001 ..... 0011011 @r2
@ -708,6 +710,7 @@ slow 0010000 .......... 001 ..... 0111011 @r
srow 0010000 .......... 101 ..... 0111011 @r
rorw 0110000 .......... 101 ..... 0111011 @r
rolw 0110000 .......... 001 ..... 0111011 @r
grevw 0110100 .......... 101 ..... 0111011 @r
bsetiw 0010100 .......... 001 ..... 0011011 @sh5
bclriw 0100100 .......... 001 ..... 0011011 @sh5
@ -715,3 +718,4 @@ binviw 0110100 .......... 001 ..... 0011011 @sh5
sloiw 0010000 .......... 001 ..... 0011011 @sh5
sroiw 0010000 .......... 101 ..... 0011011 @sh5
roriw 0110000 .......... 101 ..... 0011011 @sh5
greviw 0110100 .......... 101 ..... 0011011 @sh5

View File

@ -197,6 +197,23 @@ static bool trans_rol(DisasContext *ctx, arg_rol *a)
return gen_shift(ctx, a, tcg_gen_rotl_tl);
}
static bool trans_grev(DisasContext *ctx, arg_grev *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift(ctx, a, gen_helper_grev);
}
static bool trans_grevi(DisasContext *ctx, arg_grevi *a)
{
REQUIRE_EXT(ctx, RVB);
if (a->shamt >= TARGET_LONG_BITS) {
return false;
}
return gen_grevi(ctx, a);
}
static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
{
REQUIRE_64BIT(ctx);
@ -329,3 +346,17 @@ static bool trans_rolw(DisasContext *ctx, arg_rolw *a)
REQUIRE_EXT(ctx, RVB);
return gen_shiftw(ctx, a, gen_rolw);
}
static bool trans_grevw(DisasContext *ctx, arg_grevw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
return gen_shiftw(ctx, a, gen_grevw);
}
static bool trans_greviw(DisasContext *ctx, arg_greviw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
return gen_shiftiw(ctx, a, gen_grevw);
}

View File

@ -16,6 +16,7 @@ riscv_ss.add(files(
'gdbstub.c',
'op_helper.c',
'vector_helper.c',
'bitmanip_helper.c',
'translate.c',
))

View File

@ -627,6 +627,28 @@ static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2)
tcg_gen_not_tl(ret, ret);
}
static bool gen_grevi(DisasContext *ctx, arg_grevi *a)
{
TCGv source1 = tcg_temp_new();
TCGv source2;
gen_get_gpr(source1, a->rs1);
if (a->shamt == (TARGET_LONG_BITS - 8)) {
/* rev8, byte swaps */
tcg_gen_bswap_tl(source1, source1);
} else {
source2 = tcg_temp_new();
tcg_gen_movi_tl(source2, a->shamt);
gen_helper_grev(source1, source1, source2);
tcg_temp_free(source2);
}
gen_set_gpr(a->rd, source1);
tcg_temp_free(source1);
return true;
}
static void gen_ctzw(TCGv ret, TCGv arg1)
{
tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
@ -699,6 +721,12 @@ static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
tcg_temp_free_i32(t2);
}
static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2)
{
tcg_gen_ext32u_tl(arg1, arg1);
gen_helper_grev(ret, arg1, arg2);
}
static bool gen_arith(DisasContext *ctx, arg_r *a,
void(*func)(TCGv, TCGv, TCGv))
{