qemu-devel.nongnu.org archive mirror
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).