?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. #ifndef included_atof32
  2. #define included_atof32
  3. #include "f32mul.z80"
  4. #include "ascii_to_BCD.z80"
  5. #include "ascii_to_BCD.z80"
  6. #include "f32_pow10_LUT.z80"
  7.  
  8.  
  9. #ifndef TOK_ENG
  10. #define TOK_ENG 'e'
  11. #endif
  12.  
  13. ; Negative sign
  14. #ifndef TOK_NEG
  15. #define TOK_NEG '-'
  16. #endif
  17.  
  18. ; Decimal point
  19. #ifndef TOK_DECIMAL
  20. #define TOK_DECIMAL '.'
  21. #endif
  22.  
  23.  
  24.  
  25.  
  26. #define ptr_sto scrap
  27. atof32:
  28. ;Inputs:
  29. ;  HL points to the string
  30. ;  BC points to where to write the float
  31. ;Output:
  32. ;  AHL is the f32 float
  33. ;  scrap is the pointer to the end of the string
  34. ;Destroys:
  35. ;  BC, DE
  36. ;  2 bytes at scrap
  37. ;
  38. ;
  39.   call pushpop
  40.   push bc ; save the pointer to the output
  41. ;Check for a negative sign, save for later, and advance the pointer if so.
  42. ;   Advance ptr
  43.   ld a,(hl)
  44.   sub TOK_NEG
  45.   sub 1
  46.   push af
  47.   jr nc,$+3
  48.   inc hl
  49. ;Skip all leading zeroes
  50.   ld a,(hl)
  51.   cp '0'
  52.   jr z,$-4      ;jumps back to the `inc hl`
  53.  
  54. ;Set exponent to 0
  55.   ld b,0
  56. ;Check if the next char is TOK_DECIMAL
  57.   sub TOK_DECIMAL
  58.   or a      ;to reset the carry flag
  59.   jr nz,atof32_skip_1
  60.   .db $FE   ;start of cp *
  61. ;Get rid of zeroes
  62.   dec b
  63.   inc hl
  64.   ld a,(hl)
  65.   cp '0'
  66.   jr z,$-5      ;jumps back to the `dec b`
  67.   scf
  68. atof32_skip_1:
  69. ; at this point, we ought to pointing at our first non-zero digit, unless all
  70. ; digits were 0, in which case we might be pointing to TOK_ENG
  71.   rl c
  72.   ld a,(hl)
  73.   sub '0'
  74.   cp 10
  75.   jp nc,atof32_zero_check_eng
  76.   srl c
  77.  
  78. ;Now we read in the next 8 digits. Ideally, we want 27 bits worth, but 8 digits
  79. ; gives us about 26.5 bits
  80.   call ascii_to_BCD
  81.   ld d,a
  82.   call ascii_to_BCD
  83.   ld e,a
  84.   push de
  85.   call ascii_to_BCD
  86.   ld d,a
  87.   call ascii_to_BCD
  88.   ld e,a
  89.  
  90. ;Now `scrap` holds the 4-digit base-100 number (little-endian)
  91. ;b is the exponent
  92. ;if carry flag is set, just need to get rid of remaining digits
  93. ;Otherwise, need to get rid of remaining digits, while incrementing the exponent
  94.  
  95.   sbc a,a
  96.   ld c,a
  97. atof32_loop_1:
  98.   ld a,(hl)
  99.   cp TOK_DECIMAL
  100.   jr nz,$+8
  101.   dec c
  102.   jp pe,atof32_skip_7 ; we've reached our first decimal
  103.   jr atof32_skip_2    ; else C was already FF, then a decimal was already encountered
  104.  
  105.   sub '0'
  106.   cp 10
  107.   jr nc,atof32_skip_6
  108. ; carry flag is set
  109. atof32_skip_7:
  110.   inc hl
  111.   ld a,b
  112.   adc a,c
  113.   ; if carry flag is set, then we added 0
  114.   jr c,atof32_loop_1
  115.   jp z,atof32_inf2
  116.   ld b,a
  117.   jr atof32_loop_1
  118.  
  119. atof32_skip_6:
  120.   ld a,(hl)
  121. ;Now check for engineering `E` to modify the exponent
  122.   cp TOK_ENG
  123.   call z,atof32_str_eng_exp
  124.  
  125. atof32_skip_2:
  126.   ld (ptr_sto),hl ; save the pointer to the end of the string
  127.   pop hl
  128.   ex de,hl        ; DEHL is the number
  129.  
  130.   push bc         ; B is the base-10 exponent
  131.   call atof32_scrap_times_256
  132.   ld b,c
  133.   call atof32_scrap_times_256
  134.   push bc         ; BC is the upper 16 bis of the result
  135.   call atof32_scrap_times_256
  136.   ld b,c
  137.   call atof32_scrap_times_256
  138.   pop de
  139.   ld h,b
  140.   ld l,c
  141.   ; DEHL is 32 bits of the significand
  142.   pop bc  ; B is the base-10 exponent
  143.  
  144. ;HLC holds the 3-digit significand, need to normalize it
  145. ; make sure it isn't zero
  146.   ld a,e
  147.   or d
  148.   or l
  149.   or h
  150.   jp z,atof32_zero
  151.  
  152.  
  153.   ld c,$7E
  154.   ld a,d
  155.   or a
  156.   jr atof32_loop_3_start
  157. atof32_loop_3:
  158.   dec c
  159.   add hl,hl
  160.   rl e
  161.   adc a,a
  162. atof32_loop_3_start:
  163.   jp p,atof32_loop_3
  164.  
  165.   add a,a
  166.   ld d,a
  167.   pop af
  168.   rr c
  169.   rr d
  170.  
  171. ; round
  172.   sla l
  173.   jr nc,+_
  174.   inc h
  175.   jr nz,+_
  176.   inc e
  177.   jr nz,+_
  178.   inc d
  179.   jr nz,+_
  180.   inc c
  181. _:
  182. ;CDEH * 10^B
  183.  
  184. ; write the float in CDEH to the output
  185.   ld a,h
  186.   pop hl
  187.   ld (hl),a
  188.   inc hl
  189.   ld (hl),e
  190.   inc hl
  191.   ld (hl),d
  192.   inc hl
  193.   ld (hl),c
  194.   dec hl
  195.   dec hl
  196.   dec hl
  197.  
  198. ; now multiply the float at HL by 10^B
  199.   xor a
  200.   sub b
  201.   ld de,f32_pown10_LUT
  202.   jp p,$+7
  203.   ld a,b
  204.   ld de,f32_pow10_LUT
  205.  
  206.   cp 38
  207.   jr c,$+4
  208.   ld a,-1
  209.  
  210.   ld b,h
  211.   ld c,l
  212.   call atof32_mul_first
  213.   call atof32_mul_twice
  214. atof32_mul_twice:
  215.   call atof32_mul_once
  216. atof32_mul_once:
  217.   inc de
  218.   inc de
  219.   inc de
  220.   inc de
  221. atof32_mul_first:
  222.   rra
  223.   call c,f32mul
  224.   ret
  225.  
  226. atof32_str_eng_exp:
  227. ; HL points to the string, B is the current exponent, returns adjusted exponent in B
  228.   push de   ; save lower digits of input
  229.   ld e,0
  230.   inc hl
  231.   ld a,(hl)
  232.   sub TOK_NEG   ;negative exponent?
  233.   ld c,a        ;backup result
  234.   jr nz,atof32_skip_5
  235.   jr atof32_skip_3
  236. atof32_loop_2:
  237.   ld d,a  ; save the digit to add
  238.  
  239. ; make sure E doesn't exceed 3 (else the exponent is over 40)
  240.   ld a,e
  241.   cp 4
  242.   jr nc,atof32_eng_overflow
  243.  
  244.   add a,a
  245.   add a,a
  246.   add a,e
  247.   add a,a ; E*10
  248.   add a,d ; E*10+D
  249.   ld e,a
  250.  
  251. atof32_skip_3:
  252.   inc hl
  253. atof32_skip_5:
  254.   ld a,(hl)
  255.   sub '0'
  256.   cp 10
  257.   jr c,atof32_loop_2
  258.  
  259.   ld a,e
  260.   cp 60
  261.   jr nc,atof32_eng_overflow
  262.   ld a,c
  263.   or a
  264.   ld a,b
  265.   jr nz,atof32_skip_4
  266.   sub e
  267.   .db $FE  ; start of `cp *` to skip the next byte
  268. atof32_skip_4:
  269.   add a,e
  270.   ld b,a
  271.   pop de
  272.   ret
  273.  
  274. atof32_scrap_times_256:
  275.   call atof32_scrap_times_16
  276. atof32_scrap_times_16:
  277.   call atof32_scrap_times_4
  278. atof32_scrap_times_4:
  279.   call atof32_scrap_times_2
  280. atof32_scrap_times_2:
  281. ;DEHL 8 BCD digits, need to multiply by 2
  282.   ld a,l
  283.   add a,a
  284.   daa
  285.   ld l,a
  286.  
  287.   ld a,h
  288.   adc a,a
  289.   daa
  290.   ld h,a
  291.  
  292.   ld a,e
  293.   adc a,a
  294.   daa
  295.   ld e,a
  296.  
  297.   ld a,d
  298.   adc a,a
  299.   daa
  300.   ld d,a
  301.  
  302.   rl c
  303.   ret
  304.  
  305. atof32_inf2:
  306.   ld c,-1
  307. atof32_eng_overflow:
  308.   pop de  ; pop off saved digits
  309.   pop af  ; pop off the return address for the call
  310.   pop hl  ; pop off the other saved digits
  311.   ld a,c
  312.   or a
  313.   jr z,atof32_zero
  314. atof32_inf:
  315. ;return inf
  316.   pop af
  317.   pop hl
  318.   ld a,0
  319.   ld (hl),a
  320.   inc hl
  321.   ld (hl),a
  322.   inc hl
  323.   ld (hl),a
  324.   dec a
  325.   rra
  326.   rr (hl)
  327.   inc hl
  328.   ld (hl),a
  329.   ret
  330.  
  331. atof32_zero_check_eng:
  332.   cp TOK_ENG-'0'
  333.   jr nz,atof32_zero_write_hl
  334.   ; otherwise, we need to read through the engineering exponent
  335.   inc hl
  336.   ld a,(hl)
  337.   cp TOK_NEG
  338.   jr nz,$+3
  339.   inc hl
  340.   ld a,(hl)
  341.   sub '0'
  342.   cp 10
  343.   jr c,$-6  ; jumps back to the `inc hl`
  344. atof32_zero_write_hl:
  345.   ld (ptr_sto),hl ; save the pointer to the end of the string
  346. atof32_zero:
  347.   pop af
  348.   pop hl
  349.   ld a,0
  350.   ld (hl),a
  351.   inc hl
  352.   ld (hl),a
  353.   inc hl
  354.   ld (hl),a
  355.   inc hl
  356.   rra
  357.   ld (hl),a
  358.   ret
  359. #endif
  360.