summaryrefslogtreecommitdiffstats
path: root/assembler/test.asm
blob: cea8724e682606a6b46971ffe21a01007df8a3d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/* 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 */
%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:
	/* MUL instruction */
	mul	r0,r1,r2	/* mul, r2 := msb, spr6d := lsb */

	/* 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 */
	jdn	r0,r1,label	/* jump if difference is negative */
	jdpz	r0,r1,label	/* jump if difference is non negative */
	jdp	r0,r1,label	/* jump if difference is positive */
	jdnz	r0,r1,label	/* jump if difference is non positive */

	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).
	 */
function_a:
	jl r0, r1, out+
 loop:
	nap
	jmp loop-
 out:
	mov r0, r0
	ret lr0, lr1

function_b:
	jl r0, r1, out+
 loop:
	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.
 */
	mov	(2 + 3),r0
	mov	(6 - 2),r0
	mov	(2 * 3),r0
	mov	(10 / 5),r0
	mov	(1 | 2),r0
	mov	(3 & 2),r0
	mov	(3 ^ 2),r0
	mov	(~1),r0
	mov	(2 << 3),r0
	mov	(8 >> 2),r0
	mov	(1 << (0x3 + 2)),r0
	mov	(1 + (2 + (3 + 4))),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 */
	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 */
	tram	0x12345678, 0x1234		/* Write 0x12345678 to Template Ram offset 0x1234 */


// vim: syntax=b43 ts=8
bues.ch cgit interface