078-0399-01A Neuron Assembly Reference
078-0399-01A Neuron Assembly Reference
Language Reference
078-0399-01A
Echelon, LONWORKS, LONMARK, NodeBuilder, LonTalk, Neuron,
3120, 3150, ShortStack, LonMaker, and the Echelon logo are
trademarks of Echelon Corporation registered in the United
States and other countries. 3170 is a trademark of the
Echelon Corporation.
Echelon Corporation
www.echelon.com
Welcome
Echelon’s Neuron® assembly language is the symbolic programming language for
both Series 3100 and Series 5000 Neuron Chips and Smart Transceivers. You
can write a Neuron assembly language function or program that interacts with a
Neuron C application program to provide LONWORKS® networking for new or
existing smart devices. The Neuron assembly language is not intended as a
general programming language for LONWORKS devices, but should be used only
to optimize new or existing Neuron C applications.
This document describes the Neuron assembly language. The Neuron assembly
language can be used with any programmable Series 3100 device (Neuron 3120®
Chip, FT 3120 Smart Transceiver, PL 3120 Smart Transceiver, Neuron 3150®
Chip, FT 3150 Smart Transceiver, PL 3150 Smart Transceiver, and PL 3170™
Smart Transceiver) and with any programmable Series 5000 device (FT 5000
Smart Transceiver and Neuron 5000 Processor). Where applicable, this
document identifies differences in the Neuron assembly language that are
specific to a particular device series.
Audience
This document assumes that you have a good understanding of general assembly
language programming concepts and techniques. It also assumes that you are
familiar with the Neuron C programming language and LONWORKS device
development. In addition, a general understanding of either the Series 3100 or
Series 5000 Neuron architecture is required.
Related Documentation
The following manuals are available from the Echelon Web site
(www.echelon.com) and provide additional information that can help you develop
applications for Neuron Chip or Smart Transceiver devices:
• I/O Model Reference for Smart Transceivers and Neuron Chips (078-
0392-01A). This manual describes the I/O models that are available for
Series 3100 and Series 5000 devices.
All of the Echelon documentation is available in Adobe® PDF format. To view the
PDF files, you must have a current version of the Adobe Reader®, which you can
download from Adobe at: www.adobe.com/products/acrobat/readstep2.html.
iv
Table of Contents
Welcome .........................................................................................................iii
Audience ........................................................................................................iii
Related Documentation ................................................................................iii
Chapter 1. Introduction ..................................................................................... 1
Introduction.................................................................................................... 2
Neuron Assembler Tools................................................................................ 3
Neuron C Compiler for Assembly Programming................................... 3
Neuron Assembler Command Line Tool ................................................ 3
Command Usage ............................................................................... 4
NAS Command Switches.................................................................. 4
Neuron Librarian Tool ............................................................................ 5
NodeBuilder Development Tool.............................................................. 6
Assembler Files .............................................................................................. 6
Source Files.............................................................................................. 6
Naming Convention .......................................................................... 6
File Format........................................................................................ 7
Output Files ............................................................................................. 7
General Neuron Assembly Syntax ................................................................ 8
Labels ....................................................................................................... 9
Assembly Instructions............................................................................. 9
Operands ................................................................................................ 10
Literal Constants ............................................................................ 10
Symbols............................................................................................ 10
Expressions...................................................................................... 11
Comments .............................................................................................. 14
Assembler Directives ................................................................................... 14
Interfacing with Neuron C Programs ......................................................... 14
Chapter 2. Neuron Architecture for Neuron Assembly Programming........... 15
Neuron Architecture .................................................................................... 16
Hardware Resources for Assembly Programs ............................................ 17
CPU Registers........................................................................................ 17
General-Purpose Registers............................................................. 18
Pointer Registers............................................................................. 19
Flag Register ................................................................................... 21
Instruction Pointer.......................................................................... 21
Base-Page Register and Stack Registers....................................... 21
Stacks ..................................................................................................... 22
Data Stack ....................................................................................... 22
Return Stack ................................................................................... 23
Stack Manipulation ............................................................................... 24
Segments ................................................................................................ 25
Using Neuron Chip Memory ................................................................. 26
Chips with Off-Chip Memory ......................................................... 26
Chips without Off-Chip Memory.................................................... 28
Accessing Global and Static Data......................................................... 29
Addressing Modes ........................................................................................ 30
Immediate .............................................................................................. 30
Absolute.................................................................................................. 30
Direct ...................................................................................................... 30
Implicit ................................................................................................... 31
vi
BRNEQ (Branch If Not Equal).................................................................... 74
BRNZ (Branch If Not Zero) ......................................................................... 76
BRZ (Branch If Zero).................................................................................... 77
CALL (Call Near) ......................................................................................... 78
CALLF (Call Far) ......................................................................................... 79
CALLR (Call Relative) ................................................................................. 80
DBRNZ (Decrement and Branch If Not Zero) ............................................ 81
DEALLOC (Deallocate and Return) ........................................................... 82
DEC (Decrement) ......................................................................................... 84
DIV (Divide).................................................................................................. 85
DROP (Drop from Stack) ............................................................................. 86
DROP_R (Drop from Stack and Return)..................................................... 87
INC (Increment) ........................................................................................... 88
MUL (Multiply) ............................................................................................ 90
NOP (No Operation)..................................................................................... 91
NOT (Not) ..................................................................................................... 92
OR (Or).......................................................................................................... 93
OR_R (Or and Return) ................................................................................. 94
POP (Pop from Stack) .................................................................................. 95
POPD (Pop Pointer Direct)........................................................................ 100
POPPUSH (Pop from Data Stack and Push onto Return Stack)............ 101
PUSH (Push onto Stack)............................................................................ 102
PUSHD (Push Pointer Direct)................................................................... 107
PUSHPOP (Pop from Return Stack and Push onto Data Stack)............ 109
PUSHS (Push Short).................................................................................. 110
RET (Return from Call) ............................................................................. 111
ROLC (Rotate Left through Carry)........................................................... 112
RORC (Rotate Right through Carry) ........................................................ 113
SBC (Subtract with Carry) ........................................................................ 114
SBR (Short Branch) ................................................................................... 115
SBRNZ (Short Branch If Not Zero)........................................................... 117
SBRZ (Short Branch If Zero) ..................................................................... 119
SHL (Shift Left).......................................................................................... 121
SHLA (Shift Left Arithmetically).............................................................. 122
SHR (Shift Right) ....................................................................................... 123
SHRA (Shift Right Arithmetically)........................................................... 124
SUB (Subtract) ........................................................................................... 125
XCH (Exchange)......................................................................................... 127
XOR (Exclusive Or) .................................................................................... 128
XOR_R (Exclusive Or and Return) ........................................................... 129
Chapter 7. Neuron Assembler Directives.......................................................131
Overview of the Assembler Directives ...................................................... 132
APEXP (Application Symbol Export)........................................................ 134
DATA.B (Reserve Initialized Memory) ..................................................... 135
ELSE (Conditional Assembly)................................................................... 137
END (Assembly Control) ........................................................................... 138
ENDIF (Conditional Assembly) ................................................................ 139
EQU (Equate Symbol)................................................................................ 140
ERROR (Conditional Assembly) ............................................................... 141
EXPORT (Export Symbol) ......................................................................... 142
IF (Conditional Assembly)......................................................................... 143
IFDEF (Conditional Assembly) ................................................................. 144
IFNDEF (Conditional Assembly) .............................................................. 145
viii
_log16 (Logical Value, 16 Bit).................................................................... 175
_log8 (Logical Value, 8 Bit)........................................................................ 175
_lognot16 (Negated Logical Value, 16 Bit) ............................................... 176
_lognot8 (Negated Logical Value, 8 Bit) ................................................... 176
_lshift16_add16 (Left Shift and Add, 16 Bit) ........................................... 177
_lshift8_add16 (Left Shift and Add, Converts 8 Bits to 16 Bits)............. 177
_lshift8by1_add16 (Left Shift By 1 and Add, Converts 8 to 16 Bits)...... 177
_lshift8by2_add16 (Left Shift By 2 and Add, Converts 8 to 16 Bits)...... 178
_max16 (Maximum Value, 16 Bit) ............................................................ 178
_max16s (Maximum Signed Value, 16 Bit) .............................................. 178
_max8 (Maximum Value, 8 Bit) ................................................................ 179
_max8s (Maximum Signed Value, 8 Bit) .................................................. 179
_memcpy (Copy Memory) .......................................................................... 180
_memcpy1 (Copy Memory from Offset) .................................................... 180
_memset (Set Memory) .............................................................................. 180
_memset1 (Set Memory at P0) .................................................................. 181
_min16 (Minimum Value, 16 Bit) ............................................................. 181
_min16s (Minimum Signed Value, 16 Bit) ............................................... 181
_min8 (minimum Value, 8 Bit).................................................................. 182
_min8s (Minimum Signed Value, 8 Bit) ................................................... 182
_minus16s (Negative Signed Value, 16 Bit) ............................................. 182
_mod8 (Modulo, 8 Bit)................................................................................ 183
_mod8s (Modulo Signed, 8 Bit).................................................................. 183
_mul16 (Multiply, 16 Bit) .......................................................................... 183
_mul16s (Multiply Signed, 16 Bit) ............................................................ 184
_mul8 (Multiply, 8 Bit) .............................................................................. 184
_mul8s (Multiply Signed, 8 Bit) ................................................................ 185
_mul_8_16 (Multiply, 8 Bit to 16 Bit) ....................................................... 185
_muls_8_16 (Multiply Signed, 8 Bit to 16 Bit) ......................................... 185
_mul8l (Multiply, 8 Bit with 16 Bit Result).............................................. 186
_mul8ls (Multiply Signed, 8 Bit with 16 Bit Result) ............................... 186
_not16 (Not, 16 Bit).................................................................................... 186
_or16 (Or, 16 Bit)........................................................................................ 187
_pop (Pop from TOS and Push to Offset).................................................. 187
_pop1 (Pop from TOS and Push Short to Offset) ..................................... 187
_popd (Pop from TOS and NEXT, Push to Offset, 16 Bit) ....................... 188
_popd1 (Pop from TOS and NEXT, Push Short to Offset, 16 Bit)........... 188
_push (Push from Offset to TOS) .............................................................. 189
_push1 (Push Short from Offset to TOS).................................................. 189
_push4 (Copy Top 4 Bytes of Stack, Push to Stack) ................................ 189
_pushd (Push from Offset to TOS and NEXT, 16 Bit) ............................. 190
_pushd1 (Push Short from Offset to TOS and NEXT, 16 Bit)................. 190
_r_shift16 (Right Shift, 16 Bit).................................................................. 190
_r_shift16s (Right Shift Signed, 16 Bit).................................................... 191
_r_shift8 (Right Shift, 8 Bit)...................................................................... 191
_r_shift8_<n> (Right Shift <n>, 8 Bit)...................................................... 191
_r_shift8s (Right Shift Signed, 8 Bit)........................................................ 192
_register_call (Call Function from Register) ............................................ 192
_sign_extend16 (Convert 8 Bit to 16 Bit, Preserve Sign) ........................ 193
_sub16 (Subtract, 16 Bit) ........................................................................... 193
_sub16s (Subtract Signed, 16 Bit)............................................................. 193
_xor16 (Exclusive OR, 16 Bit) ................................................................... 194
x
1
Introduction
2 Introduction
• Chapter 8, System-Provided Functions, on page 159, describes system-
provided functions for various arithmetical or logical operations or for
stack management.
This book also contains several appendixes with additional information.
Command Usage
The following command usage notes apply to running the nas command:
• If no command switches or arguments follow the command name, the tool
responds with usage hints and a list of available command switches.
• Most command switches come in two forms: A short form and a long
form.
Examples:
Short form: nas –l …
Examples:
nas --listing=yes abc.ns
nas --listing abc.ns
• Command switches can appear at any location within the command line
or in any order (on separate lines) within a script.
4 Introduction
Table 1. Command Switches for the nas Command
Command Switch
Short
Long Form Form Description
Assembler Files
The Neuron Assembler requires a single source input file, and produces one
object output file, and optionally also produces a listing output file. The
descriptions and requirements for native Neuron assembly files also apply to
Neuron assembly source files that are used with the Neuron C Compiler’s
#pragma include_assembly_file directive.
The following sections describe these files.
Source Files
A source file (the input file) contains zero, one, or more lines of Neuron assembly
source code. This source code can consist of Neuron assembly instructions or
Neuron assembly directives.
The following sections describe the file naming convention and file format for
source files.
Naming Convention
A file that contains Neuron assembly source can have any file name that is
allowed by the operating system, but the use of the .ns file extension is
recommended. If no file name extension is provided on the command line, the
Neuron Assembler assumes an .ns extension.
A file that is used with the Neuron Librarian (NLIB) must follow the Windows
8.3 naming convention (for example, filename.ext, where filename is no more
6 Introduction
than eight characters and ext is one of the allowable extensions for Neuron
assembly files, such as .ns and .no). Spaces are not allowed in the file name or
the extension.
File Format
Each line in an assembly source file is independent, with no line-continuation
character or terminator character. An assembly source line can contain one of
the following:
• A blank line (zero, one, or more whitespace characters (blanks, spaces, or
tabs), followed by a newline or carriage-return character). The Neuron
Assembler ignores blank lines.
• A comment. A comment starts with a semicolon character (;) and ends
with a newline or carriage-return character. The Neuron Assembler
ignores all characters after the semicolon.
• A label. A label is an identifier for an instruction, directive, or segment.
• An assembly instruction, with zero, one, or more arguments. The line
with the instruction can begin with an optional label, and can also end
with an optional comment.
• An assembler directive. The line with the directive can begin with an
optional label (if the directive allows one), and can also end with an
optional comment.
If the line contains a label, it must begin in the first column. If the line contains
an instruction or directive without a label, the instruction or directive must begin
beyond the first column. A comment can begin in any column, but always
extends to the end of the line.
Spaces or tabs separate the label, the instruction mnemonic or directive, and the
first argument (if any). Multiple arguments are separated by spaces, tabs, or
commas, depending on the syntax of the particular instruction or directive.
Thus, the basic format for an assembly source line is:
label instruction operand ; comment
label DIRECTIVE argument ; comment
By convention, instruction mnemonics are specified in lower case and directives
are specified in upper case.
Output Files
The Neuron Assembler produces the following output files:
• An object output file
• An optional listing output file
The object output file contains assembled code, ready for the Neuron Linker.
Typically, the object output file has the same name as the input source file, but
has an .no file extension.
The listing output file contains the source instructions, directives, and comments
from the source input file, and includes the instruction opcodes and addressing
information (including symbolic or segment-relative addresses that are resolved
8 Introduction
present, they take the form of either literals or identifiers for data items.
Operand identifiers are either reserved names of registers or stack
pointers, or are assumed to be data items declared in another part of the
file. Depending on the instruction, two operands are separated by either
white space or a comma, and depending on the addressing mode, they can
be enclosed in square brackets ([ ]) or combined with other special
characters.
• The terminating semicolon and comment are optional, but highly
recommended for most assembly source lines. See Documenting Changes
to the Stack on page 40 for additional comment recommendations.
The following sections provide additional information about these syntax
elements.
Labels
A label is an identifier for an instruction, directive, or segment. The Neuron
Assembler defines label values by their position in the source file relative to the
instructions and directives. A relocatable label has no absolute value until link
time.
A label can comprise either lower or upper case letters a..z or A..Z, the digits 0..9,
and any of the following special characters: underscore (_), period (.), or percent
(%). The first character cannot be one of the numeric digits, nor can it be the
period (.) character. Labels are case sensitive.
Note that Neuron Assembler keywords are reserved and cannot be used for
labels, regardless of case. Reserved words include instruction mnemonics,
assembler directives, or register names. See Appendix C, Reserved Keywords, on
page 219, for a list of assembler keywords.
Assembly Instructions
An assembly instruction is a keyword that represents a class of machine
operation codes (opcodes). The specific opcode is defined by the instruction,
combined with its operands.
An assembly instruction can comprise either upper or lower case characters a..z
or A..Z and the underscore character (_). Assembly instructions are not case
sensitive.
Each instruction accepts zero, one, or two operands (which can include special
characters).
An exclamation character (!) can precede an instruction. This character indicates
that any warning that results from using the -w command line switch is
suppressed for that instruction. Using this character can be useful if the -w
switch warns of something that is intentional or otherwise unavoidable.
See Chapter 6, Neuron Assembly Language Instruction Statements, on page 59,
for a description of all supported instructions.
Literal Constants
A literal constant is a numeric value, such as 12 or 173. The Neuron Assembler
supports numeric values in any of four radixes (bases): binary (base 2), octal
(base 8), decimal (base 10), and hexadecimal (base 16).
The RADIX directive specifies the default radix for an assembly language
function (see RADIX (Default Radix) on page 154). To explicitly specify the radix
for a literal constant, prefix the constant’s value with one of the following letters
and the apostrophe character (‘):
• b’ for binary numbers
• o’ for octal numbers
• d’ for decimal numbers
• h’ for hexadecimal numbers
You can specify the radix letter in either upper or lower case. You can specify
leading zeros for any literal constant without changing its value. However, if the
default radix is hexadecimal, a literal constant must always begin with a numeric
digit or leading zero.
For example, you can specify the decimal value 123 as b’01111011, o’173, d’123,
or h’7b.
Symbols
A symbol is one or more consecutive alphanumeric characters. A symbol can
comprise either lower or upper case letters a..z or A..Z, the digits 0..9, and any of
the following special characters: underscore (_), period (.), or percent (%). The
10 Introduction
first character cannot be one of the numeric digits, nor can it be the period (.)
character. Symbols are case sensitive.
Note that Neuron Assembler keywords are reserved and cannot be used for
symbols, regardless of case. Reserved words include instruction mnemonics,
assembler directives, or register names. See Appendix C, Reserved Keywords, on
page 219, for a list of assembler keywords.
A label is a type of symbol (see Labels on page 9). A symbol that acts as a label
for the EQU directive is defined explicitly by the directive’s argument expression,
regardless of whether the directive is in a relocatable segment. See EQU (Equate
Symbol) on page 140 for more information about this directive.
You can also define a symbol by importing its value from an assembled object file.
The value of an imported symbol is known only at link time. In addition, you can
export a symbol to make it available at link time to another assembly file or a
Neuron C file. See one of the following sections for more information about
importing and exporting symbols: APEXP (Application Symbol Export) on page
134, EXPORT (Export Symbol) on page 142, and IMPORT (Import External
Symbol) on page 146.
Expressions
Some Neuron assembly instructions accept expressions as arguments. The
simplest expression consists of a literal constant or a symbol. However, the
assembler also accepts expressions for which the value is the result of a
computation. The computation can involve multiple literal constants or symbols
and use a variety of operators. If the value of an expression is not computable at
assembly time, the assembly object output file must contain sufficient
information for the Neuron Linker to compute the expression value at link time.
General Expressions
The assembler supports the following types of operators for creating general
expressions:
• Unary
• Binary
• Special operators
All expression values are 16-bit expressions, and all operators produce 16-bit
results. All operations use unsigned two’s-complement arithmetic. You can add
parentheses to an expression to syntactically determine its boundaries without
changing its value.
Unary operators are symbols that appear in front of an expression and perform
an operation on the value of that expression. Table 2 lists the unary operators.
Table 2. Unary Operators
Operator Description
Operator Description
+ Two’s-complement addition
- Two’s-complement subtraction
* Multiplication
| Bitwise OR
^ Bitwise Exclusive OR
The special operators are symbols that instruct the Neuron Assembler to perform
a specific action. The values of expressions that use special operators are
computed at link time. Table 4 lists the special operators.
Table 4. Special Operators
Operator Description
A special operator function begins with the @ character, followed by the function
name, and then by a parenthesized expression. The function names can be
specified in either lower or upper case. Table 5 lists the special operator
functions.
Table 5. Special Operator Functions
Function Description
12 Introduction
Example:
The following example demonstrates the use of the @NEAR expression. The
example implements a one-byte variable in the RAMNEAR segment, and a
function named Example that increments this global variable.
; open RAMNEAR segment, declare one byte
; uninitialized variable
SEG RAMNEAR
ORG
myVariable EXPORT
RES 1
SEG CODE
ORG
pNear EQU 1
Example APEXP ; ( -- )
push [pNear][@NEAR(myVariable)]
inc
pop [pNear][@NEAR(myVariable)]
ret ; return to caller
Constant Expressions
A constant expression is a general expression that is computable at assembly
time and has a constant value in an appropriate range for the specified
instruction or directive.
An expression that is not constant is one that is computable only at link time or
that has a variable value at runtime. Such symbols must be designated as
imported symbols.
Important: An expression that uses either the * or @NEAR special operator
cannot be a constant expression.
When using negative constants, or expressions that yield negative results, in a
byte context, you must use the @LB special operator (or specify the --autotrunc
[-a] command-line switch) to obtain a one-byte value for the value. For example,
use PUSH #@LB(-1) instead of PUSH #-1 (the latter will fail assembly).
Displacements
A displacement is a relative address value. A displacement can be interpreted as
a signed or unsigned number, depending on the instruction with which the
displacement appears.
To compute the absolute address value, add the displacement (using either
signed or unsigned arithmetic, as appropriate) to the absolute address of the
instruction that contains the displacement.
Comments
A comment is part of an assembly source line that provides useful information to
the code developer. The Neuron Assembler ignores comments. A comment starts
with a semicolon character (;) and ends with a newline or carriage-return
character.
Recommendation: Use comments to document changes to the data and return
stacks. See Documenting Changes to the Stack on page 40 for a recommended
method of documenting stack changes.
Assembler Directives
An assembler directive provides information to the Neuron Assembler to control
or affect the processing of the remainder of the assembly file.
The directives have syntax analogous to the assembly instructions. Most
directives require arguments, which are similar to the operands of the assembly
instructions.
See Chapter 7, Neuron Assembler Directives, on page 131, for more information
about the Neuron Assembler directives.
14 Introduction
2
Neuron Architecture for Neuron
Assembly Programming
CPU Registers
The Neuron architecture provides the following types of CPU registers for
Neuron assembly language programming:
• General-purpose 16-bit pointer registers and 8-bit data registers
• A flag register
• An instruction pointer
• A base-page register
• A data-stack pointer register (8-bit, BP-relative)
• A register containing the element on top of the data stack (TOS)
• A return-stack pointer register (8-bit, BP-relative)
The following sections describe these registers.
General-Purpose Description
Register
Pointer Registers
The Neuron architecture defines four general-purpose pointer registers, typically
named P0, P1, P2, and P3, as described in Table 7 on page 20. Each of the
pointer registers is 16 bits wide.
A scratch register is one that can be used for temporary data storage by multiple
programs or functions. That is, must typically be saved before and restored after
calling any other function.
Important: Do not modify P1 or P2 in your Neuron assembly functions.
The Neuron Assembly language refers to the general-purpose pointer registers by
their numerical identifier, 0..3. A typical assembly language function defines the
mnemonics P0 to P3 for these registers by using the EQU assembly directive.
Example: The following push instruction uses indirect-relative addressing. This
addressing mode addresses the argument through two operands: a pointer
register and an offset. The effective address of the operation’s argument is
obtained by adding the offset to the contents of the pointer register.
The following instruction pushes the 7th byte from the memory address pointed
to by the P0 register onto the data stack:
push [0][7]
Defining mnemonic names for the general-purpose registers makes this
instruction more easily readable. The following example is equivalent to the
previous one:
P0 EQU 0
push [P0][7]
However, because you define the P0 mnemonic, it carries no special meaning for
the Neuron Assembler. The Assembler does not validate that the mnemonic
refers to the correct or intended register.
For the purpose of clarity (and unless explicitly mentioned to the contrary), all
source code examples in this book assume that the following mnemonics are
defined:
P0 EQU 0
Flag Register
The flag register (FLAGS) is an 8-bit data register that contains the Carry flag
and other flags that are used by the system firmware. The Carry flag is the
most-significant bit of register, as shown in Figure 1.
A Neuron assembly function would rarely use the FLAGS register explicitly;
however, a number of assembly instructions for conditional branches and
arithmetic use the Carry flag from this register.
Instruction Pointer
The instruction pointer (IP) is a 16-bit address register that contains the address
of the next instruction to be executed. It is explicitly modified by call, branch,
and return instructions. Conditional branch instructions (when the branch is not
taken) and all other Neuron assembly instructions implicitly increment the IP by
the size of the instruction.
...
lsb(ret)
msb(ret)
RSP +
General-Purpose
Registers
256 Bytes
TOS BP +23 R15
DSP + NEXT BP +9 R1
DSP -1 ... BP +8 R0
lsb P3
-1..-8 + lsb P1
(DSP-relative DSP -8 msb P1
addressing mode)
lsb P0
BP +0 msb P0
GPR
BP
IP
0x0000
Stacks
Each of the Neuron processors has two stacks: a data stack and a return stack.
The data stack starts at lower addresses and grows toward high memory. The
return stack starts at the top of the base page and grows toward low memory. In
general, it is up to the programmer to ensure that these two stacks do not
overlap.
Data Stack
The data stack is located both in registers and in base page RAM, that is, it
consists of two registers and associated memory. Access to the data stack is
controlled by two registers:
• Top of stack (TOS) is an 8-bit data register that holds the top element of
the data stack.
• Data stack register (DSP) is an 8-bit address register that, when added to
the BP, points to the location in the data stack where the NEXT element
exists. The DSP grows towards higher addresses.
Example: If the values 1, 2, 3, and 4 were on the data stack, and a PUSH
instruction pushed the value 5 onto the data stack, the register contents would be
as shown in Figure 3 on page 23. Note that DSP points to the NEXT element.
4 NEXT
3
TOS 5 2
1
Low
Return Stack
The return stack is also located in base page RAM. It consists of one register and
associated memory. The return stack pointer (RSP) is an 8-bit address register
that is added to the BP to address the top of the return stack. The RSP grows
towards lower addresses.
When calls are executed, the address of the next sequential instruction is stored
on the top of the return stack. This is a 16-bit address stored with the least
significant byte first (that is, the high order byte is pushed last).
Example: If a call were executed from location H'0124, the contents of the return
stack would be as shown in Figure 4 on page 24.
25 Address of
next sequential
instruction after call
01
?? RSP = old RSP - 2
Low
Stack Manipulation
The Neuron assembly language provides the following instructions to manipulate
the data stack:
• PUSH to place data from literal data, an address, or a register into the
TOS element of the stack
• PUSH TOS to copy the value in the TOS element of the stack into the
TOS element (so that it occupies both the TOS and NEXT elements)
• PUSH NEXT to copy the value in the NEXT element to the TOS element
• POP to remove data from the TOS element of the stack and place it into
an address or a register
• ALLOC to allocate space on the stack
• DEALLOC to deallocate space on the stack
• DROP to delete data from the TOS element of the stack or from the
NEXT element of the stack
• INC and DEC to increment and decrement the TOS element on the stack
• ROLC and RORC to rotate the value in the TOS element on the stack left
or right through the Carry flag
• SHL, SHLA, SHR, and SHRA to shift the value in the TOS element on
the stack left or right, either logically or arithmetically
• XCH to exchange the value in the TOS element of the stack with the
value in the NEXT element of the stack
In addition, the Neuron assembly language provides the following instructions to
work with both the data stack and the return stack:
• PUSHPOP to remove the top element of the return stack and place it into
the TOS element of the data stack
Segments
The assembler groups assembly instructions and data blocks into one or more
segments. A segment is a group of assembly instructions and data blocks that
are assembled into consecutive bytes of machine instructions and data, at
consecutive and ascending addresses. That is, when a segment is closed, it is
complete and can be assembled and written to the object output file.
The basic unit for the assembler is a statement, but the basic unit for the linker
is a segment. The linker relocates code and data on a segment-by-segment basis.
During assembly:
• One segment of each type is always open.
• Additional code and data can be added only to an open segment.
• Only one of the open segments is the currently active segment.
• The next assembly instruction or data statement encountered in the
assembly file is added to the active segment.
The segment type does not affect the assembly of the source lines within it, but
does affect the linking of the segment.
The Neuron Assembler supports the segment types listed in Table 8.
Table 8. Segment Types
EECODE For code and constant data that resides in on-chip or off-chip
EEPROM.
EENEAR For data that resides in on-chip EEPROM for Series 3100
devices or mandatory EEPROM for Series 5000 devices. The
size of the EENEAR segment is 256 bytes.
RAMCODE For code and constant data that resides in off-chip RAM.
RAMNEAR For data that resides in on-chip or off-chip RAM. Only Neuron
3150 Chip, FT 3150 Smart Transceiver, and Series 5000
devices support off-chip RAM. The size of the RAMNEAR
segment is 256 bytes.
ROM For code or constant data that resides in the user area of
ROM. Only Neuron 3150 Chip and FT 3150 Smart
Transceiver support a ROM user area.
Notes:
• EEPROM: electrically erasable programmable read-only memory
• RAM: random access memory
• ROM: read-only memory
Figure 5. Off-Chip Memory on the Neuron 3150 Chip, the FT 3150 Smart Transceiver, and
PL 3150 Smart Transceiver
Addressing Modes
The Neuron assembly language supports several addressing modes to specify the
effective address of the argument of an instruction. The syntax for the
instruction operand generally specifies the addressing mode used. For example,
the number sign or hash (#) denotes the immediate addressing mode.
Not all of the addressing modes are available for all instructions. See Chapter 6,
Neuron Assembly Language Instruction Statements, on page 59, for a description
of the instructions and the addressing modes that each supports.
The following sections describe the supported addressing modes.
Immediate
In the immediate addressing mode, the instruction operand is a literal constant
or an expression that resolves to a constant value. In this addressing mode, the
instruction does not reference any registers or memory addresses.
Example:
push #10 ; (10, ...)
pushd #h’98bc ; (bc, 98, ...)
The push #10 instruction pushes the number 10 onto the data stack. The pushd
#h’98bc instruction pushes the most-significant byte (h’98) into NEXT and the
least-significant byte (h’bc) into TOS.
Absolute
In the absolute addressing mode, the instruction operand is an absolute address
in memory or an expression that resolves to an absolute address. Because the
address is an absolute address, the address must be 16 bits.
Example:
push myVariable ; (myVar, ...)
callf myRoutine ; (--)
The push myVariable instruction pushes the value at the location named
myVariable into TOS. The callf myRoutine instruction is a far call to the
myRoutine function.
Direct
In the direct addressing mode, the instruction operand is a register name or an
expression that resolves to a name of a register. In contrast with the relative
addressing modes, the direct addressing mode manipulates the contents of the
register, rather than using the register as a pointer or address.
Example:
push tos ; (TOS, ...)
sub tos,next ; (TOS-NEXT, ...)
Implicit
In the implicit addressing mode, the instruction takes no operands. The
instruction’s arguments are implicit.
Example:
add ; (TOS+NEXT, ...)
pushpop ; ( )
The add instruction adds the contents of TOS with the contents of NEXT, and
places the result in TOS. The pushpop instruction pops the top element from the
return stack and pushes it onto the data stack.
Pointer Direct
In the pointer-direct addressing mode, the instruction operand is a pointer
register (P0, P1, P2, or P3) or an expression that resolves to a pointer register. In
contrast with the relative addressing modes, the pointer-direct addressing mode
manipulates the contents of the register, rather than using the register as a
pointer or address.
Example:
inc [P0] ; ( )
pushd [P3] ; ([P3], ...)
The inc [P0] instruction increments the pointer register P0. The pushd [P3]
instruction pushes the two-byte pointer register P3 onto the data stack.
Indirect Relative
In the indirect-relative addressing mode, the instruction takes two arguments: a
pointer register (P0, P1, P2, or P3) or an expression that resolves to a pointer
register, plus an offset value or expression that resolves to an offset value. The
offset must be in the range 0 to 255. The indirect-relative addressing mode uses
the pointer register plus offset as a pointer or address, rather than using the
contents of the register.
Example:
push [P0][12] ; ( )
pop [P3][4] ; ([P3][4], ...)
The push [P0][12] instruction pushes the 12th byte from the address contained in
the P0 general-purpose pointer register onto the data stack by adding the value
of the second operand (12) to the value of the P0 pointer register. The pop [P3][4]
instruction pops the value in TOS to the location specified as 4 bytes from the
value of the P3 pointer register.
DSP Relative
In the DSP-relative addressing mode, the instruction takes two operands: the
data stack pointer (DSP) and a negative displacement value or expression that
resolves to a negative displacement value. The displacement must be in the
range -1 to -8.
Example:
; (t, n, a, b, c, d, e --)
push [dsp][-1] ; (a, t, n, a, b, c, d, e -- )
pop [dsp][-4] ; (t, n, a, b, c, a, e --)
The push [dsp][-1] instruction pushes the a copy of the first element below NEXT
into TOS (‘a’ in this example). The pop [dsp][-4] instruction pops the value held
in TOS into the fourth stack element below NEXT.
The DSP-relative offset refers to the position before the instruction executes.
See Documenting Changes to the Stack on page 40 for information about the
importance of using stack comments like those in the example to document how
the instructions affect the stacks.
BP Relative
In the BP-relative addressing mode, the instruction argument is a general-
purpose register (R0 to R15). The register name is prefixed by an exclamation
mark (!) to indicate a displacement relative to the base page.
Example:
pop !R0 ; ( )
push !R2 ; ([R2], ...)
The pop !R0 instruction pops the value of TOS into the R0 register (byte 8 of the
base page). The push !R2 instruction pushes the contents of the R2 register (byte
10 of the base page) into TOS.
Indirect
In the indirect addressing mode, the instruction operand is the value that is at
the top of the return stack.
Example:
push [rsp] ; (z, ...)
The push [rsp] instruction pushes the contents of the top of the return stack
(pointed to by RSP) into TOS on the data stack. RSP is not changed.
Another instruction that uses the indirect addressing mode is the dbrnz
instruction, which uses this addressing mode for the branch destination. Its
reference to [RSP] is implied.
Relative
In the relative addressing mode, the instruction takes a relative address for its
operand; a distance rather than an absolute address (some instructions that use
relative addressing take a second operand). The branch destination is computed
by adding the relative address (the distance from the current IP) to the
instruction pointer IP. Some instructions that use relative addressing support
signed distances (that is, support branching in both directions), while other
instructions support relative addressing for positive distances only (only jump
forward).
Unlike absolute addresses, which always require a 16-bit value, relative
addresses support shorter branch distances with the benefit of more compact
machine code, which benefits both the memory footprint and execution time.
Example:
loop ...
brz loop ;
The brz instruction branches to the relative address provided in its operand if the
instruction’s argument, the value in TOS, is zero. If TOS is not zero, this
; do the math:
call _mul16 ; ((piFac*r)(2), r(2), piDiv(2))
brf muldiv ; ( -- carea)
For this implementation, the Neuron assembly file imports the two external
functions: _mul16 and muldiv. The _mul16 function has a preceding underscore
because it is intended for use only with assembly functions. Note that neither
the _mul16 nor the muldiv function names has a percent sign (%) prefix. The
_mul16 system function is not defined in, or designed for, the Neuron C
application name space. The muldiv function is designed for the Neuron C
application name space, but is imported using the system keyword in Neuron C,
which makes the symbol available without the percent sign (%) prefix.
The assembly file then defines two mnemonics for the pi value approximation,
and defines a mnemonic for one of the general-purpose 16-bit registers. This
register temporarily holds a 16-bit value; as long as we do not interpret such a
value as a pointer, these registers can hold any 16-bit value, even though they
are typically used for pointer values.
The %carea function is then declared, using the percent sign (%) prefix, with the
APEXP directive to make this symbol available to the Neuron C application
name space.
The %carea function then sets up the stack for calling the _mul16 and muldiv
functions. Note that because the _mul16 function is located in the near code
area, it can be called with the two-byte CALL instruction, rather than the
slightly less efficient three-byte CALLF instruction.
By setting the stack up correctly, the carea function can branch into the muldiv
function (using the BRF instruction), rather than having to call the muldiv
function (using the CALLF and RET instructions). The carea function can use
the branch instruction because the stack layout for executing the muldiv function
is correct, and contains only the arguments for the muldiv function. Also, the
result type of the carea function is the same as that of the muldiv function.
For more information about the _mul16 function, see _mul16 (Multiply, 16 Bit)
on page 183. For more information about the muldiv() function, see the Neuron C
Reference Guide.
Multi-Byte Values
For multi-byte values, add the element’s size, in bytes, to the value in the
comment. Enclose the size in parentheses following the value itself. For
example, for a 16-bit value named address, the comment would read as
address(2). Therefore, the following two stack-effect comments are equivalent:
; (address(2), …)
; (addresslo, addresshi, …)
Pointer Values
For pointer values, use square brackets ([ ]) to indicate that the value is fetched
from an address. For example, the following stack-effect comment describes one
byte from the location address(2):
; ([address(2)])
Conditional Values
Occasionally, stack elements are conditional. For example, the BRNEQ
instruction drops TOS if the comparison (which is part of the BRNEQ operation)
results in equality, but leaves TOS intact otherwise. Use braces ({ }) to indicate
conditional stack elements. For example, the following comment indicates that
Stack-Transformation Comments
A stack-transformation comment does not apply to an individual operation, but to
an entire function, and typically follows the EXPORT or APEXP directive. The
stack transformation comment shows the expected stack layout at the beginning
of the function (the function arguments), a double hyphen (as a separator), and
the data stack elements of relevance after the function completes.
For example, the stack transformation comment for the assembly version of a
strlen() equivalent function, which takes a pointer argument and returns an
unsigned integer result, would be:
%strlen APEXP ; (pString(2) –- length)
Thus, pString(2) represents the 2-byte function argument, and length
represents the function return value.
You could think of stack transformation comments as the Neuron Assembly
equivalent of Neuron C function prototypes. However, the Neuron Assembler
does not verify the “prototype” against the actual implementation.
Compiled Neuron C
Neuron C Program File
Program
0 warning(s), 0 error(s)
The --listing option causes the Assembler to generate a listing file. The
Neuron Assembler creates two output files:
• checksum.nl (the listing file)
• checksum.no (the object file)
To add an object file to a Neuron library, use the Neuron Librarian command-line
tool (NLIB.EXE).
Example: To add the previously assembled checksum.no file to an existing
library named wwdc.lib, use the NLIB command as shown below:
C:\myDevice> nlib --add wwdc.lib checksum.no
Neuron C Librarian, version 5.00.21, build 0
Copyright (c) Echelon Corporation 1992-2009
0 warning(s), 0 error(s)
You can add multiple files to a library at once, or you can add each file separately
by running the NLIB command several times. You can use the --report option
to inspect an existing library and list its contents.
See Neuron C Compiler for Assembly Programming on page 3 for more
information about compiling a Neuron C program that includes Neuron assembly
code. See Neuron Assembler Command Line Tool on page 3 for more information
about the NAS command. See the Neuron C Programmer’s Guide for more
information about the Neuron Librarian.
void TestCall(void) {
unsigned cs;
cs = Checksum(8, “ABCDEFGH”);
void TestCall(void) {
unsigned cs;
cs = Checksum(8, “ABCDEFGH”);
}
Naming Conventions
Within a Neuron assembly file, declare functions, variables, or any other linkable
item that interfaces with the Neuron C application, with a percent-sign prefix.
This declaration allows the symbol to become part of the Neuron C name space.
To make the symbol and its meaning available to the Neuron C application, you
must provide its C language ‘extern’ specification (for variables and constants) or
its prototype (for functions).
Within a Neuron C file, when you specify an external symbol, the Neuron C
compiler automatically assumes a percent-sign prefix.
Example:
The following example includes an assembly-coded function in a Neuron C
program:
#pragma include_assembly_file “checksum.ns”
extern unsigned Checksum(unsigned, const char*);
The compiler-generated calls to this function from the Neuron C application use
the name %Checksum. Thus, the assembly function must use the %Checksum
label with the APEXP directive:
%Checksum APEXP
... ; function body
ret ; return to caller
The Neuron C Compiler (and its companion tools, such as the Neuron Assembler
or Linker) cannot verify that the prototype (or extern specification that you
provide) actually matches the implementation in the assembly source file. It is
the programmer’s responsibility to ensure that the specification in Neuron C
matches the implementation in Neuron Assembly.
Function Parameters
Typically, an assembly language function is called with parameters. The
compiler pushes function arguments on the stack from right-to-left, so that the
last argument is in the TOS element of the stack. For example, for a function
Calling Conventions
Depending on its use, an assembly language function can use different calling
conventions:
• Assembly-coded functions that are used exclusively by other assembly-
coded functions can employ any appropriate calling conventions for
efficiency or ease of use. For example, a function could pass pointer
arguments through general-purpose pointer registers.
• Any function that calls, or might be called from, code that is generated by
the Neuron C compiler must meet the guidelines described in this section.
To avoid naming collisions, the Neuron C compiler enforces the following naming
convention for global and static data:
• Firmware labels begin with alphabetic characters.
• Firmware labels that are used as interfaces for application code are
prefixed with the underscore (_) character.
• Global labels are prefixed with the percent sign (%). For a Neuron C
variable or function name, the % character is added by the compiler, not
the programmer. For Neuron assembler functions or data that interface
with Neuron C, you must be sure to add the % character for all exported
labels. When importing symbols from a Neuron C application into your
assembly programming project, you must also add the % character for all
imported symbols.
• Static labels are also prefixed with the percent sign (%). A Neuron C
static segment label is the % character plus name of the module (without
the file extension) plus another % character and a unique number
generated by the compiler. For example, an anonymous string “ABC”
argument for a function call within a file named MyDevice.nc might be
named %MYDEVICE%STR1 by the compiler.
Your Neuron assembly functions must follow the same naming convention so that
the functions can interface with Neuron C programs.
Functions exchange arguments and results on the data stack. When calling a
function, the caller pushes the function’s arguments onto the data stack, right to
left, in the order of the Neuron C function prototype.
However, unlike most implementations of the C language, in Neuron C, the
called function, not the caller, is responsible for clearing the arguments off the
data stack prior to returning to the caller. Thus, the called function must leave
only function results (if any) on the data stack.
void Testcall(void) {
unsigned cs;
cs = Checksum(8, “ABCDEFGH”);
}
For this Neuron C code, the Neuron C compiler translates the Testcall function
into the following assembly code (taken from the assembly listing of the compiler-
generated code):
IMPORT %Checksum
SEG CODE
ORG
0000 _%MYDEVICE%STR1 EXPORT
0000 41 42 DATA.B 41,42,43,44,45,46,47,48
0002 43 44 45 46
0006 47 48
0008 00 DATA.B 0
SEG CODE
ORG
0000 %Testcall APEXP ; Function body
0000 C0 ALLOC #1
0001 B5 0000* PUSHD #_%MYDEVICE%STR1
0004 B4 08 PUSH #8
0006 77 0000* CALLF %Checksum
0009 E5 DROP NEXT
000A 7F DEALLOC #1
The listed code performs the following tasks:
1. First, the compiler generates an IMPORT %Checksum statement as
result of the Neuron C function prototype specification.
2. In the first code segment (SEG CODE), the compiler allocates initialized
data for the anonymous constant string variable using the compiler-
generated name _%MYDEVICE%STR1 (the “MYDEVICE” part of the name
is derived from the name of the Neuron C file). The DATA.B directive
Data Representation
The following sections describe how various types of data are represented in the
Neuron assembly language. The data types described include integers,
characters, strings, multi-byte objects, arrays, structures, unions, and bitfields.
Multi-Byte Values
Multi-byte scalar objects (such as signed and unsigned long integers) are stored
as two consecutive bytes in big endian orientation: the most significant byte is
stored at the lower address. Whenever a long integer is pushed onto the data
stack, the most significant byte is pushed first (or popped last).
Bitfields
Bitfields in a Neuron C structure or union are always packed within one or more
bytes. A single bitfield cannot cross a byte boundary; thus, the maximum bitfield
size is eight bits. The first bitfield in a byte uses the most significant bits, and
subsequent bitfields within the byte use the next most significant bits until all
bits are used.
Anonymous bitfields of non-zero size are supported as placeholders, allowing for
exact positioning of the named bitfields within their container byte. Anonymous
bitfields of size zero always complete the current container.
A new byte is begun when a bitfield is encountered that is too large for the
remaining bits, or when an anonymous bitfield is encountered with size 0, or
when a non-bitfield object is encountered.
Example:
The following example shows how to set up and call a diagnosis function that is
defined in Neuron C.
The Neuron C definition for this function is:
void diagnosis(unsigned currentValue,
unsigned remainingSize,
const char* remainingData){
...
}
The following Neuron assembly language code shows how to call this Neuron C
function:
pData EQU 0
IFDEF _DEBUG
IMPORT %diagnosis ; (cs, size, pData -- )
... ; (cs) R(size)
pushd [pdata] ; (pData(2), cs) R(size)
pushd [pData] ; (pData(2), pData(2), cs) R(size)
push [rsp] ; (size, pData(2), pData(2), cs) R(size)
push [dsp][-4] ; (cs, size, pData(2), pData(2), cs) R(size)
callf %diagnosis ; (pData(2), cs) R(size)
popd [pData] ; (cs) R(size)
ENDIF
Thus, the Neuron assembly code performs the general steps for calling the
Neuron C function:
1. Import the diagnosis symbol (IMPORT %diagnosis).
2. Preserve all general-purpose registers in use (pushd [pData]).
3. Push the function arguments onto the data stack, from right to left
(pushd [pData], push [rsp], push [dsp][-4]).
4. Call the diagnosis function (callf %diagnosis).
5. Process optional function results and clear the stack frame. This example
does not show processing for function results.
6. Restore general-purpose registers saved (popd [pData]).
This implementation uses conditional assembly based on a predefined symbol
_DEBUG. Using conditional assembly allows this function to be called only
within debug builds. However, conditional assembly is not available with
Neuron C programs; you must create a Neuron assembly code library and link
the library with the Neuron C program.
The assembly function pushes the pointer register P0 on to the stack twice
(pushd [pData]): once to save the register content across the call to the diagnosis
function, and a second time to provide the current pointer value to the diagnosis
function itself. An alternative implementation could push the pointer once
(pushd [pData]), then duplicate the value on the stack using two push next
pData EQU 0
void TestCall(void) {
unsigned cs;
cs = Checksum(8, “ABCDEFGH”);
}
The Neuron C compiler reads the Checksum function arguments from right to
left, and pushes them onto the stack so that the first argument (unsigned) is in
TOS, the top of the stack. When the function completes, the compiler expects the
function result (cs) on the data stack. Thus, the function must digest all
arguments and local variables before returning to the caller.
The #pragma include_assembly_file compiler directive instructs the compiler to
include the assembly source file, but the compiler does not parse the included
assembly file. Likewise, the compiler does not analyze the included assembly
code to ensure that there is an appropriate Neuron C function prototype for the
assembly implementation. You must provide a proper function prototype,
typically in a header file. In addition, you muse ensure that the number, order,
and type of arguments, and any results, are correct, both in the Neuron C
function prototype and in the Neuron assembly implementation.
Note that certain Neuron C specifications have no direct correspondence in a
Neuron assembly function. For example, the declaration of the pData argument
as const (a variable pointer to constant data) is correct from a C language point of
view, but it is your responsibility in the assembly function to ensure that this
data is not modified.
Arithmetic Operations
ADD Add
DEC Decrement
DIV Divide
INC Increment
MUL Multiply
SUB Subtract
Logical Operations
AND And
NOT Not
OR Or
XOR Exclusive or
Stack Manipulation
ALLOC Allocate
XCH Exchange
BR Branch
Other Operations
NOP No operation
The following sections describe each of the Neuron Assembler instructions. The
description for each instruction includes a table with the following information:
• The hexadecimal representation of the instruction’s opcode
The opcode is the part of a machine instruction that informs the processor
of the type of operation to be performed and the type of data to be used.
The first byte of an instruction is its opcode, and remaining bytes are its
data. Some Neuron machine instructions have variable opcodes because
data is included in the opcode so that the instruction’s size can be as
small as possible.
• The size of the instruction, in bytes
Each machine instruction requires either one, two, or three bytes of
Syntax:
The ADC instruction requires no operands:
ADC
Table 10 describes the attributes of the ADC instruction.
Table 10. ADC Instruction
Example:
The following example performs the operation 2+3. The example assumes that
the Carry flag is set.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
adc ; (6, -, -)
The value of TOS after this code executes is 6 because 2+3+Carry = 6. In this
case, the value of the Carry flag is used for the addition, and then modified
(cleared) because the unsigned addition did not require an extra carry bit.
Syntax:
In implicit addressing mode, the ADD instruction requires no operands:
ADD
In immediate addressing mode, the ADD instruction instruction requires one
operand:
ADD #number
The number sign or hash (#) is required to specify the immediate value.
Table 11 describes the attributes of the ADD instruction.
Table 11. ADD Instruction
ADD 50 1 4 Modified
Example:
The following example performs the operation 2+3+4.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
add ; (5, -, -)
add #4 ; (9, -, -)
The value of TOS after the first ADD instruction is 5 because 2+3 = 5. The ADD
#4 instruction adds 4 to TOS (4+5), so that TOS then contains 9. The value of the
Carry flag is modified (cleared) after each of the add instructions because neither
unsigned addition requires an extra carry bit.
Syntax:
The ADD_R instruction requires no operands:
ADD_R
Table 12 describes the attributes of the ADD_R instruction.
Table 12. ADD_R Instruction
ADD_R 5C 1 7 Modified
Example:
The following example performs the operation 2+3 and performs the return-from-
call operation. The example assumes that the return stack contains the address
of the caller to which the ADD_R instruction returns.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
add_r ; (5, -, -)
The value of TOS after this code executes is 5 because 2+3 = 5. The value of the
Carry flag is modified (cleared) because the unsigned addition did not require an
extra carry bit. After completing the addition, the ADD_R instruction performs
the return-from-call operation.
Syntax:
The ALLOC instruction requires a single operand to specify the number of bytes
to allocate on the data stack:
ALLOC #number
The value of number must be in the range 1..8. The number sign or hash (#) is
required to specify the immediate value.
Table 13 describes the attributes of the ALLOC instruction.
Table 13. ALLOC Instruction
ALLOC #1 C0 1 3 None
ALLOC #2 C1 1 3 None
ALLOC #3 C2 1 3 None
ALLOC #4 C3 1 3 None
ALLOC #5 C4 1 3 None
ALLOC #6 C5 1 3 None
ALLOC #7 C6 1 3 None
ALLOC #8 C7 1 3 None
Example:
The following example allocates two bytes on the data stack. The resulting
values of TOS and NEXT are not specified.
alloc #2 ; (a, b)
Syntax:
In implicit addressing mode, the AND instruction requires no operands:
AND
In immediate addressing mode, the AND instruction requires one operand:
AND #number
The number sign or hash (#) is required to specify the immediate value.
Table 14 describes the attributes of the AND instruction.
Table 14. AND Instruction
AND 51 1 4 Cleared
Example:
The following example performs the operation 2 AND 3 AND 4.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
and ; (2, -, -)
and #4 ; (0, -, -)
The value of TOS after the first AND instruction is 2 because 2 AND 3 = 2. The
AND #4 instruction performs a logical AND of 4 with TOS (4 AND 2), so that
TOS then contains 0.
Syntax:
The AND_R instruction requires no operands:
AND_R
Table 15 describes the attributes of the AND_R instruction.
Table 15. AND_R Instruction
AND_R 5D 1 7 Cleared
Example:
The following example performs the operation 2 AND 3 and performs the return-
from-call operation. The example assumes that the return stack contains the
address of the caller to which the AND_R instruction returns.
pushs #2 ; (2, -, -)
pushs #3 ; (3, -, -)
and_r ; (2, -, -)
The value of TOS after this code executes is 2 because 2 AND 3 = 2. After
completing the logical and operation, the AND_R instruction performs the
return-from-call operation.
Syntax:
The BR instruction requires a single operand to specify the displacement or label:
BR displacement
BR label
Table 16 describes the attributes of the BR instruction.
Table 16. BR Instruction
BR 71 2 2 None
Example:
The following example shows two functions that share a common set of code. The
BR instruction branches unconditionally from the end of one function to the
Common label to run the common code.
Sub_B ... ; subroutine B
br Common
Sub_A ... ; subroutine A
Common ... ; common code
ret ; return to caller
Syntax:
The BRC instruction requires a single operand to specify the displacement or
label:
BRC displacement
BRC label
Table 17 describes the attributes of the BRC instruction.
Table 17. BRC Instruction
BRC 33 2 2 Used
Example:
The following example assumes that TOS and NEXT have data values to be
added. The ADD instruction adds them and sets the Carry flag for the unsigned
addition. The BRC instruction branches to the Ovflw label if the Carry flag is
set, otherwise the program continues. The BR instruction ensures that the code
at the Ovflw label is only run when needed.
add ; (result, -, -)
brc Ovflw
...
br Common
Ovflw ... ; handle Carry set condition
Common ...
Syntax:
The BRF instruction requires a single operand to specify the address or label:
BRF address
BRF label
Table 18 describes the attributes of the BRF instruction.
Table 18. BRF Instruction
BRF 75 3 4 None
Example:
The following example uses the BRF instruction to branch into a library function,
whose address is unknown until the program is compiled and linked.
brf LibRoutine ;
Syntax:
The BRNC instruction requires a single operand to specify the displacement or
label:
BRNC displacement
BRNC label
Table 19 describes the attributes of the BRNC instruction.
Table 19. BRNC Instruction
BRNC 32 2 2 Used
Example:
The following example assumes that TOS and NEXT have data values to be
added. The ADD instruction adds them and sets the Carry flag for the unsigned
addition. The BRNC instruction branches to the Ok label if the Carry flag is not
set, otherwise the program continues. The BR instruction ensures that the code
at the Ok label is only run when needed.
add ; (result, -, -)
brnc Ok
... ; handle Carry set condition
br Common
Ok ...
Common ...
Syntax:
The BRNEQ instruction requires two operands: one to specify the number for
comparison and one to specify the displacement or label:
BRNEQ #number, displacement
BRNEQ #number, label
The number sign or hash (#) is required to specify the immediate value.
Table 20 describes the attributes of the BRNEQ instruction.
Table 20. BRNEQ Instruction
BRNEQ 76 3 4 None
(if branch is
taken)
6
(if branch is not
taken)
Example:
The following example tests the argument in TOS for the ASCII codes 65 (for ‘A’),
66 (for ‘B’), and 67 (for ‘C’), and calls a related function for each. The example
shows one possible assembly implementation of a C-language switch/case
construct.
Example APEXP ; (argument -- )
Syntax:
The BRNZ instruction requires a single operand to specify the displacement or
label:
BRNZ displacement
BRNZ label
Table 21 describes the attributes of the BRNZ instruction.
Table 21. BRNZ Instruction
BRNZ 72 2 4 None
Example:
The following example assumes that the stack already has an array of data
values from which we want to process non-zero values and skip zero values.
search brnz numFnd
br search ; skip zeros
numFnd ...
Syntax:
The BRZ instruction requires a single operand to specify the displacement or
label:
BRZ displacement
BRZ label
Table 22 describes the attributes of the BRZ instruction.
Table 22. BRZ Instruction
BRZ 73 2 4 None
Example:
The following example assumes that the stack already has an array of data
values from which we want to process zero values and skip non-zero values.
search brz zeroFnd
br search ; skip non-zeros
zeroFnd ...
Syntax:
The CALL instruction requires a single operand to specify the near address:
CALL near_address
Table 23 describes the attributes of the CALL instruction.
Table 23. CALL Instruction
CALL 00 to 1F 2 6 None
Example:
The following example calls the _add_8_16f system function to add an 8-bit value
with a 16-bit value.
call _add_8_16f ;
Syntax:
The CALLF instruction requires a single operand to specify the far address:
CALLF address
Table 24 describes the attributes of the CALLF instruction.
Table 24. CALLF Instruction
CALLF 77 3 7 None
Example:
The following example calls a function named %PTRINC. This example assumes
that the called function resides at a high memory address.
callf %PTRINC ; calculate next ptr bytes
...
%PTRINC APEXP ; function body
...
ret ; return to caller
Syntax:
The CALLR instruction requires a single operand to specify the displacement:
CALLR displacement
Table 25 describes the attributes of the CALLR instruction.
Table 25. CALLR Instruction
CALLR 74 2 5 None
Example:
The following example calls a local function named myFilter. This example
assumes that the called function is a nearby function.
callr myFilter
...
myFilter ...
ret ; return to caller
Syntax:
The DBRNZ instruction requires a single operand to specify the displacement:
DBRNZ displacement
Table 26 describes the attributes of the DBRNZ instruction.
Table 26. DBRNZ Instruction
DBRNZ 70 2 5 None
Example:
The following example calls a function named do_it repeatedly, until the value n
on the return stack is zero. Thus, this example implements a do until loop
construct. This example assumes that the called function resides at a high
memory address or is a system function.
Example APEXP ; ( n -- )
poppush ; ( ) R(n)
loop_body ; ( ) R(n)
callf do_it ; ( ) R(n)
dbrnz loop_body ; ( ) R({n})
ret ; ( ) R( )
Syntax:
The DEALLOC instruction requires a single operand to specify the number of
bytes to allocate on the data stack:
DEALLOC #number
The value of number must be in the range 1..8 The number sign or hash (#) is
required to specify the immediate value.
Table 27 describes the attributes of the DEALLOC instruction.
Table 27. DEALLOC Instruction
DEALLOC #1 7F 1 6 None
DEALLOC #2 7E 1 6 None
DEALLOC #3 7D 1 6 None
DEALLOC #4 7C 1 6 None
DEALLOC #5 7B 1 6 None
DEALLOC #6 7A 1 6 None
DEALLOC #7 79 1 6 None
DEALLOC #8 78 1 6 None
Example:
The following example allocates two bytes on the data stack as part of a function,
then at the end of the function, deallocates the two bytes from the data stack and
performs a return from call operation.
Syntax:
The DEC instruction requires no operands:
DEC
Table 28 describes the attributes of the DEC instruction.
Table 28. DEC Instruction
DEC 3F 1 2 Modified
Example:
The following example calls assumes that TOS contains a loop-control variable.
The DEC instruction decrements TOS. When TOS becomes zero, the BRZ
instruction branches to the Done label. As long as TOS is not zero, the BR
instruction branches to the Loop label. Thus, this example implements a for
loop construct.
Loop ... ; loop body
dec ; ( n )
brz Done
br Loop
Done ...
ret ; return to caller
Syntax:
The DIV instruction requires no operands:
DIV
Table 29 describes the attributes of the DIV instruction.
Table 29. DIV Instruction
DIV ED 1 14 None
Example:
The following example performs the division 7/3. Before the DIV instruction
executes, TOS contains 7 and NEXT contains 3. After the DIV instruction
executes, TOS contains 2 (7/3 = 2, with remainder) and NEXT contains 1 (the
remainder).
pushs #3 ; (3, -, -)
pushs #7 ; (7, 3, -)
div ; (2, 1, -)
Syntax:
The DROP instruction requires a single operand to specify which stack element
to drop:
DROP [RSP]
DROP TOS
DROP NEXT
Table 30 describes the attributes of the DROP instruction.
Table 30. DROP Instruction
Example:
The following example calls a function named clearFlags, which requires three
stack arguments. The function consumes one of the arguments, but does not
consume the others. This example uses the DROP TOS instruction twice to clear
the remaining arguments from the data stack.
push #MSG_CLR ; ( flags, *msg_p, len )
call clearFlags ; ( *msg_p, len, - )
drop TOS ; ( len, -- )
drop TOS ; ( -- )
...
clearFlags
...
ret ; return to caller
Syntax:
The DROP instruction requires a single operand to specify which stack element
to drop:
DROP_R TOS
DROP_R NEXT
Table 31 describes the attributes of the DROP_R instruction.
Table 31. DROP_R Instruction
Example:
The following example implements a function named set_mode, which uses
conditional compilation to perform different tasks for different modes. If the
mode MODE1 is defined, the function consumes the TOS value by using the POP
instruction. If the mode MODE1 is not defined, the function uses the DROP_R
TOS instruction to drop the mode argument from the data stack and return to
the function’s caller.
set_mode ; (mode)
IFDEF MODE1
; Limit to 0 or 1
and #h'1
pop _mode ; ()
ret ; return to caller
ELSE
drop_r tos ; ()
ENDIF
Syntax:
The INC instruction for the TOS requires no operands:
INC
The INC instruction for a pointer register requires a single operand to specify the
pointer register:
INC [0]
INC [1]
INC [2]
INC [3]
Table 32 describes the attributes of the INC instruction.
Table 32. INC Instruction
INC 3E 1 2 Modified
Example:
The following example calls assumes that TOS contains a loop-control variable
with a negative value. The INC instruction increments TOS. When TOS
becomes zero and Carry flag is set, the BRC instruction branches to the Done
label. As long as the Carry flag is not set, the BR instruction branches to the
Loop label. Thus, this example implements a for loop construct.
Loop ... ; loop body
inc ; ( n )
brc Done
br Loop
Syntax:
The MUL instruction requires no operands:
MUL
Table 33 describes the attributes of the MUL instruction.
Table 33. MUL Instruction
MUL EC 1 14 None
Example:
The following example performs the multiplication 18*68 (h’12 * h’44). Before
the MUL instruction executes, TOS contains 18 (h’12) and NEXT contains 68
(h’44). After the MUL instruction executes, TOS contains 200 (h’C8), which are
the low 8 bits of the product, and NEXT contains 4 (h’04), which are the high 8
bits of the product. Together, NEXT:TOS contain the 16-bit product, 1224
(h’04C8).
pushs #@LB(68) ; (h’44, -, -)
pushs #@LB(18) ; (h’12, h’44, -)
mul ; (h’C8, h’04, -)
Syntax:
The NOP instruction requires no operands:
NOP
Table 34 describes the attributes of the NOP instruction.
Table 34. NOP Instruction
NOP 20 1 1 None
Example:
The following example uses the NOP instruction to adjust the timing cycles
required for a specific function. The function causes a delay of 22*count+9 cycles
(not including the initial call to the function). The function assumes that the
count value is already on the data stack.
delay_22n_cycles APEXP
poppush ; () [count]
delay_22n_loop
pushd [msg_p]
popd [msg_p]
rolc
rorc
nop
dbrnz delay_22n_loop
ret ; return to caller
Syntax:
The NOT instruction requires no operands:
NOT
Table 35 describes the attributes of the NOT instruction.
Table 35. NOT Instruction
NOT 3D 1 2 Cleared
Example:
The following example defines a clear_flags function. This function assumes that
flag values to be cleared are in TOS. This function uses the NOT instruction to
invert the passed flag values, then pushes a saved set of flags onto the stack,
performs a logical AND of the inverted flags and the saved flags so that the
passed flag values are cleared, then pops the updated flags to memory.
%clear_flags APEXP ; ( clrMe -- )
not ; ( !clrMe -- )
push flags ; ( flags, !clrMe -- )
and
pop flags ; ( -- )
ret ; return to caller
Syntax:
In implicit addressing mode, the OR instruction requires no operands:
OR
In immediate addressing mode, the OR instruction requires one operand:
OR #number
The number sign or hash (#) is required to specify the immediate value.
Table 36 describes the attributes of the OR instruction.
Table 36. OR Instruction
OR 52 1 4 Cleared
OR #number 5A 2 3 Cleared
Example:
The following example performs the operation 2 OR 3 OR 4.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
or ; (3, -, -)
or #4 ; (7, -, -)
The value of TOS after the first OR instruction is 3 because 2 OR 3 = 3. The OR
#4 instruction performs a logical OR of 4 with TOS (4 OR 3), so that TOS then
contains 7.
Syntax:
The OR_R instruction requires no operands:
OR_R
Table 37 describes the attributes of the OR_R instruction.
Table 37. OR_R Instruction
OR_R 5E 1 7 Cleared
Example:
The following example performs the operation 2 OR 3 and performs the return-
from-call operation. The example assumes that the return stack contains the
address of the caller to which the OR_R instruction returns.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
or_r ; (3, -, -)
The value of TOS after this code executes is 3 because 2 OR 3 = 3. After
completing the logical OR operation, the OR_R instruction performs the return-
from-call operation.
Syntax:
The POP instruction requires one or two operands to specify which data stack
value to pop and the location into which to store the value:
POP [0][offset]
POP [1][offset]
POP [0][TOS]
POP [1][TOS]
POP [2][TOS]
POP [3][TOS]
POP FLAGS
POP RSP
POP DSP
POP [DSP][-8]
POP [DSP][-7]
POP [DSP][-6]
POP [DSP][-5]
POP [DSP][-4]
POP [DSP][-3]
POP [DSP][-2]
POP [DSP][-1]
POP address
POP !8
POP !9
POP !10
POP !11
POP !12
POP !13
POP !14
POP !15
POP !16
POP !17
POP !18
POP !19
POP !20
POP !21
POP !22
POP !23
POP !TOS
The exclamation point (!) is required for the POP !byte-register and POP !TOS
instructions to specify the displacement relative to the base-page register.
Table 38 describes the attributes of the POP instruction.
Table 38. POP Instruction
POP !8 C8 1 4 None
POP !9 C9 1 4 None
Examples:
The following example moves the value 23 from TOS into the element following
NEXT. The instruction overwrites the destination element and consumes TOS;
the remainder of the stack remains unchanged.
Example APEXP ; ( -- )
pushs #1 ; ( 1 )
pushs #2 ; ( 2, 1 )
pushs #3 ; ( 3, 2, 1 )
push #d’23 ; ( d’23, 3, 2, 1 )
pop [dsp][-1] ; ( 3, d’23, 1 )
dealloc #3 ; ( )
Example APEXP ; ( -- )
pushs #0 ; ( 0 )
pop !R0 ; ( )
ret ; return to caller
The following example function clears the N-th byte of the base page. N is in the
range 0 to 255. This example assumes that N is in TOS when calling this
function.
Example APEXP ; ( n -- )
pushs #0 ; ( 0, n )
Syntax:
The POPD instruction requires one operand to specify the pointer register:
POPD [0]
POPD [1]
POPD [2]
POPD [3]
Table 39 describes the attributes of the POPD instruction.
Table 39. POPD Instruction
Example:
The following example preserves the P1 and P2 pointer registers by pushing
them onto the stack before performing operations that could affect these
registers, then popping them from the stack.
P1 EQU 1
P2 EQU 2
popd [P1]
popd [P2]
ret ; return to caller
Syntax:
The POPPUSH instruction requires no operands:
POPPUSH
Table 40 describes the attributes of the POPPUSH instruction.
Table 40. POPPUSH Instruction
POPPUSH E7 1 5 None
Example:
The following example calls a function named do_it repeatedly, until the value n
on the return stack is zero. Thus, this example implements a do until loop
construct. This example assumes that the called function resides at a high
memory address or is a system function.
Example APEXP ; ( n -- )
poppush ; ( ) R(n)
loop_body ; ( ) R(n)
callf do_it ; ( ) R(n)
dbrnz loop_body ; ( ) R({n})
ret ; ( ) R( )
Syntax:
The PUSH instruction requires one or two operands to specify which data stack
value to pop and the location into which to store the value:
PUSH [0][offset]
PUSH [1][offset]
PUSH [2][offset]
PUSH [3][offset]
PUSH [0][TOS]
PUSH [1][TOS]
PUSH [2][TOS]
PUSH [3][TOS]
PUSH FLAGS
PUSH RSP
PUSH DSP
PUSH [DSP][-8]
PUSH [DSP][-7]
PUSH [DSP][-6]
PUSH [DSP][-5]
PUSH [DSP][-4]
PUSH [DSP][-3]
PUSH [DSP][-2]
PUSH [DSP][-1]
PUSH address
PUSH TOS
PUSH NEXT
PUSH #number
PUSH !8
PUSH !9
PUSH !10
PUSH !11
PUSH !12
PUSH !13
PUSH !14
PUSH !15
PUSH !16
PUSH !17
PUSH !18
PUSH !19
PUSH !20
PUSH !21
PUSH !22
PUSH !23
PUSH !TOS
The number sign or hash (#) is required to specify the immediate value for the
PUSH #number instruction. The exclamation point (!) is required for the PUSH
!byte-register and PUSH !TOS instructions to specify the displacement relative to
the base-page register.
Table 41 describes the attributes of the PUSH instruction.
Table 41. PUSH Instruction
PUSH !8 88 1 4 None
PUSH !9 89 1 4 None
The following example loads TOS with the contents of the general-purpose
register R0.
R0 EQU 8
The following example calls the do_it_n function N times, with N >= 0 in TOS.
The number of remaining invocations is passed to the do_it_n function with each
call, which consumes its argument.
Example APEXP ; ( n -- )
poppush ; ( ) R(n)
loop_body ; ( ) R(n)
push [rsp] ; ( n ) R(n)
dec ; ( n-- ) R(n)
callf do_it_n ; ( ) R(n)
dbrnz loop_body ; ( ) R({n})
ret ; ( ) R( )
The following example loads TOS with the content of N-th byte in the base page.
N is passed into this example function in TOS.
Example APEXP ; ( n -– v )
push !tos ; ( n, v -- )
drop_r tos ; ( v )
Syntax:
The PUSHD instruction requires one or two operands to specify the location from
which to push the data:
PUSHD [0]
PUSHD [1]
PUSHD [2]
PUSHD [3]
PUSHD #expression
PUSHD #msb,#lsb
The number sign or hash (#) is required to specify the immediate value for the
PUSHD #expression and PUSHD #msb,#lsb instructions.
Table 42 describes the attributes of the PUSHD instruction.
Table 42. PUSHD Instruction
PUSHD B5 3 6 None
#expression
PUSHD B5 3 6 None
#msb,#lsb
Example:
The following example preserves the P1 and P2 pointer registers by pushing
them onto the stack before performing operations that could affect these
registers, then popping them from the stack.
P1 EQU 1
P2 EQU 2
popd [P1]
popd [P2]
ret ; return to caller
Syntax:
The PUSHPOP instruction requires no operands:
PUSHPOP
Table 43 describes the attributes of the PUSHPOP instruction.
Table 43. PUSHPOP Instruction
PUSHPOP A7 1 5 None
Example:
The following example uses the POPPUSH instruction to save the contents of the
top of the stack so that it can store other values onto the stack below the top
values. It then uses the PUSHPOP instruction to restore the values to the top of
the stack. The comments show the contents of the data stack and the return
stack for each operation.
poppush ; (A--) R(B--)
poppush ; (--) R(A, B--)
pushd [C] ; (A --) R(A, B --)
pushd [D] ; (D, C --) R(A, B --)
pushd [E] ; (E, D, C --) R(A, B --)
pushpop ; (A, E, D, C -- ) R( B -- )
pushpop ; (B, A, E, D, C -- ) R( -- )
Syntax:
The PUSHS instruction requires a single operand to specify the number:
PUSHS #number
The value of number must be in the range 0..7. The number sign or hash (#) is
required to specify the immediate value.
Table 44 describes the attributes of the PUSHS instruction.
Table 44. PUSHS Instruction
PUSHS #0 80 1 4 None
PUSHS #1 81 1 4 None
PUSHS #2 82 1 4 None
PUSHS #3 83 1 4 None
PUSHS #4 84 1 4 None
PUSHS #5 85 1 4 None
PUSHS #6 86 1 4 None
PUSHS #7 87 1 4 None
Example:
The following example performs the operation 2 AND 3 by pushing the
immediate values 2 and 3 onto the stack.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
and ; (2, -, -)
Syntax:
The RET instruction requires no operands:
RET
Table 45 describes the attributes of the RET instruction.
Table 45. RET Instruction
RET 31 1 4 None
Example:
The following example calls a function named clearFlags. After the function
completes, the RET instruction returns from the function, and the function
continues operation with the instruction that follows CALL instruction.
call clearFlags ; ( )
...
br somewhere
clearFlags
...
ret ; return to caller
Syntax:
The ROLC instruction requires no operands:
ROLC
Table 46 describes the attributes of the ROLC instruction.
Table 46. ROLC Instruction
Example:
The following example pushes the number 150 (h’96) onto the data stack, and
then uses the ROLC instruction to rotate the TOS value left through the Carry
flag. This example assumes that the Carry flag is not set (has value 0). After the
ROLC instruction completes, TOS has the value 44 (h’2C) and the Carry flag is
set (has value 1 from bit 7 of the original h’96 in TOS).
push #d’150 ; ( d’150, -- )
rolc ; ( d’44, -- )
Syntax:
The RORC instruction requires no operands:
RORC
Table 47 describes the attributes of the RORC instruction.
Table 47. RORC Instruction
Example:
The following example pushes the number 150 (h’96) onto the data stack, and
then uses the RORC instruction to rotate the TOS value right through the Carry
flag. This example assumes that the Carry flag is not set (has value 0). After the
RORC instruction completes, TOS has the value 75 (h’4B) and the Carry flag is
not set (has value 0 from bit 0 of the original h’96 in TOS).
push #d’150 ; ( d’150, -- )
rorc ; ( d’75, -- )
Syntax:
The SBC instruction requires two operands:
SBC NEXT,TOS
Table 48 describes the attributes of the SBC instruction.
Table 48. SBC Instruction
Example:
The following example performs the operation 3-2. The example assumes that
the Carry flag is not set.
pushs #3 ; (3, -, -)
pushs #2 ; (2, 3, -)
sbc next,tos ; (1, -, -)
The value of TOS after this code executes is 1 because (3+Carry)-2 = 1. In this
case, the value of the Carry flag is used for the subtraction, and then modified
(cleared) because the unsigned subtraction did not require an extra carry bit.
Syntax:
The SBR instruction requires a single operand to specify the displacement or
label:
SBR displacement
SBR label
Table 49 describes the attributes of the SBR instruction. In the table, the
asterisk (*) specifies the current value of the instruction pointer (IP).
Table 49. SBR Instruction
Example:
The following example shows two functions that share a common set of code. The
SBR instruction branches unconditionally from the end of one function to the
Common label to run the common code. This example assumes that the code at
label Sub_A requires fewer than 16 bytes.
Sub_B ... ; subroutine B
sbr Common
Sub_A ... ; subroutine A
Common ... ; common code
ret ; return to caller
Syntax:
The SBRNZ instruction requires a single operand to specify the displacement or
label:
SBRNZ displacement
SBRNZ label
Table 50 describes the attributes of the SBRNZ instruction. In the table, the
asterisk (*) specifies the current value of the instruction pointer (IP).
Table 50. SBRNZ Instruction
Example:
The following example assumes that the stack already has an array of data
values from which we want to process non-zero values and skip zero values.
search sbrnz numFnd
sbr search ; skip zeros
numFnd ...
Syntax:
The SBRZ instruction requires a single operand to specify the displacement or
label:
SBRZ displacement
SBRZ label
Table 51 describes the attributes of the SBRZ instruction. In the table, the
asterisk (*) specifies the current value of the instruction pointer (IP).
Table 51. SBRZ Instruction
Example:
The following example assumes that the stack already has an array of data
values from which we want to process zero values and skip non-zero values.
search sbrz zeroFnd
sbr search ; skip non-zeros
zeroFnd ...
Syntax:
The SHL instruction requires no operands:
SHL
Table 52 describes the attributes of the SHL instruction.
Table 52. SHL Instruction
SHL 3B 1 2 Cleared
Example:
The following example pushes the number 150 (h’96) onto the data stack, and
then uses the SHL instruction to shift the TOS value left. After the SHL
instruction completes, TOS has the value 44 (h’2C) and the Carry flag is cleared.
push #d’150 ; ( d’150, -- )
shl ; ( d’44, -- )
Syntax:
The SHLA instruction requires no operands:
SHLA
Table 53 describes the attributes of the SHLA instruction.
Table 53. SHLA Instruction
SHLA 30 1 2 Modified
Example:
The following example pushes the number 150 (h’96) onto the data stack, and
then uses the SHLA instruction to shift the TOS value left arithmetically. After
the SHLA instruction completes, TOS has the value 44 (h’2C) and the Carry flag
is set to 1 (the previous value of bit 7 in TOS).
push #d’150 ; ( d’150, -- )
shla ; ( d’44, -- )
Syntax:
The SHR instruction requires no operands:
SHR
Table 54 describes the attributes of the SHR instruction.
Table 54. SHR Instruction
SHR 3A 1 2 Cleared
Example:
The following example pushes the number 150 (h’96) onto the data stack, and
then uses the SHR instruction to shift the TOS value right. After the SHR
instruction completes, TOS has the value 75 (h’4B) and the Carry flag is cleared.
push #d’150 ; ( d’150, -- )
shr ; ( d’75, -- )
Syntax:
The SHRA instruction requires no operands:
SHRA
Table 55 describes the attributes of the SHRA instruction.
Table 55. SHRA Instruction
SHRA 3C 1 2 Modified
Example:
The following example pushes the number 150 (h’96) onto the data stack, and
then uses the SHRA instruction to shift the TOS value right arithmetically.
After the SHRA instruction completes, TOS has the value 203 (h’CB) and the
Carry flag is set to 0 (the previous value of bit 0 in TOS).
push #d’150 ; ( d’150, -- )
shra ; ( d’203, -- )
Syntax:
The SUB instruction requires two operands:
SUB NEXT,TOS
SUB TOS,NEXT
Table 56 describes the attributes of the SUB instruction.
Table 56. SUB Instruction
Example:
The following example performs the operation 3-2 and the operation 2-3.
pushs #3 ; (3, -, -)
pushs #2 ; (2, 3, -)
sub next,tos ; (1, -, -)
pushs #3 ; (3, 1, -)
pushs #2 ; (2, 3, 1)
sub tos,next ; (255, 1, -)
Syntax:
The XCH instruction requires no operands:
XCH
Table 57 describes the attributes of the XCH instruction.
Table 57. XCH Instruction
XCH B6 1 4 None
Example:
The following example pushes two numbers onto the data stack, then exchanges
their positions on the stack.
pushs #3 ; (3, -, -)
pushs #2 ; (2, 3, -)
xch ; (3, 2, -)
Syntax:
In implicit addressing mode, the XOR instruction requires no operands:
XOR
In immediate addressing mode, the XOR instruction requires one operand:
XOR #number
The number sign or hash (#) is required to specify the immediate value.
Table 58 describes the attributes of the XOR instruction.
Table 58. XOR Instruction
XOR 53 1 4 Cleared
Example:
The following example performs the operation (2 XOR 3) XOR 4.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
xor ; (1, -, -)
xor #4 ; (5, -, -)
The value of TOS after the first XOR instruction is 1 because 2 XOR 3 = 1. The
XOR #4 instruction performs a logical XOR of 4 with TOS (4 XOR 1), so that TOS
then contains 5.
Syntax:
The XOR_R instruction requires no operands:
XOR_R
Table 59 describes the attributes of the XOR_R instruction.
Table 59. XOR_R Instruction
XOR_R 5F 1 7 Cleared
Example:
The following example performs the operation 2 XOR 3 and performs the return-
from-call operation. The example assumes that the return stack contains the
address of the caller to which the XOR_R instruction returns.
pushs #2 ; (2, -, -)
pushs #3 ; (3, 2, -)
xor_r ; (1, -, -)
The value of TOS after this code executes is 3 because 2 XOR 3 = 1. After
completing the logical XOR operation, the XOR_R instruction performs the
return-from-call operation.
Data Allocation
Segment Control
Conditional Assembly
ELSE, ELSEIF
ENDIF, IF
Control conditional assembly
ERROR
IFDEF, IFNDEF
Other Directives
Syntax:
The APEXP directive requires either a label or an argument, or both.
label APEXP
APEXP symbol
APEXP symbol, symbol, ...
label APEXP symbol
label APEXP symbol, symbol, ...
An argument can be a symbol, or it can be a list of symbols separated by commas.
The argument specifies the symbols to be exported. If there is no argument for
the directive, it must have a label, and the label becomes the exported symbol. If
there are both an argument and a label, the argument specifies the symbols to be
exported and the label is a standard label.
Examples:
The following example exports the label %IOToggle as an external symbol to the
Neuron C application:
%IOToggle APEXP
The following example exports the symbols Flag1 and Flag2 to the Neuron C
application:
InFlags APEXP Flag1, Flag2
Syntax:
The DATA.B directive requires an expression, or a list of expressions separated
by commas. A label is optional.
DATA.B expr
DATA.B expr, expr, ...
label DATA.B expr
label DATA.B expr, expr, ...
The assembler reserves a block of data with a size, in bytes, that matches the
number of expressions in the argument, and initializes each byte to the
corresponding expression's value.
The expr expression can have one of the following forms:
• A numeric expression with a value in the range 0..255. Each number,
which can be a constant of a symbolic expression resolved by the linker,
represents one byte of initialized data. For example:
Examples:
The following example defines a look-up table of three constant bytes:
SEG CODE
ORG
APEXP %lookupTable
Syntax:
The ELSE directive has no arguments and cannot have a label. The ELSE
directive must be preceded by a matching IF, IFDEF, or IFNDEF directive.
ELSE
Syntax:
The END directive has no arguments and does not need a label.
END
Syntax:
The ENDIF directive has no arguments and cannot have a label. The ENDIF
directive must be preceded by a matching IF, IFDEF, or IFNDEF directive.
ENDIF
Syntax:
The EQU directive requires a label and a constant expression argument.
label EQU const_expr
Example:
The following example loads TOS with the content of the general-purpose
register R0 (base page offset value 8), using the mnemonic name “R0”:
R0 EQU 8
Example APEXP ; ( -- r0)
push !R0 ; ( r0 )
ret ; return to caller
Syntax:
The ERROR directive requires a quoted string as its argument, and cannot have
a label.
ERROR “string”
Example:
The following example stops compilation for the current file and displays a
message when neither the AAA nor the BBB conditional compilation symbols are
defined:
IFDEF AAA
…
ELSE
IFDEF BBB
…
ELSE
ERROR “You must define either AAA or BBB”
ENDIF
ENDIF
Syntax:
The EXPORT directive requires either a label or an argument, or both.
label EXPORT
EXPORT symbol
EXPORT symbol, symbol, ...
label EXPORT symbol
label EXPORT symbol, symbol, ...
An argument can be a symbol, or it can be a list of symbols separated by commas.
The argument specifies the symbols to be exported. If there is no argument for
the directive, it must have a label, and the label becomes the exported symbol. If
there are both an argument and a label, the argument specifies the symbols to be
exported and the label is a standard label.
Examples:
The following example exports the label myFunction as a symbol to another
Neuron assembly module:
myFunction EXPORT
The following example exports the symbols Flag1 and Flag2 to a Neuron
assembly module:
InFlags EXPORT Flag1, Flag2
Syntax:
The IF directive requires a constant expression as its argument and cannot have
a label. The IF directive must be followed by a matching ENDIF directive.
IF const_expr
If the expression evaluates to a non-zero value, the Neuron assembler processes
the lines following the directive, up to a matching ELSE directive, if any. If the
expression evaluates to zero, the Neuron assembler skips all of the lines following
the directive, up to a matching ELSE directive, if any, or to the matching ENDIF
directive.
Syntax:
The IFDEF directive requires a symbol as its argument and cannot have a label.
The IFDEF directive must be followed by a matching ENDIF directive.
IFDEF symbol
If the symbol is defined, the Neuron assembler processes the lines following the
directive, up to a matching ELSE directive, if any. If the symbol is not defined,
the Neuron assembler skips all of the lines following the directive, up to a
matching ELSE directive, if any, or to the matching ENDIF directive.
You can define symbols anywhere in the assembly source file using the EQU
directive; see EQU (Equate Symbol) on page 140. You can also provide a symbol
to the assembler using the --define command from the console; see NAS
Command Switches on page 4.
Syntax:
The IFNDEF directive requires a symbol as its argument and cannot have a
label. The IFNDEF directive must be followed by a matching ENDIF directive.
IFNDEF symbol
If the symbol is not defined, the Neuron assembler processes the lines following
the directive, up to a matching ELSE directive, if any. If the symbol is defined,
the Neuron assembler skips all of the lines following the directive, up to a
matching ELSE directive, if any, or to the matching ENDIF directive.
You can define symbols anywhere in the assembly source file using the EQU
directive; see EQU (Equate Symbol) on page 140. You can also provide a symbol
to the assembler using the --define command line on the console; see NAS
Command Switches on page 4.
Syntax:
The IMPORT directive requires a symbol, or a list of symbols separated by
commas. This directive cannot have a label.
IMPORT symbol
IMPORT symbol, symbol, ...
Each symbol in the argument of the IMPORT directive is designated as an
imported symbol.
Syntax:
The INCLUDE directive requires a file name enclosed in double-quote characters
as its argument. The file name can optionally provide an absolute or relative
path to the file.
INCLUDE “string”
The argument is used as a file name to be included in the assembly process, with
the included file appearing in the place of the INCLUDE directive. The file name
must be specified exactly, including extension. There is no default extension, but
the .inc extension is recommended.
Syntax:
The LIBRARY directive requires a library file name enclosed in double-quote
characters as its argument. The file name can optionally provide an absolute or
relative path to the library.
LIBRARY “string”
The argument is used as a library name to be passed to the linker. The library
name must be specified exactly, including extension. There is no default
extension, but the .LIB extension is recommended.
The library reference (the double-quoted string argument) can optionally contain
pre-defined macros. A macro is a keyword, enclosed in single dollar-signs, which
expands to a well-defined value during linking. Using macros allows you to
create code (and library references) that is location-independent and can
assemble and link on different machines.
Table 61 lists the macros that are supported for the LIBRARY directive.
Table 61. System Macros for LIBRARY Directive
Macro Expansion
$IMG$ $LONWORKS$\Images
$STD$ $LONWORKS$\NeuronC\Libraries
Syntax:
The LIST directive has no arguments and cannot have a label.
LIST
Syntax:
The NOLIST directive has no arguments and cannot have a label.
NOLIST
Syntax:
The ORG directive can have one optional argument, but cannot have a label. The
argument, if any, can either be a constant expression or the keyword
CONSTRAINED. The argument specifies the nature of the new segment being
opened.
ORG
ORG const_expr
ORG CONSTRAINED
If no argument is specified, the ORG directive opens a new relocatable segment of
any size.
The value of the const_expr argument is used as the absolute starting address of
the segment. The starting address is passed to the linker. The assembler does
not check the validity of this starting address. However, the linker does check
the validity of the starting address, and checks for address conflicts between
multiple absolute segments.
The CONSTRAINED keyword instructs the linker to relocate the segment so that
it does not cross a Neuron memory page boundary. A Neuron memory page is
256 bytes.
Syntax:
The PAGE directive has no arguments and cannot have a label.
PAGE
Syntax:
The RADIX directive requires an argument for the radix name. This directive
cannot have a label.
RADIX BINARY
RADIX OCTAL
RADIX DECIMAL
RADIX HEX
The radix name can be specified in either lower or upper case.
Syntax:
The RES directive requires a constant expression argument. A label is optional.
RES const_expr
label RES const_expr
The const_expr argument designates the number of bytes to reserve as an
uninitialized data block.
Although the allocated data is uninitialized, the Neuron Chip’s and Smart
Transceiver’s system firmware always clears all RAM to zero as part of the
power-up sequence. Thus, RAM variables do need not to be explicitly initialized
to zero.
Example:
The following example reserves space for a two-byte global variable in the
RAMFAR segment:
SEG RAMFAR
ORG
APEXP %globalVar
%globalVar RES d’2
Syntax:
The SEG directive requires one argument for the type of segment that is being
made active. This directive cannot have a label.
SEG CODE
SEG EECODE
SEG EEFAR
SEG EENEAR
SEG INITCODE
SEG RAMCODE
SEG RAMFAR
SEG RAMNEAR
SEG ROM
SEG SIDATA
Segment type names can be specified in either lower or upper case. See
Segments on page 25 for information about the segment types.
Syntax:
The SUBHEAD directive requires a character or string as its argument and
cannot have a label. The characters that follow the SUBHEAD directive, and any
whitespace that follows the directive, are used as the subheading. The argument
for the directive is terminated by the end of the line or by a semicolon.
SUBHEAD string
If the string argument for the SUBHEAD directive is empty, the subheading line
is cleared. The specified subheading appears on all subsequent pages of the
assembly listing until another SUBHEAD directive is encountered. The
SUBHEAD directive itself does not appear in the listing file.
Example:
This example returns the absolute value of -8.
pushd #-d’8 ; (-d’8, -d’1)
call _abs16 ; (d’8, 0)
Example:
This example returns the absolute value of -8.
push #@lb(-d’8) ; (-d’8)
call _abs8 ; (d’8)
Example:
This example adds 50 to 300.
pushd #d’300 ; (d’44, 1)
pushd #d’50 ; (d’50, 0, d’44, 1)
call _add16 ; (d’94, 1)
Example:
This example adds 50 to 300.
pushd #d’300 ; (d’44, 1)
pushd #d’50 ; (d’50, 0, d’44, 1)
call _add16s ; (d’94, 1)
Example:
This example adds 50 to 300.
pushd #d’300 ; (d’44, 1)
push #d’50 ; (d’50, d’44, 1)
call _add_8_16f ; (d’94, 1)
Example:
This example adds -50 to 300.
pushd #d’300 ; (d’44, 1)
push #@lb(-d’50) ; (-d’50, d’44, 1)
call _adds_8_16 ; (d’250, 0)
Example:
This example performs the operation h’1234 AND h’4321.
pushd #h’1234 ; (h’34, h’12)
pushd #h’4321 ; (h,21, h’43, h’34, h’12)
call _and16 ; (h’20, h’02)
Example:
This example drops 13 bytes from the stack and returns to the caller of
LocalFunction.
callr LocalFunction
; _dealloc returns here.
LocalFunction
push #d’13 ; (13, a, b, c, …, m)
call _dealloc ; ()
Example:
This example decrements 300.
pushd #d’300 ; (44, 1)
call _dec16 ; (43, 1)
Example:
This example divides 8 by 2.
pushd #d’2 ; (d’2, 0)
pushd #d’8 ; (d’8, 0, d’2, 0)
call _div16 ; (d’4, 0)
Example:
This example divides 8 by 2.
pushd #d’2 ; (d’2, 0)
pushd #d’8 ; (d’8, 0, d’2, 0)
call _div16s ; (d’4, 0)
Example:
This example divides 9 by 2.
pushs #d’2 ; (d’2)
push #d’8 ; (d’9, d’2)
call _div8 ; (d’4)
Example:
This example divides 8 by 2.
pushs #d’2 ; (d’2)
push #d’8 ; (d’8, d’2)
call _div8s ; (d’4)
Example:
This example drops 3 bytes from the stack.
pushs #d’3 ; (d’3, a, b, c)
Example:
This example drops 3 bytes from the stack and returns a.
pushs #d’3 ; (3, a, b, c, d)
call _drop_n_preserve_1 ; (a)
Example:
This example drops 3 bytes from the stack and returns a, b.
pushs #d’3 ; (3, a, b, c, d, e)
call _drop_n_preserve_2 ; (a, b)
LocalFunction
pushs #d’3 ; (3, a, b, c, d)
call _drop_n_return_1 ; (a)
Example:
This example drops 3 bytes from the stack and returns a,b to LocalFunction.
callr LocalFunction ; (a, b, c, d, e)
; _drop_n_return_2 returns here. ; (a, b)
LocalFunction
pushs #d’3 ; (3, a, b, c, d, e)
call _drop_n_return_2 ; (a, b)
Example:
This example determines if h’1234 == h’4321.
pushd #h’1234 ; (h’34, h’12)
pushd #h’4321 ; (h,21, h’43, h’34, h’12)
Example:
This example determines if h’12 == h’21.
push #h’12 ; (h’12)
push #h’21 ; (h,21, h’12)
call _equal8 ; (0)
Example:
This example determines if d’10 >= -d’10.
pushd #-d’10 ; (-d’10, -d’1)
pushd #d’10 ; (d’10, 0, -d’10, -d’1)
call _gequ16s ; (1)
Example:
This example determines if d’10 >= -d’10.
push #@lb(-d’10) ; (-d’10)
push #d’10 ; (d’10, -d’10)
call _gequ8s ; (1)
Example:
This example gets the address of stack item c.
push #@lb(-d’3) ; (-3, a, b, c)
call _get_sp ; (&c(2), a, b, c)
Example:
This example increments 300.
pushd #d’300 ; (44, 1)
call _inc16 ; (45, 1)
Stack Transformation: ( -- )
Location: Far
Registers Affected: None
Example:
This example acquires the semaphore, then modifies a global variable, then
releases the semaphore.
import io_iaccess, io_irelease
... ; ( data -- )
callf io_iaccess ; ( data -- )
pop globalVar ; ( -- )
callf io_irelease ; ( -- )
Stack Transformation: ( -- )
Location: Far
Registers Affected: None
Example:
This example acquires the semaphore, then modifies a global variable, then
releases the semaphore. This example assumes that interrupts are running on
the application processor and that the NodeBuilder debugger will be used.
Because you should not use the io_iaccess_wait() function in release target code,
you should modify all instances of io_iaccess_wait() to io_iaccess() after debugging
is complete.
import io_iaccess, io_access_wait, io_irelease
... ; ( data -- )
callf io_iaccess_wait ; ( data -- )
pop globalVar ; ( -- )
callf io_irelease ; ( -- )
Stack Transformation: ( -- )
Location: Far
Registers Affected: None
Example:
... ; ( data -- )
callf io_iaccess ; ( data -- )
pop globalVar ; ( -- )
callf io_irelease ; ( -- )
Example:
This example shifts 16 left 2.
pushs #d’2 ; (d’2)
pushd #d’16 ; (d’16, 0, d’2)
call _l_shift16 ; (d’64, 0)
Example:
This example shifts 16 left 2.
pushs #d’2 ; (d’2)
pushd #d’16 ; (d’16, 0, d’2)
call _l_shift16s ; (d’64, 0)
Example:
This example shifts 16 left 2.
pushs #d’2 ; (d’2)
push #d’16 ; (d’16, d’2)
call _l_shift8 ; (d’64)
Example:
This example shifts 16 left 2.
pushs #d’2 ; (d’2)
push #d’16 ; (d’16, d’2)
call _l_shift8s ; (d’64)
Example:
This example shifts 16 left 3.
push #d’16 ; (d’16)
call _l_shift8_3 ; (d’128)
Example:
This example loads two bytes from address h’f000, which for this example is
assumed to contain h’05 at h’f000 and h’01 at h’f001.
pushd #h’f000 ; (h’00, h’f0)
call _ldP0_fetchl ; (h’01, h’05)
Example:
This example determines if d’10 < d’20.
pushd #d’20 ; (d’20, 0)
pushd #d’10 ; (d’10, 0, d’20, 0)
call _less16 ; (1)
Example:
This example determines if d’10 < -d’10.
pushd #-d’10 ; (-d’10, -d’1)
pushd #d’10 ; (d’10, 0, -d’10, -d’1)
call _less16s ; (0)
Example:
This example determines if d’10 < d’20.
push #d’20 ; (d’20)
push #d’10 ; (d’10, d’20)
call _less8 ; (1)
Example:
This example determines if d’10 < -d’10.
push #@lb(-d’10) ; (-d’10)
push #d’10 ; (d’10, -d’10)
call _less8s ; (0)
Example:
This example returns the logical value for 5.
pushd #d’5 ; (d’5, 0)
call _log16 ; (1)
Example:
This example returns the logical value for 5.
pushs #d’5 ; (d’5)
call _log8 ; (1)
Example:
This example returns the logical inverse of 5.
pushd #d’5 ; (d’5, 0)
call _lognot16 ; (0)
Example:
This example returns the logical inverse of 5.
pushs #d’5 ; (d’5)
call _lognot8 ; (0)
Example:
This example uses a base of h’efe3, an index of 10, and a shift value of 1.
pushd #h’efe3 ; (h’e3, h’ef)
pushs #d’1 ; (1, h’e3, h’ef)
pushd #d’10 ; (d’10, 0, 1, h’e3, h’ef)
callf _lshift16_add16 ; (h’f7, h’ef)
Example:
This example uses a base of h’efe3, an index of 10, and a shift value of 1.
pushd #h’efe3 ; (h’e3, h’ef)
pushs #d’1 ; (1, h’e3, h’ef)
push #d’10 ; (d’10, 1, h’e3, h’ef)
callf _lshift8_add16 ; (h’f7, h’ef)
Example:
This example uses a base of h’efe3 and an index of 10.
pushd #h’efe3 ; (h’e3, h’ef)
push #d’10 ; (d’10, h’e3, h’ef)
callf _lshift8by1_add16 ; (h’f7, h’ef)
Example:
This example uses a base of h’efe3 and an index of 5.
pushd #h’efe3 ; (h’e3, h’ef)
push #d’5 ; (d’5, h’e3, h’ef)
callf _lshift8by2_add16 ; (h’f7, h’ef)
Example:
This example gets the maximum of 8 and 2.
pushd #d’2 ; (d’2, 0)
pushd #d’8 ; (d’8, 0, d’2, 0)
call _max16 ; (d’8, 0)
Example:
This example gets the maximum of -8 and 2.
pushd #d’2 ; (d’2, 0)
pushd #@lb(-d’8) ; (-d’8, -d’1, d’2, 0)
call _max16s ; (d’2, 0)
Example:
This example gets the maximum of 8 and 2.
pushs #d’2 ; (d’2)
push #d’8 ; (d’8, d’2)
call _max8 ; (d’8)
Example:
This example gets the maximum of -8 and 2.
pushs #d’2 ; (d’2)
push #@lb(-d’8) ; (-d’8, d’2)
call _max8s ; (d’2)
Example:
This example copies 4 bytes from h’eff0 to h’eff8.
pushs #d’4 ; (d’4)
pushd #h’eff0 ; (h’f0, h’ef, d’4)
pushd #h’eff8 ; (h’f8,h’ef,h’f0,h’ef,d’4)
call _memcpy ; ()
Example:
This example copies four bytes at offset 3 from within P0 to P3. That is, P3[3] =
P0[3], and so on.
pushs #d’4 ; (d’4)
pushs #d’3 ; (d’3, d’4)
call _memcpy1 ; ()
Example:
This example initializes four bytes at P0 to 33.
pushs #d’4 ; (d’4)
push #d’33 ; (d’33, d’4)
call _memset1 ; ()
Example:
This example gets the minimum of 8 and 2.
pushd #d’2 ; (d’2, 0)
pushd #d’8 ; (d’8, 0, d’2, 0)
call _min16 ; (d’2, 0)
Example:
This example gets the minimum of -8 and 2.
pushd #d’2 ; (d’2, 0)
pushd #@lb(-d’8) ; (-d’8, -d’1, d’2, 0)
call _min16s ; (-d’8, -d’1)
Example:
This example gets the minimum of 8 and 2.
pushs #d’2 ; (d’2)
push #d’8 ; (d’8, d’2)
call _min8 ; (d’2)
Example:
This example gets the minimum of -8 and 2.
pushs #d’2 ; (d’2)
push #@lb(-d’8) ; (-d’8, d’2)
call _min8s ; (-d’8)
Example:
This example negates 2.
pushd #d’2 ; (d’2, 0)
call _minus16s ; (-d’2, -d’1)
Example:
This example performs 8 modulo 2.
pushs #d’2 ; (d’2)
push #d’8 ; (d’8, d’2)
call _mod8 ; (d’0)
Example:
This example performs 8 modulo 2.
pushs #d’2 ; (d’2)
push #d’8 ; (d’8, d’2)
call _mod8s ; (d’0)
Example:
This example multiplies 50 times 40.
pushd #d’50 ; (d’50, 0)
pushd #d’40 ; (d’40, 0, d’50, 0)
call _mul16 ; (d’208, 7)
Example:
This example multiplies 50 times 40.
pushd #d’50 ; (d’50, 0)
pushd #d’40 ; (d’40, 0, d’50, 0)
call _mul16s ; (d’208, 7)
Example:
This example multiplies 50 times 40.
push #d’50 ; (d’50)
push #d’40 ; (d’40, d’50)
call _mul8 ; (d’208, 7)
Example:
This example multiplies 50 times 40.
push #d’50 ; (d’50)
push #d’40 ; (d’40, d’50)
call _mul8s ; (d’208, 7)
Example:
This example multiplies 50 times 40.
pushd #d’50 ; (d’50, 0)
push #d’40 ; (d’40, d’50, 0)
call _mul_8_16 ; (d’208, 7)
Example:
This example multiplies 50 times 40.
pushd #d’50 ; (d’50, 0)
Example:
This example multiplies 50 times 40.
push #d’50 ; (d’50)
push #d’40 ; (d’40, d’50)
call _mul8l ; (d’208, 7)
Example:
This example multiplies 50 times -40.
push #d’50 ; (d’50)
push #@lb(-d’40) ; (-d’40, d’50)
call _mul8ls ; (d’48, d’248)
Example:
This example returns the one’s complement of 8.
Example:
This example determines h’1234 OR h’4321.
pushd #h’1234 ; (h’34, h’12)
pushd #h’4321 ; (h,21, h’43, h’34, h’12)
call _or16 ; (h’35, h’53)
Example:
This example does the equivalent of a POP [DSP][-3].
; (a, b, c, d, e)
push #@lb(-d’5) ; (-5, a, b, c, d, e)
call _pop ; (b, c, d, a)
Example:
This example does the equivalent of two POP [DSP][-3] instructions.
; (a, b, c, d, e, f)
push #@lb(-d’5) ; (-d’5, a, b, c, d, e, f)
callf _popd ; (c, d, a, b)
Example:
This example does the equivalent of two POP [DSP][-9] instructions.
; (a, b, c, d, …, i, j, k, l)
pushs #7 ; (7, a, b, c, …, i, j, k, l)
callf _popd1 ; (c, d, e, f, …, i, j, a, b)
Example:
This example does the equivalent of a PUSH [DSP][-3].
; (a, b, c, d, e)
push #@lb(-d’5) ; (-d’5, a, b, c, d, e)
call _push ; (e, a, b, c, d, e)
Example:
This example does the equivalent of a PUSH [DSP][-9].
; (a, b, c, d, …, h, i, j, k)
pushs #7 ; (7, a, b, c, d, e)
call _push1 ; (k, a, b, c, d, …, j, k)
Example:
This example does the equivalent of two PUSH [DSP][-3] instructions.
; (a, b, c, d, e)
push #@lb(-d’5) ; (-d’5, a, b, c, d, e)
callf _pushd ; (d, e, a, b, c, d, e)
Example:
This example does the equivalent of two PUSH [DSP][-9] instructions.
; (a, b, c, d, …, h, i, j, k)
pushs #7 ; (7, a, b, c, d, e)
callf _pushd1 ; (j, k, a, b, c, d, …, j, k)
Example:
This example shifts 16 right 2.
pushs #d’2 ; (d’2)
pushd #d’16 ; (d’16, 0, d’2)
call _r_shift16 ; (d’4, 0)
Example:
This example shifts -16 right 2.
pushs #d’2 ; (d’2)
pushd #-d’16 ; (-d’16, -d’1, d’2)
call _r_shift16s ; (-d’4, -d’1)
Example:
This example shifts 16 right 2.
pushs #d’2 ; (d’2)
push #d’16 ; (d’16, d’2)
call _r_shift8 ; (d’4)
Example:
This example shifts 16 right 3.
push #d’16 ; (d’16)
call _r_shift8_3 ; (d’2)
Example:
This example shifts -16 right 2.
pushs #d’2 ; (d’2)
push #@lb(-d’16) ; (-d’16, d’2)
call _r_shift8s ; (-d’4)
Example:
This example invokes a function at address h’f423 (by specifying h’f422).
pushd #h’f422 ; (h’f422)
call _register_call ; ()
Example:
This example sign extends -2.
push #@lb(-d’2) ; (h’fe)
call _sign_extend16 ; (h’fe, h’ff)
Example:
This example subtracts 50 from 300.
pushd #d’300 ; (d’44, 1)
pushd #d’50 ; (d’50, 0, d’44, 1)
call _sub16 ; (d’250, 0)
Example:
This example subtracts 50 from 300.
pushd #d’300 ; (d’44, 1)
Example:
This example determines h’1234 XOR h’4321.
pushd #h’1234 ; (h’34, h’12)
pushd #h’4321 ; (h’21, h’43, h’34, h’12)
call _xor16 ; (h’15, h’51)
AND #literal TOS = TOS & LITERAL AND literal with TOS.
C=0
IP = IP+2
BRNEQ #literal, label IF [TOS <> literal] Branch if TOS not equal to
constant. Else drop TOS.
IP = IP+SD
ELSE
TOS = [DSP--]
IP = IP+3
CALLF word-label [RSP--] = LSB (IP+2) Call far function using a 16-bit
address.
[RSP--] = MSB (IP+2)
IP = absolute address
POP absolute [absolute address] = TOS Pops TOS and stores it at the
address absolute address.
TOS = [DSP--]
IP = IP+3
POP [PTR] [D] [[BP+(PTR*2)]+D] = TOS Pops TOS and stores it at the
address held in 2-byte pointer
TOS = [DSP--]
PTR plus unsigned
IP = IP+2 displacement D of 0 to 255.
POP [DSP][D] [BP + DSP + D]= TOS Pop DSP relative with
displacement D.
TOS = [DSP--]
Negative displacement ranging
IP = IP+1
from -1 to -8.
POPD [PTR] [BP + (PTR * 2) + 1]= TOS Pop pointer (2 bytes) from data
stack into pointer PTR.
[BP + (PTR * 2)] = [DSP--]
TOS = [DSP--]
IP = IP+1
00 CALL 1 2 6
01 CALL 1 2 6
02 CALL 1 2 6
03 CALL 1 2 6
04 CALL 1 2 6
05 CALL 1 2 6
06 CALL 1 2 6
07 CALL 1 2 6
08 CALL 1 2 6
09 CALL 1 2 6
0A CALL 1 2 6
0B CALL 1 2 6
0C CALL 1 2 6
0D CALL 1 2 6
0E CALL 1 2 6
0F CALL 1 2 6
10 CALL 1 2 6
11 CALL 1 2 6
12 CALL 1 2 6
13 CALL 1 2 6
14 CALL 1 2 6
15 CALL 1 2 6
16 CALL 1 2 6
17 CALL 1 2 6
18 CALL 1 2 6
19 CALL 1 2 6
1A CALL 1 2 6
1B CALL 1 2 6
1C CALL 1 2 6
1D CALL 1 2 6
1E CALL 1 2 6
1F CALL 1 2 6
20 NOP 0 1 1
21 SBR 0 1 1
22 SBR 0 1 1
23 SBR 0 1 1
24 SBR 0 1 1
25 SBR 0 1 1
26 SBR 0 1 1
27 SBR 0 1 1
28 SBR 0 1 1
29 SBR 0 1 1
2A SBR 0 1 1
2B SBR 0 1 1
2C SBR 0 1 1
2D SBR 0 1 1
2E SBR 0 1 1
2F SBR 0 1 1
30 SHLA 0 1 2
31 RET 0 1 4
32 BRNC 1 2 2
33 BRC 1 2 2
34 INC [0] 0 1 6
35 INC [1] 0 1 6
36 INC [2] 0 1 6
37 INC [3] 0 1 6
38 RORC 0 1 2
39 ROLC 0 1 2
3A SHR 0 1 2
3B SHL 0 1 2
3C SHRA 0 1 2
3D NOT 0 1 2
3E INC 0 1 2
3F DEC 0 1 2
40 SBRZ 0 1 3
41 SBRZ 0 1 3
42 SBRZ 0 1 3
43 SBRZ 0 1 3
44 SBRZ 0 1 3
45 SBRZ 0 1 3
46 SBRZ 0 1 3
47 SBRZ 0 1 3
48 SBRZ 0 1 3
49 SBRZ 0 1 3
4A SBRZ 0 1 3
4B SBRZ 0 1 3
4C SBRZ 0 1 3
4D SBRZ 0 1 3
4E SBRZ 0 1 3
4F SBRZ 0 1 3
50 ADD 0 1 4
51 AND 0 1 4
52 OR 0 1 4
53 XOR 0 1 4
54 ADC 0 1 4
55 SUB TOS,NEXT 0 1 4
56 SBC NEXT,TOS 0 1 4
57 SUB NEXT,TOS 0 1 4
58 ADD #number 1 2 3
59 AND #number 1 2 3
5A OR #number 1 2 3
5B XOR #number 1 2 3
5C ADD_R 0 1 7
5D AND_R 0 1 7
5E OR_R 0 1 7
5F XOR_R 0 1 7
60 SBRNZ 0 1 3
61 SBRNZ 0 1 3
62 SBRNZ 0 1 3
63 SBRNZ 0 1 3
64 SBRNZ 0 1 3
65 SBRNZ 0 1 3
66 SBRNZ 0 1 3
67 SBRNZ 0 1 3
68 SBRNZ 0 1 3
69 SBRNZ 0 1 3
6A SBRNZ 0 1 3
6B SBRNZ 0 1 3
6C SBRNZ 0 1 3
6D SBRNZ 0 1 3
6E SBRNZ 0 1 3
6F SBRNZ 0 1 3
70 DBRNZ 1 2 5
71 BR 1 2 2
72 BRNZ 1 2 4
73 BRZ 1 2 4
74 CALLR 1 2 5
75 BRF 2 3 4
76 BRNEQ 2 3 4 or 6
77 CALLF 2 3 7
78 DEALLOC #8 0 1 6
79 DEALLOC #7 0 1 6
7A DEALLOC #6 0 1 6
7B DEALLOC #5 0 1 6
7C DEALLOC #4 0 1 6
7D DEALLOC #3 0 1 6
7E DEALLOC #2 0 1 6
7F DEALLOC #1 0 1 6
DROP_R TOS
80 PUSHS #0 0 1 4
81 PUSHS #1 0 1 4
82 PUSHS #2 0 1 4
83 PUSHS #3 0 1 4
84 PUSHS #4 0 1 4
85 PUSHS #5 0 1 4
86 PUSHS #6 0 1 4
87 PUSHS #7 0 1 4
88 PUSH !8 0 1 4
89 PUSH !9 0 1 4
8A PUSH !10 0 1 4
8B PUSH !11 0 1 4
8C PUSH !12 0 1 4
8D PUSH !13 0 1 4
8E PUSH !14 0 1 4
8F PUSH !15 0 1 4
90 PUSH !16 0 1 4
91 PUSH !17 0 1 4
92 PUSH !18 0 1 4
93 PUSH !19 0 1 4
94 PUSH !20 0 1 4
95 PUSH !21 0 1 4
96 PUSH !22 0 1 4
97 PUSH !23 0 1 4
98 PUSH [0][offset] 1 2 7
99 PUSH [1][offset] 1 2 7
9A PUSH [2][offset] 1 2 7
9B PUSH [3][offset] 1 2 7
9C PUSH [0][TOS] 0 1 6
9D PUSH [1][TOS] 0 1 6
9E PUSH [2][TOS] 0 1 6
9F PUSH [3][TOS] 0 1 6
A0 PUSH FLAGS 0 1 4
A1 PUSH [RSP] 0 1 4
A2 PUSH RSP 0 1 4
A3 PUSH DSP 0 1 4
A4 PUSH TOS 0 1 3
A5 PUSH NEXT 0 1 4
A6 PUSH !TOS 0 1 4
A7 PUSHPOP 0 1 5
A8 - - - -
A9 - - - -
AA - - - -
AB - - - -
AC - - - -
AD - - - -
AE - - - -
AF - - - -
B0 PUSHD [0] 0 1 6
B1 PUSHD [1] 0 1 6
B2 PUSHD [2] 0 1 6
B3 PUSHD [3] 0 1 6
B4 PUSH #number 1 2 4
B5 PUSHD 2 3 6
#expression
B6 XCH 0 1 4
B7 PUSH address 2 3 7
B8 PUSH DSP[-8] 0 1 5
B9 PUSH DSP[-7] 0 1 5
BA PUSH DSP[-6] 0 1 5
BB PUSH DSP[-5] 0 1 5
BC PUSH DSP[-4] 0 1 5
BD PUSH DSP[-3] 0 1 5
BE PUSH DSP[-2] 0 1 5
BF PUSH DSP[-1] 0 1 5
C0 ALLOC #1 0 1 3
C1 ALLOC #2 0 1 3
C2 ALLOC #3 0 1 3
C3 ALLOC #4 0 1 3
C4 ALLOC #5 0 1 3
C5 ALLOC #6 0 1 3
C6 ALLOC #7 0 1 3
C7 ALLOC #8 0 1 3
C8 POP !8 0 1 4
C9 POP !9 0 1 4
CA POP !10 0 1 4
CB POP !11 0 1 4
CC POP !12 0 1 4
CD POP !13 0 1 4
CE POP !14 0 1 4
CF POP !15 0 1 4
D0 POP !16 0 1 4
D1 POP !17 0 1 4
D2 POP !18 0 1 4
D3 POP !19 0 1 4
D4 POP !20 0 1 4
D5 POP !21 0 1 4
D6 POP !22 0 1 4
D7 POP !23 0 1 4
D8 POP [0][offset] 1 2 7
D9 POP [1][offset] 1 2 7
DA POP [2][offset] 1 2 7
DB POP [3][offset] 1 2 7
DC POP [0][TOS] 0 1 6
DD POP [1][TOS] 0 1 6
DE POP [2][TOS] 0 1 6
DF POP [3][TOS] 0 1 6
E0 POP FLAGS 0 1 4
E1 - - - -
E2 POP RSP 0 1 4
E3 POP DSP 0 1 4
E4 DROP TOS 0 1 3
E5 DROP NEXT 0 1 2
E6 POP !TOS 0 1 4
E7 POPPUSH 0 1 5
E8 - - - -
E9 - - - -
EA - - - -
EB - - - -
EC MUL 0 1 14
ED DIV 0 1 14
EE - - - -
EF - - - -
F0 POPD [0] 0 1 6
F1 POPD [1] 0 1 6
F2 POPD [2] 0 1 6
F3 POPD [3] 0 1 6
F4 - - - -
F5 DROP_R NEXT 0 1 5
F6 DROP [RSP] 0 1 2
F7 POP address 2 3 7
F8 POP [DSP][-8] 0 1 5
F9 POP [DSP][-7] 0 1 5
FA POP [DSP][-6] 0 1 5
FB POP [DSP][-5] 0 1 5
FC POP [DSP][-4] 0 1 5
FD POP [DSP][-3] 0 1 5
FE POP [DSP][-2] 0 1 5
FF POP [DSP][-1] 0 1 5
222 Index
EXPORT directive, 142 _lshift16_add16, 176
expression _lshift8_add16, 177
address, 14 _lshift8by1_add16, 177
constant, 13 _lshift8by2_add16, 178
general, 11 _max16, 178
_max16s, 178
_max8, 179
F _max8s, 179
file _memcpy, 179
format, 7 _memcpy1, 180
naming convention, 6 _memset, 180
output, 7 _memset1, 181
source, 6 _min16, 181
FLAGS register, 21 _min16s, 181
format, file, 7 _min8, 182
function _min8s, 182
design, 37 _minus16s, 182
parameters, 48 _mod8, 183
functions _mod8s, 183
_abs16, 160 _mul_8_16, 185
_abs8, 161 _mul16, 183
_add_8_16, 162 _mul16s, 184
_add_8_16f, 162 _mul8, 184
_add16, 161 _mul8l, 185
_add16s, 161 _mul8ls, 186
_alloc, 162 _mul8s, 184
_and16, 163 _muls_8_16, 185
_dealloc, 163 _not16, 186
_dec16, 163 _or16, 186
_div16, 164 _pop, 187
_div16s, 164 _pop1, 187
_div8, 165 _popd, 188
_div8s, 165 _popd1, 188
_drop_n, 165 _push, 188
_drop_n_preserve_1, 166 _push1, 189
_drop_n_preserve_2, 166 _push4, 189
_drop_n_return_1, 166 _pushd, 190
_drop_n_return_2, 167 _pushd1, 190
_equal16, 167 _r_shift16, 190
_equal8, 168 _r_shift16s, 191
_gequ16s, 168 _r_shift8, 191
_gequ8, 168 _r_shift8_n, 191
_gequ8s, 169 _r_shift8s, 192
_get_sp, 169 _register_call, 192
_inc16, 169 _sign_extend16, 192
_l_shift16, 172 _sub16, 193
_l_shift16s, 172 _sub16s, 193
_l_shift8, 172 _xor16, 193
_l_shift8_n, 173 io_iaccess, 170
_l_shift8s, 173 io_iaccess_wait, 170
_ldP0_fetchl, 173 io_irelease, 171
_less16, 174 system provided, 160
_less16s, 174
_less8, 174 G
_less8s, 175
_log16, 175 general expression, 11
_log8, 175 general-purpose register, 18
_lognot16, 176 gequ16s function, 168
_lognot8, 176 gequ8 function, 168
224 Index
M P
max16 function, 178 PAGE directive, 153
max16s function, 178 parameters, function, 48
max8 function, 179 pointer direct addressing mode, 31
max8s function, 179 pointer register, 19
memcpy function, 179 pop function, 187
memcpy1 function, 180 POP instruction, 95
memory map, 26 pop1 function, 187
memset function, 180 popd function, 188
memset1 function, 181 POPD instruction, 100
min16 function, 181 popd1 function, 188
min16s function, 181 POPPUSH instruction, 101
min8 function, 182 postfix notation, 36
min8s function, 182 pragma include_assembly_file, 39, 42
minus16s function, 182 push function, 188
mnemonic, 196 PUSH instruction, 102
mod8 function, 183 push1 function, 189
mod8s function, 183 push4 function, 189
MUL instruction, 90 pushd function, 190
mul_8_16 function, 185 PUSHD instruction, 107
mul16 function, 183 pushd1 function, 190
mul16s function, 184 PUSHPOP instruction, 109
mul8 function, 184 PUSHS instruction, 110
mul8l function, 185
mul8ls function, 186
mul8s function, 184
R
muls_8_16 function, 185 r_shift16 function, 190
multi-byte values, 51 r_shift16s function, 191
r_shift8 function, 191
N r_shift8_n function, 191
r_shift8s function, 192
naming convention RADIX directive, 10, 154
code, 48 register
file, 6 data stack, 22
nas command, 3 flag, 21
Neuron architecture, 16 general purpose, 18
Neuron Assembler command-line tool, 3 pointer, 19
Neuron C program, 42 return stack, 23
Neuron Chip memory, 26 scratch, 18
Neuron Librarian tool, 5 register_call function, 192
nlib command, 5 relative addressing mode, 33
NodeBuilder Development Tool, 6 RES directive, 155
NOLIST directive, 151 reserved keywords, 220
NOP instruction, 91 RESOURCE directive, 156
NOT instruction, 92 RET instruction, 111
not16 function, 186 return stack, 23
return stack register, 23
Reverse Polish notation, 36
O ROLC instruction, 112
object output file, 7 RORC instruction, 113
opcode, 9, 208 RSP, 23
operand, 10
operator, 11 S
OR instruction, 93
OR_R instruction, 94 SBC instruction, 114
or16 function, 186 SBR instruction, 115
ORG directive, 152 SBRNZ instruction, 117
SBRZ instruction, 119
226 Index
www.echelon.com