Hexagon (target/hexagon) add F2_sfinvsqrta
Rd32,Pe4 = sfinvsqrta(Rs32) Square root approx The helper packs the 2 32-bit results into a 64-bit value, and the fGEN_TCG override unpacks them into the proper results. Test cases in tests/tcg/hexagon/multi_result.c FP exception tests added to tests/tcg/hexagon/fpstuff.c Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <1617930474-31979-19-git-send-email-tsimpson@quicinc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
d934c16d8a
commit
dd8705bdf5
@ -247,7 +247,7 @@ int arch_sf_invsqrt_common(float32 *Rs, float32 *Rd, int *adjust,
|
||||
int r_exp;
|
||||
int ret = 0;
|
||||
RsV = *Rs;
|
||||
if (float32_is_infinity(RsV)) {
|
||||
if (float32_is_any_nan(RsV)) {
|
||||
if (extract32(RsV, 22, 1) == 0) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
@ -299,3 +299,22 @@ const uint8_t recip_lookup_table[128] = {
|
||||
0x011, 0x00f, 0x00e, 0x00d, 0x00c, 0x00b, 0x00a, 0x009,
|
||||
0x008, 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x000,
|
||||
};
|
||||
|
||||
const uint8_t invsqrt_lookup_table[128] = {
|
||||
0x069, 0x066, 0x063, 0x061, 0x05e, 0x05b, 0x059, 0x057,
|
||||
0x054, 0x052, 0x050, 0x04d, 0x04b, 0x049, 0x047, 0x045,
|
||||
0x043, 0x041, 0x03f, 0x03d, 0x03b, 0x039, 0x037, 0x036,
|
||||
0x034, 0x032, 0x030, 0x02f, 0x02d, 0x02c, 0x02a, 0x028,
|
||||
0x027, 0x025, 0x024, 0x022, 0x021, 0x01f, 0x01e, 0x01d,
|
||||
0x01b, 0x01a, 0x019, 0x017, 0x016, 0x015, 0x014, 0x012,
|
||||
0x011, 0x010, 0x00f, 0x00d, 0x00c, 0x00b, 0x00a, 0x009,
|
||||
0x008, 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001,
|
||||
0x0fe, 0x0fa, 0x0f6, 0x0f3, 0x0ef, 0x0eb, 0x0e8, 0x0e4,
|
||||
0x0e1, 0x0de, 0x0db, 0x0d7, 0x0d4, 0x0d1, 0x0ce, 0x0cb,
|
||||
0x0c9, 0x0c6, 0x0c3, 0x0c0, 0x0be, 0x0bb, 0x0b8, 0x0b6,
|
||||
0x0b3, 0x0b1, 0x0af, 0x0ac, 0x0aa, 0x0a8, 0x0a5, 0x0a3,
|
||||
0x0a1, 0x09f, 0x09d, 0x09b, 0x099, 0x097, 0x095, 0x093,
|
||||
0x091, 0x08f, 0x08d, 0x08b, 0x089, 0x087, 0x086, 0x084,
|
||||
0x082, 0x080, 0x07f, 0x07d, 0x07b, 0x07a, 0x078, 0x077,
|
||||
0x075, 0x074, 0x072, 0x071, 0x06f, 0x06e, 0x06c, 0x06b,
|
||||
};
|
||||
|
@ -32,4 +32,6 @@ int arch_sf_invsqrt_common(float32 *Rs, float32 *Rd, int *adjust,
|
||||
|
||||
extern const uint8_t recip_lookup_table[128];
|
||||
|
||||
extern const uint8_t invsqrt_lookup_table[128];
|
||||
|
||||
#endif
|
||||
|
@ -216,6 +216,22 @@
|
||||
tcg_temp_free_i64(tmp); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Approximation of the reciprocal square root
|
||||
* r1,p0 = sfinvsqrta(r0)
|
||||
*
|
||||
* The helper packs the 2 32-bit results into a 64-bit value,
|
||||
* so unpack them into the proper results.
|
||||
*/
|
||||
#define fGEN_TCG_F2_sfinvsqrta(SHORTCODE) \
|
||||
do { \
|
||||
TCGv_i64 tmp = tcg_temp_new_i64(); \
|
||||
gen_helper_sfinvsqrta(tmp, cpu_env, RsV); \
|
||||
tcg_gen_extrh_i64_i32(RdV, tmp); \
|
||||
tcg_gen_extrl_i64_i32(PeV, tmp); \
|
||||
tcg_temp_free_i64(tmp); \
|
||||
} while (0)
|
||||
|
||||
/* Floating point */
|
||||
#define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
|
||||
gen_helper_conv_sf2df(RddV, cpu_env, RsV)
|
||||
|
@ -25,6 +25,7 @@ DEF_HELPER_FLAGS_3(debug_commit_end, TCG_CALL_NO_WG, void, env, int, int)
|
||||
DEF_HELPER_2(commit_store, void, env, int)
|
||||
DEF_HELPER_FLAGS_4(fcircadd, TCG_CALL_NO_RWG_SE, s32, s32, s32, s32, s32)
|
||||
DEF_HELPER_3(sfrecipa, i64, env, f32, f32)
|
||||
DEF_HELPER_2(sfinvsqrta, i64, env, f32)
|
||||
|
||||
/* Floating point */
|
||||
DEF_HELPER_2(conv_sf2df, f64, env, f32)
|
||||
|
@ -1642,6 +1642,7 @@ SH2_RR_ENC(F2_conv_sf2w, "1011","100","-","000","ddddd")
|
||||
SH2_RR_ENC(F2_conv_sf2uw_chop, "1011","011","-","001","ddddd")
|
||||
SH2_RR_ENC(F2_conv_sf2w_chop, "1011","100","-","001","ddddd")
|
||||
SH2_RR_ENC(F2_sffixupr, "1011","101","-","000","ddddd")
|
||||
SH2_RR_ENC(F2_sfinvsqrta, "1011","111","-","0ee","ddddd")
|
||||
|
||||
|
||||
DEF_FIELDROW_DESC32(ICLASS_S2op" 1100 -------- PP------ --------","[#12] Rd=(Rs,#u6)")
|
||||
|
@ -178,6 +178,22 @@ Q6INSN(F2_sffixupd,"Rd32=sffixupd(Rs32,Rt32)",ATTRIBS(),
|
||||
RdV = RtV;
|
||||
})
|
||||
|
||||
Q6INSN(F2_sfinvsqrta,"Rd32,Pe4=sfinvsqrta(Rs32)",ATTRIBS(),
|
||||
"Reciprocal Square Root Approximation",
|
||||
{
|
||||
fHIDE(int idx;)
|
||||
fHIDE(int adjust;)
|
||||
fHIDE(int mant;)
|
||||
fHIDE(int exp;)
|
||||
if (fSF_INVSQRT_COMMON(RsV,RdV,adjust)) {
|
||||
PeV = adjust;
|
||||
idx = (RsV >> 17) & 0x7f;
|
||||
mant = (fSF_INVSQRT_LOOKUP(idx) << 15);
|
||||
exp = fSF_BIAS() - ((fSF_GETEXP(RsV) - fSF_BIAS()) >> 1) - 1;
|
||||
RdV = fMAKESF(fGETBIT(31,RsV),exp,mant);
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(F2_sffixupr,"Rd32=sffixupr(Rs32)",ATTRIBS(),
|
||||
"Fix Up Radicand",
|
||||
{
|
||||
|
@ -326,6 +326,27 @@ uint64_t HELPER(sfrecipa)(CPUHexagonState *env, float32 RsV, float32 RtV)
|
||||
return ((uint64_t)RdV << 32) | PeV;
|
||||
}
|
||||
|
||||
uint64_t HELPER(sfinvsqrta)(CPUHexagonState *env, float32 RsV)
|
||||
{
|
||||
int PeV = 0;
|
||||
float32 RdV;
|
||||
int idx;
|
||||
int adjust;
|
||||
int mant;
|
||||
int exp;
|
||||
|
||||
arch_fpop_start(env);
|
||||
if (arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status)) {
|
||||
PeV = adjust;
|
||||
idx = (RsV >> 17) & 0x7f;
|
||||
mant = (invsqrt_lookup_table[idx] << 15);
|
||||
exp = SF_BIAS - ((float32_getexp(RsV) - SF_BIAS) >> 1) - 1;
|
||||
RdV = build_float32(extract32(RsV, 31, 1), exp, mant);
|
||||
}
|
||||
arch_fpop_end(env);
|
||||
return ((uint64_t)RdV << 32) | PeV;
|
||||
}
|
||||
|
||||
/*
|
||||
* mem_noshuf
|
||||
* Section 5.5 of the Hexagon V67 Programmer's Reference Manual
|
||||
|
@ -441,6 +441,20 @@ static void check_canonical_NaN(void)
|
||||
check_fpstatus(usr, 0);
|
||||
}
|
||||
|
||||
static void check_invsqrta(void)
|
||||
{
|
||||
int result;
|
||||
int predval;
|
||||
|
||||
asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
|
||||
"%1 = p0\n\t"
|
||||
: "+r"(result), "=r"(predval)
|
||||
: "r"(0x7f800000)
|
||||
: "p0");
|
||||
check32(result, 0xff800000);
|
||||
check32(predval, 0x0);
|
||||
}
|
||||
|
||||
static void check_float2int_convs()
|
||||
{
|
||||
int res32;
|
||||
@ -590,6 +604,7 @@ int main()
|
||||
check_dfminmax();
|
||||
check_recip_exception();
|
||||
check_canonical_NaN();
|
||||
check_invsqrta();
|
||||
check_float2int_convs();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
|
@ -31,6 +31,20 @@ static int sfrecipa(int Rs, int Rt, int *pred_result)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sfinvsqrta(int Rs, int *pred_result)
|
||||
{
|
||||
int result;
|
||||
int predval;
|
||||
|
||||
asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
|
||||
"%1 = p0\n\t"
|
||||
: "+r"(result), "=r"(predval)
|
||||
: "r"(Rs)
|
||||
: "p0");
|
||||
*pred_result = predval;
|
||||
return result;
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
static void check(int val, int expect)
|
||||
@ -59,9 +73,24 @@ static void test_sfrecipa()
|
||||
check_p(pred_result, 0x00);
|
||||
}
|
||||
|
||||
static void test_sfinvsqrta()
|
||||
{
|
||||
int res;
|
||||
int pred_result;
|
||||
|
||||
res = sfinvsqrta(0x04030201, &pred_result);
|
||||
check(res, 0x4d330000);
|
||||
check_p(pred_result, 0xe0);
|
||||
|
||||
res = sfinvsqrta(0x0, &pred_result);
|
||||
check(res, 0x3f800000);
|
||||
check_p(pred_result, 0x0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_sfrecipa();
|
||||
test_sfinvsqrta();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
|
Loading…
Reference in New Issue
Block a user