Advertisement
PikalaxALT

WIP Float16 Library for the GBZ80 processor

Jul 21st, 2017
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; 16-bit floats have an 11-bit signed value and a 5-bit signed precision.
  2.  
  3. ; These control codes are required by the standard.
  4. F16_INF    EQU $7BFF
  5. F16_NEGINF EQU $7FFF
  6. F16_NAN    EQU $FFFF
  7.  
  8. CastFloat16ToFixed48:
  9. ; de: f16
  10. ; hl: q48 *
  11. ; returns to *hl
  12.  
  13. ; Arithmetically right-shift the precision
  14.     ld b, d
  15.     sra b
  16.     sra b
  17.     sra b
  18.  
  19. ; Mask away the precision and extend the sign of the value
  20.     ld a, d
  21.     and $7
  22.     bit 2, a
  23.     jr z, .no_sign_extend
  24.     or $f8
  25. .no_sign_extend
  26.     ld d, a
  27.  
  28. ; Prepare the output buffer.  Fixed, big-endian 48-bit numbers have the binary point 32 bits in.
  29.     ld a, 0
  30.     jr z, .no_output_sign_extend
  31.     dec a
  32. .no_output_sign_extend
  33. ; Sign extend
  34.     push hl
  35.     ld [hli], a
  36.     ld [hli], a
  37. ; Load the input float
  38.     ld [hl], d
  39.     inc hl
  40.     ld [hl], e
  41.     inc hl
  42. ; Fill the rest with 0
  43.     xor a
  44.     ld [hli], a
  45.     ld [hl], a
  46.     pop hl
  47.  
  48. ; If the precision is 0, no shifting is needed
  49.     ld a, b
  50.     and a
  51.     ret z
  52. ; Check the sign of the precision
  53.     bit 7, a
  54.     jr z, .precision_positive
  55. ; Right-shift to gain the required fixed-point precision
  56.     cpl
  57.     inc a
  58.     ld b, a
  59.     ld c, 6
  60. .neg_prec_outer
  61.     push hl
  62.     push bc
  63.     and a
  64. .neg_prec_inner
  65.     rr [hl]
  66.     inc hl
  67.     dec c
  68.     jr nz, .neg_prec_inner
  69.     pop bc
  70.     pop hl
  71.     dec b
  72.     jr nz, .neg_prec_outer
  73.     ret
  74.  
  75. .precision_positive
  76. ; Left-shift to gain the required fixed-point magnitude
  77.     push hl
  78.     ld de, 5
  79.     add hl, de
  80.     ld c, 6
  81. .pos_prec_outer
  82.     push hl
  83.     push bc
  84.     and a
  85. .pos_prec_inner
  86.     rl [hl]
  87.     dec hl
  88.     dec c
  89.     jr nz, .pos_prec_inner
  90.     pop bc
  91.     pop hl
  92.     dec b
  93.     jr nz, .pos_prec_outer
  94.     pop hl
  95.     ret
  96.  
  97. CastFixed48ToFloat16:
  98. ; hl: q48 *
  99. ; returns f16 de
  100.     bit 7, [hl]
  101.     push af ; save sign
  102.     jr z, .positive
  103.     ; take absolute value
  104.     push hl
  105.     ld c, 6
  106. .cpl_loop
  107.     ld a, [hl]
  108.     cpl
  109.     ld [hli], a
  110.     dec c
  111.     jr nz, .cpl_loop
  112.     dec hl
  113.     inc [hl]
  114.     pop hl
  115. .positive
  116.     ; find most significant position
  117.     ld b, 16
  118. .most_significant_position_loop
  119.     ld c, 8
  120.     ld a, [hli]
  121. .most_significant_position_loop_inner
  122.     add a
  123.     jr c, .got_most_significant_position
  124.     dec b
  125.     dec c
  126.     jr nz, .most_significant_position_loop
  127.     jr .most_significant_position_loop
  128.  
  129. .got_most_significant_position
  130.     push bc
  131.     ; calculate the shift
  132.     ld a, b
  133.     bit 7, a
  134.     jr z, .shift_left
  135.     cpl
  136.     inc a
  137.     ld b, a
  138.     cp 16
  139.     jr c, .shift_right
  140.     ; can't fit in an f16, return 0
  141.     ld de, 0
  142.     add sp, 4
  143.     ret
  144.  
  145. .shift_left
  146.     cp 11
  147.     jr c, .okay_shift_left
  148.     ; can't fit in an f16, return infinity
  149.     ld de, F16_INF
  150.     pop af
  151.     pop af
  152.     ret z
  153.     set 2, d
  154.     ret
  155.  
  156. .okay_shift_left
  157.     ld de, 5
  158.     add hl, de
  159.     inc e
  160.     ld c, e
  161. .shift_left_loop_outer
  162.     push bc
  163.     and a
  164. .shift_left_loop_inner
  165.     rl [hl]
  166.     dec hl
  167.     dec c
  168.     jr nz, .shift_left_loop_inner
  169.     pop bc
  170.     add hl, de
  171.     dec b
  172.     jr nz, .shift_left_loop_outer
  173.     inc hl
  174.     jr .pack
  175.  
  176. .shift_right
  177.     ld de, -6
  178.     ld c, 6
  179. .shift_right_loop_outer
  180.     push bc
  181.     and a
  182. .shift_right_loop_inner
  183.     rr [hl]
  184.     inc hl
  185.     dec c
  186.     jr nz, .shift_right_loop_inner
  187.     pop bc
  188.     add hl, de
  189.     dec b
  190.     jr nz, .shift_right_loop_outer
  191. .pack
  192.     pop bc
  193.     sla b
  194.     sla b
  195.     sla b
  196.     inc hl
  197.     inc hl
  198.     ld a, [hli]
  199.     ld e, [hl]
  200.     and $3
  201.     ld d, a
  202.     pop af
  203.     jr z, .no_cpl
  204.     ld a, d
  205.     cpl
  206.     and $7
  207.     ld d, a
  208.     ld a, e
  209.     cpl
  210.     inc a
  211.     ld e, a
  212. .no_cpl
  213.     ld a, d
  214.     or b
  215.     ld d, a
  216.     ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement