Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; 16-bit floats have an 11-bit signed value and a 5-bit signed precision.
- ; These control codes are required by the standard.
- F16_INF EQU $7BFF
- F16_NEGINF EQU $7FFF
- F16_NAN EQU $FFFF
- CastFloat16ToFixed48:
- ; de: f16
- ; hl: q48 *
- ; returns to *hl
- ; Arithmetically right-shift the precision
- ld b, d
- sra b
- sra b
- sra b
- ; Mask away the precision and extend the sign of the value
- ld a, d
- and $7
- bit 2, a
- jr z, .no_sign_extend
- or $f8
- .no_sign_extend
- ld d, a
- ; Prepare the output buffer. Fixed, big-endian 48-bit numbers have the binary point 32 bits in.
- ld a, 0
- jr z, .no_output_sign_extend
- dec a
- .no_output_sign_extend
- ; Sign extend
- push hl
- ld [hli], a
- ld [hli], a
- ; Load the input float
- ld [hl], d
- inc hl
- ld [hl], e
- inc hl
- ; Fill the rest with 0
- xor a
- ld [hli], a
- ld [hl], a
- pop hl
- ; If the precision is 0, no shifting is needed
- ld a, b
- and a
- ret z
- ; Check the sign of the precision
- bit 7, a
- jr z, .precision_positive
- ; Right-shift to gain the required fixed-point precision
- cpl
- inc a
- ld b, a
- ld c, 6
- .neg_prec_outer
- push hl
- push bc
- and a
- .neg_prec_inner
- rr [hl]
- inc hl
- dec c
- jr nz, .neg_prec_inner
- pop bc
- pop hl
- dec b
- jr nz, .neg_prec_outer
- ret
- .precision_positive
- ; Left-shift to gain the required fixed-point magnitude
- push hl
- ld de, 5
- add hl, de
- ld c, 6
- .pos_prec_outer
- push hl
- push bc
- and a
- .pos_prec_inner
- rl [hl]
- dec hl
- dec c
- jr nz, .pos_prec_inner
- pop bc
- pop hl
- dec b
- jr nz, .pos_prec_outer
- pop hl
- ret
- CastFixed48ToFloat16:
- ; hl: q48 *
- ; returns f16 de
- bit 7, [hl]
- push af ; save sign
- jr z, .positive
- ; take absolute value
- push hl
- ld c, 6
- .cpl_loop
- ld a, [hl]
- cpl
- ld [hli], a
- dec c
- jr nz, .cpl_loop
- dec hl
- inc [hl]
- pop hl
- .positive
- ; find most significant position
- ld b, 16
- .most_significant_position_loop
- ld c, 8
- ld a, [hli]
- .most_significant_position_loop_inner
- add a
- jr c, .got_most_significant_position
- dec b
- dec c
- jr nz, .most_significant_position_loop
- jr .most_significant_position_loop
- .got_most_significant_position
- push bc
- ; calculate the shift
- ld a, b
- bit 7, a
- jr z, .shift_left
- cpl
- inc a
- ld b, a
- cp 16
- jr c, .shift_right
- ; can't fit in an f16, return 0
- ld de, 0
- add sp, 4
- ret
- .shift_left
- cp 11
- jr c, .okay_shift_left
- ; can't fit in an f16, return infinity
- ld de, F16_INF
- pop af
- pop af
- ret z
- set 2, d
- ret
- .okay_shift_left
- ld de, 5
- add hl, de
- inc e
- ld c, e
- .shift_left_loop_outer
- push bc
- and a
- .shift_left_loop_inner
- rl [hl]
- dec hl
- dec c
- jr nz, .shift_left_loop_inner
- pop bc
- add hl, de
- dec b
- jr nz, .shift_left_loop_outer
- inc hl
- jr .pack
- .shift_right
- ld de, -6
- ld c, 6
- .shift_right_loop_outer
- push bc
- and a
- .shift_right_loop_inner
- rr [hl]
- inc hl
- dec c
- jr nz, .shift_right_loop_inner
- pop bc
- add hl, de
- dec b
- jr nz, .shift_right_loop_outer
- .pack
- pop bc
- sla b
- sla b
- sla b
- inc hl
- inc hl
- ld a, [hli]
- ld e, [hl]
- and $3
- ld d, a
- pop af
- jr z, .no_cpl
- ld a, d
- cpl
- and $7
- ld d, a
- ld a, e
- cpl
- inc a
- ld e, a
- .no_cpl
- ld a, d
- or b
- ld d, a
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement