2
0

softfpu.pp 295 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521
  1. {*
  2. ===============================================================================
  3. The original notice of the softfloat package is shown below. The conversion
  4. to pascal was done by Carl Eric Codere in 2002 ([email protected]).
  5. ===============================================================================
  6. This C source file is part of the SoftFloat IEC/IEEE Floating-Point
  7. Arithmetic Package, Release 2a.
  8. Written by John R. Hauser. This work was made possible in part by the
  9. International Computer Science Institute, located at Suite 600, 1947 Center
  10. Street, Berkeley, California 94704. Funding was partially provided by the
  11. National Science Foundation under grant MIP-9311980. The original version
  12. of this code was written as part of a project to build a fixed-point vector
  13. processor in collaboration with the University of California at Berkeley,
  14. overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  15. is available through the Web page
  16. `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.
  17. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
  18. has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
  19. TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
  20. PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
  21. AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
  22. Derivative works are acceptable, even for commercial purposes, so long as
  23. (1) they include prominent notice that the work is derivative, and (2) they
  24. include prominent notice akin to these four paragraphs for those parts of
  25. this code that are retained.
  26. ===============================================================================
  27. The float80 and float128 part is translated from the softfloat package
  28. by Florian Klaempfl and contained the following copyright notice
  29. The code might contain some duplicate stuff because the floatx80/float128 port was
  30. done based on the 64 bit enabled softfloat code.
  31. ===============================================================================
  32. This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
  33. Package, Release 2b.
  34. Written by John R. Hauser. This work was made possible in part by the
  35. International Computer Science Institute, located at Suite 600, 1947 Center
  36. Street, Berkeley, California 94704. Funding was partially provided by the
  37. National Science Foundation under grant MIP-9311980. The original version
  38. of this code was written as part of a project to build a fixed-point vector
  39. processor in collaboration with the University of California at Berkeley,
  40. overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  41. is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
  42. arithmetic/SoftFloat.html'.
  43. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
  44. been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
  45. RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
  46. AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
  47. COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
  48. EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
  49. INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
  50. OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
  51. Derivative works are acceptable, even for commercial purposes, so long as
  52. (1) the source code for the derivative work includes prominent notice that
  53. the work is derivative, and (2) the source code includes prominent notice with
  54. these four paragraphs for those parts of this code that are retained.
  55. ===============================================================================
  56. *}
  57. { $define FPC_SOFTFLOAT_FLOATX80}
  58. { $define FPC_SOFTFLOAT_FLOAT128}
  59. { the softfpu unit can be also embedded directly into the system unit }
  60. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  61. {$mode objfpc}
  62. unit softfpu;
  63. { Overflow checking must be disabled,
  64. since some operations expect overflow!
  65. }
  66. {$Q-}
  67. {$goto on}
  68. interface
  69. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  70. {$if not(defined(fpc_softfpu_implementation))}
  71. {
  72. -------------------------------------------------------------------------------
  73. Software IEC/IEEE floating-point types.
  74. -------------------------------------------------------------------------------
  75. }
  76. TYPE
  77. float32 = longword;
  78. {$define FPC_SYSTEM_HAS_float32}
  79. { we use here a record in the function header because
  80. the record allows bitwise conversion to single }
  81. float32rec = record
  82. float32 : float32;
  83. end;
  84. flag = byte;
  85. bits8 = byte;
  86. sbits8 = shortint;
  87. bits16 = word;
  88. sbits16 = smallint;
  89. sbits32 = longint;
  90. bits32 = longword;
  91. {$ifndef fpc}
  92. qword = int64;
  93. {$endif}
  94. { now part of the system unit
  95. uint64 = qword;
  96. }
  97. bits64 = qword;
  98. sbits64 = int64;
  99. {$ifdef ENDIAN_LITTLE}
  100. float64 = packed record
  101. low: bits32;
  102. high: bits32;
  103. end;
  104. int64rec = packed record
  105. low: bits32;
  106. high: bits32;
  107. end;
  108. floatx80 = packed record
  109. low : qword;
  110. high : word;
  111. end;
  112. float128 = packed record
  113. low : qword;
  114. high : qword;
  115. end;
  116. {$else}
  117. float64 = record
  118. case byte of
  119. 1: (high,low : bits32);
  120. // force the record to be aligned like a double
  121. // else *_to_double will fail for cpus like sparc
  122. 2: (dummy : double);
  123. end;
  124. int64rec = packed record
  125. high,low : bits32;
  126. end;
  127. floatx80 = packed record
  128. high : word;
  129. low : qword;
  130. end;
  131. float128 = packed record
  132. high : qword;
  133. low : qword;
  134. end;
  135. {$endif}
  136. {$define FPC_SYSTEM_HAS_float64}
  137. {*
  138. -------------------------------------------------------------------------------
  139. Returns 1 if the double-precision floating-point value `a' is less than
  140. the corresponding value `b', and 0 otherwise. The comparison is performed
  141. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  142. -------------------------------------------------------------------------------
  143. *}
  144. Function float64_lt(a: float64;b: float64): flag; compilerproc;
  145. {*
  146. -------------------------------------------------------------------------------
  147. Returns 1 if the double-precision floating-point value `a' is less than
  148. or equal to the corresponding value `b', and 0 otherwise. The comparison
  149. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  150. Arithmetic.
  151. -------------------------------------------------------------------------------
  152. *}
  153. Function float64_le(a: float64;b: float64): flag; compilerproc;
  154. {*
  155. -------------------------------------------------------------------------------
  156. Returns 1 if the double-precision floating-point value `a' is equal to
  157. the corresponding value `b', and 0 otherwise. The comparison is performed
  158. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  159. -------------------------------------------------------------------------------
  160. *}
  161. Function float64_eq(a: float64;b: float64): flag; compilerproc;
  162. {*
  163. -------------------------------------------------------------------------------
  164. Returns the square root of the double-precision floating-point value `a'.
  165. The operation is performed according to the IEC/IEEE Standard for Binary
  166. Floating-Point Arithmetic.
  167. -------------------------------------------------------------------------------
  168. *}
  169. Procedure float64_sqrt( a: float64; var out: float64 ); compilerproc;
  170. {*
  171. -------------------------------------------------------------------------------
  172. Returns the remainder of the double-precision floating-point value `a'
  173. with respect to the corresponding value `b'. The operation is performed
  174. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  175. -------------------------------------------------------------------------------
  176. *}
  177. Function float64_rem(a: float64; b : float64) : float64; compilerproc;
  178. {*
  179. -------------------------------------------------------------------------------
  180. Returns the result of dividing the double-precision floating-point value `a'
  181. by the corresponding value `b'. The operation is performed according to the
  182. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  183. -------------------------------------------------------------------------------
  184. *}
  185. Function float64_div(a: float64; b : float64) : float64; compilerproc;
  186. {*
  187. -------------------------------------------------------------------------------
  188. Returns the result of multiplying the double-precision floating-point values
  189. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  190. for Binary Floating-Point Arithmetic.
  191. -------------------------------------------------------------------------------
  192. *}
  193. Function float64_mul( a: float64; b:float64) : float64; compilerproc;
  194. {*
  195. -------------------------------------------------------------------------------
  196. Returns the result of subtracting the double-precision floating-point values
  197. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  198. for Binary Floating-Point Arithmetic.
  199. -------------------------------------------------------------------------------
  200. *}
  201. Function float64_sub(a: float64; b : float64) : float64; compilerproc;
  202. {*
  203. -------------------------------------------------------------------------------
  204. Returns the result of adding the double-precision floating-point values `a'
  205. and `b'. The operation is performed according to the IEC/IEEE Standard for
  206. Binary Floating-Point Arithmetic.
  207. -------------------------------------------------------------------------------
  208. *}
  209. Function float64_add( a: float64; b : float64) : float64; compilerproc;
  210. {*
  211. -------------------------------------------------------------------------------
  212. Rounds the double-precision floating-point value `a' to an integer,
  213. and returns the result as a double-precision floating-point value. The
  214. operation is performed according to the IEC/IEEE Standard for Binary
  215. Floating-Point Arithmetic.
  216. -------------------------------------------------------------------------------
  217. *}
  218. Function float64_round_to_int(a: float64) : float64; compilerproc;
  219. {*
  220. -------------------------------------------------------------------------------
  221. Returns the result of converting the double-precision floating-point value
  222. `a' to the single-precision floating-point format. The conversion is
  223. performed according to the IEC/IEEE Standard for Binary Floating-Point
  224. Arithmetic.
  225. -------------------------------------------------------------------------------
  226. *}
  227. Function float64_to_float32(a: float64) : float32rec; compilerproc;
  228. {*
  229. -------------------------------------------------------------------------------
  230. Returns the result of converting the double-precision floating-point value
  231. `a' to the 32-bit two's complement integer format. The conversion is
  232. performed according to the IEC/IEEE Standard for Binary Floating-Point
  233. Arithmetic, except that the conversion is always rounded toward zero.
  234. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  235. the conversion overflows, the largest integer with the same sign as `a' is
  236. returned.
  237. -------------------------------------------------------------------------------
  238. *}
  239. Function float64_to_int32_round_to_zero(a: float64 ): int32; compilerproc;
  240. {*
  241. -------------------------------------------------------------------------------
  242. Returns the result of converting the double-precision floating-point value
  243. `a' to the 32-bit two's complement integer format. The conversion is
  244. performed according to the IEC/IEEE Standard for Binary Floating-Point
  245. Arithmetic---which means in particular that the conversion is rounded
  246. according to the current rounding mode. If `a' is a NaN, the largest
  247. positive integer is returned. Otherwise, if the conversion overflows, the
  248. largest integer with the same sign as `a' is returned.
  249. -------------------------------------------------------------------------------
  250. *}
  251. Function float64_to_int32(a: float64): int32; compilerproc;
  252. {*
  253. -------------------------------------------------------------------------------
  254. Returns 1 if the single-precision floating-point value `a' is less than
  255. the corresponding value `b', and 0 otherwise. The comparison is performed
  256. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  257. -------------------------------------------------------------------------------
  258. *}
  259. Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
  260. {*
  261. -------------------------------------------------------------------------------
  262. Returns 1 if the single-precision floating-point value `a' is less than
  263. or equal to the corresponding value `b', and 0 otherwise. The comparison
  264. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  265. Arithmetic.
  266. -------------------------------------------------------------------------------
  267. *}
  268. Function float32_le( a: float32rec; b : float32rec ):flag; compilerproc;
  269. {*
  270. -------------------------------------------------------------------------------
  271. Returns 1 if the single-precision floating-point value `a' is equal to
  272. the corresponding value `b', and 0 otherwise. The comparison is performed
  273. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  274. -------------------------------------------------------------------------------
  275. *}
  276. Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
  277. {*
  278. -------------------------------------------------------------------------------
  279. Returns the square root of the single-precision floating-point value `a'.
  280. The operation is performed according to the IEC/IEEE Standard for Binary
  281. Floating-Point Arithmetic.
  282. -------------------------------------------------------------------------------
  283. *}
  284. Function float32_sqrt(a: float32rec ): float32rec; compilerproc;
  285. {*
  286. -------------------------------------------------------------------------------
  287. Returns the remainder of the single-precision floating-point value `a'
  288. with respect to the corresponding value `b'. The operation is performed
  289. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  290. -------------------------------------------------------------------------------
  291. *}
  292. Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
  293. {*
  294. -------------------------------------------------------------------------------
  295. Returns the result of dividing the single-precision floating-point value `a'
  296. by the corresponding value `b'. The operation is performed according to the
  297. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  298. -------------------------------------------------------------------------------
  299. *}
  300. Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
  301. {*
  302. -------------------------------------------------------------------------------
  303. Returns the result of multiplying the single-precision floating-point values
  304. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  305. for Binary Floating-Point Arithmetic.
  306. -------------------------------------------------------------------------------
  307. *}
  308. Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
  309. {*
  310. -------------------------------------------------------------------------------
  311. Returns the result of subtracting the single-precision floating-point values
  312. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  313. for Binary Floating-Point Arithmetic.
  314. -------------------------------------------------------------------------------
  315. *}
  316. Function float32_sub( a: float32rec ; b:float32rec ): float32rec; compilerproc;
  317. {*
  318. -------------------------------------------------------------------------------
  319. Returns the result of adding the single-precision floating-point values `a'
  320. and `b'. The operation is performed according to the IEC/IEEE Standard for
  321. Binary Floating-Point Arithmetic.
  322. -------------------------------------------------------------------------------
  323. *}
  324. Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
  325. {*
  326. -------------------------------------------------------------------------------
  327. Rounds the single-precision floating-point value `a' to an integer,
  328. and returns the result as a single-precision floating-point value. The
  329. operation is performed according to the IEC/IEEE Standard for Binary
  330. Floating-Point Arithmetic.
  331. -------------------------------------------------------------------------------
  332. *}
  333. Function float32_round_to_int( a: float32rec): float32rec; compilerproc;
  334. {*
  335. -------------------------------------------------------------------------------
  336. Returns the result of converting the single-precision floating-point value
  337. `a' to the double-precision floating-point format. The conversion is
  338. performed according to the IEC/IEEE Standard for Binary Floating-Point
  339. Arithmetic.
  340. -------------------------------------------------------------------------------
  341. *}
  342. Function float32_to_float64( a : float32rec) : Float64; compilerproc;
  343. {*
  344. -------------------------------------------------------------------------------
  345. Returns the result of converting the single-precision floating-point value
  346. `a' to the 32-bit two's complement integer format. The conversion is
  347. performed according to the IEC/IEEE Standard for Binary Floating-Point
  348. Arithmetic, except that the conversion is always rounded toward zero.
  349. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  350. the conversion overflows, the largest integer with the same sign as `a' is
  351. returned.
  352. -------------------------------------------------------------------------------
  353. *}
  354. Function float32_to_int32_round_to_zero( a: Float32rec ): int32; compilerproc;
  355. {*
  356. -------------------------------------------------------------------------------
  357. Returns the result of converting the single-precision floating-point value
  358. `a' to the 32-bit two's complement integer format. The conversion is
  359. performed according to the IEC/IEEE Standard for Binary Floating-Point
  360. Arithmetic---which means in particular that the conversion is rounded
  361. according to the current rounding mode. If `a' is a NaN, the largest
  362. positive integer is returned. Otherwise, if the conversion overflows, the
  363. largest integer with the same sign as `a' is returned.
  364. -------------------------------------------------------------------------------
  365. *}
  366. Function float32_to_int32( a : float32rec) : int32; compilerproc;
  367. {*
  368. -------------------------------------------------------------------------------
  369. Returns the result of converting the 32-bit two's complement integer `a' to
  370. the double-precision floating-point format. The conversion is performed
  371. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  372. -------------------------------------------------------------------------------
  373. *}
  374. Function int32_to_float64( a: int32) : float64; compilerproc;
  375. {*
  376. -------------------------------------------------------------------------------
  377. Returns the result of converting the 32-bit two's complement integer `a' to
  378. the single-precision floating-point format. The conversion is performed
  379. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  380. -------------------------------------------------------------------------------
  381. *}
  382. Function int32_to_float32( a: int32): float32rec; compilerproc;
  383. {*----------------------------------------------------------------------------
  384. | Returns the result of converting the 64-bit two's complement integer `a'
  385. | to the double-precision floating-point format. The conversion is performed
  386. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  387. *----------------------------------------------------------------------------*}
  388. Function int64_to_float64( a: int64 ): float64; compilerproc;
  389. Function qword_to_float64( a: qword ): float64; compilerproc;
  390. {*----------------------------------------------------------------------------
  391. | Returns the result of converting the 64-bit two's complement integer `a'
  392. | to the single-precision floating-point format. The conversion is performed
  393. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  394. *----------------------------------------------------------------------------*}
  395. Function int64_to_float32( a: int64 ): float32rec; compilerproc;
  396. Function qword_to_float32( a: qword ): float32rec; compilerproc;
  397. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  398. function float128_is_nan( a : float128): flag;
  399. function float128_is_signaling_nan( a : float128): flag;
  400. function float128_to_int32(a: float128): int32;
  401. function float128_to_int32_round_to_zero(a: float128): int32;
  402. function float128_to_int64(a: float128): int64;
  403. function float128_to_int64_round_to_zero(a: float128): int64;
  404. function float128_to_float32(a: float128): float32;
  405. function float128_to_float64(a: float128): float64;
  406. function float64_to_float128( a : float64) : float128;
  407. {$ifdef FPC_SOFTFLOAT_FLOAT80}
  408. function float128_to_floatx80(a: float128): floatx80;
  409. {$endif FPC_SOFTFLOAT_FLOAT80}
  410. function float128_round_to_int(a: float128): float128;
  411. function float128_add(a: float128; b: float128): float128;
  412. function float128_sub(a: float128; b: float128): float128;
  413. function float128_mul(a: float128; b: float128): float128;
  414. function float128_div(a: float128; b: float128): float128;
  415. function float128_rem(a: float128; b: float128): float128;
  416. function float128_sqrt(a: float128): float128;
  417. function float128_eq(a: float128; b: float128): flag;
  418. function float128_le(a: float128; b: float128): flag;
  419. function float128_lt(a: float128; b: float128): flag;
  420. function float128_eq_signaling(a: float128; b: float128): flag;
  421. function float128_le_quiet(a: float128; b: float128): flag;
  422. function float128_lt_quiet(a: float128; b: float128): flag;
  423. {$endif FPC_SOFTFLOAT_FLOAT128}
  424. CONST
  425. {-------------------------------------------------------------------------------
  426. Software IEC/IEEE floating-point underflow tininess-detection mode.
  427. -------------------------------------------------------------------------------
  428. *}
  429. float_tininess_after_rounding = 0;
  430. float_tininess_before_rounding = 1;
  431. {*
  432. -------------------------------------------------------------------------------
  433. Underflow tininess-detection mode, statically initialized to default value.
  434. (The declaration in `softfloat.h' must match the `int8' type here.)
  435. -------------------------------------------------------------------------------
  436. *}
  437. const float_detect_tininess: int8 = float_tininess_after_rounding;
  438. {$endif not(defined(fpc_softfpu_implementation))}
  439. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  440. implementation
  441. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  442. {$if not(defined(fpc_softfpu_interface))}
  443. (*****************************************************************************)
  444. (*----------------------------------------------------------------------------*)
  445. (* Primitive arithmetic functions, including multi-word arithmetic, and *)
  446. (* division and square root approximations. (Can be specialized to target if *)
  447. (* desired.) *)
  448. (* ---------------------------------------------------------------------------*)
  449. (*****************************************************************************)
  450. {*----------------------------------------------------------------------------
  451. | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
  452. | and 7, and returns the properly rounded 32-bit integer corresponding to the
  453. | input. If `zSign' is 1, the input is negated before being converted to an
  454. | integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
  455. | is simply rounded to an integer, with the inexact exception raised if the
  456. | input cannot be represented exactly as an integer. However, if the fixed-
  457. | point input is too large, the invalid exception is raised and the largest
  458. | positive or negative integer is returned.
  459. *----------------------------------------------------------------------------*}
  460. function roundAndPackInt32( zSign: flag; absZ : bits64): int32;
  461. var
  462. roundingMode: int8;
  463. roundNearestEven: flag;
  464. roundIncrement, roundBits: int8;
  465. z: int32;
  466. begin
  467. roundingMode := softfloat_rounding_mode;
  468. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  469. roundIncrement := $40;
  470. if ( roundNearestEven=0 ) then
  471. begin
  472. if ( roundingMode = float_round_to_zero ) then
  473. begin
  474. roundIncrement := 0;
  475. end
  476. else begin
  477. roundIncrement := $7F;
  478. if ( zSign<>0 ) then
  479. begin
  480. if ( roundingMode = float_round_up ) then
  481. roundIncrement := 0;
  482. end
  483. else begin
  484. if ( roundingMode = float_round_down ) then
  485. roundIncrement := 0;
  486. end;
  487. end;
  488. end;
  489. roundBits := absZ and $7F;
  490. absZ := ( absZ + roundIncrement ) shr 7;
  491. absZ := absZ and not( ord( ( roundBits xor $40 ) = 0 ) and roundNearestEven );
  492. z := absZ;
  493. if ( zSign<>0 ) then
  494. z := - z;
  495. if ( ( absZ shr 32 ) or ( z and ( ord( z < 0 ) xor zSign ) ) )<>0 then
  496. begin
  497. float_raise( float_flag_invalid );
  498. if zSign<>0 then
  499. result:=sbits32($80000000)
  500. else
  501. result:=$7FFFFFFF;
  502. exit;
  503. end;
  504. if ( roundBits<>0 ) then
  505. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  506. result:=z;
  507. end;
  508. {*----------------------------------------------------------------------------
  509. | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
  510. | `absZ1', with binary point between bits 63 and 64 (between the input words),
  511. | and returns the properly rounded 64-bit integer corresponding to the input.
  512. | If `zSign' is 1, the input is negated before being converted to an integer.
  513. | Ordinarily, the fixed-point input is simply rounded to an integer, with
  514. | the inexact exception raised if the input cannot be represented exactly as
  515. | an integer. However, if the fixed-point input is too large, the invalid
  516. | exception is raised and the largest positive or negative integer is
  517. | returned.
  518. *----------------------------------------------------------------------------*}
  519. function roundAndPackInt64( zSign: flag; absZ0: bits64; absZ1 : bits64): int64;
  520. var
  521. roundingMode: int8;
  522. roundNearestEven, increment: flag;
  523. z: int64;
  524. label
  525. overflow;
  526. begin
  527. roundingMode := softfloat_rounding_mode;
  528. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  529. increment := ord( sbits64(absZ1) < 0 );
  530. if ( roundNearestEven=0 ) then
  531. begin
  532. if ( roundingMode = float_round_to_zero ) then
  533. begin
  534. increment := 0;
  535. end
  536. else begin
  537. if ( zSign<>0 ) then
  538. begin
  539. increment := ord(( roundingMode = float_round_down ) and (absZ1<>0));
  540. end
  541. else begin
  542. increment := ord(( roundingMode = float_round_up ) and (absZ1<>0));
  543. end;
  544. end;
  545. end;
  546. if ( increment<>0 ) then
  547. begin
  548. inc(absZ0);
  549. if ( absZ0 = 0 ) then
  550. goto overflow;
  551. absZ0 := absZ0 and not( ord( bits64( absZ1 shl 1 ) = 0 ) and roundNearestEven );
  552. end;
  553. z := absZ0;
  554. if ( zSign<>0 ) then
  555. z := - z;
  556. if ( (z<>0) and (( ord( z < 0 ) xor zSign )<>0) ) then
  557. begin
  558. overflow:
  559. float_raise( float_flag_invalid );
  560. if zSign<>0 then
  561. result:=int64($8000000000000000)
  562. else
  563. result:=int64($7FFFFFFFFFFFFFFF);
  564. end;
  565. if ( absZ1<>0 ) then
  566. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  567. result:=z;
  568. end;
  569. {*
  570. -------------------------------------------------------------------------------
  571. Shifts `a' right by the number of bits given in `count'. If any nonzero
  572. bits are shifted off, they are ``jammed'' into the least significant bit of
  573. the result by setting the least significant bit to 1. The value of `count'
  574. can be arbitrarily large; in particular, if `count' is greater than 32, the
  575. result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  576. The result is stored in the location pointed to by `zPtr'.
  577. -------------------------------------------------------------------------------
  578. *}
  579. Procedure shift32RightJamming( a: bits32 ; count: int16 ; VAR zPtr :bits32);
  580. var
  581. z: Bits32;
  582. Begin
  583. if ( count = 0 ) then
  584. z := a
  585. else
  586. if ( count < 32 ) then
  587. Begin
  588. z := ( a shr count ) or bits32( (( a shl ( ( - count ) AND 31 )) ) <> 0);
  589. End
  590. else
  591. Begin
  592. z := bits32( a <> 0 );
  593. End;
  594. zPtr := z;
  595. End;
  596. {*----------------------------------------------------------------------------
  597. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  598. | number of bits given in `count'. Any bits shifted off are lost. The value
  599. | of `count' can be arbitrarily large; in particular, if `count' is greater
  600. | than 128, the result will be 0. The result is broken into two 64-bit pieces
  601. | which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  602. *----------------------------------------------------------------------------*}
  603. procedure shift128Right(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  604. var
  605. z0, z1: bits64;
  606. negCount: int8;
  607. begin
  608. negCount := ( - count ) and 63;
  609. if ( count = 0 ) then
  610. begin
  611. z1 := a1;
  612. z0 := a0;
  613. end
  614. else if ( count < 64 ) then
  615. begin
  616. z1 := ( a0 shl negCount ) or ( a1 shr count );
  617. z0 := a0 shr count;
  618. end
  619. else
  620. begin
  621. if ( count shl 64 )<>0 then
  622. z1 := a0 shr ( count and 63 )
  623. else
  624. z1 := 0;
  625. z0 := 0;
  626. end;
  627. z1Ptr := z1;
  628. z0Ptr := z0;
  629. end;
  630. {*----------------------------------------------------------------------------
  631. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  632. | number of bits given in `count'. If any nonzero bits are shifted off, they
  633. | are ``jammed'' into the least significant bit of the result by setting the
  634. | least significant bit to 1. The value of `count' can be arbitrarily large;
  635. | in particular, if `count' is greater than 128, the result will be either
  636. | 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  637. | nonzero. The result is broken into two 64-bit pieces which are stored at
  638. | the locations pointed to by `z0Ptr' and `z1Ptr'.
  639. *----------------------------------------------------------------------------*}
  640. procedure shift128RightJamming(a0,a1 : bits64; count : int16; var z0Ptr, z1Ptr : bits64);
  641. var
  642. z0,z1 : bits64;
  643. negCount : int8;
  644. begin
  645. negCount := ( - count ) and 63;
  646. if ( count = 0 ) then begin
  647. z1 := a1;
  648. z0 := a0;
  649. end
  650. else if ( count < 64 ) then begin
  651. z1 := ( a0 shl negCount ) or ( a1 shr count ) or ord( ( a1 shl negCount ) <> 0 );
  652. z0 := a0>>count;
  653. end
  654. else begin
  655. if ( count = 64 ) then begin
  656. z1 := a0 or ord( a1 <> 0 );
  657. end
  658. else if ( count < 128 ) then begin
  659. z1 := ( a0 shr ( count and 63 ) ) or ord( ( ( a0 shl negCount ) or a1 ) <> 0 );
  660. end
  661. else begin
  662. z1 := ord( ( a0 or a1 ) <> 0 );
  663. end;
  664. z0 := 0;
  665. end;
  666. z1Ptr := z1;
  667. z0Ptr := z0;
  668. end;
  669. {*
  670. -------------------------------------------------------------------------------
  671. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  672. number of bits given in `count'. Any bits shifted off are lost. The value
  673. of `count' can be arbitrarily large; in particular, if `count' is greater
  674. than 64, the result will be 0. The result is broken into two 32-bit pieces
  675. which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  676. -------------------------------------------------------------------------------
  677. *}
  678. Procedure
  679. shift64Right(
  680. a0 :bits32; a1: bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32);
  681. Var
  682. z0, z1: bits32;
  683. negCount : int8;
  684. Begin
  685. negCount := ( - count ) AND 31;
  686. if ( count = 0 ) then
  687. Begin
  688. z1 := a1;
  689. z0 := a0;
  690. End
  691. else if ( count < 32 ) then
  692. Begin
  693. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  694. z0 := a0 shr count;
  695. End
  696. else
  697. Begin
  698. if (count < 64) then
  699. z1 := ( a0 shr ( count AND 31 ) )
  700. else
  701. z1 := 0;
  702. z0 := 0;
  703. End;
  704. z1Ptr := z1;
  705. z0Ptr := z0;
  706. End;
  707. {*
  708. -------------------------------------------------------------------------------
  709. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  710. number of bits given in `count'. If any nonzero bits are shifted off, they
  711. are ``jammed'' into the least significant bit of the result by setting the
  712. least significant bit to 1. The value of `count' can be arbitrarily large;
  713. in particular, if `count' is greater than 64, the result will be either 0
  714. or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  715. nonzero. The result is broken into two 32-bit pieces which are stored at
  716. the locations pointed to by `z0Ptr' and `z1Ptr'.
  717. -------------------------------------------------------------------------------
  718. *}
  719. Procedure
  720. shift64RightJamming(
  721. a0:bits32; a1: bits32; count:int16; VAR Z0Ptr :bits32;VAR z1Ptr: bits32 );
  722. VAR
  723. z0, z1 : bits32;
  724. negCount : int8;
  725. Begin
  726. negCount := ( - count ) AND 31;
  727. if ( count = 0 ) then
  728. Begin
  729. z1 := a1;
  730. z0 := a0;
  731. End
  732. else
  733. if ( count < 32 ) then
  734. Begin
  735. z1 := ( a0 shl negCount ) OR ( a1 shr count ) OR bits32( ( a1 shl negCount ) <> 0 );
  736. z0 := a0 shr count;
  737. End
  738. else
  739. Begin
  740. if ( count = 32 ) then
  741. Begin
  742. z1 := a0 OR bits32( a1 <> 0 );
  743. End
  744. else
  745. if ( count < 64 ) Then
  746. Begin
  747. z1 := ( a0 shr ( count AND 31 ) ) OR bits32( ( ( a0 shl negCount ) OR a1 ) <> 0 );
  748. End
  749. else
  750. Begin
  751. z1 := bits32( ( a0 OR a1 ) <> 0 );
  752. End;
  753. z0 := 0;
  754. End;
  755. z1Ptr := z1;
  756. z0Ptr := z0;
  757. End;
  758. {*----------------------------------------------------------------------------
  759. | Shifts `a' right by the number of bits given in `count'. If any nonzero
  760. | bits are shifted off, they are ``jammed'' into the least significant bit of
  761. | the result by setting the least significant bit to 1. The value of `count'
  762. | can be arbitrarily large; in particular, if `count' is greater than 64, the
  763. | result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  764. | The result is stored in the location pointed to by `zPtr'.
  765. *----------------------------------------------------------------------------*}
  766. procedure shift64RightJamming(a: bits64; count: int16; var zPtr : bits64);
  767. var
  768. z: bits64;
  769. begin
  770. if ( count = 0 ) then
  771. begin
  772. z := a;
  773. end
  774. else if ( count < 64 ) then
  775. begin
  776. z := ( a shr count ) or ord( ( a shl ( ( - count ) and 63 ) ) <> 0 );
  777. end
  778. else
  779. begin
  780. z := ord( a <> 0 );
  781. end;
  782. zPtr := z;
  783. end;
  784. {*
  785. -------------------------------------------------------------------------------
  786. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
  787. by 32 _plus_ the number of bits given in `count'. The shifted result is
  788. at most 64 nonzero bits; these are broken into two 32-bit pieces which are
  789. stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  790. off form a third 32-bit result as follows: The _last_ bit shifted off is
  791. the most-significant bit of the extra result, and the other 31 bits of the
  792. extra result are all zero if and only if _all_but_the_last_ bits shifted off
  793. were all zero. This extra result is stored in the location pointed to by
  794. `z2Ptr'. The value of `count' can be arbitrarily large.
  795. (This routine makes more sense if `a0', `a1', and `a2' are considered
  796. to form a fixed-point value with binary point between `a1' and `a2'. This
  797. fixed-point value is shifted right by the number of bits given in `count',
  798. and the integer part of the result is returned at the locations pointed to
  799. by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  800. corrupted as described above, and is returned at the location pointed to by
  801. `z2Ptr'.)
  802. -------------------------------------------------------------------------------
  803. }
  804. Procedure
  805. shift64ExtraRightJamming(
  806. a0: bits32;
  807. a1: bits32;
  808. a2: bits32;
  809. count: int16;
  810. VAR z0Ptr: bits32;
  811. VAR z1Ptr: bits32;
  812. VAR z2Ptr: bits32
  813. );
  814. Var
  815. z0, z1, z2: bits32;
  816. negCount : int8;
  817. Begin
  818. negCount := ( - count ) AND 31;
  819. if ( count = 0 ) then
  820. Begin
  821. z2 := a2;
  822. z1 := a1;
  823. z0 := a0;
  824. End
  825. else
  826. Begin
  827. if ( count < 32 ) Then
  828. Begin
  829. z2 := a1 shl negCount;
  830. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  831. z0 := a0 shr count;
  832. End
  833. else
  834. Begin
  835. if ( count = 32 ) then
  836. Begin
  837. z2 := a1;
  838. z1 := a0;
  839. End
  840. else
  841. Begin
  842. a2 := a2 or a1;
  843. if ( count < 64 ) then
  844. Begin
  845. z2 := a0 shl negCount;
  846. z1 := a0 shr ( count AND 31 );
  847. End
  848. else
  849. Begin
  850. if count = 64 then
  851. z2 := a0
  852. else
  853. z2 := bits32(a0 <> 0);
  854. z1 := 0;
  855. End;
  856. End;
  857. z0 := 0;
  858. End;
  859. z2 := z2 or bits32( a2 <> 0 );
  860. End;
  861. z2Ptr := z2;
  862. z1Ptr := z1;
  863. z0Ptr := z0;
  864. End;
  865. {*
  866. -------------------------------------------------------------------------------
  867. Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
  868. number of bits given in `count'. Any bits shifted off are lost. The value
  869. of `count' must be less than 32. The result is broken into two 32-bit
  870. pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  871. -------------------------------------------------------------------------------
  872. *}
  873. Procedure
  874. shortShift64Left(
  875. a0:bits32; a1:bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
  876. Begin
  877. z1Ptr := a1 shl count;
  878. if count = 0 then
  879. z0Ptr := a0
  880. else
  881. z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );
  882. End;
  883. {*
  884. -------------------------------------------------------------------------------
  885. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
  886. by the number of bits given in `count'. Any bits shifted off are lost.
  887. The value of `count' must be less than 32. The result is broken into three
  888. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  889. `z1Ptr', and `z2Ptr'.
  890. -------------------------------------------------------------------------------
  891. *}
  892. Procedure
  893. shortShift96Left(
  894. a0: bits32;
  895. a1: bits32;
  896. a2: bits32;
  897. count: int16;
  898. VAR z0Ptr: bits32;
  899. VAR z1Ptr: bits32;
  900. VAR z2Ptr: bits32
  901. );
  902. Var
  903. z0, z1, z2: bits32;
  904. negCount: int8;
  905. Begin
  906. z2 := a2 shl count;
  907. z1 := a1 shl count;
  908. z0 := a0 shl count;
  909. if ( 0 < count ) then
  910. Begin
  911. negCount := ( ( - count ) AND 31 );
  912. z1 := z1 or (a2 shr negCount);
  913. z0 := z0 or (a1 shr negCount);
  914. End;
  915. z2Ptr := z2;
  916. z1Ptr := z1;
  917. z0Ptr := z0;
  918. End;
  919. {*----------------------------------------------------------------------------
  920. | Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
  921. | number of bits given in `count'. Any bits shifted off are lost. The value
  922. | of `count' must be less than 64. The result is broken into two 64-bit
  923. | pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  924. *----------------------------------------------------------------------------*}
  925. procedure shortShift128Left(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; z1Ptr : bits64);
  926. begin
  927. z1Ptr := a1 shl count;
  928. if count=0 then
  929. z0Ptr:=a0
  930. else
  931. z0Ptr:=( a0 shl count ) or ( a1 shr ( ( - count ) and 63 ) );
  932. end;
  933. {*
  934. -------------------------------------------------------------------------------
  935. Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
  936. value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
  937. any carry out is lost. The result is broken into two 32-bit pieces which
  938. are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  939. -------------------------------------------------------------------------------
  940. *}
  941. Procedure
  942. add64(
  943. a0:bits32; a1:bits32; b0:bits32; b1:bits32; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
  944. Var
  945. z1: bits32;
  946. Begin
  947. z1 := a1 + b1;
  948. z1Ptr := z1;
  949. z0Ptr := a0 + b0 + bits32( z1 < a1 );
  950. End;
  951. {*
  952. -------------------------------------------------------------------------------
  953. Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
  954. 96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  955. modulo 2^96, so any carry out is lost. The result is broken into three
  956. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  957. `z1Ptr', and `z2Ptr'.
  958. -------------------------------------------------------------------------------
  959. *}
  960. Procedure
  961. add96(
  962. a0: bits32;
  963. a1: bits32;
  964. a2: bits32;
  965. b0: bits32;
  966. b1: bits32;
  967. b2: bits32;
  968. VAR z0Ptr: bits32;
  969. VAR z1Ptr: bits32;
  970. VAR z2Ptr: bits32
  971. );
  972. var
  973. z0, z1, z2: bits32;
  974. carry0, carry1: int8;
  975. Begin
  976. z2 := a2 + b2;
  977. carry1 := int8( z2 < a2 );
  978. z1 := a1 + b1;
  979. carry0 := int8( z1 < a1 );
  980. z0 := a0 + b0;
  981. z1 := z1 + carry1;
  982. z0 := z0 + bits32( z1 < carry1 );
  983. z0 := z0 + carry0;
  984. z2Ptr := z2;
  985. z1Ptr := z1;
  986. z0Ptr := z0;
  987. End;
  988. {*----------------------------------------------------------------------------
  989. | Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
  990. | by the number of bits given in `count'. Any bits shifted off are lost.
  991. | The value of `count' must be less than 64. The result is broken into three
  992. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  993. | `z1Ptr', and `z2Ptr'.
  994. *----------------------------------------------------------------------------*}
  995. procedure shortShift192Left(a0,a1,a2 : bits64;count : int16;var z0Ptr,z1Ptr,z2Ptr : bits64);
  996. var
  997. z0, z1, z2 : bits64;
  998. negCount : int8;
  999. begin
  1000. z2 := a2 shl count;
  1001. z1 := a1 shl count;
  1002. z0 := a0 shl count;
  1003. if ( 0 < count ) then
  1004. begin
  1005. negCount := ( ( - count ) and 63 );
  1006. z1 := z1 or (a2 shr negCount);
  1007. z0 := z0 or (a1 shr negCount);
  1008. end;
  1009. z2Ptr := z2;
  1010. z1Ptr := z1;
  1011. z0Ptr := z0;
  1012. end;
  1013. {*----------------------------------------------------------------------------
  1014. | Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
  1015. | value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
  1016. | any carry out is lost. The result is broken into two 64-bit pieces which
  1017. | are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  1018. *----------------------------------------------------------------------------*}
  1019. procedure add128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);inline;
  1020. var
  1021. z1 : bits64;
  1022. begin
  1023. z1 := a1 + b1;
  1024. z1Ptr := z1;
  1025. z0Ptr := a0 + b0 + ord( z1 < a1 );
  1026. end;
  1027. {*----------------------------------------------------------------------------
  1028. | Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
  1029. | 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  1030. | modulo 2^192, so any carry out is lost. The result is broken into three
  1031. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  1032. | `z1Ptr', and `z2Ptr'.
  1033. *----------------------------------------------------------------------------*}
  1034. procedure add192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);
  1035. var
  1036. z0, z1, z2 : bits64;
  1037. carry0, carry1 : int8;
  1038. begin
  1039. z2 := a2 + b2;
  1040. carry1 := ord( z2 < a2 );
  1041. z1 := a1 + b1;
  1042. carry0 := ord( z1 < a1 );
  1043. z0 := a0 + b0;
  1044. inc(z1, carry1);
  1045. inc(z0, ord( z1 < carry1 ));
  1046. inc(z0, carry0);
  1047. z2Ptr := z2;
  1048. z1Ptr := z1;
  1049. z0Ptr := z0;
  1050. end;
  1051. {*
  1052. -------------------------------------------------------------------------------
  1053. Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
  1054. 64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  1055. 2^64, so any borrow out (carry out) is lost. The result is broken into two
  1056. 32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  1057. `z1Ptr'.
  1058. -------------------------------------------------------------------------------
  1059. *}
  1060. Procedure
  1061. sub64(
  1062. a0: bits32; a1 : bits32; b0 :bits32; b1: bits32; VAR z0Ptr:bits32; VAR z1Ptr: bits32 );
  1063. Begin
  1064. z1Ptr := a1 - b1;
  1065. z0Ptr := a0 - b0 - bits32( a1 < b1 );
  1066. End;
  1067. {*
  1068. -------------------------------------------------------------------------------
  1069. Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
  1070. the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
  1071. is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
  1072. into three 32-bit pieces which are stored at the locations pointed to by
  1073. `z0Ptr', `z1Ptr', and `z2Ptr'.
  1074. -------------------------------------------------------------------------------
  1075. *}
  1076. Procedure
  1077. sub96(
  1078. a0:bits32;
  1079. a1:bits32;
  1080. a2:bits32;
  1081. b0:bits32;
  1082. b1:bits32;
  1083. b2:bits32;
  1084. VAR z0Ptr:bits32;
  1085. VAR z1Ptr:bits32;
  1086. VAR z2Ptr:bits32
  1087. );
  1088. Var
  1089. z0, z1, z2: bits32;
  1090. borrow0, borrow1: int8;
  1091. Begin
  1092. z2 := a2 - b2;
  1093. borrow1 := int8( a2 < b2 );
  1094. z1 := a1 - b1;
  1095. borrow0 := int8( a1 < b1 );
  1096. z0 := a0 - b0;
  1097. z0 := z0 - bits32( z1 < borrow1 );
  1098. z1 := z1 - borrow1;
  1099. z0 := z0 -borrow0;
  1100. z2Ptr := z2;
  1101. z1Ptr := z1;
  1102. z0Ptr := z0;
  1103. End;
  1104. {*----------------------------------------------------------------------------
  1105. | Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
  1106. | 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  1107. | 2^128, so any borrow out (carry out) is lost. The result is broken into two
  1108. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  1109. | `z1Ptr'.
  1110. *----------------------------------------------------------------------------*}
  1111. procedure sub128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);
  1112. begin
  1113. z1Ptr := a1 - b1;
  1114. z0Ptr := a0 - b0 - ord( a1 < b1 );
  1115. end;
  1116. {*----------------------------------------------------------------------------
  1117. | Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
  1118. | from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
  1119. | Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
  1120. | result is broken into three 64-bit pieces which are stored at the locations
  1121. | pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
  1122. *----------------------------------------------------------------------------*}
  1123. procedure sub192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);
  1124. var
  1125. z0, z1, z2 : bits64;
  1126. borrow0, borrow1 : int8;
  1127. begin
  1128. z2 := a2 - b2;
  1129. borrow1 := ord( a2 < b2 );
  1130. z1 := a1 - b1;
  1131. borrow0 := ord( a1 < b1 );
  1132. z0 := a0 - b0;
  1133. dec(z0, ord( z1 < borrow1 ));
  1134. dec(z1, borrow1);
  1135. dec(z0, borrow0);
  1136. z2Ptr := z2;
  1137. z1Ptr := z1;
  1138. z0Ptr := z0;
  1139. end;
  1140. {*
  1141. -------------------------------------------------------------------------------
  1142. Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
  1143. into two 32-bit pieces which are stored at the locations pointed to by
  1144. `z0Ptr' and `z1Ptr'.
  1145. -------------------------------------------------------------------------------
  1146. *}
  1147. Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr
  1148. :bits32 );
  1149. Var
  1150. aHigh, aLow, bHigh, bLow: bits16;
  1151. z0, zMiddleA, zMiddleB, z1: bits32;
  1152. Begin
  1153. aLow := a and $ffff;
  1154. aHigh := a shr 16;
  1155. bLow := b and $ffff;
  1156. bHigh := b shr 16;
  1157. z1 := ( bits32( aLow) ) * bLow;
  1158. zMiddleA := ( bits32 (aLow) ) * bHigh;
  1159. zMiddleB := ( bits32 (aHigh) ) * bLow;
  1160. z0 := ( bits32 (aHigh) ) * bHigh;
  1161. zMiddleA := zMiddleA + zMiddleB;
  1162. z0 := z0 + ( ( bits32 ( zMiddleA < zMiddleB ) ) shl 16 ) + ( zMiddleA shr 16 );
  1163. zMiddleA := zmiddleA shl 16;
  1164. z1 := z1 + zMiddleA;
  1165. z0 := z0 + bits32( z1 < zMiddleA );
  1166. z1Ptr := z1;
  1167. z0Ptr := z0;
  1168. End;
  1169. {*
  1170. -------------------------------------------------------------------------------
  1171. Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
  1172. to obtain a 96-bit product. The product is broken into three 32-bit pieces
  1173. which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  1174. `z2Ptr'.
  1175. -------------------------------------------------------------------------------
  1176. *}
  1177. Procedure
  1178. mul64By32To96(
  1179. a0:bits32;
  1180. a1:bits32;
  1181. b:bits32;
  1182. VAR z0Ptr:bits32;
  1183. VAR z1Ptr:bits32;
  1184. VAR z2Ptr:bits32
  1185. );
  1186. Var
  1187. z0, z1, z2, more1: bits32;
  1188. Begin
  1189. mul32To64( a1, b, z1, z2 );
  1190. mul32To64( a0, b, z0, more1 );
  1191. add64( z0, more1, 0, z1, z0, z1 );
  1192. z2Ptr := z2;
  1193. z1Ptr := z1;
  1194. z0Ptr := z0;
  1195. End;
  1196. {*
  1197. -------------------------------------------------------------------------------
  1198. Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
  1199. 64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
  1200. product. The product is broken into four 32-bit pieces which are stored at
  1201. the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  1202. -------------------------------------------------------------------------------
  1203. *}
  1204. Procedure
  1205. mul64To128(
  1206. a0:bits32;
  1207. a1:bits32;
  1208. b0:bits32;
  1209. b1:bits32;
  1210. VAR z0Ptr:bits32;
  1211. VAR z1Ptr:bits32;
  1212. VAR z2Ptr:bits32;
  1213. VAR z3Ptr:bits32
  1214. );
  1215. Var
  1216. z0, z1, z2, z3: bits32;
  1217. more1, more2: bits32;
  1218. Begin
  1219. mul32To64( a1, b1, z2, z3 );
  1220. mul32To64( a1, b0, z1, more2 );
  1221. add64( z1, more2, 0, z2, z1, z2 );
  1222. mul32To64( a0, b0, z0, more1 );
  1223. add64( z0, more1, 0, z1, z0, z1 );
  1224. mul32To64( a0, b1, more1, more2 );
  1225. add64( more1, more2, 0, z2, more1, z2 );
  1226. add64( z0, z1, 0, more1, z0, z1 );
  1227. z3Ptr := z3;
  1228. z2Ptr := z2;
  1229. z1Ptr := z1;
  1230. z0Ptr := z0;
  1231. End;
  1232. {*----------------------------------------------------------------------------
  1233. | Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
  1234. | into two 64-bit pieces which are stored at the locations pointed to by
  1235. | `z0Ptr' and `z1Ptr'.
  1236. *----------------------------------------------------------------------------*}
  1237. procedure mul64To128( a, b : bits64; var z0Ptr, z1Ptr : bits64);
  1238. var
  1239. aHigh, aLow, bHigh, bLow : bits32;
  1240. z0, zMiddleA, zMiddleB, z1 : bits64;
  1241. begin
  1242. aLow := a;
  1243. aHigh := a shr 32;
  1244. bLow := b;
  1245. bHigh := b shr 32;
  1246. z1 := ( bits64(aLow) ) * bLow;
  1247. zMiddleA := ( bits64( aLow )) * bHigh;
  1248. zMiddleB := ( bits64( aHigh )) * bLow;
  1249. z0 := ( bits64(aHigh) ) * bHigh;
  1250. inc(zMiddleA, zMiddleB);
  1251. inc(z0 ,( ( bits64( zMiddleA < zMiddleB ) ) shl 32 ) + ( zMiddleA shr 32 ));
  1252. zMiddleA := zMiddleA shl 32;
  1253. inc(z1, zMiddleA);
  1254. inc(z0, ord( z1 < zMiddleA ));
  1255. z1Ptr := z1;
  1256. z0Ptr := z0;
  1257. end;
  1258. {*----------------------------------------------------------------------------
  1259. | Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
  1260. | 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
  1261. | product. The product is broken into four 64-bit pieces which are stored at
  1262. | the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  1263. *----------------------------------------------------------------------------*}
  1264. procedure mul128To256(a0,a1,b0,b1 : bits64;var z0Ptr,z1Ptr,z2Ptr,z3Ptr : bits64);
  1265. var
  1266. z0,z1,z2,z3,more1,more2 : bits64;
  1267. begin
  1268. mul64To128( a1, b1, z2, z3 );
  1269. mul64To128( a1, b0, z1, more2 );
  1270. add128( z1, more2, 0, z2, z1, z2 );
  1271. mul64To128( a0, b0, z0, more1 );
  1272. add128( z0, more1, 0, z1, z0, z1 );
  1273. mul64To128( a0, b1, more1, more2 );
  1274. add128( more1, more2, 0, z2, more1, z2 );
  1275. add128( z0, z1, 0, more1, z0, z1 );
  1276. z3Ptr := z3;
  1277. z2Ptr := z2;
  1278. z1Ptr := z1;
  1279. z0Ptr := z0;
  1280. end;
  1281. {*----------------------------------------------------------------------------
  1282. | Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
  1283. | `b' to obtain a 192-bit product. The product is broken into three 64-bit
  1284. | pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  1285. | `z2Ptr'.
  1286. *----------------------------------------------------------------------------*}
  1287. procedure mul128By64To192(a0,a1,b : bits64;var z0Ptr,z1Ptr,z2Ptr : bits64);
  1288. var
  1289. z0, z1, z2, more1 : bits64;
  1290. begin
  1291. mul64To128( a1, b, z1, z2 );
  1292. mul64To128( a0, b, z0, more1 );
  1293. add128( z0, more1, 0, z1, z0, z1 );
  1294. z2Ptr := z2;
  1295. z1Ptr := z1;
  1296. z0Ptr := z0;
  1297. end;
  1298. {*----------------------------------------------------------------------------
  1299. | Returns an approximation to the 64-bit integer quotient obtained by dividing
  1300. | `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
  1301. | divisor `b' must be at least 2^63. If q is the exact quotient truncated
  1302. | toward zero, the approximation returned lies between q and q + 2 inclusive.
  1303. | If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
  1304. | unsigned integer is returned.
  1305. *----------------------------------------------------------------------------*}
  1306. Function estimateDiv128To64( a0:bits64; a1: bits64; b:bits64): bits64;
  1307. var
  1308. b0, b1, rem0, rem1, term0, term1, z : bits64;
  1309. begin
  1310. if ( b <= a0 ) then
  1311. begin
  1312. result:=qword( $FFFFFFFFFFFFFFFF );
  1313. exit;
  1314. end;
  1315. b0 := b shr 32;
  1316. if ( b0 shl 32 <= a0 ) then
  1317. z:=qword( $FFFFFFFF00000000 )
  1318. else
  1319. z:=( a0 div b0 ) shl 32;
  1320. mul64To128( b, z, term0, term1 );
  1321. sub128( a0, a1, term0, term1, rem0, rem1 );
  1322. while ( ( sbits64(rem0) ) < 0 ) do begin
  1323. dec(z,qword( $100000000 ));
  1324. b1 := b shl 32;
  1325. add128( rem0, rem1, b0, b1, rem0, rem1 );
  1326. end;
  1327. rem0 := ( rem0 shl 32 ) or ( rem1 shr 32 );
  1328. if ( b0 shl 32 <= rem0 ) then
  1329. z:=z or $FFFFFFFF
  1330. else
  1331. z:=z or rem0 div b0;
  1332. result:=z;
  1333. end;
  1334. {*
  1335. -------------------------------------------------------------------------------
  1336. Returns an approximation to the 32-bit integer quotient obtained by dividing
  1337. `b' into the 64-bit value formed by concatenating `a0' and `a1'. The
  1338. divisor `b' must be at least 2^31. If q is the exact quotient truncated
  1339. toward zero, the approximation returned lies between q and q + 2 inclusive.
  1340. If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
  1341. unsigned integer is returned.
  1342. -------------------------------------------------------------------------------
  1343. *}
  1344. Function estimateDiv64To32( a0:bits32; a1: bits32; b:bits32): bits32;
  1345. Var
  1346. b0, b1: bits32;
  1347. rem0, rem1, term0, term1: bits32;
  1348. z: bits32;
  1349. Begin
  1350. if ( b <= a0 ) then
  1351. Begin
  1352. estimateDiv64To32 := $FFFFFFFF;
  1353. exit;
  1354. End;
  1355. b0 := b shr 16;
  1356. if ( b0 shl 16 <= a0 ) then
  1357. z:= $FFFF0000
  1358. else
  1359. z:= ( a0 div b0 ) shl 16;
  1360. mul32To64( b, z, term0, term1 );
  1361. sub64( a0, a1, term0, term1, rem0, rem1 );
  1362. while ( ( sbits32 (rem0) ) < 0 ) do
  1363. Begin
  1364. z := z - $10000;
  1365. b1 := b shl 16;
  1366. add64( rem0, rem1, b0, b1, rem0, rem1 );
  1367. End;
  1368. rem0 := ( rem0 shl 16 ) OR ( rem1 shr 16 );
  1369. if ( b0 shl 16 <= rem0 ) then
  1370. z := z or $FFFF
  1371. else
  1372. z := z or (rem0 div b0);
  1373. estimateDiv64To32 := z;
  1374. End;
  1375. {*
  1376. -------------------------------------------------------------------------------
  1377. Returns an approximation to the square root of the 32-bit significand given
  1378. by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
  1379. `aExp' (the least significant bit) is 1, the integer returned approximates
  1380. 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
  1381. is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
  1382. case, the approximation returned lies strictly within +/-2 of the exact
  1383. value.
  1384. -------------------------------------------------------------------------------
  1385. *}
  1386. Function estimateSqrt32( aExp: int16; a: bits32 ): bits32;
  1387. const sqrtOddAdjustments: array[0..15] of bits16 = (
  1388. $0004, $0022, $005D, $00B1, $011D, $019F, $0236, $02E0,
  1389. $039C, $0468, $0545, $0631, $072B, $0832, $0946, $0A67
  1390. );
  1391. const sqrtEvenAdjustments: array[0..15] of bits16 = (
  1392. $0A2D, $08AF, $075A, $0629, $051A, $0429, $0356, $029E,
  1393. $0200, $0179, $0109, $00AF, $0068, $0034, $0012, $0002
  1394. );
  1395. Var
  1396. index: int8;
  1397. z: bits32;
  1398. Begin
  1399. index := ( a shr 27 ) AND 15;
  1400. if ( aExp AND 1 ) <> 0 then
  1401. Begin
  1402. z := $4000 + ( a shr 17 ) - sqrtOddAdjustments[ index ];
  1403. z := ( ( a div z ) shl 14 ) + ( z shl 15 );
  1404. a := a shr 1;
  1405. End
  1406. else
  1407. Begin
  1408. z := $8000 + ( a shr 17 ) - sqrtEvenAdjustments[ index ];
  1409. z := a div z + z;
  1410. if ( $20000 <= z ) then
  1411. z := $FFFF8000
  1412. else
  1413. z := ( z shl 15 );
  1414. if ( z <= a ) then
  1415. Begin
  1416. estimateSqrt32 := bits32 ( ( sbits32 (a )) shr 1 );
  1417. exit;
  1418. End;
  1419. End;
  1420. estimateSqrt32 := ( ( estimateDiv64To32( a, 0, z ) ) shr 1 ) + ( z shr 1 );
  1421. End;
  1422. {*
  1423. -------------------------------------------------------------------------------
  1424. Returns the number of leading 0 bits before the most-significant 1 bit of
  1425. `a'. If `a' is zero, 32 is returned.
  1426. -------------------------------------------------------------------------------
  1427. *}
  1428. Function countLeadingZeros32( a:bits32 ): int8;
  1429. const countLeadingZerosHigh:array[0..255] of int8 = (
  1430. 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
  1431. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1432. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1433. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1434. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1435. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1436. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1437. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1438. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1439. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1440. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1441. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1442. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1443. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1444. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1445. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  1446. );
  1447. Var
  1448. shiftCount: int8;
  1449. Begin
  1450. shiftCount := 0;
  1451. if ( a < $10000 ) then
  1452. Begin
  1453. shiftCount := shiftcount + 16;
  1454. a := a shl 16;
  1455. End;
  1456. if ( a < $1000000 ) then
  1457. Begin
  1458. shiftCount := shiftcount + 8;
  1459. a := a shl 8;
  1460. end;
  1461. shiftCount := shiftcount + countLeadingZerosHigh[ a shr 24 ];
  1462. countLeadingZeros32:= shiftCount;
  1463. End;
  1464. {*----------------------------------------------------------------------------
  1465. | Returns the number of leading 0 bits before the most-significant 1 bit of
  1466. | `a'. If `a' is zero, 64 is returned.
  1467. *----------------------------------------------------------------------------*}
  1468. function countLeadingZeros64( a : bits64): int8;
  1469. var
  1470. shiftcount : int8;
  1471. Begin
  1472. shiftCount := 0;
  1473. if ( a < bits64(bits64(1) shl 32 )) then
  1474. shiftCount := shiftcount + 32
  1475. else
  1476. a := a shr 32;
  1477. shiftCount := shiftCount + countLeadingZeros32( a );
  1478. countLeadingZeros64:= shiftCount;
  1479. End;
  1480. {*
  1481. -------------------------------------------------------------------------------
  1482. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is
  1483. equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1484. returns 0.
  1485. -------------------------------------------------------------------------------
  1486. *}
  1487. Function eq64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1488. Begin
  1489. eq64 := flag( a0 = b0 ) and flag( a1 = b1 );
  1490. End;
  1491. {*
  1492. -------------------------------------------------------------------------------
  1493. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1494. than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
  1495. Otherwise, returns 0.
  1496. -------------------------------------------------------------------------------
  1497. *}
  1498. Function le64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1499. Begin
  1500. le64:= flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 <= b1 ) );
  1501. End;
  1502. {*
  1503. -------------------------------------------------------------------------------
  1504. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1505. than the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1506. returns 0.
  1507. -------------------------------------------------------------------------------
  1508. *}
  1509. Function lt64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1510. Begin
  1511. lt64 := flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 < b1 ) );
  1512. End;
  1513. {*
  1514. -------------------------------------------------------------------------------
  1515. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is not
  1516. equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1517. returns 0.
  1518. -------------------------------------------------------------------------------
  1519. *}
  1520. Function ne64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
  1521. Begin
  1522. ne64:= flag( a0 <> b0 ) or flag( a1 <> b1 );
  1523. End;
  1524. const
  1525. float128_default_nan_high = qword($FFFFFFFFFFFFFFFF);
  1526. float128_default_nan_low = qword($FFFFFFFFFFFFFFFF);
  1527. (*****************************************************************************)
  1528. (* End Low-Level arithmetic *)
  1529. (*****************************************************************************)
  1530. {*
  1531. -------------------------------------------------------------------------------
  1532. Functions and definitions to determine: (1) whether tininess for underflow
  1533. is detected before or after rounding by default, (2) what (if anything)
  1534. happens when exceptions are raised, (3) how signaling NaNs are distinguished
  1535. from quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNs
  1536. are propagated from function inputs to output. These details are ENDIAN
  1537. specific
  1538. -------------------------------------------------------------------------------
  1539. *}
  1540. {$IFDEF ENDIAN_LITTLE}
  1541. {*
  1542. -------------------------------------------------------------------------------
  1543. Internal canonical NaN format.
  1544. -------------------------------------------------------------------------------
  1545. *}
  1546. TYPE
  1547. commonNaNT = packed record
  1548. sign: flag;
  1549. high, low : bits32;
  1550. end;
  1551. {*
  1552. -------------------------------------------------------------------------------
  1553. The pattern for a default generated single-precision NaN.
  1554. -------------------------------------------------------------------------------
  1555. *}
  1556. const float32_default_nan = $FFC00000;
  1557. {*
  1558. -------------------------------------------------------------------------------
  1559. Returns 1 if the single-precision floating-point value `a' is a NaN;
  1560. otherwise returns 0.
  1561. -------------------------------------------------------------------------------
  1562. *}
  1563. Function float32_is_nan( a : float32 ): flag;
  1564. Begin
  1565. float32_is_nan:= flag( $FF000000 < bits32 ( a shl 1 ) );
  1566. End;
  1567. {*
  1568. -------------------------------------------------------------------------------
  1569. Returns 1 if the single-precision floating-point value `a' is a signaling
  1570. NaN; otherwise returns 0.
  1571. -------------------------------------------------------------------------------
  1572. *}
  1573. Function float32_is_signaling_nan( a : float32 ): flag;
  1574. Begin
  1575. float32_is_signaling_nan := flag
  1576. ( ( ( a shr 22 ) and $1FF ) = $1FE ) and( a and $003FFFFF );
  1577. End;
  1578. {*
  1579. -------------------------------------------------------------------------------
  1580. Returns the result of converting the single-precision floating-point NaN
  1581. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1582. exception is raised.
  1583. -------------------------------------------------------------------------------
  1584. *}
  1585. Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT );
  1586. var
  1587. z : commonNaNT ;
  1588. Begin
  1589. if ( float32_is_signaling_nan( a ) <> 0) then
  1590. float_raise( float_flag_invalid );
  1591. z.sign := a shr 31;
  1592. z.low := 0;
  1593. z.high := a shl 9;
  1594. c := z;
  1595. End;
  1596. {*
  1597. -------------------------------------------------------------------------------
  1598. Returns the result of converting the canonical NaN `a' to the single-
  1599. precision floating-point format.
  1600. -------------------------------------------------------------------------------
  1601. *}
  1602. Function commonNaNToFloat32( a : commonNaNT ): float32;
  1603. Begin
  1604. commonNaNToFloat32 := ( ( bits32 (a.sign) ) shl 31 ) or $7FC00000 or ( a.high shr 9 );
  1605. End;
  1606. {*
  1607. -------------------------------------------------------------------------------
  1608. Takes two single-precision floating-point values `a' and `b', one of which
  1609. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1610. signaling NaN, the invalid exception is raised.
  1611. -------------------------------------------------------------------------------
  1612. *}
  1613. Function propagateFloat32NaN( a : float32 ; b: float32 ): float32;
  1614. Var
  1615. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1616. label returnLargerSignificand;
  1617. Begin
  1618. aIsNaN := float32_is_nan( a );
  1619. aIsSignalingNaN := float32_is_signaling_nan( a );
  1620. bIsNaN := float32_is_nan( b );
  1621. bIsSignalingNaN := float32_is_signaling_nan( b );
  1622. a := a or $00400000;
  1623. b := b or $00400000;
  1624. if ( aIsSignalingNaN or bIsSignalingNaN ) <> 0 then
  1625. float_raise( float_flag_invalid );
  1626. if ( aIsSignalingNaN )<> 0 then
  1627. Begin
  1628. if ( bIsSignalingNaN ) <> 0 then
  1629. goto returnLargerSignificand;
  1630. if bIsNan <> 0 then
  1631. propagateFloat32NaN := b
  1632. else
  1633. propagateFloat32NaN := a;
  1634. exit;
  1635. End
  1636. else if ( aIsNaN <> 0) then
  1637. Begin
  1638. if ( bIsSignalingNaN or not bIsNaN )<> 0 then
  1639. Begin
  1640. propagateFloat32NaN := a;
  1641. exit;
  1642. End;
  1643. returnLargerSignificand:
  1644. if ( bits32 ( a shl 1 ) < bits32 ( b shl 1 ) ) then
  1645. Begin
  1646. propagateFloat32NaN := b;
  1647. exit;
  1648. End;
  1649. if ( bits32 ( b shl 1 ) < bits32 ( a shl 1 ) ) then
  1650. Begin
  1651. propagateFloat32NaN := a;
  1652. End;
  1653. if a < b then
  1654. propagateFloat32NaN := a
  1655. else
  1656. propagateFloat32NaN := b;
  1657. exit;
  1658. End
  1659. else
  1660. Begin
  1661. propagateFloat32NaN := b;
  1662. exit;
  1663. End;
  1664. End;
  1665. {*
  1666. -------------------------------------------------------------------------------
  1667. The pattern for a default generated double-precision NaN. The `high' and
  1668. `low' values hold the most- and least-significant bits, respectively.
  1669. -------------------------------------------------------------------------------
  1670. *}
  1671. const
  1672. float64_default_nan_high = $FFF80000;
  1673. float64_default_nan_low = $00000000;
  1674. {*
  1675. -------------------------------------------------------------------------------
  1676. Returns 1 if the double-precision floating-point value `a' is a NaN;
  1677. otherwise returns 0.
  1678. -------------------------------------------------------------------------------
  1679. *}
  1680. Function float64_is_nan( a : float64 ) : flag;
  1681. Begin
  1682. float64_is_nan :=
  1683. flag( $FFE00000 <= bits32 ( a.high shl 1 ) )
  1684. and ( a.low or ( a.high and $000FFFFF ) );
  1685. End;
  1686. {*
  1687. -------------------------------------------------------------------------------
  1688. Returns 1 if the double-precision floating-point value `a' is a signaling
  1689. NaN; otherwise returns 0.
  1690. -------------------------------------------------------------------------------
  1691. *}
  1692. Function float64_is_signaling_nan( a : float64 ): flag;
  1693. Begin
  1694. float64_is_signaling_nan :=
  1695. flag( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  1696. and ( a.low or ( a.high and $0007FFFF ) );
  1697. End;
  1698. {*
  1699. -------------------------------------------------------------------------------
  1700. Returns the result of converting the double-precision floating-point NaN
  1701. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1702. exception is raised.
  1703. -------------------------------------------------------------------------------
  1704. *}
  1705. Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
  1706. Var
  1707. z : commonNaNT;
  1708. Begin
  1709. if ( float64_is_signaling_nan( a )<>0 ) then
  1710. float_raise( float_flag_invalid );
  1711. z.sign := a.high shr 31;
  1712. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  1713. c := z;
  1714. End;
  1715. function float64ToCommonNaN( a : float64 ) : commonNaNT;
  1716. Var
  1717. z : commonNaNT;
  1718. Begin
  1719. if ( float64_is_signaling_nan( a )<>0 ) then
  1720. float_raise( float_flag_invalid );
  1721. z.sign := a.high shr 31;
  1722. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  1723. result := z;
  1724. End;
  1725. {*
  1726. -------------------------------------------------------------------------------
  1727. Returns the result of converting the canonical NaN `a' to the double-
  1728. precision floating-point format.
  1729. -------------------------------------------------------------------------------
  1730. *}
  1731. Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64 );
  1732. Var
  1733. z: float64;
  1734. Begin
  1735. shift64Right( a.high, a.low, 12, z.high, z.low );
  1736. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  1737. c := z;
  1738. End;
  1739. {*
  1740. -------------------------------------------------------------------------------
  1741. Takes two double-precision floating-point values `a' and `b', one of which
  1742. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1743. signaling NaN, the invalid exception is raised.
  1744. -------------------------------------------------------------------------------
  1745. *}
  1746. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  1747. Var
  1748. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1749. label returnLargerSignificand;
  1750. Begin
  1751. aIsNaN := float64_is_nan( a );
  1752. aIsSignalingNaN := float64_is_signaling_nan( a );
  1753. bIsNaN := float64_is_nan( b );
  1754. bIsSignalingNaN := float64_is_signaling_nan( b );
  1755. a.high := a.high or $00080000;
  1756. b.high := b.high or $00080000;
  1757. if ( aIsSignalingNaN or bIsSignalingNaN )<> 0 then
  1758. float_raise( float_flag_invalid );
  1759. if ( aIsSignalingNaN )<>0 then
  1760. Begin
  1761. if ( bIsSignalingNaN )<>0 then
  1762. goto returnLargerSignificand;
  1763. if bIsNan <> 0 then
  1764. c := b
  1765. else
  1766. c := a;
  1767. exit;
  1768. End
  1769. else if ( aIsNaN )<> 0 then
  1770. Begin
  1771. if ( bIsSignalingNaN or not bIsNaN ) <> 0 then
  1772. Begin
  1773. c := a;
  1774. exit;
  1775. End;
  1776. returnLargerSignificand:
  1777. if ( lt64( a.high shl 1, a.low, b.high shl 1, b.low ) ) <> 0 then
  1778. Begin
  1779. c := b;
  1780. exit;
  1781. End;
  1782. if ( lt64( b.high shl 1, b.low, a.high shl 1, a.low ) ) <> 0 then
  1783. Begin
  1784. c := a;
  1785. exit;
  1786. End;
  1787. if a.high < b.high then
  1788. c := a
  1789. else
  1790. c := b;
  1791. exit;
  1792. End
  1793. else
  1794. Begin
  1795. c := b;
  1796. exit;
  1797. End;
  1798. End;
  1799. {*----------------------------------------------------------------------------
  1800. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  1801. | than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1802. | returns 0.
  1803. *----------------------------------------------------------------------------*}
  1804. function lt128(a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  1805. begin
  1806. result := ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 < b1 ) ));
  1807. end;
  1808. {*----------------------------------------------------------------------------
  1809. | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
  1810. | otherwise returns 0.
  1811. *----------------------------------------------------------------------------*}
  1812. function float128_is_nan( a : float128): flag;
  1813. begin
  1814. result:= ord(( int64( $FFFE000000000000 ) <= bits64( a.high shl 1 ) )
  1815. and ( (a.low<>0) or (( a.high and int64( $0000FFFFFFFFFFFF ) )<>0 ) ));
  1816. end;
  1817. {*----------------------------------------------------------------------------
  1818. | Returns 1 if the quadruple-precision floating-point value `a' is a
  1819. | signaling NaN; otherwise returns 0.
  1820. *----------------------------------------------------------------------------*}
  1821. function float128_is_signaling_nan( a : float128): flag;
  1822. begin
  1823. result:=ord(( ( ( a.high shr 47 ) and $FFFF ) = $FFFE ) and
  1824. ( (a.low<>0) or (( a.high and int64( $00007FFFFFFFFFFF ) )<>0) ));
  1825. end;
  1826. {*----------------------------------------------------------------------------
  1827. | Returns the result of converting the quadruple-precision floating-point NaN
  1828. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1829. | exception is raised.
  1830. *----------------------------------------------------------------------------*}
  1831. function float128ToCommonNaN( a : float128): commonNaNT;
  1832. var
  1833. z: commonNaNT;
  1834. qhigh,qlow : qword;
  1835. begin
  1836. if ( float128_is_signaling_nan( a )<>0) then
  1837. float_raise( float_flag_invalid );
  1838. z.sign := a.high shr 63;
  1839. shortShift128Left( a.high, a.low, 16, qhigh, qlow );
  1840. z.high:=qhigh shr 32;
  1841. z.low:=qhigh and $ffffffff;
  1842. result:=z;
  1843. end;
  1844. {*----------------------------------------------------------------------------
  1845. | Returns the result of converting the canonical NaN `a' to the quadruple-
  1846. | precision floating-point format.
  1847. *----------------------------------------------------------------------------*}
  1848. function commonNaNToFloat128( a : commonNaNT): float128;
  1849. var
  1850. z: float128;
  1851. begin
  1852. shift128Right( a.high, a.low, 16, z.high, z.low );
  1853. z.high := z.high or ( ( bits64(a.sign) ) shl 63 ) or int64( $7FFF800000000000 );
  1854. result:=z;
  1855. end;
  1856. {*----------------------------------------------------------------------------
  1857. | Takes two quadruple-precision floating-point values `a' and `b', one of
  1858. | which is a NaN, and returns the appropriate NaN result. If either `a' or
  1859. | `b' is a signaling NaN, the invalid exception is raised.
  1860. *----------------------------------------------------------------------------*}
  1861. function propagateFloat128NaN( a: float128; b : float128): float128;
  1862. var
  1863. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1864. label
  1865. returnLargerSignificand;
  1866. begin
  1867. aIsNaN := float128_is_nan( a );
  1868. aIsSignalingNaN := float128_is_signaling_nan( a );
  1869. bIsNaN := float128_is_nan( b );
  1870. bIsSignalingNaN := float128_is_signaling_nan( b );
  1871. a.high := a.high or int64( $0000800000000000 );
  1872. b.high := b.high or int64( $0000800000000000 );
  1873. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  1874. float_raise( float_flag_invalid );
  1875. if ( aIsSignalingNaN )<>0 then
  1876. begin
  1877. if ( bIsSignalingNaN )<>0 then
  1878. goto returnLargerSignificand;
  1879. if bIsNaN<>0 then
  1880. result := b
  1881. else
  1882. result := a;
  1883. exit;
  1884. end
  1885. else if ( aIsNaN )<>0 then
  1886. begin
  1887. if ( bIsSignalingNaN or not( bIsNaN) )<>0 then
  1888. begin
  1889. result := a;
  1890. exit;
  1891. end;
  1892. returnLargerSignificand:
  1893. if ( lt128( a.high shl 1, a.low, b.high shl 1, b.low ) )<>0 then
  1894. begin
  1895. result := b;
  1896. exit;
  1897. end;
  1898. if ( lt128( b.high shl 1, b.low, a.high shl 1, a.low ) )<>0 then
  1899. begin
  1900. result := a;
  1901. exit
  1902. end;
  1903. if ( a.high < b.high ) then
  1904. result := a
  1905. else
  1906. result := b;
  1907. exit;
  1908. end
  1909. else
  1910. result:=b;
  1911. end;
  1912. {$ELSE}
  1913. { Big endian code }
  1914. (*----------------------------------------------------------------------------
  1915. | Internal canonical NaN format.
  1916. *----------------------------------------------------------------------------*)
  1917. type
  1918. commonNANT = packed record
  1919. sign : flag;
  1920. high, low : bits32;
  1921. end;
  1922. (*----------------------------------------------------------------------------
  1923. | The pattern for a default generated single-precision NaN.
  1924. *----------------------------------------------------------------------------*)
  1925. const float32_default_nan = $7FFFFFFF;
  1926. (*----------------------------------------------------------------------------
  1927. | Returns 1 if the single-precision floating-point value `a' is a NaN;
  1928. | otherwise returns 0.
  1929. *----------------------------------------------------------------------------*)
  1930. function float32_is_nan(a: float32): flag;
  1931. begin
  1932. float32_is_nan := flag( $FF000000 < bits32( a shl 1 ) );
  1933. end;
  1934. (*----------------------------------------------------------------------------
  1935. | Returns 1 if the single-precision floating-point value `a' is a signaling
  1936. | NaN; otherwise returns 0.
  1937. *----------------------------------------------------------------------------*)
  1938. function float32_is_signaling_nan(a: float32):flag;
  1939. begin
  1940. float32_is_signaling_nan := flag( ( ( a shr 22 ) and $1FF ) = $1FE ) and flag( boolean((a and $003FFFFF)<>0) );
  1941. end;
  1942. (*----------------------------------------------------------------------------
  1943. | Returns the result of converting the single-precision floating-point NaN
  1944. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1945. | exception is raised.
  1946. *----------------------------------------------------------------------------*)
  1947. Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT );
  1948. var
  1949. z: commonNANT;
  1950. begin
  1951. if float32_is_signaling_nan(a)<>0 then
  1952. float_raise(float_flag_invalid);
  1953. z.sign := a shr 31;
  1954. z.low := 0;
  1955. z.high := a shl 9;
  1956. c:=z;
  1957. end;
  1958. (*----------------------------------------------------------------------------
  1959. | Returns the result of converting the canonical NaN `a' to the single-
  1960. | precision floating-point format.
  1961. *----------------------------------------------------------------------------*)
  1962. function CommonNanToFloat32(a : CommonNaNT): float32;
  1963. begin
  1964. CommonNanToFloat32:= ( ( bits32( a.sign )) shl 31 ) OR $7FC00000 OR ( a.high shr 9 );
  1965. end;
  1966. (*----------------------------------------------------------------------------
  1967. | Takes two single-precision floating-point values `a' and `b', one of which
  1968. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1969. | signaling NaN, the invalid exception is raised.
  1970. *----------------------------------------------------------------------------*)
  1971. function propagateFloat32NaN( a: float32 ; b: float32): float32;
  1972. var
  1973. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1974. begin
  1975. aIsNaN := float32_is_nan( a );
  1976. aIsSignalingNaN := float32_is_signaling_nan( a );
  1977. bIsNaN := float32_is_nan( b );
  1978. bIsSignalingNaN := float32_is_signaling_nan( b );
  1979. a := a or $00400000;
  1980. b := b or $00400000;
  1981. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  1982. float_raise( float_flag_invalid );
  1983. if bIsSignalingNaN<>0 then
  1984. propagateFloat32Nan := b
  1985. else if aIsSignalingNan<>0 then
  1986. propagateFloat32Nan := a
  1987. else if bIsNan<>0 then
  1988. propagateFloat32Nan := b
  1989. else
  1990. propagateFloat32Nan := a;
  1991. end;
  1992. (*----------------------------------------------------------------------------
  1993. | The pattern for a default generated double-precision NaN. The `high' and
  1994. | `low' values hold the most- and least-significant bits, respectively.
  1995. *----------------------------------------------------------------------------*)
  1996. const
  1997. float64_default_nan_high = $7FFFFFFF;
  1998. float64_default_nan_low = $FFFFFFFF;
  1999. (*----------------------------------------------------------------------------
  2000. | Returns 1 if the double-precision floating-point value `a' is a NaN;
  2001. | otherwise returns 0.
  2002. *----------------------------------------------------------------------------*)
  2003. function float64_is_nan(a: float64): flag;
  2004. begin
  2005. float64_is_nan := flag (
  2006. ( $FFE00000 <= bits32 ( a.high shl 1 ) )
  2007. and ( (a.low<>0) or (( a.high and $000FFFFF )<>0) ));
  2008. end;
  2009. (*----------------------------------------------------------------------------
  2010. | Returns 1 if the double-precision floating-point value `a' is a signaling
  2011. | NaN; otherwise returns 0.
  2012. *----------------------------------------------------------------------------*)
  2013. function float64_is_signaling_nan( a:float64): flag;
  2014. begin
  2015. float64_is_signaling_nan := flag(
  2016. ( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  2017. and ( (a.low<>0) or ( ( a.high and $0007FFFF )<>0) ));
  2018. end;
  2019. (*----------------------------------------------------------------------------
  2020. | Returns the result of converting the double-precision floating-point NaN
  2021. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  2022. | exception is raised.
  2023. *----------------------------------------------------------------------------*)
  2024. Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
  2025. var
  2026. z : commonNaNT;
  2027. begin
  2028. if ( float64_is_signaling_nan( a )<>0 ) then
  2029. float_raise( float_flag_invalid );
  2030. z.sign := a.high shr 31;
  2031. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  2032. c:=z;
  2033. end;
  2034. (*----------------------------------------------------------------------------
  2035. | Returns the result of converting the canonical NaN `a' to the double-
  2036. | precision floating-point format.
  2037. *----------------------------------------------------------------------------*)
  2038. Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64 );
  2039. var
  2040. z: float64;
  2041. begin
  2042. shift64Right( a.high, a.low, 12, z.high, z.low );
  2043. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  2044. c:=z;
  2045. end;
  2046. (*----------------------------------------------------------------------------
  2047. | Takes two double-precision floating-point values `a' and `b', one of which
  2048. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  2049. | signaling NaN, the invalid exception is raised.
  2050. *----------------------------------------------------------------------------*)
  2051. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  2052. var
  2053. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN : flag;
  2054. begin
  2055. aIsNaN := float64_is_nan( a );
  2056. aIsSignalingNaN := float64_is_signaling_nan( a );
  2057. bIsNaN := float64_is_nan( b );
  2058. bIsSignalingNaN := float64_is_signaling_nan( b );
  2059. a.high := a.high or $00080000;
  2060. b.high := b.high or $00080000;
  2061. if ( (aIsSignalingNaN<>0) or (bIsSignalingNaN<>0) ) then
  2062. float_raise( float_flag_invalid );
  2063. if bIsSignalingNaN<>0 then
  2064. c := b
  2065. else if aIsSignalingNan<>0 then
  2066. c := a
  2067. else if bIsNan<>0 then
  2068. c := b
  2069. else
  2070. c := a;
  2071. end;
  2072. {$ENDIF}
  2073. (****************************************************************************)
  2074. (* END ENDIAN SPECIFIC CODE *)
  2075. (****************************************************************************)
  2076. {*
  2077. -------------------------------------------------------------------------------
  2078. Returns the fraction bits of the single-precision floating-point value `a'.
  2079. -------------------------------------------------------------------------------
  2080. *}
  2081. Function ExtractFloat32Frac(a : Float32) : Bits32;
  2082. Begin
  2083. ExtractFloat32Frac := A AND $007FFFFF;
  2084. End;
  2085. {*
  2086. -------------------------------------------------------------------------------
  2087. Returns the exponent bits of the single-precision floating-point value `a'.
  2088. -------------------------------------------------------------------------------
  2089. *}
  2090. Function extractFloat32Exp( a: float32 ): Int16;
  2091. Begin
  2092. extractFloat32Exp := (a shr 23) AND $FF;
  2093. End;
  2094. {*
  2095. -------------------------------------------------------------------------------
  2096. Returns the sign bit of the single-precision floating-point value `a'.
  2097. -------------------------------------------------------------------------------
  2098. *}
  2099. Function extractFloat32Sign( a: float32 ): Flag;
  2100. Begin
  2101. extractFloat32Sign := a shr 31;
  2102. End;
  2103. {*
  2104. -------------------------------------------------------------------------------
  2105. Normalizes the subnormal single-precision floating-point value represented
  2106. by the denormalized significand `aSig'. The normalized exponent and
  2107. significand are stored at the locations pointed to by `zExpPtr' and
  2108. `zSigPtr', respectively.
  2109. -------------------------------------------------------------------------------
  2110. *}
  2111. Procedure normalizeFloat32Subnormal( aSig : bits32; VAR zExpPtr: Int16; VAR zSigPtr :bits32);
  2112. Var
  2113. ShiftCount : BYTE;
  2114. Begin
  2115. shiftCount := countLeadingZeros32( aSig ) - 8;
  2116. zSigPtr := aSig shl shiftCount;
  2117. zExpPtr := 1 - shiftCount;
  2118. End;
  2119. {*
  2120. -------------------------------------------------------------------------------
  2121. Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
  2122. single-precision floating-point value, returning the result. After being
  2123. shifted into the proper positions, the three fields are simply added
  2124. together to form the result. This means that any integer portion of `zSig'
  2125. will be added into the exponent. Since a properly normalized significand
  2126. will have an integer portion equal to 1, the `zExp' input should be 1 less
  2127. than the desired result exponent whenever `zSig' is a complete, normalized
  2128. significand.
  2129. -------------------------------------------------------------------------------
  2130. *}
  2131. Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32;
  2132. Begin
  2133. packFloat32 := ( ( bits32( zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 23 )
  2134. + zSig;
  2135. End;
  2136. {*
  2137. -------------------------------------------------------------------------------
  2138. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2139. and significand `zSig', and returns the proper single-precision floating-
  2140. point value corresponding to the abstract input. Ordinarily, the abstract
  2141. value is simply rounded and packed into the single-precision format, with
  2142. the inexact exception raised if the abstract input cannot be represented
  2143. exactly. However, if the abstract value is too large, the overflow and
  2144. inexact exceptions are raised and an infinity or maximal finite value is
  2145. returned. If the abstract value is too small, the input value is rounded to
  2146. a subnormal number, and the underflow and inexact exceptions are raised if
  2147. the abstract input cannot be represented exactly as a subnormal single-
  2148. precision floating-point number.
  2149. The input significand `zSig' has its binary point between bits 30
  2150. and 29, which is 7 bits to the left of the usual location. This shifted
  2151. significand must be normalized or smaller. If `zSig' is not normalized,
  2152. `zExp' must be 0; in that case, the result returned is a subnormal number,
  2153. and it must not require rounding. In the usual case that `zSig' is
  2154. normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
  2155. The handling of underflow and overflow follows the IEC/IEEE Standard for
  2156. Binary Floating-Point Arithmetic.
  2157. -------------------------------------------------------------------------------
  2158. *}
  2159. Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : float32;
  2160. Var
  2161. roundingMode : BYTE;
  2162. roundNearestEven : Flag;
  2163. roundIncrement, roundBits : BYTE;
  2164. IsTiny : Flag;
  2165. Begin
  2166. roundingMode := softfloat_rounding_mode;
  2167. if (roundingMode = float_round_nearest_even) then
  2168. Begin
  2169. roundNearestEven := Flag(TRUE);
  2170. end
  2171. else
  2172. roundNearestEven := Flag(FALSE);
  2173. roundIncrement := $40;
  2174. if ( Boolean(roundNearestEven) = FALSE) then
  2175. Begin
  2176. if ( roundingMode = float_round_to_zero ) Then
  2177. Begin
  2178. roundIncrement := 0;
  2179. End
  2180. else
  2181. Begin
  2182. roundIncrement := $7F;
  2183. if ( zSign <> 0 ) then
  2184. Begin
  2185. if roundingMode = float_round_up then roundIncrement := 0;
  2186. End
  2187. else
  2188. Begin
  2189. if roundingMode = float_round_down then roundIncrement := 0;
  2190. End;
  2191. End
  2192. End;
  2193. roundBits := zSig AND $7F;
  2194. if ($FD <= bits16 (zExp) ) then
  2195. Begin
  2196. if (( $FD < zExp ) OR ( zExp = $FD ) AND ( sbits32 ( zSig + roundIncrement ) < 0 ) ) then
  2197. Begin
  2198. float_raise( float_flag_overflow OR float_flag_inexact );
  2199. roundAndPackFloat32:=packFloat32( zSign, $FF, 0 ) - Flag( roundIncrement = 0 );
  2200. exit;
  2201. End;
  2202. if ( zExp < 0 ) then
  2203. Begin
  2204. isTiny :=
  2205. flag(( float_detect_tininess = float_tininess_before_rounding )
  2206. OR ( zExp < -1 )
  2207. OR ( (zSig + roundIncrement) < $80000000 ));
  2208. shift32RightJamming( zSig, - zExp, zSig );
  2209. zExp := 0;
  2210. roundBits := zSig AND $7F;
  2211. if ( (isTiny = flag(TRUE)) and (roundBits<>0) ) then
  2212. float_raise( float_flag_underflow );
  2213. End;
  2214. End;
  2215. if ( roundBits )<> 0 then
  2216. softfloat_exception_flags := float_flag_inexact OR softfloat_exception_flags;
  2217. zSig := ( zSig + roundIncrement ) shr 7;
  2218. zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and roundNearestEven );
  2219. if ( zSig = 0 ) then zExp := 0;
  2220. roundAndPackFloat32 := packFloat32( zSign, zExp, zSig );
  2221. exit;
  2222. End;
  2223. {*
  2224. -------------------------------------------------------------------------------
  2225. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2226. and significand `zSig', and returns the proper single-precision floating-
  2227. point value corresponding to the abstract input. This routine is just like
  2228. `roundAndPackFloat32' except that `zSig' does not have to be normalized.
  2229. Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
  2230. floating-point exponent.
  2231. -------------------------------------------------------------------------------
  2232. *}
  2233. Function normalizeRoundAndPackFloat32( zSign: flag; zExp: int16; zSig:bits32 ): float32;
  2234. Var
  2235. ShiftCount : int8;
  2236. Begin
  2237. shiftCount := countLeadingZeros32( zSig ) - 1;
  2238. normalizeRoundAndPackFloat32 := roundAndPackFloat32( zSign, zExp - shiftCount, zSig shl shiftCount );
  2239. End;
  2240. {*
  2241. -------------------------------------------------------------------------------
  2242. Returns the most-significant 20 fraction bits of the double-precision
  2243. floating-point value `a'.
  2244. -------------------------------------------------------------------------------
  2245. *}
  2246. Function extractFloat64Frac0(a: float64): bits32;
  2247. Begin
  2248. extractFloat64Frac0 := a.high and $000FFFFF;
  2249. End;
  2250. {*
  2251. -------------------------------------------------------------------------------
  2252. Returns the least-significant 32 fraction bits of the double-precision
  2253. floating-point value `a'.
  2254. -------------------------------------------------------------------------------
  2255. *}
  2256. Function extractFloat64Frac1(a: float64): bits32;
  2257. Begin
  2258. extractFloat64Frac1 := a.low;
  2259. End;
  2260. {$define FPC_SYSTEM_HAS_extractFloat64Frac}
  2261. Function extractFloat64Frac(a: float64): bits64;
  2262. Begin
  2263. extractFloat64Frac := bits64(a) and $000FFFFFFFFFFFFF;
  2264. End;
  2265. {*
  2266. -------------------------------------------------------------------------------
  2267. Returns the exponent bits of the double-precision floating-point value `a'.
  2268. -------------------------------------------------------------------------------
  2269. *}
  2270. Function extractFloat64Exp(a: float64): int16;
  2271. Begin
  2272. extractFloat64Exp:= ( a.high shr 20 ) AND $7FF;
  2273. End;
  2274. {*
  2275. -------------------------------------------------------------------------------
  2276. Returns the sign bit of the double-precision floating-point value `a'.
  2277. -------------------------------------------------------------------------------
  2278. *}
  2279. Function extractFloat64Sign(a: float64) : flag;
  2280. Begin
  2281. extractFloat64Sign := a.high shr 31;
  2282. End;
  2283. {*
  2284. -------------------------------------------------------------------------------
  2285. Normalizes the subnormal double-precision floating-point value represented
  2286. by the denormalized significand formed by the concatenation of `aSig0' and
  2287. `aSig1'. The normalized exponent is stored at the location pointed to by
  2288. `zExpPtr'. The most significant 21 bits of the normalized significand are
  2289. stored at the location pointed to by `zSig0Ptr', and the least significant
  2290. 32 bits of the normalized significand are stored at the location pointed to
  2291. by `zSig1Ptr'.
  2292. -------------------------------------------------------------------------------
  2293. *}
  2294. Procedure normalizeFloat64Subnormal(
  2295. aSig0: bits32;
  2296. aSig1: bits32;
  2297. VAR zExpPtr : Int16;
  2298. VAR zSig0Ptr : Bits32;
  2299. VAR zSig1Ptr : Bits32
  2300. );
  2301. Var
  2302. ShiftCount : Int8;
  2303. Begin
  2304. if ( aSig0 = 0 ) then
  2305. Begin
  2306. shiftCount := countLeadingZeros32( aSig1 ) - 11;
  2307. if ( shiftCount < 0 ) then
  2308. Begin
  2309. zSig0Ptr := aSig1 shr ( - shiftCount );
  2310. zSig1Ptr := aSig1 shl ( shiftCount AND 31 );
  2311. End
  2312. else
  2313. Begin
  2314. zSig0Ptr := aSig1 shl shiftCount;
  2315. zSig1Ptr := 0;
  2316. End;
  2317. zExpPtr := - shiftCount - 31;
  2318. End
  2319. else
  2320. Begin
  2321. shiftCount := countLeadingZeros32( aSig0 ) - 11;
  2322. shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
  2323. zExpPtr := 1 - shiftCount;
  2324. End;
  2325. End;
  2326. procedure normalizeFloat64Subnormal(aSig : bits64;var zExpPtr : int16; var zSigPtr : bits64);
  2327. var
  2328. shiftCount : int8;
  2329. begin
  2330. shiftCount := countLeadingZeros64( aSig ) - 11;
  2331. zSigPtr := aSig shl shiftCount;
  2332. zExpPtr := 1 - shiftCount;
  2333. end;
  2334. {*
  2335. -------------------------------------------------------------------------------
  2336. Packs the sign `zSign', the exponent `zExp', and the significand formed by
  2337. the concatenation of `zSig0' and `zSig1' into a double-precision floating-
  2338. point value, returning the result. After being shifted into the proper
  2339. positions, the three fields `zSign', `zExp', and `zSig0' are simply added
  2340. together to form the most significant 32 bits of the result. This means
  2341. that any integer portion of `zSig0' will be added into the exponent. Since
  2342. a properly normalized significand will have an integer portion equal to 1,
  2343. the `zExp' input should be 1 less than the desired result exponent whenever
  2344. `zSig0' and `zSig1' concatenated form a complete, normalized significand.
  2345. -------------------------------------------------------------------------------
  2346. *}
  2347. Procedure
  2348. packFloat64( zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1 : Bits32; VAR c : float64);
  2349. var
  2350. z: Float64;
  2351. Begin
  2352. z.low := zSig1;
  2353. z.high := ( ( bits32 (zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 20 ) + zSig0;
  2354. c := z;
  2355. End;
  2356. {*----------------------------------------------------------------------------
  2357. | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
  2358. | double-precision floating-point value, returning the result. After being
  2359. | shifted into the proper positions, the three fields are simply added
  2360. | together to form the result. This means that any integer portion of `zSig'
  2361. | will be added into the exponent. Since a properly normalized significand
  2362. | will have an integer portion equal to 1, the `zExp' input should be 1 less
  2363. | than the desired result exponent whenever `zSig' is a complete, normalized
  2364. | significand.
  2365. *----------------------------------------------------------------------------*}
  2366. function packFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;inline;
  2367. begin
  2368. result := float64(( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 52 ) + zSig);
  2369. end;
  2370. {*
  2371. -------------------------------------------------------------------------------
  2372. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2373. and extended significand formed by the concatenation of `zSig0', `zSig1',
  2374. and `zSig2', and returns the proper double-precision floating-point value
  2375. corresponding to the abstract input. Ordinarily, the abstract value is
  2376. simply rounded and packed into the double-precision format, with the inexact
  2377. exception raised if the abstract input cannot be represented exactly.
  2378. However, if the abstract value is too large, the overflow and inexact
  2379. exceptions are raised and an infinity or maximal finite value is returned.
  2380. If the abstract value is too small, the input value is rounded to a
  2381. subnormal number, and the underflow and inexact exceptions are raised if the
  2382. abstract input cannot be represented exactly as a subnormal double-precision
  2383. floating-point number.
  2384. The input significand must be normalized or smaller. If the input
  2385. significand is not normalized, `zExp' must be 0; in that case, the result
  2386. returned is a subnormal number, and it must not require rounding. In the
  2387. usual case that the input significand is normalized, `zExp' must be 1 less
  2388. than the ``true'' floating-point exponent. The handling of underflow and
  2389. overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2390. -------------------------------------------------------------------------------
  2391. *}
  2392. Procedure
  2393. roundAndPackFloat64(
  2394. zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1: Bits32; zSig2: Bits32; Var c: Float64 );
  2395. Var
  2396. roundingMode : Int8;
  2397. roundNearestEven, increment, isTiny : Flag;
  2398. Begin
  2399. roundingMode := softfloat_rounding_mode;
  2400. roundNearestEven := flag( roundingMode = float_round_nearest_even );
  2401. increment := flag( sbits32 (zSig2) < 0 );
  2402. if ( roundNearestEven = flag(FALSE) ) then
  2403. Begin
  2404. if ( roundingMode = float_round_to_zero ) then
  2405. increment := 0
  2406. else
  2407. Begin
  2408. if ( zSign )<> 0 then
  2409. Begin
  2410. increment := flag( roundingMode = float_round_down ) and zSig2;
  2411. End
  2412. else
  2413. Begin
  2414. increment := flag( roundingMode = float_round_up ) and zSig2;
  2415. End
  2416. End
  2417. End;
  2418. if ( $7FD <= bits16 (zExp) ) then
  2419. Begin
  2420. if (( $7FD < zExp )
  2421. or (( zExp = $7FD )
  2422. and (eq64( $001FFFFF, $FFFFFFFF, zSig0, zSig1 )<>0)
  2423. and (increment<>0)
  2424. )
  2425. ) then
  2426. Begin
  2427. float_raise( float_flag_overflow OR float_flag_inexact );
  2428. if (( roundingMode = float_round_to_zero )
  2429. or ( (zSign<>0) and ( roundingMode = float_round_up ) )
  2430. or ( (zSign = 0) and ( roundingMode = float_round_down ) )
  2431. ) then
  2432. Begin
  2433. packFloat64( zSign, $7FE, $000FFFFF, $FFFFFFFF, c );
  2434. exit;
  2435. End;
  2436. packFloat64( zSign, $7FF, 0, 0, c );
  2437. exit;
  2438. End;
  2439. if ( zExp < 0 ) then
  2440. Begin
  2441. isTiny :=
  2442. flag( float_detect_tininess = float_tininess_before_rounding )
  2443. or flag( zExp < -1 )
  2444. or flag(increment = 0)
  2445. or flag(lt64( zSig0, zSig1, $001FFFFF, $FFFFFFFF)<>0);
  2446. shift64ExtraRightJamming(
  2447. zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
  2448. zExp := 0;
  2449. if ( isTiny<>0) and (zSig2<>0 ) then float_raise( float_flag_underflow );
  2450. if ( roundNearestEven )<>0 then
  2451. Begin
  2452. increment := flag( sbits32 (zSig2) < 0 );
  2453. End
  2454. else
  2455. Begin
  2456. if ( zSign )<>0 then
  2457. Begin
  2458. increment := flag( roundingMode = float_round_down ) and zSig2;
  2459. End
  2460. else
  2461. Begin
  2462. increment := flag( roundingMode = float_round_up ) and zSig2;
  2463. End
  2464. End;
  2465. End;
  2466. End;
  2467. if ( zSig2 )<>0 then
  2468. softfloat_exception_flags := softfloat_exception_flags OR float_flag_inexact;
  2469. if ( increment )<>0 then
  2470. Begin
  2471. add64( zSig0, zSig1, 0, 1, zSig0, zSig1 );
  2472. zSig1 := zSig1 and not ( bits32(flag( zSig2 + zSig2 = 0 )) and roundNearestEven );
  2473. End
  2474. else
  2475. Begin
  2476. if ( ( zSig0 or zSig1 ) = 0 ) then zExp := 0;
  2477. End;
  2478. packFloat64( zSign, zExp, zSig0, zSig1, c );
  2479. End;
  2480. {*----------------------------------------------------------------------------
  2481. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2482. | and significand `zSig', and returns the proper double-precision floating-
  2483. | point value corresponding to the abstract input. Ordinarily, the abstract
  2484. | value is simply rounded and packed into the double-precision format, with
  2485. | the inexact exception raised if the abstract input cannot be represented
  2486. | exactly. However, if the abstract value is too large, the overflow and
  2487. | inexact exceptions are raised and an infinity or maximal finite value is
  2488. | returned. If the abstract value is too small, the input value is rounded
  2489. | to a subnormal number, and the underflow and inexact exceptions are raised
  2490. | if the abstract input cannot be represented exactly as a subnormal double-
  2491. | precision floating-point number.
  2492. | The input significand `zSig' has its binary point between bits 62
  2493. | and 61, which is 10 bits to the left of the usual location. This shifted
  2494. | significand must be normalized or smaller. If `zSig' is not normalized,
  2495. | `zExp' must be 0; in that case, the result returned is a subnormal number,
  2496. | and it must not require rounding. In the usual case that `zSig' is
  2497. | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
  2498. | The handling of underflow and overflow follows the IEC/IEEE Standard for
  2499. | Binary Floating-Point Arithmetic.
  2500. *----------------------------------------------------------------------------*}
  2501. function roundAndPackFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;
  2502. var
  2503. roundingMode: int8;
  2504. roundNearestEven: flag;
  2505. roundIncrement, roundBits: int16;
  2506. isTiny: flag;
  2507. begin
  2508. roundingMode := softfloat_rounding_mode;
  2509. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  2510. roundIncrement := $200;
  2511. if ( roundNearestEven=0 ) then
  2512. begin
  2513. if ( roundingMode = float_round_to_zero ) then
  2514. begin
  2515. roundIncrement := 0;
  2516. end
  2517. else begin
  2518. roundIncrement := $3FF;
  2519. if ( zSign<>0 ) then
  2520. begin
  2521. if ( roundingMode = float_round_up ) then
  2522. roundIncrement := 0;
  2523. end
  2524. else begin
  2525. if ( roundingMode = float_round_down ) then
  2526. roundIncrement := 0;
  2527. end
  2528. end
  2529. end;
  2530. roundBits := zSig and $3FF;
  2531. if ( $7FD <= bits16(zExp) ) then
  2532. begin
  2533. if ( ( $7FD < zExp )
  2534. or ( ( zExp = $7FD )
  2535. and ( sbits64( zSig + roundIncrement ) < 0 ) )
  2536. ) then
  2537. begin
  2538. float_raise( float_flag_overflow or float_flag_inexact );
  2539. result := float64(qword(packFloat64( zSign, $7FF, 0 )) - ord( roundIncrement = 0 ));
  2540. exit;
  2541. end;
  2542. if ( zExp < 0 ) then
  2543. begin
  2544. isTiny := ord(
  2545. ( float_detect_tininess = float_tininess_before_rounding )
  2546. or ( zExp < -1 )
  2547. or ( (zSig + roundIncrement) < int64( $8000000000000000 ) ) );
  2548. shift64RightJamming( zSig, - zExp, zSig );
  2549. zExp := 0;
  2550. roundBits := zSig and $3FF;
  2551. if ( isTiny and roundBits )<>0 then
  2552. float_raise( float_flag_underflow );
  2553. end
  2554. end;
  2555. if ( roundBits<>0 ) then
  2556. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  2557. zSig := ( zSig + roundIncrement ) shr 10;
  2558. zSig := zSig and not( ord( ( roundBits xor $200 ) = 0 ) and roundNearestEven );
  2559. if ( zSig = 0 ) then
  2560. zExp := 0;
  2561. result:=packFloat64( zSign, zExp, zSig );
  2562. end;
  2563. {*
  2564. -------------------------------------------------------------------------------
  2565. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2566. and significand formed by the concatenation of `zSig0' and `zSig1', and
  2567. returns the proper double-precision floating-point value corresponding
  2568. to the abstract input. This routine is just like `roundAndPackFloat64'
  2569. except that the input significand has fewer bits and does not have to be
  2570. normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
  2571. point exponent.
  2572. -------------------------------------------------------------------------------
  2573. *}
  2574. Procedure
  2575. normalizeRoundAndPackFloat64(
  2576. zSign:flag; zExp:int16; zSig0:bits32; zSig1:bits32; VAR c: float64 );
  2577. Var
  2578. shiftCount : int8;
  2579. zSig2 : bits32;
  2580. Begin
  2581. if ( zSig0 = 0 ) then
  2582. Begin
  2583. zSig0 := zSig1;
  2584. zSig1 := 0;
  2585. zExp := zExp -32;
  2586. End;
  2587. shiftCount := countLeadingZeros32( zSig0 ) - 11;
  2588. if ( 0 <= shiftCount ) then
  2589. Begin
  2590. zSig2 := 0;
  2591. shortShift64Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  2592. End
  2593. else
  2594. Begin
  2595. shift64ExtraRightJamming
  2596. (zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
  2597. End;
  2598. zExp := zExp - shiftCount;
  2599. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, c );
  2600. End;
  2601. {*
  2602. -------------------------------------------------------------------------------
  2603. Returns the result of converting the 32-bit two's complement integer `a' to
  2604. the single-precision floating-point format. The conversion is performed
  2605. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2606. -------------------------------------------------------------------------------
  2607. *}
  2608. Function int32_to_float32( a: int32): float32rec; compilerproc;
  2609. Var
  2610. zSign : Flag;
  2611. Begin
  2612. if ( a = 0 ) then
  2613. Begin
  2614. int32_to_float32.float32 := 0;
  2615. exit;
  2616. End;
  2617. if ( a = sbits32 ($80000000) ) then
  2618. Begin
  2619. int32_to_float32.float32 := packFloat32( 1, $9E, 0 );
  2620. exit;
  2621. end;
  2622. zSign := flag( a < 0 );
  2623. If zSign<>0 then
  2624. a := -a;
  2625. int32_to_float32.float32:=
  2626. normalizeRoundAndPackFloat32( zSign, $9C, a );
  2627. End;
  2628. {*
  2629. -------------------------------------------------------------------------------
  2630. Returns the result of converting the 32-bit two's complement integer `a' to
  2631. the double-precision floating-point format. The conversion is performed
  2632. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2633. -------------------------------------------------------------------------------
  2634. *}
  2635. Function int32_to_float64( a: int32) : float64;{$ifdef fpc} [public,Alias:'INT32_TO_FLOAT64'];compilerproc;{$endif}
  2636. var
  2637. zSign : flag;
  2638. absA : bits32;
  2639. shiftCount : int8;
  2640. zSig0, zSig1 : bits32;
  2641. Begin
  2642. if ( a = 0 ) then
  2643. Begin
  2644. packFloat64( 0, 0, 0, 0, result );
  2645. exit;
  2646. end;
  2647. zSign := flag( a < 0 );
  2648. if ZSign<>0 then
  2649. AbsA := -a
  2650. else
  2651. AbsA := a;
  2652. shiftCount := countLeadingZeros32( absA ) - 11;
  2653. if ( 0 <= shiftCount ) then
  2654. Begin
  2655. zSig0 := absA shl shiftCount;
  2656. zSig1 := 0;
  2657. End
  2658. else
  2659. Begin
  2660. shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );
  2661. End;
  2662. packFloat64( zSign, $412 - shiftCount, zSig0, zSig1, result );
  2663. End;
  2664. {*
  2665. -------------------------------------------------------------------------------
  2666. Returns the result of converting the single-precision floating-point value
  2667. `a' to the 32-bit two's complement integer format. The conversion is
  2668. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2669. Arithmetic---which means in particular that the conversion is rounded
  2670. according to the current rounding mode. If `a' is a NaN, the largest
  2671. positive integer is returned. Otherwise, if the conversion overflows, the
  2672. largest integer with the same sign as `a' is returned.
  2673. -------------------------------------------------------------------------------
  2674. *}
  2675. Function float32_to_int32( a : float32rec) : int32;compilerproc;
  2676. Var
  2677. aSign: flag;
  2678. aExp, shiftCount: int16;
  2679. aSig, aSigExtra: bits32;
  2680. z: int32;
  2681. roundingMode: int8;
  2682. Begin
  2683. aSig := extractFloat32Frac( a.float32 );
  2684. aExp := extractFloat32Exp( a.float32 );
  2685. aSign := extractFloat32Sign( a.float32 );
  2686. shiftCount := aExp - $96;
  2687. if ( 0 <= shiftCount ) then
  2688. Begin
  2689. if ( $9E <= aExp ) then
  2690. Begin
  2691. if ( a.float32 <> $CF000000 ) then
  2692. Begin
  2693. float_raise( float_flag_invalid );
  2694. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  2695. Begin
  2696. float32_to_int32 := $7FFFFFFF;
  2697. exit;
  2698. End;
  2699. End;
  2700. float32_to_int32 := sbits32 ($80000000);
  2701. exit;
  2702. End;
  2703. z := ( aSig or $00800000 ) shl shiftCount;
  2704. if ( aSign<>0 ) then z := - z;
  2705. End
  2706. else
  2707. Begin
  2708. if ( aExp < $7E ) then
  2709. Begin
  2710. aSigExtra := aExp OR aSig;
  2711. z := 0;
  2712. End
  2713. else
  2714. Begin
  2715. aSig := aSig OR $00800000;
  2716. aSigExtra := aSig shl ( shiftCount and 31 );
  2717. z := aSig shr ( - shiftCount );
  2718. End;
  2719. if ( aSigExtra<>0 ) then
  2720. softfloat_exception_flags := softfloat_exception_flags
  2721. or float_flag_inexact;
  2722. roundingMode := softfloat_rounding_mode;
  2723. if ( roundingMode = float_round_nearest_even ) then
  2724. Begin
  2725. if ( sbits32 (aSigExtra) < 0 ) then
  2726. Begin
  2727. Inc(z);
  2728. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  2729. z := z and not 1;
  2730. End;
  2731. if ( aSign<>0 ) then
  2732. z := - z;
  2733. End
  2734. else
  2735. Begin
  2736. aSigExtra := flag( aSigExtra <> 0 );
  2737. if ( aSign<>0 ) then
  2738. Begin
  2739. z := z + (flag( roundingMode = float_round_down ) and aSigExtra);
  2740. z := - z;
  2741. End
  2742. else
  2743. Begin
  2744. z := z + (flag( roundingMode = float_round_up ) and aSigExtra);
  2745. End
  2746. End;
  2747. End;
  2748. float32_to_int32 := z;
  2749. End;
  2750. {*
  2751. -------------------------------------------------------------------------------
  2752. Returns the result of converting the single-precision floating-point value
  2753. `a' to the 32-bit two's complement integer format. The conversion is
  2754. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2755. Arithmetic, except that the conversion is always rounded toward zero.
  2756. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  2757. the conversion overflows, the largest integer with the same sign as `a' is
  2758. returned.
  2759. -------------------------------------------------------------------------------
  2760. *}
  2761. Function float32_to_int32_round_to_zero( a: Float32rec ): int32;compilerproc;
  2762. Var
  2763. aSign : flag;
  2764. aExp, shiftCount : int16;
  2765. aSig : bits32;
  2766. z : int32;
  2767. Begin
  2768. aSig := extractFloat32Frac( a.float32 );
  2769. aExp := extractFloat32Exp( a.float32 );
  2770. aSign := extractFloat32Sign( a.float32 );
  2771. shiftCount := aExp - $9E;
  2772. if ( 0 <= shiftCount ) then
  2773. Begin
  2774. if ( a.float32 <> $CF000000 ) then
  2775. Begin
  2776. float_raise( float_flag_invalid );
  2777. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  2778. Begin
  2779. float32_to_int32_round_to_zero := $7FFFFFFF;
  2780. exit;
  2781. end;
  2782. End;
  2783. float32_to_int32_round_to_zero:= sbits32 ($80000000);
  2784. exit;
  2785. End
  2786. else
  2787. if ( aExp <= $7E ) then
  2788. Begin
  2789. if ( aExp or aSig )<>0 then
  2790. softfloat_exception_flags :=
  2791. softfloat_exception_flags or float_flag_inexact;
  2792. float32_to_int32_round_to_zero := 0;
  2793. exit;
  2794. End;
  2795. aSig := ( aSig or $00800000 ) shl 8;
  2796. z := aSig shr ( - shiftCount );
  2797. if ( bits32 ( aSig shl ( shiftCount and 31 ) )<> 0 ) then
  2798. Begin
  2799. softfloat_exception_flags :=
  2800. softfloat_exception_flags or float_flag_inexact;
  2801. End;
  2802. if ( aSign<>0 ) then z := - z;
  2803. float32_to_int32_round_to_zero := z;
  2804. End;
  2805. {*
  2806. -------------------------------------------------------------------------------
  2807. Returns the result of converting the single-precision floating-point value
  2808. `a' to the double-precision floating-point format. The conversion is
  2809. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2810. Arithmetic.
  2811. -------------------------------------------------------------------------------
  2812. *}
  2813. Function float32_to_float64( a : float32rec) : Float64;compilerproc;
  2814. Var
  2815. aSign : flag;
  2816. aExp : int16;
  2817. aSig, zSig0, zSig1: bits32;
  2818. tmp : CommonNanT;
  2819. Begin
  2820. aSig := extractFloat32Frac( a.float32 );
  2821. aExp := extractFloat32Exp( a.float32 );
  2822. aSign := extractFloat32Sign( a.float32 );
  2823. if ( aExp = $FF ) then
  2824. Begin
  2825. if ( aSig<>0 ) then
  2826. Begin
  2827. float32ToCommonNaN(a.float32, tmp);
  2828. commonNaNToFloat64(tmp , result);
  2829. exit;
  2830. End;
  2831. packFloat64( aSign, $7FF, 0, 0, result);
  2832. exit;
  2833. End;
  2834. if ( aExp = 0 ) then
  2835. Begin
  2836. if ( aSig = 0 ) then
  2837. Begin
  2838. packFloat64( aSign, 0, 0, 0, result );
  2839. exit;
  2840. end;
  2841. normalizeFloat32Subnormal( aSig, aExp, aSig );
  2842. Dec(aExp);
  2843. End;
  2844. shift64Right( aSig, 0, 3, zSig0, zSig1 );
  2845. packFloat64( aSign, aExp + $380, zSig0, zSig1, result );
  2846. End;
  2847. {*
  2848. -------------------------------------------------------------------------------
  2849. Rounds the single-precision floating-point value `a' to an integer,
  2850. and returns the result as a single-precision floating-point value. The
  2851. operation is performed according to the IEC/IEEE Standard for Binary
  2852. Floating-Point Arithmetic.
  2853. -------------------------------------------------------------------------------
  2854. *}
  2855. Function float32_round_to_int( a: float32rec): float32rec;compilerproc;
  2856. Var
  2857. aSign: flag;
  2858. aExp: int16;
  2859. lastBitMask, roundBitsMask: bits32;
  2860. roundingMode: int8;
  2861. z: float32;
  2862. Begin
  2863. aExp := extractFloat32Exp( a.float32 );
  2864. if ( $96 <= aExp ) then
  2865. Begin
  2866. if ( ( aExp = $FF ) and (extractFloat32Frac( a.float32 )<>0) ) then
  2867. Begin
  2868. float32_round_to_int.float32 := propagateFloat32NaN( a.float32, a.float32 );
  2869. exit;
  2870. End;
  2871. float32_round_to_int:=a;
  2872. exit;
  2873. End;
  2874. if ( aExp <= $7E ) then
  2875. Begin
  2876. if ( bits32 ( a.float32 shl 1 ) = 0 ) then
  2877. Begin
  2878. float32_round_to_int:=a;
  2879. exit;
  2880. end;
  2881. softfloat_exception_flags
  2882. := softfloat_exception_flags OR float_flag_inexact;
  2883. aSign := extractFloat32Sign( a.float32 );
  2884. case ( softfloat_rounding_mode ) of
  2885. float_round_nearest_even:
  2886. Begin
  2887. if ( ( aExp = $7E ) and (extractFloat32Frac( a.float32 )<>0) ) then
  2888. Begin
  2889. float32_round_to_int.float32 := packFloat32( aSign, $7F, 0 );
  2890. exit;
  2891. End;
  2892. End;
  2893. float_round_down:
  2894. Begin
  2895. if aSign <> 0 then
  2896. float32_round_to_int.float32 := $BF800000
  2897. else
  2898. float32_round_to_int.float32 := 0;
  2899. exit;
  2900. End;
  2901. float_round_up:
  2902. Begin
  2903. if aSign <> 0 then
  2904. float32_round_to_int.float32 := $80000000
  2905. else
  2906. float32_round_to_int.float32 := $3F800000;
  2907. exit;
  2908. End;
  2909. end;
  2910. float32_round_to_int.float32 := packFloat32( aSign, 0, 0 );
  2911. End;
  2912. lastBitMask := 1;
  2913. {_____________________________!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  2914. lastBitMask := lastBitMask shl ($96 - aExp);
  2915. roundBitsMask := lastBitMask - 1;
  2916. z := a.float32;
  2917. roundingMode := softfloat_rounding_mode;
  2918. if ( roundingMode = float_round_nearest_even ) then
  2919. Begin
  2920. z := z + (lastBitMask shr 1);
  2921. if ( ( z and roundBitsMask ) = 0 ) then
  2922. z := z and not lastBitMask;
  2923. End
  2924. else if ( roundingMode <> float_round_to_zero ) then
  2925. Begin
  2926. if ( (extractFloat32Sign( z ) xor flag(roundingMode = float_round_up ))<>0 ) then
  2927. Begin
  2928. z := z + roundBitsMask;
  2929. End;
  2930. End;
  2931. z := z and not roundBitsMask;
  2932. if ( z <> a.float32 ) then
  2933. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  2934. float32_round_to_int.float32 := z;
  2935. End;
  2936. {*
  2937. -------------------------------------------------------------------------------
  2938. Returns the result of adding the absolute values of the single-precision
  2939. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  2940. before being returned. `zSign' is ignored if the result is a NaN.
  2941. The addition is performed according to the IEC/IEEE Standard for Binary
  2942. Floating-Point Arithmetic.
  2943. -------------------------------------------------------------------------------
  2944. *}
  2945. Function addFloat32Sigs( a:float32; b: float32; zSign:flag ): float32;
  2946. Var
  2947. aExp, bExp, zExp: int16;
  2948. aSig, bSig, zSig: bits32;
  2949. expDiff: int16;
  2950. label roundAndPack;
  2951. Begin
  2952. aSig:=extractFloat32Frac( a );
  2953. aExp:=extractFloat32Exp( a );
  2954. bSig:=extractFloat32Frac( b );
  2955. bExp := extractFloat32Exp( b );
  2956. expDiff := aExp - bExp;
  2957. aSig := aSig shl 6;
  2958. bSig := bSig shl 6;
  2959. if ( 0 < expDiff ) then
  2960. Begin
  2961. if ( aExp = $FF ) then
  2962. Begin
  2963. if ( aSig <> 0) then
  2964. Begin
  2965. addFloat32Sigs := propagateFloat32NaN( a, b );
  2966. exit;
  2967. End;
  2968. addFloat32Sigs := a;
  2969. exit;
  2970. End;
  2971. if ( bExp = 0 ) then
  2972. Begin
  2973. Dec(expDiff);
  2974. End
  2975. else
  2976. Begin
  2977. bSig := bSig or $20000000;
  2978. End;
  2979. shift32RightJamming( bSig, expDiff, bSig );
  2980. zExp := aExp;
  2981. End
  2982. else
  2983. If ( expDiff < 0 ) then
  2984. Begin
  2985. if ( bExp = $FF ) then
  2986. Begin
  2987. if ( bSig<>0 ) then
  2988. Begin
  2989. addFloat32Sigs := propagateFloat32NaN( a, b );
  2990. exit;
  2991. end;
  2992. addFloat32Sigs := packFloat32( zSign, $FF, 0 );
  2993. exit;
  2994. End;
  2995. if ( aExp = 0 ) then
  2996. Begin
  2997. Inc(expDiff);
  2998. End
  2999. else
  3000. Begin
  3001. aSig := aSig OR $20000000;
  3002. End;
  3003. shift32RightJamming( aSig, - expDiff, aSig );
  3004. zExp := bExp;
  3005. End
  3006. else
  3007. Begin
  3008. if ( aExp = $FF ) then
  3009. Begin
  3010. if ( aSig OR bSig )<> 0 then
  3011. Begin
  3012. addFloat32Sigs := propagateFloat32NaN( a, b );
  3013. exit;
  3014. end;
  3015. addFloat32Sigs := a;
  3016. exit;
  3017. End;
  3018. if ( aExp = 0 ) then
  3019. Begin
  3020. addFloat32Sigs := packFloat32( zSign, 0, ( aSig + bSig ) shr 6 );
  3021. exit;
  3022. end;
  3023. zSig := $40000000 + aSig + bSig;
  3024. zExp := aExp;
  3025. goto roundAndPack;
  3026. End;
  3027. aSig := aSig OR $20000000;
  3028. zSig := ( aSig + bSig ) shl 1;
  3029. Dec(zExp);
  3030. if ( sbits32 (zSig) < 0 ) then
  3031. Begin
  3032. zSig := aSig + bSig;
  3033. Inc(zExp);
  3034. End;
  3035. roundAndPack:
  3036. addFloat32Sigs := roundAndPackFloat32( zSign, zExp, zSig );
  3037. End;
  3038. {*
  3039. -------------------------------------------------------------------------------
  3040. Returns the result of subtracting the absolute values of the single-
  3041. precision floating-point values `a' and `b'. If `zSign' is 1, the
  3042. difference is negated before being returned. `zSign' is ignored if the
  3043. result is a NaN. The subtraction is performed according to the IEC/IEEE
  3044. Standard for Binary Floating-Point Arithmetic.
  3045. -------------------------------------------------------------------------------
  3046. *}
  3047. Function subFloat32Sigs( a:float32; b:float32; zSign:flag ): float32;
  3048. Var
  3049. aExp, bExp, zExp: int16;
  3050. aSig, bSig, zSig: bits32;
  3051. expDiff : int16;
  3052. label aExpBigger;
  3053. label bExpBigger;
  3054. label aBigger;
  3055. label bBigger;
  3056. label normalizeRoundAndPack;
  3057. Begin
  3058. aSig := extractFloat32Frac( a );
  3059. aExp := extractFloat32Exp( a );
  3060. bSig := extractFloat32Frac( b );
  3061. bExp := extractFloat32Exp( b );
  3062. expDiff := aExp - bExp;
  3063. aSig := aSig shl 7;
  3064. bSig := bSig shl 7;
  3065. if ( 0 < expDiff ) then goto aExpBigger;
  3066. if ( expDiff < 0 ) then goto bExpBigger;
  3067. if ( aExp = $FF ) then
  3068. Begin
  3069. if ( aSig OR bSig )<> 0 then
  3070. Begin
  3071. subFloat32Sigs := propagateFloat32NaN( a, b );
  3072. exit;
  3073. End;
  3074. float_raise( float_flag_invalid );
  3075. subFloat32Sigs := float32_default_nan;
  3076. exit;
  3077. End;
  3078. if ( aExp = 0 ) then
  3079. Begin
  3080. aExp := 1;
  3081. bExp := 1;
  3082. End;
  3083. if ( bSig < aSig ) Then goto aBigger;
  3084. if ( aSig < bSig ) Then goto bBigger;
  3085. subFloat32Sigs := packFloat32( flag(softfloat_rounding_mode = float_round_down), 0, 0 );
  3086. exit;
  3087. bExpBigger:
  3088. if ( bExp = $FF ) then
  3089. Begin
  3090. if ( bSig<>0 ) then
  3091. Begin
  3092. subFloat32Sigs := propagateFloat32NaN( a, b );
  3093. exit;
  3094. End;
  3095. subFloat32Sigs := packFloat32( zSign XOR 1, $FF, 0 );
  3096. exit;
  3097. End;
  3098. if ( aExp = 0 ) then
  3099. Begin
  3100. Inc(expDiff);
  3101. End
  3102. else
  3103. Begin
  3104. aSig := aSig OR $40000000;
  3105. End;
  3106. shift32RightJamming( aSig, - expDiff, aSig );
  3107. bSig := bSig OR $40000000;
  3108. bBigger:
  3109. zSig := bSig - aSig;
  3110. zExp := bExp;
  3111. zSign := zSign xor 1;
  3112. goto normalizeRoundAndPack;
  3113. aExpBigger:
  3114. if ( aExp = $FF ) then
  3115. Begin
  3116. if ( aSig <> 0) then
  3117. Begin
  3118. subFloat32Sigs := propagateFloat32NaN( a, b );
  3119. exit;
  3120. End;
  3121. subFloat32Sigs := a;
  3122. exit;
  3123. End;
  3124. if ( bExp = 0 ) then
  3125. Begin
  3126. Dec(expDiff);
  3127. End
  3128. else
  3129. Begin
  3130. bSig := bSig OR $40000000;
  3131. End;
  3132. shift32RightJamming( bSig, expDiff, bSig );
  3133. aSig := aSig OR $40000000;
  3134. aBigger:
  3135. zSig := aSig - bSig;
  3136. zExp := aExp;
  3137. normalizeRoundAndPack:
  3138. Dec(zExp);
  3139. subFloat32Sigs := normalizeRoundAndPackFloat32( zSign, zExp, zSig );
  3140. End;
  3141. {*
  3142. -------------------------------------------------------------------------------
  3143. Returns the result of adding the single-precision floating-point values `a'
  3144. and `b'. The operation is performed according to the IEC/IEEE Standard for
  3145. Binary Floating-Point Arithmetic.
  3146. -------------------------------------------------------------------------------
  3147. *}
  3148. Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
  3149. Var
  3150. aSign, bSign: Flag;
  3151. Begin
  3152. aSign := extractFloat32Sign( a.float32 );
  3153. bSign := extractFloat32Sign( b.float32 );
  3154. if ( aSign = bSign ) then
  3155. Begin
  3156. float32_add.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
  3157. End
  3158. else
  3159. Begin
  3160. float32_add.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
  3161. End;
  3162. End;
  3163. {*
  3164. -------------------------------------------------------------------------------
  3165. Returns the result of subtracting the single-precision floating-point values
  3166. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3167. for Binary Floating-Point Arithmetic.
  3168. -------------------------------------------------------------------------------
  3169. *}
  3170. Function float32_sub( a: float32rec ; b:float32rec ): float32rec;compilerproc;
  3171. Var
  3172. aSign, bSign: flag;
  3173. Begin
  3174. aSign := extractFloat32Sign( a.float32 );
  3175. bSign := extractFloat32Sign( b.float32 );
  3176. if ( aSign = bSign ) then
  3177. Begin
  3178. float32_sub.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
  3179. End
  3180. else
  3181. Begin
  3182. float32_sub.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
  3183. End;
  3184. End;
  3185. {*
  3186. -------------------------------------------------------------------------------
  3187. Returns the result of multiplying the single-precision floating-point values
  3188. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3189. for Binary Floating-Point Arithmetic.
  3190. -------------------------------------------------------------------------------
  3191. *}
  3192. Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
  3193. Var
  3194. aSign, bSign, zSign: flag;
  3195. aExp, bExp, zExp : int16;
  3196. aSig, bSig, zSig0, zSig1: bits32;
  3197. Begin
  3198. aSig := extractFloat32Frac( a.float32 );
  3199. aExp := extractFloat32Exp( a.float32 );
  3200. aSign := extractFloat32Sign( a.float32 );
  3201. bSig := extractFloat32Frac( b.float32 );
  3202. bExp := extractFloat32Exp( b.float32 );
  3203. bSign := extractFloat32Sign( b.float32 );
  3204. zSign := aSign xor bSign;
  3205. if ( aExp = $FF ) then
  3206. Begin
  3207. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig<>0) ) ) then
  3208. Begin
  3209. float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3210. End;
  3211. if ( ( bExp OR bSig ) = 0 ) then
  3212. Begin
  3213. float_raise( float_flag_invalid );
  3214. float32_mul.float32 := float32_default_nan;
  3215. exit;
  3216. End;
  3217. float32_mul.float32 := packFloat32( zSign, $FF, 0 );
  3218. exit;
  3219. End;
  3220. if ( bExp = $FF ) then
  3221. Begin
  3222. if ( bSig <> 0 ) then
  3223. Begin
  3224. float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3225. exit;
  3226. End;
  3227. if ( ( aExp OR aSig ) = 0 ) then
  3228. Begin
  3229. float_raise( float_flag_invalid );
  3230. float32_mul.float32 := float32_default_nan;
  3231. exit;
  3232. End;
  3233. float32_mul.float32 := packFloat32( zSign, $FF, 0 );
  3234. exit;
  3235. End;
  3236. if ( aExp = 0 ) then
  3237. Begin
  3238. if ( aSig = 0 ) then
  3239. Begin
  3240. float32_mul.float32 := packFloat32( zSign, 0, 0 );
  3241. exit;
  3242. End;
  3243. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3244. End;
  3245. if ( bExp = 0 ) then
  3246. Begin
  3247. if ( bSig = 0 ) then
  3248. Begin
  3249. float32_mul.float32 := packFloat32( zSign, 0, 0 );
  3250. exit;
  3251. End;
  3252. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3253. End;
  3254. zExp := aExp + bExp - $7F;
  3255. aSig := ( aSig OR $00800000 ) shl 7;
  3256. bSig := ( bSig OR $00800000 ) shl 8;
  3257. mul32To64( aSig, bSig, zSig0, zSig1 );
  3258. zSig0 := zSig0 OR bits32( zSig1 <> 0 );
  3259. if ( 0 <= sbits32 ( zSig0 shl 1 ) ) then
  3260. Begin
  3261. zSig0 := zSig0 shl 1;
  3262. Dec(zExp);
  3263. End;
  3264. float32_mul.float32 := roundAndPackFloat32( zSign, zExp, zSig0 );
  3265. End;
  3266. {*
  3267. -------------------------------------------------------------------------------
  3268. Returns the result of dividing the single-precision floating-point value `a'
  3269. by the corresponding value `b'. The operation is performed according to the
  3270. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3271. -------------------------------------------------------------------------------
  3272. *}
  3273. Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
  3274. Var
  3275. aSign, bSign, zSign: flag;
  3276. aExp, bExp, zExp: int16;
  3277. aSig, bSig, zSig, rem0, rem1, term0, term1: bits32;
  3278. Begin
  3279. aSig := extractFloat32Frac( a.float32 );
  3280. aExp := extractFloat32Exp( a.float32 );
  3281. aSign := extractFloat32Sign( a.float32 );
  3282. bSig := extractFloat32Frac( b.float32 );
  3283. bExp := extractFloat32Exp( b.float32 );
  3284. bSign := extractFloat32Sign( b.float32 );
  3285. zSign := aSign xor bSign;
  3286. if ( aExp = $FF ) then
  3287. Begin
  3288. if ( aSig <> 0 ) then
  3289. Begin
  3290. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3291. exit;
  3292. End;
  3293. if ( bExp = $FF ) then
  3294. Begin
  3295. if ( bSig <> 0) then
  3296. Begin
  3297. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3298. End;
  3299. float_raise( float_flag_invalid );
  3300. float32_div.float32 := float32_default_nan;
  3301. exit;
  3302. End;
  3303. float32_div.float32 := packFloat32( zSign, $FF, 0 );
  3304. exit;
  3305. End;
  3306. if ( bExp = $FF ) then
  3307. Begin
  3308. if ( bSig <> 0) then
  3309. Begin
  3310. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3311. exit;
  3312. End;
  3313. float32_div.float32 := packFloat32( zSign, 0, 0 );
  3314. exit;
  3315. End;
  3316. if ( bExp = 0 ) Then
  3317. Begin
  3318. if ( bSig = 0 ) Then
  3319. Begin
  3320. if ( ( aExp OR aSig ) = 0 ) then
  3321. Begin
  3322. float_raise( float_flag_invalid );
  3323. float32_div.float32 := float32_default_nan;
  3324. exit;
  3325. End;
  3326. float_raise( float_flag_divbyzero );
  3327. float32_div.float32 := packFloat32( zSign, $FF, 0 );
  3328. exit;
  3329. End;
  3330. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3331. End;
  3332. if ( aExp = 0 ) Then
  3333. Begin
  3334. if ( aSig = 0 ) Then
  3335. Begin
  3336. float32_div.float32 := packFloat32( zSign, 0, 0 );
  3337. exit;
  3338. End;
  3339. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3340. End;
  3341. zExp := aExp - bExp + $7D;
  3342. aSig := ( aSig OR $00800000 ) shl 7;
  3343. bSig := ( bSig OR $00800000 ) shl 8;
  3344. if ( bSig <= ( aSig + aSig ) ) then
  3345. Begin
  3346. aSig := aSig shr 1;
  3347. Inc(zExp);
  3348. End;
  3349. zSig := estimateDiv64To32( aSig, 0, bSig );
  3350. if ( ( zSig and $3F ) <= 2 ) then
  3351. Begin
  3352. mul32To64( bSig, zSig, term0, term1 );
  3353. sub64( aSig, 0, term0, term1, rem0, rem1 );
  3354. while ( sbits32 (rem0) < 0 ) do
  3355. Begin
  3356. Dec(zSig);
  3357. add64( rem0, rem1, 0, bSig, rem0, rem1 );
  3358. End;
  3359. zSig := zSig or bits32( rem1 <> 0 );
  3360. End;
  3361. float32_div.float32 := roundAndPackFloat32( zSign, zExp, zSig );
  3362. End;
  3363. {*
  3364. -------------------------------------------------------------------------------
  3365. Returns the remainder of the single-precision floating-point value `a'
  3366. with respect to the corresponding value `b'. The operation is performed
  3367. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3368. -------------------------------------------------------------------------------
  3369. *}
  3370. Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
  3371. Var
  3372. aSign, bSign, zSign: flag;
  3373. aExp, bExp, expDiff: int16;
  3374. aSig, bSig, q, allZero, alternateASig: bits32;
  3375. sigMean: sbits32;
  3376. Begin
  3377. aSig := extractFloat32Frac( a.float32 );
  3378. aExp := extractFloat32Exp( a.float32 );
  3379. aSign := extractFloat32Sign( a.float32 );
  3380. bSig := extractFloat32Frac( b.float32 );
  3381. bExp := extractFloat32Exp( b.float32 );
  3382. bSign := extractFloat32Sign( b.float32 );
  3383. if ( aExp = $FF ) then
  3384. Begin
  3385. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig <>0)) ) then
  3386. Begin
  3387. float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3388. exit;
  3389. End;
  3390. float_raise( float_flag_invalid );
  3391. float32_rem.float32 := float32_default_nan;
  3392. exit;
  3393. End;
  3394. if ( bExp = $FF ) then
  3395. Begin
  3396. if ( bSig <> 0 ) then
  3397. Begin
  3398. float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3399. exit;
  3400. End;
  3401. float32_rem := a;
  3402. exit;
  3403. End;
  3404. if ( bExp = 0 ) then
  3405. Begin
  3406. if ( bSig = 0 ) then
  3407. Begin
  3408. float_raise( float_flag_invalid );
  3409. float32_rem.float32 := float32_default_nan;
  3410. exit;
  3411. End;
  3412. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3413. End;
  3414. if ( aExp = 0 ) then
  3415. Begin
  3416. if ( aSig = 0 ) then
  3417. Begin
  3418. float32_rem := a;
  3419. exit;
  3420. End;
  3421. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3422. End;
  3423. expDiff := aExp - bExp;
  3424. aSig := ( aSig OR $00800000 ) shl 8;
  3425. bSig := ( bSig OR $00800000 ) shl 8;
  3426. if ( expDiff < 0 ) then
  3427. Begin
  3428. if ( expDiff < -1 ) then
  3429. Begin
  3430. float32_rem := a;
  3431. exit;
  3432. End;
  3433. aSig := aSig shr 1;
  3434. End;
  3435. q := bits32( bSig <= aSig );
  3436. if ( q <> 0) then
  3437. aSig := aSig - bSig;
  3438. expDiff := expDiff - 32;
  3439. while ( 0 < expDiff ) do
  3440. Begin
  3441. q := estimateDiv64To32( aSig, 0, bSig );
  3442. if (2 < q) then
  3443. q := q - 2
  3444. else
  3445. q := 0;
  3446. aSig := - ( ( bSig shr 2 ) * q );
  3447. expDiff := expDiff - 30;
  3448. End;
  3449. expDiff := expDiff + 32;
  3450. if ( 0 < expDiff ) then
  3451. Begin
  3452. q := estimateDiv64To32( aSig, 0, bSig );
  3453. if (2 < q) then
  3454. q := q - 2
  3455. else
  3456. q := 0;
  3457. q := q shr (32 - expDiff);
  3458. bSig := bSig shr 2;
  3459. aSig := ( ( aSig shr 1 ) shl ( expDiff - 1 ) ) - bSig * q;
  3460. End
  3461. else
  3462. Begin
  3463. aSig := aSig shr 2;
  3464. bSig := bSig shr 2;
  3465. End;
  3466. Repeat
  3467. alternateASig := aSig;
  3468. Inc(q);
  3469. aSig := aSig - bSig;
  3470. Until not ( 0 <= sbits32 (aSig) );
  3471. sigMean := aSig + alternateASig;
  3472. if ( ( sigMean < 0 ) OR ( ( sigMean = 0 ) AND (( q and 1 )<>0) ) ) then
  3473. Begin
  3474. aSig := alternateASig;
  3475. End;
  3476. zSign := flag( sbits32 (aSig) < 0 );
  3477. if ( zSign<>0 ) then
  3478. aSig := - aSig;
  3479. float32_rem.float32 := normalizeRoundAndPackFloat32( aSign xor zSign, bExp, aSig );
  3480. End;
  3481. {*
  3482. -------------------------------------------------------------------------------
  3483. Returns the square root of the single-precision floating-point value `a'.
  3484. The operation is performed according to the IEC/IEEE Standard for Binary
  3485. Floating-Point Arithmetic.
  3486. -------------------------------------------------------------------------------
  3487. *}
  3488. Function float32_sqrt(a: float32rec ): float32rec;compilerproc;
  3489. Var
  3490. aSign : flag;
  3491. aExp, zExp : int16;
  3492. aSig, zSig, rem0, rem1, term0, term1: bits32;
  3493. label roundAndPack;
  3494. Begin
  3495. aSig := extractFloat32Frac( a.float32 );
  3496. aExp := extractFloat32Exp( a.float32 );
  3497. aSign := extractFloat32Sign( a.float32 );
  3498. if ( aExp = $FF ) then
  3499. Begin
  3500. if ( aSig <> 0) then
  3501. Begin
  3502. float32_sqrt.float32 := propagateFloat32NaN( a.float32, 0 );
  3503. exit;
  3504. End;
  3505. if ( aSign = 0) then
  3506. Begin
  3507. float32_sqrt := a;
  3508. exit;
  3509. End;
  3510. float_raise( float_flag_invalid );
  3511. float32_sqrt.float32 := float32_default_nan;
  3512. exit;
  3513. End;
  3514. if ( aSign <> 0) then
  3515. Begin
  3516. if ( ( aExp OR aSig ) = 0 ) then
  3517. Begin
  3518. float32_sqrt := a;
  3519. exit;
  3520. End;
  3521. float_raise( float_flag_invalid );
  3522. float32_sqrt.float32 := float32_default_nan;
  3523. exit;
  3524. End;
  3525. if ( aExp = 0 ) then
  3526. Begin
  3527. if ( aSig = 0 ) then
  3528. Begin
  3529. float32_sqrt.float32 := 0;
  3530. exit;
  3531. End;
  3532. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3533. End;
  3534. zExp := ( ( aExp - $7F ) shr 1 ) + $7E;
  3535. aSig := ( aSig OR $00800000 ) shl 8;
  3536. zSig := estimateSqrt32( aExp, aSig ) + 2;
  3537. if ( ( zSig and $7F ) <= 5 ) then
  3538. Begin
  3539. if ( zSig < 2 ) then
  3540. Begin
  3541. zSig := $7FFFFFFF;
  3542. goto roundAndPack;
  3543. End
  3544. else
  3545. Begin
  3546. aSig := aSig shr (aExp and 1);
  3547. mul32To64( zSig, zSig, term0, term1 );
  3548. sub64( aSig, 0, term0, term1, rem0, rem1 );
  3549. while ( sbits32 (rem0) < 0 ) do
  3550. Begin
  3551. Dec(zSig);
  3552. shortShift64Left( 0, zSig, 1, term0, term1 );
  3553. term1 := term1 or 1;
  3554. add64( rem0, rem1, term0, term1, rem0, rem1 );
  3555. End;
  3556. zSig := zSig OR bits32( ( rem0 OR rem1 ) <> 0 );
  3557. End;
  3558. End;
  3559. shift32RightJamming( zSig, 1, zSig );
  3560. roundAndPack:
  3561. float32_sqrt.float32 := roundAndPackFloat32( 0, zExp, zSig );
  3562. End;
  3563. {*
  3564. -------------------------------------------------------------------------------
  3565. Returns 1 if the single-precision floating-point value `a' is equal to
  3566. the corresponding value `b', and 0 otherwise. The comparison is performed
  3567. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3568. -------------------------------------------------------------------------------
  3569. *}
  3570. Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
  3571. Begin
  3572. if ((( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 )<>0))
  3573. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 )<>0) )
  3574. ) then
  3575. Begin
  3576. if ( (float32_is_signaling_nan( a.float32 )<>0) OR (float32_is_signaling_nan( b.float32 )<>0) ) then
  3577. Begin
  3578. float_raise( float_flag_invalid );
  3579. End;
  3580. float32_eq := 0;
  3581. exit;
  3582. End;
  3583. float32_eq := flag( a.float32 = b.float32 ) OR flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) = 0 );
  3584. End;
  3585. {*
  3586. -------------------------------------------------------------------------------
  3587. Returns 1 if the single-precision floating-point value `a' is less than
  3588. or equal to the corresponding value `b', and 0 otherwise. The comparison
  3589. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  3590. Arithmetic.
  3591. -------------------------------------------------------------------------------
  3592. *}
  3593. Function float32_le( a: float32rec; b : float32rec ):flag;compilerproc;
  3594. var
  3595. aSign, bSign: flag;
  3596. Begin
  3597. if ( ( ( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 )<>0) )
  3598. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 )<>0) )
  3599. ) then
  3600. Begin
  3601. float_raise( float_flag_invalid );
  3602. float32_le := 0;
  3603. exit;
  3604. End;
  3605. aSign := extractFloat32Sign( a.float32 );
  3606. bSign := extractFloat32Sign( b.float32 );
  3607. if ( aSign <> bSign ) then
  3608. Begin
  3609. float32_le := aSign OR flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) = 0 );
  3610. exit;
  3611. End;
  3612. float32_le := flag(flag( a.float32 = b.float32 ) OR flag( aSign xor flag( a.float32 < b.float32 ) ));
  3613. End;
  3614. {*
  3615. -------------------------------------------------------------------------------
  3616. Returns 1 if the single-precision floating-point value `a' is less than
  3617. the corresponding value `b', and 0 otherwise. The comparison is performed
  3618. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3619. -------------------------------------------------------------------------------
  3620. *}
  3621. Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
  3622. var
  3623. aSign, bSign: flag;
  3624. Begin
  3625. if ( ( ( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 ) <>0))
  3626. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 ) <>0) )
  3627. ) then
  3628. Begin
  3629. float_raise( float_flag_invalid );
  3630. float32_lt :=0;
  3631. exit;
  3632. End;
  3633. aSign := extractFloat32Sign( a.float32 );
  3634. bSign := extractFloat32Sign( b.float32 );
  3635. if ( aSign <> bSign ) then
  3636. Begin
  3637. float32_lt := aSign AND flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) <> 0 );
  3638. exit;
  3639. End;
  3640. float32_lt := flag(flag( a.float32 <> b.float32 ) AND flag( aSign xor flag( a.float32 < b.float32 ) ));
  3641. End;
  3642. {*
  3643. -------------------------------------------------------------------------------
  3644. Returns 1 if the single-precision floating-point value `a' is equal to
  3645. the corresponding value `b', and 0 otherwise. The invalid exception is
  3646. raised if either operand is a NaN. Otherwise, the comparison is performed
  3647. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3648. -------------------------------------------------------------------------------
  3649. *}
  3650. Function float32_eq_signaling( a: float32; b: float32) : flag;
  3651. Begin
  3652. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a ) <> 0))
  3653. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b ) <> 0))
  3654. ) then
  3655. Begin
  3656. float_raise( float_flag_invalid );
  3657. float32_eq_signaling := 0;
  3658. exit;
  3659. End;
  3660. float32_eq_signaling := (flag( a = b ) OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 ));
  3661. End;
  3662. {*
  3663. -------------------------------------------------------------------------------
  3664. Returns 1 if the single-precision floating-point value `a' is less than or
  3665. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  3666. cause an exception. Otherwise, the comparison is performed according to the
  3667. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3668. -------------------------------------------------------------------------------
  3669. *}
  3670. Function float32_le_quiet( a: float32 ; b : float32 ): flag;
  3671. Var
  3672. aSign, bSign: flag;
  3673. aExp, bExp: int16;
  3674. Begin
  3675. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  3676. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  3677. ) then
  3678. Begin
  3679. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  3680. Begin
  3681. float_raise( float_flag_invalid );
  3682. End;
  3683. float32_le_quiet := 0;
  3684. exit;
  3685. End;
  3686. aSign := extractFloat32Sign( a );
  3687. bSign := extractFloat32Sign( b );
  3688. if ( aSign <> bSign ) then
  3689. Begin
  3690. float32_le_quiet := aSign OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 );
  3691. exit;
  3692. End;
  3693. float32_le_quiet := flag(flag( a = b ) OR flag( aSign xor flag( a < b ) ));
  3694. End;
  3695. {*
  3696. -------------------------------------------------------------------------------
  3697. Returns 1 if the single-precision floating-point value `a' is less than
  3698. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  3699. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  3700. Standard for Binary Floating-Point Arithmetic.
  3701. -------------------------------------------------------------------------------
  3702. *}
  3703. Function float32_lt_quiet( a: float32 ; b: float32 ): flag;
  3704. Var
  3705. aSign, bSign: flag;
  3706. Begin
  3707. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  3708. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  3709. ) then
  3710. Begin
  3711. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  3712. Begin
  3713. float_raise( float_flag_invalid );
  3714. End;
  3715. float32_lt_quiet := 0;
  3716. exit;
  3717. End;
  3718. aSign := extractFloat32Sign( a );
  3719. bSign := extractFloat32Sign( b );
  3720. if ( aSign <> bSign ) then
  3721. Begin
  3722. float32_lt_quiet := aSign AND flag( bits32 ( ( a OR b ) shl 1 ) <> 0 );
  3723. exit;
  3724. End;
  3725. float32_lt_quiet := flag(flag( a <> b ) AND ( aSign xor flag( a < b ) ));
  3726. End;
  3727. {*
  3728. -------------------------------------------------------------------------------
  3729. Returns the result of converting the double-precision floating-point value
  3730. `a' to the 32-bit two's complement integer format. The conversion is
  3731. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3732. Arithmetic---which means in particular that the conversion is rounded
  3733. according to the current rounding mode. If `a' is a NaN, the largest
  3734. positive integer is returned. Otherwise, if the conversion overflows, the
  3735. largest integer with the same sign as `a' is returned.
  3736. -------------------------------------------------------------------------------
  3737. *}
  3738. Function float64_to_int32(a: float64): int32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32'];compilerproc;{$endif}
  3739. var
  3740. aSign: flag;
  3741. aExp, shiftCount: int16;
  3742. aSig0, aSig1, absZ, aSigExtra: bits32;
  3743. z: int32;
  3744. roundingMode: int8;
  3745. label invalid;
  3746. Begin
  3747. aSig1 := extractFloat64Frac1( a );
  3748. aSig0 := extractFloat64Frac0( a );
  3749. aExp := extractFloat64Exp( a );
  3750. aSign := extractFloat64Sign( a );
  3751. shiftCount := aExp - $413;
  3752. if ( 0 <= shiftCount ) then
  3753. Begin
  3754. if ( $41E < aExp ) then
  3755. Begin
  3756. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  3757. aSign := 0;
  3758. goto invalid;
  3759. End;
  3760. shortShift64Left(
  3761. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  3762. if ( $80000000 < absZ ) then
  3763. goto invalid;
  3764. End
  3765. else
  3766. Begin
  3767. aSig1 := flag( aSig1 <> 0 );
  3768. if ( aExp < $3FE ) then
  3769. Begin
  3770. aSigExtra := aExp OR aSig0 OR aSig1;
  3771. absZ := 0;
  3772. End
  3773. else
  3774. Begin
  3775. aSig0 := aSig0 OR $00100000;
  3776. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  3777. absZ := aSig0 shr ( - shiftCount );
  3778. End;
  3779. End;
  3780. roundingMode := softfloat_rounding_mode;
  3781. if ( roundingMode = float_round_nearest_even ) then
  3782. Begin
  3783. if ( sbits32(aSigExtra) < 0 ) then
  3784. Begin
  3785. Inc(absZ);
  3786. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  3787. absZ := absZ and not 1;
  3788. End;
  3789. if aSign <> 0 then
  3790. z := - absZ
  3791. else
  3792. z := absZ;
  3793. End
  3794. else
  3795. Begin
  3796. aSigExtra := bits32( aSigExtra <> 0 );
  3797. if ( aSign <> 0) then
  3798. Begin
  3799. z := - ( absZ
  3800. + ( int32( roundingMode = float_round_down ) and aSigExtra ) );
  3801. End
  3802. else
  3803. Begin
  3804. z := absZ + ( int32( roundingMode = float_round_up ) and aSigExtra );
  3805. End
  3806. End;
  3807. if ( (( aSign xor flag( z < 0 ) )<>0) AND (z<>0) ) then
  3808. Begin
  3809. invalid:
  3810. float_raise( float_flag_invalid );
  3811. if (aSign <> 0 ) then
  3812. float64_to_int32 := sbits32 ($80000000)
  3813. else
  3814. float64_to_int32 := $7FFFFFFF;
  3815. exit;
  3816. End;
  3817. if ( aSigExtra <> 0) then
  3818. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  3819. float64_to_int32 := z;
  3820. End;
  3821. {*
  3822. -------------------------------------------------------------------------------
  3823. Returns the result of converting the double-precision floating-point value
  3824. `a' to the 32-bit two's complement integer format. The conversion is
  3825. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3826. Arithmetic, except that the conversion is always rounded toward zero.
  3827. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  3828. the conversion overflows, the largest integer with the same sign as `a' is
  3829. returned.
  3830. -------------------------------------------------------------------------------
  3831. *}
  3832. Function float64_to_int32_round_to_zero(a: float64 ): int32;
  3833. {$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32_ROUND_TO_ZERO'];compilerproc;{$endif}
  3834. Var
  3835. aSign: flag;
  3836. aExp, shiftCount: int16;
  3837. aSig0, aSig1, absZ, aSigExtra: bits32;
  3838. z: int32;
  3839. label invalid;
  3840. Begin
  3841. aSig1 := extractFloat64Frac1( a );
  3842. aSig0 := extractFloat64Frac0( a );
  3843. aExp := extractFloat64Exp( a );
  3844. aSign := extractFloat64Sign( a );
  3845. shiftCount := aExp - $413;
  3846. if ( 0 <= shiftCount ) then
  3847. Begin
  3848. if ( $41E < aExp ) then
  3849. Begin
  3850. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  3851. aSign := 0;
  3852. goto invalid;
  3853. End;
  3854. shortShift64Left(
  3855. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  3856. End
  3857. else
  3858. Begin
  3859. if ( aExp < $3FF ) then
  3860. Begin
  3861. if ( aExp OR aSig0 OR aSig1 )<>0 then
  3862. Begin
  3863. softfloat_exception_flags :=
  3864. softfloat_exception_flags or float_flag_inexact;
  3865. End;
  3866. float64_to_int32_round_to_zero := 0;
  3867. exit;
  3868. End;
  3869. aSig0 := aSig0 or $00100000;
  3870. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  3871. absZ := aSig0 shr ( - shiftCount );
  3872. End;
  3873. if aSign <> 0 then
  3874. z := - absZ
  3875. else
  3876. z := absZ;
  3877. if ( (( aSign xor flag( z < 0 )) <> 0) AND (z<>0) ) then
  3878. Begin
  3879. invalid:
  3880. float_raise( float_flag_invalid );
  3881. if (aSign <> 0) then
  3882. float64_to_int32_round_to_zero := sbits32 ($80000000)
  3883. else
  3884. float64_to_int32_round_to_zero := $7FFFFFFF;
  3885. exit;
  3886. End;
  3887. if ( aSigExtra <> 0) then
  3888. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  3889. float64_to_int32_round_to_zero := z;
  3890. End;
  3891. {*
  3892. -------------------------------------------------------------------------------
  3893. Returns the result of converting the double-precision floating-point value
  3894. `a' to the single-precision floating-point format. The conversion is
  3895. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3896. Arithmetic.
  3897. -------------------------------------------------------------------------------
  3898. *}
  3899. Function float64_to_float32(a: float64 ): float32rec;compilerproc;
  3900. Var
  3901. aSign: flag;
  3902. aExp: int16;
  3903. aSig0, aSig1, zSig: bits32;
  3904. allZero: bits32;
  3905. tmp : CommonNanT;
  3906. Begin
  3907. aSig1 := extractFloat64Frac1( a );
  3908. aSig0 := extractFloat64Frac0( a );
  3909. aExp := extractFloat64Exp( a );
  3910. aSign := extractFloat64Sign( a );
  3911. if ( aExp = $7FF ) then
  3912. Begin
  3913. if ( aSig0 OR aSig1 ) <> 0 then
  3914. Begin
  3915. float64ToCommonNaN( a, tmp );
  3916. float64_to_float32.float32 := commonNaNToFloat32( tmp );
  3917. exit;
  3918. End;
  3919. float64_to_float32.float32 := packFloat32( aSign, $FF, 0 );
  3920. exit;
  3921. End;
  3922. shift64RightJamming( aSig0, aSig1, 22, allZero, zSig );
  3923. if ( aExp <> 0) then
  3924. zSig := zSig OR $40000000;
  3925. float64_to_float32.float32 := roundAndPackFloat32( aSign, aExp - $381, zSig );
  3926. End;
  3927. {*
  3928. -------------------------------------------------------------------------------
  3929. Rounds the double-precision floating-point value `a' to an integer,
  3930. and returns the result as a double-precision floating-point value. The
  3931. operation is performed according to the IEC/IEEE Standard for Binary
  3932. Floating-Point Arithmetic.
  3933. -------------------------------------------------------------------------------
  3934. *}
  3935. function float64_round_to_int(a: float64) : Float64;{$ifdef fpc} [public,Alias:'FLOAT64_ROUND_TO_INT'];compilerproc;{$endif}
  3936. Var
  3937. aSign: flag;
  3938. aExp: int16;
  3939. lastBitMask, roundBitsMask: bits32;
  3940. roundingMode: int8;
  3941. z: float64;
  3942. Begin
  3943. aExp := extractFloat64Exp( a );
  3944. if ( $413 <= aExp ) then
  3945. Begin
  3946. if ( $433 <= aExp ) then
  3947. Begin
  3948. if ( ( aExp = $7FF )
  3949. AND
  3950. (
  3951. ( extractFloat64Frac0( a ) OR extractFloat64Frac1( a )
  3952. ) <>0)
  3953. ) then
  3954. Begin
  3955. propagateFloat64NaN( a, a, result );
  3956. exit;
  3957. End;
  3958. result := a;
  3959. exit;
  3960. End;
  3961. lastBitMask := 1;
  3962. lastBitMask := ( lastBitMask shl ( $432 - aExp ) ) shl 1;
  3963. roundBitsMask := lastBitMask - 1;
  3964. z := a;
  3965. roundingMode := softfloat_rounding_mode;
  3966. if ( roundingMode = float_round_nearest_even ) then
  3967. Begin
  3968. if ( lastBitMask <> 0) then
  3969. Begin
  3970. add64( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
  3971. if ( ( z.low and roundBitsMask ) = 0 ) then
  3972. z.low := z.low and not lastBitMask;
  3973. End
  3974. else
  3975. Begin
  3976. if ( sbits32 (z.low) < 0 ) then
  3977. Begin
  3978. Inc(z.high);
  3979. if ( bits32 ( z.low shl 1 ) = 0 ) then
  3980. z.high := z.high and not 1;
  3981. End;
  3982. End;
  3983. End
  3984. else if ( roundingMode <> float_round_to_zero ) then
  3985. Begin
  3986. if ( extractFloat64Sign( z )
  3987. xor flag( roundingMode = float_round_up ) )<> 0 then
  3988. Begin
  3989. add64( z.high, z.low, 0, roundBitsMask, z.high, z.low );
  3990. End;
  3991. End;
  3992. z.low := z.low and not roundBitsMask;
  3993. End
  3994. else
  3995. Begin
  3996. if ( aExp <= $3FE ) then
  3997. Begin
  3998. if ( ( ( bits32 ( a.high shl 1 ) ) OR a.low ) = 0 ) then
  3999. Begin
  4000. result := a;
  4001. exit;
  4002. End;
  4003. softfloat_exception_flags := softfloat_exception_flags or
  4004. float_flag_inexact;
  4005. aSign := extractFloat64Sign( a );
  4006. case ( softfloat_rounding_mode ) of
  4007. float_round_nearest_even:
  4008. Begin
  4009. if ( ( aExp = $3FE )
  4010. AND ( (extractFloat64Frac0( a ) OR extractFloat64Frac1( a ) )<>0)
  4011. ) then
  4012. Begin
  4013. packFloat64( aSign, $3FF, 0, 0, result );
  4014. exit;
  4015. End;
  4016. End;
  4017. float_round_down:
  4018. Begin
  4019. if aSign<>0 then
  4020. packFloat64( 1, $3FF, 0, 0, result )
  4021. else
  4022. packFloat64( 0, 0, 0, 0, result );
  4023. exit;
  4024. End;
  4025. float_round_up:
  4026. Begin
  4027. if aSign <> 0 then
  4028. packFloat64( 1, 0, 0, 0, result )
  4029. else
  4030. packFloat64( 0, $3FF, 0, 0, result );
  4031. exit;
  4032. End;
  4033. end;
  4034. packFloat64( aSign, 0, 0, 0, result );
  4035. exit;
  4036. End;
  4037. lastBitMask := 1;
  4038. lastBitMask := lastBitMask shl ($413 - aExp);
  4039. roundBitsMask := lastBitMask - 1;
  4040. z.low := 0;
  4041. z.high := a.high;
  4042. roundingMode := softfloat_rounding_mode;
  4043. if ( roundingMode = float_round_nearest_even ) then
  4044. Begin
  4045. z.high := z.high + lastBitMask shr 1;
  4046. if ( ( ( z.high and roundBitsMask ) OR a.low ) = 0 ) then
  4047. Begin
  4048. z.high := z.high and not lastBitMask;
  4049. End;
  4050. End
  4051. else if ( roundingMode <> float_round_to_zero ) then
  4052. Begin
  4053. if ( extractFloat64Sign( z )
  4054. xor flag( roundingMode = float_round_up ) )<> 0 then
  4055. Begin
  4056. z.high := z.high or bits32( a.low <> 0 );
  4057. z.high := z.high + roundBitsMask;
  4058. End;
  4059. End;
  4060. z.high := z.high and not roundBitsMask;
  4061. End;
  4062. if ( ( z.low <> a.low ) OR ( z.high <> a.high ) ) then
  4063. Begin
  4064. softfloat_exception_flags :=
  4065. softfloat_exception_flags or float_flag_inexact;
  4066. End;
  4067. result := z;
  4068. End;
  4069. {*
  4070. -------------------------------------------------------------------------------
  4071. Returns the result of adding the absolute values of the double-precision
  4072. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  4073. before being returned. `zSign' is ignored if the result is a NaN.
  4074. The addition is performed according to the IEC/IEEE Standard for Binary
  4075. Floating-Point Arithmetic.
  4076. -------------------------------------------------------------------------------
  4077. *}
  4078. Procedure addFloat64Sigs( a:float64 ; b: float64 ; zSign:flag; Var out: float64 );
  4079. Var
  4080. aExp, bExp, zExp: int16;
  4081. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  4082. expDiff: int16;
  4083. label shiftRight1;
  4084. label roundAndPack;
  4085. Begin
  4086. aSig1 := extractFloat64Frac1( a );
  4087. aSig0 := extractFloat64Frac0( a );
  4088. aExp := extractFloat64Exp( a );
  4089. bSig1 := extractFloat64Frac1( b );
  4090. bSig0 := extractFloat64Frac0( b );
  4091. bExp := extractFloat64Exp( b );
  4092. expDiff := aExp - bExp;
  4093. if ( 0 < expDiff ) then
  4094. Begin
  4095. if ( aExp = $7FF ) then
  4096. Begin
  4097. if ( aSig0 OR aSig1 ) <> 0 then
  4098. Begin
  4099. propagateFloat64NaN( a, b, out );
  4100. exit;
  4101. end;
  4102. out := a;
  4103. exit;
  4104. End;
  4105. if ( bExp = 0 ) then
  4106. Begin
  4107. Dec(expDiff);
  4108. End
  4109. else
  4110. Begin
  4111. bSig0 := bSig0 or $00100000;
  4112. End;
  4113. shift64ExtraRightJamming(
  4114. bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
  4115. zExp := aExp;
  4116. End
  4117. else if ( expDiff < 0 ) then
  4118. Begin
  4119. if ( bExp = $7FF ) then
  4120. Begin
  4121. if ( bSig0 OR bSig1 ) <> 0 then
  4122. Begin
  4123. propagateFloat64NaN( a, b, out );
  4124. exit;
  4125. End;
  4126. packFloat64( zSign, $7FF, 0, 0, out );
  4127. End;
  4128. if ( aExp = 0 ) then
  4129. Begin
  4130. Inc(expDiff);
  4131. End
  4132. else
  4133. Begin
  4134. aSig0 := aSig0 or $00100000;
  4135. End;
  4136. shift64ExtraRightJamming(
  4137. aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
  4138. zExp := bExp;
  4139. End
  4140. else
  4141. Begin
  4142. if ( aExp = $7FF ) then
  4143. Begin
  4144. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  4145. Begin
  4146. propagateFloat64NaN( a, b, out );
  4147. exit;
  4148. End;
  4149. out := a;
  4150. exit;
  4151. End;
  4152. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4153. if ( aExp = 0 ) then
  4154. Begin
  4155. packFloat64( zSign, 0, zSig0, zSig1, out );
  4156. exit;
  4157. End;
  4158. zSig2 := 0;
  4159. zSig0 := zSig0 or $00200000;
  4160. zExp := aExp;
  4161. goto shiftRight1;
  4162. End;
  4163. aSig0 := aSig0 or $00100000;
  4164. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4165. Dec(zExp);
  4166. if ( zSig0 < $00200000 ) then
  4167. goto roundAndPack;
  4168. Inc(zExp);
  4169. shiftRight1:
  4170. shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  4171. roundAndPack:
  4172. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );
  4173. End;
  4174. {*
  4175. -------------------------------------------------------------------------------
  4176. Returns the result of subtracting the absolute values of the double-
  4177. precision floating-point values `a' and `b'. If `zSign' is 1, the
  4178. difference is negated before being returned. `zSign' is ignored if the
  4179. result is a NaN. The subtraction is performed according to the IEC/IEEE
  4180. Standard for Binary Floating-Point Arithmetic.
  4181. -------------------------------------------------------------------------------
  4182. *}
  4183. Procedure subFloat64Sigs( a:float64; b: float64 ; zSign:flag; Var out: float64 );
  4184. Var
  4185. aExp, bExp, zExp: int16;
  4186. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits32;
  4187. expDiff: int16;
  4188. z: float64;
  4189. label aExpBigger;
  4190. label bExpBigger;
  4191. label aBigger;
  4192. label bBigger;
  4193. label normalizeRoundAndPack;
  4194. Begin
  4195. aSig1 := extractFloat64Frac1( a );
  4196. aSig0 := extractFloat64Frac0( a );
  4197. aExp := extractFloat64Exp( a );
  4198. bSig1 := extractFloat64Frac1( b );
  4199. bSig0 := extractFloat64Frac0( b );
  4200. bExp := extractFloat64Exp( b );
  4201. expDiff := aExp - bExp;
  4202. shortShift64Left( aSig0, aSig1, 10, aSig0, aSig1 );
  4203. shortShift64Left( bSig0, bSig1, 10, bSig0, bSig1 );
  4204. if ( 0 < expDiff ) then goto aExpBigger;
  4205. if ( expDiff < 0 ) then goto bExpBigger;
  4206. if ( aExp = $7FF ) then
  4207. Begin
  4208. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  4209. Begin
  4210. propagateFloat64NaN( a, b, out );
  4211. exit;
  4212. End;
  4213. float_raise( float_flag_invalid );
  4214. z.low := float64_default_nan_low;
  4215. z.high := float64_default_nan_high;
  4216. out := z;
  4217. exit;
  4218. End;
  4219. if ( aExp = 0 ) then
  4220. Begin
  4221. aExp := 1;
  4222. bExp := 1;
  4223. End;
  4224. if ( bSig0 < aSig0 ) then goto aBigger;
  4225. if ( aSig0 < bSig0 ) then goto bBigger;
  4226. if ( bSig1 < aSig1 ) then goto aBigger;
  4227. if ( aSig1 < bSig1 ) then goto bBigger;
  4228. packFloat64( flag(softfloat_rounding_mode = float_round_down), 0, 0, 0 , out);
  4229. exit;
  4230. bExpBigger:
  4231. if ( bExp = $7FF ) then
  4232. Begin
  4233. if ( bSig0 OR bSig1 ) <> 0 then
  4234. Begin
  4235. propagateFloat64NaN( a, b, out );
  4236. exit;
  4237. End;
  4238. packFloat64( zSign xor 1, $7FF, 0, 0, out );
  4239. exit;
  4240. End;
  4241. if ( aExp = 0 ) then
  4242. Begin
  4243. Inc(expDiff);
  4244. End
  4245. else
  4246. Begin
  4247. aSig0 := aSig0 or $40000000;
  4248. End;
  4249. shift64RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  4250. bSig0 := bSig0 or $40000000;
  4251. bBigger:
  4252. sub64( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
  4253. zExp := bExp;
  4254. zSign := zSign xor 1;
  4255. goto normalizeRoundAndPack;
  4256. aExpBigger:
  4257. if ( aExp = $7FF ) then
  4258. Begin
  4259. if ( aSig0 OR aSig1 ) <> 0 then
  4260. Begin
  4261. propagateFloat64NaN( a, b, out );
  4262. exit;
  4263. End;
  4264. out := a;
  4265. exit;
  4266. End;
  4267. if ( bExp = 0 ) then
  4268. Begin
  4269. Dec(expDiff);
  4270. End
  4271. else
  4272. Begin
  4273. bSig0 := bSig0 or $40000000;
  4274. End;
  4275. shift64RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
  4276. aSig0 := aSig0 or $40000000;
  4277. aBigger:
  4278. sub64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4279. zExp := aExp;
  4280. normalizeRoundAndPack:
  4281. Dec(zExp);
  4282. normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1, out );
  4283. End;
  4284. {*
  4285. -------------------------------------------------------------------------------
  4286. Returns the result of adding the double-precision floating-point values `a'
  4287. and `b'. The operation is performed according to the IEC/IEEE Standard for
  4288. Binary Floating-Point Arithmetic.
  4289. -------------------------------------------------------------------------------
  4290. *}
  4291. Function float64_add( a: float64; b : float64) : Float64;
  4292. {$ifdef fpc}[public,Alias:'FLOAT64_ADD'];compilerproc;{$endif}
  4293. Var
  4294. aSign, bSign: flag;
  4295. Begin
  4296. aSign := extractFloat64Sign( a );
  4297. bSign := extractFloat64Sign( b );
  4298. if ( aSign = bSign ) then
  4299. Begin
  4300. addFloat64Sigs( a, b, aSign, result );
  4301. End
  4302. else
  4303. Begin
  4304. subFloat64Sigs( a, b, aSign, result );
  4305. End;
  4306. End;
  4307. {*
  4308. -------------------------------------------------------------------------------
  4309. Returns the result of subtracting the double-precision floating-point values
  4310. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  4311. for Binary Floating-Point Arithmetic.
  4312. -------------------------------------------------------------------------------
  4313. *}
  4314. Function float64_sub(a: float64; b : float64) : Float64;
  4315. {$ifdef fpc}[public,Alias:'FLOAT64_SUB'];compilerproc;{$endif}
  4316. Var
  4317. aSign, bSign: flag;
  4318. Begin
  4319. aSign := extractFloat64Sign( a );
  4320. bSign := extractFloat64Sign( b );
  4321. if ( aSign = bSign ) then
  4322. Begin
  4323. subFloat64Sigs( a, b, aSign, result );
  4324. End
  4325. else
  4326. Begin
  4327. addFloat64Sigs( a, b, aSign, result );
  4328. End;
  4329. End;
  4330. {*
  4331. -------------------------------------------------------------------------------
  4332. Returns the result of multiplying the double-precision floating-point values
  4333. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  4334. for Binary Floating-Point Arithmetic.
  4335. -------------------------------------------------------------------------------
  4336. *}
  4337. Function float64_mul( a: float64; b:float64) : Float64;
  4338. {$ifdef fpc}[public,Alias:'FLOAT64_MUL'];compilerproc;{$endif}
  4339. Var
  4340. aSign, bSign, zSign: flag;
  4341. aExp, bExp, zExp: int16;
  4342. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits32;
  4343. z: float64;
  4344. label invalid;
  4345. Begin
  4346. aSig1 := extractFloat64Frac1( a );
  4347. aSig0 := extractFloat64Frac0( a );
  4348. aExp := extractFloat64Exp( a );
  4349. aSign := extractFloat64Sign( a );
  4350. bSig1 := extractFloat64Frac1( b );
  4351. bSig0 := extractFloat64Frac0( b );
  4352. bExp := extractFloat64Exp( b );
  4353. bSign := extractFloat64Sign( b );
  4354. zSign := aSign xor bSign;
  4355. if ( aExp = $7FF ) then
  4356. Begin
  4357. if ( (( aSig0 OR aSig1 ) <>0)
  4358. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  4359. Begin
  4360. propagateFloat64NaN( a, b, result );
  4361. exit;
  4362. End;
  4363. if ( ( bExp OR bSig0 OR bSig1 ) = 0 ) then goto invalid;
  4364. packFloat64( zSign, $7FF, 0, 0, result );
  4365. exit;
  4366. End;
  4367. if ( bExp = $7FF ) then
  4368. Begin
  4369. if ( bSig0 OR bSig1 )<> 0 then
  4370. Begin
  4371. propagateFloat64NaN( a, b, result );
  4372. exit;
  4373. End;
  4374. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  4375. Begin
  4376. invalid:
  4377. float_raise( float_flag_invalid );
  4378. z.low := float64_default_nan_low;
  4379. z.high := float64_default_nan_high;
  4380. result := z;
  4381. exit;
  4382. End;
  4383. packFloat64( zSign, $7FF, 0, 0, result );
  4384. exit;
  4385. End;
  4386. if ( aExp = 0 ) then
  4387. Begin
  4388. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4389. Begin
  4390. packFloat64( zSign, 0, 0, 0, result );
  4391. exit;
  4392. End;
  4393. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4394. End;
  4395. if ( bExp = 0 ) then
  4396. Begin
  4397. if ( ( bSig0 OR bSig1 ) = 0 ) then
  4398. Begin
  4399. packFloat64( zSign, 0, 0, 0, result );
  4400. exit;
  4401. End;
  4402. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  4403. End;
  4404. zExp := aExp + bExp - $400;
  4405. aSig0 := aSig0 or $00100000;
  4406. shortShift64Left( bSig0, bSig1, 12, bSig0, bSig1 );
  4407. mul64To128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
  4408. add64( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
  4409. zSig2 := zSig2 or flag( zSig3 <> 0 );
  4410. if ( $00200000 <= zSig0 ) then
  4411. Begin
  4412. shift64ExtraRightJamming(
  4413. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  4414. Inc(zExp);
  4415. End;
  4416. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
  4417. End;
  4418. {*
  4419. -------------------------------------------------------------------------------
  4420. Returns the result of dividing the double-precision floating-point value `a'
  4421. by the corresponding value `b'. The operation is performed according to the
  4422. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4423. -------------------------------------------------------------------------------
  4424. *}
  4425. Function float64_div(a: float64; b : float64) : Float64;
  4426. {$ifdef fpc}[public,Alias:'FLOAT64_DIV'];compilerproc;{$endif}
  4427. Var
  4428. aSign, bSign, zSign: flag;
  4429. aExp, bExp, zExp: int16;
  4430. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  4431. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  4432. z: float64;
  4433. label invalid;
  4434. Begin
  4435. aSig1 := extractFloat64Frac1( a );
  4436. aSig0 := extractFloat64Frac0( a );
  4437. aExp := extractFloat64Exp( a );
  4438. aSign := extractFloat64Sign( a );
  4439. bSig1 := extractFloat64Frac1( b );
  4440. bSig0 := extractFloat64Frac0( b );
  4441. bExp := extractFloat64Exp( b );
  4442. bSign := extractFloat64Sign( b );
  4443. zSign := aSign xor bSign;
  4444. if ( aExp = $7FF ) then
  4445. Begin
  4446. if ( aSig0 OR aSig1 )<> 0 then
  4447. Begin
  4448. propagateFloat64NaN( a, b, result );
  4449. exit;
  4450. end;
  4451. if ( bExp = $7FF ) then
  4452. Begin
  4453. if ( bSig0 OR bSig1 )<>0 then
  4454. Begin
  4455. propagateFloat64NaN( a, b, result );
  4456. exit;
  4457. End;
  4458. goto invalid;
  4459. End;
  4460. packFloat64( zSign, $7FF, 0, 0, result );
  4461. exit;
  4462. End;
  4463. if ( bExp = $7FF ) then
  4464. Begin
  4465. if ( bSig0 OR bSig1 )<> 0 then
  4466. Begin
  4467. propagateFloat64NaN( a, b, result );
  4468. exit;
  4469. End;
  4470. packFloat64( zSign, 0, 0, 0, result );
  4471. exit;
  4472. End;
  4473. if ( bExp = 0 ) then
  4474. Begin
  4475. if ( ( bSig0 OR bSig1 ) = 0 ) then
  4476. Begin
  4477. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  4478. Begin
  4479. invalid:
  4480. float_raise( float_flag_invalid );
  4481. z.low := float64_default_nan_low;
  4482. z.high := float64_default_nan_high;
  4483. result := z;
  4484. exit;
  4485. End;
  4486. float_raise( float_flag_divbyzero );
  4487. packFloat64( zSign, $7FF, 0, 0, result );
  4488. exit;
  4489. End;
  4490. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  4491. End;
  4492. if ( aExp = 0 ) then
  4493. Begin
  4494. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4495. Begin
  4496. packFloat64( zSign, 0, 0, 0, result );
  4497. exit;
  4498. End;
  4499. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4500. End;
  4501. zExp := aExp - bExp + $3FD;
  4502. shortShift64Left( aSig0 OR $00100000, aSig1, 11, aSig0, aSig1 );
  4503. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  4504. if ( le64( bSig0, bSig1, aSig0, aSig1 )<>0 ) then
  4505. Begin
  4506. shift64Right( aSig0, aSig1, 1, aSig0, aSig1 );
  4507. Inc(zExp);
  4508. End;
  4509. zSig0 := estimateDiv64To32( aSig0, aSig1, bSig0 );
  4510. mul64By32To96( bSig0, bSig1, zSig0, term0, term1, term2 );
  4511. sub96( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
  4512. while ( sbits32 (rem0) < 0 ) do
  4513. Begin
  4514. Dec(zSig0);
  4515. add96( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
  4516. End;
  4517. zSig1 := estimateDiv64To32( rem1, rem2, bSig0 );
  4518. if ( ( zSig1 and $3FF ) <= 4 ) then
  4519. Begin
  4520. mul64By32To96( bSig0, bSig1, zSig1, term1, term2, term3 );
  4521. sub96( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
  4522. while ( sbits32 (rem1) < 0 ) do
  4523. Begin
  4524. Dec(zSig1);
  4525. add96( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
  4526. End;
  4527. zSig1 := zSig1 or flag( ( rem1 OR rem2 OR rem3 ) <> 0 );
  4528. End;
  4529. shift64ExtraRightJamming( zSig0, zSig1, 0, 11, zSig0, zSig1, zSig2 );
  4530. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
  4531. End;
  4532. {*
  4533. -------------------------------------------------------------------------------
  4534. Returns the remainder of the double-precision floating-point value `a'
  4535. with respect to the corresponding value `b'. The operation is performed
  4536. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4537. -------------------------------------------------------------------------------
  4538. *}
  4539. Function float64_rem(a: float64; b : float64) : float64;
  4540. {$ifdef fpc}[public,Alias:'FLOAT64_REM'];compilerproc;{$endif}
  4541. Var
  4542. aSign, bSign, zSign: flag;
  4543. aExp, bExp, expDiff: int16;
  4544. aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits32;
  4545. allZero, alternateASig0, alternateASig1, sigMean1: bits32;
  4546. sigMean0: sbits32;
  4547. z: float64;
  4548. label invalid;
  4549. Begin
  4550. aSig1 := extractFloat64Frac1( a );
  4551. aSig0 := extractFloat64Frac0( a );
  4552. aExp := extractFloat64Exp( a );
  4553. aSign := extractFloat64Sign( a );
  4554. bSig1 := extractFloat64Frac1( b );
  4555. bSig0 := extractFloat64Frac0( b );
  4556. bExp := extractFloat64Exp( b );
  4557. bSign := extractFloat64Sign( b );
  4558. if ( aExp = $7FF ) then
  4559. Begin
  4560. if ((( aSig0 OR aSig1 )<>0)
  4561. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  4562. Begin
  4563. propagateFloat64NaN( a, b, result );
  4564. exit;
  4565. End;
  4566. goto invalid;
  4567. End;
  4568. if ( bExp = $7FF ) then
  4569. Begin
  4570. if ( bSig0 OR bSig1 ) <> 0 then
  4571. Begin
  4572. propagateFloat64NaN( a, b, result );
  4573. exit;
  4574. End;
  4575. result := a;
  4576. exit;
  4577. End;
  4578. if ( bExp = 0 ) then
  4579. Begin
  4580. if ( ( bSig0 OR bSig1 ) = 0 ) then
  4581. Begin
  4582. invalid:
  4583. float_raise( float_flag_invalid );
  4584. z.low := float64_default_nan_low;
  4585. z.high := float64_default_nan_high;
  4586. result := z;
  4587. exit;
  4588. End;
  4589. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  4590. End;
  4591. if ( aExp = 0 ) then
  4592. Begin
  4593. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4594. Begin
  4595. result := a;
  4596. exit;
  4597. End;
  4598. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4599. End;
  4600. expDiff := aExp - bExp;
  4601. if ( expDiff < -1 ) then
  4602. Begin
  4603. result := a;
  4604. exit;
  4605. End;
  4606. shortShift64Left(
  4607. aSig0 OR $00100000, aSig1, 11 - flag( expDiff < 0 ), aSig0, aSig1 );
  4608. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  4609. q := le64( bSig0, bSig1, aSig0, aSig1 );
  4610. if ( q )<>0 then
  4611. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  4612. expDiff := expDiff - 32;
  4613. while ( 0 < expDiff ) do
  4614. Begin
  4615. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  4616. if 4 < q then
  4617. q:= q - 4
  4618. else
  4619. q := 0;
  4620. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  4621. shortShift96Left( term0, term1, term2, 29, term1, term2, allZero );
  4622. shortShift64Left( aSig0, aSig1, 29, aSig0, allZero );
  4623. sub64( aSig0, 0, term1, term2, aSig0, aSig1 );
  4624. expDiff := expDiff - 29;
  4625. End;
  4626. if ( -32 < expDiff ) then
  4627. Begin
  4628. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  4629. if 4 < q then
  4630. q := q - 4
  4631. else
  4632. q := 0;
  4633. q := q shr (- expDiff);
  4634. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  4635. expDiff := expDiff + 24;
  4636. if ( expDiff < 0 ) then
  4637. Begin
  4638. shift64Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  4639. End
  4640. else
  4641. Begin
  4642. shortShift64Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
  4643. End;
  4644. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  4645. sub64( aSig0, aSig1, term1, term2, aSig0, aSig1 );
  4646. End
  4647. else
  4648. Begin
  4649. shift64Right( aSig0, aSig1, 8, aSig0, aSig1 );
  4650. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  4651. End;
  4652. Repeat
  4653. alternateASig0 := aSig0;
  4654. alternateASig1 := aSig1;
  4655. Inc(q);
  4656. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  4657. Until not ( 0 <= sbits32 (aSig0) );
  4658. add64(
  4659. aSig0, aSig1, alternateASig0, alternateASig1, bits32(sigMean0), sigMean1 );
  4660. if ( ( sigMean0 < 0 )
  4661. OR ( ( ( sigMean0 OR sigMean1 ) = 0 ) AND (( q AND 1 )<>0) ) ) then
  4662. Begin
  4663. aSig0 := alternateASig0;
  4664. aSig1 := alternateASig1;
  4665. End;
  4666. zSign := flag( sbits32 (aSig0) < 0 );
  4667. if ( zSign <> 0 ) then
  4668. sub64( 0, 0, aSig0, aSig1, aSig0, aSig1 );
  4669. normalizeRoundAndPackFloat64( aSign xor zSign, bExp - 4, aSig0, aSig1, result );
  4670. End;
  4671. {*
  4672. -------------------------------------------------------------------------------
  4673. Returns the square root of the double-precision floating-point value `a'.
  4674. The operation is performed according to the IEC/IEEE Standard for Binary
  4675. Floating-Point Arithmetic.
  4676. -------------------------------------------------------------------------------
  4677. *}
  4678. Procedure float64_sqrt( a: float64; var out: float64 );
  4679. {$ifdef fpc}[public,Alias:'FLOAT64_SQRT'];compilerproc;{$endif}
  4680. Var
  4681. aSign: flag;
  4682. aExp, zExp: int16;
  4683. aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits32;
  4684. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  4685. z: float64;
  4686. label invalid;
  4687. Begin
  4688. aSig1 := extractFloat64Frac1( a );
  4689. aSig0 := extractFloat64Frac0( a );
  4690. aExp := extractFloat64Exp( a );
  4691. aSign := extractFloat64Sign( a );
  4692. if ( aExp = $7FF ) then
  4693. Begin
  4694. if ( aSig0 OR aSig1 ) <> 0 then
  4695. Begin
  4696. propagateFloat64NaN( a, a, out );
  4697. exit;
  4698. End;
  4699. if ( aSign = 0) then
  4700. Begin
  4701. out := a;
  4702. exit;
  4703. End;
  4704. goto invalid;
  4705. End;
  4706. if ( aSign <> 0 ) then
  4707. Begin
  4708. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  4709. Begin
  4710. out := a;
  4711. exit;
  4712. End;
  4713. invalid:
  4714. float_raise( float_flag_invalid );
  4715. z.low := float64_default_nan_low;
  4716. z.high := float64_default_nan_high;
  4717. out := z;
  4718. exit;
  4719. End;
  4720. if ( aExp = 0 ) then
  4721. Begin
  4722. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4723. Begin
  4724. packFloat64( 0, 0, 0, 0, out );
  4725. exit;
  4726. End;
  4727. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4728. End;
  4729. zExp := ( ( aExp - $3FF ) shr 1 ) + $3FE;
  4730. aSig0 := aSig0 or $00100000;
  4731. shortShift64Left( aSig0, aSig1, 11, term0, term1 );
  4732. zSig0 := ( estimateSqrt32( aExp, term0 ) shr 1 ) + 1;
  4733. if ( zSig0 = 0 ) then
  4734. zSig0 := $7FFFFFFF;
  4735. doubleZSig0 := zSig0 + zSig0;
  4736. shortShift64Left( aSig0, aSig1, 9 - ( aExp and 1 ), aSig0, aSig1 );
  4737. mul32To64( zSig0, zSig0, term0, term1 );
  4738. sub64( aSig0, aSig1, term0, term1, rem0, rem1 );
  4739. while ( sbits32 (rem0) < 0 ) do
  4740. Begin
  4741. Dec(zSig0);
  4742. doubleZSig0 := doubleZSig0 - 2;
  4743. add64( rem0, rem1, 0, doubleZSig0 OR 1, rem0, rem1 );
  4744. End;
  4745. zSig1 := estimateDiv64To32( rem1, 0, doubleZSig0 );
  4746. if ( ( zSig1 and $1FF ) <= 5 ) then
  4747. Begin
  4748. if ( zSig1 = 0 ) then
  4749. zSig1 := 1;
  4750. mul32To64( doubleZSig0, zSig1, term1, term2 );
  4751. sub64( rem1, 0, term1, term2, rem1, rem2 );
  4752. mul32To64( zSig1, zSig1, term2, term3 );
  4753. sub96( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  4754. while ( sbits32 (rem1) < 0 ) do
  4755. Begin
  4756. Dec(zSig1);
  4757. shortShift64Left( 0, zSig1, 1, term2, term3 );
  4758. term3 := term3 or 1;
  4759. term2 := term2 or doubleZSig0;
  4760. add96( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  4761. End;
  4762. zSig1 := zSig1 or bits32( ( rem1 OR rem2 OR rem3 ) <> 0 );
  4763. End;
  4764. shift64ExtraRightJamming( zSig0, zSig1, 0, 10, zSig0, zSig1, zSig2 );
  4765. roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2, out );
  4766. End;
  4767. {*
  4768. -------------------------------------------------------------------------------
  4769. Returns 1 if the double-precision floating-point value `a' is equal to
  4770. the corresponding value `b', and 0 otherwise. The comparison is performed
  4771. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4772. -------------------------------------------------------------------------------
  4773. *}
  4774. Function float64_eq(a: float64; b: float64): flag;
  4775. {$ifdef fpc}[public,Alias:'FLOAT64_EQ'];compilerproc;{$endif}
  4776. Begin
  4777. if
  4778. (
  4779. ( extractFloat64Exp( a ) = $7FF )
  4780. AND
  4781. (
  4782. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4783. )
  4784. )
  4785. OR (
  4786. ( extractFloat64Exp( b ) = $7FF )
  4787. AND (
  4788. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4789. )
  4790. )
  4791. ) then
  4792. Begin
  4793. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  4794. float_raise( float_flag_invalid );
  4795. float64_eq := 0;
  4796. exit;
  4797. End;
  4798. float64_eq := flag(
  4799. ( a.low = b.low )
  4800. AND ( ( a.high = b.high )
  4801. OR ( ( a.low = 0 )
  4802. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  4803. ));
  4804. End;
  4805. {*
  4806. -------------------------------------------------------------------------------
  4807. Returns 1 if the double-precision floating-point value `a' is less than
  4808. or equal to the corresponding value `b', and 0 otherwise. The comparison
  4809. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  4810. Arithmetic.
  4811. -------------------------------------------------------------------------------
  4812. *}
  4813. Function float64_le(a: float64;b: float64): flag;
  4814. {$ifdef fpc}[public,Alias:'FLOAT64_LE'];compilerproc;{$endif}
  4815. Var
  4816. aSign, bSign: flag;
  4817. Begin
  4818. if
  4819. (
  4820. ( extractFloat64Exp( a ) = $7FF )
  4821. AND
  4822. (
  4823. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4824. )
  4825. )
  4826. OR (
  4827. ( extractFloat64Exp( b ) = $7FF )
  4828. AND (
  4829. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4830. )
  4831. )
  4832. ) then
  4833. Begin
  4834. float_raise( float_flag_invalid );
  4835. float64_le := 0;
  4836. exit;
  4837. End;
  4838. aSign := extractFloat64Sign( a );
  4839. bSign := extractFloat64Sign( b );
  4840. if ( aSign <> bSign ) then
  4841. Begin
  4842. float64_le := flag(
  4843. (aSign <> 0)
  4844. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  4845. = 0 ));
  4846. exit;
  4847. End;
  4848. if aSign <> 0 then
  4849. float64_le := le64( b.high, b.low, a.high, a.low )
  4850. else
  4851. float64_le := le64( a.high, a.low, b.high, b.low );
  4852. End;
  4853. {*
  4854. -------------------------------------------------------------------------------
  4855. Returns 1 if the double-precision floating-point value `a' is less than
  4856. the corresponding value `b', and 0 otherwise. The comparison is performed
  4857. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4858. -------------------------------------------------------------------------------
  4859. *}
  4860. Function float64_lt(a: float64;b: float64): flag;
  4861. {$ifdef fpc}[public,Alias:'FLOAT64_LT'];compilerproc;{$endif}
  4862. Var
  4863. aSign, bSign: flag;
  4864. Begin
  4865. if
  4866. (
  4867. ( extractFloat64Exp( a ) = $7FF )
  4868. AND
  4869. (
  4870. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4871. )
  4872. )
  4873. OR (
  4874. ( extractFloat64Exp( b ) = $7FF )
  4875. AND (
  4876. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4877. )
  4878. )
  4879. ) then
  4880. Begin
  4881. float_raise( float_flag_invalid );
  4882. float64_lt := 0;
  4883. exit;
  4884. End;
  4885. aSign := extractFloat64Sign( a );
  4886. bSign := extractFloat64Sign( b );
  4887. if ( aSign <> bSign ) then
  4888. Begin
  4889. float64_lt := flag(
  4890. (aSign <> 0)
  4891. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  4892. <> 0 ));
  4893. exit;
  4894. End;
  4895. if aSign <> 0 then
  4896. float64_lt := lt64( b.high, b.low, a.high, a.low )
  4897. else
  4898. float64_lt := lt64( a.high, a.low, b.high, b.low );
  4899. End;
  4900. {*
  4901. -------------------------------------------------------------------------------
  4902. Returns 1 if the double-precision floating-point value `a' is equal to
  4903. the corresponding value `b', and 0 otherwise. The invalid exception is
  4904. raised if either operand is a NaN. Otherwise, the comparison is performed
  4905. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4906. -------------------------------------------------------------------------------
  4907. *}
  4908. Function float64_eq_signaling( a: float64; b: float64): flag;
  4909. Begin
  4910. if
  4911. (
  4912. ( extractFloat64Exp( a ) = $7FF )
  4913. AND
  4914. (
  4915. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4916. )
  4917. )
  4918. OR (
  4919. ( extractFloat64Exp( b ) = $7FF )
  4920. AND (
  4921. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4922. )
  4923. )
  4924. ) then
  4925. Begin
  4926. float_raise( float_flag_invalid );
  4927. float64_eq_signaling := 0;
  4928. exit;
  4929. End;
  4930. float64_eq_signaling := flag(
  4931. ( a.low = b.low )
  4932. AND ( ( a.high = b.high )
  4933. OR ( ( a.low = 0 )
  4934. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  4935. ));
  4936. End;
  4937. {*
  4938. -------------------------------------------------------------------------------
  4939. Returns 1 if the double-precision floating-point value `a' is less than or
  4940. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  4941. cause an exception. Otherwise, the comparison is performed according to the
  4942. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4943. -------------------------------------------------------------------------------
  4944. *}
  4945. Function float64_le_quiet(a: float64 ; b: float64 ): flag;
  4946. Var
  4947. aSign, bSign : flag;
  4948. Begin
  4949. if
  4950. (
  4951. ( extractFloat64Exp( a ) = $7FF )
  4952. AND
  4953. (
  4954. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  4955. )
  4956. )
  4957. OR (
  4958. ( extractFloat64Exp( b ) = $7FF )
  4959. AND (
  4960. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  4961. )
  4962. )
  4963. ) then
  4964. Begin
  4965. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  4966. float_raise( float_flag_invalid );
  4967. float64_le_quiet := 0;
  4968. exit;
  4969. End;
  4970. aSign := extractFloat64Sign( a );
  4971. bSign := extractFloat64Sign( b );
  4972. if ( aSign <> bSign ) then
  4973. Begin
  4974. float64_le_quiet := flag
  4975. ((aSign <> 0)
  4976. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  4977. = 0 ));
  4978. exit;
  4979. End;
  4980. if aSign <> 0 then
  4981. float64_le_quiet := le64( b.high, b.low, a.high, a.low )
  4982. else
  4983. float64_le_quiet := le64( a.high, a.low, b.high, b.low );
  4984. End;
  4985. {*
  4986. -------------------------------------------------------------------------------
  4987. Returns 1 if the double-precision floating-point value `a' is less than
  4988. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  4989. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  4990. Standard for Binary Floating-Point Arithmetic.
  4991. -------------------------------------------------------------------------------
  4992. *}
  4993. Function float64_lt_quiet(a: float64; b: float64 ): Flag;
  4994. Var
  4995. aSign, bSign: flag;
  4996. Begin
  4997. if
  4998. (
  4999. ( extractFloat64Exp( a ) = $7FF )
  5000. AND
  5001. (
  5002. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5003. )
  5004. )
  5005. OR (
  5006. ( extractFloat64Exp( b ) = $7FF )
  5007. AND (
  5008. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5009. )
  5010. )
  5011. ) then
  5012. Begin
  5013. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  5014. float_raise( float_flag_invalid );
  5015. float64_lt_quiet := 0;
  5016. exit;
  5017. End;
  5018. aSign := extractFloat64Sign( a );
  5019. bSign := extractFloat64Sign( b );
  5020. if ( aSign <> bSign ) then
  5021. Begin
  5022. float64_lt_quiet := flag(
  5023. (aSign<>0)
  5024. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5025. <> 0 ));
  5026. exit;
  5027. End;
  5028. If aSign <> 0 then
  5029. float64_lt_quiet := lt64( b.high, b.low, a.high, a.low )
  5030. else
  5031. float64_lt_quiet := lt64( a.high, a.low, b.high, b.low );
  5032. End;
  5033. {*----------------------------------------------------------------------------
  5034. | Returns the result of converting the 64-bit two's complement integer `a'
  5035. | to the single-precision floating-point format. The conversion is performed
  5036. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5037. *----------------------------------------------------------------------------*}
  5038. function int64_to_float32( a: int64 ): float32rec; compilerproc;
  5039. var
  5040. zSign : flag;
  5041. absA : uint64;
  5042. shiftCount: int8;
  5043. zSig : bits32;
  5044. intval : int64rec;
  5045. Begin
  5046. if ( a = 0 ) then
  5047. begin
  5048. int64_to_float32.float32 := 0;
  5049. exit;
  5050. end;
  5051. if a < 0 then
  5052. zSign := flag(TRUE)
  5053. else
  5054. zSign := flag(FALSE);
  5055. if zSign<>0 then
  5056. absA := -a
  5057. else
  5058. absA := a;
  5059. shiftCount := countLeadingZeros64( absA ) - 40;
  5060. if ( 0 <= shiftCount ) then
  5061. begin
  5062. int64_to_float32.float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount );
  5063. end
  5064. else
  5065. begin
  5066. shiftCount := shiftCount + 7;
  5067. if ( shiftCount < 0 ) then
  5068. begin
  5069. intval.low := int64rec(AbsA).low;
  5070. intval.high := int64rec(AbsA).high;
  5071. shift64RightJamming( intval.low, intval.high, - shiftCount,
  5072. intval.low, intval.high);
  5073. int64rec(absA).low := intval.low;
  5074. int64rec(absA).high := intval.high;
  5075. end
  5076. else
  5077. absA := absA shl shiftCount;
  5078. int64_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA );
  5079. end;
  5080. End;
  5081. {*----------------------------------------------------------------------------
  5082. | Returns the result of converting the 64-bit two's complement integer `a'
  5083. | to the single-precision floating-point format. The conversion is performed
  5084. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5085. | Unisgned version.
  5086. *----------------------------------------------------------------------------*}
  5087. function qword_to_float32( a: qword ): float32rec; compilerproc;
  5088. var
  5089. zSign : flag;
  5090. absA : uint64;
  5091. shiftCount: int8;
  5092. zSig : bits32;
  5093. intval : int64rec;
  5094. Begin
  5095. if ( a = 0 ) then
  5096. begin
  5097. qword_to_float32.float32 := 0;
  5098. exit;
  5099. end;
  5100. zSign := flag(FALSE);
  5101. absA := a;
  5102. shiftCount := countLeadingZeros64( absA ) - 40;
  5103. if ( 0 <= shiftCount ) then
  5104. begin
  5105. qword_to_float32.float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount );
  5106. end
  5107. else
  5108. begin
  5109. shiftCount := shiftCount + 7;
  5110. if ( shiftCount < 0 ) then
  5111. begin
  5112. intval.low := int64rec(AbsA).low;
  5113. intval.high := int64rec(AbsA).high;
  5114. shift64RightJamming( intval.low, intval.high, - shiftCount,
  5115. intval.low, intval.high);
  5116. int64rec(absA).low := intval.low;
  5117. int64rec(absA).high := intval.high;
  5118. end
  5119. else
  5120. absA := absA shl shiftCount;
  5121. qword_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA );
  5122. end;
  5123. End;
  5124. {*----------------------------------------------------------------------------
  5125. | Returns the result of converting the 64-bit two's complement integer `a'
  5126. | to the double-precision floating-point format. The conversion is performed
  5127. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5128. *----------------------------------------------------------------------------*}
  5129. function qword_to_float64( a: qword ): float64;
  5130. {$ifdef fpc}[public,Alias:'QWORD_TO_FLOAT64'];compilerproc;{$endif}
  5131. var
  5132. zSign : flag;
  5133. float_result : float64;
  5134. intval : int64rec;
  5135. AbsA : bits64;
  5136. shiftcount : int8;
  5137. zSig0, zSig1 : bits32;
  5138. Begin
  5139. if ( a = 0 ) then
  5140. Begin
  5141. packFloat64( 0, 0, 0, 0, result );
  5142. exit;
  5143. end;
  5144. zSign := flag(FALSE);
  5145. AbsA := a;
  5146. shiftCount := countLeadingZeros64( absA ) - 11;
  5147. if ( 0 <= shiftCount ) then
  5148. Begin
  5149. absA := absA shl shiftcount;
  5150. zSig0:=int64rec(absA).high;
  5151. zSig1:=int64rec(absA).low;
  5152. End
  5153. else
  5154. Begin
  5155. shift64Right( int64rec(absA).high, int64rec(absA).low,
  5156. - shiftCount, zSig0, zSig1 );
  5157. End;
  5158. packFloat64( zSign, $432 - shiftCount, zSig0, zSig1, float_result );
  5159. qword_to_float64:= float_result;
  5160. End;
  5161. {*----------------------------------------------------------------------------
  5162. | Returns the result of converting the 64-bit two's complement integer `a'
  5163. | to the double-precision floating-point format. The conversion is performed
  5164. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5165. *----------------------------------------------------------------------------*}
  5166. function int64_to_float64( a: int64 ): float64;
  5167. {$ifdef fpc}[public,Alias:'INT64_TO_FLOAT64'];compilerproc;{$endif}
  5168. var
  5169. zSign : flag;
  5170. float_result : float64;
  5171. intval : int64rec;
  5172. AbsA : bits64;
  5173. shiftcount : int8;
  5174. zSig0, zSig1 : bits32;
  5175. Begin
  5176. if ( a = 0 ) then
  5177. Begin
  5178. packFloat64( 0, 0, 0, 0, result );
  5179. exit;
  5180. end;
  5181. zSign := flag( a < 0 );
  5182. if ZSign<>0 then
  5183. AbsA := -a
  5184. else
  5185. AbsA := a;
  5186. shiftCount := countLeadingZeros64( absA ) - 11;
  5187. if ( 0 <= shiftCount ) then
  5188. Begin
  5189. absA := absA shl shiftcount;
  5190. zSig0:=int64rec(absA).high;
  5191. zSig1:=int64rec(absA).low;
  5192. End
  5193. else
  5194. Begin
  5195. shift64Right( int64rec(absA).high, int64rec(absA).low,
  5196. - shiftCount, zSig0, zSig1 );
  5197. End;
  5198. packFloat64( zSign, $432 - shiftCount, zSig0, zSig1, float_result );
  5199. int64_to_float64:= float_result;
  5200. End;
  5201. {*----------------------------------------------------------------------------
  5202. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
  5203. | is equal to the 128-bit value formed by concatenating `b0' and `b1'.
  5204. | Otherwise, returns 0.
  5205. *----------------------------------------------------------------------------*}
  5206. function eq128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  5207. begin
  5208. result := ord(( a0 = b0 ) and ( a1 = b1 ));
  5209. end;
  5210. {*----------------------------------------------------------------------------
  5211. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  5212. | than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
  5213. | Otherwise, returns 0.
  5214. *----------------------------------------------------------------------------*}
  5215. function le128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  5216. begin
  5217. result:=ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 <= b1 ) ));
  5218. end;
  5219. {*----------------------------------------------------------------------------
  5220. | Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
  5221. | by 64 _plus_ the number of bits given in `count'. The shifted result is
  5222. | at most 128 nonzero bits; these are broken into two 64-bit pieces which are
  5223. | stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  5224. | off form a third 64-bit result as follows: The _last_ bit shifted off is
  5225. | the most-significant bit of the extra result, and the other 63 bits of the
  5226. | extra result are all zero if and only if _all_but_the_last_ bits shifted off
  5227. | were all zero. This extra result is stored in the location pointed to by
  5228. | `z2Ptr'. The value of `count' can be arbitrarily large.
  5229. | (This routine makes more sense if `a0', `a1', and `a2' are considered
  5230. | to form a fixed-point value with binary point between `a1' and `a2'. This
  5231. | fixed-point value is shifted right by the number of bits given in `count',
  5232. | and the integer part of the result is returned at the locations pointed to
  5233. | by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  5234. | corrupted as described above, and is returned at the location pointed to by
  5235. | `z2Ptr'.)
  5236. *----------------------------------------------------------------------------*}
  5237. procedure shift128ExtraRightJamming(
  5238. a0: bits64;
  5239. a1: bits64;
  5240. a2: bits64;
  5241. count: int16;
  5242. var z0Ptr: bits64;
  5243. var z1Ptr: bits64;
  5244. var z2Ptr: bits64);
  5245. var
  5246. z0, z1, z2: bits64;
  5247. negCount: int8;
  5248. begin
  5249. negCount := ( - count ) and 63;
  5250. if ( count = 0 ) then
  5251. begin
  5252. z2 := a2;
  5253. z1 := a1;
  5254. z0 := a0;
  5255. end
  5256. else begin
  5257. if ( count < 64 ) then
  5258. begin
  5259. z2 := a1 shr negCount;
  5260. z1 := ( a0 shl negCount ) or ( a1 shr count );
  5261. z0 := a0 shr count;
  5262. end
  5263. else begin
  5264. if ( count = 64 ) then
  5265. begin
  5266. z2 := a1;
  5267. z1 := a0;
  5268. end
  5269. else begin
  5270. a2 := a2 or a1;
  5271. if ( count < 128 ) then
  5272. begin
  5273. z2 := a0 shl negCount;
  5274. z1 := a0 shr ( count and 63 );
  5275. end
  5276. else begin
  5277. if ( count = 128 ) then
  5278. z2 := a0
  5279. else
  5280. z2 := ord( a0 <> 0 );
  5281. z1 := 0;
  5282. end;
  5283. end;
  5284. z0 := 0;
  5285. end;
  5286. z2 := z2 or ord( a2 <> 0 );
  5287. end;
  5288. z2Ptr := z2;
  5289. z1Ptr := z1;
  5290. z0Ptr := z0;
  5291. end;
  5292. {*----------------------------------------------------------------------------
  5293. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
  5294. | _plus_ the number of bits given in `count'. The shifted result is at most
  5295. | 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
  5296. | bits shifted off form a second 64-bit result as follows: The _last_ bit
  5297. | shifted off is the most-significant bit of the extra result, and the other
  5298. | 63 bits of the extra result are all zero if and only if _all_but_the_last_
  5299. | bits shifted off were all zero. This extra result is stored in the location
  5300. | pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
  5301. | (This routine makes more sense if `a0' and `a1' are considered to form
  5302. | a fixed-point value with binary point between `a0' and `a1'. This fixed-
  5303. | point value is shifted right by the number of bits given in `count', and
  5304. | the integer part of the result is returned at the location pointed to by
  5305. | `z0Ptr'. The fractional part of the result may be slightly corrupted as
  5306. | described above, and is returned at the location pointed to by `z1Ptr'.)
  5307. *----------------------------------------------------------------------------*}
  5308. procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  5309. var
  5310. z0, z1: bits64;
  5311. negCount: int8;
  5312. begin
  5313. negCount := ( - count ) and 63;
  5314. if ( count = 0 ) then
  5315. begin
  5316. z1 := a1;
  5317. z0 := a0;
  5318. end
  5319. else if ( count < 64 ) then
  5320. begin
  5321. z1 := ( a0 shl negCount ) or ord( a1 <> 0 );
  5322. z0 := a0 shr count;
  5323. end
  5324. else begin
  5325. if ( count = 64 ) then
  5326. begin
  5327. z1 := a0 or ord( a1 <> 0 );
  5328. end
  5329. else begin
  5330. z1 := ord( ( a0 or a1 ) <> 0 );
  5331. end;
  5332. z0 := 0;
  5333. end;
  5334. z1Ptr := z1;
  5335. z0Ptr := z0;
  5336. end;
  5337. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  5338. {*----------------------------------------------------------------------------
  5339. | Returns the fraction bits of the extended double-precision floating-point
  5340. | value `a'.
  5341. *----------------------------------------------------------------------------*}
  5342. function extractFloatx80Frac(a : floatx80): bits64;inline;
  5343. begin
  5344. result:=a.low;
  5345. end;
  5346. {*----------------------------------------------------------------------------
  5347. | Returns the exponent bits of the extended double-precision floating-point
  5348. | value `a'.
  5349. *----------------------------------------------------------------------------*}
  5350. function extractFloatx80Exp(a : floatx80): int32;inline;
  5351. begin
  5352. result:=a.high and $7FFF;
  5353. end;
  5354. {*----------------------------------------------------------------------------
  5355. | Returns the sign bit of the extended double-precision floating-point value
  5356. | `a'.
  5357. *----------------------------------------------------------------------------*}
  5358. function extractFloatx80Sign(a : floatx80): flag;inline;
  5359. begin
  5360. result:=a.high shr 15;
  5361. end;
  5362. {*----------------------------------------------------------------------------
  5363. | Normalizes the subnormal extended double-precision floating-point value
  5364. | represented by the denormalized significand `aSig'. The normalized exponent
  5365. | and significand are stored at the locations pointed to by `zExpPtr' and
  5366. | `zSigPtr', respectively.
  5367. *----------------------------------------------------------------------------*}
  5368. procedure normalizeFloatx80Subnormal( aSig: bits64; var zExpPtr: int32; var zSigPtr : bits64);
  5369. var
  5370. shiftCount: int8;
  5371. begin
  5372. shiftCount := countLeadingZeros64( aSig );
  5373. zSigPtr := aSig shl shiftCount;
  5374. zExpPtr := 1 - shiftCount;
  5375. end;
  5376. {*----------------------------------------------------------------------------
  5377. | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
  5378. | extended double-precision floating-point value, returning the result.
  5379. *----------------------------------------------------------------------------*}
  5380. function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;
  5381. var
  5382. z: floatx80;
  5383. begin
  5384. z.low := zSig;
  5385. z.high := ( bits16(zSign) shl 15 ) + zExp;
  5386. result:=z;
  5387. end;
  5388. {*----------------------------------------------------------------------------
  5389. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  5390. | and extended significand formed by the concatenation of `zSig0' and `zSig1',
  5391. | and returns the proper extended double-precision floating-point value
  5392. | corresponding to the abstract input. Ordinarily, the abstract value is
  5393. | rounded and packed into the extended double-precision format, with the
  5394. | inexact exception raised if the abstract input cannot be represented
  5395. | exactly. However, if the abstract value is too large, the overflow and
  5396. | inexact exceptions are raised and an infinity or maximal finite value is
  5397. | returned. If the abstract value is too small, the input value is rounded to
  5398. | a subnormal number, and the underflow and inexact exceptions are raised if
  5399. | the abstract input cannot be represented exactly as a subnormal extended
  5400. | double-precision floating-point number.
  5401. | If `roundingPrecision' is 32 or 64, the result is rounded to the same
  5402. | number of bits as single or double precision, respectively. Otherwise, the
  5403. | result is rounded to the full precision of the extended double-precision
  5404. | format.
  5405. | The input significand must be normalized or smaller. If the input
  5406. | significand is not normalized, `zExp' must be 0; in that case, the result
  5407. | returned is a subnormal number, and it must not require rounding. The
  5408. | handling of underflow and overflow follows the IEC/IEEE Standard for Binary
  5409. | Floating-Point Arithmetic.
  5410. *----------------------------------------------------------------------------*}
  5411. function roundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
  5412. var
  5413. roundingMode: int8;
  5414. roundNearestEven, increment, isTiny: flag;
  5415. roundIncrement, roundMask, roundBits: int64;
  5416. label
  5417. precision80;
  5418. begin
  5419. roundingMode := softfloat_rounding_mode;
  5420. roundNearestEven := flag( roundingMode = float_round_nearest_even );
  5421. if ( roundingPrecision = 80 ) then
  5422. goto precision80;
  5423. if ( roundingPrecision = 64 ) then
  5424. begin
  5425. roundIncrement := int64( $0000000000000400 );
  5426. roundMask := int64( $00000000000007FF );
  5427. end
  5428. else if ( roundingPrecision = 32 ) then
  5429. begin
  5430. roundIncrement := int64( $0000008000000000 );
  5431. roundMask := int64( $000000FFFFFFFFFF );
  5432. end
  5433. else begin
  5434. goto precision80;
  5435. end;
  5436. zSig0 := zSig0 or ord( zSig1 <> 0 );
  5437. if ( not (roundNearestEven<>0) ) then
  5438. begin
  5439. if ( roundingMode = float_round_to_zero ) then
  5440. begin
  5441. roundIncrement := 0;
  5442. end
  5443. else begin
  5444. roundIncrement := roundMask;
  5445. if ( zSign<>0 ) then
  5446. begin
  5447. if ( roundingMode = float_round_up ) then
  5448. roundIncrement := 0;
  5449. end
  5450. else begin
  5451. if ( roundingMode = float_round_down ) then
  5452. roundIncrement := 0;
  5453. end;
  5454. end;
  5455. end;
  5456. roundBits := zSig0 and roundMask;
  5457. if ( $7FFD <= (bits32) ( zExp - 1 ) ) begin
  5458. if ( ( $7FFE < zExp )
  5459. or ( ( zExp = $7FFE ) and ( zSig0 + roundIncrement < zSig0 ) )
  5460. ) begin
  5461. goto overflow;
  5462. end;
  5463. if ( zExp <= 0 ) begin
  5464. isTiny =
  5465. ( float_detect_tininess = float_tininess_before_rounding )
  5466. or ( zExp < 0 )
  5467. or ( zSig0 <= zSig0 + roundIncrement );
  5468. shift64RightJamming( zSig0, 1 - zExp, zSig0 );
  5469. zExp := 0;
  5470. roundBits := zSig0 and roundMask;
  5471. if ( isTiny and roundBits ) float_raise( float_flag_underflow );
  5472. if ( roundBits ) softfloat_exception_flags |= float_flag_inexact;
  5473. zSig0 += roundIncrement;
  5474. if ( (sbits64) zSig0 < 0 ) zExp := 1;
  5475. roundIncrement := roundMask + 1;
  5476. if ( roundNearestEven and ( roundBits shl 1 = roundIncrement ) ) begin
  5477. roundMask |= roundIncrement;
  5478. end;
  5479. zSig0 = ~ roundMask;
  5480. result:=packFloatx80( zSign, zExp, zSig0 );
  5481. end;
  5482. end;
  5483. if ( roundBits ) softfloat_exception_flags |= float_flag_inexact;
  5484. zSig0 += roundIncrement;
  5485. if ( zSig0 < roundIncrement ) begin
  5486. ++zExp;
  5487. zSig0 := LIT64( $8000000000000000 );
  5488. end;
  5489. roundIncrement := roundMask + 1;
  5490. if ( roundNearestEven and ( roundBits shl 1 = roundIncrement ) ) begin
  5491. roundMask |= roundIncrement;
  5492. end;
  5493. zSig0 = ~ roundMask;
  5494. if ( zSig0 = 0 ) zExp := 0;
  5495. result:=packFloatx80( zSign, zExp, zSig0 );
  5496. precision80:
  5497. increment := ( (sbits64) zSig1 < 0 );
  5498. if ( ! roundNearestEven ) begin
  5499. if ( roundingMode = float_round_to_zero ) begin
  5500. increment := 0;
  5501. end;
  5502. else begin
  5503. if ( zSign ) begin
  5504. increment := ( roundingMode = float_round_down ) and zSig1;
  5505. end;
  5506. else begin
  5507. increment := ( roundingMode = float_round_up ) and zSig1;
  5508. end;
  5509. end;
  5510. end;
  5511. if ( $7FFD <= (bits32) ( zExp - 1 ) ) begin
  5512. if ( ( $7FFE < zExp )
  5513. or ( ( zExp = $7FFE )
  5514. and ( zSig0 = LIT64( $FFFFFFFFFFFFFFFF ) )
  5515. and increment
  5516. )
  5517. ) begin
  5518. roundMask := 0;
  5519. overflow:
  5520. float_raise( float_flag_overflow or float_flag_inexact );
  5521. if ( ( roundingMode = float_round_to_zero )
  5522. or ( zSign and ( roundingMode = float_round_up ) )
  5523. or ( ! zSign and ( roundingMode = float_round_down ) )
  5524. ) begin
  5525. result:=packFloatx80( zSign, $7FFE, ~ roundMask );
  5526. end;
  5527. result:=packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
  5528. end;
  5529. if ( zExp <= 0 ) begin
  5530. isTiny =
  5531. ( float_detect_tininess = float_tininess_before_rounding )
  5532. or ( zExp < 0 )
  5533. or ! increment
  5534. or ( zSig0 < LIT64( $FFFFFFFFFFFFFFFF ) );
  5535. shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, zSig0, zSig1 );
  5536. zExp := 0;
  5537. if ( isTiny and zSig1 ) float_raise( float_flag_underflow );
  5538. if ( zSig1 ) softfloat_exception_flags |= float_flag_inexact;
  5539. if ( roundNearestEven ) begin
  5540. increment := ( (sbits64) zSig1 < 0 );
  5541. end;
  5542. else begin
  5543. if ( zSign ) begin
  5544. increment := ( roundingMode = float_round_down ) and zSig1;
  5545. end;
  5546. else begin
  5547. increment := ( roundingMode = float_round_up ) and zSig1;
  5548. end;
  5549. end;
  5550. if ( increment ) begin
  5551. ++zSig0;
  5552. zSig0 =
  5553. ~ ( ( (bits64) ( zSig1 shl 1 ) = 0 ) and roundNearestEven );
  5554. if ( (sbits64) zSig0 < 0 ) zExp := 1;
  5555. end;
  5556. result:=packFloatx80( zSign, zExp, zSig0 );
  5557. end;
  5558. end;
  5559. if ( zSig1 ) softfloat_exception_flags |= float_flag_inexact;
  5560. if ( increment ) begin
  5561. ++zSig0;
  5562. if ( zSig0 = 0 ) begin
  5563. ++zExp;
  5564. zSig0 := LIT64( $8000000000000000 );
  5565. end;
  5566. else begin
  5567. zSig0 = ~ ( ( (bits64) ( zSig1 shl 1 ) = 0 ) and roundNearestEven );
  5568. end;
  5569. end;
  5570. else begin
  5571. if ( zSig0 = 0 ) zExp := 0;
  5572. end;
  5573. result:=packFloatx80( zSign, zExp, zSig0 );
  5574. end;
  5575. {*----------------------------------------------------------------------------
  5576. | Takes an abstract floating-point value having sign `zSign', exponent
  5577. | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
  5578. | and returns the proper extended double-precision floating-point value
  5579. | corresponding to the abstract input. This routine is just like
  5580. | `roundAndPackFloatx80' except that the input significand does not have to be
  5581. | normalized.
  5582. *----------------------------------------------------------------------------*}
  5583. function normalizeRoundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
  5584. var
  5585. shiftCount: int8;
  5586. begin
  5587. if ( zSig0 = 0 ) begin
  5588. zSig0 := zSig1;
  5589. zSig1 := 0;
  5590. zExp -= 64;
  5591. end;
  5592. shiftCount := countLeadingZeros64( zSig0 );
  5593. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  5594. zExp := eExp - shiftCount;
  5595. return
  5596. roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
  5597. end;
  5598. {*----------------------------------------------------------------------------
  5599. | Returns the result of converting the extended double-precision floating-
  5600. | point value `a' to the 32-bit two's complement integer format. The
  5601. | conversion is performed according to the IEC/IEEE Standard for Binary
  5602. | Floating-Point Arithmetic---which means in particular that the conversion
  5603. | is rounded according to the current rounding mode. If `a' is a NaN, the
  5604. | largest positive integer is returned. Otherwise, if the conversion
  5605. | overflows, the largest integer with the same sign as `a' is returned.
  5606. *----------------------------------------------------------------------------*}
  5607. function floatx80_to_int32(a: floatx80): int32;
  5608. var
  5609. aSign: flag;
  5610. aExp, shiftCount: int32;
  5611. aSig: bits64;
  5612. begin
  5613. aSig := extractFloatx80Frac( a );
  5614. aExp := extractFloatx80Exp( a );
  5615. aSign := extractFloatx80Sign( a );
  5616. if ( ( aExp = $7FFF ) and (bits64) ( aSig shl 1 ) ) aSign := 0;
  5617. shiftCount := $4037 - aExp;
  5618. if ( shiftCount <= 0 ) shiftCount := 1;
  5619. shift64RightJamming( aSig, shiftCount, aSig );
  5620. result := roundAndPackInt32( aSign, aSig );
  5621. end;
  5622. {*----------------------------------------------------------------------------
  5623. | Returns the result of converting the extended double-precision floating-
  5624. | point value `a' to the 32-bit two's complement integer format. The
  5625. | conversion is performed according to the IEC/IEEE Standard for Binary
  5626. | Floating-Point Arithmetic, except that the conversion is always rounded
  5627. | toward zero. If `a' is a NaN, the largest positive integer is returned.
  5628. | Otherwise, if the conversion overflows, the largest integer with the same
  5629. | sign as `a' is returned.
  5630. *----------------------------------------------------------------------------*}
  5631. function floatx80_to_int32_round_to_zero(a: floatx80): int32;
  5632. var
  5633. aSign: flag;
  5634. aExp, shiftCount: int32;
  5635. aSig, savedASig: bits64;
  5636. z: int32;
  5637. begin
  5638. aSig := extractFloatx80Frac( a );
  5639. aExp := extractFloatx80Exp( a );
  5640. aSign := extractFloatx80Sign( a );
  5641. if ( $401E < aExp ) begin
  5642. if ( ( aExp = $7FFF ) and (bits64) ( aSig shl 1 ) ) aSign := 0;
  5643. goto invalid;
  5644. end;
  5645. else if ( aExp < $3FFF ) begin
  5646. if ( aExp or aSig ) softfloat_exception_flags or= float_flag_inexact;
  5647. result := 0;
  5648. end;
  5649. shiftCount := $403E - aExp;
  5650. savedASig := aSig;
  5651. aSig >>= shiftCount;
  5652. z := aSig;
  5653. if ( aSign ) z := - z;
  5654. if ( ( z < 0 ) xor aSign ) begin
  5655. invalid:
  5656. float_raise( float_flag_invalid );
  5657. result := aSign ? (sbits32) $80000000 : $7FFFFFFF;
  5658. end;
  5659. if ( ( aSig shl shiftCount ) <> savedASig ) begin
  5660. softfloat_exception_flags or= float_flag_inexact;
  5661. end;
  5662. result := z;
  5663. end;
  5664. {*----------------------------------------------------------------------------
  5665. | Returns the result of converting the extended double-precision floating-
  5666. | point value `a' to the 64-bit two's complement integer format. The
  5667. | conversion is performed according to the IEC/IEEE Standard for Binary
  5668. | Floating-Point Arithmetic---which means in particular that the conversion
  5669. | is rounded according to the current rounding mode. If `a' is a NaN,
  5670. | the largest positive integer is returned. Otherwise, if the conversion
  5671. | overflows, the largest integer with the same sign as `a' is returned.
  5672. *----------------------------------------------------------------------------*}
  5673. function floatx80_to_int64(a: floatx80): int64;
  5674. var
  5675. aSign: flag;
  5676. aExp, shiftCount: int32;
  5677. aSig, aSigExtra: bits64;
  5678. begin
  5679. aSig := extractFloatx80Frac( a );
  5680. aExp := extractFloatx80Exp( a );
  5681. aSign := extractFloatx80Sign( a );
  5682. shiftCount := $403E - aExp;
  5683. if ( shiftCount <= 0 ) begin
  5684. if ( shiftCount ) begin
  5685. float_raise( float_flag_invalid );
  5686. if ( ! aSign
  5687. or ( ( aExp = $7FFF )
  5688. and ( aSig <> LIT64( $8000000000000000 ) ) )
  5689. ) begin
  5690. result := LIT64( $7FFFFFFFFFFFFFFF );
  5691. end;
  5692. result := (sbits64) LIT64( $8000000000000000 );
  5693. end;
  5694. aSigExtra := 0;
  5695. end;
  5696. else begin
  5697. shift64ExtraRightJamming( aSig, 0, shiftCount, aSig, aSigExtra );
  5698. end;
  5699. result := roundAndPackInt64( aSign, aSig, aSigExtra );
  5700. end;
  5701. {*----------------------------------------------------------------------------
  5702. | Returns the result of converting the extended double-precision floating-
  5703. | point value `a' to the 64-bit two's complement integer format. The
  5704. | conversion is performed according to the IEC/IEEE Standard for Binary
  5705. | Floating-Point Arithmetic, except that the conversion is always rounded
  5706. | toward zero. If `a' is a NaN, the largest positive integer is returned.
  5707. | Otherwise, if the conversion overflows, the largest integer with the same
  5708. | sign as `a' is returned.
  5709. *----------------------------------------------------------------------------*}
  5710. function floatx80_to_int64_round_to_zero(a: floatx80): int64;
  5711. var
  5712. aSign: flag;
  5713. aExp, shiftCount: int32;
  5714. aSig: bits64;
  5715. z: int64;
  5716. begin
  5717. aSig := extractFloatx80Frac( a );
  5718. aExp := extractFloatx80Exp( a );
  5719. aSign := extractFloatx80Sign( a );
  5720. shiftCount := aExp - $403E;
  5721. if ( 0 <= shiftCount ) begin
  5722. aSig = LIT64( $7FFFFFFFFFFFFFFF );
  5723. if ( ( a.high <> $C03E ) or aSig ) begin
  5724. float_raise( float_flag_invalid );
  5725. if ( ! aSign or ( ( aExp = $7FFF ) and aSig ) ) begin
  5726. result := LIT64( $7FFFFFFFFFFFFFFF );
  5727. end;
  5728. end;
  5729. result := (sbits64) LIT64( $8000000000000000 );
  5730. end;
  5731. else if ( aExp < $3FFF ) begin
  5732. if ( aExp or aSig ) softfloat_exception_flags or= float_flag_inexact;
  5733. result := 0;
  5734. end;
  5735. z := aSig>>( - shiftCount );
  5736. if ( (bits64) ( aSig shl ( shiftCount and 63 ) ) ) begin
  5737. softfloat_exception_flags or= float_flag_inexact;
  5738. end;
  5739. if ( aSign ) z := - z;
  5740. result := z;
  5741. end;
  5742. {*----------------------------------------------------------------------------
  5743. | Returns the result of converting the extended double-precision floating-
  5744. | point value `a' to the single-precision floating-point format. The
  5745. | conversion is performed according to the IEC/IEEE Standard for Binary
  5746. | Floating-Point Arithmetic.
  5747. *----------------------------------------------------------------------------*}
  5748. function floatx80_to_float32(a: floatx80): float32;
  5749. var
  5750. aSign: flag;
  5751. aExp: int32;
  5752. aSig: bits64;
  5753. begin
  5754. aSig := extractFloatx80Frac( a );
  5755. aExp := extractFloatx80Exp( a );
  5756. aSign := extractFloatx80Sign( a );
  5757. if ( aExp = $7FFF ) begin
  5758. if ( (bits64) ( aSig shl 1 ) ) begin
  5759. result := commonNaNToFloat32( floatx80ToCommonNaN( a ) );
  5760. end;
  5761. result := packFloat32( aSign, $FF, 0 );
  5762. end;
  5763. shift64RightJamming( aSig, 33, aSig );
  5764. if ( aExp or aSig ) aExp -= $3F81;
  5765. result := roundAndPackFloat32( aSign, aExp, aSig );
  5766. end;
  5767. {*----------------------------------------------------------------------------
  5768. | Returns the result of converting the extended double-precision floating-
  5769. | point value `a' to the double-precision floating-point format. The
  5770. | conversion is performed according to the IEC/IEEE Standard for Binary
  5771. | Floating-Point Arithmetic.
  5772. *----------------------------------------------------------------------------*}
  5773. function floatx80_to_float64(a: floatx80): float64;
  5774. var
  5775. aSign: flag;
  5776. aExp: int32;
  5777. aSig, zSig: bits64;
  5778. begin
  5779. aSig := extractFloatx80Frac( a );
  5780. aExp := extractFloatx80Exp( a );
  5781. aSign := extractFloatx80Sign( a );
  5782. if ( aExp = $7FFF ) begin
  5783. if ( (bits64) ( aSig shl 1 ) ) begin
  5784. result := commonNaNToFloat64( floatx80ToCommonNaN( a ) );
  5785. end;
  5786. result := packFloat64( aSign, $7FF, 0 );
  5787. end;
  5788. shift64RightJamming( aSig, 1, zSig );
  5789. if ( aExp or aSig ) aExp -= $3C01;
  5790. result := roundAndPackFloat64( aSign, aExp, zSig );
  5791. end;
  5792. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  5793. {*----------------------------------------------------------------------------
  5794. | Returns the result of converting the extended double-precision floating-
  5795. | point value `a' to the quadruple-precision floating-point format. The
  5796. | conversion is performed according to the IEC/IEEE Standard for Binary
  5797. | Floating-Point Arithmetic.
  5798. *----------------------------------------------------------------------------*}
  5799. function floatx80_to_float128(a: floatx80): float128;
  5800. var
  5801. aSign: flag;
  5802. aExp: int16;
  5803. aSig, zSig0, zSig1: bits64;
  5804. begin
  5805. aSig := extractFloatx80Frac( a );
  5806. aExp := extractFloatx80Exp( a );
  5807. aSign := extractFloatx80Sign( a );
  5808. if ( ( aExp = $7FFF ) and (bits64) ( aSig shl 1 ) ) begin
  5809. result := commonNaNToFloat128( floatx80ToCommonNaN( a ) );
  5810. end;
  5811. shift128Right( aSig shl 1, 0, 16, zSig0, zSig1 );
  5812. result := packFloat128( aSign, aExp, zSig0, zSig1 );
  5813. end;
  5814. {$endif FPC_SOFTFLOAT_FLOAT128}
  5815. {*----------------------------------------------------------------------------
  5816. | Rounds the extended double-precision floating-point value `a' to an integer,
  5817. | and Returns the result as an extended quadruple-precision floating-point
  5818. | value. The operation is performed according to the IEC/IEEE Standard for
  5819. | Binary Floating-Point Arithmetic.
  5820. *----------------------------------------------------------------------------*}
  5821. function floatx80_round_to_int(a: floatx80): floatx80;
  5822. var
  5823. aSign: flag;
  5824. aExp: int32;
  5825. lastBitMask, roundBitsMask: bits64;
  5826. roundingMode: int8;
  5827. z: floatx80;
  5828. begin
  5829. aExp := extractFloatx80Exp( a );
  5830. if ( $403E <= aExp ) begin
  5831. if ( ( aExp = $7FFF ) and (bits64) ( extractFloatx80Frac( a ) shl 1 ) ) begin
  5832. result := propagateFloatx80NaN( a, a );
  5833. end;
  5834. result := a;
  5835. end;
  5836. if ( aExp < $3FFF ) begin
  5837. if ( ( aExp = 0 )
  5838. and ( (bits64) ( extractFloatx80Frac( a ) shl 1 ) = 0 ) ) begin
  5839. result := a;
  5840. end;
  5841. softfloat_exception_flags or= float_flag_inexact;
  5842. aSign := extractFloatx80Sign( a );
  5843. switch ( softfloat_rounding_mode ) begin
  5844. case float_round_nearest_even:
  5845. if ( ( aExp = $3FFE ) and (bits64) ( extractFloatx80Frac( a ) shl 1 )
  5846. ) begin
  5847. result :=
  5848. packFloatx80( aSign, $3FFF, LIT64( $8000000000000000 ) );
  5849. end;
  5850. break;
  5851. case float_round_down:
  5852. result :=
  5853. aSign ?
  5854. packFloatx80( 1, $3FFF, LIT64( $8000000000000000 ) )
  5855. : packFloatx80( 0, 0, 0 );
  5856. case float_round_up:
  5857. result :=
  5858. aSign ? packFloatx80( 1, 0, 0 )
  5859. : packFloatx80( 0, $3FFF, LIT64( $8000000000000000 ) );
  5860. end;
  5861. result := packFloatx80( aSign, 0, 0 );
  5862. end;
  5863. lastBitMask := 1;
  5864. lastBitMask shl = $403E - aExp;
  5865. roundBitsMask := lastBitMask - 1;
  5866. z := a;
  5867. roundingMode := softfloat_rounding_mode;
  5868. if ( roundingMode = float_round_nearest_even ) begin
  5869. z.low += lastBitMask>>1;
  5870. if ( ( z.low and roundBitsMask ) = 0 ) z.low = ~ lastBitMask;
  5871. end;
  5872. else if ( roundingMode <> float_round_to_zero ) begin
  5873. if ( extractFloatx80Sign( z ) xor ( roundingMode = float_round_up ) ) begin
  5874. z.low += roundBitsMask;
  5875. end;
  5876. end;
  5877. z.low = ~ roundBitsMask;
  5878. if ( z.low = 0 ) begin
  5879. ++z.high;
  5880. z.low := LIT64( $8000000000000000 );
  5881. end;
  5882. if ( z.low <> a.low ) softfloat_exception_flags or= float_flag_inexact;
  5883. result := z;
  5884. end;
  5885. {*----------------------------------------------------------------------------
  5886. | Returns the result of adding the absolute values of the extended double-
  5887. | precision floating-point values `a' and `b'. If `zSign' is 1, the sum is
  5888. | negated before being returned. `zSign' is ignored if the result is a NaN.
  5889. | The addition is performed according to the IEC/IEEE Standard for Binary
  5890. | Floating-Point Arithmetic.
  5891. *----------------------------------------------------------------------------*}
  5892. function addFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
  5893. var
  5894. aExp, bExp, zExp: int32;
  5895. aSig, bSig, zSig0, zSig1: bits64;
  5896. expDiff: int32;
  5897. begin
  5898. aSig := extractFloatx80Frac( a );
  5899. aExp := extractFloatx80Exp( a );
  5900. bSig := extractFloatx80Frac( b );
  5901. bExp := extractFloatx80Exp( b );
  5902. expDiff := aExp - bExp;
  5903. if ( 0 < expDiff ) begin
  5904. if ( aExp = $7FFF ) begin
  5905. if ( (bits64) ( aSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  5906. result := a;
  5907. end;
  5908. if ( bExp = 0 ) --expDiff;
  5909. shift64ExtraRightJamming( bSig, 0, expDiff, bSig, zSig1 );
  5910. zExp := aExp;
  5911. end;
  5912. else if ( expDiff < 0 ) begin
  5913. if ( bExp = $7FFF ) begin
  5914. if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  5915. result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
  5916. end;
  5917. if ( aExp = 0 ) ++expDiff;
  5918. shift64ExtraRightJamming( aSig, 0, - expDiff, aSig, zSig1 );
  5919. zExp := bExp;
  5920. end;
  5921. else begin
  5922. if ( aExp = $7FFF ) begin
  5923. if ( (bits64) ( ( aSig or bSig ) shl 1 ) ) begin
  5924. result := propagateFloatx80NaN( a, b );
  5925. end;
  5926. result := a;
  5927. end;
  5928. zSig1 := 0;
  5929. zSig0 := aSig + bSig;
  5930. if ( aExp = 0 ) begin
  5931. normalizeFloatx80Subnormal( zSig0, zExp, zSig0 );
  5932. goto roundAndPack;
  5933. end;
  5934. zExp := aExp;
  5935. goto shiftRight1;
  5936. end;
  5937. zSig0 := aSig + bSig;
  5938. if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
  5939. shiftRight1:
  5940. shift64ExtraRightJamming( zSig0, zSig1, 1, zSig0, zSig1 );
  5941. zSig0 or= LIT64( $8000000000000000 );
  5942. ++zExp;
  5943. roundAndPack:
  5944. result :=
  5945. roundAndPackFloatx80(
  5946. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  5947. end;
  5948. {*----------------------------------------------------------------------------
  5949. | Returns the result of subtracting the absolute values of the extended
  5950. | double-precision floating-point values `a' and `b'. If `zSign' is 1, the
  5951. | difference is negated before being returned. `zSign' is ignored if the
  5952. | result is a NaN. The subtraction is performed according to the IEC/IEEE
  5953. | Standard for Binary Floating-Point Arithmetic.
  5954. *----------------------------------------------------------------------------*}
  5955. function subFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
  5956. var
  5957. aExp, bExp, zExp: int32;
  5958. aSig, bSig, zSig0, zSig1: bits64;
  5959. expDiff: int32;
  5960. z: floatx80;
  5961. begin
  5962. aSig := extractFloatx80Frac( a );
  5963. aExp := extractFloatx80Exp( a );
  5964. bSig := extractFloatx80Frac( b );
  5965. bExp := extractFloatx80Exp( b );
  5966. expDiff := aExp - bExp;
  5967. if ( 0 < expDiff ) goto aExpBigger;
  5968. if ( expDiff < 0 ) goto bExpBigger;
  5969. if ( aExp = $7FFF ) begin
  5970. if ( (bits64) ( ( aSig or bSig ) shl 1 ) ) begin
  5971. result := propagateFloatx80NaN( a, b );
  5972. end;
  5973. float_raise( float_flag_invalid );
  5974. z.low := floatx80_default_nan_low;
  5975. z.high := floatx80_default_nan_high;
  5976. result := z;
  5977. end;
  5978. if ( aExp = 0 ) begin
  5979. aExp := 1;
  5980. bExp := 1;
  5981. end;
  5982. zSig1 := 0;
  5983. if ( bSig < aSig ) goto aBigger;
  5984. if ( aSig < bSig ) goto bBigger;
  5985. result := packFloatx80( softfloat_rounding_mode = float_round_down, 0, 0 );
  5986. bExpBigger:
  5987. if ( bExp = $7FFF ) begin
  5988. if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  5989. result := packFloatx80( zSign xor 1, $7FFF, LIT64( $8000000000000000 ) );
  5990. end;
  5991. if ( aExp = 0 ) ++expDiff;
  5992. shift128RightJamming( aSig, 0, - expDiff, aSig, zSig1 );
  5993. bBigger:
  5994. sub128( bSig, 0, aSig, zSig1, zSig0, zSig1 );
  5995. zExp := bExp;
  5996. zSign xor = 1;
  5997. goto normalizeRoundAndPack;
  5998. aExpBigger:
  5999. if ( aExp = $7FFF ) begin
  6000. if ( (bits64) ( aSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  6001. result := a;
  6002. end;
  6003. if ( bExp = 0 ) --expDiff;
  6004. shift128RightJamming( bSig, 0, expDiff, bSig, zSig1 );
  6005. aBigger:
  6006. sub128( aSig, 0, bSig, zSig1, zSig0, zSig1 );
  6007. zExp := aExp;
  6008. normalizeRoundAndPack:
  6009. result :=
  6010. normalizeRoundAndPackFloatx80(
  6011. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6012. end;
  6013. {*----------------------------------------------------------------------------
  6014. | Returns the result of adding the extended double-precision floating-point
  6015. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  6016. | Standard for Binary Floating-Point Arithmetic.
  6017. *----------------------------------------------------------------------------*}
  6018. function floatx80_add(a: floatx80; b: floatx80): floatx80;
  6019. var
  6020. aSign, bSign: flag;
  6021. begin
  6022. aSign := extractFloatx80Sign( a );
  6023. bSign := extractFloatx80Sign( b );
  6024. if ( aSign = bSign ) begin
  6025. result := addFloatx80Sigs( a, b, aSign );
  6026. end;
  6027. else begin
  6028. result := subFloatx80Sigs( a, b, aSign );
  6029. end;
  6030. end;
  6031. {*----------------------------------------------------------------------------
  6032. | Returns the result of subtracting the extended double-precision floating-
  6033. | point values `a' and `b'. The operation is performed according to the
  6034. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6035. *----------------------------------------------------------------------------*}
  6036. function floatx80_sub(a: floatx80; b: floatx80 ): floatx80;
  6037. var
  6038. aSign, bSign: flag;
  6039. begin
  6040. aSign := extractFloatx80Sign( a );
  6041. bSign := extractFloatx80Sign( b );
  6042. if ( aSign = bSign ) begin
  6043. result := subFloatx80Sigs( a, b, aSign );
  6044. end;
  6045. else begin
  6046. result := addFloatx80Sigs( a, b, aSign );
  6047. end;
  6048. end;
  6049. {*----------------------------------------------------------------------------
  6050. | Returns the result of multiplying the extended double-precision floating-
  6051. | point values `a' and `b'. The operation is performed according to the
  6052. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6053. *----------------------------------------------------------------------------*}
  6054. function floatx80_mul(a: floatx80; b: floatx80): floatx80;
  6055. var
  6056. aSign, bSign, zSign: flag;
  6057. aExp, bExp, zExp: int32;
  6058. aSig, bSig, zSig0, zSig1: bits64;
  6059. z: floatx80;
  6060. begin
  6061. aSig := extractFloatx80Frac( a );
  6062. aExp := extractFloatx80Exp( a );
  6063. aSign := extractFloatx80Sign( a );
  6064. bSig := extractFloatx80Frac( b );
  6065. bExp := extractFloatx80Exp( b );
  6066. bSign := extractFloatx80Sign( b );
  6067. zSign := aSign xor bSign;
  6068. if ( aExp = $7FFF ) begin
  6069. if ( (bits64) ( aSig shl 1 )
  6070. or ( ( bExp = $7FFF ) and (bits64) ( bSig shl 1 ) ) ) begin
  6071. result := propagateFloatx80NaN( a, b );
  6072. end;
  6073. if ( ( bExp or bSig ) = 0 ) goto invalid;
  6074. result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
  6075. end;
  6076. if ( bExp = $7FFF ) begin
  6077. if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  6078. if ( ( aExp or aSig ) = 0 ) begin
  6079. invalid:
  6080. float_raise( float_flag_invalid );
  6081. z.low := floatx80_default_nan_low;
  6082. z.high := floatx80_default_nan_high;
  6083. result := z;
  6084. end;
  6085. result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
  6086. end;
  6087. if ( aExp = 0 ) begin
  6088. if ( aSig = 0 ) result := packFloatx80( zSign, 0, 0 );
  6089. normalizeFloatx80Subnormal( aSig, aExp, aSig );
  6090. end;
  6091. if ( bExp = 0 ) begin
  6092. if ( bSig = 0 ) result := packFloatx80( zSign, 0, 0 );
  6093. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6094. end;
  6095. zExp := aExp + bExp - $3FFE;
  6096. mul64To128( aSig, bSig, zSig0, zSig1 );
  6097. if ( 0 < (sbits64) zSig0 ) begin
  6098. shortShift128Left( zSig0, zSig1, 1, zSig0, zSig1 );
  6099. --zExp;
  6100. end;
  6101. result :=
  6102. roundAndPackFloatx80(
  6103. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6104. end;
  6105. {*----------------------------------------------------------------------------
  6106. | Returns the result of dividing the extended double-precision floating-point
  6107. | value `a' by the corresponding value `b'. The operation is performed
  6108. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6109. *----------------------------------------------------------------------------*}
  6110. function floatx80_div(a: floatx80; b: floatx80 ): floatx80;
  6111. var
  6112. aSign, bSign, zSign: flag;
  6113. aExp, bExp, zExp: int32;
  6114. aSig, bSig, zSig0, zSig1: bits64;
  6115. rem0, rem1, rem2, term0, term1, term2: bits64;
  6116. z: floatx80;
  6117. begin
  6118. aSig := extractFloatx80Frac( a );
  6119. aExp := extractFloatx80Exp( a );
  6120. aSign := extractFloatx80Sign( a );
  6121. bSig := extractFloatx80Frac( b );
  6122. bExp := extractFloatx80Exp( b );
  6123. bSign := extractFloatx80Sign( b );
  6124. zSign := aSign xor bSign;
  6125. if ( aExp = $7FFF ) begin
  6126. if ( (bits64) ( aSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  6127. if ( bExp = $7FFF ) begin
  6128. if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  6129. goto invalid;
  6130. end;
  6131. result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
  6132. end;
  6133. if ( bExp = $7FFF ) begin
  6134. if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  6135. result := packFloatx80( zSign, 0, 0 );
  6136. end;
  6137. if ( bExp = 0 ) begin
  6138. if ( bSig = 0 ) begin
  6139. if ( ( aExp or aSig ) = 0 ) begin
  6140. invalid:
  6141. float_raise( float_flag_invalid );
  6142. z.low := floatx80_default_nan_low;
  6143. z.high := floatx80_default_nan_high;
  6144. result := z;
  6145. end;
  6146. float_raise( float_flag_divbyzero );
  6147. result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
  6148. end;
  6149. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6150. end;
  6151. if ( aExp = 0 ) begin
  6152. if ( aSig = 0 ) result := packFloatx80( zSign, 0, 0 );
  6153. normalizeFloatx80Subnormal( aSig, aExp, aSig );
  6154. end;
  6155. zExp := aExp - bExp + $3FFE;
  6156. rem1 := 0;
  6157. if ( bSig <= aSig ) begin
  6158. shift128Right( aSig, 0, 1, aSig, rem1 );
  6159. ++zExp;
  6160. end;
  6161. zSig0 := estimateDiv128To64( aSig, rem1, bSig );
  6162. mul64To128( bSig, zSig0, term0, term1 );
  6163. sub128( aSig, rem1, term0, term1, rem0, rem1 );
  6164. while ( (sbits64) rem0 < 0 ) begin
  6165. --zSig0;
  6166. add128( rem0, rem1, 0, bSig, rem0, rem1 );
  6167. end;
  6168. zSig1 := estimateDiv128To64( rem1, 0, bSig );
  6169. if ( (bits64) ( zSig1 shl 1 ) <= 8 ) begin
  6170. mul64To128( bSig, zSig1, term1, term2 );
  6171. sub128( rem1, 0, term1, term2, rem1, rem2 );
  6172. while ( (sbits64) rem1 < 0 ) begin
  6173. --zSig1;
  6174. add128( rem1, rem2, 0, bSig, rem1, rem2 );
  6175. end;
  6176. zSig1 or= ( ( rem1 or rem2 ) <> 0 );
  6177. end;
  6178. result :=
  6179. roundAndPackFloatx80(
  6180. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6181. end;
  6182. {*----------------------------------------------------------------------------
  6183. | Returns the remainder of the extended double-precision floating-point value
  6184. | `a' with respect to the corresponding value `b'. The operation is performed
  6185. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6186. *----------------------------------------------------------------------------*}
  6187. function floatx80_rem(a: floatx80; b: floatx80 ): floatx80;
  6188. var
  6189. aSign, bSign, zSign: flag;
  6190. aExp, bExp, expDiff: int32;
  6191. aSig0, aSig1, bSig: bits64;
  6192. q, term0, term1, alternateASig0, alternateASig1: bits64;
  6193. z: floatx80;
  6194. begin
  6195. aSig0 := extractFloatx80Frac( a );
  6196. aExp := extractFloatx80Exp( a );
  6197. aSign := extractFloatx80Sign( a );
  6198. bSig := extractFloatx80Frac( b );
  6199. bExp := extractFloatx80Exp( b );
  6200. bSign := extractFloatx80Sign( b );
  6201. if ( aExp = $7FFF ) begin
  6202. if ( (bits64) ( aSig0 shl 1 )
  6203. or ( ( bExp = $7FFF ) and (bits64) ( bSig shl 1 ) ) ) begin
  6204. result := propagateFloatx80NaN( a, b );
  6205. end;
  6206. goto invalid;
  6207. end;
  6208. if ( bExp = $7FFF ) begin
  6209. if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
  6210. result := a;
  6211. end;
  6212. if ( bExp = 0 ) begin
  6213. if ( bSig = 0 ) begin
  6214. invalid:
  6215. float_raise( float_flag_invalid );
  6216. z.low := floatx80_default_nan_low;
  6217. z.high := floatx80_default_nan_high;
  6218. result := z;
  6219. end;
  6220. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6221. end;
  6222. if ( aExp = 0 ) begin
  6223. if ( (bits64) ( aSig0 shl 1 ) = 0 ) result := a;
  6224. normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );
  6225. end;
  6226. bSig or= LIT64( $8000000000000000 );
  6227. zSign := aSign;
  6228. expDiff := aExp - bExp;
  6229. aSig1 := 0;
  6230. if ( expDiff < 0 ) begin
  6231. if ( expDiff < -1 ) result := a;
  6232. shift128Right( aSig0, 0, 1, aSig0, aSig1 );
  6233. expDiff := 0;
  6234. end;
  6235. q := ( bSig <= aSig0 );
  6236. if ( q ) aSig0 -= bSig;
  6237. expDiff -= 64;
  6238. while ( 0 < expDiff ) begin
  6239. q := estimateDiv128To64( aSig0, aSig1, bSig );
  6240. q := ( 2 < q ) ? q - 2 : 0;
  6241. mul64To128( bSig, q, term0, term1 );
  6242. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  6243. shortShift128Left( aSig0, aSig1, 62, aSig0, aSig1 );
  6244. expDiff -= 62;
  6245. end;
  6246. expDiff += 64;
  6247. if ( 0 < expDiff ) begin
  6248. q := estimateDiv128To64( aSig0, aSig1, bSig );
  6249. q := ( 2 < q ) ? q - 2 : 0;
  6250. q >>= 64 - expDiff;
  6251. mul64To128( bSig, q shl ( 64 - expDiff ), term0, term1 );
  6252. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  6253. shortShift128Left( 0, bSig, 64 - expDiff, term0, term1 );
  6254. while ( le128( term0, term1, aSig0, aSig1 ) ) begin
  6255. ++q;
  6256. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  6257. end;
  6258. end;
  6259. else begin
  6260. term1 := 0;
  6261. term0 := bSig;
  6262. end;
  6263. sub128( term0, term1, aSig0, aSig1, alternateASig0, alternateASig1 );
  6264. if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
  6265. or ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
  6266. and ( q and 1 ) )
  6267. ) begin
  6268. aSig0 := alternateASig0;
  6269. aSig1 := alternateASig1;
  6270. zSign := ! zSign;
  6271. end;
  6272. result :=
  6273. normalizeRoundAndPackFloatx80(
  6274. 80, zSign, bExp + expDiff, aSig0, aSig1 );
  6275. end;
  6276. {*----------------------------------------------------------------------------
  6277. | Returns the square root of the extended double-precision floating-point
  6278. | value `a'. The operation is performed according to the IEC/IEEE Standard
  6279. | for Binary Floating-Point Arithmetic.
  6280. *----------------------------------------------------------------------------*}
  6281. function floatx80_sqrt(a: floatx80): floatx80;
  6282. var
  6283. aSign: flag;
  6284. aExp, zExp: int32;
  6285. aSig0, aSig1, zSig0, zSig1, doubleZSig0: bits64;
  6286. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  6287. z: floatx80;
  6288. label
  6289. invalid;
  6290. begin
  6291. aSig0 := extractFloatx80Frac( a );
  6292. aExp := extractFloatx80Exp( a );
  6293. aSign := extractFloatx80Sign( a );
  6294. if ( aExp = $7FFF ) begin
  6295. if ( (bits64) ( aSig0 shl 1 ) ) result := propagateFloatx80NaN( a, a );
  6296. if ( ! aSign ) result := a;
  6297. goto invalid;
  6298. end;
  6299. if ( aSign ) begin
  6300. if ( ( aExp or aSig0 ) = 0 ) result := a;
  6301. invalid:
  6302. float_raise( float_flag_invalid );
  6303. z.low := floatx80_default_nan_low;
  6304. z.high := floatx80_default_nan_high;
  6305. result := z;
  6306. end;
  6307. if ( aExp = 0 ) begin
  6308. if ( aSig0 = 0 ) result := packFloatx80( 0, 0, 0 );
  6309. normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );
  6310. end;
  6311. zExp := ( ( aExp - $3FFF )>>1 ) + $3FFF;
  6312. zSig0 := estimateSqrt32( aExp, aSig0>>32 );
  6313. shift128Right( aSig0, 0, 2 + ( aExp and 1 ), aSig0, aSig1 );
  6314. zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
  6315. doubleZSig0 := zSig0 shl 1;
  6316. mul64To128( zSig0, zSig0, term0, term1 );
  6317. sub128( aSig0, aSig1, term0, term1, rem0, rem1 );
  6318. while ( (sbits64) rem0 < 0 ) begin
  6319. --zSig0;
  6320. doubleZSig0 -= 2;
  6321. add128( rem0, rem1, zSig0>>63, doubleZSig0 or 1, rem0, rem1 );
  6322. end;
  6323. zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
  6324. if ( ( zSig1 and LIT64( $3FFFFFFFFFFFFFFF ) ) <= 5 ) begin
  6325. if ( zSig1 = 0 ) zSig1 := 1;
  6326. mul64To128( doubleZSig0, zSig1, term1, term2 );
  6327. sub128( rem1, 0, term1, term2, rem1, rem2 );
  6328. mul64To128( zSig1, zSig1, term2, term3 );
  6329. sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  6330. while ( (sbits64) rem1 < 0 ) begin
  6331. --zSig1;
  6332. shortShift128Left( 0, zSig1, 1, term2, term3 );
  6333. term3 or= 1;
  6334. term2 or= doubleZSig0;
  6335. add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  6336. end;
  6337. zSig1 or= ( ( rem1 or rem2 or rem3 ) <> 0 );
  6338. end;
  6339. shortShift128Left( 0, zSig1, 1, zSig0, zSig1 );
  6340. zSig0 or= doubleZSig0;
  6341. result :=
  6342. roundAndPackFloatx80(
  6343. floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
  6344. end;
  6345. {*----------------------------------------------------------------------------
  6346. | Returns 1 if the extended double-precision floating-point value `a' is
  6347. | equal to the corresponding value `b', and 0 otherwise. The comparison is
  6348. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  6349. | Arithmetic.
  6350. *----------------------------------------------------------------------------*}
  6351. function floatx80_eq(a: floatx80; b: floatx80 ): flag;
  6352. begin
  6353. if ( ( ( extractFloatx80Exp( a ) = $7FFF )
  6354. and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
  6355. or ( ( extractFloatx80Exp( b ) = $7FFF )
  6356. and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
  6357. ) begin
  6358. if ( floatx80_is_signaling_nan( a )
  6359. or floatx80_is_signaling_nan( b ) ) begin
  6360. float_raise( float_flag_invalid );
  6361. end;
  6362. result := 0;
  6363. end;
  6364. result :=
  6365. ( a.low = b.low )
  6366. and ( ( a.high = b.high )
  6367. or ( ( a.low = 0 )
  6368. and ( (bits16) ( ( a.high or b.high ) shl 1 ) = 0 ) )
  6369. );
  6370. end;
  6371. {*----------------------------------------------------------------------------
  6372. | Returns 1 if the extended double-precision floating-point value `a' is
  6373. | less than or equal to the corresponding value `b', and 0 otherwise. The
  6374. | comparison is performed according to the IEC/IEEE Standard for Binary
  6375. | Floating-Point Arithmetic.
  6376. *----------------------------------------------------------------------------*}
  6377. function floatx80_le(a: floatx80; b: floatx80 ): flag;
  6378. var
  6379. aSign, bSign: flag;
  6380. begin
  6381. if ( ( ( extractFloatx80Exp( a ) = $7FFF )
  6382. and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
  6383. or ( ( extractFloatx80Exp( b ) = $7FFF )
  6384. and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
  6385. ) begin
  6386. float_raise( float_flag_invalid );
  6387. result := 0;
  6388. end;
  6389. aSign := extractFloatx80Sign( a );
  6390. bSign := extractFloatx80Sign( b );
  6391. if ( aSign <> bSign ) begin
  6392. result :=
  6393. aSign
  6394. or ( ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  6395. = 0 );
  6396. end;
  6397. result :=
  6398. aSign ? le128( b.high, b.low, a.high, a.low )
  6399. : le128( a.high, a.low, b.high, b.low );
  6400. end;
  6401. {*----------------------------------------------------------------------------
  6402. | Returns 1 if the extended double-precision floating-point value `a' is
  6403. | less than the corresponding value `b', and 0 otherwise. The comparison
  6404. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  6405. | Arithmetic.
  6406. *----------------------------------------------------------------------------*}
  6407. function floatx80_lt(a: floatx80; b: floatx80 ): flag;
  6408. var
  6409. aSign, bSign: flag;
  6410. begin
  6411. if ( ( ( extractFloatx80Exp( a ) = $7FFF )
  6412. and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
  6413. or ( ( extractFloatx80Exp( b ) = $7FFF )
  6414. and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
  6415. ) begin
  6416. float_raise( float_flag_invalid );
  6417. result := 0;
  6418. end;
  6419. aSign := extractFloatx80Sign( a );
  6420. bSign := extractFloatx80Sign( b );
  6421. if ( aSign <> bSign ) begin
  6422. result :=
  6423. aSign
  6424. and ( ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  6425. <> 0 );
  6426. end;
  6427. result :=
  6428. aSign ? lt128( b.high, b.low, a.high, a.low )
  6429. : lt128( a.high, a.low, b.high, b.low );
  6430. end;
  6431. {*----------------------------------------------------------------------------
  6432. | Returns 1 if the extended double-precision floating-point value `a' is equal
  6433. | to the corresponding value `b', and 0 otherwise. The invalid exception is
  6434. | raised if either operand is a NaN. Otherwise, the comparison is performed
  6435. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6436. *----------------------------------------------------------------------------*}
  6437. function floatx80_eq_signaling(a: floatx80; b: floatx80 ): flag;
  6438. begin
  6439. if ( ( ( extractFloatx80Exp( a ) = $7FFF )
  6440. and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
  6441. or ( ( extractFloatx80Exp( b ) = $7FFF )
  6442. and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
  6443. ) begin
  6444. float_raise( float_flag_invalid );
  6445. result := 0;
  6446. end;
  6447. result :=
  6448. ( a.low = b.low )
  6449. and ( ( a.high = b.high )
  6450. or ( ( a.low = 0 )
  6451. and ( (bits16) ( ( a.high or b.high ) shl 1 ) = 0 ) )
  6452. );
  6453. end;
  6454. {*----------------------------------------------------------------------------
  6455. | Returns 1 if the extended double-precision floating-point value `a' is less
  6456. | than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
  6457. | do not cause an exception. Otherwise, the comparison is performed according
  6458. | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6459. *----------------------------------------------------------------------------*}
  6460. function floatx80_le_quiet(a: floatx80; b: floatx80 ): flag;
  6461. var
  6462. aSign, bSign: flag;
  6463. begin
  6464. if ( ( ( extractFloatx80Exp( a ) = $7FFF )
  6465. and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
  6466. or ( ( extractFloatx80Exp( b ) = $7FFF )
  6467. and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
  6468. ) begin
  6469. if ( floatx80_is_signaling_nan( a )
  6470. or floatx80_is_signaling_nan( b ) ) begin
  6471. float_raise( float_flag_invalid );
  6472. end;
  6473. result := 0;
  6474. end;
  6475. aSign := extractFloatx80Sign( a );
  6476. bSign := extractFloatx80Sign( b );
  6477. if ( aSign <> bSign ) begin
  6478. result :=
  6479. aSign
  6480. or ( ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  6481. = 0 );
  6482. end;
  6483. result :=
  6484. aSign ? le128( b.high, b.low, a.high, a.low )
  6485. : le128( a.high, a.low, b.high, b.low );
  6486. end;
  6487. {*----------------------------------------------------------------------------
  6488. | Returns 1 if the extended double-precision floating-point value `a' is less
  6489. | than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
  6490. | an exception. Otherwise, the comparison is performed according to the
  6491. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6492. *----------------------------------------------------------------------------*}
  6493. function floatx80_lt_quiet(a: floatx80; b: floatx80 ): flag;
  6494. var
  6495. aSign, bSign: flag;
  6496. begin
  6497. if ( ( ( extractFloatx80Exp( a ) = $7FFF )
  6498. and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
  6499. or ( ( extractFloatx80Exp( b ) = $7FFF )
  6500. and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
  6501. ) begin
  6502. if ( floatx80_is_signaling_nan( a )
  6503. or floatx80_is_signaling_nan( b ) ) begin
  6504. float_raise( float_flag_invalid );
  6505. end;
  6506. result := 0;
  6507. end;
  6508. aSign := extractFloatx80Sign( a );
  6509. bSign := extractFloatx80Sign( b );
  6510. if ( aSign <> bSign ) begin
  6511. result :=
  6512. aSign
  6513. and ( ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  6514. <> 0 );
  6515. end;
  6516. result :=
  6517. aSign ? lt128( b.high, b.low, a.high, a.low )
  6518. : lt128( a.high, a.low, b.high, b.low );
  6519. end;
  6520. {$endif FPC_SOFTFLOAT_FLOATX80}
  6521. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  6522. {*----------------------------------------------------------------------------
  6523. | Returns the least-significant 64 fraction bits of the quadruple-precision
  6524. | floating-point value `a'.
  6525. *----------------------------------------------------------------------------*}
  6526. function extractFloat128Frac1(a : float128): bits64;
  6527. begin
  6528. result:=a.low;
  6529. end;
  6530. {*----------------------------------------------------------------------------
  6531. | Returns the most-significant 48 fraction bits of the quadruple-precision
  6532. | floating-point value `a'.
  6533. *----------------------------------------------------------------------------*}
  6534. function extractFloat128Frac0(a : float128): bits64;
  6535. begin
  6536. result:=a.high and int64($0000FFFFFFFFFFFF);
  6537. end;
  6538. {*----------------------------------------------------------------------------
  6539. | Returns the exponent bits of the quadruple-precision floating-point value
  6540. | `a'.
  6541. *----------------------------------------------------------------------------*}
  6542. function extractFloat128Exp(a : float128): int32;
  6543. begin
  6544. result:=( a.high shr 48 ) and $7FFF;
  6545. end;
  6546. {*----------------------------------------------------------------------------
  6547. | Returns the sign bit of the quadruple-precision floating-point value `a'.
  6548. *----------------------------------------------------------------------------*}
  6549. function extractFloat128Sign(a : float128): flag;
  6550. begin
  6551. result:=a.high shr 63;
  6552. end;
  6553. {*----------------------------------------------------------------------------
  6554. | Normalizes the subnormal quadruple-precision floating-point value
  6555. | represented by the denormalized significand formed by the concatenation of
  6556. | `aSig0' and `aSig1'. The normalized exponent is stored at the location
  6557. | pointed to by `zExpPtr'. The most significant 49 bits of the normalized
  6558. | significand are stored at the location pointed to by `zSig0Ptr', and the
  6559. | least significant 64 bits of the normalized significand are stored at the
  6560. | location pointed to by `zSig1Ptr'.
  6561. *----------------------------------------------------------------------------*}
  6562. procedure normalizeFloat128Subnormal(
  6563. aSig0: bits64;
  6564. aSig1: bits64;
  6565. var zExpPtr: int32;
  6566. var zSig0Ptr: bits64;
  6567. var zSig1Ptr: bits64);
  6568. var
  6569. shiftCount: int8;
  6570. begin
  6571. if ( aSig0 = 0 ) then
  6572. begin
  6573. shiftCount := countLeadingZeros64( aSig1 ) - 15;
  6574. if ( shiftCount < 0 ) then
  6575. begin
  6576. zSig0Ptr := aSig1 shr ( - shiftCount );
  6577. zSig1Ptr := aSig1 shl ( shiftCount and 63 );
  6578. end
  6579. else begin
  6580. zSig0Ptr := aSig1 shl shiftCount;
  6581. zSig1Ptr := 0;
  6582. end;
  6583. zExpPtr := - shiftCount - 63;
  6584. end
  6585. else begin
  6586. shiftCount := countLeadingZeros64( aSig0 ) - 15;
  6587. shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
  6588. zExpPtr := 1 - shiftCount;
  6589. end;
  6590. end;
  6591. {*----------------------------------------------------------------------------
  6592. | Packs the sign `zSign', the exponent `zExp', and the significand formed
  6593. | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
  6594. | floating-point value, returning the result. After being shifted into the
  6595. | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
  6596. | added together to form the most significant 32 bits of the result. This
  6597. | means that any integer portion of `zSig0' will be added into the exponent.
  6598. | Since a properly normalized significand will have an integer portion equal
  6599. | to 1, the `zExp' input should be 1 less than the desired result exponent
  6600. | whenever `zSig0' and `zSig1' concatenated form a complete, normalized
  6601. | significand.
  6602. *----------------------------------------------------------------------------*}
  6603. function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64) : float128;
  6604. var
  6605. z: float128;
  6606. begin
  6607. z.low := zSig1;
  6608. z.high := ( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 48 ) + zSig0;
  6609. result:=z;
  6610. end;
  6611. {*----------------------------------------------------------------------------
  6612. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  6613. | and extended significand formed by the concatenation of `zSig0', `zSig1',
  6614. | and `zSig2', and returns the proper quadruple-precision floating-point value
  6615. | corresponding to the abstract input. Ordinarily, the abstract value is
  6616. | simply rounded and packed into the quadruple-precision format, with the
  6617. | inexact exception raised if the abstract input cannot be represented
  6618. | exactly. However, if the abstract value is too large, the overflow and
  6619. | inexact exceptions are raised and an infinity or maximal finite value is
  6620. | returned. If the abstract value is too small, the input value is rounded to
  6621. | a subnormal number, and the underflow and inexact exceptions are raised if
  6622. | the abstract input cannot be represented exactly as a subnormal quadruple-
  6623. | precision floating-point number.
  6624. | The input significand must be normalized or smaller. If the input
  6625. | significand is not normalized, `zExp' must be 0; in that case, the result
  6626. | returned is a subnormal number, and it must not require rounding. In the
  6627. | usual case that the input significand is normalized, `zExp' must be 1 less
  6628. | than the ``true'' floating-point exponent. The handling of underflow and
  6629. | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6630. *----------------------------------------------------------------------------*}
  6631. function roundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64; zSig2: bits64): float128;
  6632. var
  6633. roundingMode: int8;
  6634. roundNearestEven, increment, isTiny: flag;
  6635. begin
  6636. roundingMode := softfloat_rounding_mode;
  6637. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  6638. increment := ord( sbits64(zSig2) < 0 );
  6639. if ( roundNearestEven=0 ) then
  6640. begin
  6641. if ( roundingMode = float_round_to_zero ) then
  6642. begin
  6643. increment := 0;
  6644. end
  6645. else begin
  6646. if ( zSign<>0 ) then
  6647. begin
  6648. increment := ord( roundingMode = float_round_down ) and zSig2;
  6649. end
  6650. else begin
  6651. increment := ord( roundingMode = float_round_up ) and zSig2;
  6652. end;
  6653. end;
  6654. end;
  6655. if ( $7FFD <= bits32(zExp) ) then
  6656. begin
  6657. if ( ord( $7FFD < zExp )
  6658. or ( ord( zExp = $7FFD )
  6659. and eq128(
  6660. int64( $0001FFFFFFFFFFFF ),
  6661. int64( $FFFFFFFFFFFFFFFF ),
  6662. zSig0,
  6663. zSig1
  6664. )
  6665. and increment
  6666. )
  6667. )<>0 then
  6668. begin
  6669. float_raise( float_flag_overflow or float_flag_inexact );
  6670. if ( ord( roundingMode = float_round_to_zero )
  6671. or ( zSign and ord( roundingMode = float_round_up ) )
  6672. or ( not(zSign) and ord( roundingMode = float_round_down ) )
  6673. )<>0 then
  6674. begin
  6675. result :=
  6676. packFloat128(
  6677. zSign,
  6678. $7FFE,
  6679. int64( $0000FFFFFFFFFFFF ),
  6680. int64( $FFFFFFFFFFFFFFFF )
  6681. );
  6682. end;
  6683. result:=packFloat128( zSign, $7FFF, 0, 0 );
  6684. end;
  6685. if ( zExp < 0 ) then
  6686. begin
  6687. isTiny :=
  6688. ord(( float_detect_tininess = float_tininess_before_rounding )
  6689. or ( zExp < -1 )
  6690. or not( increment<>0 )
  6691. or boolean(lt128(
  6692. zSig0,
  6693. zSig1,
  6694. int64( $0001FFFFFFFFFFFF ),
  6695. int64( $FFFFFFFFFFFFFFFF )
  6696. )));
  6697. shift128ExtraRightJamming(
  6698. zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
  6699. zExp := 0;
  6700. if ( isTiny and zSig2 )<>0 then
  6701. float_raise( float_flag_underflow );
  6702. if ( roundNearestEven<>0 ) then
  6703. begin
  6704. increment := ord( sbits64(zSig2) < 0 );
  6705. end
  6706. else begin
  6707. if ( zSign<>0 ) then
  6708. begin
  6709. increment := ord( roundingMode = float_round_down ) and zSig2;
  6710. end
  6711. else begin
  6712. increment := ord( roundingMode = float_round_up ) and zSig2;
  6713. end;
  6714. end;
  6715. end;
  6716. end;
  6717. if ( zSig2<>0 ) then
  6718. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  6719. if ( increment<>0 ) then
  6720. begin
  6721. add128( zSig0, zSig1, 0, 1, zSig0, zSig1 );
  6722. zSig1 := zSig1 and not( ord( zSig2 + zSig2 = 0 ) and roundNearestEven );
  6723. end
  6724. else begin
  6725. if ( ( zSig0 or zSig1 ) = 0 ) then
  6726. zExp := 0;
  6727. end;
  6728. result:=packFloat128( zSign, zExp, zSig0, zSig1 );
  6729. end;
  6730. {*----------------------------------------------------------------------------
  6731. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  6732. | and significand formed by the concatenation of `zSig0' and `zSig1', and
  6733. | returns the proper quadruple-precision floating-point value corresponding
  6734. | to the abstract input. This routine is just like `roundAndPackFloat128'
  6735. | except that the input significand has fewer bits and does not have to be
  6736. | normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
  6737. | point exponent.
  6738. *----------------------------------------------------------------------------*}
  6739. function normalizeRoundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): float128;
  6740. var
  6741. shiftCount: int8;
  6742. zSig2: bits64;
  6743. begin
  6744. if ( zSig0 = 0 ) then
  6745. begin
  6746. zSig0 := zSig1;
  6747. zSig1 := 0;
  6748. dec(zExp, 64);
  6749. end;
  6750. shiftCount := countLeadingZeros64( zSig0 ) - 15;
  6751. if ( 0 <= shiftCount ) then
  6752. begin
  6753. zSig2 := 0;
  6754. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  6755. end
  6756. else begin
  6757. shift128ExtraRightJamming(
  6758. zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
  6759. end;
  6760. dec(zExp, shiftCount);
  6761. result:=roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  6762. end;
  6763. {*----------------------------------------------------------------------------
  6764. | Returns the result of converting the quadruple-precision floating-point
  6765. | value `a' to the 32-bit two's complement integer format. The conversion
  6766. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  6767. | Arithmetic---which means in particular that the conversion is rounded
  6768. | according to the current rounding mode. If `a' is a NaN, the largest
  6769. | positive integer is returned. Otherwise, if the conversion overflows, the
  6770. | largest integer with the same sign as `a' is returned.
  6771. *----------------------------------------------------------------------------*}
  6772. function float128_to_int32(a: float128): int32;
  6773. var
  6774. aSign: flag;
  6775. aExp, shiftCount: int32;
  6776. aSig0, aSig1: bits64;
  6777. begin
  6778. aSig1 := extractFloat128Frac1( a );
  6779. aSig0 := extractFloat128Frac0( a );
  6780. aExp := extractFloat128Exp( a );
  6781. aSign := extractFloat128Sign( a );
  6782. if ( ord( aExp = $7FFF ) and ( aSig0 or aSig1 ) )<>0 then
  6783. aSign := 0;
  6784. if ( aExp<>0 ) then
  6785. aSig0 := aSig0 or int64( $0001000000000000 );
  6786. aSig0 := aSig0 or ord( aSig1 <> 0 );
  6787. shiftCount := $4028 - aExp;
  6788. if ( 0 < shiftCount ) then
  6789. shift64RightJamming( aSig0, shiftCount, aSig0 );
  6790. result := roundAndPackInt32( aSign, aSig0 );
  6791. end;
  6792. {*----------------------------------------------------------------------------
  6793. | Returns the result of converting the quadruple-precision floating-point
  6794. | value `a' to the 32-bit two's complement integer format. The conversion
  6795. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  6796. | Arithmetic, except that the conversion is always rounded toward zero. If
  6797. | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
  6798. | conversion overflows, the largest integer with the same sign as `a' is
  6799. | returned.
  6800. *----------------------------------------------------------------------------*}
  6801. function float128_to_int32_round_to_zero(a: float128): int32;
  6802. var
  6803. aSign: flag;
  6804. aExp, shiftCount: int32;
  6805. aSig0, aSig1, savedASig: bits64;
  6806. z: int32;
  6807. label
  6808. invalid;
  6809. begin
  6810. aSig1 := extractFloat128Frac1( a );
  6811. aSig0 := extractFloat128Frac0( a );
  6812. aExp := extractFloat128Exp( a );
  6813. aSign := extractFloat128Sign( a );
  6814. aSig0 := aSig0 or ord( aSig1 <> 0 );
  6815. if ( $401E < aExp ) then
  6816. begin
  6817. if ( ord( aExp = $7FFF ) and aSig0 )<>0 then
  6818. aSign := 0;
  6819. goto invalid;
  6820. end
  6821. else if ( aExp < $3FFF ) then
  6822. begin
  6823. if ( aExp or aSig0 )<>0 then
  6824. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  6825. result := 0;
  6826. exit;
  6827. end;
  6828. aSig0 := aSig0 or int64( $0001000000000000 );
  6829. shiftCount := $402F - aExp;
  6830. savedASig := aSig0;
  6831. aSig0 := aSig0 shr shiftCount;
  6832. z := aSig0;
  6833. if ( aSign )<>0 then
  6834. z := - z;
  6835. if ( ord( z < 0 ) xor aSign )<>0 then
  6836. begin
  6837. invalid:
  6838. float_raise( float_flag_invalid );
  6839. if aSign<>0 then
  6840. result:=$80000000
  6841. else
  6842. result:=$7FFFFFFF;
  6843. exit;
  6844. end;
  6845. if ( ( aSig0 shl shiftCount ) <> savedASig ) then
  6846. begin
  6847. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  6848. end;
  6849. result := z;
  6850. end;
  6851. {*----------------------------------------------------------------------------
  6852. | Returns the result of converting the quadruple-precision floating-point
  6853. | value `a' to the 64-bit two's complement integer format. The conversion
  6854. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  6855. | Arithmetic---which means in particular that the conversion is rounded
  6856. | according to the current rounding mode. If `a' is a NaN, the largest
  6857. | positive integer is returned. Otherwise, if the conversion overflows, the
  6858. | largest integer with the same sign as `a' is returned.
  6859. *----------------------------------------------------------------------------*}
  6860. function float128_to_int64(a: float128): int64;
  6861. var
  6862. aSign: flag;
  6863. aExp, shiftCount: int32;
  6864. aSig0, aSig1: bits64;
  6865. begin
  6866. aSig1 := extractFloat128Frac1( a );
  6867. aSig0 := extractFloat128Frac0( a );
  6868. aExp := extractFloat128Exp( a );
  6869. aSign := extractFloat128Sign( a );
  6870. if ( aExp<>0 ) then
  6871. aSig0 := aSig0 or int64( $0001000000000000 );
  6872. shiftCount := $402F - aExp;
  6873. if ( shiftCount <= 0 ) then
  6874. begin
  6875. if ( $403E < aExp ) then
  6876. begin
  6877. float_raise( float_flag_invalid );
  6878. if ( (aSign=0)
  6879. or ( ( aExp = $7FFF )
  6880. and ( (aSig1<>0) or ( aSig0 <> int64( $0001000000000000 ) ) )
  6881. )
  6882. ) then
  6883. begin
  6884. result := int64( $7FFFFFFFFFFFFFFF );
  6885. end;
  6886. result := int64( $8000000000000000 );
  6887. end;
  6888. shortShift128Left( aSig0, aSig1, - shiftCount, aSig0, aSig1 );
  6889. end
  6890. else begin
  6891. shift64ExtraRightJamming( aSig0, aSig1, shiftCount, aSig0, aSig1 );
  6892. end;
  6893. result := roundAndPackInt64( aSign, aSig0, aSig1 );
  6894. end;
  6895. {*----------------------------------------------------------------------------
  6896. | Returns the result of converting the quadruple-precision floating-point
  6897. | value `a' to the 64-bit two's complement integer format. The conversion
  6898. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  6899. | Arithmetic, except that the conversion is always rounded toward zero.
  6900. | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  6901. | the conversion overflows, the largest integer with the same sign as `a' is
  6902. | returned.
  6903. *----------------------------------------------------------------------------*}
  6904. function float128_to_int64_round_to_zero(a: float128): int64;
  6905. var
  6906. aSign: flag;
  6907. aExp, shiftCount: int32;
  6908. aSig0, aSig1: bits64;
  6909. z: int64;
  6910. begin
  6911. aSig1 := extractFloat128Frac1( a );
  6912. aSig0 := extractFloat128Frac0( a );
  6913. aExp := extractFloat128Exp( a );
  6914. aSign := extractFloat128Sign( a );
  6915. if ( aExp<>0 ) then
  6916. aSig0 := aSig0 or int64( $0001000000000000 );
  6917. shiftCount := aExp - $402F;
  6918. if ( 0 < shiftCount ) then
  6919. begin
  6920. if ( $403E <= aExp ) then
  6921. begin
  6922. aSig0 := aSig0 and int64( $0000FFFFFFFFFFFF );
  6923. if ( ( a.high = int64( $C03E000000000000 ) )
  6924. and ( aSig1 < int64( $0002000000000000 ) ) ) then
  6925. begin
  6926. if ( aSig1<>0 ) then
  6927. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  6928. end
  6929. else begin
  6930. float_raise( float_flag_invalid );
  6931. if ( (aSign=0) or ( ( aExp = $7FFF ) and (( aSig0 or aSig1 )<>0) ) ) then
  6932. begin
  6933. result := int64( $7FFFFFFFFFFFFFFF );
  6934. exit;
  6935. end;
  6936. end;
  6937. result := int64( $8000000000000000 );
  6938. exit;
  6939. end;
  6940. z := ( aSig0 shl shiftCount ) or ( aSig1>>( ( - shiftCount ) and 63 ) );
  6941. if ( int64( aSig1 shl shiftCount )<>0 ) then
  6942. begin
  6943. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  6944. end;
  6945. end
  6946. else begin
  6947. if ( aExp < $3FFF ) then
  6948. begin
  6949. if ( aExp or aSig0 or aSig1 )<>0 then
  6950. begin
  6951. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  6952. end;
  6953. result := 0;
  6954. exit;
  6955. end;
  6956. z := aSig0 shr ( - shiftCount );
  6957. if ( (aSig1<>0)
  6958. or ( (shiftCount<>0) and (int64( aSig0 shl ( shiftCount and 63 ) )<>0) ) ) then
  6959. begin
  6960. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  6961. end;
  6962. end;
  6963. if ( aSign<>0 ) then
  6964. z := - z;
  6965. result := z;
  6966. end;
  6967. {*----------------------------------------------------------------------------
  6968. | Returns the result of converting the quadruple-precision floating-point
  6969. | value `a' to the single-precision floating-point format. The conversion
  6970. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  6971. | Arithmetic.
  6972. *----------------------------------------------------------------------------*}
  6973. function float128_to_float32(a: float128): float32;
  6974. var
  6975. aSign: flag;
  6976. aExp: int32;
  6977. aSig0, aSig1: bits64;
  6978. zSig: bits32;
  6979. begin
  6980. aSig1 := extractFloat128Frac1( a );
  6981. aSig0 := extractFloat128Frac0( a );
  6982. aExp := extractFloat128Exp( a );
  6983. aSign := extractFloat128Sign( a );
  6984. if ( aExp = $7FFF ) then
  6985. begin
  6986. if ( aSig0 or aSig1 )<>0 then
  6987. begin
  6988. result := commonNaNToFloat32( float128ToCommonNaN( a ) );
  6989. exit;
  6990. end;
  6991. result := packFloat32( aSign, $FF, 0 );
  6992. exit;
  6993. end;
  6994. aSig0 := aSig0 or ord( aSig1 <> 0 );
  6995. shift64RightJamming( aSig0, 18, aSig0 );
  6996. zSig := aSig0;
  6997. if ( aExp or zSig )<>0 then
  6998. begin
  6999. zSig := zSig or $40000000;
  7000. dec(aExp,$3F81);
  7001. end;
  7002. result := roundAndPackFloat32( aSign, aExp, zSig );
  7003. end;
  7004. {*----------------------------------------------------------------------------
  7005. | Returns the result of converting the quadruple-precision floating-point
  7006. | value `a' to the double-precision floating-point format. The conversion
  7007. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7008. | Arithmetic.
  7009. *----------------------------------------------------------------------------*}
  7010. function float128_to_float64(a: float128): float64;
  7011. var
  7012. aSign: flag;
  7013. aExp: int32;
  7014. aSig0, aSig1: bits64;
  7015. begin
  7016. aSig1 := extractFloat128Frac1( a );
  7017. aSig0 := extractFloat128Frac0( a );
  7018. aExp := extractFloat128Exp( a );
  7019. aSign := extractFloat128Sign( a );
  7020. if ( aExp = $7FFF ) then
  7021. begin
  7022. if ( aSig0 or aSig1 )<>0 then
  7023. begin
  7024. commonNaNToFloat64( float128ToCommonNaN( a ),result);
  7025. exit;
  7026. end;
  7027. result:=packFloat64( aSign, $7FF, 0);
  7028. exit;
  7029. end;
  7030. shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );
  7031. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7032. if ( aExp or aSig0 )<>0 then
  7033. begin
  7034. aSig0 := aSig0 or int64( $4000000000000000 );
  7035. dec(aExp,$3C01);
  7036. end;
  7037. result := roundAndPackFloat64( aSign, aExp, aSig0 );
  7038. end;
  7039. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  7040. {*----------------------------------------------------------------------------
  7041. | Returns the result of converting the quadruple-precision floating-point
  7042. | value `a' to the extended double-precision floating-point format. The
  7043. | conversion is performed according to the IEC/IEEE Standard for Binary
  7044. | Floating-Point Arithmetic.
  7045. *----------------------------------------------------------------------------*}
  7046. function float128_to_floatx80(a: float128): floatx80;
  7047. var
  7048. aSign: flag;
  7049. aExp: int32;
  7050. aSig0, aSig1: bits64;
  7051. begin
  7052. aSig1 := extractFloat128Frac1( a );
  7053. aSig0 := extractFloat128Frac0( a );
  7054. aExp := extractFloat128Exp( a );
  7055. aSign := extractFloat128Sign( a );
  7056. if ( aExp = $7FFF ) begin
  7057. if ( aSig0 or aSig1 ) begin
  7058. result := commonNaNToFloatx80( float128ToCommonNaN( a ) );
  7059. exit;
  7060. end;
  7061. result := packFloatx80( aSign, $7FFF, int64( $8000000000000000 ) );
  7062. exit;
  7063. end;
  7064. if ( aExp = 0 ) begin
  7065. if ( ( aSig0 or aSig1 ) = 0 ) then
  7066. begin
  7067. result := packFloatx80( aSign, 0, 0 );
  7068. exit;
  7069. end;
  7070. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  7071. end;
  7072. else begin
  7073. aSig0 or= int64( $0001000000000000 );
  7074. end;
  7075. shortShift128Left( aSig0, aSig1, 15, aSig0, aSig1 );
  7076. result := roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );
  7077. end;
  7078. {$endif FPC_SOFTFLOAT_FLOATX80}
  7079. {*----------------------------------------------------------------------------
  7080. | Rounds the quadruple-precision floating-point value `a' to an integer, and
  7081. | Returns the result as a quadruple-precision floating-point value. The
  7082. | operation is performed according to the IEC/IEEE Standard for Binary
  7083. | Floating-Point Arithmetic.
  7084. *----------------------------------------------------------------------------*}
  7085. function float128_round_to_int(a: float128): float128;
  7086. var
  7087. aSign: flag;
  7088. aExp: int32;
  7089. lastBitMask, roundBitsMask: bits64;
  7090. roundingMode: int8;
  7091. z: float128;
  7092. begin
  7093. aExp := extractFloat128Exp( a );
  7094. if ( $402F <= aExp ) then
  7095. begin
  7096. if ( $406F <= aExp ) then
  7097. begin
  7098. if ( ( aExp = $7FFF )
  7099. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) )<>0)
  7100. ) then
  7101. begin
  7102. result := propagateFloat128NaN( a, a );
  7103. exit;
  7104. end;
  7105. result := a;
  7106. exit;
  7107. end;
  7108. lastBitMask := 1;
  7109. lastBitMask := ( lastBitMask shl ( $406E - aExp ) ) shl 1;
  7110. roundBitsMask := lastBitMask - 1;
  7111. z := a;
  7112. roundingMode := softfloat_rounding_mode;
  7113. if ( roundingMode = float_round_nearest_even ) then
  7114. begin
  7115. if ( lastBitMask )<>0 then
  7116. begin
  7117. add128( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
  7118. if ( ( z.low and roundBitsMask ) = 0 ) then
  7119. z.low := z.low and not(lastBitMask);
  7120. end
  7121. else begin
  7122. if ( sbits64(z.low) < 0 ) then
  7123. begin
  7124. inc(z.high);
  7125. if ( bits64( z.low shl 1 ) = 0 ) then
  7126. z.high := z.high and not(1);
  7127. end;
  7128. end;
  7129. end
  7130. else if ( roundingMode <> float_round_to_zero ) then
  7131. begin
  7132. if ( extractFloat128Sign( z )
  7133. xor ord( roundingMode = float_round_up ) )<>0 then
  7134. begin
  7135. add128( z.high, z.low, 0, roundBitsMask, z.high, z.low );
  7136. end;
  7137. end;
  7138. z.low := z.low and not(roundBitsMask);
  7139. end
  7140. else begin
  7141. if ( aExp < $3FFF ) then
  7142. begin
  7143. if ( ( ( bits64( a.high shl 1 ) ) or a.low ) = 0 ) then
  7144. begin
  7145. result := a;
  7146. exit;
  7147. end;
  7148. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  7149. aSign := extractFloat128Sign( a );
  7150. case softfloat_rounding_mode of
  7151. float_round_nearest_even:
  7152. if ( ( aExp = $3FFE )
  7153. and ( (extractFloat128Frac0( a )<>0)
  7154. or (extractFloat128Frac1( a )<>0) )
  7155. ) then begin
  7156. begin
  7157. result := packFloat128( aSign, $3FFF, 0, 0 );
  7158. exit;
  7159. end;
  7160. end;
  7161. float_round_down:
  7162. begin
  7163. if aSign<>0 then
  7164. result:=packFloat128( 1, $3FFF, 0, 0 )
  7165. else
  7166. result:=packFloat128( 0, 0, 0, 0 );
  7167. exit;
  7168. end;
  7169. float_round_up:
  7170. begin
  7171. if aSign<>0 then
  7172. result := packFloat128( 1, 0, 0, 0 )
  7173. else
  7174. result:=packFloat128( 0, $3FFF, 0, 0 );
  7175. exit;
  7176. end;
  7177. end;
  7178. result := packFloat128( aSign, 0, 0, 0 );
  7179. exit;
  7180. end;
  7181. lastBitMask := 1;
  7182. lastBitMask := lastBitMask shl ($402F - aExp);
  7183. roundBitsMask := lastBitMask - 1;
  7184. z.low := 0;
  7185. z.high := a.high;
  7186. roundingMode := softfloat_rounding_mode;
  7187. if ( roundingMode = float_round_nearest_even ) then begin
  7188. inc(z.high,lastBitMask shr 1);
  7189. if ( ( ( z.high and roundBitsMask ) or a.low ) = 0 ) then begin
  7190. z.high := z.high and not(lastBitMask);
  7191. end;
  7192. end
  7193. else if ( roundingMode <> float_round_to_zero ) then begin
  7194. if ( (extractFloat128Sign( z )<>0)
  7195. xor ( roundingMode = float_round_up ) ) then begin
  7196. z.high := z.high or ord( a.low <> 0 );
  7197. z.high := z.high+roundBitsMask;
  7198. end;
  7199. end;
  7200. z.high := z.high and not(roundBitsMask);
  7201. end;
  7202. if ( ( z.low <> a.low ) or ( z.high <> a.high ) ) then begin
  7203. softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
  7204. end;
  7205. result := z;
  7206. end;
  7207. {*----------------------------------------------------------------------------
  7208. | Returns the result of adding the absolute values of the quadruple-precision
  7209. | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  7210. | before being returned. `zSign' is ignored if the result is a NaN.
  7211. | The addition is performed according to the IEC/IEEE Standard for Binary
  7212. | Floating-Point Arithmetic.
  7213. *----------------------------------------------------------------------------*}
  7214. function addFloat128Sigs(a,b : float128; zSign : flag ): float128;
  7215. var
  7216. aExp, bExp, zExp: int32;
  7217. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
  7218. expDiff: int32;
  7219. label
  7220. shiftRight1,roundAndPack;
  7221. begin
  7222. aSig1 := extractFloat128Frac1( a );
  7223. aSig0 := extractFloat128Frac0( a );
  7224. aExp := extractFloat128Exp( a );
  7225. bSig1 := extractFloat128Frac1( b );
  7226. bSig0 := extractFloat128Frac0( b );
  7227. bExp := extractFloat128Exp( b );
  7228. expDiff := aExp - bExp;
  7229. if ( 0 < expDiff ) then begin
  7230. if ( aExp = $7FFF ) then begin
  7231. if ( aSig0 or aSig1 )<>0 then
  7232. begin
  7233. result := propagateFloat128NaN( a, b );
  7234. exit;
  7235. end;
  7236. result := a;
  7237. exit;
  7238. end;
  7239. if ( bExp = 0 ) then begin
  7240. dec(expDiff);
  7241. end
  7242. else begin
  7243. bSig0 := bSig0 or int64( $0001000000000000 );
  7244. end;
  7245. shift128ExtraRightJamming(
  7246. bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
  7247. zExp := aExp;
  7248. end
  7249. else if ( expDiff < 0 ) then begin
  7250. if ( bExp = $7FFF ) then begin
  7251. if ( bSig0 or bSig1 )<>0 then
  7252. begin
  7253. result := propagateFloat128NaN( a, b );
  7254. exit;
  7255. end;
  7256. result := packFloat128( zSign, $7FFF, 0, 0 );
  7257. exit;
  7258. end;
  7259. if ( aExp = 0 ) then begin
  7260. inc(expDiff);
  7261. end
  7262. else begin
  7263. aSig0 := aSig0 or int64( $0001000000000000 );
  7264. end;
  7265. shift128ExtraRightJamming(
  7266. aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
  7267. zExp := bExp;
  7268. end
  7269. else begin
  7270. if ( aExp = $7FFF ) then begin
  7271. if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin
  7272. result := propagateFloat128NaN( a, b );
  7273. exit;
  7274. end;
  7275. result := a;
  7276. exit;
  7277. end;
  7278. add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  7279. if ( aExp = 0 ) then
  7280. begin
  7281. result := packFloat128( zSign, 0, zSig0, zSig1 );
  7282. exit;
  7283. end;
  7284. zSig2 := 0;
  7285. zSig0 := zSig0 or int64( $0002000000000000 );
  7286. zExp := aExp;
  7287. goto shiftRight1;
  7288. end;
  7289. aSig0 := aSig0 or int64( $0001000000000000 );
  7290. add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  7291. dec(zExp);
  7292. if ( zSig0 < int64( $0002000000000000 ) ) then goto roundAndPack;
  7293. inc(zExp);
  7294. shiftRight1:
  7295. shift128ExtraRightJamming(
  7296. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  7297. roundAndPack:
  7298. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  7299. end;
  7300. {*----------------------------------------------------------------------------
  7301. | Returns the result of subtracting the absolute values of the quadruple-
  7302. | precision floating-point values `a' and `b'. If `zSign' is 1, the
  7303. | difference is negated before being returned. `zSign' is ignored if the
  7304. | result is a NaN. The subtraction is performed according to the IEC/IEEE
  7305. | Standard for Binary Floating-Point Arithmetic.
  7306. *----------------------------------------------------------------------------*}
  7307. function subFloat128Sigs( a, b : float128; zSign : flag): float128;
  7308. var
  7309. aExp, bExp, zExp: int32;
  7310. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits64;
  7311. expDiff: int32;
  7312. z: float128;
  7313. label
  7314. aExpBigger,bExpBigger,aBigger,bBigger,normalizeRoundAndPack;
  7315. begin
  7316. aSig1 := extractFloat128Frac1( a );
  7317. aSig0 := extractFloat128Frac0( a );
  7318. aExp := extractFloat128Exp( a );
  7319. bSig1 := extractFloat128Frac1( b );
  7320. bSig0 := extractFloat128Frac0( b );
  7321. bExp := extractFloat128Exp( b );
  7322. expDiff := aExp - bExp;
  7323. shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );
  7324. shortShift128Left( bSig0, bSig1, 14, bSig0, bSig1 );
  7325. if ( 0 < expDiff ) then goto aExpBigger;
  7326. if ( expDiff < 0 ) then goto bExpBigger;
  7327. if ( aExp = $7FFF ) then begin
  7328. if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin
  7329. result := propagateFloat128NaN( a, b );
  7330. exit;
  7331. end;
  7332. float_raise( float_flag_invalid );
  7333. z.low := float128_default_nan_low;
  7334. z.high := float128_default_nan_high;
  7335. result := z;
  7336. exit;
  7337. end;
  7338. if ( aExp = 0 ) then begin
  7339. aExp := 1;
  7340. bExp := 1;
  7341. end;
  7342. if ( bSig0 < aSig0 ) then goto aBigger;
  7343. if ( aSig0 < bSig0 ) then goto bBigger;
  7344. if ( bSig1 < aSig1 ) then goto aBigger;
  7345. if ( aSig1 < bSig1 ) then goto bBigger;
  7346. result := packFloat128( ord(softfloat_rounding_mode = float_round_down), 0, 0, 0 );
  7347. exit;
  7348. bExpBigger:
  7349. if ( bExp = $7FFF ) then begin
  7350. if ( bSig0 or bSig1 )<>0 then
  7351. begin
  7352. result := propagateFloat128NaN( a, b );
  7353. exit;
  7354. end;
  7355. result := packFloat128( zSign xor 1, $7FFF, 0, 0 );
  7356. exit;
  7357. end;
  7358. if ( aExp = 0 ) then begin
  7359. inc(expDiff);
  7360. end
  7361. else begin
  7362. aSig0 := aSig0 or int64( $4000000000000000 );
  7363. end;
  7364. shift128RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  7365. bSig0 := bSig0 or int64( $4000000000000000 );
  7366. bBigger:
  7367. sub128( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
  7368. zExp := bExp;
  7369. zSign := zSign xor 1;
  7370. goto normalizeRoundAndPack;
  7371. aExpBigger:
  7372. if ( aExp = $7FFF ) then begin
  7373. if ( aSig0 or aSig1 )<>0 then
  7374. begin
  7375. result := propagateFloat128NaN( a, b );
  7376. exit;
  7377. end;
  7378. result := a;
  7379. exit;
  7380. end;
  7381. if ( bExp = 0 ) then begin
  7382. dec(expDiff);
  7383. end
  7384. else begin
  7385. bSig0 := bSig0 or int64( $4000000000000000 );
  7386. end;
  7387. shift128RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
  7388. aSig0 := aSig0 or int64( $4000000000000000 );
  7389. aBigger:
  7390. sub128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  7391. zExp := aExp;
  7392. normalizeRoundAndPack:
  7393. dec(zExp);
  7394. result := normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );
  7395. end;
  7396. {*----------------------------------------------------------------------------
  7397. | Returns the result of adding the quadruple-precision floating-point values
  7398. | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  7399. | for Binary Floating-Point Arithmetic.
  7400. *----------------------------------------------------------------------------*}
  7401. function float128_add(a: float128; b: float128): float128;
  7402. var
  7403. aSign, bSign: flag;
  7404. begin
  7405. aSign := extractFloat128Sign( a );
  7406. bSign := extractFloat128Sign( b );
  7407. if ( aSign = bSign ) then begin
  7408. result := addFloat128Sigs( a, b, aSign );
  7409. end
  7410. else begin
  7411. result := subFloat128Sigs( a, b, aSign );
  7412. end;
  7413. end;
  7414. {*----------------------------------------------------------------------------
  7415. | Returns the result of subtracting the quadruple-precision floating-point
  7416. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  7417. | Standard for Binary Floating-Point Arithmetic.
  7418. *----------------------------------------------------------------------------*}
  7419. function float128_sub(a: float128; b: float128): float128;
  7420. var
  7421. aSign, bSign: flag;
  7422. begin
  7423. aSign := extractFloat128Sign( a );
  7424. bSign := extractFloat128Sign( b );
  7425. if ( aSign = bSign ) then begin
  7426. result := subFloat128Sigs( a, b, aSign );
  7427. end
  7428. else begin
  7429. result := addFloat128Sigs( a, b, aSign );
  7430. end;
  7431. end;
  7432. {*----------------------------------------------------------------------------
  7433. | Returns the result of multiplying the quadruple-precision floating-point
  7434. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  7435. | Standard for Binary Floating-Point Arithmetic.
  7436. *----------------------------------------------------------------------------*}
  7437. function float128_mul(a: float128; b: float128): float128;
  7438. var
  7439. aSign, bSign, zSign: flag;
  7440. aExp, bExp, zExp: int32;
  7441. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits64;
  7442. z: float128;
  7443. label
  7444. invalid;
  7445. begin
  7446. aSig1 := extractFloat128Frac1( a );
  7447. aSig0 := extractFloat128Frac0( a );
  7448. aExp := extractFloat128Exp( a );
  7449. aSign := extractFloat128Sign( a );
  7450. bSig1 := extractFloat128Frac1( b );
  7451. bSig0 := extractFloat128Frac0( b );
  7452. bExp := extractFloat128Exp( b );
  7453. bSign := extractFloat128Sign( b );
  7454. zSign := aSign xor bSign;
  7455. if ( aExp = $7FFF ) then begin
  7456. if ( (( aSig0 or aSig1 )<>0)
  7457. or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin
  7458. result := propagateFloat128NaN( a, b );
  7459. exit;
  7460. end;
  7461. if ( ( bExp or bSig0 or bSig1 ) = 0 ) then goto invalid;
  7462. result := packFloat128( zSign, $7FFF, 0, 0 );
  7463. exit;
  7464. end;
  7465. if ( bExp = $7FFF ) then begin
  7466. if ( bSig0 or bSig1 )<>0 then
  7467. begin
  7468. result := propagateFloat128NaN( a, b );
  7469. exit;
  7470. end;
  7471. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin
  7472. invalid:
  7473. float_raise( float_flag_invalid );
  7474. z.low := float128_default_nan_low;
  7475. z.high := float128_default_nan_high;
  7476. result := z;
  7477. exit;
  7478. end;
  7479. result := packFloat128( zSign, $7FFF, 0, 0 );
  7480. exit;
  7481. end;
  7482. if ( aExp = 0 ) then begin
  7483. if ( ( aSig0 or aSig1 ) = 0 ) then
  7484. begin
  7485. result := packFloat128( zSign, 0, 0, 0 );
  7486. exit;
  7487. end;
  7488. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  7489. end;
  7490. if ( bExp = 0 ) then begin
  7491. if ( ( bSig0 or bSig1 ) = 0 ) then
  7492. begin
  7493. result := packFloat128( zSign, 0, 0, 0 );
  7494. exit;
  7495. end;
  7496. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  7497. end;
  7498. zExp := aExp + bExp - $4000;
  7499. aSig0 := aSig0 or int64( $0001000000000000 );
  7500. shortShift128Left( bSig0, bSig1, 16, bSig0, bSig1 );
  7501. mul128To256( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
  7502. add128( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
  7503. zSig2 := zSig2 or ord( zSig3 <> 0 );
  7504. if ( int64( $0002000000000000 ) <= zSig0 ) then begin
  7505. shift128ExtraRightJamming(
  7506. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  7507. inc(zExp);
  7508. end;
  7509. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  7510. end;
  7511. {*----------------------------------------------------------------------------
  7512. | Returns the result of dividing the quadruple-precision floating-point value
  7513. | `a' by the corresponding value `b'. The operation is performed according to
  7514. | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7515. *----------------------------------------------------------------------------*}
  7516. function float128_div(a: float128; b: float128): float128;
  7517. var
  7518. aSign, bSign, zSign: flag;
  7519. aExp, bExp, zExp: int32;
  7520. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
  7521. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  7522. z: float128;
  7523. label
  7524. invalid;
  7525. begin
  7526. aSig1 := extractFloat128Frac1( a );
  7527. aSig0 := extractFloat128Frac0( a );
  7528. aExp := extractFloat128Exp( a );
  7529. aSign := extractFloat128Sign( a );
  7530. bSig1 := extractFloat128Frac1( b );
  7531. bSig0 := extractFloat128Frac0( b );
  7532. bExp := extractFloat128Exp( b );
  7533. bSign := extractFloat128Sign( b );
  7534. zSign := aSign xor bSign;
  7535. if ( aExp = $7FFF ) then begin
  7536. if ( aSig0 or aSig1 )<>0 then
  7537. begin
  7538. result := propagateFloat128NaN( a, b );
  7539. exit;
  7540. end;
  7541. if ( bExp = $7FFF ) then begin
  7542. if ( bSig0 or bSig1 )<>0 then
  7543. begin
  7544. result := propagateFloat128NaN( a, b );
  7545. exit;
  7546. end;
  7547. goto invalid;
  7548. end;
  7549. result := packFloat128( zSign, $7FFF, 0, 0 );
  7550. exit;
  7551. end;
  7552. if ( bExp = $7FFF ) then begin
  7553. if ( bSig0 or bSig1 )<>0 then
  7554. begin
  7555. result := propagateFloat128NaN( a, b );
  7556. exit;
  7557. end;
  7558. result := packFloat128( zSign, 0, 0, 0 );
  7559. exit;
  7560. end;
  7561. if ( bExp = 0 ) then begin
  7562. if ( ( bSig0 or bSig1 ) = 0 ) then begin
  7563. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin
  7564. invalid:
  7565. float_raise( float_flag_invalid );
  7566. z.low := float128_default_nan_low;
  7567. z.high := float128_default_nan_high;
  7568. result := z;
  7569. exit;
  7570. end;
  7571. float_raise( float_flag_divbyzero );
  7572. result := packFloat128( zSign, $7FFF, 0, 0 );
  7573. exit;
  7574. end;
  7575. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  7576. end;
  7577. if ( aExp = 0 ) then begin
  7578. if ( ( aSig0 or aSig1 ) = 0 ) then
  7579. begin
  7580. result := packFloat128( zSign, 0, 0, 0 );
  7581. exit;
  7582. end;
  7583. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  7584. end;
  7585. zExp := aExp - bExp + $3FFD;
  7586. shortShift128Left(
  7587. aSig0 or int64( $0001000000000000 ), aSig1, 15, aSig0, aSig1 );
  7588. shortShift128Left(
  7589. bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );
  7590. if ( le128( bSig0, bSig1, aSig0, aSig1 )<>0 ) then begin
  7591. shift128Right( aSig0, aSig1, 1, aSig0, aSig1 );
  7592. inc(zExp);
  7593. end;
  7594. zSig0 := estimateDiv128To64( aSig0, aSig1, bSig0 );
  7595. mul128By64To192( bSig0, bSig1, zSig0, term0, term1, term2 );
  7596. sub192( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
  7597. while ( sbits64(rem0) < 0 ) do begin
  7598. dec(zSig0);
  7599. add192( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
  7600. end;
  7601. zSig1 := estimateDiv128To64( rem1, rem2, bSig0 );
  7602. if ( ( zSig1 and $3FFF ) <= 4 ) then begin
  7603. mul128By64To192( bSig0, bSig1, zSig1, term1, term2, term3 );
  7604. sub192( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
  7605. while ( sbits64(rem1) < 0 ) do begin
  7606. dec(zSig1);
  7607. add192( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
  7608. end;
  7609. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  7610. end;
  7611. shift128ExtraRightJamming( zSig0, zSig1, 0, 15, zSig0, zSig1, zSig2 );
  7612. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  7613. end;
  7614. {*----------------------------------------------------------------------------
  7615. | Returns the remainder of the quadruple-precision floating-point value `a'
  7616. | with respect to the corresponding value `b'. The operation is performed
  7617. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7618. *----------------------------------------------------------------------------*}
  7619. function float128_rem(a: float128; b: float128): float128;
  7620. var
  7621. aSign, bSign, zSign: flag;
  7622. aExp, bExp, expDiff: int32;
  7623. aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits64;
  7624. allZero, alternateASig0, alternateASig1, sigMean1: bits64;
  7625. sigMean0: sbits64;
  7626. z: float128;
  7627. label
  7628. invalid;
  7629. begin
  7630. aSig1 := extractFloat128Frac1( a );
  7631. aSig0 := extractFloat128Frac0( a );
  7632. aExp := extractFloat128Exp( a );
  7633. aSign := extractFloat128Sign( a );
  7634. bSig1 := extractFloat128Frac1( b );
  7635. bSig0 := extractFloat128Frac0( b );
  7636. bExp := extractFloat128Exp( b );
  7637. bSign := extractFloat128Sign( b );
  7638. if ( aExp = $7FFF ) then begin
  7639. if ( (( aSig0 or aSig1 )<>0)
  7640. or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin
  7641. result := propagateFloat128NaN( a, b );
  7642. exit;
  7643. end;
  7644. goto invalid;
  7645. end;
  7646. if ( bExp = $7FFF ) then begin
  7647. if ( bSig0 or bSig1 )<>0 then
  7648. begin
  7649. result := propagateFloat128NaN( a, b );
  7650. exit;
  7651. end;
  7652. result := a;
  7653. exit;
  7654. end;
  7655. if ( bExp = 0 ) then begin
  7656. if ( ( bSig0 or bSig1 ) = 0 ) then begin
  7657. invalid:
  7658. float_raise( float_flag_invalid );
  7659. z.low := float128_default_nan_low;
  7660. z.high := float128_default_nan_high;
  7661. result := z;
  7662. exit;
  7663. end;
  7664. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  7665. end;
  7666. if ( aExp = 0 ) then begin
  7667. if ( ( aSig0 or aSig1 ) = 0 ) then
  7668. begin
  7669. result := a;
  7670. exit;
  7671. end;
  7672. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  7673. end;
  7674. expDiff := aExp - bExp;
  7675. if ( expDiff < -1 ) then
  7676. begin
  7677. result := a;
  7678. exit;
  7679. end;
  7680. shortShift128Left(
  7681. aSig0 or int64( $0001000000000000 ),
  7682. aSig1,
  7683. 15 - ord( expDiff < 0 ),
  7684. aSig0,
  7685. aSig1
  7686. );
  7687. shortShift128Left(
  7688. bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );
  7689. q := le128( bSig0, bSig1, aSig0, aSig1 );
  7690. if ( q )<>0 then sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  7691. dec(expDiff,64);
  7692. while ( 0 < expDiff ) do begin
  7693. q := estimateDiv128To64( aSig0, aSig1, bSig0 );
  7694. if ( 4 < q ) then
  7695. q := q - 4
  7696. else
  7697. q := 0;
  7698. mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );
  7699. shortShift192Left( term0, term1, term2, 61, term1, term2, allZero );
  7700. shortShift128Left( aSig0, aSig1, 61, aSig0, allZero );
  7701. sub128( aSig0, 0, term1, term2, aSig0, aSig1 );
  7702. dec(expDiff,61);
  7703. end;
  7704. if ( -64 < expDiff ) then begin
  7705. q := estimateDiv128To64( aSig0, aSig1, bSig0 );
  7706. if ( 4 < q ) then
  7707. q := q - 4
  7708. else
  7709. q := 0;
  7710. q := q shr (- expDiff);
  7711. shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );
  7712. inc(expDiff,52);
  7713. if ( expDiff < 0 ) then begin
  7714. shift128Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  7715. end
  7716. else begin
  7717. shortShift128Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
  7718. end;
  7719. mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );
  7720. sub128( aSig0, aSig1, term1, term2, aSig0, aSig1 );
  7721. end
  7722. else begin
  7723. shift128Right( aSig0, aSig1, 12, aSig0, aSig1 );
  7724. shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );
  7725. end;
  7726. repeat
  7727. alternateASig0 := aSig0;
  7728. alternateASig1 := aSig1;
  7729. inc(q);
  7730. sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  7731. until not( 0 <= sbits64(aSig0) );
  7732. add128(
  7733. aSig0, aSig1, alternateASig0, alternateASig1, bits64(sigMean0), sigMean1 );
  7734. if ( ( sigMean0 < 0 )
  7735. or ( ( ( sigMean0 or sigMean1 ) = 0 ) and (( q and 1 )<>0) ) ) then begin
  7736. aSig0 := alternateASig0;
  7737. aSig1 := alternateASig1;
  7738. end;
  7739. zSign := ord( sbits64(aSig0) < 0 );
  7740. if ( zSign<>0 ) then sub128( 0, 0, aSig0, aSig1, aSig0, aSig1 );
  7741. result :=
  7742. normalizeRoundAndPackFloat128( aSign xor zSign, bExp - 4, aSig0, aSig1 );
  7743. end;
  7744. {*----------------------------------------------------------------------------
  7745. | Returns the square root of the quadruple-precision floating-point value `a'.
  7746. | The operation is performed according to the IEC/IEEE Standard for Binary
  7747. | Floating-Point Arithmetic.
  7748. *----------------------------------------------------------------------------*}
  7749. function float128_sqrt(a: float128): float128;
  7750. var
  7751. aSign: flag;
  7752. aExp, zExp: int32;
  7753. aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits64;
  7754. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  7755. z: float128;
  7756. label
  7757. invalid;
  7758. begin
  7759. aSig1 := extractFloat128Frac1( a );
  7760. aSig0 := extractFloat128Frac0( a );
  7761. aExp := extractFloat128Exp( a );
  7762. aSign := extractFloat128Sign( a );
  7763. if ( aExp = $7FFF ) then begin
  7764. if ( aSig0 or aSig1 )<>0 then
  7765. begin
  7766. result := propagateFloat128NaN( a, a );
  7767. exit;
  7768. end;
  7769. if ( aSign=0 ) then
  7770. begin
  7771. result := a;
  7772. exit;
  7773. end;
  7774. goto invalid;
  7775. end;
  7776. if ( aSign<>0 ) then begin
  7777. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then
  7778. begin
  7779. result := a;
  7780. exit;
  7781. end;
  7782. invalid:
  7783. float_raise( float_flag_invalid );
  7784. z.low := float128_default_nan_low;
  7785. z.high := float128_default_nan_high;
  7786. result := z;
  7787. exit;
  7788. end;
  7789. if ( aExp = 0 ) then begin
  7790. if ( ( aSig0 or aSig1 ) = 0 ) then
  7791. begin
  7792. result := packFloat128( 0, 0, 0, 0 );
  7793. exit;
  7794. end;
  7795. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  7796. end;
  7797. zExp := ( ( aExp - $3FFF )>>1 ) + $3FFE;
  7798. aSig0 := aSig0 or int64( $0001000000000000 );
  7799. zSig0 := estimateSqrt32( aExp, aSig0>>17 );
  7800. shortShift128Left( aSig0, aSig1, 13 - ( aExp and 1 ), aSig0, aSig1 );
  7801. zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
  7802. doubleZSig0 := zSig0 shl 1;
  7803. mul64To128( zSig0, zSig0, term0, term1 );
  7804. sub128( aSig0, aSig1, term0, term1, rem0, rem1 );
  7805. while ( sbits64(rem0) < 0 ) do begin
  7806. dec(zSig0);
  7807. dec(doubleZSig0,2);
  7808. add128( rem0, rem1, zSig0 shr 63, doubleZSig0 or 1, rem0, rem1 );
  7809. end;
  7810. zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
  7811. if ( ( zSig1 and $1FFF ) <= 5 ) then begin
  7812. if ( zSig1 = 0 ) then zSig1 := 1;
  7813. mul64To128( doubleZSig0, zSig1, term1, term2 );
  7814. sub128( rem1, 0, term1, term2, rem1, rem2 );
  7815. mul64To128( zSig1, zSig1, term2, term3 );
  7816. sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  7817. while ( sbits64(rem1) < 0 ) do begin
  7818. dec(zSig1);
  7819. shortShift128Left( 0, zSig1, 1, term2, term3 );
  7820. term3 := term3 or 1;
  7821. term2 := term2 or doubleZSig0;
  7822. add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  7823. end;
  7824. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  7825. end;
  7826. shift128ExtraRightJamming( zSig0, zSig1, 0, 14, zSig0, zSig1, zSig2 );
  7827. result := roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 );
  7828. end;
  7829. {*----------------------------------------------------------------------------
  7830. | Returns 1 if the quadruple-precision floating-point value `a' is equal to
  7831. | the corresponding value `b', and 0 otherwise. The comparison is performed
  7832. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7833. *----------------------------------------------------------------------------*}
  7834. function float128_eq(a: float128; b: float128): flag;
  7835. begin
  7836. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  7837. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  7838. or ( ( extractFloat128Exp( b ) = $7FFF )
  7839. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  7840. ) then begin
  7841. if ( (float128_is_signaling_nan( a )<>0)
  7842. or (float128_is_signaling_nan( b )<>0) ) then begin
  7843. float_raise( float_flag_invalid );
  7844. end;
  7845. result := 0;
  7846. exit;
  7847. end;
  7848. result := ord(
  7849. ( a.low = b.low )
  7850. and ( ( a.high = b.high )
  7851. or ( ( a.low = 0 )
  7852. and ( bits64( ( a.high or b.high ) shl 1 ) = 0 ) )
  7853. ));
  7854. end;
  7855. {*----------------------------------------------------------------------------
  7856. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  7857. | or equal to the corresponding value `b', and 0 otherwise. The comparison
  7858. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7859. | Arithmetic.
  7860. *----------------------------------------------------------------------------*}
  7861. function float128_le(a: float128; b: float128): flag;
  7862. var
  7863. aSign, bSign: flag;
  7864. begin
  7865. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  7866. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  7867. or ( ( extractFloat128Exp( b ) = $7FFF )
  7868. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  7869. ) then begin
  7870. float_raise( float_flag_invalid );
  7871. result := 0;
  7872. exit;
  7873. end;
  7874. aSign := extractFloat128Sign( a );
  7875. bSign := extractFloat128Sign( b );
  7876. if ( aSign <> bSign ) then begin
  7877. result := ord(
  7878. (aSign<>0)
  7879. or ( ( ( bits64 ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  7880. = 0 ));
  7881. exit;
  7882. end;
  7883. if aSign<>0 then
  7884. result := le128( b.high, b.low, a.high, a.low )
  7885. else
  7886. result := le128( a.high, a.low, b.high, b.low );
  7887. end;
  7888. {*----------------------------------------------------------------------------
  7889. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  7890. | the corresponding value `b', and 0 otherwise. The comparison is performed
  7891. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7892. *----------------------------------------------------------------------------*}
  7893. function float128_lt(a: float128; b: float128): flag;
  7894. var
  7895. aSign, bSign: flag;
  7896. begin
  7897. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  7898. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  7899. or ( ( extractFloat128Exp( b ) = $7FFF )
  7900. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  7901. ) then begin
  7902. float_raise( float_flag_invalid );
  7903. result := 0;
  7904. exit;
  7905. end;
  7906. aSign := extractFloat128Sign( a );
  7907. bSign := extractFloat128Sign( b );
  7908. if ( aSign <> bSign ) then begin
  7909. result := ord(
  7910. (aSign<>0)
  7911. and ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  7912. <> 0 ));
  7913. exit;
  7914. end;
  7915. if aSign<>0 then
  7916. result := lt128( b.high, b.low, a.high, a.low )
  7917. else
  7918. result := lt128( a.high, a.low, b.high, b.low );
  7919. end;
  7920. {*----------------------------------------------------------------------------
  7921. | Returns 1 if the quadruple-precision floating-point value `a' is equal to
  7922. | the corresponding value `b', and 0 otherwise. The invalid exception is
  7923. | raised if either operand is a NaN. Otherwise, the comparison is performed
  7924. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7925. *----------------------------------------------------------------------------*}
  7926. function float128_eq_signaling(a: float128; b: float128): flag;
  7927. begin
  7928. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  7929. and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  7930. or ( ( extractFloat128Exp( b ) = $7FFF )
  7931. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  7932. ) then begin
  7933. float_raise( float_flag_invalid );
  7934. result := 0;
  7935. exit;
  7936. end;
  7937. result := ord(
  7938. ( a.low = b.low )
  7939. and ( ( a.high = b.high )
  7940. or ( ( a.low = 0 )
  7941. and ( bits64 ( ( a.high or b.high ) shl 1 ) = 0 ) )
  7942. ));
  7943. end;
  7944. {*----------------------------------------------------------------------------
  7945. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  7946. | or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  7947. | cause an exception. Otherwise, the comparison is performed according to the
  7948. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7949. *----------------------------------------------------------------------------*}
  7950. function float128_le_quiet(a: float128; b: float128): flag;
  7951. var
  7952. aSign, bSign: flag;
  7953. begin
  7954. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  7955. and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  7956. or ( ( extractFloat128Exp( b ) = $7FFF )
  7957. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  7958. ) then begin
  7959. if ( (float128_is_signaling_nan( a )<>0)
  7960. or (float128_is_signaling_nan( b )<>0) ) then begin
  7961. float_raise( float_flag_invalid );
  7962. end;
  7963. result := 0;
  7964. exit;
  7965. end;
  7966. aSign := extractFloat128Sign( a );
  7967. bSign := extractFloat128Sign( b );
  7968. if ( aSign <> bSign ) then begin
  7969. result := ord(
  7970. (aSign<>0)
  7971. or ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  7972. = 0 ));
  7973. exit;
  7974. end;
  7975. if aSign<>0 then
  7976. result := le128( b.high, b.low, a.high, a.low )
  7977. else
  7978. result := le128( a.high, a.low, b.high, b.low );
  7979. end;
  7980. {*----------------------------------------------------------------------------
  7981. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  7982. | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  7983. | exception. Otherwise, the comparison is performed according to the IEC/IEEE
  7984. | Standard for Binary Floating-Point Arithmetic.
  7985. *----------------------------------------------------------------------------*}
  7986. function float128_lt_quiet(a: float128; b: float128): flag;
  7987. var
  7988. aSign, bSign: flag;
  7989. begin
  7990. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  7991. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  7992. or ( ( extractFloat128Exp( b ) = $7FFF )
  7993. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  7994. ) then begin
  7995. if ( (float128_is_signaling_nan( a )<>0)
  7996. or (float128_is_signaling_nan( b )<>0) ) then begin
  7997. float_raise( float_flag_invalid );
  7998. end;
  7999. result := 0;
  8000. exit;
  8001. end;
  8002. aSign := extractFloat128Sign( a );
  8003. bSign := extractFloat128Sign( b );
  8004. if ( aSign <> bSign ) then begin
  8005. result := ord(
  8006. (aSign<>0)
  8007. and ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8008. <> 0 ));
  8009. exit;
  8010. end;
  8011. if aSign<>0 then
  8012. result:=lt128( b.high, b.low, a.high, a.low )
  8013. else
  8014. result:=lt128( a.high, a.low, b.high, b.low );
  8015. end;
  8016. {----------------------------------------------------------------------------
  8017. | Returns the result of converting the double-precision floating-point value
  8018. | `a' to the quadruple-precision floating-point format. The conversion is
  8019. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  8020. | Arithmetic.
  8021. *----------------------------------------------------------------------------}
  8022. function float64_to_float128( a : float64) : float128;
  8023. var
  8024. aSign : flag;
  8025. aExp : int16;
  8026. aSig, zSig0, zSig1 : bits64;
  8027. begin
  8028. aSig := extractFloat64Frac( a );
  8029. aExp := extractFloat64Exp( a );
  8030. aSign := extractFloat64Sign( a );
  8031. if ( aExp = $7FF ) then begin
  8032. if ( aSig<>0 ) then
  8033. result:=commonNaNToFloat128( float64ToCommonNaN( a ) );
  8034. result:=packFloat128( aSign, $7FFF, 0, 0 );
  8035. exit;
  8036. end;
  8037. if ( aExp = 0 ) then begin
  8038. if ( aSig = 0 ) then
  8039. begin
  8040. result:=packFloat128( aSign, 0, 0, 0 );
  8041. exit;
  8042. end;
  8043. normalizeFloat64Subnormal( aSig, aExp, aSig );
  8044. dec(aExp);
  8045. end;
  8046. shift128Right( aSig, 0, 4, zSig0, zSig1 );
  8047. result:=packFloat128( aSign, aExp + $3C00, zSig0, zSig1 );
  8048. end;
  8049. {$endif FPC_SOFTFLOAT_FLOAT128}
  8050. {$endif not(defined(fpc_softfpu_interface))}
  8051. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  8052. end.
  8053. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}