CPUSim64 Directives

The CPUSim64 has two types of directives: Preprocessor directives and Assembler directives.

Preprocessor directives are instructions to the preprocessor. They tell the preprocessor how to modify your source .asm source file. The output of the preprocessor is pure CPUSim64 assembler code.

Assembler directives are instructions to the Assembler. They consist mainly of directives to allocate scopes or data.

Normally the assemble.sh, run.sh and debug.sh scripts will run the preprocessor before passing the output on to the assembler. Sometimes it is helpful to see how the preprocessor modified your code when there are errors. You can run just the preprocessor by using the preprocess.sh script. It will create a .pp.asm file that contains the output of just the preprocessor.

Preprocessor Directives

Preprocessor directives always start with a pound sign (#). They are written by themselves on a line. Some directives have a begin and and end directive that must be used in pairs.

DirectiveOperandsDescription
#include<systemfile.def>
"localfile.asm"
Includes the contents of a system file or a file in the current directory.
#defineIDENT literalDefines the substitution symbol IDENT as a synonym for the literal value.
#undefIDENTUndefines the substitution symbol IDENT.
#def_func
#end_func
FUNC_IDENT(params)
none
Defines a stack-based function. Params are a comma-separated list of formal argument identifiers.
#callFUNC_IDENT(args)Calls a stack-based function. The args are a comma separated list of values that will be passed on the stack matching the formal parameters defined for the function.
#def_macro
#end_macro
MACRO_IDENT(params)
none
Defines a substitution macro. Params are a comma-separated list of placeholder names. Inside the body of the macro, parameters are represented using the special placeholder symbol ${param}, where param is the name of the parameter to substitute.
#macroMACRO_IDENT(args)Instantiates a substitution of the macro. The args are a comma separated list of symbols that will be substituted into the macro matching the formal parameters defined for the macro.
#globallabel: .dc? ...Defines global read/write variables in the __DATA__ section of the program. Accessing the variables is done with load/store instructions.
#svarident_listDefines stack variables for the function. The ident_list is a comma-separated list of variable names to be created. Must be the first directive following the beginning of a #def_func directive. Accessing the variables is done with load/store instructions.
#varident_listDefines integer register variables for the function. The ident_list is a comma-separated list of variable names to be created. Must follow the #svar directive if present. Accessing the variables is done with the move instruction.
#fvarident_listDefines floating point register variables for the function. The ident_list is a comma-separated list of variable names to be created. Must follow the #var directive if present. Accessing the variables is done with the move instruction.
#returnopMoves the operand into register r0 and then returns. Causes all #svar, #var and #fvar variables to be deallocated.
#freturnopMoves the operand into register f0 and then returns. Causes all #svar, #var and #fvar variables to be deallocated.
#if
#else_if
#else
#end_if
IDENT cmpOp IDENT/literal
IDENT cmpOp IDENT/literal
none
none
Causes conditional inclusion of code lines. IDENT must be a symbol defined by a #define directive. The valid comparison operaters are ==, !=, <=, =>, <, and >. If just an IDENT is supplied instead of an expression, the "truthiness" of the identifier is evaluated. O is false, everything else is true.
#ifdef
#else
#end_if
IDENT
none
none
Causes conditional inclusion of code lines. IDENT must be a symbol defined by a #define directive. If the identifier is defined (doesn't matter what it is defined as) then the code will be included. If the identifier is not defined the optional else block code will be included.
#ifndef
#else
#end_if
IDENT
none
none
Causes conditional inclusion of code lines. IDENT must be a symbol defined by a #define directive. If the identifier is not defined then the code will be included. If the identifier is defined (doesn't matter what it is defined as) the optional else block code will be included.
#for
#end_for
inital IDENT cmpOp IDENT/literal increment
none
Generates assembler code for a for loop. The initial value is specified by initial. The loop variable is identified by IDENT. The valid comparison operaters are ==, !=, <=, =>, <, and >. The final value, increment, is the amount to add to the loop variable each loop.
#while
#end_while
IDENT cmpOp IDENT/literal
none
Generates assembler code for a while loop. The loop variable is identified by IDENT. The valid comparison operaters are ==, !=, <=, =>, <, and >. The loop condition is evaluated at the beginning of the loop.
#do_while
#end_do_while
none
IDENT cmpOp IDENT/literal
Generates assembler code for a do/while loop. The loop variable is identified by IDENT. The valid comparison operaters are ==, !=, <=, =>, <, and >. The loop condition is evaluated at the end of the loop.
#breaknoneBreaks out of the innermost loop.
#continuenoneContinues to the next iteration of the innermost loop.
#if_cond
#else_if_cond
#else_cond
#end_cond
IDENT cmpOp IDENT/literal
IDENT cmpOp IDENT/literal
none
none
Generates assembler code for an if/else construct.
#if_cond_sr
#else_cond
#end_cond
z|nz|n|p|nn|np|pe|po|o|no
none
none
Generates assembler code for an if/else construct based on the conditions in the status register (SR)
#sync
#end_sync
IDENT
IDENT[OFFSET]
Acquires a lock on the mutex at IDENT (or IDENT[OFFSET]) and releases it at the end of the block. Need to declare the mutex with
#macro DEFINE_MUTEX(IDENT)
and initialize it with
#call initializeMutex(IDENT)
Include threadlib.asm to get access to these macros/functions.

Assembler Directives

DirectiveOperandsDescription
.orgliteralSets the location in memory for the next instruction.
.line«filename», linenumResets the source filename and line number
.line_begin
.line_end
«filename», linenum
none
Resets the source filename and line number for the enclosed statements.
.block_begin
.block_end
IDENT
none
Creates a new scope for line labels. Label names beginning with a dollar sign ($) will be relative to the enclosing scope.
.dciint_literalStores the specified integer in the next word of the assembled code.
.dcffloat_literalStores the specified floating point value in the next word of the assembled code.
.dcacountCauses count + 1 words to be allocated at this point in the code. Contents are undefined. The first word will contain the count.
.dcbbyte_listCauses the bytes specified by the comma separated byte_list to be allocated at this point in the code. Bytes will be packed 8 to a word (big-endian). The first word will contain the count.
.dcsstring_literalCauses the string specified to be allocated at this point in the code. String is encoded in UTF-8 and will be packed 8 to a word (big-endian). The first word will contain the UTF-8 byte count.
.dcwint_list
float_list
char_list
Causes the words specified by the comma separated list to be allocated at this point in the code. Initializers are placed one per word. The first word will contain the count.

Literals can be a decimal integer, hexadecimal integer, floating point literal, character literal or string literal.

Examples

Unicode escapes are UTF-16 values. They must be exactly four hexadecimal digits.