Hexagon (target/hexagon) add A4_addp_c/A4_subp_c
Rdd32 = add(Rss32, Rtt32, Px4):carry Add with carry Rdd32 = sub(Rss32, Rtt32, Px4):carry Sub with carry Test cases in tests/tcg/hexagon/multi_result.c Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <1617930474-31979-22-git-send-email-tsimpson@quicinc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
0a65d28693
commit
57d352ac29
@ -237,6 +237,43 @@
|
||||
tcg_temp_free_i64(tmp); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Add or subtract with carry.
|
||||
* Predicate register is used as an extra input and output.
|
||||
* r5:4 = add(r1:0, r3:2, p1):carry
|
||||
*/
|
||||
#define fGEN_TCG_A4_addp_c(SHORTCODE) \
|
||||
do { \
|
||||
TCGv_i64 carry = tcg_temp_new_i64(); \
|
||||
TCGv_i64 zero = tcg_const_i64(0); \
|
||||
tcg_gen_extu_i32_i64(carry, PxV); \
|
||||
tcg_gen_andi_i64(carry, carry, 1); \
|
||||
tcg_gen_add2_i64(RddV, carry, RssV, zero, carry, zero); \
|
||||
tcg_gen_add2_i64(RddV, carry, RddV, carry, RttV, zero); \
|
||||
tcg_gen_extrl_i64_i32(PxV, carry); \
|
||||
gen_8bitsof(PxV, PxV); \
|
||||
tcg_temp_free_i64(carry); \
|
||||
tcg_temp_free_i64(zero); \
|
||||
} while (0)
|
||||
|
||||
/* r5:4 = sub(r1:0, r3:2, p1):carry */
|
||||
#define fGEN_TCG_A4_subp_c(SHORTCODE) \
|
||||
do { \
|
||||
TCGv_i64 carry = tcg_temp_new_i64(); \
|
||||
TCGv_i64 zero = tcg_const_i64(0); \
|
||||
TCGv_i64 not_RttV = tcg_temp_new_i64(); \
|
||||
tcg_gen_extu_i32_i64(carry, PxV); \
|
||||
tcg_gen_andi_i64(carry, carry, 1); \
|
||||
tcg_gen_not_i64(not_RttV, RttV); \
|
||||
tcg_gen_add2_i64(RddV, carry, RssV, zero, carry, zero); \
|
||||
tcg_gen_add2_i64(RddV, carry, RddV, carry, not_RttV, zero); \
|
||||
tcg_gen_extrl_i64_i32(PxV, carry); \
|
||||
gen_8bitsof(PxV, PxV); \
|
||||
tcg_temp_free_i64(carry); \
|
||||
tcg_temp_free_i64(zero); \
|
||||
tcg_temp_free_i64(not_RttV); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Compare each of the 8 unsigned bytes
|
||||
* The minimum is placed in each byte of the destination.
|
||||
|
@ -361,5 +361,16 @@ static inline void gen_store_conditional8(CPUHexagonState *env,
|
||||
tcg_gen_movi_tl(hex_llsc_addr, ~0);
|
||||
}
|
||||
|
||||
static TCGv gen_8bitsof(TCGv result, TCGv value)
|
||||
{
|
||||
TCGv zero = tcg_const_tl(0);
|
||||
TCGv ones = tcg_const_tl(0xff);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, result, value, zero, ones, zero);
|
||||
tcg_temp_free(zero);
|
||||
tcg_temp_free(ones);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#include "tcg_funcs_generated.c.inc"
|
||||
#include "tcg_func_table_generated.c.inc"
|
||||
|
@ -153,6 +153,21 @@ Q6INSN(A2_subp,"Rdd32=sub(Rtt32,Rss32)",ATTRIBS(),
|
||||
"Sub",
|
||||
{ RddV=RttV-RssV;})
|
||||
|
||||
/* 64-bit with carry */
|
||||
|
||||
Q6INSN(A4_addp_c,"Rdd32=add(Rss32,Rtt32,Px4):carry",ATTRIBS(),"Add with Carry",
|
||||
{
|
||||
RddV = RssV + RttV + fLSBOLD(PxV);
|
||||
PxV = f8BITSOF(fCARRY_FROM_ADD(RssV,RttV,fLSBOLD(PxV)));
|
||||
})
|
||||
|
||||
Q6INSN(A4_subp_c,"Rdd32=sub(Rss32,Rtt32,Px4):carry",ATTRIBS(),"Sub with Carry",
|
||||
{
|
||||
RddV = RssV + ~RttV + fLSBOLD(PxV);
|
||||
PxV = f8BITSOF(fCARRY_FROM_ADD(RssV,~RttV,fLSBOLD(PxV)));
|
||||
})
|
||||
|
||||
|
||||
/* NEG and ABS */
|
||||
|
||||
Q6INSN(A2_negsat,"Rd32=neg(Rs32):sat",ATTRIBS(),
|
||||
|
@ -1749,6 +1749,8 @@ SH_RRR_ENC(S4_extractp_rp, "0001","11-","-","10-","ddddd")
|
||||
DEF_FIELDROW_DESC32(ICLASS_S3op" 0010 -------- PP------ --------","[#2] Rdd=(Rss,Rtt,Pu)")
|
||||
SH_RRR_ENC(S2_valignrb, "0010","0--","-","-uu","ddddd")
|
||||
SH_RRR_ENC(S2_vsplicerb, "0010","100","-","-uu","ddddd")
|
||||
SH_RRR_ENC(A4_addp_c, "0010","110","-","-xx","ddddd")
|
||||
SH_RRR_ENC(A4_subp_c, "0010","111","-","-xx","ddddd")
|
||||
|
||||
|
||||
DEF_FIELDROW_DESC32(ICLASS_S3op" 0011 -------- PP------ --------","[#3] Rdd=(Rss,Rt)")
|
||||
|
@ -85,6 +85,38 @@ static long long vminub(long long Rtt, long long Rss,
|
||||
return result;
|
||||
}
|
||||
|
||||
static long long add_carry(long long Rss, long long Rtt,
|
||||
int pred_in, int *pred_result)
|
||||
{
|
||||
long long result;
|
||||
int predval = pred_in;
|
||||
|
||||
asm volatile("p0 = %1\n\t"
|
||||
"%0 = add(%2, %3, p0):carry\n\t"
|
||||
"%1 = p0\n\t"
|
||||
: "=r"(result), "+r"(predval)
|
||||
: "r"(Rss), "r"(Rtt)
|
||||
: "p0");
|
||||
*pred_result = predval;
|
||||
return result;
|
||||
}
|
||||
|
||||
static long long sub_carry(long long Rss, long long Rtt,
|
||||
int pred_in, int *pred_result)
|
||||
{
|
||||
long long result;
|
||||
int predval = pred_in;
|
||||
|
||||
asm volatile("p0 = !cmp.eq(%1, #0)\n\t"
|
||||
"%0 = sub(%2, %3, p0):carry\n\t"
|
||||
"%1 = p0\n\t"
|
||||
: "=r"(result), "+r"(predval)
|
||||
: "r"(Rss), "r"(Rtt)
|
||||
: "p0");
|
||||
*pred_result = predval;
|
||||
return result;
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
static void check_ll(long long val, long long expect)
|
||||
@ -188,12 +220,62 @@ static void test_vminub()
|
||||
check_p(pred_result, 0xaa);
|
||||
}
|
||||
|
||||
static void test_add_carry()
|
||||
{
|
||||
long long res64;
|
||||
int pred_result;
|
||||
|
||||
res64 = add_carry(0x0000000000000000LL,
|
||||
0xffffffffffffffffLL,
|
||||
1, &pred_result);
|
||||
check_ll(res64, 0x0000000000000000LL);
|
||||
check_p(pred_result, 0xff);
|
||||
|
||||
res64 = add_carry(0x0000000100000000LL,
|
||||
0xffffffffffffffffLL,
|
||||
0, &pred_result);
|
||||
check_ll(res64, 0x00000000ffffffffLL);
|
||||
check_p(pred_result, 0xff);
|
||||
|
||||
res64 = add_carry(0x0000000100000000LL,
|
||||
0xffffffffffffffffLL,
|
||||
0, &pred_result);
|
||||
check_ll(res64, 0x00000000ffffffffLL);
|
||||
check_p(pred_result, 0xff);
|
||||
}
|
||||
|
||||
static void test_sub_carry()
|
||||
{
|
||||
long long res64;
|
||||
int pred_result;
|
||||
|
||||
res64 = sub_carry(0x0000000000000000LL,
|
||||
0x0000000000000000LL,
|
||||
1, &pred_result);
|
||||
check_ll(res64, 0x0000000000000000LL);
|
||||
check_p(pred_result, 0xff);
|
||||
|
||||
res64 = sub_carry(0x0000000100000000LL,
|
||||
0x0000000000000000LL,
|
||||
0, &pred_result);
|
||||
check_ll(res64, 0x00000000ffffffffLL);
|
||||
check_p(pred_result, 0xff);
|
||||
|
||||
res64 = sub_carry(0x0000000100000000LL,
|
||||
0x0000000000000000LL,
|
||||
0, &pred_result);
|
||||
check_ll(res64, 0x00000000ffffffffLL);
|
||||
check_p(pred_result, 0xff);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_sfrecipa();
|
||||
test_sfinvsqrta();
|
||||
test_vacsh();
|
||||
test_vminub();
|
||||
test_add_carry();
|
||||
test_sub_carry();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
|
Loading…
Reference in New Issue
Block a user