All of lore.kernel.org
 help / color / mirror / Atom feed
From: Aurelien Jarno <aurelien@aurel32.net>
To: Jia Liu <proljc@gmail.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v11 01/14] target-mips: Add ASE DSP internal functions
Date: Thu, 18 Oct 2012 13:18:15 +0200	[thread overview]
Message-ID: <20121018111815.GA32459@ohm.aurel32.net> (raw)
In-Reply-To: <20121018060559.GA26903@ohm.aurel32.net>

On Thu, Oct 18, 2012 at 08:05:59AM +0200, Aurelien Jarno wrote:
> On Thu, Oct 18, 2012 at 09:53:20AM +0800, Jia Liu wrote:
> > Hi Aurelien,
> > 
> > On Wed, Oct 17, 2012 at 11:15 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > > On Wed, Oct 17, 2012 at 11:39:00AM +0800, Jia Liu wrote:
> > >> Hi Aurelien,
> > >>
> > >> On Wed, Oct 17, 2012 at 7:20 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > >> > On Tue, Oct 16, 2012 at 12:39:05AM +0800, Jia Liu wrote:
> > >> >> +/* a[0] is LO, a[1] is HI. */
> > >> >> +static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
> > >> >> +                                             int32_t ac,
> > >> >> +                                             int64_t *a,
> > >> >> +                                             CPUMIPSState *env)
> > >> >> +{
> > >> >> +    uint32_t temp64, temp63;
> > >> >> +    int64_t temp[2];
> > >> >> +    int64_t acc[2];
> > >> >> +    int64_t temp_sum;
> > >> >> +
> > >> >> +    temp[0] = a[0];
> > >> >> +    temp[1] = a[1];
> > >> >> +
> > >> >> +    acc[0] = env->active_tc.LO[ac];
> > >> >> +    acc[1] = env->active_tc.HI[ac];
> > >> >> +
> > >> >> +    temp_sum = acc[0] - temp[0];
> > >> >> +    if (MIPSDSP_OVERFLOW(acc[0], -temp[0], temp_sum, 0x8000000000000000ull)) {
> > >> >> +        acc[1] -= 1;
> > >> >> +    }
> > >> >> +    acc[0] = temp_sum;
> > >> >> +
> > >> >> +    temp_sum = acc[1] - temp[1];
> > >> >> +    acc[1] = temp_sum;
> > >> >> +
> > >> >> +    temp64 = acc[1] & 0x01;
> > >> >> +    temp63 = (acc[0] >> 63) & 0x01;
> > >> >> +
> > >> >> +    /* MIPSDSP_OVERFLOW only can check if a 64 bits sub is overflow,
> > >> >> +     * there are two 128 bits value subed then check the 63/64 bits are equal
> > >> >> +     * or not.*/
> > >> >
> > >> > If you disagree with what I say, you can send mail, there is no need to
> > >> > put it as a comment.
> > >> >
> > >> > That said MIPSDSP_OVERFLOW doesn't work only on 64-bit values, it can
> > >> > work other size, as it is done elsewhere in this patch. The only thing
> > >> > it checked is the highest bit of the two arguments and the result.
> > >> > Therefore if you pass the highest part of the values, it can work.
> > >> >
> > >>
> > >> I did agree with you, just didn't totally get your point.
> > >>
> > >> MIPSDSP_OVERFLOW used to check overflow, but here, 128bit + 128bit,
> > >> low 64bit overflow need to be checked, so, in fact, I'm not sure what
> > >> should do. Is this code right?
> > >>
> > >> static inline void mipsdsp_sat64_acc_sub_q63(uint64_t *ret,
> > >>                                              int32_t ac,
> > >>                                              uint64_t *a,
> > >>                                              CPUMIPSState *env)
> > >> {
> > >>     uint32_t temp64;
> > >>     uint64_t temp[2];
> > >>     uint64_t acc[2];
> > >>
> > >>     temp[0] = a[0];
> > >>     temp[1] = a[1];
> > >>
> > >>     acc[0] = env->active_tc.LO[ac];
> > >>     acc[1] = env->active_tc.HI[ac];
> > >>
> > >>     temp[1] = acc[1] - temp[1];
> > >>     temp[0] = acc[0] - temp[0];
> > >>
> > >>     temp64 = temp[1] & 0x01;
> > >>
> > >>     if (temp64 ^ MIPSDSP_OVERFLOW(acc[0], temp[0], temp[0], (0x01ull << 63))) {
> > >>         if (temp64 == 1) {
> > >>             ret[0] = (0x01ull << 63);
> > >>             ret[1] = ~0ull;
> > >>         } else {
> > >>             ret[0] = (0x01ull << 63) - 1;
> > >>             ret[1] = 0x00;
> > >>         }
> > >>         set_DSPControl_overflow_flag(1, 16 + ac, env);
> > >>     } else {
> > >>         ret[0] = temp[0];
> > >>         ret[1] = acc[0] > temp[0] ? temp[1] : temp[1] - 1;
> > >>     }
> > >> }
> > >>
> > >
> > > I don't think xoring temp64 with MIPSDSP_OVERFLOW is correct. What about
> > > about something like that (untested):
> > >
> > > | static inline void mipsdsp_sat64_acc_sub_q63(uint64_t *ret,
> > > |                                              int32_t ac,
> > > |                                              uint64_t *a,
> > > |                                              CPUMIPSState *env)
> > > | {
> > > |     ret[0] = env->active_tc.LO[ac] - a[0];
> > > |     ret[1] = env->active_tc.HI[ac] - a[1];
> > > |
> > 
> > In the MIPS-DSP manual, the function is
> > 
> > function sat64AccumulateSubQ63( acc1..0, a127..0 )
> >     temp128..0 ← HI[acc]63 || HI[acc]63..0 || LO[acc]63..0
> >     temp128..0 ← temp - a127..0 if ( temp64 ≠ temp63 ) then
> >     if ( temp64 = 1 ) then
> >         temp127..0 ← 0xFFFFFFFFFFFFFFFF8000000000000000
> >     else
> >         temp127..0 ← 0x00000000000000007FFFFFFFFFFFFFFF
> >     endif
> >     DSPControlouflag:16+acc ← 1 endif
> >     return temp127..0
> > endfunction sat64AccumulateSubQ63
> > 
> > > |     if (MIPSDSP_OVERFLOW(env->active_tc.LO[ac], -a[0], ret[0], 0x8000000000000000ull)) {
> > 
> > The bit 64 will influence the overflow of bits 0-63.
> > That is, if bit 64 is 1, and bits 0-63 overflowed, it won't be caught.
> > So, if we use this code, it won't be handled.
> > 
> 
> I think you are correct, we have to take into account the overflow part,
> but also the original value of the temp64 bit.
> 
> > > |         if ((ret[1] - 1) & 1) {
> > > |             ret[0] = (0x01ull << 63);
> > > |             ret[1] = ~0ull;
> > > |         } else {
> > > |             ret[0] = (0x01ull << 63) - 1;
> > > |             ret[1] = 0x00;
> > > |         }
> > > |         set_DSPControl_overflow_flag(1, 16 + ac, env);
> > > |     }
> > > | }
> > > |
> > >
> > > The same applies for the add function, but also to some other places in
> > > the code.
> > >
> > > Also note that you might want to have two version of MIPSDSP_OVERFLOW(),
> > > one for add (like the current one), and one for sub (without the ^ -1),
> > > so that you don't have to pass the negative value of the second
> > > argument.
> > >
> > 
> > I think it is not necessary to define a new macro very much, what do
> > you think about this code? Just little changed.
> > 
> > /* a[0] is LO, a[1] is HI. */
> > static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
> >                                              int32_t ac,
> >                                              int64_t *a,
> >                                              CPUMIPSState *env)
> > {
> >     uint32_t temp64;
> > 
> >     ret[0] = env->active_tc.LO[ac] + a[0];
> >     ret[1] = env->active_tc.HI[ac] + a[1];
> > 
> >     temp64 = ret[1] & 0x01;
> > 
> >     if (temp64 ^ MIPSDSP_OVERFLOW(env->active_tc.LO[ac], a[0], ret[0],
> >                                   (0x01ull << 63))) {
> >         if (temp64 == 1) {
> >             ret[0] = (0x01ull << 63);
> >             ret[1] = ~0ull;
> >         } else {
> >             ret[0] = (0x01ull << 63) - 1;
> >             ret[1] = 0x00;
> >         }
> >         set_DSPControl_overflow_flag(1, 16 + ac, env);
> >     } else {
> >         ret[1] = (((uint64_t)env->active_tc.LO[ac] > (uint64_t)ret[0]) &&
> >                   ((uint64_t)a[0] > (uint64_t)ret[0])) ? ret[1] : ret[1] + 1;
> >     }
> > }
> > 
> > static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
> >                                              int32_t ac,
> >                                              int64_t *a,
> >                                              CPUMIPSState *env)
> > {
> >     uint32_t temp64;
> > 
> >     ret[0] = env->active_tc.LO[ac] - a[0];
> >     ret[1] = env->active_tc.HI[ac] - a[1];
> > 
> >     temp64 = ret[1] & 0x01;
> > 
> >     if (temp64 ^ MIPSDSP_OVERFLOW(env->active_tc.LO[ac], -a[0], ret[0],
> >                                   (0x01ull << 63))) {
> >         if (temp64 == 1) {
> >             ret[0] = (0x01ull << 63);
> >             ret[1] = ~0ull;
> >         } else {
> >             ret[0] = (0x01ull << 63) - 1;
> >             ret[1] = 0x00;
> >         }
> >         set_DSPControl_overflow_flag(1, 16 + ac, env);
> >     } else {
> >         ret[1] = (uint64_t)env->active_tc.LO[ac] > (uint64_t)ret[0] ?
> >             ret[1] : ret[1] - 1;
> >     }
> > }
> > 
> 
> That looks fine to me. That said given it mean we have to propagate the
> carry, you might want to avoid the else case:
> 
> | static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
> |                                              int32_t ac,
> |                                              int64_t *a,
> |                                              CPUMIPSState *env)
> | {
> |     bool temp64;
> | 
> |     ret[0] = env->active_tc.LO[ac] - a[0];
> |     ret[1] = env->active_tc.HI[ac] - a[1];
> | 
> |     if (MIPSDSP_OVERFLOW(env->active_tc.LO[ac], -a[0], ret[0],
> |                          (0x01ull << 63))) {
> |         ret[1] -= 1;
> |     }
> |     temp64 = ret[1] & 1;
> |     if (temp64 != (ret[0] >> 63)) {
> |         if (temp64) {
> |             ret[0] = (0x01ull << 63);
> |             ret[1] = ~0ull;
> |         } else {
> |             ret[0] = (0x01ull << 63) - 1;
> |             ret[1] = 0x00;
> |         }
> |         set_DSPControl_overflow_flag(1, 16 + ac, env);
> |     }
> | }
> 

Actually this is likely wrong, MIPSDSP_OVERFLOW works for the overflow
detection, not for the carry detection. So something like that should
work:

| static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
|                                              int32_t ac,
|                                              int64_t *a,
|                                              CPUMIPSState *env)
| {
|     bool temp64;
| 
|     ret[0] = env->active_tc.LO[ac] - a[0];
|     ret[1] = env->active_tc.HI[ac] - a[1];
|
|     if ((uint64_t)env->active_tc.LO[ac] > (uint64_t)ret[0]) {
|         ret[1] -= 1;
|     }
|     temp64 = ret[1] & 1;
|     if (temp64 != (ret[0] >> 63)) {
|         if (temp64) {
|             ret[0] = (0x01ull << 63);
|             ret[1] = ~0ull;
|         } else {
|             ret[0] = (0x01ull << 63) - 1;
|             ret[1] = 0x00;
|         }
|         set_DSPControl_overflow_flag(1, 16 + ac, env);
|     }
| }

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

  reply	other threads:[~2012-10-18 11:18 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-15 16:39 [Qemu-devel] [PATCH v11 00/14] QEMU MIPS ASE DSP support Jia Liu
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 01/14] target-mips: Add ASE DSP internal functions Jia Liu
2012-10-16 23:20   ` Aurelien Jarno
2012-10-17  3:39     ` Jia Liu
2012-10-17 15:15       ` Aurelien Jarno
2012-10-18  1:53         ` Jia Liu
2012-10-18  6:05           ` Aurelien Jarno
2012-10-18 11:18             ` Aurelien Jarno [this message]
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 02/14] target-mips: Add ASE DSP resources access check Jia Liu
2012-10-16 23:21   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 03/14] target-mips: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
2012-10-16 23:21   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 04/14] target-mips: Add ASE DSP branch instructions Jia Liu
2012-10-16 23:21   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 05/14] target-mips: Add ASE DSP load instructions Jia Liu
2012-10-16 23:21   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 06/14] target-mips: Add ASE DSP arithmetic instructions Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-17  4:05     ` Jia Liu
2012-10-17  4:54       ` Jia Liu
2012-10-17  6:05         ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 07/14] target-mips: Add ASE DSP GPR based shift instructions Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-30 14:47     ` Jia Liu
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 08/14] target-mips: Add ASE DSP multiply instructions Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 09/14] target-mips: Add ASE DSP bit/manipulation instructions Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-17  3:44     ` Jia Liu
2012-10-17  6:05       ` Aurelien Jarno
2012-10-17  7:16         ` Richard Henderson
2012-10-17 20:07           ` Aurelien Jarno
2012-10-18  0:09             ` Jia Liu
2012-10-17  7:41         ` Jia Liu
2012-10-17 15:15           ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 10/14] target-mips: Add ASE DSP compare-pick instructions Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 11/14] target-mips: Add ASE DSP accumulator instructions Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 12/14] target-mips: Add ASE DSP processors Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 13/14] target-mips: Add ASE DSP testcases Jia Liu
2012-10-16 23:23   ` Aurelien Jarno
2012-10-15 16:39 ` [Qemu-devel] [PATCH v11 14/14] target-mips: Change TODO file Jia Liu
2012-10-16 23:23   ` Aurelien Jarno

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20121018111815.GA32459@ohm.aurel32.net \
    --to=aurelien@aurel32.net \
    --cc=proljc@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.