Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
target/loongarch: Add fixed point arithmetic instruction translation
This includes: - ADD.{W/D}, SUB.{W/D} - ADDI.{W/D}, ADDU16ID - ALSL.{W[U]/D} - LU12I.W, LU32I.D LU52I.D - SLT[U], SLT[U]I - PCADDI, PCADDU12I, PCADDU18I, PCALAU12I - AND, OR, NOR, XOR, ANDN, ORN - MUL.{W/D}, MULH.{W[U]/D[U]} - MULW.D.W[U] - DIV.{W[U]/D[U]}, MOD.{W[U]/D[U]} - ANDI, ORI, XORI Signed-off-by: Song Gao <gaosong@loongson.cn> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220606124333.2060567-5-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
- Loading branch information
1 parent
f8da88d
commit 143d678
Showing
4 changed files
with
485 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,304 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
/* | ||
* Copyright (c) 2021 Loongson Technology Corporation Limited | ||
*/ | ||
|
||
static bool gen_rrr(DisasContext *ctx, arg_rrr *a, | ||
DisasExtend src1_ext, DisasExtend src2_ext, | ||
DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv)) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, dst_ext); | ||
TCGv src1 = gpr_src(ctx, a->rj, src1_ext); | ||
TCGv src2 = gpr_src(ctx, a->rk, src2_ext); | ||
|
||
func(dest, src1, src2); | ||
gen_set_gpr(a->rd, dest, dst_ext); | ||
|
||
return true; | ||
} | ||
|
||
static bool gen_rri_v(DisasContext *ctx, arg_rr_i *a, | ||
DisasExtend src_ext, DisasExtend dst_ext, | ||
void (*func)(TCGv, TCGv, TCGv)) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, dst_ext); | ||
TCGv src1 = gpr_src(ctx, a->rj, src_ext); | ||
TCGv src2 = tcg_constant_tl(a->imm); | ||
|
||
func(dest, src1, src2); | ||
gen_set_gpr(a->rd, dest, dst_ext); | ||
|
||
return true; | ||
} | ||
|
||
static bool gen_rri_c(DisasContext *ctx, arg_rr_i *a, | ||
DisasExtend src_ext, DisasExtend dst_ext, | ||
void (*func)(TCGv, TCGv, target_long)) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, dst_ext); | ||
TCGv src1 = gpr_src(ctx, a->rj, src_ext); | ||
|
||
func(dest, src1, a->imm); | ||
gen_set_gpr(a->rd, dest, dst_ext); | ||
|
||
return true; | ||
} | ||
|
||
static bool gen_rrr_sa(DisasContext *ctx, arg_rrr_sa *a, | ||
DisasExtend src_ext, DisasExtend dst_ext, | ||
void (*func)(TCGv, TCGv, TCGv, target_long)) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, dst_ext); | ||
TCGv src1 = gpr_src(ctx, a->rj, src_ext); | ||
TCGv src2 = gpr_src(ctx, a->rk, src_ext); | ||
|
||
func(dest, src1, src2, a->sa); | ||
gen_set_gpr(a->rd, dest, dst_ext); | ||
|
||
return true; | ||
} | ||
|
||
static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); | ||
|
||
tcg_gen_movi_tl(dest, a->imm << 12); | ||
gen_set_gpr(a->rd, dest, EXT_NONE); | ||
|
||
return true; | ||
} | ||
|
||
static bool gen_pc(DisasContext *ctx, arg_r_i *a, | ||
target_ulong (*func)(target_ulong, int)) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); | ||
target_ulong addr = func(ctx->base.pc_next, a->imm); | ||
|
||
tcg_gen_movi_tl(dest, addr); | ||
gen_set_gpr(a->rd, dest, EXT_NONE); | ||
|
||
return true; | ||
} | ||
|
||
static void gen_slt(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
tcg_gen_setcond_tl(TCG_COND_LT, dest, src1, src2); | ||
} | ||
|
||
static void gen_sltu(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
tcg_gen_setcond_tl(TCG_COND_LTU, dest, src1, src2); | ||
} | ||
|
||
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_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); | ||
} | ||
|
||
static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
TCGv t1 = 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, ret, src1, INT64_MIN); | ||
tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1); | ||
tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0); | ||
tcg_gen_and_tl(ret, ret, t0); | ||
tcg_gen_or_tl(ret, ret, t1); | ||
tcg_gen_movcond_tl(TCG_COND_NE, ret, ret, zero, ret, src2); | ||
|
||
tcg_temp_free(t0); | ||
tcg_temp_free(t1); | ||
} | ||
|
||
static void prep_divisor_du(TCGv ret, TCGv src2) | ||
{ | ||
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, ret, src2, zero, one, src2); | ||
} | ||
|
||
static void gen_div_d(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
prep_divisor_d(t0, src1, src2); | ||
tcg_gen_div_tl(dest, src1, t0); | ||
tcg_temp_free(t0); | ||
} | ||
|
||
static void gen_rem_d(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
prep_divisor_d(t0, src1, src2); | ||
tcg_gen_rem_tl(dest, src1, t0); | ||
tcg_temp_free(t0); | ||
} | ||
|
||
static void gen_div_du(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
prep_divisor_du(t0, src2); | ||
tcg_gen_divu_tl(dest, src1, t0); | ||
tcg_temp_free(t0); | ||
} | ||
|
||
static void gen_rem_du(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
prep_divisor_du(t0, src2); | ||
tcg_gen_remu_tl(dest, src1, t0); | ||
tcg_temp_free(t0); | ||
} | ||
|
||
static void gen_div_w(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
/* We need not check for integer overflow for div_w. */ | ||
prep_divisor_du(t0, src2); | ||
tcg_gen_div_tl(dest, src1, t0); | ||
tcg_temp_free(t0); | ||
} | ||
|
||
static void gen_rem_w(TCGv dest, TCGv src1, TCGv src2) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
/* We need not check for integer overflow for rem_w. */ | ||
prep_divisor_du(t0, src2); | ||
tcg_gen_rem_tl(dest, src1, t0); | ||
tcg_temp_free(t0); | ||
} | ||
|
||
static void gen_alsl(TCGv dest, TCGv src1, TCGv src2, target_long sa) | ||
{ | ||
TCGv t0 = tcg_temp_new(); | ||
tcg_gen_shli_tl(t0, src1, sa); | ||
tcg_gen_add_tl(dest, t0, src2); | ||
tcg_temp_free(t0); | ||
} | ||
|
||
static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); | ||
TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE); | ||
TCGv src2 = tcg_constant_tl(a->imm); | ||
|
||
tcg_gen_deposit_tl(dest, src1, src2, 32, 32); | ||
gen_set_gpr(a->rd, dest, EXT_NONE); | ||
|
||
return true; | ||
} | ||
|
||
static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); | ||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); | ||
TCGv src2 = tcg_constant_tl(a->imm); | ||
|
||
tcg_gen_deposit_tl(dest, src1, src2, 52, 12); | ||
gen_set_gpr(a->rd, dest, EXT_NONE); | ||
|
||
return true; | ||
} | ||
|
||
static target_ulong gen_pcaddi(target_ulong pc, int imm) | ||
{ | ||
return pc + (imm << 2); | ||
} | ||
|
||
static target_ulong gen_pcalau12i(target_ulong pc, int imm) | ||
{ | ||
return (pc + (imm << 12)) & ~0xfff; | ||
} | ||
|
||
static target_ulong gen_pcaddu12i(target_ulong pc, int imm) | ||
{ | ||
return pc + (imm << 12); | ||
} | ||
|
||
static target_ulong gen_pcaddu18i(target_ulong pc, int imm) | ||
{ | ||
return pc + ((target_ulong)(imm) << 18); | ||
} | ||
|
||
static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a) | ||
{ | ||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); | ||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); | ||
|
||
tcg_gen_addi_tl(dest, src1, a->imm << 16); | ||
gen_set_gpr(a->rd, dest, EXT_NONE); | ||
|
||
return true; | ||
} | ||
|
||
TRANS(add_w, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_add_tl) | ||
TRANS(add_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_add_tl) | ||
TRANS(sub_w, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_sub_tl) | ||
TRANS(sub_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_sub_tl) | ||
TRANS(and, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_and_tl) | ||
TRANS(or, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_or_tl) | ||
TRANS(xor, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_xor_tl) | ||
TRANS(nor, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_nor_tl) | ||
TRANS(andn, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_andc_tl) | ||
TRANS(orn, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_orc_tl) | ||
TRANS(slt, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_slt) | ||
TRANS(sltu, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu) | ||
TRANS(mul_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl) | ||
TRANS(mul_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl) | ||
TRANS(mulh_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w) | ||
TRANS(mulh_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_w) | ||
TRANS(mulh_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d) | ||
TRANS(mulh_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du) | ||
TRANS(mulw_d_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl) | ||
TRANS(mulw_d_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl) | ||
TRANS(div_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w) | ||
TRANS(mod_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w) | ||
TRANS(div_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du) | ||
TRANS(mod_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_rem_du) | ||
TRANS(div_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d) | ||
TRANS(mod_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d) | ||
TRANS(div_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du) | ||
TRANS(mod_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du) | ||
TRANS(slti, gen_rri_v, EXT_NONE, EXT_NONE, gen_slt) | ||
TRANS(sltui, gen_rri_v, EXT_NONE, EXT_NONE, gen_sltu) | ||
TRANS(addi_w, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_addi_tl) | ||
TRANS(addi_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_addi_tl) | ||
TRANS(alsl_w, gen_rrr_sa, EXT_NONE, EXT_SIGN, gen_alsl) | ||
TRANS(alsl_wu, gen_rrr_sa, EXT_NONE, EXT_ZERO, gen_alsl) | ||
TRANS(alsl_d, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_alsl) | ||
TRANS(pcaddi, gen_pc, gen_pcaddi) | ||
TRANS(pcalau12i, gen_pc, gen_pcalau12i) | ||
TRANS(pcaddu12i, gen_pc, gen_pcaddu12i) | ||
TRANS(pcaddu18i, gen_pc, gen_pcaddu18i) | ||
TRANS(andi, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_andi_tl) | ||
TRANS(ori, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_ori_tl) | ||
TRANS(xori, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_xori_tl) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# SPDX-License-Identifier: GPL-2.0-or-later | ||
# | ||
# LoongArch instruction decode definitions. | ||
# | ||
# Copyright (c) 2021 Loongson Technology Corporation Limited | ||
# | ||
|
||
# | ||
# Fields | ||
# | ||
%sa2p1 15:2 !function=plus_1 | ||
|
||
# | ||
# Argument sets | ||
# | ||
&r_i rd imm | ||
&rrr rd rj rk | ||
&rr_i rd rj imm | ||
&rrr_sa rd rj rk sa | ||
|
||
# | ||
# Formats | ||
# | ||
@rrr .... ........ ..... rk:5 rj:5 rd:5 &rrr | ||
@r_i20 .... ... imm:s20 rd:5 &r_i | ||
@rr_i12 .... ...... imm:s12 rj:5 rd:5 &rr_i | ||
@rr_ui12 .... ...... imm:12 rj:5 rd:5 &rr_i | ||
@rr_i16 .... .. imm:s16 rj:5 rd:5 &rr_i | ||
@rrr_sa2p1 .... ........ ... .. rk:5 rj:5 rd:5 &rrr_sa sa=%sa2p1 | ||
|
||
# | ||
# Fixed point arithmetic operation instruction | ||
# | ||
add_w 0000 00000001 00000 ..... ..... ..... @rrr | ||
add_d 0000 00000001 00001 ..... ..... ..... @rrr | ||
sub_w 0000 00000001 00010 ..... ..... ..... @rrr | ||
sub_d 0000 00000001 00011 ..... ..... ..... @rrr | ||
slt 0000 00000001 00100 ..... ..... ..... @rrr | ||
sltu 0000 00000001 00101 ..... ..... ..... @rrr | ||
slti 0000 001000 ............ ..... ..... @rr_i12 | ||
sltui 0000 001001 ............ ..... ..... @rr_i12 | ||
nor 0000 00000001 01000 ..... ..... ..... @rrr | ||
and 0000 00000001 01001 ..... ..... ..... @rrr | ||
or 0000 00000001 01010 ..... ..... ..... @rrr | ||
xor 0000 00000001 01011 ..... ..... ..... @rrr | ||
orn 0000 00000001 01100 ..... ..... ..... @rrr | ||
andn 0000 00000001 01101 ..... ..... ..... @rrr | ||
mul_w 0000 00000001 11000 ..... ..... ..... @rrr | ||
mulh_w 0000 00000001 11001 ..... ..... ..... @rrr | ||
mulh_wu 0000 00000001 11010 ..... ..... ..... @rrr | ||
mul_d 0000 00000001 11011 ..... ..... ..... @rrr | ||
mulh_d 0000 00000001 11100 ..... ..... ..... @rrr | ||
mulh_du 0000 00000001 11101 ..... ..... ..... @rrr | ||
mulw_d_w 0000 00000001 11110 ..... ..... ..... @rrr | ||
mulw_d_wu 0000 00000001 11111 ..... ..... ..... @rrr | ||
div_w 0000 00000010 00000 ..... ..... ..... @rrr | ||
mod_w 0000 00000010 00001 ..... ..... ..... @rrr | ||
div_wu 0000 00000010 00010 ..... ..... ..... @rrr | ||
mod_wu 0000 00000010 00011 ..... ..... ..... @rrr | ||
div_d 0000 00000010 00100 ..... ..... ..... @rrr | ||
mod_d 0000 00000010 00101 ..... ..... ..... @rrr | ||
div_du 0000 00000010 00110 ..... ..... ..... @rrr | ||
mod_du 0000 00000010 00111 ..... ..... ..... @rrr | ||
alsl_w 0000 00000000 010 .. ..... ..... ..... @rrr_sa2p1 | ||
alsl_wu 0000 00000000 011 .. ..... ..... ..... @rrr_sa2p1 | ||
alsl_d 0000 00000010 110 .. ..... ..... ..... @rrr_sa2p1 | ||
lu12i_w 0001 010 .................... ..... @r_i20 | ||
lu32i_d 0001 011 .................... ..... @r_i20 | ||
lu52i_d 0000 001100 ............ ..... ..... @rr_i12 | ||
pcaddi 0001 100 .................... ..... @r_i20 | ||
pcalau12i 0001 101 .................... ..... @r_i20 | ||
pcaddu12i 0001 110 .................... ..... @r_i20 | ||
pcaddu18i 0001 111 .................... ..... @r_i20 | ||
addi_w 0000 001010 ............ ..... ..... @rr_i12 | ||
addi_d 0000 001011 ............ ..... ..... @rr_i12 | ||
addu16i_d 0001 00 ................ ..... ..... @rr_i16 | ||
andi 0000 001101 ............ ..... ..... @rr_ui12 | ||
ori 0000 001110 ............ ..... ..... @rr_ui12 | ||
xori 0000 001111 ............ ..... ..... @rr_ui12 |
Oops, something went wrong.