b43-asm, b43-dasm: Add 5 new instructions.
[b43-tools.git] / assembler / test.asm
1 /* This is a bcm43xx microcode assembly example.
2  *
3  * Registers:
4  *      GPRs:                   r0 - r63        (General Purpose Register)
5  *      Offset Registers:       off0 - off5
6  *      SPRs:                   spr000          (Special Purpose Register)
7  *
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
11  *
12  * To access memory, two methods can be used. Examples follow.
13  * Direct linear:
14  *      mov r0,[0xCA]
15  * Indirect through Offset Register (pointer):
16  *      mov r0,[0xCA,off0]
17  */
18
19
20 /* The target architecture. Supported versions are 5 and 15 */
21 %arch   5
22
23 /* Program entry point */
24 %start  testlabel
25
26 #define PSM_BRC         spr848
27
28 #define ECOND_MAC_ON    (0x20 | 4)
29
30 %assert ((((1))) == ((((2 - 1) & 0xFF))))
31 %assert ((1 == 2) || (1 == (0xFF & 1)))
32 %assert (1 != (~1))
33 %assert ((1 == (2 - 1)) && (2 == 2))
34
35 .text
36
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
40
41 label:
42         /* MUL instruction */
43         mul     r0,r1,r2        /* mul, r2 := msb, spr6d := lsb */
44
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 */
50
51 testlabel:
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 */
57
58         sra     r0,r1,r2        /* arithmetic rightshift */
59
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 */
66
67         srx     7,8,r0,r1,r2    /* eXtended right shift (two input regs) */
68
69         rl      r0,r1,r2        /* rotate left */
70         rr      r0,r1,r2        /* rotate right */
71         nand    r0,r1,r2        /* clear bits (notmask + and) */
72
73         orx     7,8,r0,r1,r2    /* eXtended OR */
74
75         /* Copy instruction. This is a virtual instruction
76          * translated to more lowlevel stuff like OR. */
77         mov     r0,r2           /* copy data */
78
79         /* Jumps */
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 */
99
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 */
102
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 */
106
107         /* Subroutines */
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. */
112
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 */
118
119         nap                     /* sleep until event */
120
121         /* raw instruction */
122         @160    r0,r1,r2        /* equivalent to  or r0,r1,r2 */
123         @1C0    @C11, @C22, @BC3
124
125
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).
132          */
133 function_a:
134         jl r0, r1, out+
135  loop:
136         nap
137         jmp loop-
138  out:
139         mov r0, r0
140         ret lr0, lr1
141
142 function_b:
143         jl r0, r1, out+
144  loop:
145         nap
146         jmp loop-
147  out:
148         mov r0, r0
149         ret lr0, lr1
150
151
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.
156  */
157         mov     (2 + 3),r0
158         mov     (6 - 2),r0
159         mov     (2 * 3),r0
160         mov     (10 / 5),r0
161         mov     (1 | 2),r0
162         mov     (3 & 2),r0
163         mov     (3 ^ 2),r0
164         mov     (~1),r0
165         mov     (2 << 3),r0
166         mov     (8 >> 2),r0
167         mov     (1 << (0x3 + 2)),r0
168         mov     (1 + (2 + (3 + 4))),r0
169         mov     (4 >> (((((~5 | 0x21)))) | (~((10) & 2)))),r0
170
171
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 */
187
188
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.
195  */
196 .initvals(foobar)
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 */
204
205
206 // vim: syntax=b43 ts=8