Searching \ for 'Decrement 4 byte variables, redux' 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=decrement+byte+variables
Search entire site for: 'Decrement 4 byte variables, redux'.

Truncated match.
PICList Thread
'Decrement 4 byte variables, redux'
2000\02\06@023223 by Rich Leggitt

picon face
Hi all - with Andy's cool trick I'm down to 10 cycles typical with return
in Z. Any other ideas? - Rich

; given address of 32 bit little-endian counter in W,
; decrement the counter and return Z set if zero
; 99.2% of the time, this takes 10 cycles w/call
dec32           movwf FSR       ; FSR -> v
               decfsz INDF,f   ; v[0]--
               goto dec32nz

               ; here, v[0] just became 0, check the others
               incf FSR,f      ; get v[1]
               movf INDF,w
               incf FSR,f      ; OR v[2]
               iorwf INDF,w
               incf FSR,f      ; OR v[3]
               iorwf INDF,w
               return          ; return Z set if so

               ; here, v[0] is non-zero, make sure we return with Z=0
dec32nz         clrz            ; in case Z was set on entry...
               incfsz INDF,w   ; now, did v[0] underflow?
               return          ; no (this is 99.2% path)
               incf FSR,f      ; yes, advance to v[1]
               decfsz INDF,f   ; dec v[1]
               incfsz INDF,w   ; underflow?
               return          ;
               incf FSR,f      ; yes, advance to v[2]
               decfsz INDF,f   ; dec v[2]
               incfsz INDF,w   ; underflow?
               return          ;
               incf FSR,f      ; yes, advance to v[3]
               decfsz INDF,f   ; dec v[3]
               return          ; return
               return          ; in either case


2000\02\06@074322 by Dmitry Kiryashov

flavicon
face
Hi Rich.

incf FSR,F will destroy zero flag.
Let's try to use incfsz FSR,F instead.

WBR Dmitry.


PS. modified variant of your code:

; given address of 32 bit little-endian counter in W,
; decrement the counter and return Z set if zero
; 99.2% of the time, this takes 10 cycles w/call

dec32:
       movwf   FSR
       decfsz  INDF,F
       goto    dec32nz

       incf    FSR,F
       movfw   INDF

       incf    FSR,F
       iorwf   INDF,W

       incf    FSR,F
       iorwf   INDF,W  ;get _Z finally
       return

dec32nz:
       clrz            ;set _Z=0
       incfsz  INDF,W
       return

       incfsz  FSR,F   ;doesn't corrupt _Z
       decfsz  INDF,F
       incfsz  INDF,W
       return

       incfsz  FSR,F   ;...
       decfsz  INDF,F
       incfsz  INDF,W
       return

       incfsz  FSR,F   ;...
       decfsz  INDF,F
       return
       return

2000\02\06@121240 by Rich Leggitt

picon face
On Sun, 6 Feb 2000, Dmitry Kiryashov wrote:

> incf FSR,F will destroy zero flag.
Assuming FSR doesn't roll over, won't it just *clear* the Z flag?

> Let's try to use incfsz FSR,F instead.
Thanks Dmitry - Rich

2000\02\06@180559 by Dmitry Kiryashov

flavicon
face
Hi Rich.

Here is 32bit increment counter. It's a little bit
shorter so it can be used if time|memory is critical.

WBR Dmitry.

inc32:
       movwf   FSR
       clrz

       incfsz  INDF,F
       return

       incfsz  FSR,F
       incfsz  INDF,F
       return

       incfsz  FSR,F
       incfsz  INDF,F
       return

       incfsz  FSR,F
       incf    INDF,F
       return

2000\02\07@131253 by Scott Dattalo
face
flavicon
face
On Sun, 6 Feb 2000, Dmitry Kiryashov wrote:

> Hi Rich.
>
> incf FSR,F will destroy zero flag.
> Let's try to use incfsz FSR,F instead.
>
> WBR Dmitry.
>
>
> PS. modified variant of your code:
>
> ; given address of 32 bit little-endian counter in W,
> ; decrement the counter and return Z set if zero
> ; 99.2% of the time, this takes 10 cycles w/call

actually, it's 13 cycles if you take the call and return into account and
11 cycles w/o call.

{Quote hidden}

If Dmitry's optimized then chances are nobody can do much better. However,
I thought it'd be interesting to see this same thing done with 18cxxx
instruction set. I know it doesn't help you in the least, but it is
instructional

; 10-16 cycles

dec32:
   movwf   FSR0L    ; the fsr's (three of them) on the 18cxxx
   clrf    FSR0H    ; are 16bits wide

   decf    POSTINC0,F,1 ;Indirect access that increments the fsr.

   bz      dec32nz

   movf    POSTINC0,w,1
   iorwf   POSTINC0,w,1
   iorwf   POSTINC0,w,1

   return

dec32nz
  ;decf on the 18cxxx parts affects C

   skpc
    decf  POSTINC0,F,1

   skpc
    decf  POSTINC0,F,1

   skpc
    decf  POSTINC0,F,1

   setz
   return


There are probably a couple of things you can do to minimize the second
part...

Scott

2000\02\07@161504 by Rich Leggitt

picon face
On Mon, 7 Feb 2000, Scott Dattalo wrote:

> actually, it's 13 cycles if you take the call and return into account and
> 11 cycles w/o call.
Really? What am I missing?

> > dec32:                                      2 cycles to get here
> >         movwf   FSR                         3 cycles
> >         decfsz  INDF,F                      4 cycles (since no skip)
> >         goto    dec32nz                     6 cycles
> >
...

> > dec32nz:
> >         clrz            ;set _Z=0           7 cycles
> >         incfsz  INDF,W                      8 cycles (since no skip)
> >         return                              10 cycles
> >
>
> If Dmitry's optimized then chances are nobody can do much better. However,
> I thought it'd be interesting to see this same thing done with 18cxxx
> instruction set. I know it doesn't help you in the least, but it is
> instructional
Ah, never done 18cxxx before, POSTINC looks useful... :)

- Rich

2000\02\07@170314 by Rich Leggitt

picon face
On Sun, 6 Feb 2000, Dmitry Kiryashov wrote:

> Here is 32bit increment counter. It's a little bit shorter so it can
> be used if time|memory is critical.

Hey, I like it, all I have to do is negate the initial counter value upon
receipt:

neg32:  movwf FSR               ; 32 bit 2's complement
       comf INDF,f             ; i.e. invert and increment
       incf FSR,f
       comf INDF,f
       incf FSR,f
       comf INDF,f
       incf FSR,f
       comf INDF,f
       ; fall thru

inc32:
       movwf   FSR
       clrz
       incfsz  INDF,F
       return
       incfsz  FSR,F
       incfsz  INDF,F
       return
       incfsz  FSR,F
       incfsz  INDF,F
       return
       incfsz  FSR,F
       incf    INDF,F
       return

And as a bonus: negative zero sets Z, so I can dump the code to test for
receipt of a zero count... VERY COOL! Thanks.

- Rich

2000\02\07@183704 by Scott Dattalo

face
flavicon
face
On Mon, 7 Feb 2000, Rich Leggitt wrote:

> On Mon, 7 Feb 2000, Scott Dattalo wrote:
>
> > actually, it's 13 cycles if you take the call and return into account and
> > 11 cycles w/o call.
> Really? What am I missing?

I was counting time along the wrong path of execution. You're right. I
also optimized for the wrong path (and there were two polarity errors with
the Z bit). Okay I got the mistakes out of the way.


dec32:
   movwf   FSR0L    ; the fsr's (three of them) on the 18cxxx
   clrf    FSR0H    ; are 16bits wide

   decf    POSTINC0,F,1 ;Indirect access that increments the fsr.

   bnz      dec32nz     ;this was bz

 ;The lsbyte is zero , so we don't need to propogate the borrow
 ;but we need to see if the higher bytes are zero.

   movf    POSTINC0,w,1 ;The first byte is zero
   iorwf   POSTINC0,w,1 ;check the next three
   iorwf   POSTINC0,w,1

   return

dec32nz
  ;decf on the 18cxxx parts affects C

   skpnc
    return

   decf   POSINC0,F,1
   skpc
    decf  POSTINC0,F,1

   skpc
    decf  POSTINC0,F,1

   clrz          ;was setz
   return

-------------

On Mon, 7 Feb 2000, Rich Leggitt wrote:

> On Sun, 6 Feb 2000, Dmitry Kiryashov wrote:
>
> > Here is 32bit increment counter. It's a little bit shorter so it can
> > be used if time|memory is critical.
>
> Hey, I like it, all I have to do is negate the initial counter value
upon
{Quote hidden}

this would look like:
neg32:
   movwf  fsr0l
   clrf   fsr0h
   comf   postinc0,f,1
   comf   postinc0,f,1
   comf   postinc0,f,1
   comf   postinc0,f,1

inc32:
   movwf  fsr0l
   clrf   fsr0h
   clrz
   incfsz postinc0,f,1
    return
   incfsz postinc0,f,1
    return
   incfsz postinc0,f,1
    return
   incf   postinc0,f,1
   return


another way:
inc32:
   movwf  fsr0l
   clrf   fsr0h
   subwf  wreg,w,1     ;zero W and set the carry
   addwfc postinc0,f,1
   addwfc postinc0,f,1
   addwfc postinc0,f,1
   addwfc indf0,f,1

   movf   postdec0,w,1
   iorwf  postdec0,w,1
   iorwf  postdec0,w,1
   iorwf  indf0,w,1

   return

but it's a cycle longer. (but it's isochronous, and could be cascaded
since fsr0 points to the beginning byte).

Scott

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