Searching \ for 'Decrement 4 byte variables, redux' in subject line. ()
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.
'Decrement 4 byte variables, redux'
2000\02\06@023223 by

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

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

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

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
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

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

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

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

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...