float.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. ; ************* Floating point library for AVR microprocessors *************
  2. ;
  3. ; Assembler AVRASM v. 1.21
  4. ; Processor AT90S2313, AT90S8515
  5. ; Code Size 256 words (512 bytes)
  6. ; **************************************************************************
  7. ; Author Y.Andrienko
  8. ; Phone (057-2) 44-85-40, 98-07-58
  9. ; FIDO 2:461/44.14
  10. ; E-mail yurik@aqua.kharkov.ua, aya@apexmail.com
  11. ;
  12. ; Last modification - 28.09.1999
  13. ; **************************************************************************
  14. ; Floating point number format: 3-bytes
  15. ; 1st - order - bit 7 - number sign (1 - negative number)
  16. ; 6 - order sign (1 - positive order)
  17. ; 0..5 - order value
  18. ; 2nd - mantissa low byte
  19. ; 3d - mantissa high byte
  20. ; !!! This variables must be defined in main programm !!!
  21. ;.def Float1O =r16
  22. ;.def Float1L =r17
  23. ;.def Float1H =r18
  24. ;
  25. ;.def Float2O =r19
  26. ;.def Float2L =r20
  27. ;.def Float2H =r21
  28. ;.def FTempO =r22
  29. ;.def FTempL =r23
  30. ;.def FTempH =r24
  31. ;.def FCnt =r25
  32. ; ************************************************************************
  33. ; Fix2Float - translate fixed format number to floating point format
  34. ; Float2Fix - translate floating point number to fixed format
  35. ; FNeg - negate floating point number
  36. ; SwapFl - exchange Float1 and Float2
  37. ; FAdd - floating point addition Float2=Float2+Float1
  38. ; FSub - floating point substraction Float2=Float2-Float1
  39. ; FMul - floating point multiplication Float2=Float2*Float1
  40. ; FDiv - floating point division Float2=Float1/Float2
  41. ;*************************************************************************
  42. ; translate number from fix to floating point format
  43. ; Input - 2-byte number in Float2L,Float2H
  44. ; Output - 3-byte floating point number in Float2
  45. ;
  46. ; high registers used - Float2O,Float2L,Float2H
  47. Fix2Float:
  48. clc ; clear carry
  49. tst Float2L ; check number for 0
  50. brne Fx2Fl_A
  51. tst Float2H
  52. brne Fx2Fl_A
  53. ldi Float2O,$40 ; if Float2L=Float2H=0 set number to 0
  54. ret
  55. Fx2Fl_A:
  56. ldi Float2O,$50 ; if fixed num # 0 set order to 50H
  57. Fx2Fl_B:
  58. sbrc Float2H,7 ; skip if bit 7#0
  59. ret ; else return
  60. rol FLoat2L ; shift number left
  61. rol Float2H
  62. dec Float2O ; and decrement order
  63. rjmp Fx2Fl_B ; continue while bit 7#1
  64. ; translate floating point number to fixed format
  65. ; Input - Float2
  66. ; Output - Float2L, Float2H
  67. ; carry=1 if overflow
  68. ;
  69. ; registers used - Float2O, Float2L, Float2H
  70. Float2Fix:
  71. sbrc Float2O,7 ; check number sign
  72. rjmp SetOverflow ; for negative number set overflow and return
  73. sbrs Float2O,6 ; check order sign
  74. rjmp Float2eq0 ; for neg.order set number to 0
  75. andi Float2O,$3f ; mask sign bits
  76. cpi Float2O,$11 ; check maximal order
  77. brlo Fl2Fx_A ; jump if order<11H
  78. rjmp SetOverflow ; else set overflow and return
  79. Fl2Fx_A:
  80. subi Float2O,$10
  81. neg Float2O ; Float2O=10H-Float2O
  82. Fl2Fx_C:
  83. clc ; clear carry
  84. tst Float2O ; check order
  85. brne Fl2Fx_B
  86. ret ; return if order 0
  87. Fl2Fx_B:
  88. ror Float2H ; shift right
  89. ror Float2L
  90. dec Float2O ; decrement order
  91. rjmp Fl2Fx_C ; repeat while order # 0
  92. Float2eq0:
  93. clr Float2L
  94. clr Float2H
  95. ret
  96. ; Change sign of floating point number Float2=-Float2
  97. ; Input - Float2
  98. ; Output - Float2
  99. ; registers used - Float2O,Float2L,Float2H
  100. FNeg:
  101. neg Float2O
  102. subi Float2O,$80
  103. neg Float2O
  104. clc
  105. ret
  106. ; Swap Float1 and Float2 numbers
  107. ; (Thanks for A.Redchhuk)
  108. SwapFl:
  109. ; it is it was
  110. eor Float1O,Float2O ; push Float1O
  111. eor Float2O,Float1O ; mov Float1O,Float2O
  112. eor Float1O,Float2O ; pop Float2O
  113. eor Float1L,Float2L ; push Float1L
  114. eor Float2L,Float1L ; mov Float1L,Float2L
  115. eor Float1L,Float2L ; pop Float2L
  116. eor Float1H,Float2H ; push Float1H
  117. eor Float2H,Float1H ; mov Float1H,Float2H
  118. eor Float1H,Float2H ; pop Float2H
  119. ret
  120. ; Floating point addition Float2=Float1+Float2
  121. ; Input - Float1, Float2
  122. ; Output - Float2
  123. ; registers used - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H
  124. FAdd:
  125. sbrc Float1O,7 ; skip if Float1>0
  126. rjmp FAdd_A ; jump if Float1<0
  127. sbrs Float2O,7 ; skip if Float2<0
  128. rjmp FAdd_B ; jump if FLoat1 and Float2 < 0
  129. ; if numbers signs not equal (Float1>0,Float2<0 or Float1<0, Float2>0)
  130. ; if Float1>0 Float2<0 result = Float1-Float2
  131. FAdd_C:
  132. rcall FNeg ; change Float2 sign
  133. rcall SwapFl
  134. rjmp FSub ; and continue in substraction programm
  135. ; If Float1<0,Float2>0 result = Float2-Float1
  136. FAdd_X:
  137. rcall SwapFl ; Change Float1 sign
  138. rcall FNeg
  139. rcall SwapFl
  140. rjmp FSub
  141. FAdd_A:
  142. sbrs Float2O,7 ; skip if Float1<0 and Float2<0
  143. rjmp FAdd_X
  144. ; if numbers signs are equal
  145. FAdd_B:
  146. tst Float1H ; check Float1 for 0
  147. brne FAdd_D
  148. tst Float1L
  149. brne FAdd_D
  150. ret ; if Float1=0 result =Float2
  151. FAdd_D:
  152. tst Float2H ; check Float2 for 0
  153. brne FAdd_E
  154. tst Float2L
  155. brne FAdd_E
  156. rjmp Fl1toFl2 ; if Float2=0 copy Float1 as result and return
  157. FAdd_E:
  158. cp Float2O,Float1O ; compare orders
  159. breq FAdd_G ; if orders are equal
  160. brlo FAdd_F ; if Float2O<Float1O
  161. rcall SwapFl ; else swap numbers
  162. FAdd_F:
  163. sub Float2O,Float1O
  164. neg Float2O ; Float2O=Float1O-Float2O
  165. cpi Float2O,$10
  166. brlo FAdd_H ; if Float1O-Float2O<16
  167. rjmp Fl1toFl2 ; else copy Float1 as result and return
  168. FAdd_H:
  169. clc ; clear carry
  170. ror Float2H ; shift Float2 right
  171. ror Float2L
  172. dec Float2O ; decrement order
  173. brne FAdd_H ; repeat while orders not equal
  174. ; if orders are equal
  175. FAdd_G:
  176. add Float2L,Float1L ; add numbers
  177. adc Float2H,Float1H
  178. brcs FAdd_I ; jump if carry set
  179. FAdd_J:
  180. mov Float2O,Float1O ; copy order value
  181. ret ; and return
  182. FAdd_I:
  183. ror FLoat2H ; shift number
  184. ror Float2L
  185. inc Float1O ; increment order
  186. rjmp FAdd_J
  187. ; Floating point numbers substraction Float2=Float1-Float2
  188. ; Input - Float1, Float2
  189. ; Output - Float2
  190. ; registers used - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H
  191. FSub:
  192. sbrc Float1O,7 ; skip if Float1>0
  193. rjmp FSub_A ; jump if Float1<0
  194. sbrs Float2O,7 ; skip if Float2<0
  195. rjmp FSub_B ; jump if Float1>0 and Float2>0
  196. ; if numbers signs not equal
  197. FSub_C:
  198. rcall SwapFl
  199. rcall FNeg ; change sign of 2nd number
  200. rcall SwapFl
  201. rjmp FAdd ; and continue in substraction programm
  202. FSub_A:
  203. sbrs Float2O,7 ; skip if Float2<0 and Float1<0
  204. rjmp FSub_C ; jump if Float2>0 (Float1<0)
  205. ; if signs of numbers are equal
  206. FSub_B:
  207. tst Float1H ; check Float1 for 0
  208. brne FSub_D
  209. tst Float1L
  210. brne FSub_D
  211. ret ; if Float1=0 result = Float2 - return
  212. FSub_D:
  213. tst Float2H ; check Float2 for 0
  214. brne FSub_E
  215. tst Float2L
  216. brne FSub_E
  217. rcall Fl1toFl2 ; if FLoat2=0, result = -Float1, copy an return
  218. rjmp FNeg ; change sign and return
  219. FSub_E:
  220. clt
  221. cp Float1O,Float2O ; compare orders
  222. breq FSub_G ; if orders are equal
  223. brlo FSub_F ; if Float1O<Float2O
  224. set ; set flag
  225. rcall SwapFl ; swap numbers if Float1O>Float2O
  226. FSub_F:
  227. sub Float1O,Float2O
  228. neg Float1O ; Float1O=Float2O-Float1O
  229. cpi Float1O,$10
  230. brlo FSub_H ; if Float2O-Float1O<16
  231. ret ; else result=Float2
  232. ; equalize orders
  233. FSub_H:
  234. clc
  235. ror Float1H ; shift Float right
  236. ror Float1L
  237. dec Float1O
  238. brne FSub_H ; repeat before orders not equal
  239. brtc FSub_G ;
  240. rcall SwapFl ; swap again
  241. clt
  242. FSub_G:
  243. cp Float2L,Float1L
  244. cpc Float2H,Float1H
  245. brlo FSub_I
  246. FSub_J:
  247. sub Float2L,Float1L ; add numbers
  248. sbc Float2H,Float1H
  249. sbrc Float2H,7 ; skip if MSB=0
  250. ret ; else return
  251. rjmp Fx2Fl_B ; normalise result
  252. FSub_I:
  253. rcall SwapFl ; swap numbers
  254. rcall FNeg ; change result sign
  255. rjmp FSub_J
  256. ror FLoat2H ; shift number
  257. ror Float2L
  258. inc Float2O ; increment order
  259. rcall FNeg ; and change sign
  260. ret ; else return
  261. ; Floating point multiplication Float2 = Float1 * Float2
  262. ; Input - Float1, Float2
  263. ; Output - Float2
  264. ; registers used - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H
  265. ; FTempO, FTempL, FCnt
  266. ;
  267. FMul:
  268. tst Float1H ; check Float1 for 0
  269. brne FMul_A
  270. tst Float1L
  271. brne FMul_A
  272. rjmp SetRes0 ; if Float1=0, set Float2=0 and return
  273. FMul_A:
  274. tst Float2H ; check Float2 for 0
  275. brne FMul_B
  276. tst Float2L
  277. brne FMul_B
  278. ret ; if Float2=0 - return
  279. FMul_B:
  280. mov FTempO,Float1O ; Find result sign
  281. eor FTempO,Float2O ; FTempO bit 7 equal result sign
  282. cbr Float1O,$80 ; reset numbers signs
  283. cbr Float2O,$80
  284. bst FTempO,7 ; save result sign in T
  285. add Float2O,Float1O ; add orders
  286. ldi Float1O,$40 ;
  287. add Float2O,Float1O
  288. bld Float2O,7
  289. ; 16x16 bits unsigned multiplication from ****AVR200**** application note
  290. FMul_D:
  291. clr FTempO ;clear 2 highest bytes of result
  292. clr FTempL
  293. ldi FCnt,16 ;init loop counter
  294. lsr Float2H
  295. ror Float2L
  296. FMul_E:
  297. brcc FMul_F ;if bit 0 of multiplier set
  298. add FTempO,Float1L ;add multiplicand Low to byte 2 of res
  299. adc FTempL,Float1H ;add multiplicand high to byte 3 of res
  300. FMul_F:
  301. ror FTempL ;shift right result byte 3
  302. ror FTempO ;rotate right result byte 2
  303. ror Float2H ;rotate result byte 1 and multiplier High
  304. ror Float2L ;rotate result byte 0 and multiplier Low
  305. dec FCnt ;decrement loop counter
  306. brne FMul_E ;if not done, loop more
  307. ; after multiplication - normalise result
  308. FMul_H:
  309. sbrc FTempL,7
  310. rjmp FMul_G ; jump if result is normalised
  311. rol Float2L ; shift number left
  312. rol Float2H
  313. rol FTempO
  314. rol FTempL
  315. dec Float2O ; decrement result order
  316. rjmp FMul_H
  317. FMul_G:
  318. bld Float2O,7 ; restore result sign from T
  319. mov Float2L,FTempO ; copy mantissa to result
  320. mov Float2H,FTempL
  321. ret
  322. ; Floating point division Float2 = Float1/Float2
  323. ; Input - Float1, Float2
  324. ; Output - Float2
  325. ; registers used - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H
  326. ; FTempO, FTempL, FTempH, FCnt
  327. FDiv:
  328. mov FTempO,Float1L ; Check Float1 for 0
  329. or FTempO,Float1H
  330. tst FTempO
  331. brne FDiv_A
  332. rjmp SetRes0 ; if Float1=0 - result = 0
  333. FDiv_A:
  334. sbrs Float2H,7
  335. rjmp SetOverflow ; if Float2 not normalized or 0 - overflow
  336. ldi FCnt,$10 ; bits counter
  337. mov FTempO,Float1O
  338. andi FTempO,$80 ; select sign bit
  339. add FTempO,Float2O ;
  340. bst FTempO,7 ; store result sign in T
  341. mov FTempO,Float1O ; read 1st number order
  342. sub FTempO,Float2O ; substract orders
  343. subi FTempO,-$41 ; add 41H
  344. bld FTempO,7 ; restore result sign
  345. clr Float1O ; clear orders
  346. clr Float2O
  347. clr FTempH
  348. ldi FTempL,1
  349. ; main division cykle
  350. FDiv_C:
  351. sbrs FTempL,0
  352. rjmp FDiv_D
  353. sub Float1L,Float2L
  354. sbc Float1H,Float2H
  355. sbc Float1O,Float2O ; set carry
  356. rjmp FDiv_E
  357. FDiv_D:
  358. add Float1L,Float2L
  359. adc Float1H,Float2H
  360. adc Float1O,Float2O
  361. FDiv_E:
  362. andi Float1O,$01
  363. push Float1O ; save order
  364. clc
  365. eor Float1O,Float2O
  366. brne FDiv_F
  367. sec
  368. FDiv_F:
  369. pop Float1O ; restore order
  370. rol FTempL
  371. rol FTempH
  372. clc ; clear carry
  373. rol Float1L
  374. rol Float1H
  375. mov Float1O,FTempH
  376. rol Float1O
  377. dec FCnt ; decremet counter
  378. brne FDiv_C ; repeate while FCnt#0
  379. mov Float2L,FTempL ; copy result
  380. mov Float2H,FTempH
  381. mov Float2O,FTempO
  382. rjmp Fx2Fl_B ; normalise result
  383. ; Common subroutines
  384. ; Set overflow flag and return
  385. SetOverflow:
  386. sec
  387. ret
  388. ; Copy Float1 to Float2
  389. Fl1toFl2:
  390. mov Float2O,Float1O
  391. mov Float2H,Float1H
  392. mov Float2L,Float1L
  393. ret
  394. ; Set result to 0 (Float2=0)
  395. SetRes0:
  396. clr Float2L ; set result=0
  397. clr Float2H
  398. ldi Float2O,$40
  399. ret