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:
parent
e58529a8d0
commit
831ec7f3d1
64
target/riscv/bitmanip_helper.c
Normal file
64
target/riscv/bitmanip_helper.c
Normal 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);
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ riscv_ss.add(files(
|
||||
'gdbstub.c',
|
||||
'op_helper.c',
|
||||
'vector_helper.c',
|
||||
'bitmanip_helper.c',
|
||||
'translate.c',
|
||||
))
|
||||
|
||||
|
@ -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))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user