Skip to content

Instantly share code, notes, and snippets.

@gosuri
Last active December 13, 2015 22:08
Show Gist options
  • Save gosuri/4982427 to your computer and use it in GitHub Desktop.
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.
.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