xitoa.S 9.2 KB

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