beautypg.com

Echelon Neuron User Manual

Page 48

background image

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