?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. #ifndef included_atof24
  2. #define included_atof24
  3. #include "f24mul.z80"
  4. #include "ascii_to_uint8.z80"
  5. #include "f24pow10_LUT.z80"
  6.  
  7.  
  8. #ifndef TOK_ENG
  9. #define TOK_ENG 'e'
  10. #endif
  11.  
  12. ; Negative sign
  13. #ifndef TOK_NEG
  14. #define TOK_NEG '-'
  15. #endif
  16.  
  17. ; Decimal point
  18. #ifndef TOK_DECIMAL
  19. #define TOK_DECIMAL '.'
  20. #endif
  21.  
  22.  
  23.  
  24.  
  25. #define ptr_sto scrap+9
  26. atof24:
  27. ;Inputs:
  28. ;  HL points to the string
  29. ;Output:
  30. ;  AHL is the f24 float
  31. ;  scrap is the pointer to the end of the string
  32. ;Destroys:
  33. ;  BC, DE
  34. ;  4 bytes at scrap
  35. ;
  36. ;Check if there is a negative sign.
  37. ;   Save for later
  38. ;   Advance ptr
  39.   ld a,(hl)
  40.   sub TOK_NEG
  41.   sub 1
  42.   push af
  43.   jr nc,$+3
  44.   inc hl
  45. ;Skip all leading zeroes
  46.   ld a,(hl)
  47.   cp '0'
  48.   jr z,$-4      ;jumps back to the `inc hl`
  49.  
  50. ;Set exponent to 0
  51.   ld b,0
  52. ;Check if the next char is TOK_DECIMAL
  53.   sub TOK_DECIMAL
  54.   or a      ;to reset the carry flag
  55.   jr nz,atof24_skip_1
  56.   .db $FE   ;start of cp *
  57. ;Get rid of zeroes
  58.   dec b
  59.   inc hl
  60.   ld a,(hl)
  61.   cp '0'
  62.   jr z,$-5      ;jumps back to the `dec b`
  63.   scf
  64. atof24_skip_1:
  65. ; at this point, we ought to pointing at our first non-zero digit, unless all
  66. ; digits were 0, in which case we might be pointing to TOK_ENG
  67.   rl c
  68.   ld a,(hl)
  69.   sub '0'
  70.   cp 10
  71.   jp nc,atof24_zero_check_eng
  72.   srl c
  73.  
  74. ;Now we read in the next 6 digits
  75.   ld de,scrap+2
  76.   call ascii_to_uint8
  77.   call ascii_to_uint8
  78.   call ascii_to_uint8
  79. ;Now `scrap` holds the 3-digit base-100 number.
  80. ;b is the exponent
  81. ;if carry flag is set, just need to get rid of remaining digits
  82. ;Otherwise, need to get rid of remaining digits, while incrementing the exponent
  83.  
  84.   sbc a,a
  85.   ld c,a
  86. atof24_loop_1:
  87.   ld a,(hl)
  88.   cp TOK_DECIMAL
  89.   jr nz,$+8
  90.   dec c
  91.   jp pe,atof24_skip_7
  92.   jr atof24_skip_2  ; else C was already FF, then a decimal was already encountered
  93.  
  94.   sub '0'
  95.   cp 10
  96.   jr nc,atof24_skip_6
  97. atof24_skip_7:
  98. ; carry flag is set
  99.   inc hl
  100.   ld a,b
  101.   adc a,c
  102.   ; if carry flag is set, then we added 0
  103.   jr c,atof24_loop_1
  104.   jp z,atof24_inf
  105.   ld b,a
  106.   jr atof24_loop_1
  107.  
  108. atof24_skip_6:
  109.   ld a,(hl)
  110. ;Now check for engineering `E` to modify the exponent
  111.   cp TOK_ENG
  112.   call z,atof24_str_eng_exp
  113. atof24_skip_2:
  114.   ex de,hl  ; DE points to the end of the string
  115.  
  116. ;Gotta multiply the number at (scrap) by 2^17
  117.   ld hl,(scrap)
  118.   ld a,(scrap+2)
  119.   ld (ptr_sto),de ; save the pointer to the end of the string
  120.   ld e,a
  121.   ld d,-100
  122.   call atof24_scrap_times_256
  123.   push bc
  124.   call atof24_scrap_times_256
  125.   push bc
  126.   call atof24_scrap_times_256
  127.   pop hl
  128.   pop de
  129.   ld h,e
  130.  
  131. ;HLC holds the 3-digit significand, need to normalize it
  132. ; make sure it isn't zero
  133.   ld a,c
  134.   or h
  135.   or l
  136.   jp z,atof24_zero
  137.  
  138.   pop af
  139.   ld a,c
  140.   ld c,$7E  ;0x3F * 2 because we'll be shifting down later
  141.   rr c
  142.  
  143. atof24_loop_3:
  144.   dec c
  145.   add a,a
  146.   adc hl,hl
  147.   jr nc,atof24_loop_3
  148. ; round
  149.   add a,a
  150.   jr nc,+_
  151.   inc l
  152.   jr nz,+_
  153.   inc h
  154.   jr nz,+_
  155.   inc c
  156. _:
  157.   ex de,hl
  158. ;CDE * 10^B
  159.  
  160.   xor a
  161.   sub b
  162.   jp p,atof24_small
  163.   ld a,b
  164.   cp 20
  165.   jr c,$+9
  166.   ld a,c
  167.   or %01111111
  168.   ld hl,0
  169.   ret
  170.  
  171.   cp 10
  172.   jr c,atof24_mul
  173.   sub 10
  174.   push af
  175.   ld a,$60
  176.   ld hl,$2A06
  177.   jr atof24_continue
  178.  
  179. atof24_small:
  180.   cp 20
  181.   jr c,$+6
  182.   xor a
  183.   ld h,a
  184.   ld l,a
  185.   ret
  186.  
  187.   cp 10
  188.   jr c,atof24_mul
  189.   ld a,b
  190.   add a,10
  191.   push af
  192.   ld a,$1D
  193.   ld hl,$B7CE
  194. atof24_continue:
  195.   call f24mul
  196.   ex de,hl
  197.   pop bc
  198.   ld c,a
  199. atof24_mul:
  200.   ld a,b
  201.   neg
  202.   add a,19
  203.  
  204.   ld b,a
  205.   add a,a
  206.   add a,b
  207.   add a,(f24pow10_LUT+2)&255
  208.   ld l,a
  209.   adc a,(f24pow10_LUT+2)>>8
  210.   sub l
  211.   ld h,a
  212.   ld a,(hl)
  213.   dec hl
  214.   ld b,(hl)
  215.   dec hl
  216.   ld l,(hl)
  217.   ld h,b
  218. ;AHL * CDE
  219.   jp f24mul
  220.  
  221.  
  222.  
  223.  
  224. atof24_str_eng_exp:
  225. ; HL points to the string, B is the current exponent, returns adjusted exponent in B
  226.   ld e,0
  227.   inc hl
  228.   ld a,(hl)
  229.   sub TOK_NEG   ;negative exponent?
  230.   ld c,a        ;backup result
  231.   jr nz,atof24_skip_5
  232.   jr atof24_skip_3
  233. atof24_loop_2:
  234.   ld d,a  ; save the digit to add
  235.  
  236. ; make sure E doesn't exceed 2
  237.   ld a,e
  238.   cp 3
  239.   jr nc,atof24_eng_overflow
  240.  
  241.   add a,a
  242.   add a,a
  243.   add a,e
  244.   add a,a ; E*10
  245.   add a,d ; E*10+D
  246.   ld e,a
  247.  
  248. atof24_skip_3:
  249.   inc hl
  250. atof24_skip_5:
  251.   ld a,(hl)
  252.   sub '0'
  253.   cp 10
  254.   jr c,atof24_loop_2
  255.  
  256.   ld a,e
  257.   cp 20
  258.   jr nc,atof24_eng_overflow
  259.   ld a,c
  260.   or a
  261.   ld a,b
  262.   jr nz,atof24_skip_4
  263.   sub e
  264.   .db $FE  ; start of `cp *` to skip the next byte
  265. atof24_skip_4:
  266.   add a,e
  267.   ld b,a
  268.   ret
  269.  
  270. atof24_scrap_times_256:
  271.   call atof24_scrap_times_16
  272. atof24_scrap_times_16:
  273.   call atof24_scrap_times_4
  274. atof24_scrap_times_4:
  275.   call atof24_scrap_times_2
  276. atof24_scrap_times_2:
  277. ;EHL is a 3-digit base-100 number that needs to be multiplied by 256
  278.  
  279. ; multiply the bottom 2 digits by 2
  280.   add hl,hl
  281.  
  282. ; check for overflow
  283.   ld a,l
  284.   add a,d
  285.   jr nc,$+4
  286.   ld l,a
  287.   inc h
  288.  
  289.   ld a,h
  290.   add a,d
  291.   jr nc,$+3
  292.   ld h,a
  293.  
  294.   ld a,e
  295.   adc a,a
  296.   add a,d
  297.   jr c,$+3
  298.   sub d
  299.   ld e,a
  300.  
  301.   rl c
  302.   ret
  303.  
  304. atof24_eng_overflow:
  305.   pop af  ; pop off the return address for the call
  306.   ld a,c
  307.   or a
  308.   jr z,atof24_zero
  309. atof24_inf:
  310. ;return inf
  311.   pop af
  312.   ld hl,0
  313.   ld a,-1
  314.   rra
  315.   ret
  316.  
  317. atof24_zero_check_eng:
  318.   cp TOK_ENG-'0'
  319.   jr nz,atof24_zero_write_hl
  320.   ; otherwise, we need to read through the engineering exponent
  321.   inc hl
  322.   ld a,(hl)
  323.   cp TOK_NEG
  324.   jr nz,$+3
  325.   inc hl
  326.   ld a,(hl)
  327.   sub '0'
  328.   cp 10
  329.   jr c,$-6  ; jumps back to the `inc hl`
  330. atof24_zero_write_hl:
  331.   ld (ptr_sto),hl ; save the pointer to the end of the string
  332. atof24_zero:
  333.   pop af
  334.   xor a
  335.   ld h,a
  336.   ld l,a
  337.   ret
  338.  
  339. #endif
  340.