diff options
author | Taylor Simpson <tsimpson@quicinc.com> | 2022-11-08 08:28:58 -0800 |
---|---|---|
committer | Taylor Simpson <tsimpson@quicinc.com> | 2022-12-16 10:10:28 -0800 |
commit | 8e8a85c14eed845346f64431da6417869f88c470 (patch) | |
tree | 6cc155a9eb9d0dd6a36e733c9cdf07d02daf0599 /target | |
parent | 83853ea0efee80f8c39a73753a048a769a02a2c7 (diff) | |
download | qemu-8e8a85c14eed845346f64431da6417869f88c470.zip qemu-8e8a85c14eed845346f64431da6417869f88c470.tar.gz qemu-8e8a85c14eed845346f64431da6417869f88c470.tar.bz2 |
Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
These instructions will not be generated by idef-parser, so we override
them manually.
Test cases added to tests/tcg/hexagon/usr.c
Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20221108162906.3166-4-tsimpson@quicinc.com>
Diffstat (limited to 'target')
-rw-r--r-- | target/hexagon/gen_tcg.h | 10 | ||||
-rw-r--r-- | target/hexagon/genptr.c | 104 |
2 files changed, 113 insertions, 1 deletions
diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h index 50634ac..b5fe22a 100644 --- a/target/hexagon/gen_tcg.h +++ b/target/hexagon/gen_tcg.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -612,6 +612,14 @@ tcg_temp_free(tmp); \ } while (0) +/* r0 = asr(r1, r2):sat */ +#define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \ + gen_asr_r_r_sat(RdV, RsV, RtV) + +/* r0 = asl(r1, r2):sat */ +#define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \ + gen_asl_r_r_sat(RdV, RsV, RtV) + /* Floating point */ #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \ gen_helper_conv_sf2df(RddV, cpu_env, RsV) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 85416dd..cd3d745 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -456,6 +456,110 @@ static TCGv gen_8bitsof(TCGv result, TCGv value) return result; } +/* Shift left with saturation */ +static void gen_shl_sat(TCGv dst, TCGv src, TCGv shift_amt) +{ + TCGv sh32 = tcg_temp_new(); + TCGv dst_sar = tcg_temp_new(); + TCGv ovf = tcg_temp_new(); + TCGv satval = tcg_temp_new(); + TCGv min = tcg_constant_tl(0x80000000); + TCGv max = tcg_constant_tl(0x7fffffff); + + /* + * Possible values for shift_amt are 0 .. 64 + * We need special handling for values above 31 + * + * sh32 = shift & 31; + * dst = sh32 == shift ? src : 0; + * dst <<= sh32; + * dst_sar = dst >> sh32; + * satval = src < 0 ? min : max; + * if (dst_asr != src) { + * usr.OVF |= 1; + * dst = satval; + * } + */ + + tcg_gen_andi_tl(sh32, shift_amt, 31); + tcg_gen_movcond_tl(TCG_COND_EQ, dst, sh32, shift_amt, + src, tcg_constant_tl(0)); + tcg_gen_shl_tl(dst, dst, sh32); + tcg_gen_sar_tl(dst_sar, dst, sh32); + tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max); + + tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src); + tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset); + tcg_gen_or_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR], ovf); + + tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, dst, satval); + + tcg_temp_free(sh32); + tcg_temp_free(dst_sar); + tcg_temp_free(ovf); + tcg_temp_free(satval); +} + +static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt) +{ + /* + * Shift arithmetic right + * Robust when shift_amt is >31 bits + */ + TCGv tmp = tcg_temp_new(); + tcg_gen_umin_tl(tmp, shift_amt, tcg_constant_tl(31)); + tcg_gen_sar_tl(dst, src, tmp); + tcg_temp_free(tmp); +} + +/* Bidirectional shift right with saturation */ +static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV) +{ + TCGv shift_amt = tcg_temp_local_new(); + TCGLabel *positive = gen_new_label(); + TCGLabel *done = gen_new_label(); + + tcg_gen_sextract_i32(shift_amt, RtV, 0, 7); + tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive); + + /* Negative shift amount => shift left */ + tcg_gen_neg_tl(shift_amt, shift_amt); + gen_shl_sat(RdV, RsV, shift_amt); + tcg_gen_br(done); + + gen_set_label(positive); + /* Positive shift amount => shift right */ + gen_sar(RdV, RsV, shift_amt); + + gen_set_label(done); + + tcg_temp_free(shift_amt); +} + +/* Bidirectional shift left with saturation */ +static void gen_asl_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV) +{ + TCGv shift_amt = tcg_temp_local_new(); + TCGLabel *positive = gen_new_label(); + TCGLabel *done = gen_new_label(); + + tcg_gen_sextract_i32(shift_amt, RtV, 0, 7); + tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive); + + /* Negative shift amount => shift right */ + tcg_gen_neg_tl(shift_amt, shift_amt); + gen_sar(RdV, RsV, shift_amt); + tcg_gen_br(done); + + gen_set_label(positive); + /* Positive shift amount => shift left */ + gen_shl_sat(RdV, RsV, shift_amt); + + gen_set_label(done); + + tcg_temp_free(shift_amt); +} + static intptr_t vreg_src_off(DisasContext *ctx, int num) { intptr_t offset = offsetof(CPUHexagonState, VRegs[num]); |