TITLE "mp6.a by Douglas Jones, Nov 2023 -- float to int conversion" 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 ; mantfrac = bits right of point ; hiddenbits = bits overlapping exponent field ; ; exp = 01111111 means 0, so exponent = exp - bias, where bias = 0x7F ; ; 0|01111111|00000000000000000000000 = 1.0 ; ; therefore the integer part is mant << exponent - mantfrac ; shift = exponent - mantfrac ; shift = (exp - bias) - mantfrac ; shift = exp - (bias + mantfrac) ; when exponent = 0, shift = -mantfrac (use >> instead of <<) ; when exponent = mantfrac, shift = 0 ; when exponent < mantfrac, shift < 0 (meaning use >>) ; ; note: exponent < mantfrac is (exp - bias) < mantfrac ; which is exp < mantfrac + bias ; ; shift < -mantbits guarantees result is zero, which is ; exp - (bias + mantfrac) < -mantbits which is ; exp < (bias + mantfrac) - mantbits or ; exp < bias + mantfrac - mantbits ; ; shift > (expbits - hiddenbits) result is overflow, which is ; exp - (bias + mantfrac) > (expbits - hiddenbits) which is ; exp > (bias + mantfrac) + (expbits - hiddenbits) or ; exp > bias + mantfrac + expbits - hiddenbits ; constants helping describe floating format EXBITS = 8 ; bits in the exponent MANTBITS= 23 ; bits used to represent the mantissa MANTFRAC= 23 ; places right of point in mantissa HIDDNBIT= 1 ; places left of point in mantissa (the hidden bit) BIAS = #7F ; the bias HIDDEN = #800000 ; the hidden bit INT FTOINT ; no activation record, calls nothing, uses only R3-R6 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 ; R5 = ret -- the return value when done with mant ; R6 = temp -- needed occasionally ; 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 MOVESL R5,R3,9 SRU R5,9 ; mant = f.mant -- in R5 ; check exp for over and underflow ; magic constants are explained in the preface CMPI R4,BIAS + MANTFRAC + EXBITS - HIDDNBIT BLE NOOVF ; if (exp > bias+mantfrac+exbits+hiddnbit) { LIW R3,#80000000 ; n = 0x80000000 -- overflow JUMPS R1 ; -- optimized from BR DONE NOOVF: ; } else CMPI R4,BIAS + MANTFRAC - MANTBITS BGE NOUDF ; if (exp < mantfrac + bias - mantbits) { LIS R3,0 ; n = 0 -- underflow JUMPS R1 ; -- optimized from BR DONE NOUDF: ; } else { -- neither over or under! ; -- mant is guaranteed normalized by above LIW R6,HIDDEN OR R5,R6 ; mant = mant | hidden ADDI R4,R4,-(BIAS + MANTFRAC) ; shift = exp - (bias + mantfrac) BEQ ADJDONE ; if (shift == 0) { ; ret = mant BLT EXPSMAL ; } else if (shift > 0) { -- 0 to 7 left BITTST R4,0 ; -- begin bit by bit test of shift count BBR SLN1 SL R5,1 SLN1: BITTST R4,1 BBR SLN2 SL R5,2 SLN2: BITTST R4,2 BBR SLN4 SL R5,4 ; -- shift count < 8 means only test 3 bits SLN4: ; ret = mant << shift; BR ADJDONE EXPSMAL: ; } else if (shift < 0){ -- 1 to 23 right NEG R4,R4 ; shift = -shift BITTST R4,0 ; -- begin bit by bit test of shift count BBR SRN1 SR R5,1 SRN1: BITTST R4,1 BBR SRN2 SR R5,2 SRN2: BITTST R4,2 BBR SRN4 SR R5,4 SRN4: BITTST R4,3 BBR SRN8 SR R5,8 SRN8: BITTST R4,4 BBR SRN16 SR R5,16 ; -- shift count < 32 means only test 5 bits SRN16: ; ret = mant >> shift; ADJDONE: ; } 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 n END