Assembler Syntax

TODO.

This subpage is under construction.

Case Sensitivity

The Spin2/PASM2 syntax is completely case-insensitive. That means not only that addpix, AddPix and ADDPIX are all valid spellings of the ADDPIX instruction, but also that user defined labels and constants can be used with different casing than their definition.

For readability, documentation uses all-uppercase for any keywords, but any sane programmer uses all-lowercase in actual source files.

Labels

Any (not already used) symbol placed into the first column of a DAT block becomes a global label.
If a dot is placed in front, it becomes a local label, whose scope is bounded by the global labels surrounding it. This allows re-using common names such as "loop".

A label may be alone on its line or followed by instructions or data.

In the following example, two local labels .lol are defined, one under foo and another under bar:

DAT

foo
        if_z  jmp #.lol
              wrlong #0,#123
.lol    _ret_ rdlong pa,#123

bar
              mov pa,#123
.lol
              cogatn #123
              djnz pa,#.lol

Note: In P1 assembly, a colon was used instead of a dot to indicate a local label.

Accessing local labels from outside their scope

Some assemblers (notably flexspin) allow accessing local labels defined under a certain global from outside their scope. Referencing the example above,you might access either foo:lol or bar:lol.

Hub vs Cog labels

Labels are treated differently depending on wether they are defined in "Cog mode" (following ORG) or "Hub mode" (following ORGH). This affects the value the label evaluates to without the use of the @ operator:

  Label in Cog Mode Label in Hub Mode
label Cog address
(relative to ORG)
Hub address
(relative to object base)
@label Hub address
(relative to object base)
Hub address
(relative to object base)
@@@label Hub address
(absolute)
Hub address
(absolute)

Note: In a plain assembly program, the object base is zero, so all hub addresses are truly absolute. The difference only comes into play when using assembly in a high-level program.

Note 2: The triple @@@ operator is an extension not supported by all compilers.

Operators

(TODO: Are float ops even relevant to DAT/CON?)

Unary Operators

Operator Term Priority Description
!!, NOT !!x 12 Logical NOT (0 → -1, non-0 → 0)
! !x 2 Bitwise NOT (1's complement)
- -x 2 Negate (2's complement)
-. -.x 2 Floating-point negate (toggles MSB)
ABS ABS x 2 Absolute value
FABS FABS x 2 Floating-point absolute value (clears MSB)
ENCOD ENCOD x 2 Encode MSB, 0..31
DECOD DECOD x 2 Decode, 1 << (x & $1F)
BMASK BMASK x 2 Bitmask, (2 << (x & $1F)) - 1
ONES ONES x 2 Sum all '1' bits, 0..32
SQRT SQRT x 2 Square root of unsigned value
FSQRT FSQRT x 2 Floating-point square root
QLOG QLOG x 2 Unsigned value to logarithm {5'whole, 27'fraction}
QEXP QEXP x 2 Logarithm to unsigned value

Binary Operators

Operator Term Priority Description
>> x >> y 3 Shift x right by y bits, insert 0's
<< x << y 3 Shift x left by y bits, insert 0's
SAR x SAR y 3 Shift x right by y bits, insert MSB's
ROR x ROR y 3 Rotate x right by y bits
ROL x ROL y 3 Rotate x left by y bits
REV x REV y 3 Reverse order of bits 0..y of x and zero-extend
ZEROX x ZEROX y 3 Zero-extend above bit y
SIGNX x SIGNX y 3 Sign-extend from bit y
& x & y 4 Bitwise AND
^ x ^ y 5 Bitwise XOR
| x | y 6 Bitwise OR
* x * y 7 Signed multiply
*. x *. y 7 Floating-point multiply
/ x / y 7 Signed divide, return quotient
/. x /. y 7 Floating-point divide
+/ x +/ y 7 Unsigned divide, return quotient
// x // 7 7 Signed divide, return remainder
+// x +// y 7 Unsigned divide, return remainder
SCA x SCA y 7 Unsigned scale, (x * y) >> 32
SCAS x SCAS y 7 Signed scale, (x * y) >> 30
FRAC x FRAC y 7 Unsigned fraction, (x << 32) / y
+ x + y 8 Add
+. x +. y 8 Floating-point add
- x - y 8 Subtract
-. x -. y 8 Floating-point subtract
#> x #> y 9 Force x => y, signed
<# x <# y 9 Force x <= y, signed
ADDBITS x ADDBITS y 10 Make bitfield, (x & $1F) | (y & $1F) << 5
ADDPINS x ADDPINS y 10 Make pinfield, (x & $3F) | (y & $1F) << 6
< x < y 11 Signed less than (returns 0 or -1)
+< x +< y 11 Unsigned less than (returns 0 or -1)
<. x <. y 11 Floating-point less than (returns 0 or -1)
<= x <= y 11 Signed less than or equal (returns 0 or -1)
+<= x +<= y 11 Unsigned less than or equal (returns 0 or -1)
<=. x <=. y 11 Floating-point less than or equal (returns 0 or -1)
== x == y 11 Equal (returns 0 or -1)
==. x ==. y 11 Floating-point equal (returns 0 or -1)
<> x <> y 11 Not equal (returns 0 or -1)
<>. x <>. y 11 Floating-point not equal (returns 0 or -1)
>= x >= y 11 Signed greater than or equal (returns 0 or -1)
+>= x +>= y 11 Unsigned greater than or equal (returns 0 or -1)
>=. x >=. y 11 Floating-point greater than or equal (returns 0 or -1)
> x > y 11 Signed greater than (returns 0 or -1)
+> x +> y 11 Unsigned greater than (returns 0 or -1)
>. x >. y 11 Floating-point greater than (returns 0 or -1)
<=> x <=> y 11 Signed comparison (<,=,> returns -1,0,1)
&&, AND x && y 13 Logical AND (x <> 0 AND y <> 0, returns 0 or -1)
^^, XOR x ^^ y 14 Logical XOR (x <> 0 XOR y <> 0, returns 0 or -1)
||, OR x || y 15 Logical OR (x <> 0 OR y <> 0, returns 0 or -1)

Ternary Operator

Operator Term Priority Description
? : x ? y : z 16 If x <> 0 then choose y, else choose z

Condition Codes

TODO: Maybe move this

Each instruction can have a condition code. If the condition is not met, the instruction has no effect and takes 2 cycles. (Exception: BRK and NOP may not have condition codes applied to them)

Encoding Primary Name Alternate 1 Alternate 2 Alternate 3 Description
%0000 _RET_       Always execute and return (More Info)
%0001 IF_NC_AND_NZ IF_NZ_AND_NC IF_GT IF_00 Execute if C=0 AND Z=0
%0010 IF_NC_AND_Z IF_Z_AND_NC   IF_01 Execute if C=0 AND Z=1
%0011 IF_NC   IF_GE IF_0X Execute if C=0
%0100 IF_C_AND_NZ IF_NZ_AND_C   IF_10 Execute if C=1 AND Z=0
%0101 IF_NZ   IF_NE IF_X0 Execute if Z=0
%0110 IF_C_NE_Z IF_Z_NE_C     Execute if C!=Z
%0111 IF_NC_OR_NZ IF_NZ_OR_NC     Execute if C=0 OR Z=0
%1000 IF_C_AND_Z IF_Z_AND_C   IF_11 Execute if C=1 AND Z=1
%1001 IF_C_EQ_Z IF_Z_EQ_C     Execute if C=Z
%1010 IF_Z   IF_E IF_X1 Execute if Z=1
%1011 IF_NC_OR_Z IF_Z_OR_NC     Execute if C=0 OR Z=1
%1100 IF_C   IF_LT IF_1X Execute if C=1
%1101 IF_C_OR_NZ IF_NZ_OR_C     Execute if C=1 OR Z=0
%1110 IF_C_OR_Z IF_Z_OR_C     Execute if C=1 OR Z=1
%1111 (empty) IF_ALWAYS     Always execute