VC4ASM - Expression syntax

↑ Top, → Constants, → Operators

Constants

Type Example Data type Description
decimal -42 int
Integer constant, 32 bit signed or unsigned
hexadecimal -0xa4 int
Hexadecimal constant, 32 bit signed or unsigned
octal -0377 int
Octal constant, indicated by leading zero
binary 0b10010 int
Binary constant
floating point 1.0
1.4e6
float Floating point value
Note that this must include a decimal dot.
per element constant [0,2,3...] int2[16] 2 bit integer per QPU element.
accumulator
r1 register r0 ... r5
On write r5 need to be named r5quad or r5rep respectively.
memory register ra25 register ra0 ... ra31, rb0 ... rb31. The numbers rx32 ... rx63 also work, but this is normally not recommended because it prevents vc4asm from choosing from any the register file automatically for peripheral registers where this does not matter.
I/O register vary
irq
register Access to peripheral hardware, see table below.
packed register experssion ra0.8csf register Register that should be packed and/or unpacked. This can be assigned to a symbol to define aliases for register slices, e.g.
.set back_color, ra0.8ai
semaphore sacq15
srel2
register Semaphore access, read only. Depending on the name an acquire or release instruction is issued.
This syntax is only provided for compatibility with Broadcom source codes. Normally you should prefer the sacq and srel instructions.
label :loop label label receiving the absolute number of bytes from the start of the assembly.
internal raw register :[0,1,0,3] register Internal register constant. It consists of the fields register number, register type, vector rotation and pack/unpack mode. The latter two are optional and by default zero. This syntax is for internal use only and subject to change.

Hardware register

Number read write
file A file B file A file B
32 unif r0
33

r1
34


r2
35
vary r3
36


tmurs
37


r5quad r5rep
38
elem_num qpu_num irq
interrupt
39




40


unif_addr unif_addr_rel
41
x_coord y_coord x_coord y_coord
42
ms_mask rev_flag ms_mask rev_flag
43


stencil
44


tlbz
45


tlbm
46


tlbc
47


tlbam
48
vpm
49
vr_busy vw_busy vr_setup vw_setup
50
vr_wait vw_wait vr_addr vw_addr
51
mutex
mutex_acq
mutex
mutex_rel
52


recip
53


recipsqrt
54


exp
55


log
56


t0s
57


t0t
58


t0r
59


t0b
60


t1s
61


t1t
62


t1r
63


t1b

Operators and precedence

The operators share mainly the same precedence as for the C language.

Precedence Type Operator Operand types Description
1 brace ( ) all

2


unary + all
identity operation
- int → int
float → float
negative value
~ int → int
binary not
! int → int logical not, 1 if operand is zero, otherwise 0
unary
math
abs int → int
float → float
absolute value |x|
ceil float → int smallest integer not less than value
floor largest integer not greater than value
unary
exponential
exp int → float
float → float
natural exponential function
exp2 binary exponential function
exp10 common exponential function
log natural logarithm
log2 binary logarithm
log10 common logarithm
unary
trigonometric
cos int → float
float → float
cosine
sin sine
tan tangent
acos arc cosine
asin arc sine
atan arc tangent
unary
hyperbolic
cosh int → float
float → float
hyperbolic cosine
sinh hyperbolic sine
tanh hyperbolic tangent
acosh arc hyperbolic cosine
asinh arc hyperbolic sine
atanh arc hyperbolic tangent
unary
extended
math
erf int → float
float → float
error function
erfc complementary error function
3
binary
power
** int, int → int
float, float → float
int, float → float
float, int → float
power, xy
4


binary
multiplicative
* multiplication
/ division
% modulus
5
binary
additive
+ int, int → int
float, float → float
int, float → float
float, int → float
reg, int → reg
addition
In case the left operand is a register the register number changes. The resulting number must not exceed the range for the given register type. The operation never changes the type of a register.
- subtraction
In case the left operand is a register the register number changes. The resulting number must not exceed the range for the given register type. The operation never changes the type of a register.
6 binary
bit shift
<< int, int → int
float, int → float
reg, int → reg
reg, reg → reg
arithmetic shift left (signed)
Arithmetic shift left is basically the same than logical shift left unless the right operand is negative where the shift direction turns to right.
If the left operand is float, only the exponent is shifted, i.e. the number is multiplied by the power of two indicated by the right operand.
If the left operand is a register, the rotate unit of the MUL ALU is activated by small immediate values ≥ 48. The right operand need to be an integer constant or register r5.
>> arithmetic shift right (signed)
If the left operand is float, only the exponent is shifted, i.e. the number is multiplied by the power of two indicated by the right operand.
If the left operand is a register, the rotate unit of the MUL ALU is activated by small immediate values ≥ 48. The right operand need to be an integer constant or register r5.
<<< int, int → int logical shift left (unsigned shifted by signed)
Logical shift left is basically the same than arithmetic shift left unless the right operand is negative where the shift direction turns to right.
>>> logical shift right (unsigned shifted by signed)
binary
rotate
><< int, int → int 32 bit rotate left
>>< 32 bit rotate right
><<< 64 bit rotate left
>>>< 64 bit rotate right
7 binary
relational
> all, all → int greater than
>= greater than or equal
< less than
<= less than or equal
<=> full comparison, evaluates to -1 if less than, +1 if greater, 0 if equal and -0x80000000 if indeterminate
8
binary
equality
== all, all → int equal
!= not equal
=== identical, not just equal, e.g. NaN === NaN but NaN != NaN
!== not identical, e.g. 1.0 !== 1 but 1.0 == 1 and also 1.00 === 1.0
9 binary
bitwise
& int, int → int binary and
10 ^ binary exclusive or
!^ binary exclusive nor
11 | binary inclusive or
12 binary
logical
&& int, int → int logical and
13 ^^ logical exclusive or
!^^ logical exclusive nor
14 || logical inclusive or

Relational operators and different operand types

If the left and right hand side of a relational or equality operator has a different data type, e.g. register vs. integer the following sequence applies. Types with higher ordinals below always compare greater.

  1. Integer or floating point constant
    Integer comparison is always signed.
    If integer is compared against a float then the integer operand propagates to float before the comparison. Note that this can cause a loss of precision.
  2. Load immediate per element constant
    Do not rely on comparison order of two LDIPES constants.
  3. Register
    Comparing two registers is only reliable if both registers are exactly of the same type. Even equality comparison might give unexpected results. E.g. unif == ra32 evaluates to false because ra32 is pinned to register file A while unif is not.
  4. Semaphore register
    Acquire is greater than release.
  5. Label
    You can safely compare two labels.

Register operands

Some operators can be applied to registers rather than constants. This operators will not modify the value at runtime, instead they have a special meaning at compile time.

+ -
Addition and subtraction to a register modifies the register number. You must not exceed the domain of the specific register type, of course.
<< >>
Shift operators on registers activate the vector rotation of the MUL ALU to pass the result to another SIMD slice. << rotates to higher QPU element number, >> to lower elements. Note that the rotation direction is inverted when applied to a source argument, i.e. like if you take the value from a higher or lower element number.

Alphanumeric operators

Note that vc4asm treats mathematical functions like log as unary operators rather than functions. I.e. the basic syntax is log 7 rather than log(7). However, since braces are always allowed around expression the latter will work as well although the braces are no function call operator.