PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/device/lib/pic16/libc/stdlib/x_ftoa.c

https://gitlab.com/alx741/sdcc
C | 193 lines | 126 code | 35 blank | 32 comment | 8 complexity | 3efd3710ea022a15e252ae889962de5b MD5 | raw file
  1. /*-------------------------------------------------------------------------
  2. x_ftoa.c - wrapper function to use _convert_float
  3. Copyright (C) 2004, Vangelis Rokas <vrokas at otenet.gr>
  4. This library is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2.1, or (at your option) any
  7. later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this library; see the file COPYING. If not, write to the
  14. Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
  15. MA 02110-1301, USA.
  16. As a special exception, if you link this library with other files,
  17. some of which are compiled with SDCC, to produce an executable,
  18. this library does not by itself cause the resulting executable to
  19. be covered by the GNU General Public License. This exception does
  20. not however invalidate any other reasons why the executable file
  21. might be covered by the GNU General Public License.
  22. -------------------------------------------------------------------------*/
  23. #include <float.h>
  24. extern convert_frac;
  25. extern convert_int;
  26. /* char x_ftoa(float, __data char *, unsigned char, unsigned char); */
  27. extern POSTDEC1;
  28. extern PLUSW2;
  29. extern FSR0L;
  30. extern FSR0H;
  31. extern PREINC1;
  32. extern PREINC2;
  33. extern FSR2L;
  34. extern FSR2H;
  35. #define _vv0x00 0x00
  36. #define _vv0x01 0x01
  37. #define _vv0x02 0x02
  38. #define _vv0x03 0x03
  39. #define _vv0x04 0x04
  40. /* do not warn about unreferenced arguments/missing return values */
  41. #pragma save
  42. #pragma disable_warning 59
  43. #pragma disable_warning 85
  44. char x_cnvint_wrap(unsigned long num, __data char *buffer)
  45. {
  46. __asm
  47. movff _vv0x00, _POSTDEC1
  48. movff _vv0x01, _POSTDEC1
  49. movff _vv0x02, _POSTDEC1
  50. movff _vv0x03, _POSTDEC1
  51. movlw 2
  52. movff _PLUSW2, _vv0x00
  53. movlw 3
  54. movff _PLUSW2, _vv0x01
  55. movlw 4
  56. movff _PLUSW2, _vv0x02
  57. movlw 5
  58. movff _PLUSW2, _vv0x03
  59. movlw 6
  60. movff _PLUSW2, _FSR0L
  61. movlw 7
  62. movff _PLUSW2, _FSR0H
  63. call _convert_int
  64. /* return value is already in WREG */
  65. movff _PREINC1, _vv0x03
  66. movff _PREINC1, _vv0x02
  67. movff _PREINC1, _vv0x01
  68. movff _PREINC1, _vv0x00
  69. __endasm ;
  70. }
  71. char x_cnvfrac_wrap(unsigned long num, __data char *buffer, unsigned char prec)
  72. {
  73. num;
  74. buffer;
  75. prec;
  76. __asm
  77. movff _vv0x00, _POSTDEC1
  78. movff _vv0x01, _POSTDEC1
  79. movff _vv0x02, _POSTDEC1
  80. movff _vv0x03, _POSTDEC1
  81. movff _vv0x04, _POSTDEC1
  82. movlw 2
  83. movff _PLUSW2, _vv0x00
  84. movlw 3
  85. movff _PLUSW2, _vv0x01
  86. movlw 4
  87. movff _PLUSW2, _vv0x02
  88. movlw 5
  89. movff _PLUSW2, _vv0x03
  90. movlw 6
  91. movff _PLUSW2, _FSR0L
  92. movlw 7
  93. movff _PLUSW2, _FSR0H
  94. movlw 8
  95. movff _PLUSW2, _vv0x04
  96. call _convert_frac
  97. /* return value is already in WREG */
  98. movff _PREINC1, _vv0x04
  99. movff _PREINC1, _vv0x03
  100. movff _PREINC1, _vv0x02
  101. movff _PREINC1, _vv0x01
  102. movff _PREINC1, _vv0x00
  103. __endasm ;
  104. }
  105. #pragma restore
  106. union float_long {
  107. unsigned long l;
  108. float f;
  109. };
  110. char x_ftoa(float num, __data char *buffer, unsigned char buflen, unsigned char prec)
  111. {
  112. char len;
  113. char expn;
  114. unsigned long ll;
  115. unsigned long li;
  116. // volatile
  117. union float_long f_l;
  118. len = buflen;
  119. while(len--)buffer[len] = 0;
  120. f_l.f = num;
  121. if((f_l.l & SIGNBIT) == SIGNBIT) {
  122. f_l.l &= ~SIGNBIT;
  123. *buffer = '-';
  124. buffer++;
  125. }
  126. expn = EXCESS - EXP(f_l.l); // - 24;
  127. ll = MANT(f_l.l);
  128. li = 0;
  129. while( expn ) {
  130. if(expn < 0) {
  131. li <<= 1;
  132. if(ll & 0x00800000UL)li |= 1;
  133. ll <<= 1;
  134. expn++;
  135. } else {
  136. ll >>= 1;
  137. expn--;
  138. }
  139. }
  140. if(li)
  141. len = x_cnvint_wrap(li, buffer);
  142. else {
  143. *buffer = '0'; len = 1;
  144. }
  145. buffer += len;
  146. if(prec) {
  147. *buffer = '.'; len++;
  148. buffer++;
  149. len += x_cnvfrac_wrap(ll, buffer, 24-prec);
  150. buffer[ prec ] = '\0';
  151. }
  152. return (len);
  153. }