Expression Evaluator

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

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 distinguished 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 following restrictions: if the value of any float literal or 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 value 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.
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 or to be written by the current memory access.
vector Vector for TRAP instructions.

The following symbols may be used in conjunction with the break symbol:

exception
execute
read
write

The following symbols may be used in conjunction with the cond symbol:

c
e
f
ge
gt
h
l
le
lt
n
nc
ne
nh
nl
nv
nz
p
t
v
z

The following symbols may be used in conjunction with the id symbol:

illegal
add_imm
add_reg
addf.s
addi
and
andbsu
andi
andnbsu
bcond
caxi
cli
cmp_imm
cmp_reg
cmpf.s
cvt.sw
cvt.ws
div
divf.s
divu
halt
in.b
in.h
in.w
jal
jmp
jr
ld.b
ld.h
ld.w
ldsr
mov_imm
mov_reg
movbsu
movea
movhi
mpyhw
mul
mulf.s
mulu
not
notbsu
or
orbsu
ori
ornbsu
out.b
out.h
out.w
reti
rev
sar_imm
sar_reg
sch0bsd
sch0bsu
sch1bsd
sch1bsu
sei
setf
shl_imm
shl_reg
shr_imm
shr_reg
st.b
st.h
st.w
stsr
sub
subf.s
trap
trnc.sw
xb
xh
xor
xorbsu
xori
xornbsu

The following symbols may be used to retrieve the contents of a CPU program register:

r0
r1
r2
r3
r4
r5
r6
r7
r8
r9
r10
r11
r12
r13
r14
r15
r16
r17
r18
r19
r20
r21
r22
r23
r24
r25
r26
r27
r28
r29
r30
r31
gp
hp
lp
sp
tp

The following symbols may be used to retrieve the contents of a CPU system register:

adtre
chcw
ecr
eipc
eipsw
fepc
fepsw
pc
pir
psw
tkcw
sr29
sr30
sr31

Operators

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 selects 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 converted to float before performing the operation.

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 according to the order in which they appear in the expression: right-to-left for unary operators, left-to-right for binary operators.

Unary ~ 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.
u8, ubyte 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.
Binary / Divide Zero divisor yields zero as result.
* Multiply
% Remainder Zero divisor yields zero as result.
+ Add
- Subtract
<< Shift Left Cannot be used with float values.
>> Shift Right Arithmetic Cannot be used with float values.
>>> Shift Right Logical Cannot be used with float values.
> 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 float values.
^ Exclusive Or Bitwise Cannot be used with float values.
| Or Bitwise Cannot be used with float values.
&& 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.

Memory Read

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.

Reads are subjected to the alginment restrictions of the Virtual Boy's CPU: the lowest bit of the address is ignored for halfword reads, and the lowest two bits of the address are ignored for word reads.