[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instru
From: |
Song Gao |
Subject: |
Re: [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation |
Date: |
Tue, 7 Sep 2021 20:36:19 +0800 |
User-agent: |
Mozilla/5.0 (X11; Linux mips64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 |
Hi, Richard,
Thank you for your comments!
On 09/04/2021 07:04 PM, Richard Henderson wrote:
> On 9/2/21 2:40 PM, Song Gao wrote:
>> +static bool gen_r2_si12(DisasContext *ctx, arg_fmt_rdrjsi12 *a,
>> + DisasExtend src_ext, DisasExtend dst_ext,
>> + void (*func)(TCGv, TCGv, TCGv))
>> +{
>> + ctx->dst_ext = dst_ext;
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, src_ext);
>> + TCGv src2 = tcg_constant_tl(a->si12);
>
> Prefer to put declarations before statements, as per old C90 still.
>
OK.
>> + func(dest, src1, src2);
>> +
>> + if (ctx->dst_ext) {
>
> Given that func does not receive ctx, why store dst_ext into ctx and then
> read it back? It seems like you should just use the parameter directly.
>
OK, ctx->dst_ext will be deleted.
>> +static bool gen_pc(DisasContext *ctx, arg_fmt_rdsi20 *a,
>> + void (*func)(DisasContext *ctx, TCGv, target_long))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> +
>> + func(ctx, dest, a->si20);
>> + return true;
>> +}
>
> Perhaps clearer with:
>
> target_long (*func)(target_long pc, target_long si20)
>
> target_long addr = func(ctx->base.pc_next, a->si20);> OK, ctx->dst_ext will
> be deleted.
> TCGv dest = gpr_dst(ctx, a->rd);
>
> tcg_gen_movi_tl(dest, addr);
> return true;
>
>
Surely.
>
>
>> +static bool gen_mulh(DisasContext *ctx, arg_add_w *a,
>> + void(*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
>> + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
>> + TCGv_i32 discard = tcg_temp_new_i32();
>> + TCGv_i32 t0 = tcg_temp_new_i32();
>> + TCGv_i32 t1 = tcg_temp_new_i32();
>> +
>> + tcg_gen_trunc_tl_i32(t0, src1);
>> + tcg_gen_trunc_tl_i32(t1, src2);
>> + func(discard, t0, t0, t1);
>> + tcg_gen_ext_i32_tl(dest, t0);
>> +
>> + tcg_temp_free_i32(discard);
>> + tcg_temp_free_i32(t0);
>> + tcg_temp_free_i32(t1);
>> + return true;
>> +}
>
> You should be able to use gen_r3 for these.
>
> static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2)
> {
> tcg_gen_mul_i64(dest, src1, src2);
> tcg_gen_sari_i64(dest, dest, 32);
> }
>
> static void gen_mulh_wu(TCGv dest, TCGv src1, TCGv src2)
> {
> tcg_gen_mul_i64(dest, src1, src2);
> tcg_gen_sari_i64(dest, dest, 32);
> }
>
> static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2)
> {
> TCGv discard = tcg_temp_new();
> tcg_gen_muls2_tl(discard, dest, src1, src2);
> tcg_temp_free(discard);
> }
>
> static void gen_mulh_du(TCGv dest, TCGv src1, TCGv src2)
> {
> TCGv discard = tcg_temp_new();
> tcg_gen_mulu2_tl(discard, dest, src1, src2);
> tcg_temp_free(discard);
> }
>
> TRANS(mulh_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
> TRANS(mulh_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_wu)
> TRANS(mulh_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
> TRANS(mulh_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
>
>> +static bool gen_mulw_d(DisasContext *ctx, arg_add_w *a,
>> + void(*func)(TCGv_i64, TCGv))
>> +{
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
>> + TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
>> +
>> + func(src1, src1);
>> + func(src2, src2);
>> + tcg_gen_mul_i64(dest, src1, src2);
>> + return true;
>> +}
>
> The func parameter here serves the same purpose as DisasExtend, so again you
> can use gen_r3:
>
> TRANS(mulw_d_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)
> TRANS(mulw_d_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl)
>
>
OK.
>
>> +
>> +static bool gen_div_w(DisasContext *ctx, arg_fmt_rdrjrk *a,
>> + DisasExtend src_ext, DisasExtend dst_ext,
>> + void(*func)(TCGv, TCGv, TCGv))
>> +{
>> + ctx->dst_ext = dst_ext;
>> + TCGv dest = gpr_dst(ctx, a->rd);
>> + TCGv src1 = gpr_src(ctx, a->rj, src_ext);
>> + TCGv src2 = gpr_src(ctx, a->rk, src_ext);
>> + TCGv t2 = tcg_temp_new();
>> + TCGv t3 = tcg_temp_new();
>> +
>> + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src1, INT_MIN);
>> + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, -1);
>> + tcg_gen_and_tl(t2, t2, t3);
>> + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, src2, 0);
>> + tcg_gen_or_tl(t2, t2, t3);
>> + tcg_gen_movi_tl(t3, 0);
>> + tcg_gen_movcond_tl(TCG_COND_NE, src2, t2, t3, t2, src2);
>
> Bug, writing back to src2.
> OK.
>> + func(dest, src1, src2);
>
> You can split this out differently so that you can use gen_r3.
>
> static TCGv prep_divisor_d(TCGv src1, TCGv src2)
> {
> TCGv t0 = temp_new();
> TCGv t1 = tcg_temp_new();
> TCGv t2 = tcg_temp_new();
> TCGv zero = tcg_constant_tl(0);
>
> /*
> * If min / -1, set the divisor to 1.
> * This avoids potential host overflow trap and produces min.
> * If x / 0, set the divisor to 1.
> * This avoids potential host overflow trap;
> * the required result is undefined.
> */
> tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src1, INT64_MIN);
> tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, -1);
> tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, 0);
> tcg_gen_and_tl(t0, t0, t1);
> tcg_gen_or_tl(t0, t0, t2);
> tcg_gen_movcond_tl(TCG_COND_NE, t0, t0, zero, t0, src2);
>
> tcg_temp_free(t1);
> tcg_temp_free(t2);
> return t0;
> }
>
> static TCGv prep_divisor_du(TCGv src2)
> {
> TCGv t0 = temp_new();
> TCGv zero = tcg_constant_tl(0);
> TCGv one = tcg_constant_tl(1);
>
> /*
> * If x / 0, set the divisor to 1.
> * This avoids potential host overflow trap;
> * the required result is undefined.
> */
> tcg_gen_movcond_tl(TCG_COND_EQ, t0, src2, zero, one, src2);
> return t0;
> }
>
> static void gen_div_d(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_d(src1, src2);
> tcg_gen_div_tl(dest, src1, src2);
> }
>
> static void gen_rem_d(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_d(src1, src2);
> tcg_gen_rem_tl(dest, src1, src2);
> }
>
> static void gen_div_du(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_du(src2);
> tcg_gen_divu_tl(dest, src1, src2);
> }
>
> static void gen_rem_du(TCGv dest, TCGv src1, TCGv src2)
> {
> src2 = prep_divisor_du(src2);
> tcg_gen_remu_tl(dest, src1, src2);
> }
>
> static void gen_div_w(TCGv dest, TCGv src1, TCGv src2)
> {
> /* We need not check for integer overflow for div_w. */
> src2 = prep_divisor_du(src2);
> tcg_gen_div_tl(dest, src1, src2);
> }
>
> static void gen_rem_w(TCGv dest, TCGv src1, TCGv src2)
> {
> /* We need not check for integer overflow for rem_w. */
> src2 = prep_divisor_du(src2);
> tcg_gen_rem_tl(dest, src1, src2);
> }
>
> TRANS(div_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w)
> TRANS(mod_w, gen_r3, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w)
> TRANS(div_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
> TRANS(mod_wu, gen_r3, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
> TRANS(div_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d)
> TRANS(mod_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d)
> TRANS(div_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du)
> TRANS(mod_du, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du)
>
Nice.
>> --- a/target/loongarch/internals.h
>> +++ b/target/loongarch/internals.h
>> @@ -9,7 +9,6 @@
>> #ifndef LOONGARCH_INTERNALS_H
>> #define LOONGARCH_INTERNALS_H
>> -
>> void loongarch_translate_init(void);
>> void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
>
> Fold this back to a previous patch.
>
OK
>> -static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
>> -{
>> - return true;
>> -}
>
> Yes indeed, fold this patch to a previous patch.
>
OK.
Song Gao
Thanks.
>
> r~
- [PATCH v4 00/21] Add LoongArch linux-user emulation support, Song Gao, 2021/09/02
- [PATCH v4 01/21] target/loongarch: Add README, Song Gao, 2021/09/02
- [PATCH v4 05/21] target/loongarch: Add fixed point shift instruction translation, Song Gao, 2021/09/02
- [PATCH v4 04/21] target/loongarch: Add fixed point arithmetic instruction translation, Song Gao, 2021/09/02
- [PATCH v4 08/21] target/loongarch: Add fixed point atomic instruction translation, Song Gao, 2021/09/02
- [PATCH v4 11/21] target/loongarch: Add floating point comparison instruction translation, Song Gao, 2021/09/02
- [PATCH v4 13/21] target/loongarch: Add floating point move instruction translation, Song Gao, 2021/09/02
- [PATCH v4 02/21] target/loongarch: Add core definition, Song Gao, 2021/09/02
- [PATCH v4 03/21] target/loongarch: Add main translation routines, Song Gao, 2021/09/02