test.asm 5.88 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/* 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 */
22 23
%arch	5

24
/* Program entry point */
Michael Büsch's avatar
Michael Büsch committed
25 26 27 28
%start	testlabel

#define	PSM_BRC		spr848

29
#define ECOND_MAC_ON	(0x20 | 4)
Michael Büsch's avatar
Michael Büsch committed
30

31 32 33 34
%assert ((((1))) == ((((2 - 1) & 0xFF))))
%assert ((1 == 2) || (1 == (0xFF & 1)))
%assert (1 != (~1))
%assert ((1 == (2 - 1)) && (2 == 2))
Michael Büsch's avatar
Michael Büsch committed
35 36 37 38

.text

label:
39 40 41 42 43
	/* 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 */
Michael Büsch's avatar
Michael Büsch committed
44 45

testlabel:
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
	/* 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 */
94 95
	jext	ECOND_MAC_ON,label  /* jump if external condition is TRUE */
	jnext	ECOND_MAC_ON,label  /* jump if external condition is FALSE */
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

	/* 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 */
Michael Büsch's avatar
Michael Büsch committed
113 114 115
	@1C0	@C11, @C22, @BC3


116 117 118 119 120 121 122
	/* 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).
	 */
Michael Büsch's avatar
Michael Büsch committed
123 124 125 126 127 128
function_a:
	jl r0, r1, out+
 loop:
	nap
	jmp loop-
 out:
129
	mov r0, r0
Michael Büsch's avatar
Michael Büsch committed
130 131 132 133 134 135 136 137
	ret lr0, lr1

function_b:
	jl r0, r1, out+
 loop:
	nap
	jmp loop-
 out:
138
	mov r0, r0
Michael Büsch's avatar
Michael Büsch committed
139 140 141
	ret lr0, lr1


142 143 144 145 146
/* 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.
 */
Michael Büsch's avatar
Michael Büsch committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
	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


162 163 164 165 166 167 168 169 170 171 172 173 174 175
/* 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 */
176
	orx	(0 + 1), (1 * 2), 0, 0, r0 /* Allow complex immediates as M or S */
177 178 179 180 181 182 183 184 185


/* 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.
 */
Michael Büsch's avatar
Michael Büsch committed
186
.initvals(foobar)
187 188 189 190 191 192 193 194 195
	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 */


// vim: syntax=b43 ts=8