1 /* This is a bcm43xx microcode assembly example.
3 * In this example file, r0 and r1 are always input
4 * registers and r2 is output.
5 * For input we can always have constant values or (one) memory
6 * operand instead of the input registers shown here.
10 * Offset Registers: off0 - off5
13 * To access memory, two methods can be used. Examples follow.
16 * Indirect through Offset Register (pointer):
21 /* The target architecture. Supported versions are 5 and 15 */
24 /* Program entry point */
27 #define PSM_BRC spr848
29 #define ECOND_MAC_ON (0x20 | 4)
35 /* ADD instructions */
36 add r0,r1,r2 /* add */
37 add. r0,r1,r2 /* add, set carry */
38 addc r0,r1,r2 /* add with carry */
39 addc. r0,r1,r2 /* add with carry, set carry */
43 /* SUB instructions */
44 sub r0,r1,r2 /* sub */
45 sub. r0,r1,r2 /* sub, set carry */
46 subc r0,r1,r2 /* sub with carry */
47 subc. r0,r1,r2 /* sub with carry, set carry */
49 sra r0,r1,r2 /* arithmetic rightshift */
51 /* Logical instructions */
52 or r0,r1,r2 /* bitwise OR */
53 and r0,r1,r2 /* bitwise AND */
54 xor r0,r1,r2 /* bitwise XOR */
55 sr r0,r1,r2 /* rightshift */
56 sl r0,r1,r2 /* leftshift */
58 srx 7,8,r0,r1,r2 /* eXtended right shift (two input regs) */
60 rl r0,r1,r2 /* rotate left */
61 rr r0,r1,r2 /* rotate right */
62 nand r0,r1,r2 /* clear bits (notmask + and) */
64 orx 7,8,r0,r1,r2 /* eXtended OR */
66 /* Copy instruction. This is a virtual instruction
67 * translated to more lowlevel stuff like OR. */
68 mov r0,r2 /* copy data */
71 jmp label /* unconditional jump */
72 jand r0,r1,label /* jump if binary AND */
73 jnand r0,r1,label /* jump if not binary AND */
74 js r0,r1,label /* jump if all bits set */
75 jns r0,r1,label /* jump if not all bits set */
76 je r0,r1,label /* jump if equal */
77 jne r0,r1,label /* jump if not equal */
78 jls r0,r1,label /* jump if less (signed) */
79 jges r0,r1,label /* jump if greater or equal (signed) */
80 jgs r0,r1,label /* jump if greater (signed) */
81 jles r0,r1,label /* jump if less or equal (signed) */
82 jl r0,r1,label /* jump if less */
83 jge r0,r1,label /* jump if greater or equal */
84 jg r0,r1,label /* jump if greater */
85 jle r0,r1,label /* jump if less or equal */
87 jzx 7,8,r0,r1,label /* Jump if zero after shift and mask */
88 jnzx 7,8,r0,r1,label /* Jump if nonzero after shift and mask */
90 /* jump on external conditions */
91 jext ECOND_MAC_ON,r0,r0,label /* jump if external condition is TRUE */
92 jnext ECOND_MAC_ON,r0,r0,label /* jump if external condition is FALSE */
95 call lr0,label /* store PC in lr0, call func at label */
96 ret lr0,lr1 /* store PC in lr0, return to lr1
97 * Both link registers can be the same
98 * and don't interfere. */
100 /* TKIP sbox lookup */
101 tkiph r0,r2 /* Lookup high */
102 tkiphs r0,r2 /* Lookup high, byteswap */
103 tkipl r0,r2 /* Lookup low */
104 tkipls r0,r2 /* Lookup low, byteswap */
106 nap /* sleep until event */
108 /* raw instruction */
109 @160 r0,r1,r2 /* equivalent to or r0,r1,r2 */
110 @1C0 @C11, @C22, @BC3
113 /* Support for directional jumps.
114 * Directional jumps can be used to conveniently jump inside of
115 * functions without using function specific label prefixes. Note
116 * that this does not establish a sub-namespace, though. "loop"
117 * and "out" are still in the global namespace and can't be used
118 * anymore for absolute jumps (Assembler will warn about duplication).
137 /* The assembler has support for fancy assemble-time
138 * immediate constant expansion. This is called "complex immediates".
139 * Complex immediates are _always_ clamped by parentheses. There is no
140 * operator precedence. You must use parentheses to tell precedence.
152 mov (1 << (0x3 + 2)),r0
153 mov (1 + (2 + (3 + 4))),r0
154 mov (4 >> (((((~5 | 0x21)))) | (~((10) & 2)))),r0
157 /* Some regression testing for the assembler follows */
158 mov 2,off0 /* test memory stuff */
159 xor 0x124,r1,[0x0,off0] /* test memory stuff */
160 xor 0x124,r0,[0x0] /* test memory stuff */
161 mov -34,r0 /* negative dec numbers are supported */
162 or r0,r1,@BC2 /* We also support single raw operands */
163 mov 0xEEEE,r0 /* MOV supports up to 16bit */
164 jand 0x3800,r0,label /* This is emulated by jnzx */
165 jnand 0x3800,r0,label /* This is emulated by jzx */
166 or spr06c,0,spr06c /* Can have one spr input and one spr output */
167 or [0],0,[0] /* Can have one mem input and one mem output */
168 mov testlabel, r0 /* Can use label as immediate value */
169 mov r0,r1;mov r2, r3 /* ; does split instructions */
170 mov [(1+1)],[(2+2),off0] /* Can use complex immediates as memory offsets */
173 /* The .initvals section generates an "Initial Values" file
174 * with the name "foobar" in this example, which is uploaded
175 * by the kernel driver on load. This is useful for writing ucode
176 * specific values to the chip without bloating the small ucode
177 * memory space with this initialization stuff.
178 * Values are written in order they appear here.
181 mmio16 0x1234, 0xABC /* Write 0x1234 to MMIO register 0xABC */
182 mmio32 0x12345678, 0xABC /* Write 0x12345678 to MMIO register 0xABC */
183 phy 0x1234, 0xABC /* Write 0x1234 to PHY register 0xABC */
184 radio 0x1234, 0xABC /* Write 0x1234 to RADIO register 0xABC */
185 shm16 0x1234, 0x0001, 0x0002 /* Write 0x1234 to SHM routing 0x0001, register 0x0002 */
186 shm32 0x12345678, 0x0001, 0x0002 /* Write 0x12345678 to SHM routing 0x0001, register 0x0002 */
189 // vim: syntax=b43 ts=8