Searching \ for 'Signed 16-bit Operations' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/index.htm?key=signed+bit+operations
Search entire site for: 'Signed 16-bit Operations'.

Truncated match.
PICList Thread
'Signed 16-bit Operations'
1997\09\18@140249 by fdalton

flavicon
face
Thanks to all of you who had so much fun answering
my previous stupid newbie question about bit masks.

Now, I am faced with another such question that is
undoubtedly "newbie" as well.

Does anyone have efficient code that will simply
COMPARE two 16-bit SIGNED integers without too
much temporary register usage?

Is there anywhere I can look for the answers to
these kinds of questions so that I don't have to
waste precious LISTSERV bandwidth?  There must
be some kind of compendium of all of these bit
banging tricks and routine math operations somewhere.

--
------------------------------------------------------
  /\         Frank Dalton (spam_OUTfdaltonTakeThisOuTspampineinst.com)
 //\\        Pine Instrument Company
///\\\       101 Industrial Drive
////\\\\      Grove City, PA 16127
  ||         (412) 458-6391
  ||         http://www.pineinst.com
------------------------------------------------------

1997\09\18@153345 by Walter Banks

picon face
All compares on a PIC can be done with just the w register
as the only temporary. On the PIC parts compares in
general sould be done by comparing individual bytes
whenever possible, A  little attention to detail is worth it.
I believe the MPC compiler has a total of 55 different
code sequences related to 8 and 16 bit compares.

Walter Banks


> Does anyone have efficient code that will simply
> COMPARE two 16-bit SIGNED integers without too
> much temporary register usage?

1997\09\18@164012 by Clyde Smith-Stubbs

flavicon
face
On Thu, Sep 18, 1997 at 01:24:45PM -0400, Frank Dalton wrote:

> Does anyone have efficient code that will simply
> COMPARE two 16-bit SIGNED integers without too
> much temporary register usage?

Not really a newbie question - it's harder than it looks.
I'm giving away the family jools here :-)

The problem is that subtraction of signed numbers can cause
overflow; the solution is to make them unsigned, i.e. add
32768 to each number, thus bringing them into the range 0-65535,
and now you can subtract without fear of overflow, using the carry
flag as the sign of the result. Adding 32768 is as easy as toggling
the most significant bit of the number. Here's sample (compiler-generated)
code for testing i <= j which is actually turned around to be
!(j < i)

;x.c: 6: if(i <= j)
       movf    _j+1,w          ;get the most significant byte
       xorlw   128             ;make it an unsigned number
       movwf   btemp           ;save
       movf    _i+1,w          ;ditto the other operand
       xorlw   128
       subwf   btemp,w         ;subtract to compare
       movf    _i,w            ;get ready to compare low bytes
       btfsc   3,2             ;if hi bytes not equal, we're done
       subwf   _j,w
       btfss   3,0             ;now C bit is set if i <= j


> Is there anywhere I can look for the answers to
> these kinds of questions so that I don't have to

Nope, this is the right place.

Of course you can save all this heartache by using a comp... oops,
better not be too blatant!

Cheers, Clyde

--
Clyde Smith-Stubbs               |            HI-TECH Software
Email: .....clydeKILLspamspam@spam@htsoft.com          |          Phone            Fax
WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
PGP:   finger clydespamKILLspamhtsoft.com   | AUS: +61 7 3354 2411 +61 7 3354 2422
---------------------------------------------------------------------------
ANSI C for the PIC! Now shipping! See http://www.htsoft.com for more info.

1997\09\18@183316 by John Payson

picon face
> ;x.c: 6: if(i <= j)
>         movf    _j+1,w          ;get the most significant byte
>         xorlw   128             ;make it an unsigned number
>         movwf   btemp           ;save
>         movf    _i+1,w          ;ditto the other operand
>         xorlw   128
>         subwf   btemp,w         ;subtract to compare
>         movf    _i,w            ;get ready to compare low bytes
>         btfsc   3,2             ;if hi bytes not equal, we're done
???????
>         subwf   _j,w
>         btfss   3,0             ;now C bit is set if i <= j

Doesn't "movf _i,w" trash Z?  Perhaps you mistyped that?

Hmm... my attempt:
       movf    iH,w
       subwf   jH,w
       btfss   Z
        goto   Comp2
       movf    iL,w
       subwf   jL,w
Comp2:                  ; We've done an unsigned compare to this point.
       rrf     KZ,w    ; KZ=known-zero address
       xorwf   iH,w
       xorwf   iL,w
       addlw   128
       ; Carry flag now holds compare result

Probably not the best way, and pre-adding the 128 is certainly the way to
go if at least one of the operands is a temp-value (which can safely be
trashed).  But it's still interesting to see some other approaches.

1997\09\18@192249 by Clyde Smith-Stubbs

flavicon
face
On Thu, Sep 18, 1997 at 05:19:56PM -0500, John Payson wrote:

> Doesn't "movf _i,w" trash Z?  Perhaps you mistyped that?

Yeah, I was being (too) clever. I looked at the compiler output and thought
I could improve on it.

It should have read:

;x.c: 6: if(i <= j)
        movf    _j+1,w          ;get the most significant byte
        xorlw   128             ;make it an unsigned number
        movwf   btemp           ;save
        movf    _i+1,w          ;ditto the other operand
        xorlw   128
        subwf   btemp,w         ;subtract to compare
        btfss   3,2             ;if hi bytes not equal, we're done
        goto    u15
        movf    _i,w            ;get ready to compare low bytes
        subwf   _j,w
u15
        btfss   3,0             ;now C bit is set if i <= j

Of course when comparing with a constant, the temp location is not
required.
>
>
> Hmm... my attempt:
>

Interesting - same number of instructions, but avoids using the temp
location, but does require the known-zero, which not all PICs have.

Clyde

--
Clyde Smith-Stubbs               |            HI-TECH Software
Email: .....clydeKILLspamspam.....htsoft.com          |          Phone            Fax
WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
PGP:   finger EraseMEclydespam_OUTspamTakeThisOuThtsoft.com   | AUS: +61 7 3354 2411 +61 7 3354 2422
---------------------------------------------------------------------------
ANSI C for the PIC! Now shipping! See http://www.htsoft.com for more info.

1997\09\18@213114 by John Payson

picon face
> > Hmm... my attempt:
> >
>
> Interesting - same number of instructions, but avoids using the temp
> location, but does require the known-zero, which not all PICs have.

It's true that not all PICs have a hardware known-zero.  Nonetheless, you
might want to consider having the compiler allocate one.  You could use
the same location to hold things like the loop counter for shifting oper-
ations, the byte counter for structure copying, etc. if you ensured that
it was always zero in the "general" context.  In fact, having a loop counter
which is always zero when not in a loop can be useful if your loops have
power-of-two repetition counts (e.g. rather than saying:

       movlw   8
       movwf   KZloop
loop
       ...
       decfsz  KZloop
        goto   loop

you could replace the first two instructions with:

       bsf     KZloop,3

Note that in addition to the "rrf kz,w" instruction used to read C into the
MSB of W, there is also a very useful "rlf KZ,w" which is very nice when
doing arithmetic:

       movf    SourceL,w
       addwf   DestL,w
       rlf     KZ,w
       addwf   SourceH,w
       addwf   DestH,w

Note that the carry out of that instruction sequence won't be valid, but the
trick can be used for the high byte of any multi-byte addition (not generally
useful for subtraction, though).  While it "only" saves one cycle per add-
ition, 16-bit additions are probably one of the more common things people will
be doing.

By the way, it's possible to do a 3-cycle add-constant-with-propagating-carry:

       ; If const == 0, use this
       rlf     KZ,w
       addwf   dest
       ; If const != 255 use this:
       rlf     KZ,w
       addlw   const
       addwf   dest

       ; If const == 255, use this:
       movlw   255
       btfss   C
        addwf  dest

All of these lend themselves well to dest=src+const constructs:

       ; If const == 0, use this
       rlf     KZ,w
       addwf   src,w
       movwf   dest

       ; If const != 255, use this
       rlf     KZ,w
       addlw   const
       addwf   src,w
       movwf   dest

       ; If const == 255, use this
       movf    source,w
       btfss   C
        addlw  255
       movwf   dest

I don't think it's possible to do better than those.

1997\09\18@223210 by Clyde Smith-Stubbs

flavicon
face
On Thu, Sep 18, 1997 at 07:50:09PM -0500, John Payson wrote:

> It's true that not all PICs have a hardware known-zero.  Nonetheless, you
> might want to consider having the compiler allocate one.  You could use

The trouble with allocating a RAM location as a zero is that you have
to ensure it is in fact always zero (some of your suggestions make it
non zero temporarily) or be prepared to save and restore it on interrupts.

An easier approach is to use a known-zero location on chips that have it,
and do things other ways on other chips. This is already on our to-do list
(thanks to your earlier suggestions!)

Clyde

--
Clyde Smith-Stubbs               |            HI-TECH Software
Email: clydespamspam_OUThtsoft.com          |          Phone            Fax
WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
PGP:   finger @spam@clydeKILLspamspamhtsoft.com   | AUS: +61 7 3354 2411 +61 7 3354 2422
---------------------------------------------------------------------------
ANSI C for the PIC! Now shipping! See http://www.htsoft.com for more info.

1997\09\19@015946 by John Payson

picon face
> On Thu, Sep 18, 1997 at 07:50:09PM -0500, John Payson wrote:
>
> > It's true that not all PICs have a hardware known-zero.  Nonetheless, you
> > might want to consider having the compiler allocate one.  You could use
>
> The trouble with allocating a RAM location as a zero is that you have
> to ensure it is in fact always zero (some of your suggestions make it
> non zero temporarily) or be prepared to save and restore it on interrupts.

Well, there are three approaches:

[1] "CLRF" a certain address at startup and never write to it during
   program execution; use that address for nothing else.  This may not
   pose a problem, since the parts that lack a convenient hardware KZ
   generally have a fair bit of RAM.  On something like the '622, you
   could use $7F; it's hardware-KZ in one page and you could CLRF it
   in the other.

[2] Save/restore it during the interrupt routine (kinda a bummer of an
   idea, really, but it would be possible)

[3] For that and all other non-hardware compiler temps, allocate a sep-
   erate copy for use during ISR's.  This would make it necessary to
   link in twice any routine that's needed by both an ISR and the main
   program, but I wouldn't think that should be a problem.  Far better
   than saving/restoring a lot of compiler-temp variables.

If you're not well-equipped for [3], I think [1] may be the best way to
go.

> An easier approach is to use a known-zero location on chips that have it,
> and do things other ways on other chips. This is already on our to-do list
> (thanks to your earlier suggestions!)

While I can imagine that a few applications on the 16C74 could have a fit
if you stole a register for use as KZ (to which you never wrote other than
a CLRF on startup) I'd certainly want the ability to have the compiler
generate code using that if I had any RAM at all to spare (after all, any
RAM the compiler doesn't do something with will never be used--EVER).
Perhaps a compiler option?

1997\09\19@175220 by Eric van Es

flavicon
face
John Payson wrote:

> > On Thu, Sep 18, 1997 at 07:50:09PM -0500, John Payson wrote:
> > > It's true that not all PICs have a hardware known-zero.
> Nonetheless, you
> > > might want to consider having the compiler allocate one.  You
> could use

Would someone be so kind as to explain what exactly the significance of
a known zero is?
>From what I've seen, I can deduct that you use it as a fixed reference
point to which you can compare all your arithmic and answers?

Cheers!
--
Eric van Es               | Cape Town, South Africa
KILLspamvanesKILLspamspamilink.nis.za | http://www.nis.za/~vanes
LOOKING FOR TEMPORARY / HOLIDAY ACCOMODATION?
http://www.nis.za/~vanes/accom.htm

1997\09\19@182230 by Andrew Warren

face
flavicon
face
Eric van Es <RemoveMEPICLISTTakeThisOuTspamMITVMA.MIT.EDU> wrote:

> Would someone be so kind as to explain what exactly the significance
> of a known zero [register] is?

Eric:

If you know that a register contains 00, you can often use that
knowledge to optimize your code... For example, let's say that you
want to copy the state of the Carry flag into the W register.  Here's
one way:

   MOVLW   0               ;Assume that carry's clear, so W = 0.
   SKPNC                   ;If it IS clear, skip ahead.
   MOVLW   1               ;Otherwise, W = 1.

If you're REALLY clever, you can do this:

   MOVF    STATUS,W
   ANDLW   00000001B       ;Carry flag happens to occupy the LSB
                           ;of the STATUS register.

Both of those solutions, however, take more time and space than the
following, which depends upon the existance of a register known to
contain 00:

   RLF     KNOWNZERO,W

-Andy

=== Meet other PICLIST members at the Embedded Systems Conference:
=== 6:30 pm on Wednesday, 1 October, at Bytecraft Limited's booth.
===
=== For more information on the Embedded Systems Conference,
=== see: http://www.embedsyscon.com/

=== Andrew Warren - spamBeGonefastfwdspamBeGonespamix.netcom.com
=== Fast Forward Engineering - Vista, California
=== http://www.geocities.com/SiliconValley/2499

1997\09\19@183233 by John Payson

picon face
> John Payson wrote:
>
> > > On Thu, Sep 18, 1997 at 07:50:09PM -0500, John Payson wrote:
> > > > It's true that not all PICs have a hardware known-zero.
> > Nonetheless, you
> > > > might want to consider having the compiler allocate one.  You
> > could use
>
> Would someone be so kind as to explain what exactly the significance of
> a known zero is?
> >From what I've seen, I can deduct that you use it as a fixed reference
> point to which you can compare all your arithmic and answers?

A known-zero location is useful for the following two instructions:

       rlf     KZ,w    ; W will be 0 if carry clear, 1 if carry set
       rrf     KZ,w    ; W will be 0 if carry clear, 128 if carry set

If you have a loop counter that's always left at zero when you're not
using it, you can replace:

       movlw   8
       movwf   counter

with

       bsf     counter,3

or likewise for counts of 1, 2, 4, etc. or 255 [use comf or decf]; in
addition, the normal "decfsnz loop" behavior is to loop precisely 256
times if the counter is zero at the start.

1997\09\20@110354 by mikesmith_oz.nosp*m

flavicon
face
On 19 Sep 97 at 11:46, Clyde Smith-Stubbs wrote:

> On Thu, Sep 18, 1997 at 07:50:09PM -0500, John Payson wrote:
>
> > It's true that not all PICs have a hardware known-zero.  Nonetheless, you
> > might want to consider having the compiler allocate one.  You could use
>
> The trouble with allocating a RAM location as a zero is that you
> have to ensure it is in fact always zero (some of your suggestions
> make it non zero temporarily) or be prepared to save and restore it
> on interrupts.

If it's a hardware KZ, I presume you mean it can't be set Non-Z?
If this is so, how could John Payson's dec loop work, since you
couldn't set it up.

>
> An easier approach is to use a known-zero location on chips that
> have it, and do things other ways on other chips. This is already on
> our to-do list (thanks to your earlier suggestions!)

What are some example KZ's?
MikeS
<mikesmith_oz@nosp*m.relaymail.net>
(remove the you know what before replying)

More... (looser matching)
- Last day of these posts
- In 1997 , 1998 only
- Today
- New search...