qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v6 18/61] target/riscv: vector single-width integer multiply


From: LIU Zhiwei
Subject: Re: [PATCH v6 18/61] target/riscv: vector single-width integer multiply instructions
Date: Sun, 29 Mar 2020 12:00:37 +0800
User-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.6.0



On 2020/3/29 0:13, LIU Zhiwei wrote:


On 2020/3/28 23:47, Richard Henderson wrote:
On 3/28/20 8:17 AM, LIU Zhiwei wrote:
Missed the improvement here.  See tcg_gen_mulsu2_i64.
Though I have not gotten the principle, the code in tcg_gen_mulsu2_i64 is much
tidier.
Let A = signed operand,
     B = unsigned operand
     P = unsigned product

If the sign bit A is set, then P is too large.
In that case we subtract 2**64 * B to fix that:

     HI_P -= (A < 0 ? B : 0)

where the conditional is computed as (A >> 63) & B.

I think I get it.

LET  A = 2 ** 64  - X

THEN

X = 2 ** 64 - A
SIGNED_P = -X * B

if (A * B == P) then

(2 ** 64  - X) * B == P
2 **64 * B - X * B == P

-X *B == P - 2**64*B

HI_P -= (A < 0 ? B :0)

It's confusing here. I paste the clearer code.
/*
 * Let  A = signed operand,
 *      B = unsigned operand
 *      P = mulu64(A, B), unsigned product
 *
 * LET  X = 2 ** 64  - A, 2's complement of A
 *      SP = signed product
 * THEN
 *      IF A < 0
 *          SP = -X * B
 *             = -(2 ** 64 - A) * B
 *             = A * B - 2 ** 64 * B
 *             = P - 2 ** 64 * B
 *      ELSE
 *          SP = P
 * THEN
 *      HI_P -= (A < 0 ? B : 0)
 */

static int64_t do_mulhsu_d(int64_t s2, uint64_t s1)
{
    uint64_t hi_64, lo_64;

    mulu64(&lo_64, &hi_64, s2, s1);

    hi_64 -= s2 < 0 ? s1 : 0;
    return hi_64;
}

Zhiwei
Zhiwei

r~



reply via email to

[Prev in Thread] Current Thread [Next in Thread]