mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
tcg/loongarch64: Implement clz/ctz ops
Signed-off-by: WANG Xuerui <git@xen0n.name> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20211221054105.178795-16-git@xen0n.name> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
4ab2aff0db
commit
fde6930160
|
@ -18,4 +18,5 @@ C_O0_I1(r)
|
|||
C_O1_I1(r, r)
|
||||
C_O1_I2(r, r, rC)
|
||||
C_O1_I2(r, r, rU)
|
||||
C_O1_I2(r, r, rW)
|
||||
C_O1_I2(r, 0, rZ)
|
||||
|
|
|
@ -412,6 +412,28 @@ static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
|
|||
tcg_out_opc_addi_w(s, ret, arg, 0);
|
||||
}
|
||||
|
||||
static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
|
||||
TCGReg a0, TCGReg a1, TCGReg a2,
|
||||
bool c2, bool is_32bit)
|
||||
{
|
||||
if (c2) {
|
||||
/*
|
||||
* Fast path: semantics already satisfied due to constraint and
|
||||
* insn behavior, single instruction is enough.
|
||||
*/
|
||||
tcg_debug_assert(a2 == (is_32bit ? 32 : 64));
|
||||
/* all clz/ctz insns belong to DJ-format */
|
||||
tcg_out32(s, encode_dj_insn(opc, a0, a1));
|
||||
return;
|
||||
}
|
||||
|
||||
tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1));
|
||||
/* a0 = a1 ? REG_TMP0 : a2 */
|
||||
tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1);
|
||||
tcg_out_opc_masknez(s, a0, a2, a1);
|
||||
tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry-points
|
||||
*/
|
||||
|
@ -572,6 +594,20 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||
tcg_out_opc_revb_d(s, a0, a1);
|
||||
break;
|
||||
|
||||
case INDEX_op_clz_i32:
|
||||
tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true);
|
||||
break;
|
||||
case INDEX_op_clz_i64:
|
||||
tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false);
|
||||
break;
|
||||
|
||||
case INDEX_op_ctz_i32:
|
||||
tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true);
|
||||
break;
|
||||
case INDEX_op_ctz_i64:
|
||||
tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false);
|
||||
break;
|
||||
|
||||
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
|
||||
case INDEX_op_mov_i64:
|
||||
default:
|
||||
|
@ -632,6 +668,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
|
|||
/* LoongArch reg-imm bitops have their imms ZERO-extended */
|
||||
return C_O1_I2(r, r, rU);
|
||||
|
||||
case INDEX_op_clz_i32:
|
||||
case INDEX_op_clz_i64:
|
||||
case INDEX_op_ctz_i32:
|
||||
case INDEX_op_ctz_i64:
|
||||
return C_O1_I2(r, r, rW);
|
||||
|
||||
case INDEX_op_deposit_i32:
|
||||
case INDEX_op_deposit_i64:
|
||||
/* Must deposit into the same register as input */
|
||||
|
|
|
@ -120,8 +120,8 @@ typedef enum {
|
|||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 1
|
||||
#define TCG_TARGET_HAS_clz_i32 0
|
||||
#define TCG_TARGET_HAS_ctz_i32 0
|
||||
#define TCG_TARGET_HAS_clz_i32 1
|
||||
#define TCG_TARGET_HAS_ctz_i32 1
|
||||
#define TCG_TARGET_HAS_ctpop_i32 0
|
||||
#define TCG_TARGET_HAS_direct_jump 0
|
||||
#define TCG_TARGET_HAS_brcond2 0
|
||||
|
@ -156,8 +156,8 @@ typedef enum {
|
|||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 1
|
||||
#define TCG_TARGET_HAS_clz_i64 0
|
||||
#define TCG_TARGET_HAS_ctz_i64 0
|
||||
#define TCG_TARGET_HAS_clz_i64 1
|
||||
#define TCG_TARGET_HAS_ctz_i64 1
|
||||
#define TCG_TARGET_HAS_ctpop_i64 0
|
||||
#define TCG_TARGET_HAS_add2_i64 0
|
||||
#define TCG_TARGET_HAS_sub2_i64 0
|
||||
|
|
Loading…
Reference in a new issue