1 /* This is a bcm43xx microcode assembly example.
4 * GPRs: r0 - r63 (General Purpose Register)
5 * Offset Registers: off0 - off5
6 * SPRs: spr000 (Special Purpose Register)
8 * SPRs map to the driver-side IHR registers.
9 * An SPR offset is converted to an IHR offset by the following
10 * calculation: IHR = (SPR + 0x400) * 2
12 * To access memory, two methods can be used. Examples follow.
15 * Indirect through Offset Register (pointer):
20 /* The target architecture. Supported versions are 5 and 15 */
23 /* Program entry point */
26 #define PSM_BRC spr848
28 #define ECOND_MAC_ON (0x20 | 4)
30 %assert ((((1))) == ((((2 - 1) & 0xFF))))
31 %assert ((1 == 2) || (1 == (0xFF & 1)))
33 %assert ((1 == (2 - 1)) && (2 == 2))
37 /* Inline assertion inside of a complex immediate.
38 * The %assert() expression will always return zero. */
39 mov (1 + (%assert(1 == ((1 + 2) - 2)))), r0
43 mul r0,r1,r2 /* mul, r2 := msb, spr6d := lsb */
45 /* ADD instructions */
46 add r0,r1,r2 /* add */
47 add. r0,r1,r2 /* add, set carry */
48 addc r0,r1,r2 /* add with carry */
49 addc. r0,r1,r2 /* add with carry, set carry */
52 /* SUB instructions */
53 sub r0,r1,r2 /* sub */
54 sub. r0,r1,r2 /* sub, set carry */
55 subc r0,r1,r2 /* sub with carry */
56 subc. r0,r1,r2 /* sub with carry, set carry */
58 sra r0,r1,r2 /* arithmetic rightshift */
60 /* Logical instructions */
61 or r0,r1,r2 /* bitwise OR */
62 and r0,r1,r2 /* bitwise AND */
63 xor r0,r1,r2 /* bitwise XOR */
64 sr r0,r1,r2 /* rightshift */
65 sl r0,r1,r2 /* leftshift */
67 srx 7,8,r0,r1,r2 /* eXtended right shift (two input regs) */
69 rl r0,r1,r2 /* rotate left */
70 rr r0,r1,r2 /* rotate right */
71 nand r0,r1,r2 /* clear bits (notmask + and) */
73 orx 7,8,r0,r1,r2 /* eXtended OR */
75 /* Copy instruction. This is a virtual instruction
76 * translated to more lowlevel stuff like OR. */
77 mov r0,r2 /* copy data */
80 jmp label /* unconditional jump */
81 jand r0,r1,label /* jump if binary AND */
82 jnand r0,r1,label /* jump if not binary AND */
83 js r0,r1,label /* jump if all bits set */
84 jns r0,r1,label /* jump if not all bits set */
85 je r0,r1,label /* jump if equal */
86 jne r0,r1,label /* jump if not equal */
87 jls r0,r1,label /* jump if less (signed) */
88 jges r0,r1,label /* jump if greater or equal (signed) */
89 jgs r0,r1,label /* jump if greater (signed) */
90 jles r0,r1,label /* jump if less or equal (signed) */
91 jl r0,r1,label /* jump if less */
92 jge r0,r1,label /* jump if greater or equal */
93 jg r0,r1,label /* jump if greater */
94 jle r0,r1,label /* jump if less or equal */
95 jdn r0,r1,label /* jump if difference is negative */
96 jdpz r0,r1,label /* jump if difference is non negative */
97 jdp r0,r1,label /* jump if difference is positive */
98 jdnz r0,r1,label /* jump if difference is non positive */
100 jzx 7,8,r0,r1,label /* Jump if zero after shift and mask */
101 jnzx 7,8,r0,r1,label /* Jump if nonzero after shift and mask */
103 /* jump on external conditions */
104 jext ECOND_MAC_ON,label /* jump if external condition is TRUE */
105 jnext ECOND_MAC_ON,label /* jump if external condition is FALSE */
108 call lr0,label /* store PC in lr0, call func at label */
109 ret lr0,lr1 /* store PC in lr0, return to lr1
110 * Both link registers can be the same
111 * and don't interfere. */
113 /* TKIP sbox lookup */
114 tkiph r0,r2 /* Lookup high */
115 tkiphs r0,r2 /* Lookup high, byteswap */
116 tkipl r0,r2 /* Lookup low */
117 tkipls r0,r2 /* Lookup low, byteswap */
119 nap /* sleep until event */
121 /* raw instruction */
122 @160 r0,r1,r2 /* equivalent to or r0,r1,r2 */
123 @1C0 @C11, @C22, @BC3
126 /* Support for directional jumps.
127 * Directional jumps can be used to conveniently jump inside of
128 * functions without using function specific label prefixes. Note
129 * that this does not establish a sub-namespace, though. "loop"
130 * and "out" are still in the global namespace and can't be used
131 * anymore for absolute jumps (Assembler will warn about duplication).
152 /* The assembler has support for fancy assemble-time
153 * immediate constant expansion. This is called "complex immediates".
154 * Complex immediates are _always_ clamped by parentheses. There is no
155 * operator precedence. You must use parentheses to tell precedence.
167 mov (1 << (0x3 + 2)),r0
168 mov (1 + (2 + (3 + 4))),r0
169 mov (4 >> (((((~5 | 0x21)))) | (~((10) & 2)))),r0
172 /* Some regression testing for the assembler follows */
173 mov 2,off0 /* test memory stuff */
174 xor 0x124,r1,[0x0,off0] /* test memory stuff */
175 xor 0x124,r0,[0x0] /* test memory stuff */
176 mov -34,r0 /* negative dec numbers are supported */
177 or r0,r1,@BC2 /* We also support single raw operands */
178 mov 0xEEEE,r0 /* MOV supports up to 16bit */
179 jand 0x3800,r0,label /* This is emulated by jnzx */
180 jnand 0x3800,r0,label /* This is emulated by jzx */
181 or spr06c,0,spr06c /* Can have one spr input and one spr output */
182 or [0],0,[0] /* Can have one mem input and one mem output */
183 mov testlabel, r0 /* Can use label as immediate value */
184 mov r0,r1;mov r2, r3 /* ; does split instructions */
185 mov [(1+1)],[(2+2),off0] /* Can use complex immediates as memory offsets */
186 orx (0 + 1), (1 * 2), 0, 0, r0 /* Allow complex immediates as M or S */
189 /* The .initvals section generates an "Initial Values" file
190 * with the name "foobar" in this example, which is uploaded
191 * by the kernel driver on load. This is useful for writing ucode
192 * specific values to the chip without bloating the small ucode
193 * memory space with this initialization stuff.
194 * Values are written in order they appear here.
197 mmio16 0x1234, 0xABC /* Write 0x1234 to MMIO register 0xABC */
198 mmio32 0x12345678, 0xABC /* Write 0x12345678 to MMIO register 0xABC */
199 phy 0x1234, 0xABC /* Write 0x1234 to PHY register 0xABC */
200 radio 0x1234, 0xABC /* Write 0x1234 to RADIO register 0xABC */
201 shm16 0x1234, 0x0001, 0x0002 /* Write 0x1234 to SHM routing 0x0001, register 0x0002 */
202 shm32 0x12345678, 0x0001, 0x0002 /* Write 0x12345678 to SHM routing 0x0001, register 0x0002 */
203 tram 0x12345678, 0x1234 /* Write 0x12345678 to Template Ram offset 0x1234 */
206 // vim: syntax=b43 ts=8