xitoa.S
Upload User: zcw0111
Upload Date: 2021-05-17
Package Size: 48k
Code Size: 8k
Category:

3G develop

Development Platform:

C/C++

  1. ;---------------------------------------------------------------------------;
  2. ; Extended itoa, puts, printf and atoi                     (C)ChaN, 2006
  3. ;
  4. ; Module size: 277/261 words (max)
  5. ;
  6. #define USE_XPUTS
  7. #define USE_XITOA
  8. #define USE_XPRINTF
  9. #define CR_CRLF
  10. #define USE_XATOI
  11. .nolist
  12. #include <avr/io.h> // Include device specific definitions.
  13. .list
  14. #ifdef SPM_PAGESIZE // Recent devices have "lpm Rd,Z+" and "movw".
  15. .macro _LPMI reg
  16. lpm reg, Z+
  17. .endm
  18. .macro _MOVW dh,dl, sh,sl
  19. movw dl, sl
  20. .endm
  21. #else // Earlier devices do not have "lpm Rd,Z+" nor "movw".
  22. .macro _LPMI reg
  23. lpm
  24. mov reg, r0
  25. adiw ZL, 1
  26. .endm
  27. .macro _MOVW dh,dl, sh,sl
  28. mov dl, sl
  29. mov dh, sh
  30. .endm
  31. #endif
  32. ;---------------------------------------------------------------------------
  33. ; Stub function to forward to user output function
  34. ;
  35. ;Prototype: void xputc (char chr // a character to be output
  36. ; );
  37. ;Size: 17/17 words
  38. .section .bss
  39. .global xfunc_out ; xfunc_out must be initialized before using this module.
  40. xfunc_out: .ds.w 1
  41. .section .text
  42. .global xputc
  43. .func xputc
  44. xputc:
  45. #ifdef CR_CRLF
  46. cpi r24, 10 ;LF --> CRLF
  47. brne 1f ;
  48. ldi r24, 13 ;
  49. rcall 1f ;
  50. ldi r24, 10 ;/
  51. 1:
  52. #endif
  53. push ZH
  54. push ZL
  55. lds ZL, xfunc_out+0 ;Pointer to the registered output function.
  56. lds ZH, xfunc_out+1 ;/
  57. sbiw ZL, 0
  58. breq 2f
  59. icall
  60. 2: pop ZL
  61. pop ZH
  62. ret
  63. .endfunc
  64. ;---------------------------------------------------------------------------
  65. ; Direct ROM string output
  66. ;
  67. ;Prototype: void xputs (const prog_char *str // rom string to be output
  68. ; );
  69. ;Size: 10/7 words
  70. #ifdef USE_XPUTS
  71. .global xputs
  72. .func xputs
  73. xputs:
  74. _MOVW ZH,ZL, r25,r24 ; Z = pointer to rom string
  75. 1: _LPMI r24
  76. cpi r24, 0
  77. breq 2f
  78. rcall xputc
  79. rjmp 1b
  80. 2: ret
  81. .endfunc
  82. #endif
  83. ;---------------------------------------------------------------------------
  84. ; Extended direct numeral string output (32bit version)
  85. ;
  86. ;Prototype: void xitoa (long value, // value to be output
  87. ;                       char radix, // radix
  88. ;                       char width); // minimum width
  89. ;Size: 59/59 words
  90. ;
  91. #ifdef USE_XITOA
  92. .global xitoa
  93. .func xitoa
  94. xitoa:
  95. ;r25:r22 = value, r20 = base, r18 = digits
  96. clr r31 ;r31 = stack level
  97. ldi r30, ' ' ;r30 = sign
  98. ldi r19, ' ' ;r19 = filler
  99. sbrs r20, 7 ;When base indicates signd format and the value
  100. rjmp 0f ;is minus, add a '-'.
  101. neg r20 ;
  102. sbrs r25, 7 ;
  103. rjmp 0f ;
  104. ldi r30, '-' ;
  105. com r22 ;
  106. com r23 ;
  107. com r24 ;
  108. com r25 ;
  109. adc r22, r1 ;
  110. adc r23, r1 ;
  111. adc r24, r1 ;
  112. adc r25, r1 ;/
  113. 0: sbrs r18, 7 ;When digits indicates zero filled,
  114. rjmp 1f ;filler is '0'.
  115. neg r18 ;
  116. ldi r19, '0' ;/
  117. ;----- string conversion loop
  118. 1: ldi r21, 32 ;r26 = r25:r22 % r20
  119. clr r26 ;r25:r22 /= r20
  120. 2: lsl r22 ;
  121. rol r23 ;
  122. rol r24 ;
  123. rol r25 ;
  124. rol r26 ;
  125. cp r26, r20 ;
  126. brcs 3f ;
  127. sub r26, r20 ;
  128. inc r22 ;
  129. 3: dec r21 ;
  130. brne 2b ;/
  131. cpi r26, 10 ;r26 is a numeral digit '0'-'F'
  132. brcs 4f ;
  133. subi r26, -7 ;
  134. 4: subi r26, -'0' ;/
  135. push r26 ;Stack it
  136. inc r31 ;/
  137. cp r22, r1 ;Repeat until r25:r22 gets zero
  138. cpc r23, r1 ;
  139. cpc r24, r1 ;
  140. cpc r25, r1 ;
  141. brne 1b ;/
  142. cpi r30, '-' ;Minus sign if needed
  143. brne 5f ;
  144. push r30 ;
  145. inc r31 ;/
  146. 5: cp r31, r18 ;Filler
  147. brcc 6f ;
  148. push r19 ;
  149. inc r31 ;
  150. rjmp 5b ;/
  151. 6: pop r24 ;Flush stacked digits and exit
  152. rcall xputc ;
  153. dec r31 ;
  154. brne 6b ;/
  155. ret
  156. .endfunc
  157. #endif
  158. ;---------------------------------------------------------------------------;
  159. ; Formatted string output (16/32bit version)
  160. ;
  161. ;Prototype:
  162. ; void xprintf (const prog_char *format, ...);
  163. ;Size: 104/94 words
  164. ;
  165. #ifdef USE_XPRINTF
  166. .global xprintf
  167. .func xprintf
  168. xprintf:
  169. push YH
  170. push YL
  171. in YL, _SFR_IO_ADDR(SPL)
  172. #ifdef SPH
  173. in YH, _SFR_IO_ADDR(SPH)
  174. #else
  175. clr YH
  176. #endif
  177. #if FLASHEND > 0x1FFFF
  178. adiw YL, 6 ;Y = pointer to arguments
  179. #else
  180. adiw YL, 5 ;Y = pointer to arguments
  181. #endif
  182. ld ZL, Y+ ;Z = pointer to format string
  183. ld ZH, Y+ ;/
  184. 0: _LPMI r24 ;Get a format char
  185. cpi r24, 0 ;End of format string?
  186. breq 90f ;/
  187. cpi r24, '%' ;Is format?
  188. breq 20f ;/
  189. 1: rcall xputc ;Put a normal character
  190. rjmp 0b ;/
  191. 90: pop YL
  192. pop YH
  193. ret
  194. 20: ldi r18, 0 ;r18: digits
  195. clt ;T: filler
  196. _LPMI r21 ;Get flags
  197. cpi r21, '%' ;Is a %?
  198. breq 1b ;/
  199. cpi r21, '0' ;Zero filled?
  200. brne 23f ;
  201. set ;/
  202. 22: _LPMI r21 ;Get width
  203. 23: cpi r21, '9'+1 ;
  204. brcc 24f ;
  205. subi r21, '0' ;
  206. brcs 90b ;
  207. lsl r18 ;
  208. mov r0, r18 ;
  209. lsl r18 ;
  210. lsl r18 ;
  211. add r18, r0 ;
  212. add r18, r21 ;
  213. rjmp 22b ;/
  214. 24: brtc 25f ;get value (low word)
  215. neg r18 ;
  216. 25: ld r24, Y+ ;
  217. ld r25, Y+ ;/
  218. cpi r21, 'c' ;Is type character?
  219. breq 1b ;/
  220. cpi r21, 's' ;Is type RAM string?
  221. breq 50f ;/
  222. cpi r21, 'S' ;Is type ROM string?
  223. breq 60f ;/
  224. _MOVW r23,r22,r25,r24 ;r25:r22 = value
  225. clr r24 ;
  226. clr r25 ;
  227. clt ;/
  228. cpi r21, 'l' ;Is long int?
  229. brne 26f ;
  230. ld r24, Y+ ;get value (high word)
  231. ld r25, Y+ ;
  232. set ;
  233. _LPMI r21 ;/
  234. 26: cpi r21, 'd' ;Is type signed decimal?
  235. brne 27f ;/
  236. ldi r20, -10 ;
  237. brts 40f ;
  238. sbrs r23, 7 ;
  239. rjmp 40f ;
  240. ldi r24, -1 ;
  241. ldi r25, -1 ;
  242. rjmp 40f ;/
  243. 27: cpi r21, 'u' ;Is type unsigned decimal?
  244. ldi r20, 10 ;
  245. breq 40f ;/
  246. cpi r21, 'X' ;Is type hexdecimal?
  247. ldi r20, 16 ;
  248. breq 40f ;/
  249. cpi r21, 'b' ;Is type binary?
  250. ldi r20, 2 ;
  251. breq 40f ;/
  252. rjmp 90b ;abort
  253. 40: push ZH ;Output the value
  254. push ZL ;
  255. rcall xitoa ;
  256. 42: pop ZL ;
  257. pop ZH ;
  258. rjmp 0b ;/
  259. 50: push ZH ;Put a string on the RAM
  260. push ZL
  261. _MOVW ZH,ZL, r25,r24
  262. 51: ld r24, Z+
  263. cpi r24, 0
  264. breq 42b
  265. rcall xputc
  266. rjmp 51b
  267. 60: push ZH ;Put a string on the ROM
  268. push ZL
  269. rcall xputs
  270. rjmp 42b
  271. .endfunc
  272. #endif
  273. ;---------------------------------------------------------------------------
  274. ; Extended numeral string input
  275. ;
  276. ;Prototype:
  277. ; char xatoi (           /* 1: Successful, 0: Failed */
  278. ;      const char **str, /* pointer to pointer to source string */
  279. ;      long *res         /* result */
  280. ; );
  281. ;Size: 94/91 words
  282. ;
  283. #ifdef USE_XATOI
  284. .global xatoi
  285. .func xatoi
  286. xatoi:
  287. _MOVW r1, r0, r23, r22
  288. _MOVW XH, XL, r25, r24
  289. ld ZL, X+
  290. ld ZH, X+
  291. clr r18 ;r21:r18 = 0;
  292. clr r19 ;
  293. clr r20 ;
  294. clr r21 ;/
  295. clt ;T = 0;
  296. ldi r25, 10 ;r25 = 10;
  297. rjmp 41f ;/
  298. 40: adiw ZL, 1 ;Z++;
  299. 41: ld r22, Z ;r22 = *Z;
  300. cpi r22, ' ' ;if(r22 == ' ') continue
  301. breq 40b ;/
  302. brcs 70f ;if(r22 < ' ') error;
  303. cpi r22, '-' ;if(r22 == '-') {
  304. brne 42f ; T = 1;
  305. set ; continue;
  306. rjmp 40b ;}
  307. 42: cpi r22, '9'+1 ;if(r22 > '9') error;
  308. brcc 70f ;/
  309. cpi r22, '0' ;if(r22 < '0') error;
  310. brcs 70f ;/
  311. brne 51f ;if(r22 > '0') cv_start;
  312. ldi r25, 8 ;r25 = 8;
  313. adiw ZL, 1 ;r22 = *(++Z);
  314. ld r22, Z ;/
  315. cpi r22, ' '+1 ;if(r22 <= ' ') exit;
  316. brcs 80f ;/
  317. cpi r22, 'b' ;if(r22 == 'b') {
  318. brne 43f ; r25 = 2;
  319. ldi r25, 2 ; cv_start;
  320. rjmp 50f ;}
  321. 43: cpi r22, 'x' ;if(r22 != 'x') error;
  322. brne 51f ;/
  323. ldi r25, 16 ;r25 = 16;
  324. 50: adiw ZL, 1 ;Z++;
  325. ld r22, Z ;r22 = *Z;
  326. 51: cpi r22, ' '+1 ;if(r22 <= ' ') break;
  327. brcs 80f ;/
  328. cpi r22, 'a' ;if(r22 >= 'a') r22 =- 0x20;
  329. brcs 52f ;
  330. subi r22, 0x20 ;/
  331. 52: subi r22, '0' ;if((r22 -= '0') < 0) error;
  332. brcs 70f ;/
  333. cpi r22, 10 ;if(r22 >= 10) {
  334. brcs 53f ; r22 -= 7;
  335. subi r22, 7 ; if(r22 < 10) 
  336. cpi r22, 10 ;
  337. brcs 70f ;}
  338. 53: cp r22, r25 ;if(r22 >= r25) error;
  339. brcc 70f ;/
  340. 60: ldi r24, 33 ;r21:r18 *= r25;
  341. sub r23, r23 ;
  342. 61: brcc 62f ;
  343. add r23, r25 ;
  344. 62: lsr r23 ;
  345. ror r21 ;
  346. ror r20 ;
  347. ror r19 ;
  348. ror r18 ;
  349. dec r24 ;
  350. brne 61b ;/
  351. add r18, r22 ;r21:r18 += r22;
  352. adc r19, r24 ;
  353. adc r20, r24 ;
  354. adc r21, r24 ;/
  355. rjmp 50b ;repeat
  356. 70: ldi r24, 0
  357. rjmp 81f
  358. 80: ldi r24, 1
  359. 81: brtc 82f
  360. clr r22
  361. com r18
  362. com r19
  363. com r20
  364. com r21
  365. adc r18, r22
  366. adc r19, r22
  367. adc r20, r22
  368. adc r21, r22
  369. 82: st -X, ZH
  370. st -X, ZL
  371. _MOVW XH, XL, r1, r0
  372. st X+, r18
  373. st X+, r19
  374. st X+, r20
  375. st X+, r21
  376. clr r1
  377. ret
  378. .endfunc
  379. #endif