home *** CD-ROM | disk | FTP | other *** search
/ ftp.uni-stuttgart.de/pub/systems/acorn/ / Acorn.tar / Acorn / acornet / dev / assembler / extasm.spk / !extASM / Manuals / Assembly < prev   
Text File  |  1995-07-08  |  9KB  |  336 lines

  1.  
  2. Some tips and code examples for ARM assembly
  3. --------------------------------------------
  4.  
  5. IF A=1 AND B=2 THEN
  6. -------------------
  7. CMP      R1,#1
  8. CMPEQ    R2,#2
  9. BEQ      Routine
  10.  
  11. IF A=1 OR B=2 THEN
  12. ------------------
  13. CMP      R1,#1
  14. CMPNE    R2,#2
  15. BEQ      Routine
  16.  
  17. IF A>=0 AND A<=10 THEN
  18. ----------------------
  19. Three ways
  20. ----------
  21. MOV      R2,#10
  22. CMP      R1,#0
  23. CMPGE    R2,R1
  24. BGE      Routine
  25.  
  26. CMP      R1,#0
  27. RSBGES   R2,R1,#10
  28. BGE      Routine
  29.  
  30. CMP      R1,#10
  31. BLS      Routine (!)
  32.  
  33. You can also string these compares together, e.g.
  34. IF A=1 AND B=2 AND C=3 ... THEN
  35. -------------------------------
  36. CMP      R1,#1
  37. CMPEQ    R2,#2
  38. CMPEQ    R3,#3
  39. ...
  40. BEQ      Routine
  41.  
  42. You can combine discrete tests and range tests, e.g.
  43. IF A=10 OR B<=20 THEN
  44. ---------------------
  45. CMP      R1,#10
  46. CMPNE    R2,#20
  47. BLE      Routine
  48.  
  49. IF A=10 AND B<=20 THEN
  50. ----------------------
  51. CMP      R2,#20
  52. CMPLE    R1,#10
  53. BEQ      Routine
  54.  
  55.  
  56. You can even combine AND and OR, like this
  57. IF A=1 AND B=2 OR C=3 OR D=4 THEN
  58. ---------------------------------
  59. CMP      R1,#1
  60. CMPEQ    R2,#2
  61. CMPNE    R3,#3
  62. CMPNE    R4,#4
  63. BEQ      Routine
  64.  
  65. IF (A=1 OR B=2 OR C=3) AND D=4 AND E=5 OR F=6
  66. ---------------------------------------------
  67. CMP      R1,#1
  68. CMPNE    R2,#2
  69. CMPNE    R3,#3
  70. CMPEQ    R4,#4
  71. CMPEQ    R5,#5
  72. CMPNE    R6,#6
  73.  
  74. Isn't ARM assembly wonderful? Try to do this in 6 S cycles on an Intel
  75. processor.
  76.  
  77.  
  78. You can also combine calculations with compares, like
  79. IF A=1 THEN
  80.   Var=1
  81.   IF B=2 THEN Var2=1
  82. ENDIF
  83. --------------------
  84. CMP      R1,#1
  85. MOVEQ    R10,#1
  86. CMPEQ    R2,#2
  87. MOVEQ    R11,#1
  88.  
  89.  
  90. Jump tables
  91. -----------
  92. CASE A OF
  93. WHEN 0: Routine0
  94. WHEN 1: Routine1
  95. ...
  96. OTHERWISE Error
  97. ENDCASE
  98. ----------------
  99. CMP      R1,#Max_Value
  100. ADDLS    R15,R15,R1,LSL #2
  101. B        Error
  102. B        Routine0
  103. B        Routine1
  104. ...
  105.  
  106. Multiply by 2^n (i.e. 2,4,8,16,32...)
  107. -------------------------------------
  108. MOV      R1,R1,LSL #n
  109.  
  110. Multiply by 2^n+1 (i.e. 3,5,9,17,33...)
  111. ---------------------------------------
  112. ADD      R1,R1,R1,LSL #n
  113.  
  114. Multiply by 2^n-1 (i.e. 3,7,15,31...)
  115. -------------------------------------
  116. RSB      R1,R1,R1,LSL #n
  117.  
  118. Multiply by e.g. 10
  119. -------------------
  120. ADD      R1,R1,R1,LSL #2     ; Multiply by 5
  121. MOV      R1,R1,LSL #1        ; Multiply by 2
  122.  
  123. Shifting down of a number with more than 32 bits
  124. (for multi-precision arithmetics, like a 64 bit divide)
  125. -------------------------------------------------------
  126. 128Bit_Number=128Bit_Number >> 1
  127. --------------------------------
  128. MOVS     R3,R3,LSR #1
  129. MOVS     R2,R2,RRX
  130. MOVS     R1,R1,RRX
  131. MOV      R0,R0,RRX
  132.  
  133. Tricks to increase the speed
  134. ----------------------------
  135. Unrolling the loop (this avoids having a lot of branches,
  136. in proportion to the rest of the code)
  137. ---------------------------------------------------------
  138. FOR I=1 TO 100
  139. (Some calculation)
  140. NEXT
  141. ------------------
  142. MOV      R1,#10       ; Count backwards to avoid an extra compare
  143. .Loop
  144. #rept 10
  145. (Some calculation)
  146. #endr
  147. SUBS     R1,R1,#1
  148. BNE      Loop
  149.  
  150. Jump-out method (for early termination of compare etc.)
  151. -------------------------------------------------------
  152. IF A$="T" AND B$="E" AND C$="S" D$="T" THEN
  153. -------------------------------------------
  154. CMP      R1,#'T'
  155. BNE      No_Match
  156. CMP      R2,#'E'
  157. BNE      No_Match
  158. CMP      R3,#'S'
  159. BNE      No_Match
  160. CMP      R4,#'T'
  161. BNE      No_Match
  162. .Match
  163.  
  164. Alternatively, if it is not that important to jump out quickly,
  165. but that the routine is quick
  166. ---------------------------------------------------------------
  167. CMP      R1,#'T'
  168. CMPEQ    R2,#'E'
  169. CMPEQ    R3,#'S'
  170. CMPEQ    R4,#'T'
  171. BEQ      Match
  172.  
  173.  
  174. Taking advantage of the conditional execution. If a branch is used,
  175. then the pipeline has to be emptied, and instructions will be read
  176. from the new location. If one can use condition execution, then the
  177. pipeline doesn't have to be emptied.
  178. -------------------------------------------------------------------
  179. IF A=1 THEN B=1 ELSE B=2
  180. ------------------------
  181. First attempt
  182. -------------
  183. CMP      R1,#1
  184. BNE      Not_1
  185. MOV      R2,#1
  186. B        Done
  187. .Not_1
  188. MOV      R2,#2
  189. .Done
  190.  
  191. This takes 5 or 7 cycles, depending on A.
  192.  
  193. Using conditional execution
  194. ---------------------------
  195. CMP      R1,#1
  196. MOVEQ    R2,#1
  197. MOVNE    R2,#2
  198.  
  199. This takes just 3 cycles, no matter what.
  200.  
  201. Another example, making upper case letters (doesn't take into account
  202. the letters above ASCII 127)
  203. ---------------------------------------------------------------------
  204. CMP      R1,#'a'
  205. RSBGES   R2,R1,#'z'
  206. BICGE    R1,R1,#32
  207.  
  208. You can also implement new instructions, for example the following
  209. ------------------------------------------------------------------
  210. BL       R0
  211.  
  212. This can be written as
  213. ----------------------
  214. MOV      R14,R15
  215. MOV      R15,R0
  216.  
  217.  
  218. Global data
  219. -----------
  220. If you have a fair amount of data that is 'global', that is, it should
  221. be reachable from the whole program, then it can be an advantage to have
  222. a register pointing to the data. This way, a lot of expansion of ADRs
  223. and LDR/STRs can be avoided.
  224.  
  225. This can be set up easilly in the extASM assembler with the 'relative'
  226. statement. Here is an example:
  227.  
  228. ADR   R12,Global_Data
  229. ...
  230.  
  231. .Global_Data
  232. relative R12    ; R12 is the 'global data' pointer
  233. {
  234. .Label  DCD   0 ; Label  = 0  These are marked specially that they are
  235. .Label2 DCD   0 ; Label2 = 4  relative to R12, in ADR and Load/Store.
  236. ...
  237. }
  238.  
  239. LDR   R1,Label    --->  LDR R1,[R12,#Label]
  240. LDR   R2,Label2   --->  LDR R2,[R12,#Label2]
  241.  
  242.  
  243. If you set up such a data area right, you can have really much data in
  244. it, without having to auto-expand the instructions pointing to the data.
  245. This is because the ADD or SUB that an ADR is coded as, can have any
  246. immediate offset, as long as it can be RORed to an 8-bit quantity.
  247.  
  248. As often is the case, this can be shown most easily with an example:
  249.  
  250. relative R12                                 Address
  251. {                                            ----------------
  252. .Label        DCD   0       ; Label        = 0    = &00000000
  253. .Label2       DCD   0       ; Label2       = 4    = &00000004
  254. ...
  255. .AnotherLabel DCD   0       ; AnotherLabel = 1008 = &000003F0
  256. ALIGN 256
  257. .Block1       DBB   1024    ; Block1       = 1024 = &00000400
  258. .Block2       DBB   4096    ; Block2       = 2048 = &00000800
  259. }
  260.  
  261. The 'relative' area is 6 K, but each label is reachable with an ADR
  262. which is not expanded! This is because the bigger blocks are aligned,
  263. and is a multiple of the alignment in length. Here the alignment is 256,
  264. but any alignment may be used. With 256 as alignment, you can have a
  265. data area with different blocks, to a total of 256*256 = 64 K.
  266.  
  267. LDR/STR have an 12 bit byte offset, so they can only access +/-4 K from
  268. the relative register.
  269.  
  270.  
  271. With extASM you can set up 'virtual' relative areas, which means that no
  272. code in them is stored, only the variables are set up. This way, you don't
  273. have to save the data with the object file, if it's not needed. An example
  274. to illustrate this:
  275.  
  276.  
  277. #set Position=0         ; This determines where R12, the 'relative'
  278.                         ; register, will point, in this case at the
  279.                         ; start of the data area. This can be used to
  280.                         ; take advantage of the +/- sign for the ADR's
  281.                         ; address area.
  282.  
  283. Code
  284. ----
  285. ADR   R12,Data+Position ; R12 is the 'relative' register
  286. ...
  287. ADR   R1,Label          ; An example. Also LDR/STR can be used
  288.  
  289. Global data area
  290. ----------------
  291. .Data
  292. relative R12,#-Position                    ; Relative offset=0
  293. {
  294. .Start
  295. .Label   DCD   123      ; Label=0          ; The data here
  296. .Label2  DCD   234      ; Label2=4         ; will be stored
  297. .End
  298. }
  299.  
  300. relative R12,#-Position+End-Start,virtual  ; Relative offset=8
  301. {
  302. .Label3  DCD   0        ; Label3=8         ; The data here will not be
  303. .Label4  DCD   0        ; Label4=12        ; stored, only the labels
  304. }
  305.  
  306.  
  307. The alignment can also be done incrementally, so you don't need to
  308. reserve more memory than necessary. An example:
  309.  
  310. relative R12                         Address
  311. {                                    -----------------
  312. .ByteLabel    DCB   0                0     = &00000000
  313. .ByteLabel2   DCB   0                1     = &00000001
  314. ALIGN
  315. .Label        DCD   0                4     = &00000004
  316. .Label2       DCD   0                8     = &00000008
  317. ...
  318. .YetOneLabel  DCD   0                100   = &00000064
  319. ALIGN 128
  320. .Block1       DBB   128              128   = &00000080
  321. .Block2       DBB   align(Size,128)  256   = &00000100
  322. ...
  323. .YetOneBlock  DBB   128              768   = &00000300
  324. ALIGN 256
  325. .BiggerBlock  DBB   256              1024  = &00000400
  326. .BiggerBlock2 DBB   512              1536  = &00000600
  327. ...
  328. }
  329.  
  330. This way, a single, unexpanded 'relative' ADR can address huge amounts of
  331. memory, as long as the blocks are aligned.
  332.  
  333. ⌐ Terje Sletteb° 1995
  334.  
  335. This file can be copied freely.
  336.