-; This is a bcm43xx microcode assembly example.
-;
-; In this example file, r0 and r1 are always input
-; registers and r2 is output.
-; For input we can always have constant values or (one) memory
-; operand instead of the input registers shown here.
-;
-; Registers:
-; GPRs: r0 - r63
-; Offset Registers: off0 - off5
-; SPRs: spr000
-;
-; To access memory, two methods can be used. Examples follow.
-; Direct linear:
-; mov r0,[0xCA]
-; Indirect through Offset Register (pointer):
-; mov r0,[0xCA,off0]
-;
-
-
-; The target architecture. Supported versions are 5 and 15
+/* This is a bcm43xx microcode assembly example.
+ *
+ * Registers:
+ * GPRs: r0 - r63 (General Purpose Register)
+ * Offset Registers: off0 - off5
+ * SPRs: spr000 (Special Purpose Register)
+ *
+ * SPRs map to the driver-side IHR registers.
+ * An SPR offset is converted to an IHR offset by the following
+ * calculation: IHR = (SPR + 0x400) * 2
+ *
+ * To access memory, two methods can be used. Examples follow.
+ * Direct linear:
+ * mov r0,[0xCA]
+ * Indirect through Offset Register (pointer):
+ * mov r0,[0xCA,off0]
+ */
+
+
+/* The target architecture. Supported versions are 5 and 15 */
%arch 5
-; Program entry point
+/* Program entry point */
%start testlabel
#define PSM_BRC spr848
#define ECOND_MAC_ON (0x20 | 4)
+%assert ((((1))) == ((((2 - 1) & 0xFF))))
+%assert ((1 == 2) || (1 == (0xFF & 1)))
+%assert (1 != (~1))
+%assert ((1 == (2 - 1)) && (2 == 2))
.text
+ /* Inline assertion inside of a complex immediate.
+ * The %assert() expression will always return zero. */
+ mov (1 + (%assert(1 == ((1 + 2) - 2)))), r0
+
label:
- ; ADD instructions
- add r0,r1,r2 ; add
- add. r0,r1,r2 ; add, set carry
- addc r0,r1,r2 ; add with carry
- addc. r0,r1,r2 ; add with carry, set carry
+ /* ADD instructions */
+ add r0,r1,r2 /* add */
+ add. r0,r1,r2 /* add, set carry */
+ addc r0,r1,r2 /* add with carry */
+ addc. r0,r1,r2 /* add with carry, set carry */
testlabel:
- ; SUB instructions
- sub r0,r1,r2 ; sub
- sub. r0,r1,r2 ; sub, set carry
- subc r0,r1,r2 ; sub with carry
- subc. r0,r1,r2 ; sub with carry, set carry
-
- sra r0,r1,r2 ; arithmetic rightshift
-
- ; Logical instructions
- or r0,r1,r2 ; bitwise OR
- and r0,r1,r2 ; bitwise AND
- xor r0,r1,r2 ; bitwise XOR
- sr r0,r1,r2 ; rightshift
- sl r0,r1,r2 ; leftshift
-
- srx 7,8,r0,r1,r2 ; eXtended right shift (two input regs)
-
- rl r0,r1,r2 ; rotate left
- rr r0,r1,r2 ; rotate right
- nand r0,r1,r2 ; clear bits (notmask + and)
-
- orx 7,8,r0,r1,r2 ; eXtended OR
-
- ; Copy instruction. This is a virtual instruction
- ; translated to more lowlevel stuff like OR.
- mov r0,r2 ; copy data
-
- ; Jumps
- jmp label ; unconditional jump
- jand r0,r1,label ; jump if binary AND
- jnand r0,r1,label ; jump if not binary AND
- js r0,r1,label ; jump if all bits set
- jns r0,r1,label ; jump if not all bits set
- je r0,r1,label ; jump if equal
- jne r0,r1,label ; jump if not equal
- jls r0,r1,label ; jump if less (signed)
- jges r0,r1,label ; jump if greater or equal (signed)
- jgs r0,r1,label ; jump if greater (signed)
- jles r0,r1,label ; jump if less or equal (signed)
- jl r0,r1,label ; jump if less
- jge r0,r1,label ; jump if greater or equal
- jg r0,r1,label ; jump if greater
- jle r0,r1,label ; jump if less or equal
-
- jzx 7,8,r0,r1,label ; Jump if zero after shift and mask
- jnzx 7,8,r0,r1,label ; Jump if nonzero after shift and mask
-
- ; jump on external conditions
- jext ECOND_MAC_ON,r0,r0,label ; jump if external condition is TRUE
- jnext ECOND_MAC_ON,r0,r0,label ; jump if external condition is FALSE
-
- ; Subroutines
- call lr0,label ; store PC in lr0, call func at label
- ret lr0,lr1 ; store PC in lr0, return to lr1
- ; Both link registers can be the same
- ; and don't interfere.
-
- ; TKIP sbox lookup
- tkiph r0,r2 ; Lookup high
- tkiphs r0,r2 ; Lookup high, byteswap
- tkipl r0,r2 ; Lookup low
- tkipls r0,r2 ; Lookup low, byteswap
-
- nap ; sleep until event
-
- ; raw instruction
- @160 r0,r1,r2 ; equivalent to or r0,r1,r2
+ /* SUB instructions */
+ sub r0,r1,r2 /* sub */
+ sub. r0,r1,r2 /* sub, set carry */
+ subc r0,r1,r2 /* sub with carry */
+ subc. r0,r1,r2 /* sub with carry, set carry */
+
+ sra r0,r1,r2 /* arithmetic rightshift */
+
+ /* Logical instructions */
+ or r0,r1,r2 /* bitwise OR */
+ and r0,r1,r2 /* bitwise AND */
+ xor r0,r1,r2 /* bitwise XOR */
+ sr r0,r1,r2 /* rightshift */
+ sl r0,r1,r2 /* leftshift */
+
+ srx 7,8,r0,r1,r2 /* eXtended right shift (two input regs) */
+
+ rl r0,r1,r2 /* rotate left */
+ rr r0,r1,r2 /* rotate right */
+ nand r0,r1,r2 /* clear bits (notmask + and) */
+
+ orx 7,8,r0,r1,r2 /* eXtended OR */
+
+ /* Copy instruction. This is a virtual instruction
+ * translated to more lowlevel stuff like OR. */
+ mov r0,r2 /* copy data */
+
+ /* Jumps */
+ jmp label /* unconditional jump */
+ jand r0,r1,label /* jump if binary AND */
+ jnand r0,r1,label /* jump if not binary AND */
+ js r0,r1,label /* jump if all bits set */
+ jns r0,r1,label /* jump if not all bits set */
+ je r0,r1,label /* jump if equal */
+ jne r0,r1,label /* jump if not equal */
+ jls r0,r1,label /* jump if less (signed) */
+ jges r0,r1,label /* jump if greater or equal (signed) */
+ jgs r0,r1,label /* jump if greater (signed) */
+ jles r0,r1,label /* jump if less or equal (signed) */
+ jl r0,r1,label /* jump if less */
+ jge r0,r1,label /* jump if greater or equal */
+ jg r0,r1,label /* jump if greater */
+ jle r0,r1,label /* jump if less or equal */
+
+ jzx 7,8,r0,r1,label /* Jump if zero after shift and mask */
+ jnzx 7,8,r0,r1,label /* Jump if nonzero after shift and mask */
+
+ /* jump on external conditions */
+ jext ECOND_MAC_ON,label /* jump if external condition is TRUE */
+ jnext ECOND_MAC_ON,label /* jump if external condition is FALSE */
+
+ /* Subroutines */
+ call lr0,label /* store PC in lr0, call func at label */
+ ret lr0,lr1 /* store PC in lr0, return to lr1
+ * Both link registers can be the same
+ * and don't interfere. */
+
+ /* TKIP sbox lookup */
+ tkiph r0,r2 /* Lookup high */
+ tkiphs r0,r2 /* Lookup high, byteswap */
+ tkipl r0,r2 /* Lookup low */
+ tkipls r0,r2 /* Lookup low, byteswap */
+
+ nap /* sleep until event */
+
+ /* raw instruction */
+ @160 r0,r1,r2 /* equivalent to or r0,r1,r2 */
@1C0 @C11, @C22, @BC3
- ; Support for directional jumps.
- ; Directional jumps can be used to conveniently jump inside of
- ; functions without using function specific label prefixes. Note
- ; that this does not establish a sub-namespace, though. "loop"
- ; and "out" are still in the global namespace and can't be used
- ; anymore for absolute jumps (Assembler will warn about duplication).
+ /* Support for directional jumps.
+ * Directional jumps can be used to conveniently jump inside of
+ * functions without using function specific label prefixes. Note
+ * that this does not establish a sub-namespace, though. "loop"
+ * and "out" are still in the global namespace and can't be used
+ * anymore for absolute jumps (Assembler will warn about duplication).
+ */
function_a:
jl r0, r1, out+
loop:
nap
jmp loop-
out:
+ mov r0, r0
ret lr0, lr1
function_b:
nap
jmp loop-
out:
+ mov r0, r0
ret lr0, lr1
-; The assembler has support for fancy assemble-time
-; immediate constant expansion. This is called "complex immediates".
-; Complex immediates are _always_ clamped by parentheses. There is no
-; operator precedence. You must use parentheses to tell precedence.
+/* The assembler has support for fancy assemble-time
+ * immediate constant expansion. This is called "complex immediates".
+ * Complex immediates are _always_ clamped by parentheses. There is no
+ * operator precedence. You must use parentheses to tell precedence.
+ */
mov (2 + 3),r0
mov (6 - 2),r0
mov (2 * 3),r0
mov (4 >> (((((~5 | 0x21)))) | (~((10) & 2)))),r0
-; Some regression testing for the assembler follows
- mov 2,off0 ; test memory stuff
- xor 0x124,r1,[0x0,off0] ; test memory stuff
- xor 0x124,r0,[0x0] ; test memory stuff
- mov -34,r0 ; negative dec numbers are supported
- or r0,r1,@BC2 ; We also support single raw operands
- mov 0xEEEE,r0 ; MOV supports up to 16bit
- jand 0x3800,r0,label ; This is emulated by jnzx
- jnand 0x3800,r0,label ; This is emulated by jzx
- or spr06c,0,spr06c ; Can have one spr input and one spr output
- or [0],0,[0] ; Can have one mem input and one mem output
- mov testlabel, r0 ; Can use label as immediate value
-
-
-; The .initvals section generates an "Initial Values" file
-; with the name "foobar" in this example, which is uploaded
-; by the kernel driver on load. This is useful for writing ucode
-; specific values to the chip without bloating the small ucode
-; memory space with this initialization stuff.
-; Values are written in order they appear here.
+/* Some regression testing for the assembler follows */
+ mov 2,off0 /* test memory stuff */
+ xor 0x124,r1,[0x0,off0] /* test memory stuff */
+ xor 0x124,r0,[0x0] /* test memory stuff */
+ mov -34,r0 /* negative dec numbers are supported */
+ or r0,r1,@BC2 /* We also support single raw operands */
+ mov 0xEEEE,r0 /* MOV supports up to 16bit */
+ jand 0x3800,r0,label /* This is emulated by jnzx */
+ jnand 0x3800,r0,label /* This is emulated by jzx */
+ or spr06c,0,spr06c /* Can have one spr input and one spr output */
+ or [0],0,[0] /* Can have one mem input and one mem output */
+ mov testlabel, r0 /* Can use label as immediate value */
+ mov r0,r1;mov r2, r3 /* ; does split instructions */
+ mov [(1+1)],[(2+2),off0] /* Can use complex immediates as memory offsets */
+ orx (0 + 1), (1 * 2), 0, 0, r0 /* Allow complex immediates as M or S */
+
+
+/* The .initvals section generates an "Initial Values" file
+ * with the name "foobar" in this example, which is uploaded
+ * by the kernel driver on load. This is useful for writing ucode
+ * specific values to the chip without bloating the small ucode
+ * memory space with this initialization stuff.
+ * Values are written in order they appear here.
+ */
.initvals(foobar)
- mmio16 0x1234, 0xABC ; Write 0x1234 to MMIO register 0xABC
- mmio32 0x12345678, 0xABC ; Write 0x12345678 to MMIO register 0xABC
- phy 0x1234, 0xABC ; Write 0x1234 to PHY register 0xABC
- radio 0x1234, 0xABC ; Write 0x1234 to RADIO register 0xABC
- shm16 0x1234, 0x0001, 0x0002 ; Write 0x1234 to SHM routing 0x0001, register 0x0002
- shm32 0x12345678, 0x0001, 0x0002 ; Write 0x12345678 to SHM routing 0x0001, register 0x0002
+ mmio16 0x1234, 0xABC /* Write 0x1234 to MMIO register 0xABC */
+ mmio32 0x12345678, 0xABC /* Write 0x12345678 to MMIO register 0xABC */
+ phy 0x1234, 0xABC /* Write 0x1234 to PHY register 0xABC */
+ radio 0x1234, 0xABC /* Write 0x1234 to RADIO register 0xABC */
+ shm16 0x1234, 0x0001, 0x0002 /* Write 0x1234 to SHM routing 0x0001, register 0x0002 */
+ shm32 0x12345678, 0x0001, 0x0002 /* Write 0x12345678 to SHM routing 0x0001, register 0x0002 */
+ tram 0x12345678, 0x1234 /* Write 0x12345678 to Template Ram offset 0x1234 */
+
+
+// vim: syntax=b43 ts=8