mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-28 18:07:04 +00:00
target/arm: Implement SVE predicate test
This commit is contained in:
parent
e6a0b2c2bc
commit
1eaa2e4571
|
@ -3274,6 +3274,8 @@
|
|||
#define helper_sdiv64 helper_sdiv64_aarch64
|
||||
#define helper_simd_tbl helper_simd_tbl_aarch64
|
||||
#define helper_sqrt_f16 helper_sqrt_f16_aarch64
|
||||
#define helper_sve_predtest helper_sve_predtest_aarch64
|
||||
#define helper_sve_predtest1 helper_sve_predtest1_aarch64
|
||||
#define helper_udiv64 helper_udiv64_aarch64
|
||||
#define helper_vfp_cmpd_a64 helper_vfp_cmpd_a64_aarch64
|
||||
#define helper_vfp_cmped_a64 helper_vfp_cmped_a64_aarch64
|
||||
|
|
|
@ -3274,6 +3274,8 @@
|
|||
#define helper_sdiv64 helper_sdiv64_aarch64eb
|
||||
#define helper_simd_tbl helper_simd_tbl_aarch64eb
|
||||
#define helper_sqrt_f16 helper_sqrt_f16_aarch64eb
|
||||
#define helper_sve_predtest helper_sve_predtest_aarch64eb
|
||||
#define helper_sve_predtest1 helper_sve_predtest1_aarch64eb
|
||||
#define helper_udiv64 helper_udiv64_aarch64eb
|
||||
#define helper_vfp_cmpd_a64 helper_vfp_cmpd_a64_aarch64eb
|
||||
#define helper_vfp_cmped_a64 helper_vfp_cmped_a64_aarch64eb
|
||||
|
|
|
@ -3295,6 +3295,8 @@ aarch64_symbols = (
|
|||
'helper_sdiv64',
|
||||
'helper_simd_tbl',
|
||||
'helper_sqrt_f16',
|
||||
'helper_sve_predtest',
|
||||
'helper_sve_predtest1',
|
||||
'helper_udiv64',
|
||||
'helper_vfp_cmpd_a64',
|
||||
'helper_vfp_cmped_a64',
|
||||
|
|
|
@ -14,4 +14,4 @@ target/arm/decode-sve.inc.c: $(SRC_PATH)/target/arm/sve.decode $(DECODETREE)
|
|||
"GEN", $(TARGET_DIR)$@)
|
||||
|
||||
target/arm/translate-sve.o: target/arm/decode-sve.inc.c
|
||||
obj-$(TARGET_AARCH64) += translate-sve.o
|
||||
obj-$(TARGET_AARCH64) += translate-sve.o sve_helper.o
|
||||
|
|
21
qemu/target/arm/helper-sve.h
Normal file
21
qemu/target/arm/helper-sve.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* AArch64 SVE specific helper definitions
|
||||
*
|
||||
* Copyright (c) 2018 Linaro, Ltd
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
DEF_HELPER_FLAGS_2(sve_predtest1, TCG_CALL_NO_WG, i32, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(sve_predtest, TCG_CALL_NO_WG, i32, ptr, ptr, i32)
|
|
@ -612,4 +612,5 @@ DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
|
|||
|
||||
#ifdef TARGET_AARCH64
|
||||
#include "helper-a64.h"
|
||||
#include "helper-sve.h"
|
||||
#endif
|
||||
|
|
|
@ -56,6 +56,11 @@ ORR_zzz 00000100 01 1 ..... 001 100 ..... ..... @rd_rn_rm_e0
|
|||
EOR_zzz 00000100 10 1 ..... 001 100 ..... ..... @rd_rn_rm_e0
|
||||
BIC_zzz 00000100 11 1 ..... 001 100 ..... ..... @rd_rn_rm_e0
|
||||
|
||||
### SVE Predicate Misc Group
|
||||
|
||||
# SVE predicate test
|
||||
PTEST 00100101 01 010000 11 pg:4 0 rn:4 0 0000
|
||||
|
||||
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
|
||||
|
||||
# SVE load predicate register
|
||||
|
|
78
qemu/target/arm/sve_helper.c
Normal file
78
qemu/target/arm/sve_helper.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* ARM SVE Operations
|
||||
*
|
||||
* Copyright (c) 2018 Linaro, Ltd.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "tcg/tcg-gvec-desc.h"
|
||||
|
||||
|
||||
/* Return a value for NZCV as per the ARM PredTest pseudofunction.
|
||||
*
|
||||
* The return value has bit 31 set if N is set, bit 1 set if Z is clear,
|
||||
* and bit 0 set if C is set. Compare the definitions of these variables
|
||||
* within CPUARMState.
|
||||
*/
|
||||
|
||||
/* For no G bits set, NZCV = C. */
|
||||
#define PREDTEST_INIT 1
|
||||
|
||||
/* This is an iterative function, called for each Pd and Pg word
|
||||
* moving forward.
|
||||
*/
|
||||
static uint32_t iter_predtest_fwd(uint64_t d, uint64_t g, uint32_t flags)
|
||||
{
|
||||
if (likely(g)) {
|
||||
/* Compute N from first D & G.
|
||||
Use bit 2 to signal first G bit seen. */
|
||||
if (!(flags & 4)) {
|
||||
flags |= ((d & (g & -g)) != 0) << 31;
|
||||
flags |= 4;
|
||||
}
|
||||
|
||||
/* Accumulate Z from each D & G. */
|
||||
flags |= ((d & g) != 0) << 1;
|
||||
|
||||
/* Compute C from last !(D & G). Replace previous. */
|
||||
flags = deposit32(flags, 0, 1, (d & pow2floor(g)) == 0);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* The same for a single word predicate. */
|
||||
uint32_t HELPER(sve_predtest1)(uint64_t d, uint64_t g)
|
||||
{
|
||||
return iter_predtest_fwd(d, g, PREDTEST_INIT);
|
||||
}
|
||||
|
||||
/* The same for a multi-word predicate. */
|
||||
uint32_t HELPER(sve_predtest)(void *vd, void *vg, uint32_t words)
|
||||
{
|
||||
uint32_t flags = PREDTEST_INIT;
|
||||
uint64_t *d = vd, *g = vg;
|
||||
uintptr_t i = 0;
|
||||
|
||||
do {
|
||||
flags = iter_predtest_fwd(d[i], g[i], flags);
|
||||
} while (++i < words);
|
||||
|
||||
return flags;
|
||||
}
|
|
@ -86,6 +86,46 @@ static bool do_mov_z(DisasContext *s, int rd, int rn)
|
|||
return do_vector2_z(s, tcg_gen_gvec_mov, 0, rd, rn);
|
||||
}
|
||||
|
||||
/* Set the cpu flags as per a return from an SVE helper. */
|
||||
static void do_pred_flags(DisasContext *s, TCGv_i32 t)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->cpu_NF, t);
|
||||
tcg_gen_andi_i32(tcg_ctx, tcg_ctx->cpu_ZF, t, 2);
|
||||
tcg_gen_andi_i32(tcg_ctx, tcg_ctx->cpu_CF, t, 1);
|
||||
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_VF, 0);
|
||||
}
|
||||
|
||||
/* Subroutines computing the ARM PredTest psuedofunction. */
|
||||
static void do_predtest1(DisasContext *s, TCGv_i64 d, TCGv_i64 g)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
TCGv_i32 t = tcg_temp_new_i32(tcg_ctx);
|
||||
|
||||
gen_helper_sve_predtest1(tcg_ctx, t, d, g);
|
||||
do_pred_flags(s, t);
|
||||
tcg_temp_free_i32(tcg_ctx, t);
|
||||
}
|
||||
|
||||
static void do_predtest(DisasContext *s, int dofs, int gofs, int words)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
TCGv_ptr dptr = tcg_temp_new_ptr(tcg_ctx);
|
||||
TCGv_ptr gptr = tcg_temp_new_ptr(tcg_ctx);
|
||||
TCGv_i32 t;
|
||||
|
||||
tcg_gen_addi_ptr(tcg_ctx, dptr, tcg_ctx->cpu_env, dofs);
|
||||
tcg_gen_addi_ptr(tcg_ctx, gptr, tcg_ctx->cpu_env, gofs);
|
||||
t = tcg_const_i32(tcg_ctx, words);
|
||||
|
||||
gen_helper_sve_predtest(tcg_ctx, t, dptr, gptr, t);
|
||||
tcg_temp_free_ptr(tcg_ctx, dptr);
|
||||
tcg_temp_free_ptr(tcg_ctx, gptr);
|
||||
|
||||
do_pred_flags(s, t);
|
||||
tcg_temp_free_i32(tcg_ctx, t);
|
||||
}
|
||||
|
||||
/*
|
||||
*** SVE Logical - Unpredicated Group
|
||||
*/
|
||||
|
@ -114,6 +154,35 @@ static bool trans_BIC_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
|
|||
return do_vector3_z(s, tcg_gen_gvec_andc, 0, a->rd, a->rn, a->rm);
|
||||
}
|
||||
|
||||
/*
|
||||
*** SVE Predicate Misc Group
|
||||
*/
|
||||
|
||||
static bool trans_PTEST(DisasContext *s, arg_PTEST *a, uint32_t insn)
|
||||
{
|
||||
if (sve_access_check(s)) {
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
int nofs = pred_full_reg_offset(s, a->rn);
|
||||
int gofs = pred_full_reg_offset(s, a->pg);
|
||||
int words = DIV_ROUND_UP(pred_full_reg_size(s), 8);
|
||||
|
||||
if (words == 1) {
|
||||
TCGv_i64 pn = tcg_temp_new_i64(tcg_ctx);
|
||||
TCGv_i64 pg = tcg_temp_new_i64(tcg_ctx);
|
||||
|
||||
tcg_gen_ld_i64(tcg_ctx, pn, tcg_ctx->cpu_env, nofs);
|
||||
tcg_gen_ld_i64(tcg_ctx, pg, tcg_ctx->cpu_env, gofs);
|
||||
do_predtest1(s, pn, pg);
|
||||
|
||||
tcg_temp_free_i64(tcg_ctx, pn);
|
||||
tcg_temp_free_i64(tcg_ctx, pg);
|
||||
} else {
|
||||
do_predtest(s, nofs, gofs, words);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue