TITLE "mp7a.a by Douglas Jones, Nov 2023 -- float to int conversion" ; "improved version" USE "hawk.h" ; Preface ; Given a floating point number of the form: ; s|eeeeeeee|mmmmmmmmmmmmmmmmmmmmmmm ; 1| 8 bits | 23 bits sign, exp, mant ; | expbits| mantbits = bits in each field ; ; where: 1.mmmmmmmmmmmmmmmmmmmmmmm the hidden bit when exp != 00000000 ; hiddenbits = bits overlapping exponent field ; convert using: ; 1.mmmmmmmm mmmmmmmmmmmmmmm00000000 ; mantfrac = bits right of point (31) ; ; exp = 01111111 means 0, so exponent = exp - bias, where bias = 0x7F ; ; 0|01111111|00000000000000000000000 = 1.0 ; ; therefore the integer part is mant >> mantfrac - exponent ; shift = mantfrac - exponent ; shift = mantfrac - (exp - bias) ; shift = mantfrac +-exp + bias) ; shift = (mantfrac + bias) - exp ; when exponent < 0, shift > mantfrac, underflow! ; when exponent = 0, shift = mantfrac ; when exponent = (mantfrac-1) shift = 1 ; when exponent = mantfrac, shift = 0, overflow! ; when exponent < mantfrac, shift < 0, overflow!! ; ; note: exponent < mantfrac is (exp - bias) < mantfrac ; which is exp < mantfrac + bias ; constants helping describe floating format EXBITS = 8 ; bits in the exponent MANTFRAC= 31 ; places right of point in mantissa BIAS = #7F ; the bias INT FTOINT ; no activation record, calls nothing, uses only R3-R5 FTOINT: ; expects R3 = f -- a 32-bit IEEE format floating point number ; returns R3 = ret -- a 32-bit integer, the integer part of f ; n = #80000000 if f cannot be given in 32 bits ; uses R4 = exp -- the exponent part of f ; R4 = shift -- the exponent part of f after done with exp ; R5 = mant -- the mantissa part of f (used as temp early on) ; R5 = ret -- the return value when done with mant ; first, pick apart floating point number ; f = s|eeeeeeee|fffffffffffffffffffffff ; 1| 8 bits | 23 bits ; sign not extracted, we just leave f intact MOVESL R4,R3,1 SRU R4,12 SRU R4,12 ; exp = f.exp >> 23 -- in R4 ; check exp for over and underflow ; magic constants are explained in the preface LIL R5,MANTFRAC + BIAS ; -- note, R5 is available as temp here SUB R4,R5,R4 ; shift = (mantfrac + bias) - exp -- in R4 BGT NOOVF ; if (shift <= 0) { LIW R3,#80000000 ; n = 0x80000000 -- overflow JUMPS R1 ; -- optimized from BR DONE NOOVF: ; } else { CMPI R4,MANTFRAC BLE NOUDF ; if (exp > mantfrac) { LIS R3,0 ; n = 0 -- underflow JUMPS R1 ; -- optimized from BR DONE NOUDF: ; } else { -- neither over or under! MOVESL R5,R3,9 SRU R5,1 ; mant = f.mant << expbits -- in R5 ; -- mant is guaranteed normalized by above SUB R0,R3,R3 ; -- so set carry bit (becomes hidden bit) ADJUST R5,CMSB ; mant = mant + hidden BITTST R4,0 ; -- begin bit by bit test of shift count BBR SRN1 ; -- based on fasth shift from Exam II SRU R5,1 SRN1: BITTST R4,1 BBR SRN2 SRU R5,2 SRN2: BITTST R4,2 BBR SRN4 SRU R5,4 SRN4: BITTST R4,3 BBR SRN8 SRU R5,8 SRN8: BITTST R4,4 BBR SRN16 SRU R5,16 ; -- shift count < 32 means only test 5 bits SRN16: ; ret = mant >> shift; TESTR R3 BGE NOTNEG ; if (f < 0) { -- make negative result NEG R5,R5 ; ret = -ret NOTNEG: ; } MOVE R3,R5 ; -- move ret to R3 ;DONE: ; } -- need for this label optimized away above JUMPS R1 ; return ret END