test.asm 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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. /* The target architecture. Supported versions are 5 and 15 */
  19. %arch 5
  20. /* Program entry point */
  21. %start testlabel
  22. #define PSM_BRC spr848
  23. #define ECOND_MAC_ON (0x20 | 4)
  24. %assert ((((1))) == ((((2 - 1) & 0xFF))))
  25. %assert ((1 == 2) || (1 == (0xFF & 1)))
  26. %assert (1 != (~1))
  27. %assert ((1 == (2 - 1)) && (2 == 2))
  28. .text
  29. /* Inline assertion inside of a complex immediate.
  30. * The %assert() expression will always return zero. */
  31. mov (1 + (%assert(1 == ((1 + 2) - 2)))), r0
  32. label:
  33. /* MUL instruction */
  34. mul r0,r1,r2 /* mul, r2 := msb, spr6d := lsb */
  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 */
  40. testlabel:
  41. /* SUB instructions */
  42. sub r0,r1,r2 /* sub */
  43. sub. r0,r1,r2 /* sub, set carry */
  44. subc r0,r1,r2 /* sub with carry */
  45. subc. r0,r1,r2 /* sub with carry, set carry */
  46. sra r0,r1,r2 /* arithmetic rightshift */
  47. /* Logical instructions */
  48. or r0,r1,r2 /* bitwise OR */
  49. and r0,r1,r2 /* bitwise AND */
  50. xor r0,r1,r2 /* bitwise XOR */
  51. sr r0,r1,r2 /* rightshift */
  52. sl r0,r1,r2 /* leftshift */
  53. srx 7,8,r0,r1,r2 /* eXtended right shift (two input regs) */
  54. rl r0,r1,r2 /* rotate left */
  55. rr r0,r1,r2 /* rotate right */
  56. nand r0,r1,r2 /* clear bits (notmask + and) */
  57. orx 7,8,r0,r1,r2 /* eXtended OR */
  58. /* Copy instruction. This is a virtual instruction
  59. * translated to more lowlevel stuff like OR. */
  60. mov r0,r2 /* copy data */
  61. /* Jumps */
  62. jmp label /* unconditional jump */
  63. jand r0,r1,label /* jump if binary AND */
  64. jnand r0,r1,label /* jump if not binary AND */
  65. js r0,r1,label /* jump if all bits set */
  66. jns r0,r1,label /* jump if not all bits set */
  67. je r0,r1,label /* jump if equal */
  68. jne r0,r1,label /* jump if not equal */
  69. jls r0,r1,label /* jump if less (signed) */
  70. jges r0,r1,label /* jump if greater or equal (signed) */
  71. jgs r0,r1,label /* jump if greater (signed) */
  72. jles r0,r1,label /* jump if less or equal (signed) */
  73. jl r0,r1,label /* jump if less */
  74. jge r0,r1,label /* jump if greater or equal */
  75. jg r0,r1,label /* jump if greater */
  76. jle r0,r1,label /* jump if less or equal */
  77. jdn r0,r1,label /* jump if difference is negative */
  78. jdpz r0,r1,label /* jump if difference is non negative */
  79. jdp r0,r1,label /* jump if difference is positive */
  80. jdnz r0,r1,label /* jump if difference is non positive */
  81. jzx 7,8,r0,r1,label /* Jump if zero after shift and mask */
  82. jnzx 7,8,r0,r1,label /* Jump if nonzero after shift and mask */
  83. /* jump on external conditions */
  84. jext ECOND_MAC_ON,label /* jump if external condition is TRUE */
  85. jnext ECOND_MAC_ON,label /* jump if external condition is FALSE */
  86. /* Subroutines */
  87. call lr0,label /* store PC in lr0, call func at label */
  88. ret lr0,lr1 /* store PC in lr0, return to lr1
  89. * Both link registers can be the same
  90. * and don't interfere. */
  91. /* TKIP sbox lookup */
  92. tkiph r0,r2 /* Lookup high */
  93. tkiphs r0,r2 /* Lookup high, byteswap */
  94. tkipl r0,r2 /* Lookup low */
  95. tkipls r0,r2 /* Lookup low, byteswap */
  96. nap /* sleep until event */
  97. /* raw instruction */
  98. @160 r0,r1,r2 /* equivalent to or r0,r1,r2 */
  99. @1C0 @C11, @C22, @BC3
  100. /* Support for directional jumps.
  101. * Directional jumps can be used to conveniently jump inside of
  102. * functions without using function specific label prefixes. Note
  103. * that this does not establish a sub-namespace, though. "loop"
  104. * and "out" are still in the global namespace and can't be used
  105. * anymore for absolute jumps (Assembler will warn about duplication).
  106. */
  107. function_a:
  108. jl r0, r1, out+
  109. loop:
  110. nap
  111. jmp loop-
  112. out:
  113. mov r0, r0
  114. ret lr0, lr1
  115. function_b:
  116. jl r0, r1, out+
  117. loop:
  118. nap
  119. jmp loop-
  120. out:
  121. mov r0, r0
  122. ret lr0, lr1
  123. /* The assembler has support for fancy assemble-time
  124. * immediate constant expansion. This is called "complex immediates".
  125. * Complex immediates are _always_ clamped by parentheses. There is no
  126. * operator precedence. You must use parentheses to tell precedence.
  127. */
  128. mov (2 + 3),r0
  129. mov (6 - 2),r0
  130. mov (2 * 3),r0
  131. mov (10 / 5),r0
  132. mov (1 | 2),r0
  133. mov (3 & 2),r0
  134. mov (3 ^ 2),r0
  135. mov (~1),r0
  136. mov (2 << 3),r0
  137. mov (8 >> 2),r0
  138. mov (1 << (0x3 + 2)),r0
  139. mov (1 + (2 + (3 + 4))),r0
  140. mov (4 >> (((((~5 | 0x21)))) | (~((10) & 2)))),r0
  141. /* Some regression testing for the assembler follows */
  142. mov 2,off0 /* test memory stuff */
  143. xor 0x124,r1,[0x0,off0] /* test memory stuff */
  144. xor 0x124,r0,[0x0] /* test memory stuff */
  145. mov -34,r0 /* negative dec numbers are supported */
  146. or r0,r1,@BC2 /* We also support single raw operands */
  147. mov 0xEEEE,r0 /* MOV supports up to 16bit */
  148. jand 0x3800,r0,label /* This is emulated by jnzx */
  149. jnand 0x3800,r0,label /* This is emulated by jzx */
  150. or spr06c,0,spr06c /* Can have one spr input and one spr output */
  151. or [0],0,[0] /* Can have one mem input and one mem output */
  152. mov testlabel, r0 /* Can use label as immediate value */
  153. mov r0,r1;mov r2, r3 /* ; does split instructions */
  154. mov [(1+1)],[(2+2),off0] /* Can use complex immediates as memory offsets */
  155. orx (0 + 1), (1 * 2), 0, 0, r0 /* Allow complex immediates as M or S */
  156. /* The .initvals section generates an "Initial Values" file
  157. * with the name "foobar" in this example, which is uploaded
  158. * by the kernel driver on load. This is useful for writing ucode
  159. * specific values to the chip without bloating the small ucode
  160. * memory space with this initialization stuff.
  161. * Values are written in order they appear here.
  162. */
  163. .initvals(foobar)
  164. mmio16 0x1234, 0xABC /* Write 0x1234 to MMIO register 0xABC */
  165. mmio32 0x12345678, 0xABC /* Write 0x12345678 to MMIO register 0xABC */
  166. phy 0x1234, 0xABC /* Write 0x1234 to PHY register 0xABC */
  167. radio 0x1234, 0xABC /* Write 0x1234 to RADIO register 0xABC */
  168. shm16 0x1234, 0x0001, 0x0002 /* Write 0x1234 to SHM routing 0x0001, register 0x0002 */
  169. shm32 0x12345678, 0x0001, 0x0002 /* Write 0x12345678 to SHM routing 0x0001, register 0x0002 */
  170. tram 0x12345678, 0x1234 /* Write 0x12345678 to Template Ram offset 0x1234 */
  171. // vim: syntax=b43 ts=8