Last active
December 13, 2015 22:08
-
-
Save gosuri/4982427 to your computer and use it in GitHub Desktop.
SAL code to add real numbers FloatX and FloatY using only fixed point operations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.data | |
# Inputs | |
FloatX: .float 134.0625 | |
FloatY: .float 2.25 | |
# Result | |
Float_X_plus_Y: .float | |
# Temp Variables | |
X: .word | |
Y: .word | |
X_F: .word # significand of FloatX | |
X_E: .word # exponent of FloatX | |
Y_F: .word # significand of FloatY | |
Y_E: .word # exponent of FloatY | |
X_time_Y: .word | |
X_plus_Y: .word | |
X_plus_Y_F: .word | |
X_plus_Y_E: .word | |
X_plus_Y_S: .word | |
small_F: .word | |
diff: .word | |
# Constants | |
F_mask: .word 0x007fffff # 23 1s Mask for fraction portion | |
E_mask: .word 0x7f800000 # Mask for exponent portion | |
S_mask: .word 0x80000000 # Mask for sign bit | |
Hidden_one: .word 0x00800000 | |
zero: .word 0 | |
max_F: .word 0x01000000 | |
.text | |
# Extract E (exponent) and F (significand). | |
__start: move X, FloatX | |
and X_F, X, F_mask # get X_F | |
or X_F, X_F, Hidden_one # add hidden bit | |
bgtz X, DoX_E # skip if positive | |
sub X_F, zero, X_F # convert to 2's comp. | |
DoX_E: and X_E, X, E_mask # get X_E | |
srl X_E, X_E, 23 # align (shift left 23) | |
sub X_E, X_E, 127 # convert to 2's comp. | |
move Y, FloatY | |
and Y_F, Y, F_mask # get Y_F | |
or Y_F, Y_F, Hidden_one # add hidden bit | |
bgtz Y, DoY_E # skip if positive | |
sub Y_F, zero, Y_F # convert to 2's comp. | |
DoY_E: and Y_E, Y, E_mask # get Y_E. | |
srl Y_E, Y_E, 23 # align | |
sub Y_E, Y_E, 127 # convert to 2's comp. | |
# Determine which input is smaller | |
sub diff, Y_E, X_E | |
bltz diff, X_bigger | |
move X_plus_Y_E, Y_E | |
move X_plus_Y_F, Y_F | |
move small_F, X_F | |
b LittleF | |
X_bigger: move X_plus_Y_E, X_E | |
move X_plus_Y_F, X_F | |
move small_F, Y_F | |
sub diff, zero, diff | |
LittleF: sra small_F, small_F, diff # denormalize little F | |
# add denormalized mantissas | |
add X_plus_Y_F, small_F, X_plus_Y_F # add Fs | |
and X_plus_Y_S, X_plus_Y_F, S_mask | |
beqz X_plus_Y_F, Zero | |
bgez X_plus_Y_F, L1 # skip if positive | |
sub X_plus_Y_F, zero, X_plus_Y_F # convert to sign/mag | |
L1: move X_plus_Y_E, X_plus_Y_E | |
blt X_plus_Y_F, max_F, NotTooBig # skip if no overflow | |
srl X_plus_Y_F, X_plus_Y_F, 1 # divide F by 2 | |
add X_plus_Y_E, X_plus_Y_E, 1 # adjust E | |
b normalized # known to be aligned | |
Zero: move Float_X_plus_Y, 0 | |
b Finished | |
TooSmall: sll X_plus_Y_F, X_plus_Y_F, 1 # multiply by 2 | |
sub X_plus_Y_E, X_plus_Y_E, 1 # adjust E | |
NotTooBig: blt X_plus_Y_F, Hidden_one, TooSmall # check if still too big | |
normalized: sub X_plus_Y_F, X_plus_Y_F, Hidden_one # delete the hidden one | |
add X_plus_Y_E, X_plus_Y_E, 127 # convert to bias-127 | |
sll X_plus_Y_E, X_plus_Y_E, 23 # align properly | |
or X_plus_Y, X_plus_Y_E, X_plus_Y_F # merge E, F | |
or X_plus_Y, X_plus_Y, X_plus_Y_S # merge S | |
move Float_X_plus_Y, X_plus_Y # move to floating point | |
Finished: done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment