123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979 |
- From 9db41d30248bce990151f2c06c65abb845a844a8 Mon Sep 17 00:00:00 2001
- From: Kito Cheng <kito.cheng@sifive.com>
- Date: Thu, 26 Mar 2020 21:55:37 +0800
- Subject: [PATCH 004/107] target/riscv: Implement zfh extension.
- Signed-off-by: Kito Cheng <kito.cheng@sifive.com>
- Signed-off-by: Chih-Min Chao <chihmin.chao@sifive.com>
- ---
- target/riscv/fpu_helper.c | 180 ++++++++
- target/riscv/helper.h | 34 ++
- target/riscv/insn32-64.decode | 6 +
- target/riscv/insn32.decode | 32 ++
- target/riscv/insn_trans/trans_rvzfh.c.inc | 535 ++++++++++++++++++++++
- target/riscv/internals.h | 16 +
- target/riscv/translate.c | 18 +
- 7 files changed, 821 insertions(+)
- create mode 100644 target/riscv/insn_trans/trans_rvzfh.c.inc
- diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
- index 5d2cec3de3..09d37c1384 100644
- --- a/target/riscv/fpu_helper.c
- +++ b/target/riscv/fpu_helper.c
- @@ -81,6 +81,15 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
- set_float_rounding_mode(softrm, &env->fp_status);
- }
-
- +static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
- + uint64_t rs3, int flags)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + float16 frs3 = check_nanbox_h(rs3);
- + return nanbox_h(float16_muladd(frs1, frs2, frs3, flags, &env->fp_status));
- +}
- +
- static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
- uint64_t rs3, int flags)
- {
- @@ -102,6 +111,12 @@ uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
- }
-
- +uint64_t helper_fmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- + uint64_t frs3)
- +{
- + return do_fmadd_h(env, frs1, frs2, frs3, 0);
- +}
- +
- uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- uint64_t frs3)
- {
- @@ -115,6 +130,12 @@ uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- &env->fp_status);
- }
-
- +uint64_t helper_fmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- + uint64_t frs3)
- +{
- + return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_c);
- +}
- +
- uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- uint64_t frs3)
- {
- @@ -128,6 +149,12 @@ uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- &env->fp_status);
- }
-
- +uint64_t helper_fnmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- + uint64_t frs3)
- +{
- + return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_product);
- +}
- +
- uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- uint64_t frs3)
- {
- @@ -142,6 +169,13 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- float_muladd_negate_product, &env->fp_status);
- }
-
- +uint64_t helper_fnmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
- + uint64_t frs3)
- +{
- + return do_fmadd_h(env, frs1, frs2, frs3,
- + float_muladd_negate_c | float_muladd_negate_product);
- +}
- +
- uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- {
- float32 frs1 = check_nanbox_s(rs1);
- @@ -366,3 +400,149 @@ target_ulong helper_fclass_d(uint64_t frs1)
- {
- return fclass_d(frs1);
- }
- +
- +uint64_t helper_fadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return nanbox_h(float16_add(frs1, frs2, &env->fp_status));
- +}
- +
- +uint64_t helper_fsub_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return nanbox_h(float16_sub(frs1, frs2, &env->fp_status));
- +}
- +
- +uint64_t helper_fmul_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return nanbox_h(float16_mul(frs1, frs2, &env->fp_status));
- +}
- +
- +uint64_t helper_fdiv_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return nanbox_h(float16_div(frs1, frs2, &env->fp_status));
- +}
- +
- +uint64_t helper_fmin_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return nanbox_h(float16_minnum_noprop(frs1, frs2, &env->fp_status));
- +}
- +
- +uint64_t helper_fmax_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return nanbox_h(float16_maxnum_noprop(frs1, frs2, &env->fp_status));
- +}
- +
- +uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return nanbox_h(float16_sqrt(frs1, &env->fp_status));
- +}
- +
- +target_ulong helper_fle_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return float16_le(frs1, frs2, &env->fp_status);
- +}
- +
- +target_ulong helper_flt_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return float16_lt(frs1, frs2, &env->fp_status);
- +}
- +
- +target_ulong helper_feq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + float16 frs2 = check_nanbox_h(rs2);
- + return float16_eq_quiet(frs1, frs2, &env->fp_status);
- +}
- +
- +target_ulong helper_fclass_h(uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return fclass_h(frs1);
- +}
- +
- +target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return float16_to_int32(frs1, &env->fp_status);
- +}
- +
- +target_ulong helper_fcvt_wu_h(CPURISCVState *env, uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return (int32_t)float16_to_uint32(frs1, &env->fp_status);
- +}
- +
- +#if defined(TARGET_RISCV64)
- +uint64_t helper_fcvt_l_h(CPURISCVState *env, uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return float16_to_int64(frs1, &env->fp_status);
- +}
- +
- +uint64_t helper_fcvt_lu_h(CPURISCVState *env, uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return float16_to_uint64(frs1, &env->fp_status);
- +}
- +#endif
- +
- +uint64_t helper_fcvt_h_w(CPURISCVState *env, target_ulong rs1)
- +{
- + return nanbox_h(int32_to_float16((int32_t)rs1, &env->fp_status));
- +}
- +
- +uint64_t helper_fcvt_h_wu(CPURISCVState *env, target_ulong rs1)
- +{
- + return nanbox_h(uint32_to_float16((uint32_t)rs1, &env->fp_status));
- +}
- +
- +#if defined(TARGET_RISCV64)
- +uint64_t helper_fcvt_h_l(CPURISCVState *env, uint64_t rs1)
- +{
- + return nanbox_h(int64_to_float16(rs1, &env->fp_status));
- +}
- +
- +uint64_t helper_fcvt_h_lu(CPURISCVState *env, uint64_t rs1)
- +{
- + return nanbox_h(uint64_to_float16(rs1, &env->fp_status));
- +}
- +#endif
- +
- +uint64_t helper_fcvt_h_s(CPURISCVState *env, uint64_t rs1)
- +{
- + float32 frs1 = check_nanbox_s(rs1);
- + return nanbox_h(float32_to_float16(frs1, true, &env->fp_status));
- +}
- +
- +uint64_t helper_fcvt_s_h(CPURISCVState *env, uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return nanbox_s(float16_to_float32(frs1, true, &env->fp_status));
- +}
- +
- +uint64_t helper_fcvt_h_d(CPURISCVState *env, uint64_t rs1)
- +{
- + return nanbox_h(float64_to_float16(rs1, true, &env->fp_status));
- +}
- +
- +uint64_t helper_fcvt_d_h(CPURISCVState *env, uint64_t rs1)
- +{
- + float16 frs1 = check_nanbox_h(rs1);
- + return float16_to_float64(frs1, true, &env->fp_status);
- +}
- diff --git a/target/riscv/helper.h b/target/riscv/helper.h
- index e3f3f41e89..1104a3540a 100644
- --- a/target/riscv/helper.h
- +++ b/target/riscv/helper.h
- @@ -7,12 +7,16 @@ DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_WG, void, env, i32)
- /* Floating Point - fused */
- DEF_HELPER_FLAGS_4(fmadd_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- DEF_HELPER_FLAGS_4(fmadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- +DEF_HELPER_FLAGS_4(fmadd_h, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- DEF_HELPER_FLAGS_4(fmsub_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- DEF_HELPER_FLAGS_4(fmsub_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- +DEF_HELPER_FLAGS_4(fmsub_h, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- DEF_HELPER_FLAGS_4(fnmsub_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- DEF_HELPER_FLAGS_4(fnmsub_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- +DEF_HELPER_FLAGS_4(fnmsub_h, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- DEF_HELPER_FLAGS_4(fnmadd_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- DEF_HELPER_FLAGS_4(fnmadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
- +DEF_HELPER_FLAGS_4(fnmadd_h, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
-
- /* Floating Point - Single Precision */
- DEF_HELPER_FLAGS_3(fadd_s, TCG_CALL_NO_RWG, i64, env, i64, i64)
- @@ -58,6 +62,36 @@ DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, i64)
- DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, i64)
- DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64)
-
- +/* Floating Point - Half Precision */
- +DEF_HELPER_FLAGS_3(fadd_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
- +DEF_HELPER_FLAGS_3(fsub_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
- +DEF_HELPER_FLAGS_3(fmul_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
- +DEF_HELPER_FLAGS_3(fdiv_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
- +DEF_HELPER_FLAGS_3(fmin_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
- +DEF_HELPER_FLAGS_3(fmax_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
- +DEF_HELPER_FLAGS_2(fsqrt_h, TCG_CALL_NO_RWG, i64, env, i64)
- +DEF_HELPER_FLAGS_3(fle_h, TCG_CALL_NO_RWG, tl, env, i64, i64)
- +DEF_HELPER_FLAGS_3(flt_h, TCG_CALL_NO_RWG, tl, env, i64, i64)
- +DEF_HELPER_FLAGS_3(feq_h, TCG_CALL_NO_RWG, tl, env, i64, i64)
- +DEF_HELPER_FLAGS_2(fcvt_s_h, TCG_CALL_NO_RWG, i64, env, i64)
- +DEF_HELPER_FLAGS_2(fcvt_h_s, TCG_CALL_NO_RWG, i64, env, i64)
- +DEF_HELPER_FLAGS_2(fcvt_d_h, TCG_CALL_NO_RWG, i64, env, i64)
- +DEF_HELPER_FLAGS_2(fcvt_h_d, TCG_CALL_NO_RWG, i64, env, i64)
- +DEF_HELPER_FLAGS_2(fcvt_w_h, TCG_CALL_NO_RWG, tl, env, i64)
- +DEF_HELPER_FLAGS_2(fcvt_wu_h, TCG_CALL_NO_RWG, tl, env, i64)
- +#if defined(TARGET_RISCV64)
- +DEF_HELPER_FLAGS_2(fcvt_l_h, TCG_CALL_NO_RWG, tl, env, i64)
- +DEF_HELPER_FLAGS_2(fcvt_lu_h, TCG_CALL_NO_RWG, tl, env, i64)
- +#endif
- +DEF_HELPER_FLAGS_2(fcvt_h_w, TCG_CALL_NO_RWG, i64, env, tl)
- +DEF_HELPER_FLAGS_2(fcvt_h_wu, TCG_CALL_NO_RWG, i64, env, tl)
- +#if defined(TARGET_RISCV64)
- +DEF_HELPER_FLAGS_2(fcvt_h_l, TCG_CALL_NO_RWG, i64, env, tl)
- +DEF_HELPER_FLAGS_2(fcvt_h_lu, TCG_CALL_NO_RWG, i64, env, tl)
- +#endif
- +DEF_HELPER_FLAGS_1(fclass_h, TCG_CALL_NO_RWG_SE, tl, i64)
- +
- +
- /* Special functions */
- DEF_HELPER_3(csrrw, tl, env, tl, tl)
- DEF_HELPER_4(csrrs, tl, env, tl, tl, tl)
- diff --git a/target/riscv/insn32-64.decode b/target/riscv/insn32-64.decode
- index 8157dee8b7..1f5d0b7a5c 100644
- --- a/target/riscv/insn32-64.decode
- +++ b/target/riscv/insn32-64.decode
- @@ -86,3 +86,9 @@ fmv_d_x 1111001 00000 ..... 000 ..... 1010011 @r2
- hlv_wu 0110100 00001 ..... 100 ..... 1110011 @r2
- hlv_d 0110110 00000 ..... 100 ..... 1110011 @r2
- hsv_d 0110111 ..... ..... 100 00000 1110011 @r2_s
- +
- +# *** RV64Zfh Standard Extension (in addition to RV32Zfh) ***
- +fcvt_l_h 1100010 00010 ..... ... ..... 1010011 @r2_rm
- +fcvt_lu_h 1100010 00011 ..... ... ..... 1010011 @r2_rm
- +fcvt_h_l 1101010 00010 ..... ... ..... 1010011 @r2_rm
- +fcvt_h_lu 1101010 00011 ..... ... ..... 1010011 @r2_rm
- diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
- index 84080dd18c..8d9064a7a0 100644
- --- a/target/riscv/insn32.decode
- +++ b/target/riscv/insn32.decode
- @@ -592,3 +592,35 @@ vcompress_vm 010111 - ..... ..... 010 ..... 1010111 @r
-
- vsetvli 0 ........... ..... 111 ..... 1010111 @r2_zimm
- vsetvl 1000000 ..... ..... 111 ..... 1010111 @r
- +
- +# *** RV32Zfh Extension ***
- +flh ............ ..... 001 ..... 0000111 @i
- +fsh ....... ..... ..... 001 ..... 0100111 @s
- +fmadd_h ..... 10 ..... ..... ... ..... 1000011 @r4_rm
- +fmsub_h ..... 10 ..... ..... ... ..... 1000111 @r4_rm
- +fnmsub_h ..... 10 ..... ..... ... ..... 1001011 @r4_rm
- +fnmadd_h ..... 10 ..... ..... ... ..... 1001111 @r4_rm
- +fadd_h 0000010 ..... ..... ... ..... 1010011 @r_rm
- +fsub_h 0000110 ..... ..... ... ..... 1010011 @r_rm
- +fmul_h 0001010 ..... ..... ... ..... 1010011 @r_rm
- +fdiv_h 0001110 ..... ..... ... ..... 1010011 @r_rm
- +fsqrt_h 0101110 00000 ..... ... ..... 1010011 @r2_rm
- +fsgnj_h 0010010 ..... ..... 000 ..... 1010011 @r
- +fsgnjn_h 0010010 ..... ..... 001 ..... 1010011 @r
- +fsgnjx_h 0010010 ..... ..... 010 ..... 1010011 @r
- +fmin_h 0010110 ..... ..... 000 ..... 1010011 @r
- +fmax_h 0010110 ..... ..... 001 ..... 1010011 @r
- +fcvt_h_s 0100010 00000 ..... ... ..... 1010011 @r2_rm
- +fcvt_s_h 0100000 00010 ..... ... ..... 1010011 @r2_rm
- +fcvt_h_d 0100010 00001 ..... ... ..... 1010011 @r2_rm
- +fcvt_d_h 0100001 00010 ..... ... ..... 1010011 @r2_rm
- +fcvt_w_h 1100010 00000 ..... ... ..... 1010011 @r2_rm
- +fcvt_wu_h 1100010 00001 ..... ... ..... 1010011 @r2_rm
- +fmv_x_h 1110010 00000 ..... 000 ..... 1010011 @r2
- +feq_h 1010010 ..... ..... 010 ..... 1010011 @r
- +flt_h 1010010 ..... ..... 001 ..... 1010011 @r
- +fle_h 1010010 ..... ..... 000 ..... 1010011 @r
- +fclass_h 1110010 00000 ..... 001 ..... 1010011 @r2
- +fcvt_h_w 1101010 00000 ..... ... ..... 1010011 @r2_rm
- +fcvt_h_wu 1101010 00001 ..... ... ..... 1010011 @r2_rm
- +fmv_h_x 1111010 00000 ..... 000 ..... 1010011 @r2
- diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc b/target/riscv/insn_trans/trans_rvzfh.c.inc
- new file mode 100644
- index 0000000000..4c483f6372
- --- /dev/null
- +++ b/target/riscv/insn_trans/trans_rvzfh.c.inc
- @@ -0,0 +1,535 @@
- +/*
- + * RISC-V translation routines for the RV64Zfh Standard Extension.
- + *
- + * Copyright (c) 2020 Chih-Min Chao, chihmin.chao@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/>.
- + */
- +
- +#define REQUIRE_ZFH(ctx) do { \
- + return ctx->ext_zfh; \
- +} while (0)
- +
- +static bool trans_flh(DisasContext *ctx, arg_flh *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_get_gpr(t0, a->rs1);
- +
- + tcg_gen_addi_tl(t0, t0, a->imm);
- +
- + tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEUW);
- +
- + gen_nanbox_h(cpu_fpr[a->rd], cpu_fpr[a->rd]);
- +
- + mark_fs_dirty(ctx);
- + tcg_temp_free(t0);
- + return true;
- +}
- +
- +static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_get_gpr(t0, a->rs1);
- + tcg_gen_addi_tl(t0, t0, a->imm);
- +
- + tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUW);
- +
- + mark_fs_dirty(ctx);
- + tcg_temp_free(t0);
- + return true;
- +}
- +
- +static bool trans_fmadd_h(DisasContext *ctx, arg_fmadd_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fmadd_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
- + cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fmsub_h(DisasContext *ctx, arg_fmsub_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fmsub_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
- + cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fnmsub_h(DisasContext *ctx, arg_fnmsub_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fnmsub_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
- + cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fnmadd_h(DisasContext *ctx, arg_fnmadd_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fnmadd_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
- + cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fadd_h(DisasContext *ctx, arg_fadd_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fadd_h(cpu_fpr[a->rd], cpu_env,
- + cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fsub_h(DisasContext *ctx, arg_fsub_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fsub_h(cpu_fpr[a->rd], cpu_env,
- + cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fmul_h(DisasContext *ctx, arg_fmul_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fmul_h(cpu_fpr[a->rd], cpu_env,
- + cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fdiv_h(DisasContext *ctx, arg_fdiv_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fdiv_h(cpu_fpr[a->rd], cpu_env,
- + cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fsqrt_h(DisasContext *ctx, arg_fsqrt_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fsqrt_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fsgnj_h(DisasContext *ctx, arg_fsgnj_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + if (a->rs1 == a->rs2) { /* FMOV */
- + gen_check_nanbox_h(cpu_fpr[a->rd], cpu_fpr[a->rs1]);
- + } else {
- + TCGv_i64 rs1 = tcg_temp_new_i64();
- + TCGv_i64 rs2 = tcg_temp_new_i64();
- +
- + gen_check_nanbox_h(rs1, cpu_fpr[a->rs1]);
- + gen_check_nanbox_h(rs2, cpu_fpr[a->rs2]);
- +
- + /* This formulation retains the nanboxing of rs2. */
- + tcg_gen_deposit_i64(cpu_fpr[a->rd], rs2, rs1, 0, 15);
- + tcg_temp_free_i64(rs1);
- + tcg_temp_free_i64(rs2);
- + }
- +
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fsgnjn_h(DisasContext *ctx, arg_fsgnjn_h *a)
- +{
- + TCGv_i64 rs1, rs2, mask;
- +
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + rs1 = tcg_temp_new_i64();
- + gen_check_nanbox_h(rs1, cpu_fpr[a->rs1]);
- +
- + if (a->rs1 == a->rs2) { /* FNEG */
- + tcg_gen_xori_i64(cpu_fpr[a->rd], rs1, MAKE_64BIT_MASK(15, 1));
- + } else {
- + rs2 = tcg_temp_new_i64();
- + gen_check_nanbox_h(rs2, cpu_fpr[a->rs2]);
- +
- + /*
- + * Replace bit 15 in rs1 with inverse in rs2.
- + * This formulation retains the nanboxing of rs1.
- + */
- + mask = tcg_const_i64(~MAKE_64BIT_MASK(15, 1));
- + tcg_gen_not_i64(rs2, rs2);
- + tcg_gen_andc_i64(rs2, rs2, mask);
- + tcg_gen_and_i64(rs1, mask, rs1);
- + tcg_gen_or_i64(cpu_fpr[a->rd], rs1, rs2);
- +
- + tcg_temp_free_i64(mask);
- + tcg_temp_free_i64(rs2);
- + }
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fsgnjx_h(DisasContext *ctx, arg_fsgnjx_h *a)
- +{
- + TCGv_i64 rs1, rs2;
- +
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + rs1 = tcg_temp_new_i64();
- + gen_check_nanbox_s(rs1, cpu_fpr[a->rs1]);
- +
- + if (a->rs1 == a->rs2) { /* FABS */
- + tcg_gen_andi_i64(cpu_fpr[a->rd], rs1, ~MAKE_64BIT_MASK(15, 1));
- + } else {
- + rs2 = tcg_temp_new_i64();
- + gen_check_nanbox_s(rs2, cpu_fpr[a->rs2]);
- +
- + /*
- + * Xor bit 15 in rs1 with that in rs2.
- + * This formulation retains the nanboxing of rs1.
- + */
- + tcg_gen_andi_i64(rs2, rs2, MAKE_64BIT_MASK(15, 1));
- + tcg_gen_xor_i64(cpu_fpr[a->rd], rs1, rs2);
- +
- + tcg_temp_free_i64(rs2);
- + }
- +
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fmin_h(DisasContext *ctx, arg_fmin_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_helper_fmin_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
- + cpu_fpr[a->rs2]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fmax_h(DisasContext *ctx, arg_fmax_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_helper_fmax_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
- + cpu_fpr[a->rs2]);
- + mark_fs_dirty(ctx);
- + return true;
- +}
- +
- +static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_s_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
- +
- + mark_fs_dirty(ctx);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + REQUIRE_EXT(ctx, RVD);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_d_h(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
- +
- + mark_fs_dirty(ctx);
- +
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_h_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
- +
- + mark_fs_dirty(ctx);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_h_d(DisasContext *ctx, arg_fcvt_h_d *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + REQUIRE_EXT(ctx, RVD);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_h_d(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
- +
- + mark_fs_dirty(ctx);
- +
- + return true;
- +}
- +
- +static bool trans_feq_h(DisasContext *ctx, arg_feq_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + TCGv t0 = tcg_temp_new();
- + gen_helper_feq_h(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- + return true;
- +}
- +
- +static bool trans_flt_h(DisasContext *ctx, arg_flt_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + TCGv t0 = tcg_temp_new();
- + gen_helper_flt_h(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- + return true;
- +}
- +
- +static bool trans_fle_h(DisasContext *ctx, arg_fle_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- + TCGv t0 = tcg_temp_new();
- + gen_helper_fle_h(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- + return true;
- +}
- +
- +static bool trans_fclass_h(DisasContext *ctx, arg_fclass_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- +
- + gen_helper_fclass_h(t0, cpu_fpr[a->rs1]);
- +
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_w_h(DisasContext *ctx, arg_fcvt_w_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_w_h(t0, cpu_env, cpu_fpr[a->rs1]);
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_wu_h(DisasContext *ctx, arg_fcvt_wu_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_wu_h(t0, cpu_env, cpu_fpr[a->rs1]);
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_h_w(DisasContext *ctx, arg_fcvt_h_w *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_get_gpr(t0, a->rs1);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_h_w(cpu_fpr[a->rd], cpu_env, t0);
- +
- + mark_fs_dirty(ctx);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_h_wu(DisasContext *ctx, arg_fcvt_h_wu *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_get_gpr(t0, a->rs1);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_h_wu(cpu_fpr[a->rd], cpu_env, t0);
- +
- + mark_fs_dirty(ctx);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- +
- +#if defined(TARGET_RISCV64)
- + tcg_gen_ext16s_tl(t0, cpu_fpr[a->rs1]); // 16 bits->64 bits
- +#else
- + tcg_gen_extrl_i64_i32(t0, cpu_fpr[a->rs1]); //16 bits->32 bits
- + tcg_gen_ext16s_tl(t0, t0);
- +#endif
- +
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fmv_h_x(DisasContext *ctx, arg_fmv_h_x *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_get_gpr(t0, a->rs1);
- +
- + tcg_gen_extu_tl_i64(cpu_fpr[a->rd], t0);
- + gen_nanbox_h(cpu_fpr[a->rd], cpu_fpr[a->rd]);
- +
- + mark_fs_dirty(ctx);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +#ifdef TARGET_RISCV64
- +
- +static bool trans_fcvt_l_h(DisasContext *ctx, arg_fcvt_l_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_l_h(t0, cpu_env, cpu_fpr[a->rs1]);
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_lu_h(DisasContext *ctx, arg_fcvt_lu_h *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_lu_h(t0, cpu_env, cpu_fpr[a->rs1]);
- + gen_set_gpr(a->rd, t0);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_h_l(DisasContext *ctx, arg_fcvt_h_l *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_get_gpr(t0, a->rs1);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_h_l(cpu_fpr[a->rd], cpu_env, t0);
- +
- + mark_fs_dirty(ctx);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +
- +static bool trans_fcvt_h_lu(DisasContext *ctx, arg_fcvt_h_lu *a)
- +{
- + REQUIRE_FPU;
- + REQUIRE_ZFH(ctx);
- +
- + TCGv t0 = tcg_temp_new();
- + gen_get_gpr(t0, a->rs1);
- +
- + gen_set_rm(ctx, a->rm);
- + gen_helper_fcvt_h_lu(cpu_fpr[a->rd], cpu_env, t0);
- +
- + mark_fs_dirty(ctx);
- + tcg_temp_free(t0);
- +
- + return true;
- +}
- +#endif
- diff --git a/target/riscv/internals.h b/target/riscv/internals.h
- index b15ad394bb..bce91da11a 100644
- --- a/target/riscv/internals.h
- +++ b/target/riscv/internals.h
- @@ -58,4 +58,20 @@ static inline float32 check_nanbox_s(uint64_t f)
- }
- }
-
- +static inline uint64_t nanbox_h(float16 f)
- +{
- + return f | MAKE_64BIT_MASK(16, 48);
- +}
- +
- +static inline float16 check_nanbox_h(uint64_t f)
- +{
- + uint64_t mask = MAKE_64BIT_MASK(16, 48);
- +
- + if (likely((f & mask) == mask)) {
- + return (uint16_t)f;
- + } else {
- + return 0x7E00u; /* default qnan */
- + }
- +}
- +
- #endif
- diff --git a/target/riscv/translate.c b/target/riscv/translate.c
- index 2f9f5ccc62..045475a63b 100644
- --- a/target/riscv/translate.c
- +++ b/target/riscv/translate.c
- @@ -56,6 +56,7 @@ typedef struct DisasContext {
- to reset this known value. */
- int frm;
- bool ext_ifencei;
- + bool ext_zfh;
- bool hlsx;
- /* vector extension */
- bool vill;
- @@ -89,6 +90,11 @@ static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
- tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
- }
-
- +static void gen_nanbox_h(TCGv_i64 out, TCGv_i64 in)
- +{
- + tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(16, 48));
- +}
- +
- /*
- * A narrow n-bit operation, where n < FLEN, checks that input operands
- * are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1.
- @@ -97,6 +103,16 @@ static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
- *
- * Here, the result is always nan-boxed, even the canonical nan.
- */
- +static void gen_check_nanbox_h(TCGv_i64 out, TCGv_i64 in)
- +{
- + TCGv_i64 t_max = tcg_const_i64(0xffffffffffff0000ull);
- + TCGv_i64 t_nan = tcg_const_i64(0xffffffffffff7e00ull);
- +
- + tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
- + tcg_temp_free_i64(t_max);
- + tcg_temp_free_i64(t_nan);
- +}
- +
- static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
- {
- TCGv_i64 t_max = tcg_const_i64(0xffffffff00000000ull);
- @@ -589,6 +605,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
- #include "insn_trans/trans_rvd.c.inc"
- #include "insn_trans/trans_rvh.c.inc"
- #include "insn_trans/trans_rvv.c.inc"
- +#include "insn_trans/trans_rvzfh.c.inc"
- #include "insn_trans/trans_privileged.c.inc"
-
- /* Include the auto-generated decoder for 16 bit insn */
- @@ -640,6 +657,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
- ctx->misa = env->misa;
- ctx->frm = -1; /* unknown rounding mode */
- ctx->ext_ifencei = cpu->cfg.ext_ifencei;
- + ctx->ext_zfh = cpu->cfg.ext_zfh;
- ctx->vlen = cpu->cfg.vlen;
- ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
- ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
- --
- 2.33.1
|