'Want 16-bit math stack based'
|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/
addwf acc_a_hi,f ; add most significant byte
addwf acc_a,f ; add least significant byte
incf acc_a_hi ; if carry, increment MSB
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,
The division function I have is from Application Note 526.
Two 16-bit inputs, two 16-bit outputs, result and remainder.
James Cameron us.netrek.org quozlhttp://quozl.us.netrek.org/
have you seen this:
> 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.
> 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.
Byron A Jeff
> have you seen this:
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:
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.
|--- Byron A Jeff <CC.GATECH.EDU> wrote: byron
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
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
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'
;Get pointer to N2
;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
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
;accumulator += INDF (shown above)
;move the contents of the accumulator
;to the top of the stack.
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.
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 us.netrek.org quozlhttp://quozl.us.netrek.org/
More... (looser matching)
- Last day of these posts
- In 1999
, 2000 only
- New search...