Echelon Neuron User Manual
Page 48

•
For the value pi (π), you can use the following approximation: 355/113
(3.1415929203…), which has an error relative to pi of 8.5 * 10
-8
.
•
To multiply two unsigned long integers, you can use the _mul16 system
function.
•
To calculate
(a*b)/c with a 32-bit intermediate result, you can use the
standard Neuron C muldiv() function:
unsigned long muldiv(unsigned long a,
unsigned long b,
unsigned long c);
•
You can use general-purpose pointer registers for general 16-bit values,
not just for pointer values.
Thus, one possible algorithm for the carea function is:
carea := π * r
2
= π * r * r
= 355 * r * r / 113
= (355 * r) * r / 113
which becomes:
carea = muldiv(355*r, r, 113)
which finally becomes:
carea = muldiv(_mul16(355, r), r, 113)
The proposed solution uses a fixed-point approximation for pi (355/133), and a
combination of the _mul16 and muldiv() library functions. To translate the
solution into Neuron assembly instructions, read the algorithm from right to left:
1. Push the unsigned long value of 133 onto the stack.
2. Push the unsigned long radius value onto the stack. This value is the
carea function’s argument.
3. Push the unsigned long radius value onto the stack again.
4. Push the unsigned long constant 355 onto the stack.
5. Call the _mul16 function.
6. Call the muldiv() function.
The Neuron assembly implementation of this function is shown below:
IMPORT _mul16 ; (a(2), b(2) -- (a*b)(2))
IMPORT muldiv ; (a(2), b(2), c(2) -- (a*b/c)(2))
PIFACTOR EQU d’355
PIDIVISOR EQU d’113
; PIFACTOR/PIDIVISOR = PI = 3.14159…
SCRATCH16 EQU 0 ; 16-bit scratch register
%carea APEXP ; (r(2) -- (pi*r*r)(2))
; save r(2) to SCRATCH16 and put PIDIVISOR in place:
popd [SCRATCH16] ; ()
pushd #PIDIVISOR ; (piDiv(2))
; restore radius twice:
38
Writing a Neuron Assembly Utility Function