Searching \ for 'Want 16-bit math stack based' in subject line. () Help us get a faster server
FAQ page: www.piclist.com/techref/method/math.htm?key=math
Search entire site for: 'Want 16-bit math stack based'.

Truncated match.
PICList Thread
'Want 16-bit math stack based'
1999\12\15@174427 by  Summary: anyone got some 16-bit math functions in PIC assembler that use
a data stack instead of direct addressing?

I'm trying to cram some code that works fine on 16F84 into a 12C509, and
one of the big costs is the number of register file bytes used by
functions as temporary storage.  The method I've chosen for reducing it
is to adopt a data stack based on the FSR and INDF registers.

I've converted a 16-bit addition function, and I'm sure I can do the
subtract function as well.  The tough ones are multiply and divide.

Example: 16-bit addition from http://www.myke.com/

movf    acc_b_hi,w
addwf   acc_a_hi,f      ; add most significant byte
movf    acc_b,w
addwf   acc_a,f         ; add least significant byte
btfsc   status,c
incf    acc_a_hi        ; if carry, increment MSB
retlw   0

That requires four bytes of register file and seven instructions.
Now, re-working it to use a data stack makes it look like this;
(the parenthetical stuff is forth-like stack comments, the ^ tilde
indicates where the stack pointer FSR has been moved to)

;; ( lsb1 msb1 lsb2 msb2 -- lsb3 msb3 )

movf    indf,w                  ; msb2
incf    fsr,f                   ; ( lsb1 msb1 lsb2 ^ msb2 )
incf    fsr,f                   ; ( lsb1 msb1 ^ lsb2 msb2 )
addwf   indf,f                  ; msb3 = msb1 + msb2
decf    fsr,f                   ; ( lsb1 msb3 lsb2 ^ msb2 )
movf    indf,w                  ; lsb2
incf    fsr,f                   ; ( lsb1 msb3 ^ lsb2 msb2 )
incf    fsr,f                   ; ( lsb1 ^ msb3 lsb2 msb2 )
addwf   indf,f                  ; lsb3 = lsb1 + lsb2
decf    fsr,f                   ; ( lsb3 msb3 ^ lsb2 msb2 )
btfsc   status,c                ; carry?
incf    indf,f                  ; msb1
retlw   0                       ; ( lsb3 msb3 )

Now 13 instructions and no register file usage apart from the data
stack.  I have more instruction space spare than register file.

The multiply function I have is also from Myke's site.  16-bit inputs,
16-bit output.

The division function I have is from Application Note 526.
Two 16-bit inputs, two 16-bit outputs, result and remainder.

--
James Cameron   quozl us.netrek.org   http://quozl.us.netrek.org/  The code is at http://www.certi.ufsc.br/~jls/pfu.zip
I will keep it there for some days than I have to move it.
Help yourself :-)

MC & HNY
JSouto  james,

have you seen this:
www.phanderson.com/PIC/12C509/stack.html
regards,
alice

> Hi -
> There is a Forth for Pics, this is (undoubtedly) stack based.  You could
> either use it as is, or steal the code for the operations you want.   It is
> designed to  load in only the code that you require.  Check it out.
>
> David
>
>
> James Cameron wrote:
>
> > Summary: anyone got some 16-bit math functions in PIC assembler that use
> > a data stack instead of direct addressing?
> >
> > I'm trying to cram some code that works fine on 16F84 into a 12C509, and
> > one of the big costs is the number of register file bytes used by
> > functions as temporary storage.  The method I've chosen for reducing it
> > is to adopt a data stack based on the FSR and INDF registers.
> >
{Quote hidden}   >
> james,
>
>  have you seen this:
>  www.phanderson.com/PIC/12C509/stack.html
>  regards,
>  alice

Doesn't really apply. That's just a rehash of an old trick from the 16C5X
days where you could only make two subroutine calls.

> > > > I've converted a 16-bit addition function, and I'm sure I can do the
> > > > subtract function as well.  The tough ones are multiply and divide.

multiply and divide are difficult under any circumstances where a base
8x8 multiply doesn't exist. The most data saving method is repetitive
add/subtract (costing only 2 extra bytes to hold the addend/subtrahend).
Of course it's the slowest too. But you can double the use of your already
written add subtract:

Presuming that you have in your stack:

LSB1
MSB1
LSB2
MSB2

1)You move LSB1 and LSB2 into the 2 byte counter area.
2)Then copy LSB2 and MSB2 over LSB1 and LSB2.
3)Run LSB1 and LSB2 in a decriment loop. Each time though the loop:
A)Call the add routine, which adds LSB1 and LSB2 to the partial product below.
B)Reset FSR to that the top of stack points to the top LSB1 again.
4) Pop the top LSB1 and MSB1 off the stack.

The product results below.

Divide would be similar, subtracting instead of adding and counting the
number of subtracts.

But the addage "Fast or Small, pick one" really applies here.

BAJ  --- Byron A Jeff <byron CC.GATECH.EDU> wrote:
>

<snip>

{Quote hidden}

Perhaps. However, like always, there are a few tricks.

A full blown, generic, RPN-like, stack-based
arithmetic program on a 12-bit device is most probably
not feasible. I'm not sure what James really wants to
accomplish, however when I've needed similar behavior
from a pic I implemented a comprised solution.
Specifically, there are times when a computation needs
to be performed on an array of data. The index of the
array may be a function of some algorithm and hence is
not known a priori. In those cases, it sometimes makes
sense to utilize the indirect register and a
'one-deep' stack.

For example, many arithmetic computations are binary:

x = N1 operator N2

N1 and N2 are two numbers, 'operator' is '+','-', etc.
and x is the result. James wants this to be computed
like so:

push N1 on the stack
push N2 on the stack
pop N1 and N2 off of the stack, operate on them with
the 'operator' and push the result back on the stack.

(Am I being presumptuous, James?) On a ram starved
12-bit core duplicating memory locations is a waste of
precious resources. So the compromised solution that
works well in many cases is to copy only one operand
onto the stack and use indirect addressing for the
other. As an example, consider this operation:

N1 = N1 + N2

;push N1 onto the 'stack'
movf  N1_lo,w
movwf stack_lo
movf  N1_hi,w
movwf stack_hi

;Get pointer to N2
movlw N2_lo
movwf fsr

;add indf to stack

movf    indf,w      ;get low byte
incf    fsr,f       ;point to the high byte

addwf   stack_lo,f  ;add low bytes together
movf    indf,w
skpnc
incf   indf,w
addwf stack_hi,f

I use this sort of thing for finding the sum of all of
the elements of an array.

Now, you could extrapolate this concept by writing
macros to push on and pop off of a real ram-based
stack. For example, taking the equation from above

x = N1 + N2

You could do this:

Application pushes N1 and N2 onto the stack and then
calls the add routine:

add:   ; pop top two stack elements, add together
; and push back on to the stack

; copy tos to accumulator and decrement
; the stack ptr

POP  stack_ptr, accumulator

; copy a pointer to the tos to fsr
POP_INDF

;accumulator += INDF (shown above)
ADD_INDF  accumulator

;move the contents of the accumulator
;to the top of the stack.
REPLACE_TOS   accumulator

return

flexible, but slow.

I guess the point I'm trying to make is that the
compromised stack solution uses the indf to reference
one element of the stack and a memory copy to an
accumulator for the other element. This minimizes the
amount of time spent swapping the fsr contents around
and could save considerable time in looped operations
like multiplication and division.

Now if you had two (or more) indf modules like the new
18c parts, then this would be a whole lot cleaner.

.lo
__________________________________________________
Do You Yahoo!?
Thousands of Stores.  Millions of Products.  All in one place.
Yahoo! Shopping: http://shopping.yahoo.com  Thanks for the contributions.  None of them had what I wanted, so I got
out my coding axe and hacked into the routines I already had.

Having converted all the math functions I was using into stack based
functions, with two temporary memory locations, my main code has been
greatly simplified and the file register usage has been reduced down
beyond what I thought was practical.

http://quozl.us.netrek.org/stack-math.asm is the result.

--
James Cameron   quozl us.netrek.org   http://quozl.us.netrek.org/

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