The emulator is capable of evaluating expressions within breakpoint conditions and Go To prompts. These expressions inspect the current emulation state and can be used to dynamically process registers, variables and other data elements that may change from one invocation to the next.
Expressions are organized into series of tokens with three main modes of significance:
• Value | Numeric value that can be used in computation. This may take the form of a literal number provided directly in the expression, or one of the named symbols that represent things in the CPU state, current instruction and/or current memory access. |
• Operator | Modifies one or two values through a given operation. Unary operators modify only the value on their right, while binary operators consider the values on their left and right and produce a new value as the result. |
• Group |
Operand groups, mainly through the use of parentheses () ,
override the default order of operations. Anything enclosed in a group
is processed before any operations adjacent to that group.
|
Expressions are case-insensitive.
Values come in two forms:
• Literal | Provided directly by the expression. |
• Symbol | Refers to something in the current emulation state. |
Values may be one of four data types:
• Signed Word | 32-bit, two's complement integer. |
• Unsigned Word | 32-bit, unsigned integer. |
• Float | 32-bit floating short in IEEE-754 format. |
• Boolean | 1-bit value representing whether a condition is true or false. |
Signed word and unsigned word are represented as sequences of character
digits. A numeric token that begins with the characters 0x
will be interpreted as hexadecimal, allowing letters A
through
F
to be used as digits as well. If the given value can be
represented in the signed word data type, the token is a signed word.
Otherwise, if it can be represented in the unsigned word data type, the token
is an unsigned word. If the value cannot be represented in either data type,
a parsing error occurs.
Floats, like words, are represented as sequences of character digits. They
are differentiated from words by the presence of a dot .
character somewhere within the sequence. Only one dot may be present in a
float literal, and dots cannot be used in hexadecimal literals. If the given
value cannot be represented in the float data type, a parsing error occurs.
Float values in the expression evaluator are subjected to the same
restrictions as on the Virtual Boy's CPU: if the result of any float
operation is NaN, an infinity, a denormal number or negative zero, it will be
changed to positive zero.
Booleans are mechanically identical to signed words, but the semantics are
slightly different. When used in a numeric operation, a boolean will use the
value 0
if false or the value 1
if true. Boolean
literals are specified with the named values true
and
false
within the expression. In a boolean operation, any result
that is zero is considered false, and any non-zero value is considered true.
Operators exist for converting between data types (see Operators below). A Go To expression will only be valid if its final data type is signed word or unsigned word.
The following symbols may be used for accessing information about the current instruction being executed:
address | Current memory access's address. |
break | Identifies what type of break scenario is being considered. See below for a list of identifiers. |
code | Current exception's exception code. |
cond |
Condition code for Bcond and SETF
instructions. See below for a list of conditions.
|
disp | Displacement offset for jumps and memory accesses. |
fetch |
Data unit index during a fetch operation, or -1 if the read
operation is not a fetch.
|
format | Current instruction's encoding format. |
id |
Identifies which specific instruction is being executed, considering
opcode and, where applicable, subopcode . See
below for a list of identifiers.
|
imm | Immediate operand. |
opcode | Current instruction's top-level opcode. |
reg1 | Source register index. |
reg2 | Destination register index. |
regid |
System register index in LDSR and STSR
instructions.
|
size | Number of bytes occupied by the current instruction. |
subopcode | Current instruction's secondary opcode. |
type | Data type of the current memory access. |
value | Value read by the current memory access. |
vector | Vector for TRAP instructions. |
The following symbols may be used in conjunction with the break
symbol:
The following symbols may be used in conjunction with the cond
symbol:
The following symbols may be used in conjunction with the id
symbol:
The following symbols may be used to retrieve the contents of a CPU program register:
The following symbols may be used to retrieve the contents of a CPU system register:
Operators may apply to one (unary) or two (binary) values. All unary operators appear to the left of the value they modify (or another unary operator). Binary operators appear between the values they modify. Each operator considers the types of its operands in order to produce a new value of the appropriate type.
If the operands of a binary operator have different types, one of the values will be converted to the other type before performing the operation. The conversion depends on the "greater" of the two types, in the following order (higher is "greater"):
↑ | Float |
Unsigned word | |
Signed word | |
↓ | Boolean |
For example, if an operation contains both a signed word and a float, the signed word value is first converted to float.
Operators have assigned precedence that specifies the order of operations.
For example, in the expression 1 + 2 * 3
, the multiplication
happens before the addition because it has higher precedence. Parentheses
()
may be used to encapsulate operations and guarantee that they
are evaluated first regardless of the relative precedence of the adjacent
operators. For example, in the expression (1 + 2) * 3
, the
addition happens before the multiplication because it is enclosed in
parentheses.
The following operators may be used in expressions. Groups listed higher have higher precedence and happen before groups listed lower. Operators within groups have the same precedence and are processed in the order they appear in the expression from left to right.
~ | Not Bitwise | Cannot be used with a float value. |
! | Not Logical | Always produces a boolean. |
- | Negate | Cannot be used with an unsigned word value. |
bool | Cast to Boolean | |
ceil | Round Up | |
float | Cast to Float | |
floor | Round Down | |
round | Round to Nearest | |
s8 , byte |
Cast to Signed Byte | Result is of type signed word. |
s16 , halfword |
Cast to Signed Halfword | Result is of type signed word. |
s32 , word |
Cast to Signed Word | |
trunc | Truncate | Removes any fraction. |
|
Cast to Unsigned Byte | Result is of type unsigned word. |
u16 , uhalfword |
Cast to Unsigned Halfword | Result is of type unsigned word. |
u32 , uword |
Cast to Unsigned Word | |
xfloat | Reinterpret as Float | The binary value is not modified. |
xs32 , xword |
Reinterpret as Signed Word | The binary value is not modified. |
xu32 , xuword |
Reinterpret as Unsgned Word | The binary value is not modified. |
/ | Divide | Zero divisor yields zero as result. |
* | Multiply | |
% | Remainder | Zero divisor yields zero as result. |
+ | Add | |
- | Subtract | |
<< | Shift Left | Cannot be used with a float value. |
>> | Shift Right Arithmetic | Cannot be used with a float value. |
>>> | Shift Right Logical | Cannot be used with a float value. |
> | Greater | Always produces a boolean. |
>= | Greater or Equal | Always produces a boolean. |
< | Less | Always produces a boolean. |
<= | Less or Equal | Always produces a boolean. |
== | Equal | Always produces a boolean. |
!= | Not Equal | Always produces a boolean. |
& | And Bitwise | Cannot be used with a float value. |
^ | Exclusive Or Bitwise | Cannot be used with a float value. |
| | Or Bitwise | Cannot be used with a float value. |
&& | And Logical | If left is true, returns right; else returns left. |
^^ | Exclusive Or Logical | If only one operand is true, returns the truthy value. |
|| | Or Logical | If left is true, returns left; else returns right. |
A value can be read from the memory bus of the emulation state. This is done
by enclosing the part of the expression that represents the address in square
brackets []
. This functions in an identical manner to
parentheses ()
, but will additionally perform the read
operation.
Under most circumstances, a signed word read is performed. Certain operators can be placed in front of the group to alter how the read is performed:
• float |
Behaves like xfloat instead. |
• s8 , u8 |
Performs a byte read of the specified signedness. |
• s16 , u16 |
Performs a halfword read of the specified signedness. |