2
0

softfpu.pp 324 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370
  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. {$macro on}
  69. {$define compilerproc:=stdcall }
  70. interface
  71. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  72. {$if not(defined(fpc_softfpu_implementation))}
  73. {
  74. -------------------------------------------------------------------------------
  75. Software IEC/IEEE floating-point types.
  76. -------------------------------------------------------------------------------
  77. }
  78. TYPE
  79. float32 = longword;
  80. {$define FPC_SYSTEM_HAS_float32}
  81. { we use here a record in the function header because
  82. the record allows bitwise conversion to single }
  83. float32rec = record
  84. float32 : float32;
  85. end;
  86. flag = byte;
  87. bits8 = byte;
  88. sbits8 = shortint;
  89. bits16 = word;
  90. sbits16 = smallint;
  91. sbits32 = longint;
  92. bits32 = longword;
  93. {$ifndef fpc}
  94. qword = int64;
  95. {$endif}
  96. { now part of the system unit
  97. uint64 = qword;
  98. }
  99. bits64 = qword;
  100. sbits64 = int64;
  101. {$ifdef ENDIAN_LITTLE}
  102. float64 = record
  103. case byte of
  104. 1: (low,high : bits32);
  105. // force the record to be aligned like a double
  106. // else *_to_double will fail for cpus like sparc
  107. // and avoid expensive unpacking/packing operations
  108. 2: (dummy : double);
  109. end;
  110. floatx80 = record
  111. case byte of
  112. 1: (low : qword;high : word);
  113. // force the record to be aligned like a double
  114. // else *_to_double will fail for cpus like sparc
  115. // and avoid expensive unpacking/packing operations
  116. 2: (dummy : extended);
  117. end;
  118. float128 = record
  119. case byte of
  120. 1: (low,high : qword);
  121. // force the record to be aligned like a double
  122. // else *_to_double will fail for cpus like sparc
  123. // and avoid expensive unpacking/packing operations
  124. 2: (dummy : qword);
  125. end;
  126. {$else}
  127. float64 = record
  128. case byte of
  129. 1: (high,low : bits32);
  130. // force the record to be aligned like a double
  131. // else *_to_double will fail for cpus like sparc
  132. 2: (dummy : double);
  133. end;
  134. floatx80 = record
  135. case byte of
  136. 1: (high : word;low : qword);
  137. // force the record to be aligned like a double
  138. // else *_to_double will fail for cpus like sparc
  139. // and avoid expensive unpacking/packing operations
  140. 2: (dummy : qword);
  141. end;
  142. float128 = record
  143. case byte of
  144. 1: (high : qword;low : qword);
  145. // force the record to be aligned like a double
  146. // else *_to_double will fail for cpus like sparc
  147. // and avoid expensive unpacking/packing operations
  148. 2: (dummy : qword);
  149. end;
  150. {$endif}
  151. {$define FPC_SYSTEM_HAS_float64}
  152. {*
  153. -------------------------------------------------------------------------------
  154. Returns 1 if the double-precision floating-point value `a' is less than
  155. the corresponding value `b', and 0 otherwise. The comparison is performed
  156. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  157. -------------------------------------------------------------------------------
  158. *}
  159. Function float64_lt(a: float64;b: float64): flag; compilerproc;
  160. {*
  161. -------------------------------------------------------------------------------
  162. Returns 1 if the double-precision floating-point value `a' is less than
  163. or equal to the corresponding value `b', and 0 otherwise. The comparison
  164. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  165. Arithmetic.
  166. -------------------------------------------------------------------------------
  167. *}
  168. Function float64_le(a: float64;b: float64): flag; compilerproc;
  169. {*
  170. -------------------------------------------------------------------------------
  171. Returns 1 if the double-precision floating-point value `a' is equal to
  172. the corresponding value `b', and 0 otherwise. The comparison is performed
  173. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  174. -------------------------------------------------------------------------------
  175. *}
  176. Function float64_eq(a: float64;b: float64): flag; compilerproc;
  177. {*
  178. -------------------------------------------------------------------------------
  179. Returns the square root of the double-precision floating-point value `a'.
  180. The operation is performed according to the IEC/IEEE Standard for Binary
  181. Floating-Point Arithmetic.
  182. -------------------------------------------------------------------------------
  183. *}
  184. function float64_sqrt( a: float64 ): float64; compilerproc;
  185. {*
  186. -------------------------------------------------------------------------------
  187. Returns the remainder of the double-precision floating-point value `a'
  188. with respect to the corresponding value `b'. The operation is performed
  189. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  190. -------------------------------------------------------------------------------
  191. *}
  192. Function float64_rem(a: float64; b : float64) : float64; compilerproc;
  193. {*
  194. -------------------------------------------------------------------------------
  195. Returns the result of dividing the double-precision floating-point value `a'
  196. by the corresponding value `b'. The operation is performed according to the
  197. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  198. -------------------------------------------------------------------------------
  199. *}
  200. Function float64_div(a: float64; b : float64) : float64; compilerproc;
  201. {*
  202. -------------------------------------------------------------------------------
  203. Returns the result of multiplying the double-precision floating-point values
  204. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  205. for Binary Floating-Point Arithmetic.
  206. -------------------------------------------------------------------------------
  207. *}
  208. Function float64_mul( a: float64; b:float64) : float64; compilerproc;
  209. {*
  210. -------------------------------------------------------------------------------
  211. Returns the result of subtracting the double-precision floating-point values
  212. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  213. for Binary Floating-Point Arithmetic.
  214. -------------------------------------------------------------------------------
  215. *}
  216. Function float64_sub(a: float64; b : float64) : float64; compilerproc;
  217. {*
  218. -------------------------------------------------------------------------------
  219. Returns the result of adding the double-precision floating-point values `a'
  220. and `b'. The operation is performed according to the IEC/IEEE Standard for
  221. Binary Floating-Point Arithmetic.
  222. -------------------------------------------------------------------------------
  223. *}
  224. Function float64_add( a: float64; b : float64) : float64; compilerproc;
  225. {*
  226. -------------------------------------------------------------------------------
  227. Rounds the double-precision floating-point value `a' to an integer,
  228. and returns the result as a double-precision floating-point value. The
  229. operation is performed according to the IEC/IEEE Standard for Binary
  230. Floating-Point Arithmetic.
  231. -------------------------------------------------------------------------------
  232. *}
  233. Function float64_round_to_int(a: float64) : float64; compilerproc;
  234. {*
  235. -------------------------------------------------------------------------------
  236. Returns the result of converting the double-precision floating-point value
  237. `a' to the single-precision floating-point format. The conversion is
  238. performed according to the IEC/IEEE Standard for Binary Floating-Point
  239. Arithmetic.
  240. -------------------------------------------------------------------------------
  241. *}
  242. Function float64_to_float32(a: float64) : float32rec; compilerproc;
  243. {*
  244. -------------------------------------------------------------------------------
  245. Returns the result of converting the double-precision floating-point value
  246. `a' to the 32-bit two's complement integer format. The conversion is
  247. performed according to the IEC/IEEE Standard for Binary Floating-Point
  248. Arithmetic, except that the conversion is always rounded toward zero.
  249. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  250. the conversion overflows, the largest integer with the same sign as `a' is
  251. returned.
  252. -------------------------------------------------------------------------------
  253. *}
  254. Function float64_to_int32_round_to_zero(a: float64 ): int32; compilerproc;
  255. {*
  256. -------------------------------------------------------------------------------
  257. Returns the result of converting the double-precision floating-point value
  258. `a' to the 32-bit two's complement integer format. The conversion is
  259. performed according to the IEC/IEEE Standard for Binary Floating-Point
  260. Arithmetic---which means in particular that the conversion is rounded
  261. according to the current rounding mode. If `a' is a NaN, the largest
  262. positive integer is returned. Otherwise, if the conversion overflows, the
  263. largest integer with the same sign as `a' is returned.
  264. -------------------------------------------------------------------------------
  265. *}
  266. Function float64_to_int32(a: float64): int32; compilerproc;
  267. {*
  268. -------------------------------------------------------------------------------
  269. Returns 1 if the single-precision floating-point value `a' is less than
  270. the corresponding value `b', and 0 otherwise. The comparison is performed
  271. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  272. -------------------------------------------------------------------------------
  273. *}
  274. Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
  275. {*
  276. -------------------------------------------------------------------------------
  277. Returns 1 if the single-precision floating-point value `a' is less than
  278. or equal to the corresponding value `b', and 0 otherwise. The comparison
  279. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  280. Arithmetic.
  281. -------------------------------------------------------------------------------
  282. *}
  283. Function float32_le( a: float32rec; b : float32rec ):flag; compilerproc;
  284. {*
  285. -------------------------------------------------------------------------------
  286. Returns 1 if the single-precision floating-point value `a' is equal to
  287. the corresponding value `b', and 0 otherwise. The comparison is performed
  288. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  289. -------------------------------------------------------------------------------
  290. *}
  291. Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
  292. {*
  293. -------------------------------------------------------------------------------
  294. Returns the square root of the single-precision floating-point value `a'.
  295. The operation is performed according to the IEC/IEEE Standard for Binary
  296. Floating-Point Arithmetic.
  297. -------------------------------------------------------------------------------
  298. *}
  299. Function float32_sqrt(a: float32rec ): float32rec; compilerproc;
  300. {*
  301. -------------------------------------------------------------------------------
  302. Returns the remainder of the single-precision floating-point value `a'
  303. with respect to the corresponding value `b'. The operation is performed
  304. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  305. -------------------------------------------------------------------------------
  306. *}
  307. Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
  308. {*
  309. -------------------------------------------------------------------------------
  310. Returns the result of dividing the single-precision floating-point value `a'
  311. by the corresponding value `b'. The operation is performed according to the
  312. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  313. -------------------------------------------------------------------------------
  314. *}
  315. Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
  316. {*
  317. -------------------------------------------------------------------------------
  318. Returns the result of multiplying the single-precision floating-point values
  319. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  320. for Binary Floating-Point Arithmetic.
  321. -------------------------------------------------------------------------------
  322. *}
  323. Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
  324. {*
  325. -------------------------------------------------------------------------------
  326. Returns the result of subtracting the single-precision floating-point values
  327. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  328. for Binary Floating-Point Arithmetic.
  329. -------------------------------------------------------------------------------
  330. *}
  331. Function float32_sub( a: float32rec ; b:float32rec ): float32rec; compilerproc;
  332. {*
  333. -------------------------------------------------------------------------------
  334. Returns the result of adding the single-precision floating-point values `a'
  335. and `b'. The operation is performed according to the IEC/IEEE Standard for
  336. Binary Floating-Point Arithmetic.
  337. -------------------------------------------------------------------------------
  338. *}
  339. Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
  340. {*
  341. -------------------------------------------------------------------------------
  342. Rounds the single-precision floating-point value `a' to an integer,
  343. and returns the result as a single-precision floating-point value. The
  344. operation is performed according to the IEC/IEEE Standard for Binary
  345. Floating-Point Arithmetic.
  346. -------------------------------------------------------------------------------
  347. *}
  348. Function float32_round_to_int( a: float32rec): float32rec; compilerproc;
  349. {*
  350. -------------------------------------------------------------------------------
  351. Returns the result of converting the single-precision floating-point value
  352. `a' to the double-precision floating-point format. The conversion is
  353. performed according to the IEC/IEEE Standard for Binary Floating-Point
  354. Arithmetic.
  355. -------------------------------------------------------------------------------
  356. *}
  357. Function float32_to_float64( a : float32rec) : Float64; compilerproc;
  358. {*
  359. -------------------------------------------------------------------------------
  360. Returns the result of converting the single-precision floating-point value
  361. `a' to the 32-bit two's complement integer format. The conversion is
  362. performed according to the IEC/IEEE Standard for Binary Floating-Point
  363. Arithmetic, except that the conversion is always rounded toward zero.
  364. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  365. the conversion overflows, the largest integer with the same sign as `a' is
  366. returned.
  367. -------------------------------------------------------------------------------
  368. *}
  369. Function float32_to_int32_round_to_zero( a: Float32rec ): int32; compilerproc;
  370. {*
  371. -------------------------------------------------------------------------------
  372. Returns the result of converting the single-precision floating-point value
  373. `a' to the 32-bit two's complement integer format. The conversion is
  374. performed according to the IEC/IEEE Standard for Binary Floating-Point
  375. Arithmetic---which means in particular that the conversion is rounded
  376. according to the current rounding mode. If `a' is a NaN, the largest
  377. positive integer is returned. Otherwise, if the conversion overflows, the
  378. largest integer with the same sign as `a' is returned.
  379. -------------------------------------------------------------------------------
  380. *}
  381. Function float32_to_int32( a : float32rec) : int32; compilerproc;
  382. {*
  383. -------------------------------------------------------------------------------
  384. Returns the result of converting the 32-bit two's complement integer `a' to
  385. the double-precision floating-point format. The conversion is performed
  386. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  387. -------------------------------------------------------------------------------
  388. *}
  389. Function int32_to_float64( a: int32) : float64; compilerproc;
  390. {*
  391. -------------------------------------------------------------------------------
  392. Returns the result of converting the 32-bit two's complement integer `a' to
  393. the single-precision floating-point format. The conversion is performed
  394. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  395. -------------------------------------------------------------------------------
  396. *}
  397. Function int32_to_float32( a: int32): float32rec; compilerproc;
  398. {*----------------------------------------------------------------------------
  399. | Returns the result of converting the 64-bit two's complement integer `a'
  400. | to the double-precision floating-point format. The conversion is performed
  401. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  402. *----------------------------------------------------------------------------*}
  403. Function int64_to_float64( a: int64 ): float64; compilerproc;
  404. Function qword_to_float64( a: qword ): float64; compilerproc;
  405. {*----------------------------------------------------------------------------
  406. | Returns the result of converting the 64-bit two's complement integer `a'
  407. | to the single-precision floating-point format. The conversion is performed
  408. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  409. *----------------------------------------------------------------------------*}
  410. Function int64_to_float32( a: int64 ): float32rec; compilerproc;
  411. Function qword_to_float32( a: qword ): float32rec; compilerproc;
  412. // +++
  413. function float32_to_int64( a: float32 ): int64;
  414. function float32_to_int64_round_to_zero( a: float32 ): int64;
  415. function float32_eq_signaling( a: float32; b: float32) : flag;
  416. function float32_le_quiet( a: float32 ; b : float32 ): flag;
  417. function float32_lt_quiet( a: float32 ; b: float32 ): flag;
  418. function float32_is_signaling_nan( a : float32 ): flag;
  419. function float32_is_nan( a : float32 ): flag;
  420. function float64_to_int64( a: float64 ): int64;
  421. function float64_to_int64_round_to_zero( a: float64 ): int64;
  422. function float64_eq_signaling( a: float64; b: float64): flag;
  423. function float64_le_quiet(a: float64 ; b: float64 ): flag;
  424. function float64_lt_quiet(a: float64; b: float64 ): Flag;
  425. function float64_is_signaling_nan( a : float64 ): flag;
  426. function float64_is_nan( a : float64 ): flag;
  427. // ===
  428. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  429. {*----------------------------------------------------------------------------
  430. | Extended double-precision rounding precision
  431. *----------------------------------------------------------------------------*}
  432. var // threadvar!?
  433. floatx80_rounding_precision : int8 = 80;
  434. function int32_to_floatx80( a: int32 ): floatx80;
  435. function int64_to_floatx80( a: int64 ): floatx80;
  436. function qword_to_floatx80( a: qword ): floatx80;
  437. function float32_to_floatx80( a: float32 ): floatx80;
  438. function float64_to_floatx80( a: float64 ): floatx80;
  439. function floatx80_to_int32( a: floatx80 ): int32;
  440. function floatx80_to_int32_round_to_zero( a: floatx80 ): int32;
  441. function floatx80_to_int64( a: floatx80 ): int64;
  442. function floatx80_to_int64_round_to_zero( a: floatx80 ): int64;
  443. function floatx80_to_float32( a: floatx80 ): float32;
  444. function floatx80_to_float64( a: floatx80 ): float64;
  445. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  446. function floatx80_to_float128( a: floatx80 ): float128;
  447. {$endif FPC_SOFTFLOAT_FLOAT128}
  448. function floatx80_round_to_int( a: floatx80 ): floatx80;
  449. function floatx80_add( a: floatx80; b: floatx80 ): floatx80;
  450. function floatx80_sub( a: floatx80; b: floatx80 ): floatx80;
  451. function floatx80_mul( a: floatx80; b: floatx80 ): floatx80;
  452. function floatx80_div( a: floatx80; b: floatx80 ): floatx80;
  453. function floatx80_rem( a: floatx80; b: floatx80 ): floatx80;
  454. function floatx80_sqrt( a: floatx80 ): floatx80;
  455. function floatx80_eq( a: floatx80; b: floatx80 ): flag;
  456. function floatx80_le( a: floatx80; b: floatx80 ): flag;
  457. function floatx80_lt( a: floatx80; b: floatx80 ): flag;
  458. function floatx80_eq_signaling( a: floatx80; b: floatx80 ): flag;
  459. function floatx80_le_quiet( a: floatx80; b: floatx80 ): flag;
  460. function floatx80_lt_quiet( a: floatx80; b: floatx80 ): flag;
  461. function floatx80_is_signaling_nan( a: floatx80 ): flag;
  462. function floatx80_is_nan(a : floatx80 ): flag;
  463. {$endif FPC_SOFTFLOAT_FLOATX80}
  464. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  465. function int32_to_float128( a: int32 ): float128;
  466. function int64_to_float128( a: int64 ): float128;
  467. function qword_to_float128( a: qword ): float128;
  468. function float32_to_float128( a: float32 ): float128;
  469. function float128_is_nan( a : float128): flag;
  470. function float128_is_signaling_nan( a : float128): flag;
  471. function float128_to_int32(a: float128): int32;
  472. function float128_to_int32_round_to_zero(a: float128): int32;
  473. function float128_to_int64(a: float128): int64;
  474. function float128_to_int64_round_to_zero(a: float128): int64;
  475. function float128_to_float32(a: float128): float32;
  476. function float128_to_float64(a: float128): float64;
  477. function float64_to_float128( a : float64) : float128;
  478. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  479. function float128_to_floatx80(a: float128): floatx80;
  480. {$endif FPC_SOFTFLOAT_FLOATX80}
  481. function float128_round_to_int(a: float128): float128;
  482. function float128_add(a: float128; b: float128): float128;
  483. function float128_sub(a: float128; b: float128): float128;
  484. function float128_mul(a: float128; b: float128): float128;
  485. function float128_div(a: float128; b: float128): float128;
  486. function float128_rem(a: float128; b: float128): float128;
  487. function float128_sqrt(a: float128): float128;
  488. function float128_eq(a: float128; b: float128): flag;
  489. function float128_le(a: float128; b: float128): flag;
  490. function float128_lt(a: float128; b: float128): flag;
  491. function float128_eq_signaling(a: float128; b: float128): flag;
  492. function float128_le_quiet(a: float128; b: float128): flag;
  493. function float128_lt_quiet(a: float128; b: float128): flag;
  494. {$endif FPC_SOFTFLOAT_FLOAT128}
  495. CONST
  496. {-------------------------------------------------------------------------------
  497. Software IEC/IEEE floating-point underflow tininess-detection mode.
  498. -------------------------------------------------------------------------------
  499. *}
  500. float_tininess_after_rounding = 0;
  501. float_tininess_before_rounding = 1;
  502. {*
  503. -------------------------------------------------------------------------------
  504. Underflow tininess-detection mode, statically initialized to default value.
  505. (The declaration in `softfloat.h' must match the `int8' type here.)
  506. -------------------------------------------------------------------------------
  507. *}
  508. var // threadvar!?
  509. softfloat_detect_tininess: int8 = float_tininess_after_rounding;
  510. {$endif not(defined(fpc_softfpu_implementation))}
  511. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  512. implementation
  513. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  514. {$if not(defined(fpc_softfpu_interface))}
  515. (*****************************************************************************)
  516. (*----------------------------------------------------------------------------*)
  517. (* Primitive arithmetic functions, including multi-word arithmetic, and *)
  518. (* division and square root approximations. (Can be specialized to target if *)
  519. (* desired.) *)
  520. (* ---------------------------------------------------------------------------*)
  521. (*****************************************************************************)
  522. { This procedure serves as a single access point to softfloat_exception_flags.
  523. It also helps to reduce code size a bit because softfloat_exception_flags is
  524. a threadvar. }
  525. procedure set_inexact_flag;
  526. begin
  527. include(softfloat_exception_flags,float_flag_inexact);
  528. end;
  529. {*----------------------------------------------------------------------------
  530. | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
  531. | and 7, and returns the properly rounded 32-bit integer corresponding to the
  532. | input. If `zSign' is 1, the input is negated before being converted to an
  533. | integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
  534. | is simply rounded to an integer, with the inexact exception raised if the
  535. | input cannot be represented exactly as an integer. However, if the fixed-
  536. | point input is too large, the invalid exception is raised and the largest
  537. | positive or negative integer is returned.
  538. *----------------------------------------------------------------------------*}
  539. function roundAndPackInt32( zSign: flag; absZ : bits64): int32;
  540. var
  541. roundingMode: TFPURoundingMode;
  542. roundNearestEven: boolean;
  543. roundIncrement, roundBits: int8;
  544. z: int32;
  545. begin
  546. roundingMode := softfloat_rounding_mode;
  547. roundNearestEven := (roundingMode = float_round_nearest_even);
  548. roundIncrement := $40;
  549. if not roundNearestEven then
  550. begin
  551. if ( roundingMode = float_round_to_zero ) then
  552. begin
  553. roundIncrement := 0;
  554. end
  555. else begin
  556. roundIncrement := $7F;
  557. if ( zSign<>0 ) then
  558. begin
  559. if ( roundingMode = float_round_up ) then
  560. roundIncrement := 0;
  561. end
  562. else begin
  563. if ( roundingMode = float_round_down ) then
  564. roundIncrement := 0;
  565. end;
  566. end;
  567. end;
  568. roundBits := lo(absZ) and $7F;
  569. absZ := ( absZ + roundIncrement ) shr 7;
  570. absZ := absZ and not( bits64( ord( ( roundBits xor $40 ) = 0 ) and ord(roundNearestEven) ));
  571. z := absZ;
  572. if ( zSign<>0 ) then
  573. z := - z;
  574. if ( longint(hi( absZ )) or ( z and ( ord( z < 0 ) xor zSign ) ) )<>0 then
  575. begin
  576. float_raise( float_flag_invalid );
  577. if zSign<>0 then
  578. result:=sbits32($80000000)
  579. else
  580. result:=$7FFFFFFF;
  581. exit;
  582. end;
  583. if ( roundBits<>0 ) then
  584. set_inexact_flag;
  585. result:=z;
  586. end;
  587. {*----------------------------------------------------------------------------
  588. | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
  589. | `absZ1', with binary point between bits 63 and 64 (between the input words),
  590. | and returns the properly rounded 64-bit integer corresponding to the input.
  591. | If `zSign' is 1, the input is negated before being converted to an integer.
  592. | Ordinarily, the fixed-point input is simply rounded to an integer, with
  593. | the inexact exception raised if the input cannot be represented exactly as
  594. | an integer. However, if the fixed-point input is too large, the invalid
  595. | exception is raised and the largest positive or negative integer is
  596. | returned.
  597. *----------------------------------------------------------------------------*}
  598. function roundAndPackInt64( zSign: flag; absZ0: bits64; absZ1 : bits64): int64;
  599. var
  600. roundingMode: TFPURoundingMode;
  601. roundNearestEven, increment: flag;
  602. z: int64;
  603. label
  604. overflow;
  605. begin
  606. roundingMode := softfloat_rounding_mode;
  607. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  608. increment := ord( sbits64(absZ1) < 0 );
  609. if ( roundNearestEven=0 ) then
  610. begin
  611. if ( roundingMode = float_round_to_zero ) then
  612. begin
  613. increment := 0;
  614. end
  615. else begin
  616. if ( zSign<>0 ) then
  617. begin
  618. increment := ord(( roundingMode = float_round_down ) and (absZ1<>0));
  619. end
  620. else begin
  621. increment := ord(( roundingMode = float_round_up ) and (absZ1<>0));
  622. end;
  623. end;
  624. end;
  625. if ( increment<>0 ) then
  626. begin
  627. inc(absZ0);
  628. if ( absZ0 = 0 ) then
  629. goto overflow;
  630. absZ0 := absZ0 and not( ord( bits64( absZ1 shl 1 ) = 0 ) and roundNearestEven );
  631. end;
  632. z := absZ0;
  633. if ( zSign<>0 ) then
  634. z := - z;
  635. if ( (z<>0) and (( ord( z < 0 ) xor zSign )<>0) ) then
  636. begin
  637. overflow:
  638. float_raise( float_flag_invalid );
  639. if zSign<>0 then
  640. result:=int64($8000000000000000)
  641. else
  642. result:=int64($7FFFFFFFFFFFFFFF);
  643. exit;
  644. end;
  645. if ( absZ1<>0 ) then
  646. set_inexact_flag;
  647. result:=z;
  648. end;
  649. {*
  650. -------------------------------------------------------------------------------
  651. Shifts `a' right by the number of bits given in `count'. If any nonzero
  652. bits are shifted off, they are ``jammed'' into the least significant bit of
  653. the result by setting the least significant bit to 1. The value of `count'
  654. can be arbitrarily large; in particular, if `count' is greater than 32, the
  655. result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  656. The result is stored in the location pointed to by `zPtr'.
  657. -------------------------------------------------------------------------------
  658. *}
  659. Procedure shift32RightJamming( a: bits32 ; count: int16 ; VAR zPtr :bits32);
  660. var
  661. z: Bits32;
  662. Begin
  663. if ( count = 0 ) then
  664. z := a
  665. else
  666. if ( count < 32 ) then
  667. Begin
  668. z := ( a shr count ) or bits32( (( a shl ( ( - count ) AND 31 )) ) <> 0);
  669. End
  670. else
  671. Begin
  672. z := bits32( a <> 0 );
  673. End;
  674. zPtr := z;
  675. End;
  676. {*----------------------------------------------------------------------------
  677. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  678. | number of bits given in `count'. Any bits shifted off are lost. The value
  679. | of `count' can be arbitrarily large; in particular, if `count' is greater
  680. | than 128, the result will be 0. The result is broken into two 64-bit pieces
  681. | which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  682. *----------------------------------------------------------------------------*}
  683. procedure shift128Right(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  684. var
  685. z0, z1: bits64;
  686. negCount: int8;
  687. begin
  688. negCount := ( - count ) and 63;
  689. if ( count = 0 ) then
  690. begin
  691. z1 := a1;
  692. z0 := a0;
  693. end
  694. else if ( count < 64 ) then
  695. begin
  696. z1 := ( a0 shl negCount ) or ( a1 shr count );
  697. z0 := a0 shr count;
  698. end
  699. else
  700. begin
  701. if ( count < 128 ) then
  702. z1 := a0 shr ( count and 63 )
  703. else
  704. z1 := 0;
  705. z0 := 0;
  706. end;
  707. z1Ptr := z1;
  708. z0Ptr := z0;
  709. end;
  710. {*----------------------------------------------------------------------------
  711. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  712. | number of bits given in `count'. If any nonzero bits are shifted off, they
  713. | are ``jammed'' into the least significant bit of the result by setting the
  714. | least significant bit to 1. The value of `count' can be arbitrarily large;
  715. | in particular, if `count' is greater than 128, the result will be either
  716. | 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  717. | nonzero. The result is broken into two 64-bit pieces which are stored at
  718. | the locations pointed to by `z0Ptr' and `z1Ptr'.
  719. *----------------------------------------------------------------------------*}
  720. procedure shift128RightJamming(a0,a1 : bits64; count : int16; var z0Ptr, z1Ptr : bits64);
  721. var
  722. z0,z1 : bits64;
  723. negCount : int8;
  724. begin
  725. negCount := ( - count ) and 63;
  726. if ( count = 0 ) then begin
  727. z1 := a1;
  728. z0 := a0;
  729. end
  730. else if ( count < 64 ) then begin
  731. z1 := ( a0 shl negCount ) or ( a1 shr count ) or ord( ( a1 shl negCount ) <> 0 );
  732. z0 := a0 shr count;
  733. end
  734. else begin
  735. if ( count = 64 ) then begin
  736. z1 := a0 or ord( a1 <> 0 );
  737. end
  738. else if ( count < 128 ) then begin
  739. z1 := ( a0 shr ( count and 63 ) ) or ord( ( ( a0 shl negCount ) or a1 ) <> 0 );
  740. end
  741. else begin
  742. z1 := ord( ( a0 or a1 ) <> 0 );
  743. end;
  744. z0 := 0;
  745. end;
  746. z1Ptr := z1;
  747. z0Ptr := z0;
  748. end;
  749. {*
  750. -------------------------------------------------------------------------------
  751. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  752. number of bits given in `count'. Any bits shifted off are lost. The value
  753. of `count' can be arbitrarily large; in particular, if `count' is greater
  754. than 64, the result will be 0. The result is broken into two 32-bit pieces
  755. which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  756. -------------------------------------------------------------------------------
  757. *}
  758. Procedure
  759. shift64Right(
  760. a0 :bits32; a1: bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32);
  761. Var
  762. z0, z1: bits32;
  763. negCount : int8;
  764. Begin
  765. negCount := ( - count ) AND 31;
  766. if ( count = 0 ) then
  767. Begin
  768. z1 := a1;
  769. z0 := a0;
  770. End
  771. else if ( count < 32 ) then
  772. Begin
  773. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  774. z0 := a0 shr count;
  775. End
  776. else
  777. Begin
  778. if (count < 64) then
  779. z1 := ( a0 shr ( count AND 31 ) )
  780. else
  781. z1 := 0;
  782. z0 := 0;
  783. End;
  784. z1Ptr := z1;
  785. z0Ptr := z0;
  786. End;
  787. {*
  788. -------------------------------------------------------------------------------
  789. Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
  790. number of bits given in `count'. If any nonzero bits are shifted off, they
  791. are ``jammed'' into the least significant bit of the result by setting the
  792. least significant bit to 1. The value of `count' can be arbitrarily large;
  793. in particular, if `count' is greater than 64, the result will be either 0
  794. or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  795. nonzero. The result is broken into two 32-bit pieces which are stored at
  796. the locations pointed to by `z0Ptr' and `z1Ptr'.
  797. -------------------------------------------------------------------------------
  798. *}
  799. Procedure
  800. shift64RightJamming(
  801. a0:bits32; a1: bits32; count:int16; VAR Z0Ptr :bits32;VAR z1Ptr: bits32 );
  802. VAR
  803. z0, z1 : bits32;
  804. negCount : int8;
  805. Begin
  806. negCount := ( - count ) AND 31;
  807. if ( count = 0 ) then
  808. Begin
  809. z1 := a1;
  810. z0 := a0;
  811. End
  812. else
  813. if ( count < 32 ) then
  814. Begin
  815. z1 := ( a0 shl negCount ) OR ( a1 shr count ) OR bits32( ( a1 shl negCount ) <> 0 );
  816. z0 := a0 shr count;
  817. End
  818. else
  819. Begin
  820. if ( count = 32 ) then
  821. Begin
  822. z1 := a0 OR bits32( a1 <> 0 );
  823. End
  824. else
  825. if ( count < 64 ) Then
  826. Begin
  827. z1 := ( a0 shr ( count AND 31 ) ) OR bits32( ( ( a0 shl negCount ) OR a1 ) <> 0 );
  828. End
  829. else
  830. Begin
  831. z1 := bits32( ( a0 OR a1 ) <> 0 );
  832. End;
  833. z0 := 0;
  834. End;
  835. z1Ptr := z1;
  836. z0Ptr := z0;
  837. End;
  838. {*----------------------------------------------------------------------------
  839. | Shifts `a' right by the number of bits given in `count'. If any nonzero
  840. | bits are shifted off, they are ``jammed'' into the least significant bit of
  841. | the result by setting the least significant bit to 1. The value of `count'
  842. | can be arbitrarily large; in particular, if `count' is greater than 64, the
  843. | result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  844. | The result is stored in the location pointed to by `zPtr'.
  845. *----------------------------------------------------------------------------*}
  846. procedure shift64RightJamming(a: bits64; count: int16; var zPtr : bits64);
  847. var
  848. z: bits64;
  849. begin
  850. if ( count = 0 ) then
  851. begin
  852. z := a;
  853. end
  854. else if ( count < 64 ) then
  855. begin
  856. z := ( a shr count ) or ord( ( a shl ( ( - count ) and 63 ) ) <> 0 );
  857. end
  858. else
  859. begin
  860. z := ord( a <> 0 );
  861. end;
  862. zPtr := z;
  863. end;
  864. {$if not defined(shift64ExtraRightJamming)}
  865. procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  866. overload;
  867. forward;
  868. {$endif}
  869. {*
  870. -------------------------------------------------------------------------------
  871. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
  872. by 32 _plus_ the number of bits given in `count'. The shifted result is
  873. at most 64 nonzero bits; these are broken into two 32-bit pieces which are
  874. stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  875. off form a third 32-bit result as follows: The _last_ bit shifted off is
  876. the most-significant bit of the extra result, and the other 31 bits of the
  877. extra result are all zero if and only if _all_but_the_last_ bits shifted off
  878. were all zero. This extra result is stored in the location pointed to by
  879. `z2Ptr'. The value of `count' can be arbitrarily large.
  880. (This routine makes more sense if `a0', `a1', and `a2' are considered
  881. to form a fixed-point value with binary point between `a1' and `a2'. This
  882. fixed-point value is shifted right by the number of bits given in `count',
  883. and the integer part of the result is returned at the locations pointed to
  884. by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  885. corrupted as described above, and is returned at the location pointed to by
  886. `z2Ptr'.)
  887. -------------------------------------------------------------------------------
  888. }
  889. Procedure
  890. shift64ExtraRightJamming(
  891. a0: bits32;
  892. a1: bits32;
  893. a2: bits32;
  894. count: int16;
  895. VAR z0Ptr: bits32;
  896. VAR z1Ptr: bits32;
  897. VAR z2Ptr: bits32
  898. ); overload;
  899. Var
  900. z0, z1, z2: bits32;
  901. negCount : int8;
  902. Begin
  903. negCount := ( - count ) AND 31;
  904. if ( count = 0 ) then
  905. Begin
  906. z2 := a2;
  907. z1 := a1;
  908. z0 := a0;
  909. End
  910. else
  911. Begin
  912. if ( count < 32 ) Then
  913. Begin
  914. z2 := a1 shl negCount;
  915. z1 := ( a0 shl negCount ) OR ( a1 shr count );
  916. z0 := a0 shr count;
  917. End
  918. else
  919. Begin
  920. if ( count = 32 ) then
  921. Begin
  922. z2 := a1;
  923. z1 := a0;
  924. End
  925. else
  926. Begin
  927. a2 := a2 or a1;
  928. if ( count < 64 ) then
  929. Begin
  930. z2 := a0 shl negCount;
  931. z1 := a0 shr ( count AND 31 );
  932. End
  933. else
  934. Begin
  935. if count = 64 then
  936. z2 := a0
  937. else
  938. z2 := bits32(a0 <> 0);
  939. z1 := 0;
  940. End;
  941. End;
  942. z0 := 0;
  943. End;
  944. z2 := z2 or bits32( a2 <> 0 );
  945. End;
  946. z2Ptr := z2;
  947. z1Ptr := z1;
  948. z0Ptr := z0;
  949. End;
  950. {*
  951. -------------------------------------------------------------------------------
  952. Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
  953. number of bits given in `count'. Any bits shifted off are lost. The value
  954. of `count' must be less than 32. The result is broken into two 32-bit
  955. pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  956. -------------------------------------------------------------------------------
  957. *}
  958. Procedure
  959. shortShift64Left(
  960. a0:bits32; a1:bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
  961. Begin
  962. z1Ptr := a1 shl count;
  963. if count = 0 then
  964. z0Ptr := a0
  965. else
  966. z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );
  967. End;
  968. {*
  969. -------------------------------------------------------------------------------
  970. Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
  971. by the number of bits given in `count'. Any bits shifted off are lost.
  972. The value of `count' must be less than 32. The result is broken into three
  973. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  974. `z1Ptr', and `z2Ptr'.
  975. -------------------------------------------------------------------------------
  976. *}
  977. Procedure
  978. shortShift96Left(
  979. a0: bits32;
  980. a1: bits32;
  981. a2: bits32;
  982. count: int16;
  983. VAR z0Ptr: bits32;
  984. VAR z1Ptr: bits32;
  985. VAR z2Ptr: bits32
  986. );
  987. Var
  988. z0, z1, z2: bits32;
  989. negCount: int8;
  990. Begin
  991. z2 := a2 shl count;
  992. z1 := a1 shl count;
  993. z0 := a0 shl count;
  994. if ( 0 < count ) then
  995. Begin
  996. negCount := ( ( - count ) AND 31 );
  997. z1 := z1 or (a2 shr negCount);
  998. z0 := z0 or (a1 shr negCount);
  999. End;
  1000. z2Ptr := z2;
  1001. z1Ptr := z1;
  1002. z0Ptr := z0;
  1003. End;
  1004. {*----------------------------------------------------------------------------
  1005. | Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
  1006. | number of bits given in `count'. Any bits shifted off are lost. The value
  1007. | of `count' must be less than 64. The result is broken into two 64-bit
  1008. | pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  1009. *----------------------------------------------------------------------------*}
  1010. procedure shortShift128Left(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  1011. begin
  1012. z1Ptr := a1 shl count;
  1013. if count=0 then
  1014. z0Ptr:=a0
  1015. else
  1016. z0Ptr:=( a0 shl count ) or ( a1 shr ( ( - count ) and 63 ) );
  1017. end;
  1018. {*
  1019. -------------------------------------------------------------------------------
  1020. Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
  1021. value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
  1022. any carry out is lost. The result is broken into two 32-bit pieces which
  1023. are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  1024. -------------------------------------------------------------------------------
  1025. *}
  1026. Procedure
  1027. add64(
  1028. a0:bits32; a1:bits32; b0:bits32; b1:bits32; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}
  1029. Var
  1030. z1: bits32;
  1031. Begin
  1032. z1 := a1 + b1;
  1033. z1Ptr := z1;
  1034. z0Ptr := a0 + b0 + bits32( z1 < a1 );
  1035. End;
  1036. {*
  1037. -------------------------------------------------------------------------------
  1038. Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
  1039. 96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  1040. modulo 2^96, so any carry out is lost. The result is broken into three
  1041. 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
  1042. `z1Ptr', and `z2Ptr'.
  1043. -------------------------------------------------------------------------------
  1044. *}
  1045. Procedure
  1046. add96(
  1047. a0: bits32;
  1048. a1: bits32;
  1049. a2: bits32;
  1050. b0: bits32;
  1051. b1: bits32;
  1052. b2: bits32;
  1053. VAR z0Ptr: bits32;
  1054. VAR z1Ptr: bits32;
  1055. VAR z2Ptr: bits32
  1056. );
  1057. var
  1058. z0, z1, z2: bits32;
  1059. carry0, carry1: int8;
  1060. Begin
  1061. z2 := a2 + b2;
  1062. carry1 := int8( z2 < a2 );
  1063. z1 := a1 + b1;
  1064. carry0 := int8( z1 < a1 );
  1065. z0 := a0 + b0;
  1066. z1 := z1 + carry1;
  1067. z0 := z0 + bits32( z1 < carry1 );
  1068. z0 := z0 + carry0;
  1069. z2Ptr := z2;
  1070. z1Ptr := z1;
  1071. z0Ptr := z0;
  1072. End;
  1073. {*----------------------------------------------------------------------------
  1074. | Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
  1075. | by the number of bits given in `count'. Any bits shifted off are lost.
  1076. | The value of `count' must be less than 64. The result is broken into three
  1077. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  1078. | `z1Ptr', and `z2Ptr'.
  1079. *----------------------------------------------------------------------------*}
  1080. procedure shortShift192Left(a0,a1,a2 : bits64;count : int16;var z0Ptr,z1Ptr,z2Ptr : bits64);
  1081. var
  1082. z0, z1, z2 : bits64;
  1083. negCount : int8;
  1084. begin
  1085. z2 := a2 shl count;
  1086. z1 := a1 shl count;
  1087. z0 := a0 shl count;
  1088. if ( 0 < count ) then
  1089. begin
  1090. negCount := ( ( - count ) and 63 );
  1091. z1 := z1 or (a2 shr negCount);
  1092. z0 := z0 or (a1 shr negCount);
  1093. end;
  1094. z2Ptr := z2;
  1095. z1Ptr := z1;
  1096. z0Ptr := z0;
  1097. end;
  1098. {*----------------------------------------------------------------------------
  1099. | Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
  1100. | value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
  1101. | any carry out is lost. The result is broken into two 64-bit pieces which
  1102. | are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  1103. *----------------------------------------------------------------------------*}
  1104. procedure add128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}
  1105. var
  1106. z1 : bits64;
  1107. begin
  1108. z1 := a1 + b1;
  1109. z1Ptr := z1;
  1110. z0Ptr := a0 + b0 + ord( z1 < a1 );
  1111. end;
  1112. {*----------------------------------------------------------------------------
  1113. | Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
  1114. | 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  1115. | modulo 2^192, so any carry out is lost. The result is broken into three
  1116. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  1117. | `z1Ptr', and `z2Ptr'.
  1118. *----------------------------------------------------------------------------*}
  1119. procedure add192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);
  1120. var
  1121. z0, z1, z2 : bits64;
  1122. carry0, carry1 : int8;
  1123. begin
  1124. z2 := a2 + b2;
  1125. carry1 := ord( z2 < a2 );
  1126. z1 := a1 + b1;
  1127. carry0 := ord( z1 < a1 );
  1128. z0 := a0 + b0;
  1129. inc(z1, carry1);
  1130. inc(z0, ord( z1 < carry1 ));
  1131. inc(z0, carry0);
  1132. z2Ptr := z2;
  1133. z1Ptr := z1;
  1134. z0Ptr := z0;
  1135. end;
  1136. {*
  1137. -------------------------------------------------------------------------------
  1138. Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
  1139. 64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  1140. 2^64, so any borrow out (carry out) is lost. The result is broken into two
  1141. 32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  1142. `z1Ptr'.
  1143. -------------------------------------------------------------------------------
  1144. *}
  1145. Procedure
  1146. sub64(
  1147. a0: bits32; a1 : bits32; b0 :bits32; b1: bits32; VAR z0Ptr:bits32; VAR z1Ptr: bits32 );{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}
  1148. Begin
  1149. z1Ptr := a1 - b1;
  1150. z0Ptr := a0 - b0 - bits32( a1 < b1 );
  1151. End;
  1152. {*
  1153. -------------------------------------------------------------------------------
  1154. Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
  1155. the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
  1156. is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
  1157. into three 32-bit pieces which are stored at the locations pointed to by
  1158. `z0Ptr', `z1Ptr', and `z2Ptr'.
  1159. -------------------------------------------------------------------------------
  1160. *}
  1161. Procedure
  1162. sub96(
  1163. a0:bits32;
  1164. a1:bits32;
  1165. a2:bits32;
  1166. b0:bits32;
  1167. b1:bits32;
  1168. b2:bits32;
  1169. VAR z0Ptr:bits32;
  1170. VAR z1Ptr:bits32;
  1171. VAR z2Ptr:bits32
  1172. );
  1173. Var
  1174. z0, z1, z2: bits32;
  1175. borrow0, borrow1: int8;
  1176. Begin
  1177. z2 := a2 - b2;
  1178. borrow1 := int8( a2 < b2 );
  1179. z1 := a1 - b1;
  1180. borrow0 := int8( a1 < b1 );
  1181. z0 := a0 - b0;
  1182. z0 := z0 - bits32( z1 < borrow1 );
  1183. z1 := z1 - borrow1;
  1184. z0 := z0 -borrow0;
  1185. z2Ptr := z2;
  1186. z1Ptr := z1;
  1187. z0Ptr := z0;
  1188. End;
  1189. {*----------------------------------------------------------------------------
  1190. | Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
  1191. | 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  1192. | 2^128, so any borrow out (carry out) is lost. The result is broken into two
  1193. | 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  1194. | `z1Ptr'.
  1195. *----------------------------------------------------------------------------*}
  1196. procedure sub128( a0, a1, b0, b1 : bits64; var z0Ptr, z1Ptr : bits64);
  1197. begin
  1198. z1Ptr := a1 - b1;
  1199. z0Ptr := a0 - b0 - ord( a1 < b1 );
  1200. end;
  1201. {*----------------------------------------------------------------------------
  1202. | Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
  1203. | from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
  1204. | Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
  1205. | result is broken into three 64-bit pieces which are stored at the locations
  1206. | pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
  1207. *----------------------------------------------------------------------------*}
  1208. procedure sub192(a0,a1,a2,b0,b1,b2: bits64; var z0Ptr,z1Ptr,z2Ptr : bits64);
  1209. var
  1210. z0, z1, z2 : bits64;
  1211. borrow0, borrow1 : int8;
  1212. begin
  1213. z2 := a2 - b2;
  1214. borrow1 := ord( a2 < b2 );
  1215. z1 := a1 - b1;
  1216. borrow0 := ord( a1 < b1 );
  1217. z0 := a0 - b0;
  1218. dec(z0, ord( z1 < borrow1 ));
  1219. dec(z1, borrow1);
  1220. dec(z0, borrow0);
  1221. z2Ptr := z2;
  1222. z1Ptr := z1;
  1223. z0Ptr := z0;
  1224. end;
  1225. {*
  1226. -------------------------------------------------------------------------------
  1227. Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
  1228. into two 32-bit pieces which are stored at the locations pointed to by
  1229. `z0Ptr' and `z1Ptr'.
  1230. -------------------------------------------------------------------------------
  1231. *}
  1232. {$IFDEF SOFTFPU_COMPILER_MUL32TO64}
  1233. Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr :bits32 );{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}
  1234. var
  1235. tmp: qword;
  1236. begin
  1237. tmp:=qword(a) * b;
  1238. z0ptr:=hi(tmp);
  1239. z1ptr:=lo(tmp);
  1240. end;
  1241. {$ELSE}
  1242. Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr
  1243. :bits32 );
  1244. Var
  1245. aHigh, aLow, bHigh, bLow: bits16;
  1246. z0, zMiddleA, zMiddleB, z1: bits32;
  1247. Begin
  1248. aLow := bits16(a);
  1249. aHigh := a shr 16;
  1250. bLow := bits16(b);
  1251. bHigh := b shr 16;
  1252. z1 := ( bits32( aLow) ) * bLow;
  1253. zMiddleA := ( bits32 (aLow) ) * bHigh;
  1254. zMiddleB := ( bits32 (aHigh) ) * bLow;
  1255. z0 := ( bits32 (aHigh) ) * bHigh;
  1256. zMiddleA := zMiddleA + zMiddleB;
  1257. z0 := z0 + ( ( bits32 ( zMiddleA < zMiddleB ) ) shl 16 ) + ( zMiddleA shr 16 );
  1258. zMiddleA := zmiddleA shl 16;
  1259. z1 := z1 + zMiddleA;
  1260. z0 := z0 + bits32( z1 < zMiddleA );
  1261. z1Ptr := z1;
  1262. z0Ptr := z0;
  1263. End;
  1264. {$ENDIF}
  1265. {*
  1266. -------------------------------------------------------------------------------
  1267. Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
  1268. to obtain a 96-bit product. The product is broken into three 32-bit pieces
  1269. which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  1270. `z2Ptr'.
  1271. -------------------------------------------------------------------------------
  1272. *}
  1273. Procedure
  1274. mul64By32To96(
  1275. a0:bits32;
  1276. a1:bits32;
  1277. b:bits32;
  1278. VAR z0Ptr:bits32;
  1279. VAR z1Ptr:bits32;
  1280. VAR z2Ptr:bits32
  1281. );
  1282. Var
  1283. z0, z1, z2, more1: bits32;
  1284. Begin
  1285. mul32To64( a1, b, z1, z2 );
  1286. mul32To64( a0, b, z0, more1 );
  1287. add64( z0, more1, 0, z1, z0, z1 );
  1288. z2Ptr := z2;
  1289. z1Ptr := z1;
  1290. z0Ptr := z0;
  1291. End;
  1292. {*
  1293. -------------------------------------------------------------------------------
  1294. Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
  1295. 64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
  1296. product. The product is broken into four 32-bit pieces which are stored at
  1297. the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  1298. -------------------------------------------------------------------------------
  1299. *}
  1300. Procedure
  1301. mul64To128(
  1302. a0:bits32;
  1303. a1:bits32;
  1304. b0:bits32;
  1305. b1:bits32;
  1306. VAR z0Ptr:bits32;
  1307. VAR z1Ptr:bits32;
  1308. VAR z2Ptr:bits32;
  1309. VAR z3Ptr:bits32
  1310. );
  1311. Var
  1312. z0, z1, z2, z3: bits32;
  1313. more1, more2: bits32;
  1314. Begin
  1315. mul32To64( a1, b1, z2, z3 );
  1316. mul32To64( a1, b0, z1, more2 );
  1317. add64( z1, more2, 0, z2, z1, z2 );
  1318. mul32To64( a0, b0, z0, more1 );
  1319. add64( z0, more1, 0, z1, z0, z1 );
  1320. mul32To64( a0, b1, more1, more2 );
  1321. add64( more1, more2, 0, z2, more1, z2 );
  1322. add64( z0, z1, 0, more1, z0, z1 );
  1323. z3Ptr := z3;
  1324. z2Ptr := z2;
  1325. z1Ptr := z1;
  1326. z0Ptr := z0;
  1327. End;
  1328. {*----------------------------------------------------------------------------
  1329. | Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
  1330. | into two 64-bit pieces which are stored at the locations pointed to by
  1331. | `z0Ptr' and `z1Ptr'.
  1332. *----------------------------------------------------------------------------*}
  1333. procedure mul64To128( a, b : bits64; var z0Ptr, z1Ptr : bits64);
  1334. var
  1335. aHigh, aLow, bHigh, bLow : bits32;
  1336. z0, zMiddleA, zMiddleB, z1 : bits64;
  1337. begin
  1338. aLow := a;
  1339. aHigh := a shr 32;
  1340. bLow := b;
  1341. bHigh := b shr 32;
  1342. z1 := ( bits64(aLow) ) * bLow;
  1343. zMiddleA := ( bits64( aLow )) * bHigh;
  1344. zMiddleB := ( bits64( aHigh )) * bLow;
  1345. z0 := ( bits64(aHigh) ) * bHigh;
  1346. inc(zMiddleA, zMiddleB);
  1347. inc(z0 ,( ( bits64( zMiddleA < zMiddleB ) ) shl 32 ) + ( zMiddleA shr 32 ));
  1348. zMiddleA := zMiddleA shl 32;
  1349. inc(z1, zMiddleA);
  1350. inc(z0, ord( z1 < zMiddleA ));
  1351. z1Ptr := z1;
  1352. z0Ptr := z0;
  1353. end;
  1354. {*----------------------------------------------------------------------------
  1355. | Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
  1356. | 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
  1357. | product. The product is broken into four 64-bit pieces which are stored at
  1358. | the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  1359. *----------------------------------------------------------------------------*}
  1360. procedure mul128To256(a0,a1,b0,b1 : bits64;var z0Ptr,z1Ptr,z2Ptr,z3Ptr : bits64);
  1361. var
  1362. z0,z1,z2,z3,more1,more2 : bits64;
  1363. begin
  1364. mul64To128( a1, b1, z2, z3 );
  1365. mul64To128( a1, b0, z1, more2 );
  1366. add128( z1, more2, 0, z2, z1, z2 );
  1367. mul64To128( a0, b0, z0, more1 );
  1368. add128( z0, more1, 0, z1, z0, z1 );
  1369. mul64To128( a0, b1, more1, more2 );
  1370. add128( more1, more2, 0, z2, more1, z2 );
  1371. add128( z0, z1, 0, more1, z0, z1 );
  1372. z3Ptr := z3;
  1373. z2Ptr := z2;
  1374. z1Ptr := z1;
  1375. z0Ptr := z0;
  1376. end;
  1377. {*----------------------------------------------------------------------------
  1378. | Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
  1379. | `b' to obtain a 192-bit product. The product is broken into three 64-bit
  1380. | pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  1381. | `z2Ptr'.
  1382. *----------------------------------------------------------------------------*}
  1383. procedure mul128By64To192(a0,a1,b : bits64;var z0Ptr,z1Ptr,z2Ptr : bits64);
  1384. var
  1385. z0, z1, z2, more1 : bits64;
  1386. begin
  1387. mul64To128( a1, b, z1, z2 );
  1388. mul64To128( a0, b, z0, more1 );
  1389. add128( z0, more1, 0, z1, z0, z1 );
  1390. z2Ptr := z2;
  1391. z1Ptr := z1;
  1392. z0Ptr := z0;
  1393. end;
  1394. {*----------------------------------------------------------------------------
  1395. | Returns an approximation to the 64-bit integer quotient obtained by dividing
  1396. | `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
  1397. | divisor `b' must be at least 2^63. If q is the exact quotient truncated
  1398. | toward zero, the approximation returned lies between q and q + 2 inclusive.
  1399. | If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
  1400. | unsigned integer is returned.
  1401. *----------------------------------------------------------------------------*}
  1402. Function estimateDiv128To64( a0:bits64; a1: bits64; b:bits64): bits64;
  1403. var
  1404. b0, b1, rem0, rem1, term0, term1, z : bits64;
  1405. begin
  1406. if ( b <= a0 ) then
  1407. begin
  1408. result:=qword( $FFFFFFFFFFFFFFFF );
  1409. exit;
  1410. end;
  1411. b0 := b shr 32;
  1412. if ( b0 shl 32 <= a0 ) then
  1413. z:=qword( $FFFFFFFF00000000 )
  1414. else
  1415. z:=( a0 div b0 ) shl 32;
  1416. mul64To128( b, z, term0, term1 );
  1417. sub128( a0, a1, term0, term1, rem0, rem1 );
  1418. while ( ( sbits64(rem0) ) < 0 ) do begin
  1419. dec(z,qword( $100000000 ));
  1420. b1 := b shl 32;
  1421. add128( rem0, rem1, b0, b1, rem0, rem1 );
  1422. end;
  1423. rem0 := ( rem0 shl 32 ) or ( rem1 shr 32 );
  1424. if ( b0 shl 32 <= rem0 ) then
  1425. z:=z or $FFFFFFFF
  1426. else
  1427. z:=z or rem0 div b0;
  1428. result:=z;
  1429. end;
  1430. {*
  1431. -------------------------------------------------------------------------------
  1432. Returns an approximation to the 32-bit integer quotient obtained by dividing
  1433. `b' into the 64-bit value formed by concatenating `a0' and `a1'. The
  1434. divisor `b' must be at least 2^31. If q is the exact quotient truncated
  1435. toward zero, the approximation returned lies between q and q + 2 inclusive.
  1436. If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
  1437. unsigned integer is returned.
  1438. -------------------------------------------------------------------------------
  1439. *}
  1440. Function estimateDiv64To32( a0:bits32; a1: bits32; b:bits32): bits32;
  1441. Var
  1442. b0, b1: bits32;
  1443. rem0, rem1, term0, term1: bits32;
  1444. z: bits32;
  1445. Begin
  1446. if ( b <= a0 ) then
  1447. Begin
  1448. estimateDiv64To32 := $FFFFFFFF;
  1449. exit;
  1450. End;
  1451. b0 := b shr 16;
  1452. if ( b0 shl 16 <= a0 ) then
  1453. z:= $FFFF0000
  1454. else
  1455. z:= ( a0 div b0 ) shl 16;
  1456. mul32To64( b, z, term0, term1 );
  1457. sub64( a0, a1, term0, term1, rem0, rem1 );
  1458. while ( ( sbits32 (rem0) ) < 0 ) do
  1459. Begin
  1460. z := z - $10000;
  1461. b1 := b shl 16;
  1462. add64( rem0, rem1, b0, b1, rem0, rem1 );
  1463. End;
  1464. rem0 := ( rem0 shl 16 ) OR ( rem1 shr 16 );
  1465. if ( b0 shl 16 <= rem0 ) then
  1466. z := z or $FFFF
  1467. else
  1468. z := z or (rem0 div b0);
  1469. estimateDiv64To32 := z;
  1470. End;
  1471. {*
  1472. -------------------------------------------------------------------------------
  1473. Returns an approximation to the square root of the 32-bit significand given
  1474. by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
  1475. `aExp' (the least significant bit) is 1, the integer returned approximates
  1476. 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
  1477. is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
  1478. case, the approximation returned lies strictly within +/-2 of the exact
  1479. value.
  1480. -------------------------------------------------------------------------------
  1481. *}
  1482. Function estimateSqrt32( aExp: int16; a: bits32 ): bits32;
  1483. const sqrtOddAdjustments: array[0..15] of bits16 = (
  1484. $0004, $0022, $005D, $00B1, $011D, $019F, $0236, $02E0,
  1485. $039C, $0468, $0545, $0631, $072B, $0832, $0946, $0A67
  1486. );
  1487. const sqrtEvenAdjustments: array[0..15] of bits16 = (
  1488. $0A2D, $08AF, $075A, $0629, $051A, $0429, $0356, $029E,
  1489. $0200, $0179, $0109, $00AF, $0068, $0034, $0012, $0002
  1490. );
  1491. Var
  1492. index: int8;
  1493. z: bits32;
  1494. Begin
  1495. index := ( a shr 27 ) AND 15;
  1496. if ( aExp AND 1 ) <> 0 then
  1497. Begin
  1498. z := $4000 + ( a shr 17 ) - sqrtOddAdjustments[ index ];
  1499. z := ( ( a div z ) shl 14 ) + ( z shl 15 );
  1500. a := a shr 1;
  1501. End
  1502. else
  1503. Begin
  1504. z := $8000 + ( a shr 17 ) - sqrtEvenAdjustments[ index ];
  1505. z := a div z + z;
  1506. if ( $20000 <= z ) then
  1507. z := $FFFF8000
  1508. else
  1509. z := ( z shl 15 );
  1510. if ( z <= a ) then
  1511. Begin
  1512. estimateSqrt32 := bits32 ( SarLongint( sbits32 (a)) );
  1513. exit;
  1514. End;
  1515. End;
  1516. estimateSqrt32 := ( ( estimateDiv64To32( a, 0, z ) ) shr 1 ) + ( z shr 1 );
  1517. End;
  1518. {*
  1519. -------------------------------------------------------------------------------
  1520. Returns the number of leading 0 bits before the most-significant 1 bit of
  1521. `a'. If `a' is zero, 32 is returned.
  1522. -------------------------------------------------------------------------------
  1523. *}
  1524. Function countLeadingZeros32( a:bits32 ): int8;
  1525. const countLeadingZerosHigh:array[0..255] of int8 = (
  1526. 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
  1527. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1528. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1529. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1530. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1531. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1532. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1533. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1534. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1535. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1536. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1537. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1538. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1539. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1540. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1541. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  1542. );
  1543. Var
  1544. shiftCount: int8;
  1545. Begin
  1546. shiftCount := 0;
  1547. if ( a < $10000 ) then
  1548. Begin
  1549. shiftCount := shiftcount + 16;
  1550. a := a shl 16;
  1551. End;
  1552. if ( a < $1000000 ) then
  1553. Begin
  1554. shiftCount := shiftcount + 8;
  1555. a := a shl 8;
  1556. end;
  1557. shiftCount := shiftcount + countLeadingZerosHigh[ a shr 24 ];
  1558. countLeadingZeros32:= shiftCount;
  1559. End;
  1560. {*----------------------------------------------------------------------------
  1561. | Returns the number of leading 0 bits before the most-significant 1 bit of
  1562. | `a'. If `a' is zero, 64 is returned.
  1563. *----------------------------------------------------------------------------*}
  1564. function countLeadingZeros64( a : bits64): int8;
  1565. var
  1566. shiftcount : int8;
  1567. Begin
  1568. shiftCount := 0;
  1569. if ( a < bits64(bits64(1) shl 32 )) then
  1570. shiftCount := shiftcount + 32
  1571. else
  1572. a := a shr 32;
  1573. shiftCount := shiftCount + countLeadingZeros32( a );
  1574. countLeadingZeros64:= shiftCount;
  1575. End;
  1576. {*
  1577. -------------------------------------------------------------------------------
  1578. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1579. than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
  1580. Otherwise, returns 0.
  1581. -------------------------------------------------------------------------------
  1582. *}
  1583. Function le64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}
  1584. Begin
  1585. le64:= flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 <= b1 ) );
  1586. End;
  1587. {*
  1588. -------------------------------------------------------------------------------
  1589. Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
  1590. than the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1591. returns 0.
  1592. -------------------------------------------------------------------------------
  1593. *}
  1594. Function lt64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;{$IFDEF SOFTFPU_INLINE}inline;{$ENDIF}
  1595. Begin
  1596. lt64 := flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 < b1 ) );
  1597. End;
  1598. const
  1599. float128_default_nan_high = qword($FFFFFFFFFFFFFFFF);
  1600. float128_default_nan_low = qword($FFFFFFFFFFFFFFFF);
  1601. (*****************************************************************************)
  1602. (* End Low-Level arithmetic *)
  1603. (*****************************************************************************)
  1604. {*----------------------------------------------------------------------------
  1605. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  1606. | than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
  1607. | returns 0.
  1608. *----------------------------------------------------------------------------*}
  1609. function lt128(a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  1610. begin
  1611. result := ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 < b1 ) ));
  1612. end;
  1613. {*
  1614. -------------------------------------------------------------------------------
  1615. Functions and definitions to determine: (1) whether tininess for underflow
  1616. is detected before or after rounding by default, (2) what (if anything)
  1617. happens when exceptions are raised, (3) how signaling NaNs are distinguished
  1618. from quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNs
  1619. are propagated from function inputs to output. These details are ENDIAN
  1620. specific
  1621. -------------------------------------------------------------------------------
  1622. *}
  1623. {$IFDEF ENDIAN_LITTLE}
  1624. {*
  1625. -------------------------------------------------------------------------------
  1626. Internal canonical NaN format.
  1627. -------------------------------------------------------------------------------
  1628. *}
  1629. TYPE
  1630. commonNaNT = record
  1631. high, low : bits32;
  1632. sign: flag;
  1633. end;
  1634. {*
  1635. -------------------------------------------------------------------------------
  1636. The pattern for a default generated single-precision NaN.
  1637. -------------------------------------------------------------------------------
  1638. *}
  1639. const float32_default_nan = $FFC00000;
  1640. {*
  1641. -------------------------------------------------------------------------------
  1642. Returns 1 if the single-precision floating-point value `a' is a NaN;
  1643. otherwise returns 0.
  1644. -------------------------------------------------------------------------------
  1645. *}
  1646. Function float32_is_nan( a : float32 ): flag;
  1647. Begin
  1648. float32_is_nan:= flag( $FF000000 < bits32 ( a shl 1 ) );
  1649. End;
  1650. {*
  1651. -------------------------------------------------------------------------------
  1652. Returns 1 if the single-precision floating-point value `a' is a signaling
  1653. NaN; otherwise returns 0.
  1654. -------------------------------------------------------------------------------
  1655. *}
  1656. Function float32_is_signaling_nan( a : float32 ): flag;
  1657. Begin
  1658. float32_is_signaling_nan := flag
  1659. (( ( ( a shr 22 ) and $1FF ) = $1FE ) and (( a and $003FFFFF )<>0));
  1660. End;
  1661. {*
  1662. -------------------------------------------------------------------------------
  1663. Returns the result of converting the single-precision floating-point NaN
  1664. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1665. exception is raised.
  1666. -------------------------------------------------------------------------------
  1667. *}
  1668. function float32ToCommonNaN(a: float32) : commonNaNT;
  1669. var
  1670. z : commonNaNT ;
  1671. Begin
  1672. if ( float32_is_signaling_nan( a ) <> 0) then
  1673. float_raise( float_flag_invalid );
  1674. z.sign := a shr 31;
  1675. z.low := 0;
  1676. z.high := a shl 9;
  1677. result := z;
  1678. End;
  1679. {*
  1680. -------------------------------------------------------------------------------
  1681. Returns the result of converting the canonical NaN `a' to the single-
  1682. precision floating-point format.
  1683. -------------------------------------------------------------------------------
  1684. *}
  1685. Function commonNaNToFloat32( a : commonNaNT ): float32;
  1686. Begin
  1687. commonNaNToFloat32 := ( ( bits32 (a.sign) ) shl 31 ) or $7FC00000 or ( a.high shr 9 );
  1688. End;
  1689. {*
  1690. -------------------------------------------------------------------------------
  1691. Takes two single-precision floating-point values `a' and `b', one of which
  1692. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1693. signaling NaN, the invalid exception is raised.
  1694. -------------------------------------------------------------------------------
  1695. *}
  1696. Function propagateFloat32NaN( a : float32 ; b: float32 ): float32;
  1697. Var
  1698. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1699. label returnLargerSignificand;
  1700. Begin
  1701. aIsNaN := float32_is_nan( a );
  1702. aIsSignalingNaN := float32_is_signaling_nan( a );
  1703. bIsNaN := float32_is_nan( b );
  1704. bIsSignalingNaN := float32_is_signaling_nan( b );
  1705. a := a or $00400000;
  1706. b := b or $00400000;
  1707. if ( aIsSignalingNaN or bIsSignalingNaN ) <> 0 then
  1708. float_raise( float_flag_invalid );
  1709. if ( aIsSignalingNaN )<> 0 then
  1710. Begin
  1711. if ( bIsSignalingNaN ) <> 0 then
  1712. goto returnLargerSignificand;
  1713. if bIsNan <> 0 then
  1714. propagateFloat32NaN := b
  1715. else
  1716. propagateFloat32NaN := a;
  1717. exit;
  1718. End
  1719. else if ( aIsNaN <> 0) then
  1720. Begin
  1721. if ( bIsSignalingNaN or not bIsNaN )<> 0 then
  1722. Begin
  1723. propagateFloat32NaN := a;
  1724. exit;
  1725. End;
  1726. returnLargerSignificand:
  1727. if ( bits32 ( a shl 1 ) < bits32 ( b shl 1 ) ) then
  1728. Begin
  1729. propagateFloat32NaN := b;
  1730. exit;
  1731. End;
  1732. if ( bits32 ( b shl 1 ) < bits32 ( a shl 1 ) ) then
  1733. Begin
  1734. propagateFloat32NaN := a;
  1735. End;
  1736. if a < b then
  1737. propagateFloat32NaN := a
  1738. else
  1739. propagateFloat32NaN := b;
  1740. exit;
  1741. End
  1742. else
  1743. Begin
  1744. propagateFloat32NaN := b;
  1745. exit;
  1746. End;
  1747. End;
  1748. {*
  1749. -------------------------------------------------------------------------------
  1750. The pattern for a default generated double-precision NaN. The `high' and
  1751. `low' values hold the most- and least-significant bits, respectively.
  1752. -------------------------------------------------------------------------------
  1753. *}
  1754. const
  1755. float64_default_nan_high = $FFF80000;
  1756. float64_default_nan_low = $00000000;
  1757. {*
  1758. -------------------------------------------------------------------------------
  1759. Returns 1 if the double-precision floating-point value `a' is a NaN;
  1760. otherwise returns 0.
  1761. -------------------------------------------------------------------------------
  1762. *}
  1763. Function float64_is_nan( a : float64 ) : flag;
  1764. Begin
  1765. float64_is_nan :=
  1766. flag(( $FFE00000 <= bits32 ( a.high shl 1 ) )
  1767. and (( a.low or ( a.high and $000FFFFF ) )<>0));
  1768. End;
  1769. {*
  1770. -------------------------------------------------------------------------------
  1771. Returns 1 if the double-precision floating-point value `a' is a signaling
  1772. NaN; otherwise returns 0.
  1773. -------------------------------------------------------------------------------
  1774. *}
  1775. Function float64_is_signaling_nan( a : float64 ): flag;
  1776. Begin
  1777. float64_is_signaling_nan :=
  1778. flag( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  1779. and ( a.low or ( a.high and $0007FFFF ) );
  1780. End;
  1781. {*
  1782. -------------------------------------------------------------------------------
  1783. Returns the result of converting the double-precision floating-point NaN
  1784. `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1785. exception is raised.
  1786. -------------------------------------------------------------------------------
  1787. *}
  1788. function float64ToCommonNaN( a : float64 ) : commonNaNT;
  1789. Var
  1790. z : commonNaNT;
  1791. Begin
  1792. if ( float64_is_signaling_nan( a )<>0 ) then
  1793. float_raise( float_flag_invalid );
  1794. z.sign := a.high shr 31;
  1795. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  1796. result := z;
  1797. End;
  1798. {*
  1799. -------------------------------------------------------------------------------
  1800. Returns the result of converting the canonical NaN `a' to the double-
  1801. precision floating-point format.
  1802. -------------------------------------------------------------------------------
  1803. *}
  1804. function commonNaNToFloat64( a : commonNaNT) : float64;
  1805. Var
  1806. z: float64;
  1807. Begin
  1808. shift64Right( a.high, a.low, 12, z.high, z.low );
  1809. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  1810. result := z;
  1811. End;
  1812. {*
  1813. -------------------------------------------------------------------------------
  1814. Takes two double-precision floating-point values `a' and `b', one of which
  1815. is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  1816. signaling NaN, the invalid exception is raised.
  1817. -------------------------------------------------------------------------------
  1818. *}
  1819. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  1820. Var
  1821. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1822. label returnLargerSignificand;
  1823. Begin
  1824. aIsNaN := float64_is_nan( a );
  1825. aIsSignalingNaN := float64_is_signaling_nan( a );
  1826. bIsNaN := float64_is_nan( b );
  1827. bIsSignalingNaN := float64_is_signaling_nan( b );
  1828. a.high := a.high or $00080000;
  1829. b.high := b.high or $00080000;
  1830. if ( aIsSignalingNaN or bIsSignalingNaN )<> 0 then
  1831. float_raise( float_flag_invalid );
  1832. if ( aIsSignalingNaN )<>0 then
  1833. Begin
  1834. if ( bIsSignalingNaN )<>0 then
  1835. goto returnLargerSignificand;
  1836. if bIsNan <> 0 then
  1837. c := b
  1838. else
  1839. c := a;
  1840. exit;
  1841. End
  1842. else if ( aIsNaN )<> 0 then
  1843. Begin
  1844. if ( bIsSignalingNaN or not bIsNaN ) <> 0 then
  1845. Begin
  1846. c := a;
  1847. exit;
  1848. End;
  1849. returnLargerSignificand:
  1850. if ( lt64( a.high shl 1, a.low, b.high shl 1, b.low ) ) <> 0 then
  1851. Begin
  1852. c := b;
  1853. exit;
  1854. End;
  1855. if ( lt64( b.high shl 1, b.low, a.high shl 1, a.low ) ) <> 0 then
  1856. Begin
  1857. c := a;
  1858. exit;
  1859. End;
  1860. if a.high < b.high then
  1861. c := a
  1862. else
  1863. c := b;
  1864. exit;
  1865. End
  1866. else
  1867. Begin
  1868. c := b;
  1869. exit;
  1870. End;
  1871. End;
  1872. {*----------------------------------------------------------------------------
  1873. | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
  1874. | otherwise returns 0.
  1875. *----------------------------------------------------------------------------*}
  1876. function float128_is_nan( a : float128): flag;
  1877. begin
  1878. result:= ord(( bits64( $FFFE000000000000 ) <= bits64( a.high shl 1 ) )
  1879. and ( (a.low<>0) or (( a.high and int64( $0000FFFFFFFFFFFF ) )<>0 ) ));
  1880. end;
  1881. {*----------------------------------------------------------------------------
  1882. | Returns 1 if the quadruple-precision floating-point value `a' is a
  1883. | signaling NaN; otherwise returns 0.
  1884. *----------------------------------------------------------------------------*}
  1885. function float128_is_signaling_nan( a : float128): flag;
  1886. begin
  1887. result:=ord(( ( ( a.high shr 47 ) and $FFFF ) = $FFFE ) and
  1888. ( (a.low<>0) or (( a.high and int64( $00007FFFFFFFFFFF ) )<>0) ));
  1889. end;
  1890. {*----------------------------------------------------------------------------
  1891. | Returns the result of converting the quadruple-precision floating-point NaN
  1892. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  1893. | exception is raised.
  1894. *----------------------------------------------------------------------------*}
  1895. function float128ToCommonNaN( a : float128): commonNaNT;
  1896. var
  1897. z: commonNaNT;
  1898. qhigh,qlow : qword;
  1899. begin
  1900. if ( float128_is_signaling_nan( a )<>0) then
  1901. float_raise( float_flag_invalid );
  1902. z.sign := a.high shr 63;
  1903. shortShift128Left( a.high, a.low, 16, qhigh, qlow );
  1904. z.high:=qhigh shr 32;
  1905. z.low:=qhigh and $ffffffff;
  1906. result:=z;
  1907. end;
  1908. {*----------------------------------------------------------------------------
  1909. | Returns the result of converting the canonical NaN `a' to the quadruple-
  1910. | precision floating-point format.
  1911. *----------------------------------------------------------------------------*}
  1912. function commonNaNToFloat128( a : commonNaNT): float128;
  1913. var
  1914. z: float128;
  1915. begin
  1916. shift128Right( a.high, a.low, 16, z.high, z.low );
  1917. z.high := z.high or ( ( bits64(a.sign) ) shl 63 ) or int64( $7FFF800000000000 );
  1918. result:=z;
  1919. end;
  1920. {*----------------------------------------------------------------------------
  1921. | Takes two quadruple-precision floating-point values `a' and `b', one of
  1922. | which is a NaN, and returns the appropriate NaN result. If either `a' or
  1923. | `b' is a signaling NaN, the invalid exception is raised.
  1924. *----------------------------------------------------------------------------*}
  1925. function propagateFloat128NaN( a: float128; b : float128): float128;
  1926. var
  1927. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  1928. label
  1929. returnLargerSignificand;
  1930. begin
  1931. aIsNaN := float128_is_nan( a );
  1932. aIsSignalingNaN := float128_is_signaling_nan( a );
  1933. bIsNaN := float128_is_nan( b );
  1934. bIsSignalingNaN := float128_is_signaling_nan( b );
  1935. a.high := a.high or int64( $0000800000000000 );
  1936. b.high := b.high or int64( $0000800000000000 );
  1937. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  1938. float_raise( float_flag_invalid );
  1939. if ( aIsSignalingNaN )<>0 then
  1940. begin
  1941. if ( bIsSignalingNaN )<>0 then
  1942. goto returnLargerSignificand;
  1943. if bIsNaN<>0 then
  1944. result := b
  1945. else
  1946. result := a;
  1947. exit;
  1948. end
  1949. else if ( aIsNaN )<>0 then
  1950. begin
  1951. if ( bIsSignalingNaN or not( bIsNaN) )<>0 then
  1952. begin
  1953. result := a;
  1954. exit;
  1955. end;
  1956. returnLargerSignificand:
  1957. if ( lt128( a.high shl 1, a.low, b.high shl 1, b.low ) )<>0 then
  1958. begin
  1959. result := b;
  1960. exit;
  1961. end;
  1962. if ( lt128( b.high shl 1, b.low, a.high shl 1, a.low ) )<>0 then
  1963. begin
  1964. result := a;
  1965. exit
  1966. end;
  1967. if ( a.high < b.high ) then
  1968. result := a
  1969. else
  1970. result := b;
  1971. exit;
  1972. end
  1973. else
  1974. result:=b;
  1975. end;
  1976. {$ELSE}
  1977. { Big endian code }
  1978. (*----------------------------------------------------------------------------
  1979. | Internal canonical NaN format.
  1980. *----------------------------------------------------------------------------*)
  1981. type
  1982. commonNANT = record
  1983. high, low : bits32;
  1984. sign : flag;
  1985. end;
  1986. (*----------------------------------------------------------------------------
  1987. | The pattern for a default generated single-precision NaN.
  1988. *----------------------------------------------------------------------------*)
  1989. const float32_default_nan = $7FFFFFFF;
  1990. (*----------------------------------------------------------------------------
  1991. | Returns 1 if the single-precision floating-point value `a' is a NaN;
  1992. | otherwise returns 0.
  1993. *----------------------------------------------------------------------------*)
  1994. function float32_is_nan(a: float32): flag;
  1995. begin
  1996. float32_is_nan := flag( $FF000000 < bits32( a shl 1 ) );
  1997. end;
  1998. (*----------------------------------------------------------------------------
  1999. | Returns 1 if the single-precision floating-point value `a' is a signaling
  2000. | NaN; otherwise returns 0.
  2001. *----------------------------------------------------------------------------*)
  2002. function float32_is_signaling_nan(a: float32):flag;
  2003. begin
  2004. float32_is_signaling_nan := flag( ( ( a shr 22 ) and $1FF ) = $1FE ) and flag( boolean((a and $003FFFFF)<>0) );
  2005. end;
  2006. (*----------------------------------------------------------------------------
  2007. | Returns the result of converting the single-precision floating-point NaN
  2008. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  2009. | exception is raised.
  2010. *----------------------------------------------------------------------------*)
  2011. function float32ToCommonNaN( a: float32) : commonNaNT;
  2012. var
  2013. z: commonNANT;
  2014. begin
  2015. if float32_is_signaling_nan(a)<>0 then
  2016. float_raise(float_flag_invalid);
  2017. z.sign := a shr 31;
  2018. z.low := 0;
  2019. z.high := a shl 9;
  2020. result:=z;
  2021. end;
  2022. (*----------------------------------------------------------------------------
  2023. | Returns the result of converting the canonical NaN `a' to the single-
  2024. | precision floating-point format.
  2025. *----------------------------------------------------------------------------*)
  2026. function CommonNanToFloat32(a : CommonNaNT): float32;
  2027. begin
  2028. CommonNanToFloat32:= ( ( bits32( a.sign )) shl 31 ) OR $7FC00000 OR ( a.high shr 9 );
  2029. end;
  2030. (*----------------------------------------------------------------------------
  2031. | Takes two single-precision floating-point values `a' and `b', one of which
  2032. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  2033. | signaling NaN, the invalid exception is raised.
  2034. *----------------------------------------------------------------------------*)
  2035. function propagateFloat32NaN( a: float32 ; b: float32): float32;
  2036. var
  2037. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  2038. begin
  2039. aIsNaN := float32_is_nan( a );
  2040. aIsSignalingNaN := float32_is_signaling_nan( a );
  2041. bIsNaN := float32_is_nan( b );
  2042. bIsSignalingNaN := float32_is_signaling_nan( b );
  2043. a := a or $00400000;
  2044. b := b or $00400000;
  2045. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  2046. float_raise( float_flag_invalid );
  2047. if bIsSignalingNaN<>0 then
  2048. propagateFloat32Nan := b
  2049. else if aIsSignalingNan<>0 then
  2050. propagateFloat32Nan := a
  2051. else if bIsNan<>0 then
  2052. propagateFloat32Nan := b
  2053. else
  2054. propagateFloat32Nan := a;
  2055. end;
  2056. (*----------------------------------------------------------------------------
  2057. | The pattern for a default generated double-precision NaN. The `high' and
  2058. | `low' values hold the most- and least-significant bits, respectively.
  2059. *----------------------------------------------------------------------------*)
  2060. const
  2061. float64_default_nan_high = $7FFFFFFF;
  2062. float64_default_nan_low = $FFFFFFFF;
  2063. (*----------------------------------------------------------------------------
  2064. | Returns 1 if the double-precision floating-point value `a' is a NaN;
  2065. | otherwise returns 0.
  2066. *----------------------------------------------------------------------------*)
  2067. function float64_is_nan(a: float64): flag;
  2068. begin
  2069. float64_is_nan := flag (
  2070. ( $FFE00000 <= bits32 ( a.high shl 1 ) )
  2071. and ( (a.low<>0) or (( a.high and $000FFFFF )<>0) ));
  2072. end;
  2073. (*----------------------------------------------------------------------------
  2074. | Returns 1 if the double-precision floating-point value `a' is a signaling
  2075. | NaN; otherwise returns 0.
  2076. *----------------------------------------------------------------------------*)
  2077. function float64_is_signaling_nan( a:float64): flag;
  2078. begin
  2079. float64_is_signaling_nan := flag(
  2080. ( ( ( a.high shr 19 ) and $FFF ) = $FFE )
  2081. and ( (a.low<>0) or ( ( a.high and $0007FFFF )<>0) ));
  2082. end;
  2083. (*----------------------------------------------------------------------------
  2084. | Returns the result of converting the double-precision floating-point NaN
  2085. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  2086. | exception is raised.
  2087. *----------------------------------------------------------------------------*)
  2088. function float64ToCommonNaN( a : float64) : commonNaNT;
  2089. var
  2090. z : commonNaNT;
  2091. begin
  2092. if ( float64_is_signaling_nan( a )<>0 ) then
  2093. float_raise( float_flag_invalid );
  2094. z.sign := a.high shr 31;
  2095. shortShift64Left( a.high, a.low, 12, z.high, z.low );
  2096. result:=z;
  2097. end;
  2098. (*----------------------------------------------------------------------------
  2099. | Returns the result of converting the canonical NaN `a' to the double-
  2100. | precision floating-point format.
  2101. *----------------------------------------------------------------------------*)
  2102. function commonNaNToFloat64( a : commonNaNT): float64;
  2103. var
  2104. z: float64;
  2105. begin
  2106. shift64Right( a.high, a.low, 12, z.high, z.low );
  2107. z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
  2108. result:=z;
  2109. end;
  2110. (*----------------------------------------------------------------------------
  2111. | Takes two double-precision floating-point values `a' and `b', one of which
  2112. | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  2113. | signaling NaN, the invalid exception is raised.
  2114. *----------------------------------------------------------------------------*)
  2115. Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
  2116. var
  2117. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN : flag;
  2118. begin
  2119. aIsNaN := float64_is_nan( a );
  2120. aIsSignalingNaN := float64_is_signaling_nan( a );
  2121. bIsNaN := float64_is_nan( b );
  2122. bIsSignalingNaN := float64_is_signaling_nan( b );
  2123. a.high := a.high or $00080000;
  2124. b.high := b.high or $00080000;
  2125. if ( (aIsSignalingNaN<>0) or (bIsSignalingNaN<>0) ) then
  2126. float_raise( float_flag_invalid );
  2127. if bIsSignalingNaN<>0 then
  2128. c := b
  2129. else if aIsSignalingNan<>0 then
  2130. c := a
  2131. else if bIsNan<>0 then
  2132. c := b
  2133. else
  2134. c := a;
  2135. end;
  2136. {*----------------------------------------------------------------------------
  2137. | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
  2138. | otherwise returns 0.
  2139. *----------------------------------------------------------------------------*}
  2140. function float128_is_nan( a : float128): flag;
  2141. begin
  2142. result:= ord(( bits64( $FFFE000000000000 ) <= bits64( a.high shl 1 ) )
  2143. and ( (a.low<>0) or (( a.high and int64( $0000FFFFFFFFFFFF ) )<>0 ) ));
  2144. end;
  2145. {*----------------------------------------------------------------------------
  2146. | Returns 1 if the quadruple-precision floating-point value `a' is a
  2147. | signaling NaN; otherwise returns 0.
  2148. *----------------------------------------------------------------------------*}
  2149. function float128_is_signaling_nan( a : float128): flag;
  2150. begin
  2151. result:=ord(( ( ( a.high shr 47 ) and $FFFF ) = $FFFE ) and
  2152. ( (a.low<>0) or (( a.high and int64( $00007FFFFFFFFFFF ) )<>0) ));
  2153. end;
  2154. {*----------------------------------------------------------------------------
  2155. | Returns the result of converting the quadruple-precision floating-point NaN
  2156. | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  2157. | exception is raised.
  2158. *----------------------------------------------------------------------------*}
  2159. function float128ToCommonNaN( a : float128): commonNaNT;
  2160. var
  2161. z: commonNaNT;
  2162. qhigh,qlow : qword;
  2163. begin
  2164. if ( float128_is_signaling_nan( a )<>0) then
  2165. float_raise( float_flag_invalid );
  2166. z.sign := a.high shr 63;
  2167. shortShift128Left( a.high, a.low, 16, qhigh, qlow );
  2168. z.high:=qhigh shr 32;
  2169. z.low:=qhigh and $ffffffff;
  2170. result:=z;
  2171. end;
  2172. {*----------------------------------------------------------------------------
  2173. | Returns the result of converting the canonical NaN `a' to the quadruple-
  2174. | precision floating-point format.
  2175. *----------------------------------------------------------------------------*}
  2176. function commonNaNToFloat128( a : commonNaNT): float128;
  2177. var
  2178. z: float128;
  2179. begin
  2180. shift128Right( a.high, a.low, 16, z.high, z.low );
  2181. z.high := z.high or ( ( bits64(a.sign) ) shl 63 ) or int64( $7FFF800000000000 );
  2182. result:=z;
  2183. end;
  2184. {*----------------------------------------------------------------------------
  2185. | Takes two quadruple-precision floating-point values `a' and `b', one of
  2186. | which is a NaN, and returns the appropriate NaN result. If either `a' or
  2187. | `b' is a signaling NaN, the invalid exception is raised.
  2188. *----------------------------------------------------------------------------*}
  2189. function propagateFloat128NaN( a: float128; b : float128): float128;
  2190. var
  2191. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  2192. label
  2193. returnLargerSignificand;
  2194. begin
  2195. aIsNaN := float128_is_nan( a );
  2196. aIsSignalingNaN := float128_is_signaling_nan( a );
  2197. bIsNaN := float128_is_nan( b );
  2198. bIsSignalingNaN := float128_is_signaling_nan( b );
  2199. a.high := a.high or int64( $0000800000000000 );
  2200. b.high := b.high or int64( $0000800000000000 );
  2201. if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
  2202. float_raise( float_flag_invalid );
  2203. if ( aIsSignalingNaN )<>0 then
  2204. begin
  2205. if ( bIsSignalingNaN )<>0 then
  2206. goto returnLargerSignificand;
  2207. if bIsNaN<>0 then
  2208. result := b
  2209. else
  2210. result := a;
  2211. exit;
  2212. end
  2213. else if ( aIsNaN )<>0 then
  2214. begin
  2215. if ( bIsSignalingNaN or not( bIsNaN) )<>0 then
  2216. begin
  2217. result := a;
  2218. exit;
  2219. end;
  2220. returnLargerSignificand:
  2221. if ( lt128( a.high shl 1, a.low, b.high shl 1, b.low ) )<>0 then
  2222. begin
  2223. result := b;
  2224. exit;
  2225. end;
  2226. if ( lt128( b.high shl 1, b.low, a.high shl 1, a.low ) )<>0 then
  2227. begin
  2228. result := a;
  2229. exit
  2230. end;
  2231. if ( a.high < b.high ) then
  2232. result := a
  2233. else
  2234. result := b;
  2235. exit;
  2236. end
  2237. else
  2238. result:=b;
  2239. end;
  2240. {$ENDIF}
  2241. (****************************************************************************)
  2242. (* END ENDIAN SPECIFIC CODE *)
  2243. (****************************************************************************)
  2244. {*
  2245. -------------------------------------------------------------------------------
  2246. Returns the fraction bits of the single-precision floating-point value `a'.
  2247. -------------------------------------------------------------------------------
  2248. *}
  2249. Function ExtractFloat32Frac(a : Float32) : Bits32; inline;
  2250. Begin
  2251. ExtractFloat32Frac := A AND $007FFFFF;
  2252. End;
  2253. {*
  2254. -------------------------------------------------------------------------------
  2255. Returns the exponent bits of the single-precision floating-point value `a'.
  2256. -------------------------------------------------------------------------------
  2257. *}
  2258. Function extractFloat32Exp( a: float32 ): Int16; inline;
  2259. Begin
  2260. extractFloat32Exp := (a shr 23) AND $FF;
  2261. End;
  2262. {*
  2263. -------------------------------------------------------------------------------
  2264. Returns the sign bit of the single-precision floating-point value `a'.
  2265. -------------------------------------------------------------------------------
  2266. *}
  2267. Function extractFloat32Sign( a: float32 ): Flag; inline;
  2268. Begin
  2269. extractFloat32Sign := a shr 31;
  2270. End;
  2271. {*
  2272. -------------------------------------------------------------------------------
  2273. Normalizes the subnormal single-precision floating-point value represented
  2274. by the denormalized significand `aSig'. The normalized exponent and
  2275. significand are stored at the locations pointed to by `zExpPtr' and
  2276. `zSigPtr', respectively.
  2277. -------------------------------------------------------------------------------
  2278. *}
  2279. Procedure normalizeFloat32Subnormal( aSig : bits32; VAR zExpPtr: Int16; VAR zSigPtr :bits32);
  2280. Var
  2281. ShiftCount : BYTE;
  2282. Begin
  2283. shiftCount := countLeadingZeros32( aSig ) - 8;
  2284. zSigPtr := aSig shl shiftCount;
  2285. zExpPtr := 1 - shiftCount;
  2286. End;
  2287. {*
  2288. -------------------------------------------------------------------------------
  2289. Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
  2290. single-precision floating-point value, returning the result. After being
  2291. shifted into the proper positions, the three fields are simply added
  2292. together to form the result. This means that any integer portion of `zSig'
  2293. will be added into the exponent. Since a properly normalized significand
  2294. will have an integer portion equal to 1, the `zExp' input should be 1 less
  2295. than the desired result exponent whenever `zSig' is a complete, normalized
  2296. significand.
  2297. -------------------------------------------------------------------------------
  2298. *}
  2299. Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32; inline;
  2300. Begin
  2301. packFloat32 := ( ( bits32( zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 23 )
  2302. + zSig;
  2303. End;
  2304. {*
  2305. -------------------------------------------------------------------------------
  2306. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2307. and significand `zSig', and returns the proper single-precision floating-
  2308. point value corresponding to the abstract input. Ordinarily, the abstract
  2309. value is simply rounded and packed into the single-precision format, with
  2310. the inexact exception raised if the abstract input cannot be represented
  2311. exactly. However, if the abstract value is too large, the overflow and
  2312. inexact exceptions are raised and an infinity or maximal finite value is
  2313. returned. If the abstract value is too small, the input value is rounded to
  2314. a subnormal number, and the underflow and inexact exceptions are raised if
  2315. the abstract input cannot be represented exactly as a subnormal single-
  2316. precision floating-point number.
  2317. The input significand `zSig' has its binary point between bits 30
  2318. and 29, which is 7 bits to the left of the usual location. This shifted
  2319. significand must be normalized or smaller. If `zSig' is not normalized,
  2320. `zExp' must be 0; in that case, the result returned is a subnormal number,
  2321. and it must not require rounding. In the usual case that `zSig' is
  2322. normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
  2323. The handling of underflow and overflow follows the IEC/IEEE Standard for
  2324. Binary Floating-Point Arithmetic.
  2325. -------------------------------------------------------------------------------
  2326. *}
  2327. Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : float32;
  2328. Var
  2329. roundingMode : TFPURoundingMode;
  2330. roundNearestEven : boolean;
  2331. roundIncrement, roundBits : BYTE;
  2332. IsTiny : boolean;
  2333. Begin
  2334. roundingMode := softfloat_rounding_mode;
  2335. roundNearestEven := (roundingMode = float_round_nearest_even);
  2336. roundIncrement := $40;
  2337. if not roundNearestEven then
  2338. Begin
  2339. if ( roundingMode = float_round_to_zero ) Then
  2340. Begin
  2341. roundIncrement := 0;
  2342. End
  2343. else
  2344. Begin
  2345. roundIncrement := $7F;
  2346. if ( zSign <> 0 ) then
  2347. Begin
  2348. if roundingMode = float_round_up then roundIncrement := 0;
  2349. End
  2350. else
  2351. Begin
  2352. if roundingMode = float_round_down then roundIncrement := 0;
  2353. End;
  2354. End
  2355. End;
  2356. roundBits := zSig AND $7F;
  2357. if ($FD <= bits16 (zExp) ) then
  2358. Begin
  2359. if (( $FD < zExp ) OR ( zExp = $FD ) AND ( sbits32 ( zSig + roundIncrement ) < 0 ) ) then
  2360. Begin
  2361. float_raise( [float_flag_overflow,float_flag_inexact] );
  2362. roundAndPackFloat32:=packFloat32( zSign, $FF, 0 ) - Flag( roundIncrement = 0 );
  2363. exit;
  2364. End;
  2365. if ( zExp < 0 ) then
  2366. Begin
  2367. isTiny :=
  2368. ( softfloat_detect_tininess = float_tininess_before_rounding )
  2369. OR ( zExp < -1 )
  2370. OR ( (zSig + roundIncrement) < $80000000 );
  2371. shift32RightJamming( zSig, - zExp, zSig );
  2372. zExp := 0;
  2373. roundBits := zSig AND $7F;
  2374. if ( isTiny and (roundBits<>0) ) then
  2375. float_raise( float_flag_underflow );
  2376. End;
  2377. End;
  2378. if ( roundBits )<> 0 then
  2379. set_inexact_flag;
  2380. zSig := ( zSig + roundIncrement ) shr 7;
  2381. zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and ord(roundNearestEven) );
  2382. if ( zSig = 0 ) then zExp := 0;
  2383. roundAndPackFloat32 := packFloat32( zSign, zExp, zSig );
  2384. End;
  2385. {*
  2386. -------------------------------------------------------------------------------
  2387. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2388. and significand `zSig', and returns the proper single-precision floating-
  2389. point value corresponding to the abstract input. This routine is just like
  2390. `roundAndPackFloat32' except that `zSig' does not have to be normalized.
  2391. Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
  2392. floating-point exponent.
  2393. -------------------------------------------------------------------------------
  2394. *}
  2395. Function normalizeRoundAndPackFloat32( zSign: flag; zExp: int16; zSig:bits32 ): float32;
  2396. Var
  2397. ShiftCount : int8;
  2398. Begin
  2399. shiftCount := countLeadingZeros32( zSig ) - 1;
  2400. normalizeRoundAndPackFloat32 := roundAndPackFloat32( zSign, zExp - shiftCount, zSig shl shiftCount );
  2401. End;
  2402. {*
  2403. -------------------------------------------------------------------------------
  2404. Returns the most-significant 20 fraction bits of the double-precision
  2405. floating-point value `a'.
  2406. -------------------------------------------------------------------------------
  2407. *}
  2408. Function extractFloat64Frac0(a: float64): bits32; inline;
  2409. Begin
  2410. extractFloat64Frac0 := a.high and $000FFFFF;
  2411. End;
  2412. {*
  2413. -------------------------------------------------------------------------------
  2414. Returns the least-significant 32 fraction bits of the double-precision
  2415. floating-point value `a'.
  2416. -------------------------------------------------------------------------------
  2417. *}
  2418. Function extractFloat64Frac1(a: float64): bits32; inline;
  2419. Begin
  2420. extractFloat64Frac1 := a.low;
  2421. End;
  2422. {$define FPC_SYSTEM_HAS_extractFloat64Frac}
  2423. Function extractFloat64Frac(a: float64): bits64; inline;
  2424. Begin
  2425. extractFloat64Frac := bits64(a) and $000FFFFFFFFFFFFF;
  2426. End;
  2427. {*
  2428. -------------------------------------------------------------------------------
  2429. Returns the exponent bits of the double-precision floating-point value `a'.
  2430. -------------------------------------------------------------------------------
  2431. *}
  2432. Function extractFloat64Exp(a: float64): int16; inline;
  2433. Begin
  2434. extractFloat64Exp:= ( a.high shr 20 ) AND $7FF;
  2435. End;
  2436. {*
  2437. -------------------------------------------------------------------------------
  2438. Returns the sign bit of the double-precision floating-point value `a'.
  2439. -------------------------------------------------------------------------------
  2440. *}
  2441. Function extractFloat64Sign(a: float64) : flag; inline;
  2442. Begin
  2443. extractFloat64Sign := a.high shr 31;
  2444. End;
  2445. {*
  2446. -------------------------------------------------------------------------------
  2447. Normalizes the subnormal double-precision floating-point value represented
  2448. by the denormalized significand formed by the concatenation of `aSig0' and
  2449. `aSig1'. The normalized exponent is stored at the location pointed to by
  2450. `zExpPtr'. The most significant 21 bits of the normalized significand are
  2451. stored at the location pointed to by `zSig0Ptr', and the least significant
  2452. 32 bits of the normalized significand are stored at the location pointed to
  2453. by `zSig1Ptr'.
  2454. -------------------------------------------------------------------------------
  2455. *}
  2456. Procedure normalizeFloat64Subnormal(
  2457. aSig0: bits32;
  2458. aSig1: bits32;
  2459. VAR zExpPtr : Int16;
  2460. VAR zSig0Ptr : Bits32;
  2461. VAR zSig1Ptr : Bits32
  2462. );
  2463. Var
  2464. ShiftCount : Int8;
  2465. Begin
  2466. if ( aSig0 = 0 ) then
  2467. Begin
  2468. shiftCount := countLeadingZeros32( aSig1 ) - 11;
  2469. if ( shiftCount < 0 ) then
  2470. Begin
  2471. zSig0Ptr := aSig1 shr ( - shiftCount );
  2472. zSig1Ptr := aSig1 shl ( shiftCount AND 31 );
  2473. End
  2474. else
  2475. Begin
  2476. zSig0Ptr := aSig1 shl shiftCount;
  2477. zSig1Ptr := 0;
  2478. End;
  2479. zExpPtr := - shiftCount - 31;
  2480. End
  2481. else
  2482. Begin
  2483. shiftCount := countLeadingZeros32( aSig0 ) - 11;
  2484. shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
  2485. zExpPtr := 1 - shiftCount;
  2486. End;
  2487. End;
  2488. procedure normalizeFloat64Subnormal(aSig : bits64;var zExpPtr : int16; var zSigPtr : bits64);
  2489. var
  2490. shiftCount : int8;
  2491. begin
  2492. shiftCount := countLeadingZeros64( aSig ) - 11;
  2493. zSigPtr := aSig shl shiftCount;
  2494. zExpPtr := 1 - shiftCount;
  2495. end;
  2496. {*
  2497. -------------------------------------------------------------------------------
  2498. Packs the sign `zSign', the exponent `zExp', and the significand formed by
  2499. the concatenation of `zSig0' and `zSig1' into a double-precision floating-
  2500. point value, returning the result. After being shifted into the proper
  2501. positions, the three fields `zSign', `zExp', and `zSig0' are simply added
  2502. together to form the most significant 32 bits of the result. This means
  2503. that any integer portion of `zSig0' will be added into the exponent. Since
  2504. a properly normalized significand will have an integer portion equal to 1,
  2505. the `zExp' input should be 1 less than the desired result exponent whenever
  2506. `zSig0' and `zSig1' concatenated form a complete, normalized significand.
  2507. -------------------------------------------------------------------------------
  2508. *}
  2509. Procedure
  2510. packFloat64( zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1 : Bits32; VAR c : float64);
  2511. var
  2512. z: Float64;
  2513. Begin
  2514. z.low := zSig1;
  2515. z.high := ( ( bits32 (zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 20 ) + zSig0;
  2516. c := z;
  2517. End;
  2518. {*----------------------------------------------------------------------------
  2519. | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
  2520. | double-precision floating-point value, returning the result. After being
  2521. | shifted into the proper positions, the three fields are simply added
  2522. | together to form the result. This means that any integer portion of `zSig'
  2523. | will be added into the exponent. Since a properly normalized significand
  2524. | will have an integer portion equal to 1, the `zExp' input should be 1 less
  2525. | than the desired result exponent whenever `zSig' is a complete, normalized
  2526. | significand.
  2527. *----------------------------------------------------------------------------*}
  2528. function packFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;inline;
  2529. begin
  2530. result := float64(( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 52 ) + zSig);
  2531. end;
  2532. {*
  2533. -------------------------------------------------------------------------------
  2534. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2535. and extended significand formed by the concatenation of `zSig0', `zSig1',
  2536. and `zSig2', and returns the proper double-precision floating-point value
  2537. corresponding to the abstract input. Ordinarily, the abstract value is
  2538. simply rounded and packed into the double-precision format, with the inexact
  2539. exception raised if the abstract input cannot be represented exactly.
  2540. However, if the abstract value is too large, the overflow and inexact
  2541. exceptions are raised and an infinity or maximal finite value is returned.
  2542. If the abstract value is too small, the input value is rounded to a
  2543. subnormal number, and the underflow and inexact exceptions are raised if the
  2544. abstract input cannot be represented exactly as a subnormal double-precision
  2545. floating-point number.
  2546. The input significand must be normalized or smaller. If the input
  2547. significand is not normalized, `zExp' must be 0; in that case, the result
  2548. returned is a subnormal number, and it must not require rounding. In the
  2549. usual case that the input significand is normalized, `zExp' must be 1 less
  2550. than the ``true'' floating-point exponent. The handling of underflow and
  2551. overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2552. -------------------------------------------------------------------------------
  2553. *}
  2554. Procedure
  2555. roundAndPackFloat64(
  2556. zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1: Bits32; zSig2: Bits32; Var c: Float64 );
  2557. Var
  2558. roundingMode : TFPURoundingMode;
  2559. roundNearestEven, increment, isTiny : Flag;
  2560. Begin
  2561. roundingMode := softfloat_rounding_mode;
  2562. roundNearestEven := flag( roundingMode = float_round_nearest_even );
  2563. increment := flag( sbits32 (zSig2) < 0 );
  2564. if ( roundNearestEven = flag(FALSE) ) then
  2565. Begin
  2566. if ( roundingMode = float_round_to_zero ) then
  2567. increment := 0
  2568. else
  2569. Begin
  2570. if ( zSign )<> 0 then
  2571. Begin
  2572. increment := flag(( roundingMode = float_round_down ) and (zSig2<>0));
  2573. End
  2574. else
  2575. Begin
  2576. increment := flag(( roundingMode = float_round_up ) and (zSig2<>0));
  2577. End
  2578. End
  2579. End;
  2580. if ( $7FD <= bits16 (zExp) ) then
  2581. Begin
  2582. if (( $7FD < zExp )
  2583. or (( zExp = $7FD )
  2584. and (zSig0=$001FFFFF) and (zSig1=$FFFFFFFF)
  2585. and (increment<>0)
  2586. )
  2587. ) then
  2588. Begin
  2589. float_raise( [float_flag_overflow,float_flag_inexact] );
  2590. if (( roundingMode = float_round_to_zero )
  2591. or ( (zSign<>0) and ( roundingMode = float_round_up ) )
  2592. or ( (zSign = 0) and ( roundingMode = float_round_down ) )
  2593. ) then
  2594. Begin
  2595. packFloat64( zSign, $7FE, $000FFFFF, $FFFFFFFF, c );
  2596. exit;
  2597. End;
  2598. packFloat64( zSign, $7FF, 0, 0, c );
  2599. exit;
  2600. End;
  2601. if ( zExp < 0 ) then
  2602. Begin
  2603. isTiny :=
  2604. flag( softfloat_detect_tininess = float_tininess_before_rounding )
  2605. or flag( zExp < -1 )
  2606. or flag(increment = 0)
  2607. or flag(lt64( zSig0, zSig1, $001FFFFF, $FFFFFFFF)<>0);
  2608. shift64ExtraRightJamming(
  2609. zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
  2610. zExp := 0;
  2611. if ( isTiny<>0) and (zSig2<>0 ) then float_raise( float_flag_underflow );
  2612. if ( roundNearestEven )<>0 then
  2613. Begin
  2614. increment := flag( sbits32 (zSig2) < 0 );
  2615. End
  2616. else
  2617. Begin
  2618. if ( zSign )<>0 then
  2619. Begin
  2620. increment := flag(( roundingMode = float_round_down ) and (zSig2<>0));
  2621. End
  2622. else
  2623. Begin
  2624. increment := flag(( roundingMode = float_round_up ) and (zSig2<>0));
  2625. End
  2626. End;
  2627. End;
  2628. End;
  2629. if ( zSig2 )<>0 then
  2630. set_inexact_flag;
  2631. if ( increment )<>0 then
  2632. Begin
  2633. add64( zSig0, zSig1, 0, 1, zSig0, zSig1 );
  2634. zSig1 := zSig1 and not ( bits32(flag( zSig2 + zSig2 = 0 )) and roundNearestEven );
  2635. End
  2636. else
  2637. Begin
  2638. if ( ( zSig0 or zSig1 ) = 0 ) then zExp := 0;
  2639. End;
  2640. packFloat64( zSign, zExp, zSig0, zSig1, c );
  2641. End;
  2642. {*----------------------------------------------------------------------------
  2643. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2644. | and significand `zSig', and returns the proper double-precision floating-
  2645. | point value corresponding to the abstract input. Ordinarily, the abstract
  2646. | value is simply rounded and packed into the double-precision format, with
  2647. | the inexact exception raised if the abstract input cannot be represented
  2648. | exactly. However, if the abstract value is too large, the overflow and
  2649. | inexact exceptions are raised and an infinity or maximal finite value is
  2650. | returned. If the abstract value is too small, the input value is rounded
  2651. | to a subnormal number, and the underflow and inexact exceptions are raised
  2652. | if the abstract input cannot be represented exactly as a subnormal double-
  2653. | precision floating-point number.
  2654. | The input significand `zSig' has its binary point between bits 62
  2655. | and 61, which is 10 bits to the left of the usual location. This shifted
  2656. | significand must be normalized or smaller. If `zSig' is not normalized,
  2657. | `zExp' must be 0; in that case, the result returned is a subnormal number,
  2658. | and it must not require rounding. In the usual case that `zSig' is
  2659. | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
  2660. | The handling of underflow and overflow follows the IEC/IEEE Standard for
  2661. | Binary Floating-Point Arithmetic.
  2662. *----------------------------------------------------------------------------*}
  2663. function roundAndPackFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;
  2664. var
  2665. roundingMode: TFPURoundingMode;
  2666. roundNearestEven: flag;
  2667. roundIncrement, roundBits: int16;
  2668. isTiny: flag;
  2669. begin
  2670. roundingMode := softfloat_rounding_mode;
  2671. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  2672. roundIncrement := $200;
  2673. if ( roundNearestEven=0 ) then
  2674. begin
  2675. if ( roundingMode = float_round_to_zero ) then
  2676. begin
  2677. roundIncrement := 0;
  2678. end
  2679. else begin
  2680. roundIncrement := $3FF;
  2681. if ( zSign<>0 ) then
  2682. begin
  2683. if ( roundingMode = float_round_up ) then
  2684. roundIncrement := 0;
  2685. end
  2686. else begin
  2687. if ( roundingMode = float_round_down ) then
  2688. roundIncrement := 0;
  2689. end
  2690. end
  2691. end;
  2692. roundBits := zSig and $3FF;
  2693. if ( $7FD <= bits16(zExp) ) then
  2694. begin
  2695. if ( ( $7FD < zExp )
  2696. or ( ( zExp = $7FD )
  2697. and ( sbits64( zSig + roundIncrement ) < 0 ) )
  2698. ) then
  2699. begin
  2700. float_raise( [float_flag_overflow,float_flag_inexact] );
  2701. result := float64(qword(packFloat64( zSign, $7FF, 0 )) - ord( roundIncrement = 0 ));
  2702. exit;
  2703. end;
  2704. if ( zExp < 0 ) then
  2705. begin
  2706. isTiny := ord(
  2707. ( softfloat_detect_tininess = float_tininess_before_rounding )
  2708. or ( zExp < -1 )
  2709. or ( (zSig + roundIncrement) < bits64( $8000000000000000 ) ) );
  2710. shift64RightJamming( zSig, - zExp, zSig );
  2711. zExp := 0;
  2712. roundBits := zSig and $3FF;
  2713. if ( isTiny and roundBits )<>0 then
  2714. float_raise( float_flag_underflow );
  2715. end
  2716. end;
  2717. if ( roundBits<>0 ) then
  2718. set_inexact_flag;
  2719. zSig := ( zSig + roundIncrement ) shr 10;
  2720. zSig := zSig and not(qword(ord( ( roundBits xor $200 ) = 0 ) and roundNearestEven ));
  2721. if ( zSig = 0 ) then
  2722. zExp := 0;
  2723. result:=packFloat64( zSign, zExp, zSig );
  2724. end;
  2725. {*
  2726. -------------------------------------------------------------------------------
  2727. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2728. and significand formed by the concatenation of `zSig0' and `zSig1', and
  2729. returns the proper double-precision floating-point value corresponding
  2730. to the abstract input. This routine is just like `roundAndPackFloat64'
  2731. except that the input significand has fewer bits and does not have to be
  2732. normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
  2733. point exponent.
  2734. -------------------------------------------------------------------------------
  2735. *}
  2736. Procedure
  2737. normalizeRoundAndPackFloat64(
  2738. zSign:flag; zExp:int16; zSig0:bits32; zSig1:bits32; VAR c: float64 );
  2739. Var
  2740. shiftCount : int8;
  2741. zSig2 : bits32;
  2742. Begin
  2743. if ( zSig0 = 0 ) then
  2744. Begin
  2745. zSig0 := zSig1;
  2746. zSig1 := 0;
  2747. zExp := zExp -32;
  2748. End;
  2749. shiftCount := countLeadingZeros32( zSig0 ) - 11;
  2750. if ( 0 <= shiftCount ) then
  2751. Begin
  2752. zSig2 := 0;
  2753. shortShift64Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  2754. End
  2755. else
  2756. Begin
  2757. shift64ExtraRightJamming
  2758. (zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
  2759. End;
  2760. zExp := zExp - shiftCount;
  2761. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, c );
  2762. End;
  2763. {*
  2764. ----------------------------------------------------------------------------
  2765. Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  2766. and significand `zSig', and returns the proper double-precision floating-
  2767. point value corresponding to the abstract input. This routine is just like
  2768. `roundAndPackFloat64' except that `zSig' does not have to be normalized.
  2769. Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
  2770. floating-point exponent.
  2771. ----------------------------------------------------------------------------
  2772. *}
  2773. function normalizeRoundAndPackFloat64(zSign: flag; zExp: int16; zSig: bits64): float64;
  2774. var
  2775. shiftCount: int8;
  2776. begin
  2777. shiftCount := countLeadingZeros64( zSig ) - 1;
  2778. result := roundAndPackFloat64( zSign, zExp - shiftCount, zSig shl shiftCount);
  2779. end;
  2780. {*
  2781. -------------------------------------------------------------------------------
  2782. Returns the result of converting the 32-bit two's complement integer `a' to
  2783. the single-precision floating-point format. The conversion is performed
  2784. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2785. -------------------------------------------------------------------------------
  2786. *}
  2787. Function int32_to_float32( a: int32): float32rec; compilerproc;
  2788. Var
  2789. zSign : Flag;
  2790. Begin
  2791. if ( a = 0 ) then
  2792. Begin
  2793. int32_to_float32.float32 := 0;
  2794. exit;
  2795. End;
  2796. if ( a = sbits32 ($80000000) ) then
  2797. Begin
  2798. int32_to_float32.float32 := packFloat32( 1, $9E, 0 );
  2799. exit;
  2800. end;
  2801. zSign := flag( a < 0 );
  2802. If zSign<>0 then
  2803. a := -a;
  2804. int32_to_float32.float32:=
  2805. normalizeRoundAndPackFloat32( zSign, $9C, a );
  2806. End;
  2807. {*
  2808. -------------------------------------------------------------------------------
  2809. Returns the result of converting the 32-bit two's complement integer `a' to
  2810. the double-precision floating-point format. The conversion is performed
  2811. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2812. -------------------------------------------------------------------------------
  2813. *}
  2814. Function int32_to_float64( a: int32) : float64;{$ifdef fpc} [public,Alias:'INT32_TO_FLOAT64'];compilerproc;{$endif}
  2815. var
  2816. zSign : flag;
  2817. absA : bits32;
  2818. shiftCount : int8;
  2819. zSig0, zSig1 : bits32;
  2820. Begin
  2821. if ( a = 0 ) then
  2822. Begin
  2823. packFloat64( 0, 0, 0, 0, result );
  2824. exit;
  2825. end;
  2826. zSign := flag( a < 0 );
  2827. if ZSign<>0 then
  2828. AbsA := -a
  2829. else
  2830. AbsA := a;
  2831. shiftCount := countLeadingZeros32( absA ) - 11;
  2832. if ( 0 <= shiftCount ) then
  2833. Begin
  2834. zSig0 := absA shl shiftCount;
  2835. zSig1 := 0;
  2836. End
  2837. else
  2838. Begin
  2839. shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );
  2840. End;
  2841. packFloat64( zSign, $412 - shiftCount, zSig0, zSig1, result );
  2842. End;
  2843. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  2844. {$if not defined(packFloatx80)}
  2845. function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;
  2846. forward;
  2847. {$endif}
  2848. {*----------------------------------------------------------------------------
  2849. | Returns the result of converting the 32-bit two's complement integer `a'
  2850. | to the extended double-precision floating-point format. The conversion
  2851. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  2852. | Arithmetic.
  2853. *----------------------------------------------------------------------------*}
  2854. function int32_to_floatx80( a: int32 ): floatx80;
  2855. var
  2856. zSign: flag;
  2857. absA: uint32;
  2858. shiftCount: int8;
  2859. zSig: bits64;
  2860. begin
  2861. if ( a = 0 ) then begin
  2862. result := packFloatx80( 0, 0, 0 );
  2863. exit;
  2864. end;
  2865. zSign := ord( a < 0 );
  2866. if zSign <> 0 then absA := - a else absA := a;
  2867. shiftCount := countLeadingZeros32( absA ) + 32;
  2868. zSig := absA;
  2869. result := packFloatx80( zSign, $403E - shiftCount, zSig shl shiftCount );
  2870. end;
  2871. {$endif FPC_SOFTFLOAT_FLOATX80}
  2872. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  2873. {$if not defined(packFloat128)}
  2874. function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64 ) : float128;
  2875. forward;
  2876. {$endif}
  2877. {*----------------------------------------------------------------------------
  2878. | Returns the result of converting the 32-bit two's complement integer `a' to
  2879. | the quadruple-precision floating-point format. The conversion is performed
  2880. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  2881. *----------------------------------------------------------------------------*}
  2882. function int32_to_float128( a: int32 ): float128;
  2883. var
  2884. zSign: flag;
  2885. absA: uint32;
  2886. shiftCount: int8;
  2887. zSig0: bits64;
  2888. begin
  2889. if ( a = 0 ) then begin
  2890. result := packFloat128( 0, 0, 0, 0 );
  2891. exit;
  2892. end;
  2893. zSign := ord( a < 0 );
  2894. if zSign <> 0 then absA := - a else absA := a;
  2895. shiftCount := countLeadingZeros32( absA ) + 17;
  2896. zSig0 := absA;
  2897. result := packFloat128( zSign, $402E - shiftCount, zSig0 shl shiftCount, 0 );
  2898. end;
  2899. {$endif FPC_SOFTFLOAT_FLOAT128}
  2900. {*
  2901. -------------------------------------------------------------------------------
  2902. Returns the result of converting the single-precision floating-point value
  2903. `a' to the 32-bit two's complement integer format. The conversion is
  2904. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2905. Arithmetic---which means in particular that the conversion is rounded
  2906. according to the current rounding mode. If `a' is a NaN, the largest
  2907. positive integer is returned. Otherwise, if the conversion overflows, the
  2908. largest integer with the same sign as `a' is returned.
  2909. -------------------------------------------------------------------------------
  2910. *}
  2911. Function float32_to_int32( a : float32rec) : int32;compilerproc;
  2912. Var
  2913. aSign: flag;
  2914. aExp, shiftCount: int16;
  2915. aSig, aSigExtra: bits32;
  2916. z: int32;
  2917. roundingMode: TFPURoundingMode;
  2918. Begin
  2919. aSig := extractFloat32Frac( a.float32 );
  2920. aExp := extractFloat32Exp( a.float32 );
  2921. aSign := extractFloat32Sign( a.float32 );
  2922. shiftCount := aExp - $96;
  2923. if ( 0 <= shiftCount ) then
  2924. Begin
  2925. if ( $9E <= aExp ) then
  2926. Begin
  2927. if ( a.float32 <> $CF000000 ) then
  2928. Begin
  2929. float_raise( float_flag_invalid );
  2930. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  2931. Begin
  2932. float32_to_int32 := $7FFFFFFF;
  2933. exit;
  2934. End;
  2935. End;
  2936. float32_to_int32 := sbits32 ($80000000);
  2937. exit;
  2938. End;
  2939. z := ( aSig or $00800000 ) shl shiftCount;
  2940. if ( aSign<>0 ) then z := - z;
  2941. End
  2942. else
  2943. Begin
  2944. if ( aExp < $7E ) then
  2945. Begin
  2946. aSigExtra := aExp OR aSig;
  2947. z := 0;
  2948. End
  2949. else
  2950. Begin
  2951. aSig := aSig OR $00800000;
  2952. aSigExtra := aSig shl ( shiftCount and 31 );
  2953. z := aSig shr ( - shiftCount );
  2954. End;
  2955. if ( aSigExtra<>0 ) then
  2956. set_inexact_flag;
  2957. roundingMode := softfloat_rounding_mode;
  2958. if ( roundingMode = float_round_nearest_even ) then
  2959. Begin
  2960. if ( sbits32 (aSigExtra) < 0 ) then
  2961. Begin
  2962. Inc(z);
  2963. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  2964. z := z and not 1;
  2965. End;
  2966. if ( aSign<>0 ) then
  2967. z := - z;
  2968. End
  2969. else
  2970. Begin
  2971. aSigExtra := flag( aSigExtra <> 0 );
  2972. if ( aSign<>0 ) then
  2973. Begin
  2974. z := z + (flag( roundingMode = float_round_down ) and aSigExtra);
  2975. z := - z;
  2976. End
  2977. else
  2978. Begin
  2979. z := z + (flag( roundingMode = float_round_up ) and aSigExtra);
  2980. End
  2981. End;
  2982. End;
  2983. float32_to_int32 := z;
  2984. End;
  2985. {*
  2986. -------------------------------------------------------------------------------
  2987. Returns the result of converting the single-precision floating-point value
  2988. `a' to the 32-bit two's complement integer format. The conversion is
  2989. performed according to the IEC/IEEE Standard for Binary Floating-Point
  2990. Arithmetic, except that the conversion is always rounded toward zero.
  2991. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  2992. the conversion overflows, the largest integer with the same sign as `a' is
  2993. returned.
  2994. -------------------------------------------------------------------------------
  2995. *}
  2996. Function float32_to_int32_round_to_zero( a: Float32rec ): int32;compilerproc;
  2997. Var
  2998. aSign : flag;
  2999. aExp, shiftCount : int16;
  3000. aSig : bits32;
  3001. z : int32;
  3002. Begin
  3003. aSig := extractFloat32Frac( a.float32 );
  3004. aExp := extractFloat32Exp( a.float32 );
  3005. aSign := extractFloat32Sign( a.float32 );
  3006. shiftCount := aExp - $9E;
  3007. if ( 0 <= shiftCount ) then
  3008. Begin
  3009. if ( a.float32 <> $CF000000 ) then
  3010. Begin
  3011. float_raise( float_flag_invalid );
  3012. if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
  3013. Begin
  3014. float32_to_int32_round_to_zero := $7FFFFFFF;
  3015. exit;
  3016. end;
  3017. End;
  3018. float32_to_int32_round_to_zero:= sbits32 ($80000000);
  3019. exit;
  3020. End
  3021. else
  3022. if ( aExp <= $7E ) then
  3023. Begin
  3024. if ( aExp or aSig )<>0 then
  3025. set_inexact_flag;
  3026. float32_to_int32_round_to_zero := 0;
  3027. exit;
  3028. End;
  3029. aSig := ( aSig or $00800000 ) shl 8;
  3030. z := aSig shr ( - shiftCount );
  3031. if ( bits32 ( aSig shl ( shiftCount and 31 ) )<> 0 ) then
  3032. Begin
  3033. set_inexact_flag;
  3034. End;
  3035. if ( aSign<>0 ) then z := - z;
  3036. float32_to_int32_round_to_zero := z;
  3037. End;
  3038. {*----------------------------------------------------------------------------
  3039. | Returns the result of converting the single-precision floating-point value
  3040. | `a' to the 64-bit two's complement integer format. The conversion is
  3041. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  3042. | Arithmetic---which means in particular that the conversion is rounded
  3043. | according to the current rounding mode. If `a' is a NaN, the largest
  3044. | positive integer is returned. Otherwise, if the conversion overflows, the
  3045. | largest integer with the same sign as `a' is returned.
  3046. *----------------------------------------------------------------------------*}
  3047. function float32_to_int64( a: float32 ): int64;
  3048. var
  3049. aSign: flag;
  3050. aExp, shiftCount: int16;
  3051. aSig: bits32;
  3052. aSig64, aSigExtra: bits64;
  3053. begin
  3054. aSig := extractFloat32Frac( a );
  3055. aExp := extractFloat32Exp( a );
  3056. aSign := extractFloat32Sign( a );
  3057. shiftCount := $BE - aExp;
  3058. if ( shiftCount < 0 ) then begin
  3059. float_raise( float_flag_invalid );
  3060. if ( aSign = 0 ) or ( ( aExp = $FF ) and ( aSig <> 0 ) ) then begin
  3061. result := $7FFFFFFFFFFFFFFF;
  3062. exit;
  3063. end;
  3064. result := $8000000000000000;
  3065. exit;
  3066. end;
  3067. if ( aExp <> 0 ) then aSig := aSig or $00800000;
  3068. aSig64 := aSig;
  3069. aSig64 := aSig64 shl 40;
  3070. shift64ExtraRightJamming( aSig64, 0, shiftCount, aSig64, aSigExtra );
  3071. result := roundAndPackInt64( aSign, aSig64, aSigExtra );
  3072. end;
  3073. {*----------------------------------------------------------------------------
  3074. | Returns the result of converting the single-precision floating-point value
  3075. | `a' to the 64-bit two's complement integer format. The conversion is
  3076. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  3077. | Arithmetic, except that the conversion is always rounded toward zero. If
  3078. | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
  3079. | conversion overflows, the largest integer with the same sign as `a' is
  3080. | returned.
  3081. *----------------------------------------------------------------------------*}
  3082. function float32_to_int64_round_to_zero( a: float32 ): int64;
  3083. var
  3084. aSign: flag;
  3085. aExp, shiftCount: int16;
  3086. aSig: bits32;
  3087. aSig64: bits64;
  3088. z: int64;
  3089. begin
  3090. aSig := extractFloat32Frac( a );
  3091. aExp := extractFloat32Exp( a );
  3092. aSign := extractFloat32Sign( a );
  3093. shiftCount := aExp - $BE;
  3094. if ( 0 <= shiftCount ) then begin
  3095. if ( a <> $DF000000 ) then begin
  3096. float_raise( float_flag_invalid );
  3097. if ( aSign = 0) or ( ( aExp = $FF ) and ( aSig <> 0 ) ) then begin
  3098. result := $7FFFFFFFFFFFFFFF;
  3099. exit;
  3100. end;
  3101. end;
  3102. result := $8000000000000000;
  3103. exit;
  3104. end
  3105. else if ( aExp <= $7E ) then begin
  3106. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  3107. result := 0;
  3108. exit;
  3109. end;
  3110. aSig64 := aSig or $00800000;
  3111. aSig64 := aSig64 shl 40;
  3112. z := aSig64 shr ( - shiftCount );
  3113. if bits64( aSig64 shl ( shiftCount and 63 ) ) <> 0 then
  3114. set_inexact_flag;
  3115. if ( aSign <> 0 ) then z := - z;
  3116. result := z;
  3117. end;
  3118. {*
  3119. -------------------------------------------------------------------------------
  3120. Returns the result of converting the single-precision floating-point value
  3121. `a' to the double-precision floating-point format. The conversion is
  3122. performed according to the IEC/IEEE Standard for Binary Floating-Point
  3123. Arithmetic.
  3124. -------------------------------------------------------------------------------
  3125. *}
  3126. Function float32_to_float64( a : float32rec) : Float64;compilerproc;
  3127. Var
  3128. aSign : flag;
  3129. aExp : int16;
  3130. aSig, zSig0, zSig1: bits32;
  3131. tmp : CommonNanT;
  3132. Begin
  3133. aSig := extractFloat32Frac( a.float32 );
  3134. aExp := extractFloat32Exp( a.float32 );
  3135. aSign := extractFloat32Sign( a.float32 );
  3136. if ( aExp = $FF ) then
  3137. Begin
  3138. if ( aSig<>0 ) then
  3139. Begin
  3140. tmp:=float32ToCommonNaN(a.float32);
  3141. result:=commonNaNToFloat64(tmp);
  3142. exit;
  3143. End;
  3144. packFloat64( aSign, $7FF, 0, 0, result);
  3145. exit;
  3146. End;
  3147. if ( aExp = 0 ) then
  3148. Begin
  3149. if ( aSig = 0 ) then
  3150. Begin
  3151. packFloat64( aSign, 0, 0, 0, result );
  3152. exit;
  3153. end;
  3154. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3155. Dec(aExp);
  3156. End;
  3157. shift64Right( aSig, 0, 3, zSig0, zSig1 );
  3158. packFloat64( aSign, aExp + $380, zSig0, zSig1, result );
  3159. End;
  3160. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  3161. {*----------------------------------------------------------------------------
  3162. | Returns the result of converting the canonical NaN `a' to the extended
  3163. | double-precision floating-point format.
  3164. *----------------------------------------------------------------------------*}
  3165. function commonNaNToFloatx80( a : commonNaNT ) : floatx80;
  3166. var
  3167. z : floatx80;
  3168. begin
  3169. z.low := bits64( $C000000000000000 ) or ( a.high shr 1 );
  3170. z.high := ( bits16( a.sign ) shl 15 ) or $7FFF;
  3171. result := z;
  3172. end;
  3173. {*----------------------------------------------------------------------------
  3174. | Returns the result of converting the single-precision floating-point value
  3175. | `a' to the extended double-precision floating-point format. The conversion
  3176. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  3177. | Arithmetic.
  3178. *----------------------------------------------------------------------------*}
  3179. function float32_to_floatx80( a: float32 ): floatx80;
  3180. var
  3181. aSign: flag;
  3182. aExp: int16;
  3183. aSig: bits32;
  3184. tmp: commonNaNT;
  3185. begin
  3186. aSig := extractFloat32Frac( a );
  3187. aExp := extractFloat32Exp( a );
  3188. aSign := extractFloat32Sign( a );
  3189. if ( aExp = $FF ) then begin
  3190. if ( aSig <> 0 ) then begin
  3191. tmp:=float32ToCommonNaN(a);
  3192. result := commonNaNToFloatx80( tmp );
  3193. exit;
  3194. end;
  3195. result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );
  3196. exit;
  3197. end;
  3198. if ( aExp = 0 ) then begin
  3199. if ( aSig = 0 ) then begin
  3200. result := packFloatx80( aSign, 0, 0 );
  3201. exit;
  3202. end;
  3203. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3204. end;
  3205. aSig := aSig or $00800000;
  3206. result := packFloatx80( aSign, aExp + $3F80, bits64(aSig) shl 40 );
  3207. end;
  3208. {$endif FPC_SOFTFLOAT_FLOATX80}
  3209. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  3210. {*----------------------------------------------------------------------------
  3211. | Returns the result of converting the single-precision floating-point value
  3212. | `a' to the double-precision floating-point format. The conversion is
  3213. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  3214. | Arithmetic.
  3215. *----------------------------------------------------------------------------*}
  3216. function float32_to_float128( a: float32 ): float128;
  3217. var
  3218. aSign: flag;
  3219. aExp: int16;
  3220. aSig: bits32;
  3221. tmp: commonNaNT;
  3222. begin
  3223. aSig := extractFloat32Frac( a );
  3224. aExp := extractFloat32Exp( a );
  3225. aSign := extractFloat32Sign( a );
  3226. if ( aExp = $FF ) then begin
  3227. if ( aSig <> 0 ) then begin
  3228. tmp:=float32ToCommonNaN(a);
  3229. result := commonNaNToFloat128( tmp );
  3230. exit;
  3231. end;
  3232. result := packFloat128( aSign, $7FFF, 0, 0 );
  3233. exit;
  3234. end;
  3235. if ( aExp = 0 ) then begin
  3236. if ( aSig = 0 ) then begin
  3237. result := packFloat128( aSign, 0, 0, 0 );
  3238. exit;
  3239. end;
  3240. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3241. dec( aExp );
  3242. end;
  3243. result := packFloat128( aSign, aExp + $3F80, bits64( aSig ) shl 25, 0 );
  3244. end;
  3245. {$endif FPC_SOFTFLOAT_FLOAT128}
  3246. {*
  3247. -------------------------------------------------------------------------------
  3248. Rounds the single-precision floating-point value `a' to an integer,
  3249. and returns the result as a single-precision floating-point value. The
  3250. operation is performed according to the IEC/IEEE Standard for Binary
  3251. Floating-Point Arithmetic.
  3252. -------------------------------------------------------------------------------
  3253. *}
  3254. Function float32_round_to_int( a: float32rec): float32rec;compilerproc;
  3255. Var
  3256. aSign: flag;
  3257. aExp: int16;
  3258. lastBitMask, roundBitsMask: bits32;
  3259. roundingMode: TFPURoundingMode;
  3260. z: float32;
  3261. Begin
  3262. aExp := extractFloat32Exp( a.float32 );
  3263. if ( $96 <= aExp ) then
  3264. Begin
  3265. if ( ( aExp = $FF ) and (extractFloat32Frac( a.float32 )<>0) ) then
  3266. Begin
  3267. float32_round_to_int.float32 := propagateFloat32NaN( a.float32, a.float32 );
  3268. exit;
  3269. End;
  3270. float32_round_to_int:=a;
  3271. exit;
  3272. End;
  3273. if ( aExp <= $7E ) then
  3274. Begin
  3275. if ( bits32 ( a.float32 shl 1 ) = 0 ) then
  3276. Begin
  3277. float32_round_to_int:=a;
  3278. exit;
  3279. end;
  3280. set_inexact_flag;
  3281. aSign := extractFloat32Sign( a.float32 );
  3282. case ( softfloat_rounding_mode ) of
  3283. float_round_nearest_even:
  3284. Begin
  3285. if ( ( aExp = $7E ) and (extractFloat32Frac( a.float32 )<>0) ) then
  3286. Begin
  3287. float32_round_to_int.float32 := packFloat32( aSign, $7F, 0 );
  3288. exit;
  3289. End;
  3290. End;
  3291. float_round_down:
  3292. Begin
  3293. if aSign <> 0 then
  3294. float32_round_to_int.float32 := $BF800000
  3295. else
  3296. float32_round_to_int.float32 := 0;
  3297. exit;
  3298. End;
  3299. float_round_up:
  3300. Begin
  3301. if aSign <> 0 then
  3302. float32_round_to_int.float32 := $80000000
  3303. else
  3304. float32_round_to_int.float32 := $3F800000;
  3305. exit;
  3306. End;
  3307. end;
  3308. float32_round_to_int.float32 := packFloat32( aSign, 0, 0 );
  3309. exit;
  3310. End;
  3311. lastBitMask := 1;
  3312. {_____________________________!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  3313. lastBitMask := lastBitMask shl ($96 - aExp);
  3314. roundBitsMask := lastBitMask - 1;
  3315. z := a.float32;
  3316. roundingMode := softfloat_rounding_mode;
  3317. if ( roundingMode = float_round_nearest_even ) then
  3318. Begin
  3319. z := z + (lastBitMask shr 1);
  3320. if ( ( z and roundBitsMask ) = 0 ) then
  3321. z := z and not lastBitMask;
  3322. End
  3323. else if ( roundingMode <> float_round_to_zero ) then
  3324. Begin
  3325. if ( (extractFloat32Sign( z ) xor flag(roundingMode = float_round_up ))<>0 ) then
  3326. Begin
  3327. z := z + roundBitsMask;
  3328. End;
  3329. End;
  3330. z := z and not roundBitsMask;
  3331. if ( z <> a.float32 ) then
  3332. set_inexact_flag;
  3333. float32_round_to_int.float32 := z;
  3334. End;
  3335. {*
  3336. -------------------------------------------------------------------------------
  3337. Returns the result of adding the absolute values of the single-precision
  3338. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  3339. before being returned. `zSign' is ignored if the result is a NaN.
  3340. The addition is performed according to the IEC/IEEE Standard for Binary
  3341. Floating-Point Arithmetic.
  3342. -------------------------------------------------------------------------------
  3343. *}
  3344. Function addFloat32Sigs( a:float32; b: float32; zSign:flag ): float32;
  3345. Var
  3346. aExp, bExp, zExp: int16;
  3347. aSig, bSig, zSig: bits32;
  3348. expDiff: int16;
  3349. label roundAndPack;
  3350. Begin
  3351. aSig:=extractFloat32Frac( a );
  3352. aExp:=extractFloat32Exp( a );
  3353. bSig:=extractFloat32Frac( b );
  3354. bExp := extractFloat32Exp( b );
  3355. expDiff := aExp - bExp;
  3356. aSig := aSig shl 6;
  3357. bSig := bSig shl 6;
  3358. if ( 0 < expDiff ) then
  3359. Begin
  3360. if ( aExp = $FF ) then
  3361. Begin
  3362. if ( aSig <> 0) then
  3363. Begin
  3364. addFloat32Sigs := propagateFloat32NaN( a, b );
  3365. exit;
  3366. End;
  3367. addFloat32Sigs := a;
  3368. exit;
  3369. End;
  3370. if ( bExp = 0 ) then
  3371. Begin
  3372. Dec(expDiff);
  3373. End
  3374. else
  3375. Begin
  3376. bSig := bSig or $20000000;
  3377. End;
  3378. shift32RightJamming( bSig, expDiff, bSig );
  3379. zExp := aExp;
  3380. End
  3381. else
  3382. If ( expDiff < 0 ) then
  3383. Begin
  3384. if ( bExp = $FF ) then
  3385. Begin
  3386. if ( bSig<>0 ) then
  3387. Begin
  3388. addFloat32Sigs := propagateFloat32NaN( a, b );
  3389. exit;
  3390. end;
  3391. addFloat32Sigs := packFloat32( zSign, $FF, 0 );
  3392. exit;
  3393. End;
  3394. if ( aExp = 0 ) then
  3395. Begin
  3396. Inc(expDiff);
  3397. End
  3398. else
  3399. Begin
  3400. aSig := aSig OR $20000000;
  3401. End;
  3402. shift32RightJamming( aSig, - expDiff, aSig );
  3403. zExp := bExp;
  3404. End
  3405. else
  3406. Begin
  3407. if ( aExp = $FF ) then
  3408. Begin
  3409. if ( aSig OR bSig )<> 0 then
  3410. Begin
  3411. addFloat32Sigs := propagateFloat32NaN( a, b );
  3412. exit;
  3413. end;
  3414. addFloat32Sigs := a;
  3415. exit;
  3416. End;
  3417. if ( aExp = 0 ) then
  3418. Begin
  3419. addFloat32Sigs := packFloat32( zSign, 0, ( aSig + bSig ) shr 6 );
  3420. exit;
  3421. end;
  3422. zSig := $40000000 + aSig + bSig;
  3423. zExp := aExp;
  3424. goto roundAndPack;
  3425. End;
  3426. aSig := aSig OR $20000000;
  3427. zSig := ( aSig + bSig ) shl 1;
  3428. Dec(zExp);
  3429. if ( sbits32 (zSig) < 0 ) then
  3430. Begin
  3431. zSig := aSig + bSig;
  3432. Inc(zExp);
  3433. End;
  3434. roundAndPack:
  3435. addFloat32Sigs := roundAndPackFloat32( zSign, zExp, zSig );
  3436. End;
  3437. {*
  3438. -------------------------------------------------------------------------------
  3439. Returns the result of subtracting the absolute values of the single-
  3440. precision floating-point values `a' and `b'. If `zSign' is 1, the
  3441. difference is negated before being returned. `zSign' is ignored if the
  3442. result is a NaN. The subtraction is performed according to the IEC/IEEE
  3443. Standard for Binary Floating-Point Arithmetic.
  3444. -------------------------------------------------------------------------------
  3445. *}
  3446. Function subFloat32Sigs( a:float32; b:float32; zSign:flag ): float32;
  3447. Var
  3448. aExp, bExp, zExp: int16;
  3449. aSig, bSig, zSig: bits32;
  3450. expDiff : int16;
  3451. label aExpBigger;
  3452. label bExpBigger;
  3453. label aBigger;
  3454. label bBigger;
  3455. label normalizeRoundAndPack;
  3456. Begin
  3457. aSig := extractFloat32Frac( a );
  3458. aExp := extractFloat32Exp( a );
  3459. bSig := extractFloat32Frac( b );
  3460. bExp := extractFloat32Exp( b );
  3461. expDiff := aExp - bExp;
  3462. aSig := aSig shl 7;
  3463. bSig := bSig shl 7;
  3464. if ( 0 < expDiff ) then goto aExpBigger;
  3465. if ( expDiff < 0 ) then goto bExpBigger;
  3466. if ( aExp = $FF ) then
  3467. Begin
  3468. if ( aSig OR bSig )<> 0 then
  3469. Begin
  3470. subFloat32Sigs := propagateFloat32NaN( a, b );
  3471. exit;
  3472. End;
  3473. float_raise( float_flag_invalid );
  3474. subFloat32Sigs := float32_default_nan;
  3475. exit;
  3476. End;
  3477. if ( aExp = 0 ) then
  3478. Begin
  3479. aExp := 1;
  3480. bExp := 1;
  3481. End;
  3482. if ( bSig < aSig ) Then goto aBigger;
  3483. if ( aSig < bSig ) Then goto bBigger;
  3484. subFloat32Sigs := packFloat32( flag(softfloat_rounding_mode = float_round_down), 0, 0 );
  3485. exit;
  3486. bExpBigger:
  3487. if ( bExp = $FF ) then
  3488. Begin
  3489. if ( bSig<>0 ) then
  3490. Begin
  3491. subFloat32Sigs := propagateFloat32NaN( a, b );
  3492. exit;
  3493. End;
  3494. subFloat32Sigs := packFloat32( zSign XOR 1, $FF, 0 );
  3495. exit;
  3496. End;
  3497. if ( aExp = 0 ) then
  3498. Begin
  3499. Inc(expDiff);
  3500. End
  3501. else
  3502. Begin
  3503. aSig := aSig OR $40000000;
  3504. End;
  3505. shift32RightJamming( aSig, - expDiff, aSig );
  3506. bSig := bSig OR $40000000;
  3507. bBigger:
  3508. zSig := bSig - aSig;
  3509. zExp := bExp;
  3510. zSign := zSign xor 1;
  3511. goto normalizeRoundAndPack;
  3512. aExpBigger:
  3513. if ( aExp = $FF ) then
  3514. Begin
  3515. if ( aSig <> 0) then
  3516. Begin
  3517. subFloat32Sigs := propagateFloat32NaN( a, b );
  3518. exit;
  3519. End;
  3520. subFloat32Sigs := a;
  3521. exit;
  3522. End;
  3523. if ( bExp = 0 ) then
  3524. Begin
  3525. Dec(expDiff);
  3526. End
  3527. else
  3528. Begin
  3529. bSig := bSig OR $40000000;
  3530. End;
  3531. shift32RightJamming( bSig, expDiff, bSig );
  3532. aSig := aSig OR $40000000;
  3533. aBigger:
  3534. zSig := aSig - bSig;
  3535. zExp := aExp;
  3536. normalizeRoundAndPack:
  3537. Dec(zExp);
  3538. subFloat32Sigs := normalizeRoundAndPackFloat32( zSign, zExp, zSig );
  3539. End;
  3540. {*
  3541. -------------------------------------------------------------------------------
  3542. Returns the result of adding the single-precision floating-point values `a'
  3543. and `b'. The operation is performed according to the IEC/IEEE Standard for
  3544. Binary Floating-Point Arithmetic.
  3545. -------------------------------------------------------------------------------
  3546. *}
  3547. Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
  3548. Var
  3549. aSign, bSign: Flag;
  3550. Begin
  3551. aSign := extractFloat32Sign( a.float32 );
  3552. bSign := extractFloat32Sign( b.float32 );
  3553. if ( aSign = bSign ) then
  3554. Begin
  3555. float32_add.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
  3556. End
  3557. else
  3558. Begin
  3559. float32_add.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
  3560. End;
  3561. End;
  3562. {*
  3563. -------------------------------------------------------------------------------
  3564. Returns the result of subtracting the single-precision floating-point values
  3565. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3566. for Binary Floating-Point Arithmetic.
  3567. -------------------------------------------------------------------------------
  3568. *}
  3569. Function float32_sub( a: float32rec ; b:float32rec ): float32rec;compilerproc;
  3570. Var
  3571. aSign, bSign: flag;
  3572. Begin
  3573. aSign := extractFloat32Sign( a.float32 );
  3574. bSign := extractFloat32Sign( b.float32 );
  3575. if ( aSign = bSign ) then
  3576. Begin
  3577. float32_sub.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
  3578. End
  3579. else
  3580. Begin
  3581. float32_sub.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
  3582. End;
  3583. End;
  3584. {*
  3585. -------------------------------------------------------------------------------
  3586. Returns the result of multiplying the single-precision floating-point values
  3587. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  3588. for Binary Floating-Point Arithmetic.
  3589. -------------------------------------------------------------------------------
  3590. *}
  3591. Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
  3592. Var
  3593. aSign, bSign, zSign: flag;
  3594. aExp, bExp, zExp : int16;
  3595. aSig, bSig, zSig0, zSig1: bits32;
  3596. Begin
  3597. aSig := extractFloat32Frac( a.float32 );
  3598. aExp := extractFloat32Exp( a.float32 );
  3599. aSign := extractFloat32Sign( a.float32 );
  3600. bSig := extractFloat32Frac( b.float32 );
  3601. bExp := extractFloat32Exp( b.float32 );
  3602. bSign := extractFloat32Sign( b.float32 );
  3603. zSign := aSign xor bSign;
  3604. if ( aExp = $FF ) then
  3605. Begin
  3606. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig<>0) ) ) then
  3607. Begin
  3608. float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3609. exit;
  3610. End;
  3611. if ( ( bits32(bExp) OR bSig ) = 0 ) then
  3612. Begin
  3613. float_raise( float_flag_invalid );
  3614. float32_mul.float32 := float32_default_nan;
  3615. exit;
  3616. End;
  3617. float32_mul.float32 := packFloat32( zSign, $FF, 0 );
  3618. exit;
  3619. End;
  3620. if ( bExp = $FF ) then
  3621. Begin
  3622. if ( bSig <> 0 ) then
  3623. Begin
  3624. float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3625. exit;
  3626. End;
  3627. if ( ( bits32(aExp) OR aSig ) = 0 ) then
  3628. Begin
  3629. float_raise( float_flag_invalid );
  3630. float32_mul.float32 := float32_default_nan;
  3631. exit;
  3632. End;
  3633. float32_mul.float32 := packFloat32( zSign, $FF, 0 );
  3634. exit;
  3635. End;
  3636. if ( aExp = 0 ) then
  3637. Begin
  3638. if ( aSig = 0 ) then
  3639. Begin
  3640. float32_mul.float32 := packFloat32( zSign, 0, 0 );
  3641. exit;
  3642. End;
  3643. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3644. End;
  3645. if ( bExp = 0 ) then
  3646. Begin
  3647. if ( bSig = 0 ) then
  3648. Begin
  3649. float32_mul.float32 := packFloat32( zSign, 0, 0 );
  3650. exit;
  3651. End;
  3652. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3653. End;
  3654. zExp := aExp + bExp - $7F;
  3655. aSig := ( aSig OR $00800000 ) shl 7;
  3656. bSig := ( bSig OR $00800000 ) shl 8;
  3657. mul32To64( aSig, bSig, zSig0, zSig1 );
  3658. zSig0 := zSig0 OR bits32( zSig1 <> 0 );
  3659. if ( 0 <= sbits32 ( zSig0 shl 1 ) ) then
  3660. Begin
  3661. zSig0 := zSig0 shl 1;
  3662. Dec(zExp);
  3663. End;
  3664. float32_mul.float32 := roundAndPackFloat32( zSign, zExp, zSig0 );
  3665. End;
  3666. {*
  3667. -------------------------------------------------------------------------------
  3668. Returns the result of dividing the single-precision floating-point value `a'
  3669. by the corresponding value `b'. The operation is performed according to the
  3670. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3671. -------------------------------------------------------------------------------
  3672. *}
  3673. Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
  3674. Var
  3675. aSign, bSign, zSign: flag;
  3676. aExp, bExp, zExp: int16;
  3677. aSig, bSig, zSig, rem0, rem1, term0, term1: bits32;
  3678. Begin
  3679. aSig := extractFloat32Frac( a.float32 );
  3680. aExp := extractFloat32Exp( a.float32 );
  3681. aSign := extractFloat32Sign( a.float32 );
  3682. bSig := extractFloat32Frac( b.float32 );
  3683. bExp := extractFloat32Exp( b.float32 );
  3684. bSign := extractFloat32Sign( b.float32 );
  3685. zSign := aSign xor bSign;
  3686. if ( aExp = $FF ) then
  3687. Begin
  3688. if ( aSig <> 0 ) then
  3689. Begin
  3690. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3691. exit;
  3692. End;
  3693. if ( bExp = $FF ) then
  3694. Begin
  3695. if ( bSig <> 0) then
  3696. Begin
  3697. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3698. exit;
  3699. End;
  3700. float_raise( float_flag_invalid );
  3701. float32_div.float32 := float32_default_nan;
  3702. exit;
  3703. End;
  3704. float32_div.float32 := packFloat32( zSign, $FF, 0 );
  3705. exit;
  3706. End;
  3707. if ( bExp = $FF ) then
  3708. Begin
  3709. if ( bSig <> 0) then
  3710. Begin
  3711. float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3712. exit;
  3713. End;
  3714. float32_div.float32 := packFloat32( zSign, 0, 0 );
  3715. exit;
  3716. End;
  3717. if ( bExp = 0 ) Then
  3718. Begin
  3719. if ( bSig = 0 ) Then
  3720. Begin
  3721. if ( ( bits32(aExp) OR aSig ) = 0 ) then
  3722. Begin
  3723. float_raise( float_flag_invalid );
  3724. float32_div.float32 := float32_default_nan;
  3725. exit;
  3726. End;
  3727. float_raise( float_flag_divbyzero );
  3728. float32_div.float32 := packFloat32( zSign, $FF, 0 );
  3729. exit;
  3730. End;
  3731. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3732. End;
  3733. if ( aExp = 0 ) Then
  3734. Begin
  3735. if ( aSig = 0 ) Then
  3736. Begin
  3737. float32_div.float32 := packFloat32( zSign, 0, 0 );
  3738. exit;
  3739. End;
  3740. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3741. End;
  3742. zExp := aExp - bExp + $7D;
  3743. aSig := ( aSig OR $00800000 ) shl 7;
  3744. bSig := ( bSig OR $00800000 ) shl 8;
  3745. if ( bSig <= ( aSig + aSig ) ) then
  3746. Begin
  3747. aSig := aSig shr 1;
  3748. Inc(zExp);
  3749. End;
  3750. zSig := estimateDiv64To32( aSig, 0, bSig );
  3751. if ( ( zSig and $3F ) <= 2 ) then
  3752. Begin
  3753. mul32To64( bSig, zSig, term0, term1 );
  3754. sub64( aSig, 0, term0, term1, rem0, rem1 );
  3755. while ( sbits32 (rem0) < 0 ) do
  3756. Begin
  3757. Dec(zSig);
  3758. add64( rem0, rem1, 0, bSig, rem0, rem1 );
  3759. End;
  3760. zSig := zSig or bits32( rem1 <> 0 );
  3761. End;
  3762. float32_div.float32 := roundAndPackFloat32( zSign, zExp, zSig );
  3763. End;
  3764. {*
  3765. -------------------------------------------------------------------------------
  3766. Returns the remainder of the single-precision floating-point value `a'
  3767. with respect to the corresponding value `b'. The operation is performed
  3768. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3769. -------------------------------------------------------------------------------
  3770. *}
  3771. Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
  3772. Var
  3773. aSign, zSign: flag;
  3774. aExp, bExp, expDiff: int16;
  3775. aSig, bSig, q, alternateASig: bits32;
  3776. sigMean: sbits32;
  3777. Begin
  3778. aSig := extractFloat32Frac( a.float32 );
  3779. aExp := extractFloat32Exp( a.float32 );
  3780. aSign := extractFloat32Sign( a.float32 );
  3781. bSig := extractFloat32Frac( b.float32 );
  3782. bExp := extractFloat32Exp( b.float32 );
  3783. if ( aExp = $FF ) then
  3784. Begin
  3785. if ( (aSig<>0) OR ( ( bExp = $FF ) AND (bSig <>0)) ) then
  3786. Begin
  3787. float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3788. exit;
  3789. End;
  3790. float_raise( float_flag_invalid );
  3791. float32_rem.float32 := float32_default_nan;
  3792. exit;
  3793. End;
  3794. if ( bExp = $FF ) then
  3795. Begin
  3796. if ( bSig <> 0 ) then
  3797. Begin
  3798. float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
  3799. exit;
  3800. End;
  3801. float32_rem := a;
  3802. exit;
  3803. End;
  3804. if ( bExp = 0 ) then
  3805. Begin
  3806. if ( bSig = 0 ) then
  3807. Begin
  3808. float_raise( float_flag_invalid );
  3809. float32_rem.float32 := float32_default_nan;
  3810. exit;
  3811. End;
  3812. normalizeFloat32Subnormal( bSig, bExp, bSig );
  3813. End;
  3814. if ( aExp = 0 ) then
  3815. Begin
  3816. if ( aSig = 0 ) then
  3817. Begin
  3818. float32_rem := a;
  3819. exit;
  3820. End;
  3821. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3822. End;
  3823. expDiff := aExp - bExp;
  3824. aSig := ( aSig OR $00800000 ) shl 8;
  3825. bSig := ( bSig OR $00800000 ) shl 8;
  3826. if ( expDiff < 0 ) then
  3827. Begin
  3828. if ( expDiff < -1 ) then
  3829. Begin
  3830. float32_rem := a;
  3831. exit;
  3832. End;
  3833. aSig := aSig shr 1;
  3834. End;
  3835. q := bits32( bSig <= aSig );
  3836. if ( q <> 0) then
  3837. aSig := aSig - bSig;
  3838. expDiff := expDiff - 32;
  3839. while ( 0 < expDiff ) do
  3840. Begin
  3841. q := estimateDiv64To32( aSig, 0, bSig );
  3842. if (2 < q) then
  3843. q := q - 2
  3844. else
  3845. q := 0;
  3846. aSig := - ( ( bSig shr 2 ) * q );
  3847. expDiff := expDiff - 30;
  3848. End;
  3849. expDiff := expDiff + 32;
  3850. if ( 0 < expDiff ) then
  3851. Begin
  3852. q := estimateDiv64To32( aSig, 0, bSig );
  3853. if (2 < q) then
  3854. q := q - 2
  3855. else
  3856. q := 0;
  3857. q := q shr (32 - expDiff);
  3858. bSig := bSig shr 2;
  3859. aSig := ( ( aSig shr 1 ) shl ( expDiff - 1 ) ) - bSig * q;
  3860. End
  3861. else
  3862. Begin
  3863. aSig := aSig shr 2;
  3864. bSig := bSig shr 2;
  3865. End;
  3866. Repeat
  3867. alternateASig := aSig;
  3868. Inc(q);
  3869. aSig := aSig - bSig;
  3870. Until not ( 0 <= sbits32 (aSig) );
  3871. sigMean := aSig + alternateASig;
  3872. if ( ( sigMean < 0 ) OR ( ( sigMean = 0 ) AND (( q and 1 )<>0) ) ) then
  3873. Begin
  3874. aSig := alternateASig;
  3875. End;
  3876. zSign := flag( sbits32 (aSig) < 0 );
  3877. if ( zSign<>0 ) then
  3878. aSig := - aSig;
  3879. float32_rem.float32 := normalizeRoundAndPackFloat32( aSign xor zSign, bExp, aSig );
  3880. End;
  3881. {*
  3882. -------------------------------------------------------------------------------
  3883. Returns the square root of the single-precision floating-point value `a'.
  3884. The operation is performed according to the IEC/IEEE Standard for Binary
  3885. Floating-Point Arithmetic.
  3886. -------------------------------------------------------------------------------
  3887. *}
  3888. Function float32_sqrt(a: float32rec ): float32rec;compilerproc;
  3889. Var
  3890. aSign : flag;
  3891. aExp, zExp : int16;
  3892. aSig, zSig, rem0, rem1, term0, term1: bits32;
  3893. label roundAndPack;
  3894. Begin
  3895. aSig := extractFloat32Frac( a.float32 );
  3896. aExp := extractFloat32Exp( a.float32 );
  3897. aSign := extractFloat32Sign( a.float32 );
  3898. if ( aExp = $FF ) then
  3899. Begin
  3900. if ( aSig <> 0) then
  3901. Begin
  3902. float32_sqrt.float32 := propagateFloat32NaN( a.float32, 0 );
  3903. exit;
  3904. End;
  3905. if ( aSign = 0) then
  3906. Begin
  3907. float32_sqrt := a;
  3908. exit;
  3909. End;
  3910. float_raise( float_flag_invalid );
  3911. float32_sqrt.float32 := float32_default_nan;
  3912. exit;
  3913. End;
  3914. if ( aSign <> 0) then
  3915. Begin
  3916. if ( ( bits32(aExp) OR aSig ) = 0 ) then
  3917. Begin
  3918. float32_sqrt := a;
  3919. exit;
  3920. End;
  3921. float_raise( float_flag_invalid );
  3922. float32_sqrt.float32 := float32_default_nan;
  3923. exit;
  3924. End;
  3925. if ( aExp = 0 ) then
  3926. Begin
  3927. if ( aSig = 0 ) then
  3928. Begin
  3929. float32_sqrt.float32 := 0;
  3930. exit;
  3931. End;
  3932. normalizeFloat32Subnormal( aSig, aExp, aSig );
  3933. End;
  3934. zExp := ( ( aExp - $7F ) shr 1 ) + $7E;
  3935. aSig := ( aSig OR $00800000 ) shl 8;
  3936. zSig := estimateSqrt32( aExp, aSig ) + 2;
  3937. if ( ( zSig and $7F ) <= 5 ) then
  3938. Begin
  3939. if ( zSig < 2 ) then
  3940. Begin
  3941. zSig := $7FFFFFFF;
  3942. goto roundAndPack;
  3943. End
  3944. else
  3945. Begin
  3946. aSig := aSig shr (aExp and 1);
  3947. mul32To64( zSig, zSig, term0, term1 );
  3948. sub64( aSig, 0, term0, term1, rem0, rem1 );
  3949. while ( sbits32 (rem0) < 0 ) do
  3950. Begin
  3951. Dec(zSig);
  3952. shortShift64Left( 0, zSig, 1, term0, term1 );
  3953. term1 := term1 or 1;
  3954. add64( rem0, rem1, term0, term1, rem0, rem1 );
  3955. End;
  3956. zSig := zSig OR bits32( ( rem0 OR rem1 ) <> 0 );
  3957. End;
  3958. End;
  3959. shift32RightJamming( zSig, 1, zSig );
  3960. roundAndPack:
  3961. float32_sqrt.float32 := roundAndPackFloat32( 0, zExp, zSig );
  3962. End;
  3963. {*
  3964. -------------------------------------------------------------------------------
  3965. Returns 1 if the single-precision floating-point value `a' is equal to
  3966. the corresponding value `b', and 0 otherwise. The comparison is performed
  3967. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  3968. -------------------------------------------------------------------------------
  3969. *}
  3970. Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
  3971. Begin
  3972. if ((( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 )<>0))
  3973. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 )<>0) )
  3974. ) then
  3975. Begin
  3976. if ( (float32_is_signaling_nan( a.float32 )<>0) OR (float32_is_signaling_nan( b.float32 )<>0) ) then
  3977. Begin
  3978. float_raise( float_flag_invalid );
  3979. End;
  3980. float32_eq := 0;
  3981. exit;
  3982. End;
  3983. float32_eq := flag( a.float32 = b.float32 ) OR flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) = 0 );
  3984. End;
  3985. {*
  3986. -------------------------------------------------------------------------------
  3987. Returns 1 if the single-precision floating-point value `a' is less than
  3988. or equal to the corresponding value `b', and 0 otherwise. The comparison
  3989. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  3990. Arithmetic.
  3991. -------------------------------------------------------------------------------
  3992. *}
  3993. Function float32_le( a: float32rec; b : float32rec ):flag;compilerproc;
  3994. var
  3995. aSign, bSign: flag;
  3996. Begin
  3997. if ( ( ( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 )<>0) )
  3998. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 )<>0) )
  3999. ) then
  4000. Begin
  4001. float_raise( float_flag_invalid );
  4002. float32_le := 0;
  4003. exit;
  4004. End;
  4005. aSign := extractFloat32Sign( a.float32 );
  4006. bSign := extractFloat32Sign( b.float32 );
  4007. if ( aSign <> bSign ) then
  4008. Begin
  4009. float32_le := aSign OR flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) = 0 );
  4010. exit;
  4011. End;
  4012. float32_le := flag(flag( a.float32 = b.float32 ) OR flag( aSign xor flag( a.float32 < b.float32 ) ));
  4013. End;
  4014. {*
  4015. -------------------------------------------------------------------------------
  4016. Returns 1 if the single-precision floating-point value `a' is less than
  4017. the corresponding value `b', and 0 otherwise. The comparison is performed
  4018. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4019. -------------------------------------------------------------------------------
  4020. *}
  4021. Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
  4022. var
  4023. aSign, bSign: flag;
  4024. Begin
  4025. if ( ( ( extractFloat32Exp( a.float32 ) = $FF ) AND (extractFloat32Frac( a.float32 ) <>0))
  4026. OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND (extractFloat32Frac( b.float32 ) <>0) )
  4027. ) then
  4028. Begin
  4029. float_raise( float_flag_invalid );
  4030. float32_lt :=0;
  4031. exit;
  4032. End;
  4033. aSign := extractFloat32Sign( a.float32 );
  4034. bSign := extractFloat32Sign( b.float32 );
  4035. if ( aSign <> bSign ) then
  4036. Begin
  4037. float32_lt := aSign AND flag( bits32 ( ( a.float32 OR b.float32 ) shl 1 ) <> 0 );
  4038. exit;
  4039. End;
  4040. float32_lt := flag(flag( a.float32 <> b.float32 ) AND flag( aSign xor flag( a.float32 < b.float32 ) ));
  4041. End;
  4042. {*
  4043. -------------------------------------------------------------------------------
  4044. Returns 1 if the single-precision floating-point value `a' is equal to
  4045. the corresponding value `b', and 0 otherwise. The invalid exception is
  4046. raised if either operand is a NaN. Otherwise, the comparison is performed
  4047. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4048. -------------------------------------------------------------------------------
  4049. *}
  4050. Function float32_eq_signaling( a: float32; b: float32) : flag;
  4051. Begin
  4052. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a ) <> 0))
  4053. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b ) <> 0))
  4054. ) then
  4055. Begin
  4056. float_raise( float_flag_invalid );
  4057. float32_eq_signaling := 0;
  4058. exit;
  4059. End;
  4060. float32_eq_signaling := (flag( a = b ) OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 ));
  4061. End;
  4062. {*
  4063. -------------------------------------------------------------------------------
  4064. Returns 1 if the single-precision floating-point value `a' is less than or
  4065. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  4066. cause an exception. Otherwise, the comparison is performed according to the
  4067. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4068. -------------------------------------------------------------------------------
  4069. *}
  4070. Function float32_le_quiet( a: float32 ; b : float32 ): flag;
  4071. Var
  4072. aSign, bSign: flag;
  4073. Begin
  4074. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  4075. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  4076. ) then
  4077. Begin
  4078. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  4079. Begin
  4080. float_raise( float_flag_invalid );
  4081. End;
  4082. float32_le_quiet := 0;
  4083. exit;
  4084. End;
  4085. aSign := extractFloat32Sign( a );
  4086. bSign := extractFloat32Sign( b );
  4087. if ( aSign <> bSign ) then
  4088. Begin
  4089. float32_le_quiet := aSign OR flag( bits32 ( ( a OR b ) shl 1 ) = 0 );
  4090. exit;
  4091. End;
  4092. float32_le_quiet := flag(flag( a = b ) OR flag( aSign xor flag( a < b ) ));
  4093. End;
  4094. {*
  4095. -------------------------------------------------------------------------------
  4096. Returns 1 if the single-precision floating-point value `a' is less than
  4097. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  4098. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  4099. Standard for Binary Floating-Point Arithmetic.
  4100. -------------------------------------------------------------------------------
  4101. *}
  4102. Function float32_lt_quiet( a: float32 ; b: float32 ): flag;
  4103. Var
  4104. aSign, bSign: flag;
  4105. Begin
  4106. if ( ( ( extractFloat32Exp( a ) = $FF ) AND (extractFloat32Frac( a )<>0) )
  4107. OR ( ( extractFloat32Exp( b ) = $FF ) AND (extractFloat32Frac( b )<>0) )
  4108. ) then
  4109. Begin
  4110. if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
  4111. Begin
  4112. float_raise( float_flag_invalid );
  4113. End;
  4114. float32_lt_quiet := 0;
  4115. exit;
  4116. End;
  4117. aSign := extractFloat32Sign( a );
  4118. bSign := extractFloat32Sign( b );
  4119. if ( aSign <> bSign ) then
  4120. Begin
  4121. float32_lt_quiet := aSign AND flag( bits32 ( ( a OR b ) shl 1 ) <> 0 );
  4122. exit;
  4123. End;
  4124. float32_lt_quiet := flag(flag( a <> b ) AND ( aSign xor flag( a < b ) ));
  4125. End;
  4126. {*
  4127. -------------------------------------------------------------------------------
  4128. Returns the result of converting the double-precision floating-point value
  4129. `a' to the 32-bit two's complement integer format. The conversion is
  4130. performed according to the IEC/IEEE Standard for Binary Floating-Point
  4131. Arithmetic---which means in particular that the conversion is rounded
  4132. according to the current rounding mode. If `a' is a NaN, the largest
  4133. positive integer is returned. Otherwise, if the conversion overflows, the
  4134. largest integer with the same sign as `a' is returned.
  4135. -------------------------------------------------------------------------------
  4136. *}
  4137. Function float64_to_int32(a: float64): int32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32'];compilerproc;{$endif}
  4138. var
  4139. aSign: flag;
  4140. aExp, shiftCount: int16;
  4141. aSig0, aSig1, absZ, aSigExtra: bits32;
  4142. z: int32;
  4143. roundingMode: TFPURoundingMode;
  4144. label invalid;
  4145. Begin
  4146. aSig1 := extractFloat64Frac1( a );
  4147. aSig0 := extractFloat64Frac0( a );
  4148. aExp := extractFloat64Exp( a );
  4149. aSign := extractFloat64Sign( a );
  4150. shiftCount := aExp - $413;
  4151. if ( 0 <= shiftCount ) then
  4152. Begin
  4153. if ( $41E < aExp ) then
  4154. Begin
  4155. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  4156. aSign := 0;
  4157. goto invalid;
  4158. End;
  4159. shortShift64Left(
  4160. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  4161. if ( $80000000 < absZ ) then
  4162. goto invalid;
  4163. End
  4164. else
  4165. Begin
  4166. aSig1 := flag( aSig1 <> 0 );
  4167. if ( aExp < $3FE ) then
  4168. Begin
  4169. aSigExtra := aExp OR aSig0 OR aSig1;
  4170. absZ := 0;
  4171. End
  4172. else
  4173. Begin
  4174. aSig0 := aSig0 OR $00100000;
  4175. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  4176. absZ := aSig0 shr ( - shiftCount );
  4177. End;
  4178. End;
  4179. roundingMode := softfloat_rounding_mode;
  4180. if ( roundingMode = float_round_nearest_even ) then
  4181. Begin
  4182. if ( sbits32(aSigExtra) < 0 ) then
  4183. Begin
  4184. Inc(absZ);
  4185. if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
  4186. absZ := absZ and not 1;
  4187. End;
  4188. if aSign <> 0 then
  4189. z := - absZ
  4190. else
  4191. z := absZ;
  4192. End
  4193. else
  4194. Begin
  4195. aSigExtra := bits32( aSigExtra <> 0 );
  4196. if ( aSign <> 0) then
  4197. Begin
  4198. z := - ( absZ
  4199. + ( int32( roundingMode = float_round_down ) and aSigExtra ) );
  4200. End
  4201. else
  4202. Begin
  4203. z := absZ + ( int32( roundingMode = float_round_up ) and aSigExtra );
  4204. End
  4205. End;
  4206. if ( (( aSign xor flag( z < 0 ) )<>0) AND (z<>0) ) then
  4207. Begin
  4208. invalid:
  4209. float_raise( float_flag_invalid );
  4210. if (aSign <> 0 ) then
  4211. float64_to_int32 := sbits32 ($80000000)
  4212. else
  4213. float64_to_int32 := $7FFFFFFF;
  4214. exit;
  4215. End;
  4216. if ( aSigExtra <> 0) then
  4217. set_inexact_flag;
  4218. float64_to_int32 := z;
  4219. End;
  4220. {*
  4221. -------------------------------------------------------------------------------
  4222. Returns the result of converting the double-precision floating-point value
  4223. `a' to the 32-bit two's complement integer format. The conversion is
  4224. performed according to the IEC/IEEE Standard for Binary Floating-Point
  4225. Arithmetic, except that the conversion is always rounded toward zero.
  4226. If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  4227. the conversion overflows, the largest integer with the same sign as `a' is
  4228. returned.
  4229. -------------------------------------------------------------------------------
  4230. *}
  4231. Function float64_to_int32_round_to_zero(a: float64 ): int32;
  4232. {$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32_ROUND_TO_ZERO'];compilerproc;{$endif}
  4233. Var
  4234. aSign: flag;
  4235. aExp, shiftCount: int16;
  4236. aSig0, aSig1, absZ, aSigExtra: bits32;
  4237. z: int32;
  4238. label invalid;
  4239. Begin
  4240. aSig1 := extractFloat64Frac1( a );
  4241. aSig0 := extractFloat64Frac0( a );
  4242. aExp := extractFloat64Exp( a );
  4243. aSign := extractFloat64Sign( a );
  4244. shiftCount := aExp - $413;
  4245. if ( 0 <= shiftCount ) then
  4246. Begin
  4247. if ( $41E < aExp ) then
  4248. Begin
  4249. if ( ( aExp = $7FF ) AND (( aSig0 OR aSig1 )<>0) ) then
  4250. aSign := 0;
  4251. goto invalid;
  4252. End;
  4253. shortShift64Left(
  4254. aSig0 OR $00100000, aSig1, shiftCount, absZ, aSigExtra );
  4255. End
  4256. else
  4257. Begin
  4258. if ( aExp < $3FF ) then
  4259. Begin
  4260. if ( bits32(aExp) OR aSig0 OR aSig1 )<>0 then
  4261. Begin
  4262. set_inexact_flag;
  4263. End;
  4264. float64_to_int32_round_to_zero := 0;
  4265. exit;
  4266. End;
  4267. aSig0 := aSig0 or $00100000;
  4268. aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR aSig1;
  4269. absZ := aSig0 shr ( - shiftCount );
  4270. End;
  4271. if aSign <> 0 then
  4272. z := - absZ
  4273. else
  4274. z := absZ;
  4275. if ( (( aSign xor flag( z < 0 )) <> 0) AND (z<>0) ) then
  4276. Begin
  4277. invalid:
  4278. float_raise( float_flag_invalid );
  4279. if (aSign <> 0) then
  4280. float64_to_int32_round_to_zero := sbits32 ($80000000)
  4281. else
  4282. float64_to_int32_round_to_zero := $7FFFFFFF;
  4283. exit;
  4284. End;
  4285. if ( aSigExtra <> 0) then
  4286. set_inexact_flag;
  4287. float64_to_int32_round_to_zero := z;
  4288. End;
  4289. {*----------------------------------------------------------------------------
  4290. | Returns the result of converting the double-precision floating-point value
  4291. | `a' to the 64-bit two's complement integer format. The conversion is
  4292. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  4293. | Arithmetic---which means in particular that the conversion is rounded
  4294. | according to the current rounding mode. If `a' is a NaN, the largest
  4295. | positive integer is returned. Otherwise, if the conversion overflows, the
  4296. | largest integer with the same sign as `a' is returned.
  4297. *----------------------------------------------------------------------------*}
  4298. function float64_to_int64( a: float64 ): int64;
  4299. var
  4300. aSign: flag;
  4301. aExp, shiftCount: int16;
  4302. aSig, aSigExtra: bits64;
  4303. begin
  4304. aSig := extractFloat64Frac( a );
  4305. aExp := extractFloat64Exp( a );
  4306. aSign := extractFloat64Sign( a );
  4307. if ( aExp <> 0 ) then aSig := aSig or $0010000000000000;
  4308. shiftCount := $433 - aExp;
  4309. if ( shiftCount <= 0 ) then begin
  4310. if ( $43E < aExp ) then begin
  4311. float_raise( float_flag_invalid );
  4312. if ( ( aSign = 0 )
  4313. or ( ( aExp = $7FF )
  4314. and ( aSig <> $0010000000000000 ) )
  4315. ) then begin
  4316. result := $7FFFFFFFFFFFFFFF;
  4317. exit;
  4318. end;
  4319. result := $8000000000000000;
  4320. exit;
  4321. end;
  4322. aSigExtra := 0;
  4323. aSig := aSig shl ( - shiftCount );
  4324. end
  4325. else
  4326. shift64ExtraRightJamming( aSig, 0, shiftCount, aSig, aSigExtra );
  4327. result := roundAndPackInt64( aSign, aSig, aSigExtra );
  4328. end;
  4329. {*----------------------------------------------------------------------------
  4330. | Returns the result of converting the double-precision floating-point value
  4331. | `a' to the 64-bit two's complement integer format. The conversion is
  4332. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  4333. | Arithmetic, except that the conversion is always rounded toward zero.
  4334. | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  4335. | the conversion overflows, the largest integer with the same sign as `a' is
  4336. | returned.
  4337. *----------------------------------------------------------------------------*}
  4338. {$define FPC_SYSTEM_HAS_float64_to_int64_round_to_zero}
  4339. function float64_to_int64_round_to_zero( a: float64 ): int64;
  4340. var
  4341. aSign: flag;
  4342. aExp, shiftCount: int16;
  4343. aSig: bits64;
  4344. z: int64;
  4345. begin
  4346. aSig := extractFloat64Frac( a );
  4347. aExp := extractFloat64Exp( a );
  4348. aSign := extractFloat64Sign( a );
  4349. if ( aExp <> 0 ) then aSig := aSig or $0010000000000000;
  4350. shiftCount := aExp - $433;
  4351. if ( 0 <= shiftCount ) then begin
  4352. if ( $43E <= aExp ) then begin
  4353. if ( bits64 ( a ) <> bits64( $C3E0000000000000 ) ) then begin
  4354. float_raise( float_flag_invalid );
  4355. if ( ( aSign = 0 )
  4356. or ( ( aExp = $7FF )
  4357. and ( aSig <> $0010000000000000 ) )
  4358. ) then begin
  4359. result := $7FFFFFFFFFFFFFFF;
  4360. exit;
  4361. end;
  4362. end;
  4363. result := $8000000000000000;
  4364. exit;
  4365. end;
  4366. z := aSig shl shiftCount;
  4367. end
  4368. else begin
  4369. if ( aExp < $3FE ) then begin
  4370. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  4371. result := 0;
  4372. exit;
  4373. end;
  4374. z := aSig shr ( - shiftCount );
  4375. if ( bits64( aSig shl ( shiftCount and 63 ) ) <> 0 ) then
  4376. set_inexact_flag;
  4377. end;
  4378. if ( aSign <> 0 ) then z := - z;
  4379. result := z;
  4380. end;
  4381. {*
  4382. -------------------------------------------------------------------------------
  4383. Returns the result of converting the double-precision floating-point value
  4384. `a' to the single-precision floating-point format. The conversion is
  4385. performed according to the IEC/IEEE Standard for Binary Floating-Point
  4386. Arithmetic.
  4387. -------------------------------------------------------------------------------
  4388. *}
  4389. Function float64_to_float32(a: float64 ): float32rec;compilerproc;
  4390. Var
  4391. aSign: flag;
  4392. aExp: int16;
  4393. aSig0, aSig1, zSig: bits32;
  4394. allZero: bits32;
  4395. tmp : CommonNanT;
  4396. Begin
  4397. aSig1 := extractFloat64Frac1( a );
  4398. aSig0 := extractFloat64Frac0( a );
  4399. aExp := extractFloat64Exp( a );
  4400. aSign := extractFloat64Sign( a );
  4401. if ( aExp = $7FF ) then
  4402. Begin
  4403. if ( aSig0 OR aSig1 ) <> 0 then
  4404. Begin
  4405. tmp:=float64ToCommonNaN(a);
  4406. float64_to_float32.float32 := commonNaNToFloat32( tmp );
  4407. exit;
  4408. End;
  4409. float64_to_float32.float32 := packFloat32( aSign, $FF, 0 );
  4410. exit;
  4411. End;
  4412. shift64RightJamming( aSig0, aSig1, 22, allZero, zSig );
  4413. if ( aExp <> 0) then
  4414. zSig := zSig OR $40000000;
  4415. float64_to_float32.float32 := roundAndPackFloat32( aSign, aExp - $381, zSig );
  4416. End;
  4417. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  4418. {*----------------------------------------------------------------------------
  4419. | Returns the result of converting the double-precision floating-point value
  4420. | `a' to the extended double-precision floating-point format. The conversion
  4421. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  4422. | Arithmetic.
  4423. *----------------------------------------------------------------------------*}
  4424. function float64_to_floatx80( a: float64 ): floatx80;
  4425. var
  4426. aSign: flag;
  4427. aExp: int16;
  4428. aSig: bits64;
  4429. begin
  4430. aSig := extractFloat64Frac( a );
  4431. aExp := extractFloat64Exp( a );
  4432. aSign := extractFloat64Sign( a );
  4433. if ( aExp = $7FF ) then begin
  4434. if ( aSig <> 0 ) then begin
  4435. result := commonNaNToFloatx80( float64ToCommonNaN( a ) );
  4436. exit;
  4437. end;
  4438. result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );
  4439. exit;
  4440. end;
  4441. if ( aExp = 0 ) then begin
  4442. if ( aSig = 0 ) then begin
  4443. result := packFloatx80( aSign, 0, 0 );
  4444. exit;
  4445. end;
  4446. normalizeFloat64Subnormal( aSig, aExp, aSig );
  4447. end;
  4448. result :=
  4449. packFloatx80(
  4450. aSign, aExp + $3C00, ( aSig or $0010000000000000 ) shl 11 );
  4451. end;
  4452. {$endif FPC_SOFTFLOAT_FLOATX80}
  4453. {*
  4454. -------------------------------------------------------------------------------
  4455. Rounds the double-precision floating-point value `a' to an integer,
  4456. and returns the result as a double-precision floating-point value. The
  4457. operation is performed according to the IEC/IEEE Standard for Binary
  4458. Floating-Point Arithmetic.
  4459. -------------------------------------------------------------------------------
  4460. *}
  4461. function float64_round_to_int(a: float64) : Float64;{$ifdef fpc} [public,Alias:'FLOAT64_ROUND_TO_INT'];compilerproc;{$endif}
  4462. Var
  4463. aSign: flag;
  4464. aExp: int16;
  4465. lastBitMask, roundBitsMask: bits32;
  4466. roundingMode: TFPURoundingMode;
  4467. z: float64;
  4468. Begin
  4469. aExp := extractFloat64Exp( a );
  4470. if ( $413 <= aExp ) then
  4471. Begin
  4472. if ( $433 <= aExp ) then
  4473. Begin
  4474. if ( ( aExp = $7FF )
  4475. AND
  4476. (
  4477. ( extractFloat64Frac0( a ) OR extractFloat64Frac1( a )
  4478. ) <>0)
  4479. ) then
  4480. Begin
  4481. propagateFloat64NaN( a, a, result );
  4482. exit;
  4483. End;
  4484. result := a;
  4485. exit;
  4486. End;
  4487. lastBitMask := 1;
  4488. lastBitMask := ( lastBitMask shl ( $432 - aExp ) ) shl 1;
  4489. roundBitsMask := lastBitMask - 1;
  4490. z := a;
  4491. roundingMode := softfloat_rounding_mode;
  4492. if ( roundingMode = float_round_nearest_even ) then
  4493. Begin
  4494. if ( lastBitMask <> 0) then
  4495. Begin
  4496. add64( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
  4497. if ( ( z.low and roundBitsMask ) = 0 ) then
  4498. z.low := z.low and not lastBitMask;
  4499. End
  4500. else
  4501. Begin
  4502. if ( sbits32 (z.low) < 0 ) then
  4503. Begin
  4504. Inc(z.high);
  4505. if ( bits32 ( z.low shl 1 ) = 0 ) then
  4506. z.high := z.high and not 1;
  4507. End;
  4508. End;
  4509. End
  4510. else if ( roundingMode <> float_round_to_zero ) then
  4511. Begin
  4512. if ( extractFloat64Sign( z )
  4513. xor flag( roundingMode = float_round_up ) )<> 0 then
  4514. Begin
  4515. add64( z.high, z.low, 0, roundBitsMask, z.high, z.low );
  4516. End;
  4517. End;
  4518. z.low := z.low and not roundBitsMask;
  4519. End
  4520. else
  4521. Begin
  4522. if ( aExp <= $3FE ) then
  4523. Begin
  4524. if ( ( ( bits32 ( a.high shl 1 ) ) OR a.low ) = 0 ) then
  4525. Begin
  4526. result := a;
  4527. exit;
  4528. End;
  4529. set_inexact_flag;
  4530. aSign := extractFloat64Sign( a );
  4531. case ( softfloat_rounding_mode ) of
  4532. float_round_nearest_even:
  4533. Begin
  4534. if ( ( aExp = $3FE )
  4535. AND ( (extractFloat64Frac0( a ) OR extractFloat64Frac1( a ) )<>0)
  4536. ) then
  4537. Begin
  4538. packFloat64( aSign, $3FF, 0, 0, result );
  4539. exit;
  4540. End;
  4541. End;
  4542. float_round_down:
  4543. Begin
  4544. if aSign<>0 then
  4545. packFloat64( 1, $3FF, 0, 0, result )
  4546. else
  4547. packFloat64( 0, 0, 0, 0, result );
  4548. exit;
  4549. End;
  4550. float_round_up:
  4551. Begin
  4552. if aSign <> 0 then
  4553. packFloat64( 1, 0, 0, 0, result )
  4554. else
  4555. packFloat64( 0, $3FF, 0, 0, result );
  4556. exit;
  4557. End;
  4558. end;
  4559. packFloat64( aSign, 0, 0, 0, result );
  4560. exit;
  4561. End;
  4562. lastBitMask := 1;
  4563. lastBitMask := lastBitMask shl ($413 - aExp);
  4564. roundBitsMask := lastBitMask - 1;
  4565. z.low := 0;
  4566. z.high := a.high;
  4567. roundingMode := softfloat_rounding_mode;
  4568. if ( roundingMode = float_round_nearest_even ) then
  4569. Begin
  4570. z.high := z.high + lastBitMask shr 1;
  4571. if ( ( ( z.high and roundBitsMask ) OR a.low ) = 0 ) then
  4572. Begin
  4573. z.high := z.high and not lastBitMask;
  4574. End;
  4575. End
  4576. else if ( roundingMode <> float_round_to_zero ) then
  4577. Begin
  4578. if ( extractFloat64Sign( z )
  4579. xor flag( roundingMode = float_round_up ) )<> 0 then
  4580. Begin
  4581. z.high := z.high or bits32( a.low <> 0 );
  4582. z.high := z.high + roundBitsMask;
  4583. End;
  4584. End;
  4585. z.high := z.high and not roundBitsMask;
  4586. End;
  4587. if ( ( z.low <> a.low ) OR ( z.high <> a.high ) ) then
  4588. Begin
  4589. set_inexact_flag;
  4590. End;
  4591. result := z;
  4592. End;
  4593. {*
  4594. -------------------------------------------------------------------------------
  4595. Returns the result of adding the absolute values of the double-precision
  4596. floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  4597. before being returned. `zSign' is ignored if the result is a NaN.
  4598. The addition is performed according to the IEC/IEEE Standard for Binary
  4599. Floating-Point Arithmetic.
  4600. -------------------------------------------------------------------------------
  4601. *}
  4602. Procedure addFloat64Sigs( a:float64 ; b: float64 ; zSign:flag; Var out: float64 );
  4603. Var
  4604. aExp, bExp, zExp: int16;
  4605. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  4606. expDiff: int16;
  4607. label shiftRight1;
  4608. label roundAndPack;
  4609. Begin
  4610. aSig1 := extractFloat64Frac1( a );
  4611. aSig0 := extractFloat64Frac0( a );
  4612. aExp := extractFloat64Exp( a );
  4613. bSig1 := extractFloat64Frac1( b );
  4614. bSig0 := extractFloat64Frac0( b );
  4615. bExp := extractFloat64Exp( b );
  4616. expDiff := aExp - bExp;
  4617. if ( 0 < expDiff ) then
  4618. Begin
  4619. if ( aExp = $7FF ) then
  4620. Begin
  4621. if ( aSig0 OR aSig1 ) <> 0 then
  4622. Begin
  4623. propagateFloat64NaN( a, b, out );
  4624. exit;
  4625. end;
  4626. out := a;
  4627. exit;
  4628. End;
  4629. if ( bExp = 0 ) then
  4630. Begin
  4631. Dec(expDiff);
  4632. End
  4633. else
  4634. Begin
  4635. bSig0 := bSig0 or $00100000;
  4636. End;
  4637. shift64ExtraRightJamming(
  4638. bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
  4639. zExp := aExp;
  4640. End
  4641. else if ( expDiff < 0 ) then
  4642. Begin
  4643. if ( bExp = $7FF ) then
  4644. Begin
  4645. if ( bSig0 OR bSig1 ) <> 0 then
  4646. Begin
  4647. propagateFloat64NaN( a, b, out );
  4648. exit;
  4649. End;
  4650. packFloat64( zSign, $7FF, 0, 0, out );
  4651. exit;
  4652. End;
  4653. if ( aExp = 0 ) then
  4654. Begin
  4655. Inc(expDiff);
  4656. End
  4657. else
  4658. Begin
  4659. aSig0 := aSig0 or $00100000;
  4660. End;
  4661. shift64ExtraRightJamming(
  4662. aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
  4663. zExp := bExp;
  4664. End
  4665. else
  4666. Begin
  4667. if ( aExp = $7FF ) then
  4668. Begin
  4669. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  4670. Begin
  4671. propagateFloat64NaN( a, b, out );
  4672. exit;
  4673. End;
  4674. out := a;
  4675. exit;
  4676. End;
  4677. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4678. if ( aExp = 0 ) then
  4679. Begin
  4680. packFloat64( zSign, 0, zSig0, zSig1, out );
  4681. exit;
  4682. End;
  4683. zSig2 := 0;
  4684. zSig0 := zSig0 or $00200000;
  4685. zExp := aExp;
  4686. goto shiftRight1;
  4687. End;
  4688. aSig0 := aSig0 or $00100000;
  4689. add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4690. Dec(zExp);
  4691. if ( zSig0 < $00200000 ) then
  4692. goto roundAndPack;
  4693. Inc(zExp);
  4694. shiftRight1:
  4695. shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  4696. roundAndPack:
  4697. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );
  4698. End;
  4699. {*
  4700. -------------------------------------------------------------------------------
  4701. Returns the result of subtracting the absolute values of the double-
  4702. precision floating-point values `a' and `b'. If `zSign' is 1, the
  4703. difference is negated before being returned. `zSign' is ignored if the
  4704. result is a NaN. The subtraction is performed according to the IEC/IEEE
  4705. Standard for Binary Floating-Point Arithmetic.
  4706. -------------------------------------------------------------------------------
  4707. *}
  4708. Procedure subFloat64Sigs( a:float64; b: float64 ; zSign:flag; Var out: float64 );
  4709. Var
  4710. aExp, bExp, zExp: int16;
  4711. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits32;
  4712. expDiff: int16;
  4713. z: float64;
  4714. label aExpBigger;
  4715. label bExpBigger;
  4716. label aBigger;
  4717. label bBigger;
  4718. label normalizeRoundAndPack;
  4719. Begin
  4720. aSig1 := extractFloat64Frac1( a );
  4721. aSig0 := extractFloat64Frac0( a );
  4722. aExp := extractFloat64Exp( a );
  4723. bSig1 := extractFloat64Frac1( b );
  4724. bSig0 := extractFloat64Frac0( b );
  4725. bExp := extractFloat64Exp( b );
  4726. expDiff := aExp - bExp;
  4727. shortShift64Left( aSig0, aSig1, 10, aSig0, aSig1 );
  4728. shortShift64Left( bSig0, bSig1, 10, bSig0, bSig1 );
  4729. if ( 0 < expDiff ) then goto aExpBigger;
  4730. if ( expDiff < 0 ) then goto bExpBigger;
  4731. if ( aExp = $7FF ) then
  4732. Begin
  4733. if ( aSig0 OR aSig1 OR bSig0 OR bSig1 ) <> 0 then
  4734. Begin
  4735. propagateFloat64NaN( a, b, out );
  4736. exit;
  4737. End;
  4738. float_raise( float_flag_invalid );
  4739. z.low := float64_default_nan_low;
  4740. z.high := float64_default_nan_high;
  4741. out := z;
  4742. exit;
  4743. End;
  4744. if ( aExp = 0 ) then
  4745. Begin
  4746. aExp := 1;
  4747. bExp := 1;
  4748. End;
  4749. if ( bSig0 < aSig0 ) then goto aBigger;
  4750. if ( aSig0 < bSig0 ) then goto bBigger;
  4751. if ( bSig1 < aSig1 ) then goto aBigger;
  4752. if ( aSig1 < bSig1 ) then goto bBigger;
  4753. packFloat64( flag(softfloat_rounding_mode = float_round_down), 0, 0, 0 , out);
  4754. exit;
  4755. bExpBigger:
  4756. if ( bExp = $7FF ) then
  4757. Begin
  4758. if ( bSig0 OR bSig1 ) <> 0 then
  4759. Begin
  4760. propagateFloat64NaN( a, b, out );
  4761. exit;
  4762. End;
  4763. packFloat64( zSign xor 1, $7FF, 0, 0, out );
  4764. exit;
  4765. End;
  4766. if ( aExp = 0 ) then
  4767. Begin
  4768. Inc(expDiff);
  4769. End
  4770. else
  4771. Begin
  4772. aSig0 := aSig0 or $40000000;
  4773. End;
  4774. shift64RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  4775. bSig0 := bSig0 or $40000000;
  4776. bBigger:
  4777. sub64( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
  4778. zExp := bExp;
  4779. zSign := zSign xor 1;
  4780. goto normalizeRoundAndPack;
  4781. aExpBigger:
  4782. if ( aExp = $7FF ) then
  4783. Begin
  4784. if ( aSig0 OR aSig1 ) <> 0 then
  4785. Begin
  4786. propagateFloat64NaN( a, b, out );
  4787. exit;
  4788. End;
  4789. out := a;
  4790. exit;
  4791. End;
  4792. if ( bExp = 0 ) then
  4793. Begin
  4794. Dec(expDiff);
  4795. End
  4796. else
  4797. Begin
  4798. bSig0 := bSig0 or $40000000;
  4799. End;
  4800. shift64RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
  4801. aSig0 := aSig0 or $40000000;
  4802. aBigger:
  4803. sub64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  4804. zExp := aExp;
  4805. normalizeRoundAndPack:
  4806. Dec(zExp);
  4807. normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1, out );
  4808. End;
  4809. {*
  4810. -------------------------------------------------------------------------------
  4811. Returns the result of adding the double-precision floating-point values `a'
  4812. and `b'. The operation is performed according to the IEC/IEEE Standard for
  4813. Binary Floating-Point Arithmetic.
  4814. -------------------------------------------------------------------------------
  4815. *}
  4816. Function float64_add( a: float64; b : float64) : Float64;
  4817. {$ifdef fpc}[public,Alias:'FLOAT64_ADD'];compilerproc;{$endif}
  4818. Var
  4819. aSign, bSign: flag;
  4820. Begin
  4821. aSign := extractFloat64Sign( a );
  4822. bSign := extractFloat64Sign( b );
  4823. if ( aSign = bSign ) then
  4824. Begin
  4825. addFloat64Sigs( a, b, aSign, result );
  4826. End
  4827. else
  4828. Begin
  4829. subFloat64Sigs( a, b, aSign, result );
  4830. End;
  4831. End;
  4832. {*
  4833. -------------------------------------------------------------------------------
  4834. Returns the result of subtracting the double-precision floating-point values
  4835. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  4836. for Binary Floating-Point Arithmetic.
  4837. -------------------------------------------------------------------------------
  4838. *}
  4839. Function float64_sub(a: float64; b : float64) : Float64;
  4840. {$ifdef fpc}[public,Alias:'FLOAT64_SUB'];compilerproc;{$endif}
  4841. Var
  4842. aSign, bSign: flag;
  4843. Begin
  4844. aSign := extractFloat64Sign( a );
  4845. bSign := extractFloat64Sign( b );
  4846. if ( aSign = bSign ) then
  4847. Begin
  4848. subFloat64Sigs( a, b, aSign, result );
  4849. End
  4850. else
  4851. Begin
  4852. addFloat64Sigs( a, b, aSign, result );
  4853. End;
  4854. End;
  4855. {*
  4856. -------------------------------------------------------------------------------
  4857. Returns the result of multiplying the double-precision floating-point values
  4858. `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  4859. for Binary Floating-Point Arithmetic.
  4860. -------------------------------------------------------------------------------
  4861. *}
  4862. Function float64_mul( a: float64; b:float64) : Float64;
  4863. {$ifdef fpc}[public,Alias:'FLOAT64_MUL'];compilerproc;{$endif}
  4864. Var
  4865. aSign, bSign, zSign: flag;
  4866. aExp, bExp, zExp: int16;
  4867. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits32;
  4868. z: float64;
  4869. label invalid;
  4870. Begin
  4871. aSig1 := extractFloat64Frac1( a );
  4872. aSig0 := extractFloat64Frac0( a );
  4873. aExp := extractFloat64Exp( a );
  4874. aSign := extractFloat64Sign( a );
  4875. bSig1 := extractFloat64Frac1( b );
  4876. bSig0 := extractFloat64Frac0( b );
  4877. bExp := extractFloat64Exp( b );
  4878. bSign := extractFloat64Sign( b );
  4879. zSign := aSign xor bSign;
  4880. if ( aExp = $7FF ) then
  4881. Begin
  4882. if ( (( aSig0 OR aSig1 ) <>0)
  4883. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  4884. Begin
  4885. propagateFloat64NaN( a, b, result );
  4886. exit;
  4887. End;
  4888. if ( ( bits32(bExp) OR bSig0 OR bSig1 ) = 0 ) then goto invalid;
  4889. packFloat64( zSign, $7FF, 0, 0, result );
  4890. exit;
  4891. End;
  4892. if ( bExp = $7FF ) then
  4893. Begin
  4894. if ( bSig0 OR bSig1 )<> 0 then
  4895. Begin
  4896. propagateFloat64NaN( a, b, result );
  4897. exit;
  4898. End;
  4899. if ( ( aExp OR aSig0 OR aSig1 ) = 0 ) then
  4900. Begin
  4901. invalid:
  4902. float_raise( float_flag_invalid );
  4903. z.low := float64_default_nan_low;
  4904. z.high := float64_default_nan_high;
  4905. result := z;
  4906. exit;
  4907. End;
  4908. packFloat64( zSign, $7FF, 0, 0, result );
  4909. exit;
  4910. End;
  4911. if ( aExp = 0 ) then
  4912. Begin
  4913. if ( ( aSig0 OR aSig1 ) = 0 ) then
  4914. Begin
  4915. packFloat64( zSign, 0, 0, 0, result );
  4916. exit;
  4917. End;
  4918. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  4919. End;
  4920. if ( bExp = 0 ) then
  4921. Begin
  4922. if ( ( bSig0 OR bSig1 ) = 0 ) then
  4923. Begin
  4924. packFloat64( zSign, 0, 0, 0, result );
  4925. exit;
  4926. End;
  4927. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  4928. End;
  4929. zExp := aExp + bExp - $400;
  4930. aSig0 := aSig0 or $00100000;
  4931. shortShift64Left( bSig0, bSig1, 12, bSig0, bSig1 );
  4932. mul64To128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
  4933. add64( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
  4934. zSig2 := zSig2 or flag( zSig3 <> 0 );
  4935. if ( $00200000 <= zSig0 ) then
  4936. Begin
  4937. shift64ExtraRightJamming(
  4938. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  4939. Inc(zExp);
  4940. End;
  4941. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
  4942. End;
  4943. {*
  4944. -------------------------------------------------------------------------------
  4945. Returns the result of dividing the double-precision floating-point value `a'
  4946. by the corresponding value `b'. The operation is performed according to the
  4947. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  4948. -------------------------------------------------------------------------------
  4949. *}
  4950. Function float64_div(a: float64; b : float64) : Float64;
  4951. {$ifdef fpc}[public,Alias:'FLOAT64_DIV'];compilerproc;{$endif}
  4952. Var
  4953. aSign, bSign, zSign: flag;
  4954. aExp, bExp, zExp: int16;
  4955. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
  4956. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  4957. z: float64;
  4958. label invalid;
  4959. Begin
  4960. aSig1 := extractFloat64Frac1( a );
  4961. aSig0 := extractFloat64Frac0( a );
  4962. aExp := extractFloat64Exp( a );
  4963. aSign := extractFloat64Sign( a );
  4964. bSig1 := extractFloat64Frac1( b );
  4965. bSig0 := extractFloat64Frac0( b );
  4966. bExp := extractFloat64Exp( b );
  4967. bSign := extractFloat64Sign( b );
  4968. zSign := aSign xor bSign;
  4969. if ( aExp = $7FF ) then
  4970. Begin
  4971. if ( aSig0 OR aSig1 )<> 0 then
  4972. Begin
  4973. propagateFloat64NaN( a, b, result );
  4974. exit;
  4975. end;
  4976. if ( bExp = $7FF ) then
  4977. Begin
  4978. if ( bSig0 OR bSig1 )<>0 then
  4979. Begin
  4980. propagateFloat64NaN( a, b, result );
  4981. exit;
  4982. End;
  4983. goto invalid;
  4984. End;
  4985. packFloat64( zSign, $7FF, 0, 0, result );
  4986. exit;
  4987. End;
  4988. if ( bExp = $7FF ) then
  4989. Begin
  4990. if ( bSig0 OR bSig1 )<> 0 then
  4991. Begin
  4992. propagateFloat64NaN( a, b, result );
  4993. exit;
  4994. End;
  4995. packFloat64( zSign, 0, 0, 0, result );
  4996. exit;
  4997. End;
  4998. if ( bExp = 0 ) then
  4999. Begin
  5000. if ( ( bSig0 OR bSig1 ) = 0 ) then
  5001. Begin
  5002. if ( ( bits32(aExp) OR aSig0 OR aSig1 ) = 0 ) then
  5003. Begin
  5004. invalid:
  5005. float_raise( float_flag_invalid );
  5006. z.low := float64_default_nan_low;
  5007. z.high := float64_default_nan_high;
  5008. result := z;
  5009. exit;
  5010. End;
  5011. float_raise( float_flag_divbyzero );
  5012. packFloat64( zSign, $7FF, 0, 0, result );
  5013. exit;
  5014. End;
  5015. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  5016. End;
  5017. if ( aExp = 0 ) then
  5018. Begin
  5019. if ( ( aSig0 OR aSig1 ) = 0 ) then
  5020. Begin
  5021. packFloat64( zSign, 0, 0, 0, result );
  5022. exit;
  5023. End;
  5024. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  5025. End;
  5026. zExp := aExp - bExp + $3FD;
  5027. shortShift64Left( aSig0 OR $00100000, aSig1, 11, aSig0, aSig1 );
  5028. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  5029. if ( le64( bSig0, bSig1, aSig0, aSig1 )<>0 ) then
  5030. Begin
  5031. shift64Right( aSig0, aSig1, 1, aSig0, aSig1 );
  5032. Inc(zExp);
  5033. End;
  5034. zSig0 := estimateDiv64To32( aSig0, aSig1, bSig0 );
  5035. mul64By32To96( bSig0, bSig1, zSig0, term0, term1, term2 );
  5036. sub96( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
  5037. while ( sbits32 (rem0) < 0 ) do
  5038. Begin
  5039. Dec(zSig0);
  5040. add96( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
  5041. End;
  5042. zSig1 := estimateDiv64To32( rem1, rem2, bSig0 );
  5043. if ( ( zSig1 and $3FF ) <= 4 ) then
  5044. Begin
  5045. mul64By32To96( bSig0, bSig1, zSig1, term1, term2, term3 );
  5046. sub96( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
  5047. while ( sbits32 (rem1) < 0 ) do
  5048. Begin
  5049. Dec(zSig1);
  5050. add96( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
  5051. End;
  5052. zSig1 := zSig1 or flag( ( rem1 OR rem2 OR rem3 ) <> 0 );
  5053. End;
  5054. shift64ExtraRightJamming( zSig0, zSig1, 0, 11, zSig0, zSig1, zSig2 );
  5055. roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
  5056. End;
  5057. {*
  5058. -------------------------------------------------------------------------------
  5059. Returns the remainder of the double-precision floating-point value `a'
  5060. with respect to the corresponding value `b'. The operation is performed
  5061. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5062. -------------------------------------------------------------------------------
  5063. *}
  5064. Function float64_rem(a: float64; b : float64) : float64;
  5065. {$ifdef fpc}[public,Alias:'FLOAT64_REM'];compilerproc;{$endif}
  5066. Var
  5067. aSign, zSign: flag;
  5068. aExp, bExp, expDiff: int16;
  5069. aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits32;
  5070. allZero, alternateASig0, alternateASig1, sigMean1: bits32;
  5071. sigMean0: sbits32;
  5072. z: float64;
  5073. label invalid;
  5074. Begin
  5075. aSig1 := extractFloat64Frac1( a );
  5076. aSig0 := extractFloat64Frac0( a );
  5077. aExp := extractFloat64Exp( a );
  5078. aSign := extractFloat64Sign( a );
  5079. bSig1 := extractFloat64Frac1( b );
  5080. bSig0 := extractFloat64Frac0( b );
  5081. bExp := extractFloat64Exp( b );
  5082. if ( aExp = $7FF ) then
  5083. Begin
  5084. if ((( aSig0 OR aSig1 )<>0)
  5085. OR ( ( bExp = $7FF ) AND (( bSig0 OR bSig1 )<>0) ) ) then
  5086. Begin
  5087. propagateFloat64NaN( a, b, result );
  5088. exit;
  5089. End;
  5090. goto invalid;
  5091. End;
  5092. if ( bExp = $7FF ) then
  5093. Begin
  5094. if ( bSig0 OR bSig1 ) <> 0 then
  5095. Begin
  5096. propagateFloat64NaN( a, b, result );
  5097. exit;
  5098. End;
  5099. result := a;
  5100. exit;
  5101. End;
  5102. if ( bExp = 0 ) then
  5103. Begin
  5104. if ( ( bSig0 OR bSig1 ) = 0 ) then
  5105. Begin
  5106. invalid:
  5107. float_raise( float_flag_invalid );
  5108. z.low := float64_default_nan_low;
  5109. z.high := float64_default_nan_high;
  5110. result := z;
  5111. exit;
  5112. End;
  5113. normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  5114. End;
  5115. if ( aExp = 0 ) then
  5116. Begin
  5117. if ( ( aSig0 OR aSig1 ) = 0 ) then
  5118. Begin
  5119. result := a;
  5120. exit;
  5121. End;
  5122. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  5123. End;
  5124. expDiff := aExp - bExp;
  5125. if ( expDiff < -1 ) then
  5126. Begin
  5127. result := a;
  5128. exit;
  5129. End;
  5130. shortShift64Left(
  5131. aSig0 OR $00100000, aSig1, 11 - flag( expDiff < 0 ), aSig0, aSig1 );
  5132. shortShift64Left( bSig0 OR $00100000, bSig1, 11, bSig0, bSig1 );
  5133. q := le64( bSig0, bSig1, aSig0, aSig1 );
  5134. if ( q )<>0 then
  5135. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  5136. expDiff := expDiff - 32;
  5137. while ( 0 < expDiff ) do
  5138. Begin
  5139. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  5140. if 4 < q then
  5141. q:= q - 4
  5142. else
  5143. q := 0;
  5144. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  5145. shortShift96Left( term0, term1, term2, 29, term1, term2, allZero );
  5146. shortShift64Left( aSig0, aSig1, 29, aSig0, allZero );
  5147. sub64( aSig0, 0, term1, term2, aSig0, aSig1 );
  5148. expDiff := expDiff - 29;
  5149. End;
  5150. if ( -32 < expDiff ) then
  5151. Begin
  5152. q := estimateDiv64To32( aSig0, aSig1, bSig0 );
  5153. if 4 < q then
  5154. q := q - 4
  5155. else
  5156. q := 0;
  5157. q := q shr (- expDiff);
  5158. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  5159. expDiff := expDiff + 24;
  5160. if ( expDiff < 0 ) then
  5161. Begin
  5162. shift64Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  5163. End
  5164. else
  5165. Begin
  5166. shortShift64Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
  5167. End;
  5168. mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
  5169. sub64( aSig0, aSig1, term1, term2, aSig0, aSig1 );
  5170. End
  5171. else
  5172. Begin
  5173. shift64Right( aSig0, aSig1, 8, aSig0, aSig1 );
  5174. shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
  5175. End;
  5176. Repeat
  5177. alternateASig0 := aSig0;
  5178. alternateASig1 := aSig1;
  5179. Inc(q);
  5180. sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  5181. Until not ( 0 <= sbits32 (aSig0) );
  5182. add64(
  5183. aSig0, aSig1, alternateASig0, alternateASig1, bits32(sigMean0), sigMean1 );
  5184. if ( ( sigMean0 < 0 )
  5185. OR ( ( ( sigMean0 OR sigMean1 ) = 0 ) AND (( q AND 1 )<>0) ) ) then
  5186. Begin
  5187. aSig0 := alternateASig0;
  5188. aSig1 := alternateASig1;
  5189. End;
  5190. zSign := flag( sbits32 (aSig0) < 0 );
  5191. if ( zSign <> 0 ) then
  5192. sub64( 0, 0, aSig0, aSig1, aSig0, aSig1 );
  5193. normalizeRoundAndPackFloat64( aSign xor zSign, bExp - 4, aSig0, aSig1, result );
  5194. End;
  5195. {*
  5196. -------------------------------------------------------------------------------
  5197. Returns the square root of the double-precision floating-point value `a'.
  5198. The operation is performed according to the IEC/IEEE Standard for Binary
  5199. Floating-Point Arithmetic.
  5200. -------------------------------------------------------------------------------
  5201. *}
  5202. function float64_sqrt( a: float64 ): float64;
  5203. {$ifdef fpc}[public,Alias:'FLOAT64_SQRT'];compilerproc;{$endif}
  5204. Var
  5205. aSign: flag;
  5206. aExp, zExp: int16;
  5207. aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits32;
  5208. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
  5209. label invalid;
  5210. Begin
  5211. aSig1 := extractFloat64Frac1( a );
  5212. aSig0 := extractFloat64Frac0( a );
  5213. aExp := extractFloat64Exp( a );
  5214. aSign := extractFloat64Sign( a );
  5215. if ( aExp = $7FF ) then
  5216. Begin
  5217. if ( aSig0 OR aSig1 ) <> 0 then
  5218. Begin
  5219. propagateFloat64NaN( a, a, result );
  5220. exit;
  5221. End;
  5222. if ( aSign = 0) then
  5223. Begin
  5224. result := a;
  5225. exit;
  5226. End;
  5227. goto invalid;
  5228. End;
  5229. if ( aSign <> 0 ) then
  5230. Begin
  5231. if ( ( bits32(aExp) OR aSig0 OR aSig1 ) = 0 ) then
  5232. Begin
  5233. result := a;
  5234. exit;
  5235. End;
  5236. invalid:
  5237. float_raise( float_flag_invalid );
  5238. result.low := float64_default_nan_low;
  5239. result.high := float64_default_nan_high;
  5240. exit;
  5241. End;
  5242. if ( aExp = 0 ) then
  5243. Begin
  5244. if ( ( aSig0 OR aSig1 ) = 0 ) then
  5245. Begin
  5246. packFloat64( 0, 0, 0, 0, result );
  5247. exit;
  5248. End;
  5249. normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  5250. End;
  5251. zExp := ( ( aExp - $3FF ) shr 1 ) + $3FE;
  5252. aSig0 := aSig0 or $00100000;
  5253. shortShift64Left( aSig0, aSig1, 11, term0, term1 );
  5254. zSig0 := ( estimateSqrt32( aExp, term0 ) shr 1 ) + 1;
  5255. if ( zSig0 = 0 ) then
  5256. zSig0 := $7FFFFFFF;
  5257. doubleZSig0 := zSig0 + zSig0;
  5258. shortShift64Left( aSig0, aSig1, 9 - ( aExp and 1 ), aSig0, aSig1 );
  5259. mul32To64( zSig0, zSig0, term0, term1 );
  5260. sub64( aSig0, aSig1, term0, term1, rem0, rem1 );
  5261. while ( sbits32 (rem0) < 0 ) do
  5262. Begin
  5263. Dec(zSig0);
  5264. doubleZSig0 := doubleZSig0 - 2;
  5265. add64( rem0, rem1, 0, doubleZSig0 OR 1, rem0, rem1 );
  5266. End;
  5267. zSig1 := estimateDiv64To32( rem1, 0, doubleZSig0 );
  5268. if ( ( zSig1 and $1FF ) <= 5 ) then
  5269. Begin
  5270. if ( zSig1 = 0 ) then
  5271. zSig1 := 1;
  5272. mul32To64( doubleZSig0, zSig1, term1, term2 );
  5273. sub64( rem1, 0, term1, term2, rem1, rem2 );
  5274. mul32To64( zSig1, zSig1, term2, term3 );
  5275. sub96( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  5276. while ( sbits32 (rem1) < 0 ) do
  5277. Begin
  5278. Dec(zSig1);
  5279. shortShift64Left( 0, zSig1, 1, term2, term3 );
  5280. term3 := term3 or 1;
  5281. term2 := term2 or doubleZSig0;
  5282. add96( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  5283. End;
  5284. zSig1 := zSig1 or bits32( ( rem1 OR rem2 OR rem3 ) <> 0 );
  5285. End;
  5286. shift64ExtraRightJamming( zSig0, zSig1, 0, 10, zSig0, zSig1, zSig2 );
  5287. roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2, result );
  5288. End;
  5289. {*
  5290. -------------------------------------------------------------------------------
  5291. Returns 1 if the double-precision floating-point value `a' is equal to
  5292. the corresponding value `b', and 0 otherwise. The comparison is performed
  5293. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5294. -------------------------------------------------------------------------------
  5295. *}
  5296. Function float64_eq(a: float64; b: float64): flag;
  5297. {$ifdef fpc}[public,Alias:'FLOAT64_EQ'];compilerproc;{$endif}
  5298. Begin
  5299. if
  5300. (
  5301. ( extractFloat64Exp( a ) = $7FF )
  5302. AND
  5303. (
  5304. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5305. )
  5306. )
  5307. OR (
  5308. ( extractFloat64Exp( b ) = $7FF )
  5309. AND (
  5310. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5311. )
  5312. )
  5313. ) then
  5314. Begin
  5315. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  5316. float_raise( float_flag_invalid );
  5317. float64_eq := 0;
  5318. exit;
  5319. End;
  5320. float64_eq := flag(
  5321. ( a.low = b.low )
  5322. AND ( ( a.high = b.high )
  5323. OR ( ( a.low = 0 )
  5324. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  5325. ));
  5326. End;
  5327. {*
  5328. -------------------------------------------------------------------------------
  5329. Returns 1 if the double-precision floating-point value `a' is less than
  5330. or equal to the corresponding value `b', and 0 otherwise. The comparison
  5331. is performed according to the IEC/IEEE Standard for Binary Floating-Point
  5332. Arithmetic.
  5333. -------------------------------------------------------------------------------
  5334. *}
  5335. Function float64_le(a: float64;b: float64): flag;
  5336. {$ifdef fpc}[public,Alias:'FLOAT64_LE'];compilerproc;{$endif}
  5337. Var
  5338. aSign, bSign: flag;
  5339. Begin
  5340. if
  5341. (
  5342. ( extractFloat64Exp( a ) = $7FF )
  5343. AND
  5344. (
  5345. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5346. )
  5347. )
  5348. OR (
  5349. ( extractFloat64Exp( b ) = $7FF )
  5350. AND (
  5351. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5352. )
  5353. )
  5354. ) then
  5355. Begin
  5356. float_raise( float_flag_invalid );
  5357. float64_le := 0;
  5358. exit;
  5359. End;
  5360. aSign := extractFloat64Sign( a );
  5361. bSign := extractFloat64Sign( b );
  5362. if ( aSign <> bSign ) then
  5363. Begin
  5364. float64_le := flag(
  5365. (aSign <> 0)
  5366. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5367. = 0 ));
  5368. exit;
  5369. End;
  5370. if aSign <> 0 then
  5371. float64_le := le64( b.high, b.low, a.high, a.low )
  5372. else
  5373. float64_le := le64( a.high, a.low, b.high, b.low );
  5374. End;
  5375. {*
  5376. -------------------------------------------------------------------------------
  5377. Returns 1 if the double-precision floating-point value `a' is less than
  5378. the corresponding value `b', and 0 otherwise. The comparison is performed
  5379. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5380. -------------------------------------------------------------------------------
  5381. *}
  5382. Function float64_lt(a: float64;b: float64): flag;
  5383. {$ifdef fpc}[public,Alias:'FLOAT64_LT'];compilerproc;{$endif}
  5384. Var
  5385. aSign, bSign: flag;
  5386. Begin
  5387. if
  5388. (
  5389. ( extractFloat64Exp( a ) = $7FF )
  5390. AND
  5391. (
  5392. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5393. )
  5394. )
  5395. OR (
  5396. ( extractFloat64Exp( b ) = $7FF )
  5397. AND (
  5398. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5399. )
  5400. )
  5401. ) then
  5402. Begin
  5403. float_raise( float_flag_invalid );
  5404. float64_lt := 0;
  5405. exit;
  5406. End;
  5407. aSign := extractFloat64Sign( a );
  5408. bSign := extractFloat64Sign( b );
  5409. if ( aSign <> bSign ) then
  5410. Begin
  5411. float64_lt := flag(
  5412. (aSign <> 0)
  5413. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5414. <> 0 ));
  5415. exit;
  5416. End;
  5417. if aSign <> 0 then
  5418. float64_lt := lt64( b.high, b.low, a.high, a.low )
  5419. else
  5420. float64_lt := lt64( a.high, a.low, b.high, b.low );
  5421. End;
  5422. {*
  5423. -------------------------------------------------------------------------------
  5424. Returns 1 if the double-precision floating-point value `a' is equal to
  5425. the corresponding value `b', and 0 otherwise. The invalid exception is
  5426. raised if either operand is a NaN. Otherwise, the comparison is performed
  5427. according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5428. -------------------------------------------------------------------------------
  5429. *}
  5430. Function float64_eq_signaling( a: float64; b: float64): flag;
  5431. Begin
  5432. if
  5433. (
  5434. ( extractFloat64Exp( a ) = $7FF )
  5435. AND
  5436. (
  5437. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5438. )
  5439. )
  5440. OR (
  5441. ( extractFloat64Exp( b ) = $7FF )
  5442. AND (
  5443. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5444. )
  5445. )
  5446. ) then
  5447. Begin
  5448. float_raise( float_flag_invalid );
  5449. float64_eq_signaling := 0;
  5450. exit;
  5451. End;
  5452. float64_eq_signaling := flag(
  5453. ( a.low = b.low )
  5454. AND ( ( a.high = b.high )
  5455. OR ( ( a.low = 0 )
  5456. AND ( bits32 ( ( a.high OR b.high ) shl 1 ) = 0 ) )
  5457. ));
  5458. End;
  5459. {*
  5460. -------------------------------------------------------------------------------
  5461. Returns 1 if the double-precision floating-point value `a' is less than or
  5462. equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  5463. cause an exception. Otherwise, the comparison is performed according to the
  5464. IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5465. -------------------------------------------------------------------------------
  5466. *}
  5467. Function float64_le_quiet(a: float64 ; b: float64 ): flag;
  5468. Var
  5469. aSign, bSign : flag;
  5470. Begin
  5471. if
  5472. (
  5473. ( extractFloat64Exp( a ) = $7FF )
  5474. AND
  5475. (
  5476. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5477. )
  5478. )
  5479. OR (
  5480. ( extractFloat64Exp( b ) = $7FF )
  5481. AND (
  5482. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5483. )
  5484. )
  5485. ) then
  5486. Begin
  5487. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  5488. float_raise( float_flag_invalid );
  5489. float64_le_quiet := 0;
  5490. exit;
  5491. End;
  5492. aSign := extractFloat64Sign( a );
  5493. bSign := extractFloat64Sign( b );
  5494. if ( aSign <> bSign ) then
  5495. Begin
  5496. float64_le_quiet := flag
  5497. ((aSign <> 0)
  5498. OR ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5499. = 0 ));
  5500. exit;
  5501. End;
  5502. if aSign <> 0 then
  5503. float64_le_quiet := le64( b.high, b.low, a.high, a.low )
  5504. else
  5505. float64_le_quiet := le64( a.high, a.low, b.high, b.low );
  5506. End;
  5507. {*
  5508. -------------------------------------------------------------------------------
  5509. Returns 1 if the double-precision floating-point value `a' is less than
  5510. the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  5511. exception. Otherwise, the comparison is performed according to the IEC/IEEE
  5512. Standard for Binary Floating-Point Arithmetic.
  5513. -------------------------------------------------------------------------------
  5514. *}
  5515. Function float64_lt_quiet(a: float64; b: float64 ): Flag;
  5516. Var
  5517. aSign, bSign: flag;
  5518. Begin
  5519. if
  5520. (
  5521. ( extractFloat64Exp( a ) = $7FF )
  5522. AND
  5523. (
  5524. (extractFloat64Frac0( a ) OR extractFloat64Frac1( a )) <>0
  5525. )
  5526. )
  5527. OR (
  5528. ( extractFloat64Exp( b ) = $7FF )
  5529. AND (
  5530. (extractFloat64Frac0( b ) OR (extractFloat64Frac1( b )) <> 0
  5531. )
  5532. )
  5533. ) then
  5534. Begin
  5535. if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
  5536. float_raise( float_flag_invalid );
  5537. float64_lt_quiet := 0;
  5538. exit;
  5539. End;
  5540. aSign := extractFloat64Sign( a );
  5541. bSign := extractFloat64Sign( b );
  5542. if ( aSign <> bSign ) then
  5543. Begin
  5544. float64_lt_quiet := flag(
  5545. (aSign<>0)
  5546. AND ( ( ( bits32 ( ( a.high OR b.high ) shl 1 ) ) OR a.low OR b.low )
  5547. <> 0 ));
  5548. exit;
  5549. End;
  5550. If aSign <> 0 then
  5551. float64_lt_quiet := lt64( b.high, b.low, a.high, a.low )
  5552. else
  5553. float64_lt_quiet := lt64( a.high, a.low, b.high, b.low );
  5554. End;
  5555. {*----------------------------------------------------------------------------
  5556. | Returns the result of converting the 64-bit two's complement integer `a'
  5557. | to the single-precision floating-point format. The conversion is performed
  5558. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5559. *----------------------------------------------------------------------------*}
  5560. function int64_to_float32( a: int64 ): float32rec; compilerproc;
  5561. var
  5562. zSign : flag;
  5563. absA : uint64;
  5564. shiftCount: int8;
  5565. Begin
  5566. if ( a = 0 ) then
  5567. begin
  5568. int64_to_float32.float32 := 0;
  5569. exit;
  5570. end;
  5571. if a < 0 then
  5572. zSign := flag(TRUE)
  5573. else
  5574. zSign := flag(FALSE);
  5575. if zSign<>0 then
  5576. absA := -a
  5577. else
  5578. absA := a;
  5579. shiftCount := countLeadingZeros64( absA ) - 40;
  5580. if ( 0 <= shiftCount ) then
  5581. begin
  5582. int64_to_float32.float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount );
  5583. end
  5584. else
  5585. begin
  5586. shiftCount := shiftCount + 7;
  5587. if ( shiftCount < 0 ) then
  5588. shift64RightJamming( absA, - shiftCount, absA )
  5589. else
  5590. absA := absA shl shiftCount;
  5591. int64_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA );
  5592. end;
  5593. End;
  5594. {*----------------------------------------------------------------------------
  5595. | Returns the result of converting the 64-bit two's complement integer `a'
  5596. | to the single-precision floating-point format. The conversion is performed
  5597. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5598. | Unisgned version.
  5599. *----------------------------------------------------------------------------*}
  5600. function qword_to_float32( a: qword ): float32rec; compilerproc;
  5601. var
  5602. absA : uint64;
  5603. shiftCount: int8;
  5604. Begin
  5605. if ( a = 0 ) then
  5606. begin
  5607. qword_to_float32.float32 := 0;
  5608. exit;
  5609. end;
  5610. absA := a;
  5611. shiftCount := countLeadingZeros64( absA ) - 40;
  5612. if ( 0 <= shiftCount ) then
  5613. begin
  5614. qword_to_float32.float32:= packFloat32( 0, $95 - shiftCount, absA shl shiftCount );
  5615. end
  5616. else
  5617. begin
  5618. shiftCount := shiftCount + 7;
  5619. if ( shiftCount < 0 ) then
  5620. shift64RightJamming( absA, - shiftCount, absA )
  5621. else
  5622. absA := absA shl shiftCount;
  5623. qword_to_float32.float32:=roundAndPackFloat32( 0, $9C - shiftCount, absA );
  5624. end;
  5625. End;
  5626. {*----------------------------------------------------------------------------
  5627. | Returns the result of converting the 64-bit two's complement integer `a'
  5628. | to the double-precision floating-point format. The conversion is performed
  5629. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5630. *----------------------------------------------------------------------------*}
  5631. function qword_to_float64( a: qword ): float64;
  5632. {$ifdef fpc}[public,Alias:'QWORD_TO_FLOAT64'];compilerproc;{$endif}
  5633. var
  5634. shiftCount: int8;
  5635. Begin
  5636. if ( a = 0 ) then
  5637. result := packFloat64( 0, 0, 0 )
  5638. else
  5639. begin
  5640. shiftCount := countLeadingZeros64(a) - 1;
  5641. { numbers with <= 53 significant bits are converted exactly }
  5642. if (shiftCount > 9) then
  5643. result := packFloat64(0, $43c - shiftCount, a shl (shiftCount-10))
  5644. else if (shiftCount>=0) then
  5645. result := roundAndPackFloat64( 0, $43c - shiftCount, a shl shiftCount)
  5646. else
  5647. begin
  5648. { the only possible negative value is -1, in case bit 63 of 'a' is set }
  5649. shift64RightJamming(a, 1, a);
  5650. result := roundAndPackFloat64(0, $43d, a);
  5651. end;
  5652. end;
  5653. End;
  5654. {*----------------------------------------------------------------------------
  5655. | Returns the result of converting the 64-bit two's complement integer `a'
  5656. | to the double-precision floating-point format. The conversion is performed
  5657. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5658. *----------------------------------------------------------------------------*}
  5659. function int64_to_float64( a: int64 ): float64;
  5660. {$ifdef fpc}[public,Alias:'INT64_TO_FLOAT64'];compilerproc;{$endif}
  5661. Begin
  5662. if ( a = 0 ) then
  5663. result := packFloat64( 0, 0, 0 )
  5664. else if (a = int64($8000000000000000)) then
  5665. result := packFloat64( 1, $43e, 0 )
  5666. else if (a < 0) then
  5667. result := normalizeRoundAndPackFloat64( 1, $43c, -a )
  5668. else
  5669. result := normalizeRoundAndPackFloat64( 0, $43c, a );
  5670. End;
  5671. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  5672. {*----------------------------------------------------------------------------
  5673. | Returns the result of converting the 64-bit two's complement integer `a'
  5674. | to the extended double-precision floating-point format. The conversion
  5675. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  5676. | Arithmetic.
  5677. *----------------------------------------------------------------------------*}
  5678. function int64_to_floatx80( a: int64 ): floatx80;
  5679. var
  5680. zSign: flag;
  5681. absA: uint64;
  5682. shiftCount: int8;
  5683. begin
  5684. if ( a = 0 ) then begin
  5685. result := packFloatx80( 0, 0, 0 );
  5686. exit;
  5687. end;
  5688. zSign := ord( a < 0 );
  5689. if zSign <> 0 then absA := - a else absA := a;
  5690. shiftCount := countLeadingZeros64( absA );
  5691. result := packFloatx80( zSign, $403E - shiftCount, absA shl shiftCount );
  5692. end;
  5693. {*----------------------------------------------------------------------------
  5694. | Returns the result of converting the 64-bit two's complement integer `a'
  5695. | to the extended double-precision floating-point format. The conversion
  5696. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  5697. | Arithmetic.
  5698. | Unsigned version.
  5699. *----------------------------------------------------------------------------*}
  5700. function qword_to_floatx80( a: qword ): floatx80;
  5701. var
  5702. absA: bits64;
  5703. shiftCount: int8;
  5704. begin
  5705. if ( a = 0 ) then begin
  5706. result := packFloatx80( 0, 0, 0 );
  5707. exit;
  5708. end;
  5709. absA := a;
  5710. shiftCount := countLeadingZeros64( absA );
  5711. result := packFloatx80( 0, $403E - shiftCount, absA shl shiftCount );
  5712. end;
  5713. {$endif FPC_SOFTFLOAT_FLOATX80}
  5714. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  5715. {*----------------------------------------------------------------------------
  5716. | Returns the result of converting the 64-bit two's complement integer `a' to
  5717. | the quadruple-precision floating-point format. The conversion is performed
  5718. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5719. *----------------------------------------------------------------------------*}
  5720. function int64_to_float128( a: int64 ): float128;
  5721. var
  5722. zSign: flag;
  5723. absA: uint64;
  5724. shiftCount: int8;
  5725. zExp: int32;
  5726. zSig0, zSig1: bits64;
  5727. begin
  5728. if ( a = 0 ) then begin
  5729. result := packFloat128( 0, 0, 0, 0 );
  5730. exit;
  5731. end;
  5732. zSign := ord( a < 0 );
  5733. if zSign <> 0 then absA := - a else absA := a;
  5734. shiftCount := countLeadingZeros64( absA ) + 49;
  5735. zExp := $406E - shiftCount;
  5736. if ( 64 <= shiftCount ) then begin
  5737. zSig1 := 0;
  5738. zSig0 := absA;
  5739. dec( shiftCount, 64 );
  5740. end
  5741. else begin
  5742. zSig1 := absA;
  5743. zSig0 := 0;
  5744. end;
  5745. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  5746. result := packFloat128( zSign, zExp, zSig0, zSig1 );
  5747. end;
  5748. {*----------------------------------------------------------------------------
  5749. | Returns the result of converting the 64-bit two's complement integer `a' to
  5750. | the quadruple-precision floating-point format. The conversion is performed
  5751. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  5752. | Unsigned version.
  5753. *----------------------------------------------------------------------------*}
  5754. function qword_to_float128( a: qword ): float128;
  5755. var
  5756. absA: bits64;
  5757. shiftCount: int8;
  5758. zExp: int32;
  5759. zSig0, zSig1: bits64;
  5760. begin
  5761. if ( a = 0 ) then begin
  5762. result := packFloat128( 0, 0, 0, 0 );
  5763. exit;
  5764. end;
  5765. absA := a;
  5766. shiftCount := countLeadingZeros64( absA ) + 49;
  5767. zExp := $406E - shiftCount;
  5768. if ( 64 <= shiftCount ) then begin
  5769. zSig1 := 0;
  5770. zSig0 := absA;
  5771. dec( shiftCount, 64 );
  5772. end
  5773. else begin
  5774. zSig1 := absA;
  5775. zSig0 := 0;
  5776. end;
  5777. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  5778. result := packFloat128( 0, zExp, zSig0, zSig1 );
  5779. end;
  5780. {$endif FPC_SOFTFLOAT_FLOAT128}
  5781. {*----------------------------------------------------------------------------
  5782. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
  5783. | is equal to the 128-bit value formed by concatenating `b0' and `b1'.
  5784. | Otherwise, returns 0.
  5785. *----------------------------------------------------------------------------*}
  5786. function eq128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  5787. begin
  5788. result := ord(( a0 = b0 ) and ( a1 = b1 ));
  5789. end;
  5790. {*----------------------------------------------------------------------------
  5791. | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  5792. | than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
  5793. | Otherwise, returns 0.
  5794. *----------------------------------------------------------------------------*}
  5795. function le128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
  5796. begin
  5797. result:=ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 <= b1 ) ));
  5798. end;
  5799. {*----------------------------------------------------------------------------
  5800. | Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
  5801. | by 64 _plus_ the number of bits given in `count'. The shifted result is
  5802. | at most 128 nonzero bits; these are broken into two 64-bit pieces which are
  5803. | stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  5804. | off form a third 64-bit result as follows: The _last_ bit shifted off is
  5805. | the most-significant bit of the extra result, and the other 63 bits of the
  5806. | extra result are all zero if and only if _all_but_the_last_ bits shifted off
  5807. | were all zero. This extra result is stored in the location pointed to by
  5808. | `z2Ptr'. The value of `count' can be arbitrarily large.
  5809. | (This routine makes more sense if `a0', `a1', and `a2' are considered
  5810. | to form a fixed-point value with binary point between `a1' and `a2'. This
  5811. | fixed-point value is shifted right by the number of bits given in `count',
  5812. | and the integer part of the result is returned at the locations pointed to
  5813. | by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  5814. | corrupted as described above, and is returned at the location pointed to by
  5815. | `z2Ptr'.)
  5816. *----------------------------------------------------------------------------*}
  5817. procedure shift128ExtraRightJamming(
  5818. a0: bits64;
  5819. a1: bits64;
  5820. a2: bits64;
  5821. count: int16;
  5822. var z0Ptr: bits64;
  5823. var z1Ptr: bits64;
  5824. var z2Ptr: bits64);
  5825. var
  5826. z0, z1, z2: bits64;
  5827. negCount: int8;
  5828. begin
  5829. negCount := ( - count ) and 63;
  5830. if ( count = 0 ) then
  5831. begin
  5832. z2 := a2;
  5833. z1 := a1;
  5834. z0 := a0;
  5835. end
  5836. else begin
  5837. if ( count < 64 ) then
  5838. begin
  5839. z2 := a1 shl negCount;
  5840. z1 := ( a0 shl negCount ) or ( a1 shr count );
  5841. z0 := a0 shr count;
  5842. end
  5843. else begin
  5844. if ( count = 64 ) then
  5845. begin
  5846. z2 := a1;
  5847. z1 := a0;
  5848. end
  5849. else begin
  5850. a2 := a2 or a1;
  5851. if ( count < 128 ) then
  5852. begin
  5853. z2 := a0 shl negCount;
  5854. z1 := a0 shr ( count and 63 );
  5855. end
  5856. else begin
  5857. if ( count = 128 ) then
  5858. z2 := a0
  5859. else
  5860. z2 := ord( a0 <> 0 );
  5861. z1 := 0;
  5862. end;
  5863. end;
  5864. z0 := 0;
  5865. end;
  5866. z2 := z2 or ord( a2 <> 0 );
  5867. end;
  5868. z2Ptr := z2;
  5869. z1Ptr := z1;
  5870. z0Ptr := z0;
  5871. end;
  5872. {*----------------------------------------------------------------------------
  5873. | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
  5874. | _plus_ the number of bits given in `count'. The shifted result is at most
  5875. | 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
  5876. | bits shifted off form a second 64-bit result as follows: The _last_ bit
  5877. | shifted off is the most-significant bit of the extra result, and the other
  5878. | 63 bits of the extra result are all zero if and only if _all_but_the_last_
  5879. | bits shifted off were all zero. This extra result is stored in the location
  5880. | pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
  5881. | (This routine makes more sense if `a0' and `a1' are considered to form
  5882. | a fixed-point value with binary point between `a0' and `a1'. This fixed-
  5883. | point value is shifted right by the number of bits given in `count', and
  5884. | the integer part of the result is returned at the location pointed to by
  5885. | `z0Ptr'. The fractional part of the result may be slightly corrupted as
  5886. | described above, and is returned at the location pointed to by `z1Ptr'.)
  5887. *----------------------------------------------------------------------------*}
  5888. procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
  5889. var
  5890. z0, z1: bits64;
  5891. negCount: int8;
  5892. begin
  5893. negCount := ( - count ) and 63;
  5894. if ( count = 0 ) then
  5895. begin
  5896. z1 := a1;
  5897. z0 := a0;
  5898. end
  5899. else if ( count < 64 ) then
  5900. begin
  5901. z1 := ( a0 shl negCount ) or ord( a1 <> 0 );
  5902. z0 := a0 shr count;
  5903. end
  5904. else begin
  5905. if ( count = 64 ) then
  5906. begin
  5907. z1 := a0 or ord( a1 <> 0 );
  5908. end
  5909. else begin
  5910. z1 := ord( ( a0 or a1 ) <> 0 );
  5911. end;
  5912. z0 := 0;
  5913. end;
  5914. z1Ptr := z1;
  5915. z0Ptr := z0;
  5916. end;
  5917. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  5918. {*----------------------------------------------------------------------------
  5919. | Returns the fraction bits of the extended double-precision floating-point
  5920. | value `a'.
  5921. *----------------------------------------------------------------------------*}
  5922. function extractFloatx80Frac(a : floatx80): bits64;inline;
  5923. begin
  5924. result:=a.low;
  5925. end;
  5926. {*----------------------------------------------------------------------------
  5927. | Returns the exponent bits of the extended double-precision floating-point
  5928. | value `a'.
  5929. *----------------------------------------------------------------------------*}
  5930. function extractFloatx80Exp(a : floatx80): int32;inline;
  5931. begin
  5932. result:=a.high and $7FFF;
  5933. end;
  5934. {*----------------------------------------------------------------------------
  5935. | Returns the sign bit of the extended double-precision floating-point value
  5936. | `a'.
  5937. *----------------------------------------------------------------------------*}
  5938. function extractFloatx80Sign(a : floatx80): flag;inline;
  5939. begin
  5940. result:=a.high shr 15;
  5941. end;
  5942. {*----------------------------------------------------------------------------
  5943. | Normalizes the subnormal extended double-precision floating-point value
  5944. | represented by the denormalized significand `aSig'. The normalized exponent
  5945. | and significand are stored at the locations pointed to by `zExpPtr' and
  5946. | `zSigPtr', respectively.
  5947. *----------------------------------------------------------------------------*}
  5948. procedure normalizeFloatx80Subnormal( aSig: bits64; var zExpPtr: int32; var zSigPtr : bits64);
  5949. var
  5950. shiftCount: int8;
  5951. begin
  5952. shiftCount := countLeadingZeros64( aSig );
  5953. zSigPtr := aSig shl shiftCount;
  5954. zExpPtr := 1 - shiftCount;
  5955. end;
  5956. {*----------------------------------------------------------------------------
  5957. | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
  5958. | extended double-precision floating-point value, returning the result.
  5959. *----------------------------------------------------------------------------*}
  5960. function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;
  5961. var
  5962. z: floatx80;
  5963. begin
  5964. z.low := zSig;
  5965. z.high := ( bits16(zSign) shl 15 ) + zExp;
  5966. result:=z;
  5967. end;
  5968. {*----------------------------------------------------------------------------
  5969. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  5970. | and extended significand formed by the concatenation of `zSig0' and `zSig1',
  5971. | and returns the proper extended double-precision floating-point value
  5972. | corresponding to the abstract input. Ordinarily, the abstract value is
  5973. | rounded and packed into the extended double-precision format, with the
  5974. | inexact exception raised if the abstract input cannot be represented
  5975. | exactly. However, if the abstract value is too large, the overflow and
  5976. | inexact exceptions are raised and an infinity or maximal finite value is
  5977. | returned. If the abstract value is too small, the input value is rounded to
  5978. | a subnormal number, and the underflow and inexact exceptions are raised if
  5979. | the abstract input cannot be represented exactly as a subnormal extended
  5980. | double-precision floating-point number.
  5981. | If `roundingPrecision' is 32 or 64, the result is rounded to the same
  5982. | number of bits as single or double precision, respectively. Otherwise, the
  5983. | result is rounded to the full precision of the extended double-precision
  5984. | format.
  5985. | The input significand must be normalized or smaller. If the input
  5986. | significand is not normalized, `zExp' must be 0; in that case, the result
  5987. | returned is a subnormal number, and it must not require rounding. The
  5988. | handling of underflow and overflow follows the IEC/IEEE Standard for Binary
  5989. | Floating-Point Arithmetic.
  5990. *----------------------------------------------------------------------------*}
  5991. function roundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
  5992. var
  5993. roundingMode: TFPURoundingMode;
  5994. roundNearestEven, increment, isTiny: flag;
  5995. roundIncrement, roundMask, roundBits: int64;
  5996. label
  5997. precision80, overflow;
  5998. begin
  5999. roundingMode := softfloat_rounding_mode;
  6000. roundNearestEven := flag( roundingMode = float_round_nearest_even );
  6001. if ( roundingPrecision = 80 ) then
  6002. goto precision80;
  6003. if ( roundingPrecision = 64 ) then
  6004. begin
  6005. roundIncrement := int64( $0000000000000400 );
  6006. roundMask := int64( $00000000000007FF );
  6007. end
  6008. else if ( roundingPrecision = 32 ) then
  6009. begin
  6010. roundIncrement := int64( $0000008000000000 );
  6011. roundMask := int64( $000000FFFFFFFFFF );
  6012. end
  6013. else begin
  6014. goto precision80;
  6015. end;
  6016. zSig0 := zSig0 or ord( zSig1 <> 0 );
  6017. if ( not (roundNearestEven<>0) ) then
  6018. begin
  6019. if ( roundingMode = float_round_to_zero ) then
  6020. begin
  6021. roundIncrement := 0;
  6022. end
  6023. else begin
  6024. roundIncrement := roundMask;
  6025. if ( zSign<>0 ) then
  6026. begin
  6027. if ( roundingMode = float_round_up ) then
  6028. roundIncrement := 0;
  6029. end
  6030. else begin
  6031. if ( roundingMode = float_round_down ) then
  6032. roundIncrement := 0;
  6033. end;
  6034. end;
  6035. end;
  6036. roundBits := zSig0 and roundMask;
  6037. if ( $7FFD <= bits32( zExp - 1 ) ) then begin
  6038. if ( ( $7FFE < zExp )
  6039. or ( ( zExp = $7FFE ) and ( zSig0 + roundIncrement < zSig0 ) )
  6040. ) then begin
  6041. goto overflow;
  6042. end;
  6043. if ( zExp <= 0 ) then begin
  6044. isTiny := ord (
  6045. ( softfloat_detect_tininess = float_tininess_before_rounding )
  6046. or ( zExp < 0 )
  6047. or ( zSig0 <= zSig0 + roundIncrement ) );
  6048. shift64RightJamming( zSig0, 1 - zExp, zSig0 );
  6049. zExp := 0;
  6050. roundBits := zSig0 and roundMask;
  6051. if ( isTiny <> 0 ) and ( roundBits <> 0 ) then float_raise( float_flag_underflow );
  6052. if ( roundBits <> 0 ) then set_inexact_flag;
  6053. inc( zSig0, roundIncrement );
  6054. if ( sbits64( zSig0 ) < 0 ) then zExp := 1;
  6055. roundIncrement := roundMask + 1;
  6056. if ( roundNearestEven <> 0 ) and ( roundBits shl 1 = roundIncrement ) then begin
  6057. roundMask := roundMask or roundIncrement;
  6058. end;
  6059. zSig0 := zSig0 and not roundMask;
  6060. result:=packFloatx80( zSign, zExp, zSig0 );
  6061. exit;
  6062. end;
  6063. end;
  6064. if ( roundBits <> 0 ) then set_inexact_flag;
  6065. inc( zSig0, roundIncrement );
  6066. if ( zSig0 < roundIncrement ) then begin
  6067. inc(zExp);
  6068. zSig0 := bits64( $8000000000000000 );
  6069. end;
  6070. roundIncrement := roundMask + 1;
  6071. if ( roundNearestEven <> 0 ) and ( roundBits shl 1 = roundIncrement ) then begin
  6072. roundMask := roundMask or roundIncrement;
  6073. end;
  6074. zSig0 := zSig0 and not roundMask;
  6075. if ( zSig0 = 0 ) then zExp := 0;
  6076. result:=packFloatx80( zSign, zExp, zSig0 );
  6077. exit;
  6078. precision80:
  6079. increment := ord ( sbits64( zSig1 ) < 0 );
  6080. if ( roundNearestEven = 0 ) then begin
  6081. if ( roundingMode = float_round_to_zero ) then begin
  6082. increment := 0;
  6083. end
  6084. else begin
  6085. if ( zSign <> 0 ) then begin
  6086. increment := ord ( roundingMode = float_round_down ) and zSig1;
  6087. end
  6088. else begin
  6089. increment := ord ( roundingMode = float_round_up ) and zSig1;
  6090. end;
  6091. end;
  6092. end;
  6093. if ( $7FFD <= bits32( zExp - 1 ) ) then begin
  6094. if ( ( $7FFE < zExp )
  6095. or ( ( zExp = $7FFE )
  6096. and ( zSig0 = bits64( $FFFFFFFFFFFFFFFF ) )
  6097. and ( increment <> 0 )
  6098. )
  6099. ) then begin
  6100. roundMask := 0;
  6101. overflow:
  6102. float_raise( [float_flag_overflow,float_flag_inexact] );
  6103. if ( ( roundingMode = float_round_to_zero )
  6104. or ( ( zSign <> 0) and ( roundingMode = float_round_up ) )
  6105. or ( ( zSign = 0) and ( roundingMode = float_round_down ) )
  6106. ) then begin
  6107. result:=packFloatx80( zSign, $7FFE, not roundMask );
  6108. exit;
  6109. end;
  6110. result:=packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6111. exit;
  6112. end;
  6113. if ( zExp <= 0 ) then begin
  6114. isTiny := ord(
  6115. ( softfloat_detect_tininess = float_tininess_before_rounding )
  6116. or ( zExp < 0 )
  6117. or ( increment = 0 )
  6118. or ( zSig0 < bits64( $FFFFFFFFFFFFFFFF ) ) );
  6119. shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, zSig0, zSig1 );
  6120. zExp := 0;
  6121. if ( ( isTiny <> 0 ) and ( zSig1 <> 0 ) ) then float_raise( float_flag_underflow );
  6122. if ( zSig1 <> 0 ) then set_inexact_flag;
  6123. if ( roundNearestEven <> 0 ) then begin
  6124. increment := ord( sbits64( zSig1 ) < 0 );
  6125. end
  6126. else begin
  6127. if ( zSign <> 0 ) then begin
  6128. increment := ord( roundingMode = float_round_down ) and zSig1;
  6129. end
  6130. else begin
  6131. increment := ord( roundingMode = float_round_up ) and zSig1;
  6132. end;
  6133. end;
  6134. if ( increment <> 0 ) then begin
  6135. inc(zSig0);
  6136. zSig0 :=
  6137. not ( ord( bits64( zSig1 shl 1 ) = 0 ) and roundNearestEven );
  6138. if ( sbits64( zSig0 ) < 0 ) then zExp := 1;
  6139. end;
  6140. result:=packFloatx80( zSign, zExp, zSig0 );
  6141. exit;
  6142. end;
  6143. end;
  6144. if ( zSig1 <> 0 ) then set_inexact_flag;
  6145. if ( increment <> 0 ) then begin
  6146. inc(zSig0);
  6147. if ( zSig0 = 0 ) then begin
  6148. inc(zExp);
  6149. zSig0 := bits64( $8000000000000000 );
  6150. end
  6151. else begin
  6152. zSig0 := zSig0 and not bits64( ord( bits64( zSig1 shl 1 ) = 0 ) and roundNearestEven );
  6153. end;
  6154. end
  6155. else begin
  6156. if ( zSig0 = 0 ) then zExp := 0;
  6157. end;
  6158. result:=packFloatx80( zSign, zExp, zSig0 );
  6159. end;
  6160. {*----------------------------------------------------------------------------
  6161. | Takes an abstract floating-point value having sign `zSign', exponent
  6162. | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
  6163. | and returns the proper extended double-precision floating-point value
  6164. | corresponding to the abstract input. This routine is just like
  6165. | `roundAndPackFloatx80' except that the input significand does not have to be
  6166. | normalized.
  6167. *----------------------------------------------------------------------------*}
  6168. function normalizeRoundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
  6169. var
  6170. shiftCount: int8;
  6171. begin
  6172. if ( zSig0 = 0 ) then begin
  6173. zSig0 := zSig1;
  6174. zSig1 := 0;
  6175. dec( zExp, 64 );
  6176. end;
  6177. shiftCount := countLeadingZeros64( zSig0 );
  6178. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  6179. zExp := zExp - shiftCount;
  6180. result :=
  6181. roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
  6182. end;
  6183. {*----------------------------------------------------------------------------
  6184. | Returns the result of converting the extended double-precision floating-
  6185. | point value `a' to the 32-bit two's complement integer format. The
  6186. | conversion is performed according to the IEC/IEEE Standard for Binary
  6187. | Floating-Point Arithmetic---which means in particular that the conversion
  6188. | is rounded according to the current rounding mode. If `a' is a NaN, the
  6189. | largest positive integer is returned. Otherwise, if the conversion
  6190. | overflows, the largest integer with the same sign as `a' is returned.
  6191. *----------------------------------------------------------------------------*}
  6192. function floatx80_to_int32(a: floatx80): int32;
  6193. var
  6194. aSign: flag;
  6195. aExp, shiftCount: int32;
  6196. aSig: bits64;
  6197. begin
  6198. aSig := extractFloatx80Frac( a );
  6199. aExp := extractFloatx80Exp( a );
  6200. aSign := extractFloatx80Sign( a );
  6201. if ( aExp = $7FFF ) and ( bits64( aSig shl 1 ) <> 0 ) then aSign := 0;
  6202. shiftCount := $4037 - aExp;
  6203. if ( shiftCount <= 0 ) then shiftCount := 1;
  6204. shift64RightJamming( aSig, shiftCount, aSig );
  6205. result := roundAndPackInt32( aSign, aSig );
  6206. end;
  6207. {*----------------------------------------------------------------------------
  6208. | Returns the result of converting the extended double-precision floating-
  6209. | point value `a' to the 32-bit two's complement integer format. The
  6210. | conversion is performed according to the IEC/IEEE Standard for Binary
  6211. | Floating-Point Arithmetic, except that the conversion is always rounded
  6212. | toward zero. If `a' is a NaN, the largest positive integer is returned.
  6213. | Otherwise, if the conversion overflows, the largest integer with the same
  6214. | sign as `a' is returned.
  6215. *----------------------------------------------------------------------------*}
  6216. function floatx80_to_int32_round_to_zero(a: floatx80): int32;
  6217. var
  6218. aSign: flag;
  6219. aExp, shiftCount: int32;
  6220. aSig, savedASig: bits64;
  6221. z: int32;
  6222. label
  6223. invalid;
  6224. begin
  6225. aSig := extractFloatx80Frac( a );
  6226. aExp := extractFloatx80Exp( a );
  6227. aSign := extractFloatx80Sign( a );
  6228. if ( $401E < aExp ) then begin
  6229. if ( aExp = $7FFF ) and ( bits64( aSig shl 1 )<>0 ) then aSign := 0;
  6230. goto invalid;
  6231. end
  6232. else if ( aExp < $3FFF ) then begin
  6233. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  6234. result := 0;
  6235. exit;
  6236. end;
  6237. shiftCount := $403E - aExp;
  6238. savedASig := aSig;
  6239. aSig := aSig shr shiftCount;
  6240. z := aSig;
  6241. if ( aSign <> 0 ) then z := - z;
  6242. if ( ord( z < 0 ) xor aSign ) <> 0 then begin
  6243. invalid:
  6244. float_raise( float_flag_invalid );
  6245. if aSign <> 0 then result := sbits32( $80000000 ) else result := $7FFFFFFF;
  6246. exit;
  6247. end;
  6248. if ( ( aSig shl shiftCount ) <> savedASig ) then begin
  6249. set_inexact_flag;
  6250. end;
  6251. result := z;
  6252. end;
  6253. {*----------------------------------------------------------------------------
  6254. | Returns the result of converting the extended double-precision floating-
  6255. | point value `a' to the 64-bit two's complement integer format. The
  6256. | conversion is performed according to the IEC/IEEE Standard for Binary
  6257. | Floating-Point Arithmetic---which means in particular that the conversion
  6258. | is rounded according to the current rounding mode. If `a' is a NaN,
  6259. | the largest positive integer is returned. Otherwise, if the conversion
  6260. | overflows, the largest integer with the same sign as `a' is returned.
  6261. *----------------------------------------------------------------------------*}
  6262. function floatx80_to_int64(a: floatx80): int64;
  6263. var
  6264. aSign: flag;
  6265. aExp, shiftCount: int32;
  6266. aSig, aSigExtra: bits64;
  6267. begin
  6268. aSig := extractFloatx80Frac( a );
  6269. aExp := extractFloatx80Exp( a );
  6270. aSign := extractFloatx80Sign( a );
  6271. shiftCount := $403E - aExp;
  6272. if ( shiftCount <= 0 ) then begin
  6273. if ( shiftCount <> 0 ) then begin
  6274. float_raise( float_flag_invalid );
  6275. if ( ( aSign = 0 )
  6276. or ( ( aExp = $7FFF )
  6277. and ( aSig <> bits64( $8000000000000000 ) ) )
  6278. ) then begin
  6279. result := $7FFFFFFFFFFFFFFF;
  6280. exit;
  6281. end;
  6282. result := $8000000000000000;
  6283. exit;
  6284. end;
  6285. aSigExtra := 0;
  6286. end
  6287. else begin
  6288. shift64ExtraRightJamming( aSig, 0, shiftCount, aSig, aSigExtra );
  6289. end;
  6290. result := roundAndPackInt64( aSign, aSig, aSigExtra );
  6291. end;
  6292. {*----------------------------------------------------------------------------
  6293. | Returns the result of converting the extended double-precision floating-
  6294. | point value `a' to the 64-bit two's complement integer format. The
  6295. | conversion is performed according to the IEC/IEEE Standard for Binary
  6296. | Floating-Point Arithmetic, except that the conversion is always rounded
  6297. | toward zero. If `a' is a NaN, the largest positive integer is returned.
  6298. | Otherwise, if the conversion overflows, the largest integer with the same
  6299. | sign as `a' is returned.
  6300. *----------------------------------------------------------------------------*}
  6301. function floatx80_to_int64_round_to_zero(a: floatx80): int64;
  6302. var
  6303. aSign: flag;
  6304. aExp, shiftCount: int32;
  6305. aSig: bits64;
  6306. z: int64;
  6307. begin
  6308. aSig := extractFloatx80Frac( a );
  6309. aExp := extractFloatx80Exp( a );
  6310. aSign := extractFloatx80Sign( a );
  6311. shiftCount := aExp - $403E;
  6312. if ( 0 <= shiftCount ) then begin
  6313. aSig := $7FFFFFFFFFFFFFFF;
  6314. if ( ( a.high <> $C03E ) or ( aSig <> 0 ) ) then begin
  6315. float_raise( float_flag_invalid );
  6316. if ( ( aSign = 0 ) or ( ( aExp = $7FFF ) and ( aSig <> 0 ) ) ) then begin
  6317. result := $7FFFFFFFFFFFFFFF;
  6318. exit;
  6319. end;
  6320. end;
  6321. result := $8000000000000000;
  6322. exit;
  6323. end
  6324. else if ( aExp < $3FFF ) then begin
  6325. if ( aExp or aSig <> 0 ) then set_inexact_flag;
  6326. result := 0;
  6327. exit;
  6328. end;
  6329. z := aSig shr ( - shiftCount );
  6330. if bits64( aSig shl ( shiftCount and 63 ) ) <> 0 then begin
  6331. set_inexact_flag;
  6332. end;
  6333. if ( aSign <> 0 ) then z := - z;
  6334. result := z;
  6335. end;
  6336. {*----------------------------------------------------------------------------
  6337. | The pattern for a default generated extended double-precision NaN. The
  6338. | `high' and `low' values hold the most- and least-significant bits,
  6339. | respectively.
  6340. *----------------------------------------------------------------------------*}
  6341. const
  6342. floatx80_default_nan_high = $FFFF;
  6343. floatx80_default_nan_low = bits64( $C000000000000000 );
  6344. {*----------------------------------------------------------------------------
  6345. | Returns 1 if the extended double-precision floating-point value `a' is a
  6346. | signaling NaN; otherwise returns 0.
  6347. *----------------------------------------------------------------------------*}
  6348. function floatx80_is_signaling_nan(a : floatx80): flag;
  6349. var
  6350. aLow: bits64;
  6351. begin
  6352. aLow := a.low and not $4000000000000000;
  6353. result := ord(
  6354. ( a.high and $7FFF = $7FFF )
  6355. and ( bits64( aLow shl 1 ) <> 0 )
  6356. and ( a.low = aLow ) );
  6357. end;
  6358. {*----------------------------------------------------------------------------
  6359. | Returns the result of converting the extended double-precision floating-
  6360. | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
  6361. | invalid exception is raised.
  6362. *----------------------------------------------------------------------------*}
  6363. function floatx80ToCommonNaN(a : floatx80): commonNaNT;
  6364. var
  6365. z: commonNaNT;
  6366. begin
  6367. if floatx80_is_signaling_nan( a ) <> 0 then float_raise( float_flag_invalid );
  6368. z.sign := a.high shr 15;
  6369. z.low := 0;
  6370. z.high := a.low shl 1;
  6371. result := z;
  6372. end;
  6373. {*----------------------------------------------------------------------------
  6374. | Returns 1 if the extended double-precision floating-point value `a' is a
  6375. | NaN; otherwise returns 0.
  6376. *----------------------------------------------------------------------------*}
  6377. function floatx80_is_nan(a : floatx80 ): flag;
  6378. begin
  6379. result := ord( ( ( a.high and $7FFF ) = $7FFF ) and ( bits64( a.low shl 1 ) <> 0 ) );
  6380. end;
  6381. {*----------------------------------------------------------------------------
  6382. | Takes two extended double-precision floating-point values `a' and `b', one
  6383. | of which is a NaN, and returns the appropriate NaN result. If either `a' or
  6384. | `b' is a signaling NaN, the invalid exception is raised.
  6385. *----------------------------------------------------------------------------*}
  6386. function propagateFloatx80NaN(a, b: floatx80): floatx80;
  6387. var
  6388. aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
  6389. label
  6390. returnLargerSignificand;
  6391. begin
  6392. aIsNaN := floatx80_is_nan( a );
  6393. aIsSignalingNaN := floatx80_is_signaling_nan( a );
  6394. bIsNaN := floatx80_is_nan( b );
  6395. bIsSignalingNaN := floatx80_is_signaling_nan( b );
  6396. a.low := a.low or $C000000000000000;
  6397. b.low := b.low or $C000000000000000;
  6398. if aIsSignalingNaN or bIsSignalingNaN <> 0 then float_raise( float_flag_invalid );
  6399. if aIsSignalingNaN <> 0 then begin
  6400. if bIsSignalingNaN <> 0 then goto returnLargerSignificand;
  6401. if bIsNaN <> 0 then result := b else result := a;
  6402. exit;
  6403. end
  6404. else if aIsNaN <>0 then begin
  6405. if ( bIsSignalingNaN <> 0 ) or ( bIsNaN = 0) then begin
  6406. result := a;
  6407. exit;
  6408. end;
  6409. returnLargerSignificand:
  6410. if ( a.low < b.low ) then begin
  6411. result := b;
  6412. exit;
  6413. end;
  6414. if ( b.low < a.low ) then begin
  6415. result := a;
  6416. exit;
  6417. end;
  6418. if a.high < b.high then result := a else result := b;
  6419. exit;
  6420. end
  6421. else
  6422. result := b;
  6423. end;
  6424. {*----------------------------------------------------------------------------
  6425. | Returns the result of converting the extended double-precision floating-
  6426. | point value `a' to the single-precision floating-point format. The
  6427. | conversion is performed according to the IEC/IEEE Standard for Binary
  6428. | Floating-Point Arithmetic.
  6429. *----------------------------------------------------------------------------*}
  6430. function floatx80_to_float32(a: floatx80): float32;
  6431. var
  6432. aSign: flag;
  6433. aExp: int32;
  6434. aSig: bits64;
  6435. begin
  6436. aSig := extractFloatx80Frac( a );
  6437. aExp := extractFloatx80Exp( a );
  6438. aSign := extractFloatx80Sign( a );
  6439. if ( aExp = $7FFF ) then begin
  6440. if bits64( aSig shl 1 ) <> 0 then begin
  6441. result := commonNaNToFloat32( floatx80ToCommonNaN( a ) );
  6442. exit;
  6443. end;
  6444. result := packFloat32( aSign, $FF, 0 );
  6445. exit;
  6446. end;
  6447. shift64RightJamming( aSig, 33, aSig );
  6448. if ( aExp or aSig <> 0 ) then dec( aExp, $3F81 );
  6449. result := roundAndPackFloat32( aSign, aExp, aSig );
  6450. end;
  6451. {*----------------------------------------------------------------------------
  6452. | Returns the result of converting the extended double-precision floating-
  6453. | point value `a' to the double-precision floating-point format. The
  6454. | conversion is performed according to the IEC/IEEE Standard for Binary
  6455. | Floating-Point Arithmetic.
  6456. *----------------------------------------------------------------------------*}
  6457. function floatx80_to_float64(a: floatx80): float64;
  6458. var
  6459. aSign: flag;
  6460. aExp: int32;
  6461. aSig, zSig: bits64;
  6462. begin
  6463. aSig := extractFloatx80Frac( a );
  6464. aExp := extractFloatx80Exp( a );
  6465. aSign := extractFloatx80Sign( a );
  6466. if ( aExp = $7FFF ) then begin
  6467. if bits64( aSig shl 1 ) <> 0 then begin
  6468. result:=commonNaNToFloat64(floatx80ToCommonNaN(a));
  6469. exit;
  6470. end;
  6471. result := packFloat64( aSign, $7FF, 0 );
  6472. exit;
  6473. end;
  6474. shift64RightJamming( aSig, 1, zSig );
  6475. if ( aExp or aSig <> 0 ) then dec( aExp, $3C01 );
  6476. result := roundAndPackFloat64( aSign, aExp, zSig );
  6477. end;
  6478. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  6479. {*----------------------------------------------------------------------------
  6480. | Returns the result of converting the extended double-precision floating-
  6481. | point value `a' to the quadruple-precision floating-point format. The
  6482. | conversion is performed according to the IEC/IEEE Standard for Binary
  6483. | Floating-Point Arithmetic.
  6484. *----------------------------------------------------------------------------*}
  6485. function floatx80_to_float128(a: floatx80): float128;
  6486. var
  6487. aSign: flag;
  6488. aExp: int16;
  6489. aSig, zSig0, zSig1: bits64;
  6490. begin
  6491. aSig := extractFloatx80Frac( a );
  6492. aExp := extractFloatx80Exp( a );
  6493. aSign := extractFloatx80Sign( a );
  6494. if ( aExp = $7FFF ) and ( bits64( aSig shl 1 ) <> 0 ) then begin
  6495. result := commonNaNToFloat128( floatx80ToCommonNaN( a ) );
  6496. exit;
  6497. end;
  6498. shift128Right( aSig shl 1, 0, 16, zSig0, zSig1 );
  6499. result := packFloat128( aSign, aExp, zSig0, zSig1 );
  6500. end;
  6501. {$endif FPC_SOFTFLOAT_FLOAT128}
  6502. {*----------------------------------------------------------------------------
  6503. | Rounds the extended double-precision floating-point value `a' to an integer,
  6504. | and Returns the result as an extended quadruple-precision floating-point
  6505. | value. The operation is performed according to the IEC/IEEE Standard for
  6506. | Binary Floating-Point Arithmetic.
  6507. *----------------------------------------------------------------------------*}
  6508. function floatx80_round_to_int(a: floatx80): floatx80;
  6509. var
  6510. aSign: flag;
  6511. aExp: int32;
  6512. lastBitMask, roundBitsMask: bits64;
  6513. roundingMode: TFPURoundingMode;
  6514. z: floatx80;
  6515. begin
  6516. aExp := extractFloatx80Exp( a );
  6517. if ( $403E <= aExp ) then begin
  6518. if ( aExp = $7FFF ) and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) then begin
  6519. result := propagateFloatx80NaN( a, a );
  6520. exit;
  6521. end;
  6522. result := a;
  6523. exit;
  6524. end;
  6525. if ( aExp < $3FFF ) then begin
  6526. if ( ( aExp = 0 )
  6527. and ( bits64( extractFloatx80Frac( a ) shl 1 ) = 0 ) ) then begin
  6528. result := a;
  6529. exit;
  6530. end;
  6531. set_inexact_flag;
  6532. aSign := extractFloatx80Sign( a );
  6533. case softfloat_rounding_mode of
  6534. float_round_nearest_even:
  6535. if ( ( aExp = $3FFE ) and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 )
  6536. ) then begin
  6537. result :=
  6538. packFloatx80( aSign, $3FFF, bits64( $8000000000000000 ) );
  6539. exit;
  6540. end;
  6541. float_round_down: begin
  6542. if aSign <> 0 then
  6543. result := packFloatx80( 1, $3FFF, bits64( $8000000000000000 ) )
  6544. else
  6545. result := packFloatx80( 0, 0, 0 );
  6546. exit;
  6547. end;
  6548. float_round_up: begin
  6549. if aSign <> 0 then
  6550. result := packFloatx80( 1, 0, 0 )
  6551. else
  6552. result := packFloatx80( 0, $3FFF, bits64( $8000000000000000 ) );
  6553. exit;
  6554. end;
  6555. end;
  6556. result := packFloatx80( aSign, 0, 0 );
  6557. exit;
  6558. end;
  6559. lastBitMask := 1;
  6560. lastBitMask := lastBitMask shl ( $403E - aExp );
  6561. roundBitsMask := lastBitMask - 1;
  6562. z := a;
  6563. roundingMode := softfloat_rounding_mode;
  6564. if ( roundingMode = float_round_nearest_even ) then begin
  6565. inc( z.low, lastBitMask shr 1 );
  6566. if ( ( z.low and roundBitsMask ) = 0 ) then z.low := z.low and not lastBitMask;
  6567. end
  6568. else if ( roundingMode <> float_round_to_zero ) then begin
  6569. if ( extractFloatx80Sign( z ) <> 0 ) xor ( roundingMode = float_round_up ) then begin
  6570. inc( z.low, roundBitsMask );
  6571. end;
  6572. end;
  6573. z.low := z.low and not roundBitsMask;
  6574. if ( z.low = 0 ) then begin
  6575. inc(z.high);
  6576. z.low := bits64( $8000000000000000 );
  6577. end;
  6578. if ( z.low <> a.low ) then set_inexact_flag;
  6579. result := z;
  6580. end;
  6581. {*----------------------------------------------------------------------------
  6582. | Returns the result of adding the absolute values of the extended double-
  6583. | precision floating-point values `a' and `b'. If `zSign' is 1, the sum is
  6584. | negated before being returned. `zSign' is ignored if the result is a NaN.
  6585. | The addition is performed according to the IEC/IEEE Standard for Binary
  6586. | Floating-Point Arithmetic.
  6587. *----------------------------------------------------------------------------*}
  6588. function addFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
  6589. var
  6590. aExp, bExp, zExp: int32;
  6591. aSig, bSig, zSig0, zSig1: bits64;
  6592. expDiff: int32;
  6593. label
  6594. shiftRight1, roundAndPack;
  6595. begin
  6596. aSig := extractFloatx80Frac( a );
  6597. aExp := extractFloatx80Exp( a );
  6598. bSig := extractFloatx80Frac( b );
  6599. bExp := extractFloatx80Exp( b );
  6600. expDiff := aExp - bExp;
  6601. if ( 0 < expDiff ) then begin
  6602. if ( aExp = $7FFF ) then begin
  6603. if ( bits64( aSig shl 1 ) <> 0 ) then begin
  6604. result := propagateFloatx80NaN( a, b );
  6605. exit;
  6606. end;
  6607. result := a;
  6608. exit;
  6609. end;
  6610. if ( bExp = 0 ) then dec(expDiff);
  6611. shift64ExtraRightJamming( bSig, 0, expDiff, bSig, zSig1 );
  6612. zExp := aExp;
  6613. end
  6614. else if ( expDiff < 0 ) then begin
  6615. if ( bExp = $7FFF ) then begin
  6616. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6617. result := propagateFloatx80NaN( a, b );
  6618. exit;
  6619. end;
  6620. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6621. exit;
  6622. end;
  6623. if ( aExp = 0 ) then inc(expDiff);
  6624. shift64ExtraRightJamming( aSig, 0, - expDiff, aSig, zSig1 );
  6625. zExp := bExp;
  6626. end
  6627. else begin
  6628. if ( aExp = $7FFF ) then begin
  6629. if ( bits64( ( aSig or bSig ) shl 1 ) <> 0 ) then begin
  6630. result := propagateFloatx80NaN( a, b );
  6631. exit;
  6632. end;
  6633. result := a;
  6634. exit;
  6635. end;
  6636. zSig1 := 0;
  6637. zSig0 := aSig + bSig;
  6638. if ( aExp = 0 ) then begin
  6639. normalizeFloatx80Subnormal( zSig0, zExp, zSig0 );
  6640. goto roundAndPack;
  6641. end;
  6642. zExp := aExp;
  6643. goto shiftRight1;
  6644. end;
  6645. zSig0 := aSig + bSig;
  6646. if ( sbits64( zSig0 ) < 0 ) then goto roundAndPack;
  6647. shiftRight1:
  6648. shift64ExtraRightJamming( zSig0, zSig1, 1, zSig0, zSig1 );
  6649. zSig0 := zSig0 or $8000000000000000;
  6650. inc(zExp);
  6651. roundAndPack:
  6652. result :=
  6653. roundAndPackFloatx80(
  6654. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6655. end;
  6656. {*----------------------------------------------------------------------------
  6657. | Returns the result of subtracting the absolute values of the extended
  6658. | double-precision floating-point values `a' and `b'. If `zSign' is 1, the
  6659. | difference is negated before being returned. `zSign' is ignored if the
  6660. | result is a NaN. The subtraction is performed according to the IEC/IEEE
  6661. | Standard for Binary Floating-Point Arithmetic.
  6662. *----------------------------------------------------------------------------*}
  6663. function subFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
  6664. var
  6665. aExp, bExp, zExp: int32;
  6666. aSig, bSig, zSig0, zSig1: bits64;
  6667. expDiff: int32;
  6668. z: floatx80;
  6669. label
  6670. bExpBigger, bBigger, aExpBigger, aBigger, normalizeRoundAndPack;
  6671. begin
  6672. aSig := extractFloatx80Frac( a );
  6673. aExp := extractFloatx80Exp( a );
  6674. bSig := extractFloatx80Frac( b );
  6675. bExp := extractFloatx80Exp( b );
  6676. expDiff := aExp - bExp;
  6677. if ( 0 < expDiff ) then goto aExpBigger;
  6678. if ( expDiff < 0 ) then goto bExpBigger;
  6679. if ( aExp = $7FFF ) then begin
  6680. if ( bits64( ( aSig or bSig ) shl 1 ) <> 0 ) then begin
  6681. result := propagateFloatx80NaN( a, b );
  6682. exit;
  6683. end;
  6684. float_raise( float_flag_invalid );
  6685. z.low := floatx80_default_nan_low;
  6686. z.high := floatx80_default_nan_high;
  6687. result := z;
  6688. exit;
  6689. end;
  6690. if ( aExp = 0 ) then begin
  6691. aExp := 1;
  6692. bExp := 1;
  6693. end;
  6694. zSig1 := 0;
  6695. if ( bSig < aSig ) then goto aBigger;
  6696. if ( aSig < bSig ) then goto bBigger;
  6697. result := packFloatx80( ord( softfloat_rounding_mode = float_round_down ), 0, 0 );
  6698. exit;
  6699. bExpBigger:
  6700. if ( bExp = $7FFF ) then begin
  6701. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6702. result := propagateFloatx80NaN( a, b );
  6703. exit;
  6704. end;
  6705. result := packFloatx80( zSign xor 1, $7FFF, bits64( $8000000000000000 ) );
  6706. exit;
  6707. end;
  6708. if ( aExp = 0 ) then inc(expDiff);
  6709. shift128RightJamming( aSig, 0, - expDiff, aSig, zSig1 );
  6710. bBigger:
  6711. sub128( bSig, 0, aSig, zSig1, zSig0, zSig1 );
  6712. zExp := bExp;
  6713. zSign := zSign xor 1;
  6714. goto normalizeRoundAndPack;
  6715. aExpBigger:
  6716. if ( aExp = $7FFF ) then begin
  6717. if ( bits64( aSig shl 1 ) <> 0 ) then begin
  6718. result := propagateFloatx80NaN( a, b );
  6719. exit;
  6720. end;
  6721. result := a;
  6722. exit;
  6723. end;
  6724. if ( bExp = 0 ) then dec(expDiff);
  6725. shift128RightJamming( bSig, 0, expDiff, bSig, zSig1 );
  6726. aBigger:
  6727. sub128( aSig, 0, bSig, zSig1, zSig0, zSig1 );
  6728. zExp := aExp;
  6729. normalizeRoundAndPack:
  6730. result :=
  6731. normalizeRoundAndPackFloatx80(
  6732. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6733. end;
  6734. {*----------------------------------------------------------------------------
  6735. | Returns the result of adding the extended double-precision floating-point
  6736. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  6737. | Standard for Binary Floating-Point Arithmetic.
  6738. *----------------------------------------------------------------------------*}
  6739. function floatx80_add(a: floatx80; b: floatx80): floatx80;
  6740. var
  6741. aSign, bSign: flag;
  6742. begin
  6743. aSign := extractFloatx80Sign( a );
  6744. bSign := extractFloatx80Sign( b );
  6745. if ( aSign = bSign ) then begin
  6746. result := addFloatx80Sigs( a, b, aSign );
  6747. end
  6748. else begin
  6749. result := subFloatx80Sigs( a, b, aSign );
  6750. end;
  6751. end;
  6752. {*----------------------------------------------------------------------------
  6753. | Returns the result of subtracting the extended double-precision floating-
  6754. | point values `a' and `b'. The operation is performed according to the
  6755. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6756. *----------------------------------------------------------------------------*}
  6757. function floatx80_sub(a: floatx80; b: floatx80 ): floatx80;
  6758. var
  6759. aSign, bSign: flag;
  6760. begin
  6761. aSign := extractFloatx80Sign( a );
  6762. bSign := extractFloatx80Sign( b );
  6763. if ( aSign = bSign ) then begin
  6764. result := subFloatx80Sigs( a, b, aSign );
  6765. end
  6766. else begin
  6767. result := addFloatx80Sigs( a, b, aSign );
  6768. end;
  6769. end;
  6770. {*----------------------------------------------------------------------------
  6771. | Returns the result of multiplying the extended double-precision floating-
  6772. | point values `a' and `b'. The operation is performed according to the
  6773. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6774. *----------------------------------------------------------------------------*}
  6775. function floatx80_mul(a: floatx80; b: floatx80): floatx80;
  6776. var
  6777. aSign, bSign, zSign: flag;
  6778. aExp, bExp, zExp: int32;
  6779. aSig, bSig, zSig0, zSig1: bits64;
  6780. z: floatx80;
  6781. label
  6782. invalid;
  6783. begin
  6784. aSig := extractFloatx80Frac( a );
  6785. aExp := extractFloatx80Exp( a );
  6786. aSign := extractFloatx80Sign( a );
  6787. bSig := extractFloatx80Frac( b );
  6788. bExp := extractFloatx80Exp( b );
  6789. bSign := extractFloatx80Sign( b );
  6790. zSign := aSign xor bSign;
  6791. if ( aExp = $7FFF ) then begin
  6792. if ( bits64( aSig shl 1 ) <> 0 )
  6793. or ( ( bExp = $7FFF ) and ( bits64( bSig shl 1 ) <> 0 ) ) then begin
  6794. result := propagateFloatx80NaN( a, b );
  6795. exit;
  6796. end;
  6797. if ( ( bExp or bSig ) = 0 ) then goto invalid;
  6798. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6799. exit;
  6800. end;
  6801. if ( bExp = $7FFF ) then begin
  6802. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6803. result := propagateFloatx80NaN( a, b );
  6804. exit;
  6805. end;
  6806. if ( ( aExp or aSig ) = 0 ) then begin
  6807. invalid:
  6808. float_raise( float_flag_invalid );
  6809. z.low := floatx80_default_nan_low;
  6810. z.high := floatx80_default_nan_high;
  6811. result := z;
  6812. exit;
  6813. end;
  6814. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6815. exit;
  6816. end;
  6817. if ( aExp = 0 ) then begin
  6818. if ( aSig = 0 ) then begin
  6819. result := packFloatx80( zSign, 0, 0 );
  6820. exit;
  6821. end;
  6822. normalizeFloatx80Subnormal( aSig, aExp, aSig );
  6823. end;
  6824. if ( bExp = 0 ) then begin
  6825. if ( bSig = 0 ) then begin
  6826. result := packFloatx80( zSign, 0, 0 );
  6827. exit;
  6828. end;
  6829. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6830. end;
  6831. zExp := aExp + bExp - $3FFE;
  6832. mul64To128( aSig, bSig, zSig0, zSig1 );
  6833. if 0 < sbits64( zSig0 ) then begin
  6834. shortShift128Left( zSig0, zSig1, 1, zSig0, zSig1 );
  6835. dec(zExp);
  6836. end;
  6837. result :=
  6838. roundAndPackFloatx80(
  6839. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6840. end;
  6841. {*----------------------------------------------------------------------------
  6842. | Returns the result of dividing the extended double-precision floating-point
  6843. | value `a' by the corresponding value `b'. The operation is performed
  6844. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6845. *----------------------------------------------------------------------------*}
  6846. function floatx80_div(a: floatx80; b: floatx80 ): floatx80;
  6847. var
  6848. aSign, bSign, zSign: flag;
  6849. aExp, bExp, zExp: int32;
  6850. aSig, bSig, zSig0, zSig1: bits64;
  6851. rem0, rem1, rem2, term0, term1, term2: bits64;
  6852. z: floatx80;
  6853. label
  6854. invalid;
  6855. begin
  6856. aSig := extractFloatx80Frac( a );
  6857. aExp := extractFloatx80Exp( a );
  6858. aSign := extractFloatx80Sign( a );
  6859. bSig := extractFloatx80Frac( b );
  6860. bExp := extractFloatx80Exp( b );
  6861. bSign := extractFloatx80Sign( b );
  6862. zSign := aSign xor bSign;
  6863. if ( aExp = $7FFF ) then begin
  6864. if ( bits64( aSig shl 1 ) <> 0 ) then begin
  6865. result := propagateFloatx80NaN( a, b );
  6866. exit;
  6867. end;
  6868. if ( bExp = $7FFF ) then begin
  6869. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6870. result := propagateFloatx80NaN( a, b );
  6871. exit;
  6872. end;
  6873. goto invalid;
  6874. end;
  6875. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6876. exit;
  6877. end;
  6878. if ( bExp = $7FFF ) then begin
  6879. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6880. result := propagateFloatx80NaN( a, b );
  6881. exit;
  6882. end;
  6883. result := packFloatx80( zSign, 0, 0 );
  6884. exit;
  6885. end;
  6886. if ( bExp = 0 ) then begin
  6887. if ( bSig = 0 ) then begin
  6888. if ( ( aExp or aSig ) = 0 ) then begin
  6889. invalid:
  6890. float_raise( float_flag_invalid );
  6891. z.low := floatx80_default_nan_low;
  6892. z.high := floatx80_default_nan_high;
  6893. result := z;
  6894. exit;
  6895. end;
  6896. float_raise( float_flag_divbyzero );
  6897. result := packFloatx80( zSign, $7FFF, bits64( $8000000000000000 ) );
  6898. exit;
  6899. end;
  6900. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6901. end;
  6902. if ( aExp = 0 ) then begin
  6903. if ( aSig = 0 ) then begin
  6904. result := packFloatx80( zSign, 0, 0 );
  6905. exit;
  6906. end;
  6907. normalizeFloatx80Subnormal( aSig, aExp, aSig );
  6908. end;
  6909. zExp := aExp - bExp + $3FFE;
  6910. rem1 := 0;
  6911. if ( bSig <= aSig ) then begin
  6912. shift128Right( aSig, 0, 1, aSig, rem1 );
  6913. inc(zExp);
  6914. end;
  6915. zSig0 := estimateDiv128To64( aSig, rem1, bSig );
  6916. mul64To128( bSig, zSig0, term0, term1 );
  6917. sub128( aSig, rem1, term0, term1, rem0, rem1 );
  6918. while ( sbits64( rem0 ) < 0 ) do begin
  6919. dec(zSig0);
  6920. add128( rem0, rem1, 0, bSig, rem0, rem1 );
  6921. end;
  6922. zSig1 := estimateDiv128To64( rem1, 0, bSig );
  6923. if ( bits64( zSig1 shl 1 ) <= 8 ) then begin
  6924. mul64To128( bSig, zSig1, term1, term2 );
  6925. sub128( rem1, 0, term1, term2, rem1, rem2 );
  6926. while ( sbits64( rem1 ) < 0 ) do begin
  6927. dec(zSig1);
  6928. add128( rem1, rem2, 0, bSig, rem1, rem2 );
  6929. end;
  6930. zSig1 := zSig1 or ord( ( rem1 or rem2 ) <> 0 );
  6931. end;
  6932. result :=
  6933. roundAndPackFloatx80(
  6934. floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
  6935. end;
  6936. {*----------------------------------------------------------------------------
  6937. | Returns the remainder of the extended double-precision floating-point value
  6938. | `a' with respect to the corresponding value `b'. The operation is performed
  6939. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  6940. *----------------------------------------------------------------------------*}
  6941. function floatx80_rem(a: floatx80; b: floatx80 ): floatx80;
  6942. var
  6943. aSign, zSign: flag;
  6944. aExp, bExp, expDiff: int32;
  6945. aSig0, aSig1, bSig: bits64;
  6946. q, term0, term1, alternateASig0, alternateASig1: bits64;
  6947. z: floatx80;
  6948. label
  6949. invalid;
  6950. begin
  6951. aSig0 := extractFloatx80Frac( a );
  6952. aExp := extractFloatx80Exp( a );
  6953. aSign := extractFloatx80Sign( a );
  6954. bSig := extractFloatx80Frac( b );
  6955. bExp := extractFloatx80Exp( b );
  6956. if ( aExp = $7FFF ) then begin
  6957. if ( bits64( aSig0 shl 1 ) <> 0 )
  6958. or ( ( bExp = $7FFF ) and ( bits64( bSig shl 1 ) <> 0 ) ) then begin
  6959. result := propagateFloatx80NaN( a, b );
  6960. exit;
  6961. end;
  6962. goto invalid;
  6963. end;
  6964. if ( bExp = $7FFF ) then begin
  6965. if ( bits64( bSig shl 1 ) <> 0 ) then begin
  6966. result := propagateFloatx80NaN( a, b );
  6967. exit;
  6968. end;
  6969. result := a;
  6970. exit;
  6971. end;
  6972. if ( bExp = 0 ) then begin
  6973. if ( bSig = 0 ) then begin
  6974. invalid:
  6975. float_raise( float_flag_invalid );
  6976. z.low := floatx80_default_nan_low;
  6977. z.high := floatx80_default_nan_high;
  6978. result := z;
  6979. exit;
  6980. end;
  6981. normalizeFloatx80Subnormal( bSig, bExp, bSig );
  6982. end;
  6983. if ( aExp = 0 ) then begin
  6984. if ( bits64( aSig0 shl 1 ) = 0 ) then begin
  6985. result := a;
  6986. exit;
  6987. end;
  6988. normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );
  6989. end;
  6990. bSig := bSig or $8000000000000000;
  6991. zSign := aSign;
  6992. expDiff := aExp - bExp;
  6993. aSig1 := 0;
  6994. if ( expDiff < 0 ) then begin
  6995. if ( expDiff < -1 ) then begin
  6996. result := a;
  6997. exit;
  6998. end;
  6999. shift128Right( aSig0, 0, 1, aSig0, aSig1 );
  7000. expDiff := 0;
  7001. end;
  7002. q := ord( bSig <= aSig0 );
  7003. if ( q <> 0 ) then dec( aSig0, bSig );
  7004. dec( expDiff, 64 );
  7005. while ( 0 < expDiff ) do begin
  7006. q := estimateDiv128To64( aSig0, aSig1, bSig );
  7007. if ( 2 < q ) then q := q - 2 else q := 0;
  7008. mul64To128( bSig, q, term0, term1 );
  7009. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  7010. shortShift128Left( aSig0, aSig1, 62, aSig0, aSig1 );
  7011. dec( expDiff, 62 );
  7012. end;
  7013. inc( expDiff, 64 );
  7014. if ( 0 < expDiff ) then begin
  7015. q := estimateDiv128To64( aSig0, aSig1, bSig );
  7016. if ( 2 < q ) then q:= q - 2 else q := 0;
  7017. q := q shr ( 64 - expDiff );
  7018. mul64To128( bSig, q shl ( 64 - expDiff ), term0, term1 );
  7019. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  7020. shortShift128Left( 0, bSig, 64 - expDiff, term0, term1 );
  7021. while ( le128( term0, term1, aSig0, aSig1 ) <> 0 ) do begin
  7022. inc(q);
  7023. sub128( aSig0, aSig1, term0, term1, aSig0, aSig1 );
  7024. end;
  7025. end
  7026. else begin
  7027. term1 := 0;
  7028. term0 := bSig;
  7029. end;
  7030. sub128( term0, term1, aSig0, aSig1, alternateASig0, alternateASig1 );
  7031. if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) <> 0 )
  7032. or ( ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) <> 0 )
  7033. and ( q and 1 <> 0 ) )
  7034. then begin
  7035. aSig0 := alternateASig0;
  7036. aSig1 := alternateASig1;
  7037. zSign := ord( zSign = 0 );
  7038. end;
  7039. result :=
  7040. normalizeRoundAndPackFloatx80(
  7041. 80, zSign, bExp + expDiff, aSig0, aSig1 );
  7042. end;
  7043. {*----------------------------------------------------------------------------
  7044. | Returns the square root of the extended double-precision floating-point
  7045. | value `a'. The operation is performed according to the IEC/IEEE Standard
  7046. | for Binary Floating-Point Arithmetic.
  7047. *----------------------------------------------------------------------------*}
  7048. function floatx80_sqrt(a: floatx80): floatx80;
  7049. var
  7050. aSign: flag;
  7051. aExp, zExp: int32;
  7052. aSig0, aSig1, zSig0, zSig1, doubleZSig0: bits64;
  7053. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  7054. z: floatx80;
  7055. label
  7056. invalid;
  7057. begin
  7058. aSig0 := extractFloatx80Frac( a );
  7059. aExp := extractFloatx80Exp( a );
  7060. aSign := extractFloatx80Sign( a );
  7061. if ( aExp = $7FFF ) then begin
  7062. if ( bits64( aSig0 shl 1 ) <> 0 ) then begin
  7063. result := propagateFloatx80NaN( a, a );
  7064. exit;
  7065. end;
  7066. if ( aSign = 0 ) then begin
  7067. result := a;
  7068. exit;
  7069. end;
  7070. goto invalid;
  7071. end;
  7072. if ( aSign <> 0 ) then begin
  7073. if ( ( aExp or aSig0 ) = 0 ) then begin
  7074. result := a;
  7075. exit;
  7076. end;
  7077. invalid:
  7078. float_raise( float_flag_invalid );
  7079. z.low := floatx80_default_nan_low;
  7080. z.high := floatx80_default_nan_high;
  7081. result := z;
  7082. exit;
  7083. end;
  7084. if ( aExp = 0 ) then begin
  7085. if ( aSig0 = 0 ) then begin
  7086. result := packFloatx80( 0, 0, 0 );
  7087. exit;
  7088. end;
  7089. normalizeFloatx80Subnormal( aSig0, aExp, aSig0 );
  7090. end;
  7091. zExp := ( ( aExp - $3FFF ) shr 1 ) + $3FFF;
  7092. zSig0 := estimateSqrt32( aExp, aSig0 shr 32 );
  7093. shift128Right( aSig0, 0, 2 + ( aExp and 1 ), aSig0, aSig1 );
  7094. zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
  7095. doubleZSig0 := zSig0 shl 1;
  7096. mul64To128( zSig0, zSig0, term0, term1 );
  7097. sub128( aSig0, aSig1, term0, term1, rem0, rem1 );
  7098. while ( sbits64( rem0 ) < 0 ) do begin
  7099. dec(zSig0);
  7100. dec( doubleZSig0, 2 );
  7101. add128( rem0, rem1, zSig0 shr 63, doubleZSig0 or 1, rem0, rem1 );
  7102. end;
  7103. zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
  7104. if ( ( zSig1 and $3FFFFFFFFFFFFFFF ) <= 5 ) then begin
  7105. if ( zSig1 = 0 ) then zSig1 := 1;
  7106. mul64To128( doubleZSig0, zSig1, term1, term2 );
  7107. sub128( rem1, 0, term1, term2, rem1, rem2 );
  7108. mul64To128( zSig1, zSig1, term2, term3 );
  7109. sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  7110. while ( sbits64( rem1 ) < 0 ) do begin
  7111. dec(zSig1);
  7112. shortShift128Left( 0, zSig1, 1, term2, term3 );
  7113. term3 := term3 or 1;
  7114. term2 := term2 or doubleZSig0;
  7115. add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  7116. end;
  7117. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  7118. end;
  7119. shortShift128Left( 0, zSig1, 1, zSig0, zSig1 );
  7120. zSig0 := zSig0 or doubleZSig0;
  7121. result :=
  7122. roundAndPackFloatx80(
  7123. floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
  7124. end;
  7125. {*----------------------------------------------------------------------------
  7126. | Returns 1 if the extended double-precision floating-point value `a' is
  7127. | equal to the corresponding value `b', and 0 otherwise. The comparison is
  7128. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  7129. | Arithmetic.
  7130. *----------------------------------------------------------------------------*}
  7131. function floatx80_eq(a: floatx80; b: floatx80 ): flag;
  7132. begin
  7133. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7134. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 )
  7135. ) or ( ( extractFloatx80Exp( b ) = $7FFF )
  7136. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 )
  7137. ) then begin
  7138. if ( floatx80_is_signaling_nan( a )
  7139. or floatx80_is_signaling_nan( b ) <> 0 ) then begin
  7140. float_raise( float_flag_invalid );
  7141. end;
  7142. result := 0;
  7143. exit;
  7144. end;
  7145. result := ord(
  7146. ( a.low = b.low )
  7147. and ( ( a.high = b.high )
  7148. or ( ( a.low = 0 )
  7149. and ( bits16 ( ( a.high or b.high ) shl 1 ) = 0 ) )
  7150. ) );
  7151. end;
  7152. {*----------------------------------------------------------------------------
  7153. | Returns 1 if the extended double-precision floating-point value `a' is
  7154. | less than or equal to the corresponding value `b', and 0 otherwise. The
  7155. | comparison is performed according to the IEC/IEEE Standard for Binary
  7156. | Floating-Point Arithmetic.
  7157. *----------------------------------------------------------------------------*}
  7158. function floatx80_le(a: floatx80; b: floatx80 ): flag;
  7159. var
  7160. aSign, bSign: flag;
  7161. begin
  7162. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7163. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7164. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7165. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7166. then begin
  7167. float_raise( float_flag_invalid );
  7168. result := 0;
  7169. exit;
  7170. end;
  7171. aSign := extractFloatx80Sign( a );
  7172. bSign := extractFloatx80Sign( b );
  7173. if ( aSign <> bSign ) then begin
  7174. result := ord(
  7175. ( aSign <> 0 )
  7176. or ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low = 0 ) );
  7177. exit;
  7178. end;
  7179. if aSign<>0 then
  7180. result := le128( b.high, b.low, a.high, a.low )
  7181. else
  7182. result := le128( a.high, a.low, b.high, b.low );
  7183. end;
  7184. {*----------------------------------------------------------------------------
  7185. | Returns 1 if the extended double-precision floating-point value `a' is
  7186. | less than the corresponding value `b', and 0 otherwise. The comparison
  7187. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7188. | Arithmetic.
  7189. *----------------------------------------------------------------------------*}
  7190. function floatx80_lt(a: floatx80; b: floatx80 ): flag;
  7191. var
  7192. aSign, bSign: flag;
  7193. begin
  7194. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7195. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7196. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7197. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7198. then begin
  7199. float_raise( float_flag_invalid );
  7200. result := 0;
  7201. exit;
  7202. end;
  7203. aSign := extractFloatx80Sign( a );
  7204. bSign := extractFloatx80Sign( b );
  7205. if ( aSign <> bSign ) then begin
  7206. result := ord(
  7207. ( aSign <> 0 )
  7208. and ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low <> 0 ) );
  7209. exit;
  7210. end;
  7211. if aSign <> 0 then
  7212. result := lt128( b.high, b.low, a.high, a.low )
  7213. else
  7214. result := lt128( a.high, a.low, b.high, b.low );
  7215. end;
  7216. {*----------------------------------------------------------------------------
  7217. | Returns 1 if the extended double-precision floating-point value `a' is equal
  7218. | to the corresponding value `b', and 0 otherwise. The invalid exception is
  7219. | raised if either operand is a NaN. Otherwise, the comparison is performed
  7220. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7221. *----------------------------------------------------------------------------*}
  7222. function floatx80_eq_signaling(a: floatx80; b: floatx80 ): flag;
  7223. begin
  7224. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7225. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7226. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7227. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7228. then begin
  7229. float_raise( float_flag_invalid );
  7230. result := 0;
  7231. exit;
  7232. end;
  7233. result := ord(
  7234. ( a.low = b.low )
  7235. and ( ( a.high = b.high )
  7236. or ( ( a.low = 0 )
  7237. and ( bits16( ( a.high or b.high ) shl 1 ) = 0 ) )
  7238. ) );
  7239. end;
  7240. {*----------------------------------------------------------------------------
  7241. | Returns 1 if the extended double-precision floating-point value `a' is less
  7242. | than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
  7243. | do not cause an exception. Otherwise, the comparison is performed according
  7244. | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7245. *----------------------------------------------------------------------------*}
  7246. function floatx80_le_quiet(a: floatx80; b: floatx80 ): flag;
  7247. var
  7248. aSign, bSign: flag;
  7249. begin
  7250. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7251. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7252. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7253. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7254. then begin
  7255. if ( floatx80_is_signaling_nan( a )
  7256. or floatx80_is_signaling_nan( b ) <> 0 ) then begin
  7257. float_raise( float_flag_invalid );
  7258. end;
  7259. result := 0;
  7260. exit;
  7261. end;
  7262. aSign := extractFloatx80Sign( a );
  7263. bSign := extractFloatx80Sign( b );
  7264. if ( aSign <> bSign ) then begin
  7265. result := ord(
  7266. ( aSign <> 0 )
  7267. or ( ( bits16( ( a.high or b.high ) shl 1 ) ) or a.low or b.low = 0 ) );
  7268. exit;
  7269. end;
  7270. if aSign <> 0 then
  7271. result := le128( b.high, b.low, a.high, a.low )
  7272. else
  7273. result := le128( a.high, a.low, b.high, b.low );
  7274. end;
  7275. {*----------------------------------------------------------------------------
  7276. | Returns 1 if the extended double-precision floating-point value `a' is less
  7277. | than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
  7278. | an exception. Otherwise, the comparison is performed according to the
  7279. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7280. *----------------------------------------------------------------------------*}
  7281. function floatx80_lt_quiet(a: floatx80; b: floatx80 ): flag;
  7282. var
  7283. aSign, bSign: flag;
  7284. begin
  7285. if ( ( extractFloatx80Exp( a ) = $7FFF )
  7286. and ( bits64( extractFloatx80Frac( a ) shl 1 ) <> 0 ) )
  7287. or ( ( extractFloatx80Exp( b ) = $7FFF )
  7288. and ( bits64( extractFloatx80Frac( b ) shl 1 ) <> 0 ) )
  7289. then begin
  7290. if ( floatx80_is_signaling_nan( a )
  7291. or floatx80_is_signaling_nan( b ) <> 0 ) then begin
  7292. float_raise( float_flag_invalid );
  7293. end;
  7294. result := 0;
  7295. exit;
  7296. end;
  7297. aSign := extractFloatx80Sign( a );
  7298. bSign := extractFloatx80Sign( b );
  7299. if ( aSign <> bSign ) then begin
  7300. result := ord(
  7301. ( aSign <> 0 )
  7302. and ( bits16( ( a.high or b.high ) shl 1 ) or a.low or b.low <> 0 ) );
  7303. exit;
  7304. end;
  7305. if aSign <> 0 then
  7306. result := lt128( b.high, b.low, a.high, a.low )
  7307. else
  7308. result := lt128( a.high, a.low, b.high, b.low );
  7309. end;
  7310. {$endif FPC_SOFTFLOAT_FLOATX80}
  7311. {$ifdef FPC_SOFTFLOAT_FLOAT128}
  7312. {*----------------------------------------------------------------------------
  7313. | Returns the least-significant 64 fraction bits of the quadruple-precision
  7314. | floating-point value `a'.
  7315. *----------------------------------------------------------------------------*}
  7316. function extractFloat128Frac1(a : float128): bits64;
  7317. begin
  7318. result:=a.low;
  7319. end;
  7320. {*----------------------------------------------------------------------------
  7321. | Returns the most-significant 48 fraction bits of the quadruple-precision
  7322. | floating-point value `a'.
  7323. *----------------------------------------------------------------------------*}
  7324. function extractFloat128Frac0(a : float128): bits64;
  7325. begin
  7326. result:=a.high and int64($0000FFFFFFFFFFFF);
  7327. end;
  7328. {*----------------------------------------------------------------------------
  7329. | Returns the exponent bits of the quadruple-precision floating-point value
  7330. | `a'.
  7331. *----------------------------------------------------------------------------*}
  7332. function extractFloat128Exp(a : float128): int32;
  7333. begin
  7334. result:=( a.high shr 48 ) and $7FFF;
  7335. end;
  7336. {*----------------------------------------------------------------------------
  7337. | Returns the sign bit of the quadruple-precision floating-point value `a'.
  7338. *----------------------------------------------------------------------------*}
  7339. function extractFloat128Sign(a : float128): flag;
  7340. begin
  7341. result:=a.high shr 63;
  7342. end;
  7343. {*----------------------------------------------------------------------------
  7344. | Normalizes the subnormal quadruple-precision floating-point value
  7345. | represented by the denormalized significand formed by the concatenation of
  7346. | `aSig0' and `aSig1'. The normalized exponent is stored at the location
  7347. | pointed to by `zExpPtr'. The most significant 49 bits of the normalized
  7348. | significand are stored at the location pointed to by `zSig0Ptr', and the
  7349. | least significant 64 bits of the normalized significand are stored at the
  7350. | location pointed to by `zSig1Ptr'.
  7351. *----------------------------------------------------------------------------*}
  7352. procedure normalizeFloat128Subnormal(
  7353. aSig0: bits64;
  7354. aSig1: bits64;
  7355. var zExpPtr: int32;
  7356. var zSig0Ptr: bits64;
  7357. var zSig1Ptr: bits64);
  7358. var
  7359. shiftCount: int8;
  7360. begin
  7361. if ( aSig0 = 0 ) then
  7362. begin
  7363. shiftCount := countLeadingZeros64( aSig1 ) - 15;
  7364. if ( shiftCount < 0 ) then
  7365. begin
  7366. zSig0Ptr := aSig1 shr ( - shiftCount );
  7367. zSig1Ptr := aSig1 shl ( shiftCount and 63 );
  7368. end
  7369. else begin
  7370. zSig0Ptr := aSig1 shl shiftCount;
  7371. zSig1Ptr := 0;
  7372. end;
  7373. zExpPtr := - shiftCount - 63;
  7374. end
  7375. else begin
  7376. shiftCount := countLeadingZeros64( aSig0 ) - 15;
  7377. shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
  7378. zExpPtr := 1 - shiftCount;
  7379. end;
  7380. end;
  7381. {*----------------------------------------------------------------------------
  7382. | Packs the sign `zSign', the exponent `zExp', and the significand formed
  7383. | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
  7384. | floating-point value, returning the result. After being shifted into the
  7385. | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
  7386. | added together to form the most significant 32 bits of the result. This
  7387. | means that any integer portion of `zSig0' will be added into the exponent.
  7388. | Since a properly normalized significand will have an integer portion equal
  7389. | to 1, the `zExp' input should be 1 less than the desired result exponent
  7390. | whenever `zSig0' and `zSig1' concatenated form a complete, normalized
  7391. | significand.
  7392. *----------------------------------------------------------------------------*}
  7393. function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64) : float128;
  7394. var
  7395. z: float128;
  7396. begin
  7397. z.low := zSig1;
  7398. z.high := ( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 48 ) + zSig0;
  7399. result:=z;
  7400. end;
  7401. {*----------------------------------------------------------------------------
  7402. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  7403. | and extended significand formed by the concatenation of `zSig0', `zSig1',
  7404. | and `zSig2', and returns the proper quadruple-precision floating-point value
  7405. | corresponding to the abstract input. Ordinarily, the abstract value is
  7406. | simply rounded and packed into the quadruple-precision format, with the
  7407. | inexact exception raised if the abstract input cannot be represented
  7408. | exactly. However, if the abstract value is too large, the overflow and
  7409. | inexact exceptions are raised and an infinity or maximal finite value is
  7410. | returned. If the abstract value is too small, the input value is rounded to
  7411. | a subnormal number, and the underflow and inexact exceptions are raised if
  7412. | the abstract input cannot be represented exactly as a subnormal quadruple-
  7413. | precision floating-point number.
  7414. | The input significand must be normalized or smaller. If the input
  7415. | significand is not normalized, `zExp' must be 0; in that case, the result
  7416. | returned is a subnormal number, and it must not require rounding. In the
  7417. | usual case that the input significand is normalized, `zExp' must be 1 less
  7418. | than the ``true'' floating-point exponent. The handling of underflow and
  7419. | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  7420. *----------------------------------------------------------------------------*}
  7421. function roundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64; zSig2: bits64): float128;
  7422. var
  7423. roundingMode: TFPURoundingMode;
  7424. roundNearestEven, increment, isTiny: flag;
  7425. begin
  7426. roundingMode := softfloat_rounding_mode;
  7427. roundNearestEven := ord( roundingMode = float_round_nearest_even );
  7428. increment := ord( sbits64(zSig2) < 0 );
  7429. if ( roundNearestEven=0 ) then
  7430. begin
  7431. if ( roundingMode = float_round_to_zero ) then
  7432. begin
  7433. increment := 0;
  7434. end
  7435. else begin
  7436. if ( zSign<>0 ) then
  7437. begin
  7438. increment := ord( roundingMode = float_round_down ) and zSig2;
  7439. end
  7440. else begin
  7441. increment := ord( roundingMode = float_round_up ) and zSig2;
  7442. end;
  7443. end;
  7444. end;
  7445. if ( $7FFD <= bits32(zExp) ) then
  7446. begin
  7447. if ( ord( $7FFD < zExp )
  7448. or ( ord( zExp = $7FFD )
  7449. and eq128(
  7450. int64( $0001FFFFFFFFFFFF ),
  7451. bits64( $FFFFFFFFFFFFFFFF ),
  7452. zSig0,
  7453. zSig1
  7454. )
  7455. and increment
  7456. )
  7457. )<>0 then
  7458. begin
  7459. float_raise( [float_flag_overflow,float_flag_inexact] );
  7460. if ( ord( roundingMode = float_round_to_zero )
  7461. or ( zSign and ord( roundingMode = float_round_up ) )
  7462. or ( ord( zSign = 0) and ord( roundingMode = float_round_down ) )
  7463. )<>0 then
  7464. begin
  7465. result :=
  7466. packFloat128(
  7467. zSign,
  7468. $7FFE,
  7469. int64( $0000FFFFFFFFFFFF ),
  7470. bits64( $FFFFFFFFFFFFFFFF )
  7471. );
  7472. exit;
  7473. end;
  7474. result:=packFloat128( zSign, $7FFF, 0, 0 );
  7475. exit;
  7476. end;
  7477. if ( zExp < 0 ) then
  7478. begin
  7479. isTiny :=
  7480. ord(( softfloat_detect_tininess = float_tininess_before_rounding )
  7481. or ( zExp < -1 )
  7482. or not( increment<>0 )
  7483. or boolean(lt128(
  7484. zSig0,
  7485. zSig1,
  7486. int64( $0001FFFFFFFFFFFF ),
  7487. bits64( $FFFFFFFFFFFFFFFF )
  7488. )));
  7489. shift128ExtraRightJamming(
  7490. zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
  7491. zExp := 0;
  7492. if ( isTiny and zSig2 )<>0 then
  7493. float_raise( float_flag_underflow );
  7494. if ( roundNearestEven<>0 ) then
  7495. begin
  7496. increment := ord( sbits64(zSig2) < 0 );
  7497. end
  7498. else begin
  7499. if ( zSign<>0 ) then
  7500. begin
  7501. increment := ord( roundingMode = float_round_down ) and zSig2;
  7502. end
  7503. else begin
  7504. increment := ord( roundingMode = float_round_up ) and zSig2;
  7505. end;
  7506. end;
  7507. end;
  7508. end;
  7509. if ( zSig2<>0 ) then
  7510. set_inexact_flag;
  7511. if ( increment<>0 ) then
  7512. begin
  7513. add128( zSig0, zSig1, 0, 1, zSig0, zSig1 );
  7514. zSig1 := zSig1 and not bits64( ord( zSig2 + zSig2 = 0 ) and roundNearestEven );
  7515. end
  7516. else begin
  7517. if ( ( zSig0 or zSig1 ) = 0 ) then
  7518. zExp := 0;
  7519. end;
  7520. result:=packFloat128( zSign, zExp, zSig0, zSig1 );
  7521. end;
  7522. {*----------------------------------------------------------------------------
  7523. | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
  7524. | and significand formed by the concatenation of `zSig0' and `zSig1', and
  7525. | returns the proper quadruple-precision floating-point value corresponding
  7526. | to the abstract input. This routine is just like `roundAndPackFloat128'
  7527. | except that the input significand has fewer bits and does not have to be
  7528. | normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
  7529. | point exponent.
  7530. *----------------------------------------------------------------------------*}
  7531. function normalizeRoundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): float128;
  7532. var
  7533. shiftCount: int8;
  7534. zSig2: bits64;
  7535. begin
  7536. if ( zSig0 = 0 ) then
  7537. begin
  7538. zSig0 := zSig1;
  7539. zSig1 := 0;
  7540. dec(zExp, 64);
  7541. end;
  7542. shiftCount := countLeadingZeros64( zSig0 ) - 15;
  7543. if ( 0 <= shiftCount ) then
  7544. begin
  7545. zSig2 := 0;
  7546. shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
  7547. end
  7548. else begin
  7549. shift128ExtraRightJamming(
  7550. zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
  7551. end;
  7552. dec(zExp, shiftCount);
  7553. result:=roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  7554. end;
  7555. {*----------------------------------------------------------------------------
  7556. | Returns the result of converting the quadruple-precision floating-point
  7557. | value `a' to the 32-bit two's complement integer format. The conversion
  7558. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7559. | Arithmetic---which means in particular that the conversion is rounded
  7560. | according to the current rounding mode. If `a' is a NaN, the largest
  7561. | positive integer is returned. Otherwise, if the conversion overflows, the
  7562. | largest integer with the same sign as `a' is returned.
  7563. *----------------------------------------------------------------------------*}
  7564. function float128_to_int32(a: float128): int32;
  7565. var
  7566. aSign: flag;
  7567. aExp, shiftCount: int32;
  7568. aSig0, aSig1: bits64;
  7569. begin
  7570. aSig1 := extractFloat128Frac1( a );
  7571. aSig0 := extractFloat128Frac0( a );
  7572. aExp := extractFloat128Exp( a );
  7573. aSign := extractFloat128Sign( a );
  7574. if ( ord( aExp = $7FFF ) and ( aSig0 or aSig1 ) )<>0 then
  7575. aSign := 0;
  7576. if ( aExp<>0 ) then
  7577. aSig0 := aSig0 or int64( $0001000000000000 );
  7578. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7579. shiftCount := $4028 - aExp;
  7580. if ( 0 < shiftCount ) then
  7581. shift64RightJamming( aSig0, shiftCount, aSig0 );
  7582. result := roundAndPackInt32( aSign, aSig0 );
  7583. end;
  7584. {*----------------------------------------------------------------------------
  7585. | Returns the result of converting the quadruple-precision floating-point
  7586. | value `a' to the 32-bit two's complement integer format. The conversion
  7587. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7588. | Arithmetic, except that the conversion is always rounded toward zero. If
  7589. | `a' is a NaN, the largest positive integer is returned. Otherwise, if the
  7590. | conversion overflows, the largest integer with the same sign as `a' is
  7591. | returned.
  7592. *----------------------------------------------------------------------------*}
  7593. function float128_to_int32_round_to_zero(a: float128): int32;
  7594. var
  7595. aSign: flag;
  7596. aExp, shiftCount: int32;
  7597. aSig0, aSig1, savedASig: bits64;
  7598. z: int32;
  7599. label
  7600. invalid;
  7601. begin
  7602. aSig1 := extractFloat128Frac1( a );
  7603. aSig0 := extractFloat128Frac0( a );
  7604. aExp := extractFloat128Exp( a );
  7605. aSign := extractFloat128Sign( a );
  7606. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7607. if ( $401E < aExp ) then
  7608. begin
  7609. if ( ord( aExp = $7FFF ) and aSig0 )<>0 then
  7610. aSign := 0;
  7611. goto invalid;
  7612. end
  7613. else if ( aExp < $3FFF ) then
  7614. begin
  7615. if ( aExp or aSig0 )<>0 then
  7616. set_inexact_flag;
  7617. result := 0;
  7618. exit;
  7619. end;
  7620. aSig0 := aSig0 or int64( $0001000000000000 );
  7621. shiftCount := $402F - aExp;
  7622. savedASig := aSig0;
  7623. aSig0 := aSig0 shr shiftCount;
  7624. z := aSig0;
  7625. if ( aSign )<>0 then
  7626. z := - z;
  7627. if ( ord( z < 0 ) xor aSign )<>0 then
  7628. begin
  7629. invalid:
  7630. float_raise( float_flag_invalid );
  7631. if aSign<>0 then
  7632. result:= int32( $80000000 )
  7633. else
  7634. result:=$7FFFFFFF;
  7635. exit;
  7636. end;
  7637. if ( ( aSig0 shl shiftCount ) <> savedASig ) then
  7638. begin
  7639. set_inexact_flag;
  7640. end;
  7641. result := z;
  7642. end;
  7643. {*----------------------------------------------------------------------------
  7644. | Returns the result of converting the quadruple-precision floating-point
  7645. | value `a' to the 64-bit two's complement integer format. The conversion
  7646. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7647. | Arithmetic---which means in particular that the conversion is rounded
  7648. | according to the current rounding mode. If `a' is a NaN, the largest
  7649. | positive integer is returned. Otherwise, if the conversion overflows, the
  7650. | largest integer with the same sign as `a' is returned.
  7651. *----------------------------------------------------------------------------*}
  7652. function float128_to_int64(a: float128): int64;
  7653. var
  7654. aSign: flag;
  7655. aExp, shiftCount: int32;
  7656. aSig0, aSig1: bits64;
  7657. begin
  7658. aSig1 := extractFloat128Frac1( a );
  7659. aSig0 := extractFloat128Frac0( a );
  7660. aExp := extractFloat128Exp( a );
  7661. aSign := extractFloat128Sign( a );
  7662. if ( aExp<>0 ) then
  7663. aSig0 := aSig0 or int64( $0001000000000000 );
  7664. shiftCount := $402F - aExp;
  7665. if ( shiftCount <= 0 ) then
  7666. begin
  7667. if ( $403E < aExp ) then
  7668. begin
  7669. float_raise( float_flag_invalid );
  7670. if ( (aSign=0)
  7671. or ( ( aExp = $7FFF )
  7672. and ( (aSig1<>0) or ( aSig0 <> int64( $0001000000000000 ) ) )
  7673. )
  7674. ) then
  7675. begin
  7676. result := int64( $7FFFFFFFFFFFFFFF );
  7677. exit;
  7678. end;
  7679. result := int64( $8000000000000000 );
  7680. exit;
  7681. end;
  7682. shortShift128Left( aSig0, aSig1, - shiftCount, aSig0, aSig1 );
  7683. end
  7684. else begin
  7685. shift64ExtraRightJamming( aSig0, aSig1, shiftCount, aSig0, aSig1 );
  7686. end;
  7687. result := roundAndPackInt64( aSign, aSig0, aSig1 );
  7688. end;
  7689. {*----------------------------------------------------------------------------
  7690. | Returns the result of converting the quadruple-precision floating-point
  7691. | value `a' to the 64-bit two's complement integer format. The conversion
  7692. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7693. | Arithmetic, except that the conversion is always rounded toward zero.
  7694. | If `a' is a NaN, the largest positive integer is returned. Otherwise, if
  7695. | the conversion overflows, the largest integer with the same sign as `a' is
  7696. | returned.
  7697. *----------------------------------------------------------------------------*}
  7698. function float128_to_int64_round_to_zero(a: float128): int64;
  7699. var
  7700. aSign: flag;
  7701. aExp, shiftCount: int32;
  7702. aSig0, aSig1: bits64;
  7703. z: int64;
  7704. begin
  7705. aSig1 := extractFloat128Frac1( a );
  7706. aSig0 := extractFloat128Frac0( a );
  7707. aExp := extractFloat128Exp( a );
  7708. aSign := extractFloat128Sign( a );
  7709. if ( aExp<>0 ) then
  7710. aSig0 := aSig0 or int64( $0001000000000000 );
  7711. shiftCount := aExp - $402F;
  7712. if ( 0 < shiftCount ) then
  7713. begin
  7714. if ( $403E <= aExp ) then
  7715. begin
  7716. aSig0 := aSig0 and int64( $0000FFFFFFFFFFFF );
  7717. if ( ( a.high = bits64( $C03E000000000000 ) )
  7718. and ( aSig1 < int64( $0002000000000000 ) ) ) then
  7719. begin
  7720. if ( aSig1<>0 ) then
  7721. set_inexact_flag;
  7722. end
  7723. else begin
  7724. float_raise( float_flag_invalid );
  7725. if ( (aSign=0) or ( ( aExp = $7FFF ) and (( aSig0 or aSig1 )<>0) ) ) then
  7726. begin
  7727. result := int64( $7FFFFFFFFFFFFFFF );
  7728. exit;
  7729. end;
  7730. end;
  7731. result := int64( $8000000000000000 );
  7732. exit;
  7733. end;
  7734. z := ( aSig0 shl shiftCount ) or ( aSig1 shr ( ( - shiftCount ) and 63 ) );
  7735. if ( int64( aSig1 shl shiftCount )<>0 ) then
  7736. begin
  7737. set_inexact_flag;
  7738. end;
  7739. end
  7740. else begin
  7741. if ( aExp < $3FFF ) then
  7742. begin
  7743. if ( aExp or aSig0 or aSig1 )<>0 then
  7744. begin
  7745. set_inexact_flag;
  7746. end;
  7747. result := 0;
  7748. exit;
  7749. end;
  7750. z := aSig0 shr ( - shiftCount );
  7751. if ( (aSig1<>0)
  7752. or ( (shiftCount<>0) and (int64( aSig0 shl ( shiftCount and 63 ) )<>0) ) ) then
  7753. begin
  7754. set_inexact_flag;
  7755. end;
  7756. end;
  7757. if ( aSign<>0 ) then
  7758. z := - z;
  7759. result := z;
  7760. end;
  7761. {*----------------------------------------------------------------------------
  7762. | Returns the result of converting the quadruple-precision floating-point
  7763. | value `a' to the single-precision floating-point format. The conversion
  7764. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7765. | Arithmetic.
  7766. *----------------------------------------------------------------------------*}
  7767. function float128_to_float32(a: float128): float32;
  7768. var
  7769. aSign: flag;
  7770. aExp: int32;
  7771. aSig0, aSig1: bits64;
  7772. zSig: bits32;
  7773. begin
  7774. aSig1 := extractFloat128Frac1( a );
  7775. aSig0 := extractFloat128Frac0( a );
  7776. aExp := extractFloat128Exp( a );
  7777. aSign := extractFloat128Sign( a );
  7778. if ( aExp = $7FFF ) then
  7779. begin
  7780. if ( aSig0 or aSig1 )<>0 then
  7781. begin
  7782. result := commonNaNToFloat32( float128ToCommonNaN( a ) );
  7783. exit;
  7784. end;
  7785. result := packFloat32( aSign, $FF, 0 );
  7786. exit;
  7787. end;
  7788. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7789. shift64RightJamming( aSig0, 18, aSig0 );
  7790. zSig := aSig0;
  7791. if ( aExp<>0 ) or (aSig0 <> 0 ) then
  7792. begin
  7793. zSig := zSig or $40000000;
  7794. dec(aExp,$3F81);
  7795. end;
  7796. result := roundAndPackFloat32( aSign, aExp, zSig );
  7797. end;
  7798. {*----------------------------------------------------------------------------
  7799. | Returns the result of converting the quadruple-precision floating-point
  7800. | value `a' to the double-precision floating-point format. The conversion
  7801. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  7802. | Arithmetic.
  7803. *----------------------------------------------------------------------------*}
  7804. function float128_to_float64(a: float128): float64;
  7805. var
  7806. aSign: flag;
  7807. aExp: int32;
  7808. aSig0, aSig1: bits64;
  7809. begin
  7810. aSig1 := extractFloat128Frac1( a );
  7811. aSig0 := extractFloat128Frac0( a );
  7812. aExp := extractFloat128Exp( a );
  7813. aSign := extractFloat128Sign( a );
  7814. if ( aExp = $7FFF ) then
  7815. begin
  7816. if ( aSig0 or aSig1 )<>0 then
  7817. begin
  7818. result:=commonNaNToFloat64(float128ToCommonNaN(a));
  7819. exit;
  7820. end;
  7821. result:=packFloat64( aSign, $7FF, 0);
  7822. exit;
  7823. end;
  7824. shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );
  7825. aSig0 := aSig0 or ord( aSig1 <> 0 );
  7826. if ( aExp<>0 ) or (aSig0 <> 0 ) then
  7827. begin
  7828. aSig0 := aSig0 or int64( $4000000000000000 );
  7829. dec(aExp,$3C01);
  7830. end;
  7831. result := roundAndPackFloat64( aSign, aExp, aSig0 );
  7832. end;
  7833. {$ifdef FPC_SOFTFLOAT_FLOATX80}
  7834. {*----------------------------------------------------------------------------
  7835. | Returns the result of converting the quadruple-precision floating-point
  7836. | value `a' to the extended double-precision floating-point format. The
  7837. | conversion is performed according to the IEC/IEEE Standard for Binary
  7838. | Floating-Point Arithmetic.
  7839. *----------------------------------------------------------------------------*}
  7840. function float128_to_floatx80(a: float128): floatx80;
  7841. var
  7842. aSign: flag;
  7843. aExp: int32;
  7844. aSig0, aSig1: bits64;
  7845. begin
  7846. aSig1 := extractFloat128Frac1( a );
  7847. aSig0 := extractFloat128Frac0( a );
  7848. aExp := extractFloat128Exp( a );
  7849. aSign := extractFloat128Sign( a );
  7850. if ( aExp = $7FFF ) then begin
  7851. if ( aSig0 or aSig1 <> 0 ) then begin
  7852. result := commonNaNToFloatx80( float128ToCommonNaN( a ) );
  7853. exit;
  7854. end;
  7855. result := packFloatx80( aSign, $7FFF, bits64( $8000000000000000 ) );
  7856. exit;
  7857. end;
  7858. if ( aExp = 0 ) then begin
  7859. if ( ( aSig0 or aSig1 ) = 0 ) then
  7860. begin
  7861. result := packFloatx80( aSign, 0, 0 );
  7862. exit;
  7863. end;
  7864. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  7865. end
  7866. else begin
  7867. aSig0 := aSig0 or int64( $0001000000000000 );
  7868. end;
  7869. shortShift128Left( aSig0, aSig1, 15, aSig0, aSig1 );
  7870. result := roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );
  7871. end;
  7872. {$endif FPC_SOFTFLOAT_FLOATX80}
  7873. {*----------------------------------------------------------------------------
  7874. | Rounds the quadruple-precision floating-point value `a' to an integer, and
  7875. | Returns the result as a quadruple-precision floating-point value. The
  7876. | operation is performed according to the IEC/IEEE Standard for Binary
  7877. | Floating-Point Arithmetic.
  7878. *----------------------------------------------------------------------------*}
  7879. function float128_round_to_int(a: float128): float128;
  7880. var
  7881. aSign: flag;
  7882. aExp: int32;
  7883. lastBitMask, roundBitsMask: bits64;
  7884. roundingMode: TFPURoundingMode;
  7885. z: float128;
  7886. begin
  7887. aExp := extractFloat128Exp( a );
  7888. if ( $402F <= aExp ) then
  7889. begin
  7890. if ( $406F <= aExp ) then
  7891. begin
  7892. if ( ( aExp = $7FFF )
  7893. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) )<>0)
  7894. ) then
  7895. begin
  7896. result := propagateFloat128NaN( a, a );
  7897. exit;
  7898. end;
  7899. result := a;
  7900. exit;
  7901. end;
  7902. lastBitMask := 1;
  7903. lastBitMask := ( lastBitMask shl ( $406E - aExp ) ) shl 1;
  7904. roundBitsMask := lastBitMask - 1;
  7905. z := a;
  7906. roundingMode := softfloat_rounding_mode;
  7907. if ( roundingMode = float_round_nearest_even ) then
  7908. begin
  7909. if ( lastBitMask )<>0 then
  7910. begin
  7911. add128( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
  7912. if ( ( z.low and roundBitsMask ) = 0 ) then
  7913. z.low := z.low and not(lastBitMask);
  7914. end
  7915. else begin
  7916. if ( sbits64(z.low) < 0 ) then
  7917. begin
  7918. inc(z.high);
  7919. if ( bits64( z.low shl 1 ) = 0 ) then
  7920. z.high := z.high and not bits64( 1 );
  7921. end;
  7922. end;
  7923. end
  7924. else if ( roundingMode <> float_round_to_zero ) then
  7925. begin
  7926. if ( extractFloat128Sign( z )
  7927. xor ord( roundingMode = float_round_up ) )<>0 then
  7928. begin
  7929. add128( z.high, z.low, 0, roundBitsMask, z.high, z.low );
  7930. end;
  7931. end;
  7932. z.low := z.low and not(roundBitsMask);
  7933. end
  7934. else begin
  7935. if ( aExp < $3FFF ) then
  7936. begin
  7937. if ( ( ( bits64( a.high shl 1 ) ) or a.low ) = 0 ) then
  7938. begin
  7939. result := a;
  7940. exit;
  7941. end;
  7942. set_inexact_flag;
  7943. aSign := extractFloat128Sign( a );
  7944. case softfloat_rounding_mode of
  7945. float_round_nearest_even:
  7946. if ( ( aExp = $3FFE )
  7947. and ( (extractFloat128Frac0( a )<>0)
  7948. or (extractFloat128Frac1( a )<>0) )
  7949. ) then begin
  7950. begin
  7951. result := packFloat128( aSign, $3FFF, 0, 0 );
  7952. exit;
  7953. end;
  7954. end;
  7955. float_round_down:
  7956. begin
  7957. if aSign<>0 then
  7958. result:=packFloat128( 1, $3FFF, 0, 0 )
  7959. else
  7960. result:=packFloat128( 0, 0, 0, 0 );
  7961. exit;
  7962. end;
  7963. float_round_up:
  7964. begin
  7965. if aSign<>0 then
  7966. result := packFloat128( 1, 0, 0, 0 )
  7967. else
  7968. result:=packFloat128( 0, $3FFF, 0, 0 );
  7969. exit;
  7970. end;
  7971. end;
  7972. result := packFloat128( aSign, 0, 0, 0 );
  7973. exit;
  7974. end;
  7975. lastBitMask := 1;
  7976. lastBitMask := lastBitMask shl ($402F - aExp);
  7977. roundBitsMask := lastBitMask - 1;
  7978. z.low := 0;
  7979. z.high := a.high;
  7980. roundingMode := softfloat_rounding_mode;
  7981. if ( roundingMode = float_round_nearest_even ) then begin
  7982. inc(z.high,lastBitMask shr 1);
  7983. if ( ( ( z.high and roundBitsMask ) or a.low ) = 0 ) then begin
  7984. z.high := z.high and not(lastBitMask);
  7985. end;
  7986. end
  7987. else if ( roundingMode <> float_round_to_zero ) then begin
  7988. if ( (extractFloat128Sign( z )<>0)
  7989. xor ( roundingMode = float_round_up ) ) then begin
  7990. z.high := z.high or ord( a.low <> 0 );
  7991. z.high := z.high+roundBitsMask;
  7992. end;
  7993. end;
  7994. z.high := z.high and not(roundBitsMask);
  7995. end;
  7996. if ( ( z.low <> a.low ) or ( z.high <> a.high ) ) then begin
  7997. set_inexact_flag;
  7998. end;
  7999. result := z;
  8000. end;
  8001. {*----------------------------------------------------------------------------
  8002. | Returns the result of adding the absolute values of the quadruple-precision
  8003. | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
  8004. | before being returned. `zSign' is ignored if the result is a NaN.
  8005. | The addition is performed according to the IEC/IEEE Standard for Binary
  8006. | Floating-Point Arithmetic.
  8007. *----------------------------------------------------------------------------*}
  8008. function addFloat128Sigs(a,b : float128; zSign : flag ): float128;
  8009. var
  8010. aExp, bExp, zExp: int32;
  8011. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
  8012. expDiff: int32;
  8013. label
  8014. shiftRight1,roundAndPack;
  8015. begin
  8016. aSig1 := extractFloat128Frac1( a );
  8017. aSig0 := extractFloat128Frac0( a );
  8018. aExp := extractFloat128Exp( a );
  8019. bSig1 := extractFloat128Frac1( b );
  8020. bSig0 := extractFloat128Frac0( b );
  8021. bExp := extractFloat128Exp( b );
  8022. expDiff := aExp - bExp;
  8023. if ( 0 < expDiff ) then begin
  8024. if ( aExp = $7FFF ) then begin
  8025. if ( aSig0 or aSig1 )<>0 then
  8026. begin
  8027. result := propagateFloat128NaN( a, b );
  8028. exit;
  8029. end;
  8030. result := a;
  8031. exit;
  8032. end;
  8033. if ( bExp = 0 ) then begin
  8034. dec(expDiff);
  8035. end
  8036. else begin
  8037. bSig0 := bSig0 or int64( $0001000000000000 );
  8038. end;
  8039. shift128ExtraRightJamming(
  8040. bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
  8041. zExp := aExp;
  8042. end
  8043. else if ( expDiff < 0 ) then begin
  8044. if ( bExp = $7FFF ) then begin
  8045. if ( bSig0 or bSig1 )<>0 then
  8046. begin
  8047. result := propagateFloat128NaN( a, b );
  8048. exit;
  8049. end;
  8050. result := packFloat128( zSign, $7FFF, 0, 0 );
  8051. exit;
  8052. end;
  8053. if ( aExp = 0 ) then begin
  8054. inc(expDiff);
  8055. end
  8056. else begin
  8057. aSig0 := aSig0 or int64( $0001000000000000 );
  8058. end;
  8059. shift128ExtraRightJamming(
  8060. aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
  8061. zExp := bExp;
  8062. end
  8063. else begin
  8064. if ( aExp = $7FFF ) then begin
  8065. if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin
  8066. result := propagateFloat128NaN( a, b );
  8067. exit;
  8068. end;
  8069. result := a;
  8070. exit;
  8071. end;
  8072. add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  8073. if ( aExp = 0 ) then
  8074. begin
  8075. result := packFloat128( zSign, 0, zSig0, zSig1 );
  8076. exit;
  8077. end;
  8078. zSig2 := 0;
  8079. zSig0 := zSig0 or int64( $0002000000000000 );
  8080. zExp := aExp;
  8081. goto shiftRight1;
  8082. end;
  8083. aSig0 := aSig0 or int64( $0001000000000000 );
  8084. add128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  8085. dec(zExp);
  8086. if ( zSig0 < int64( $0002000000000000 ) ) then goto roundAndPack;
  8087. inc(zExp);
  8088. shiftRight1:
  8089. shift128ExtraRightJamming(
  8090. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  8091. roundAndPack:
  8092. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  8093. end;
  8094. {*----------------------------------------------------------------------------
  8095. | Returns the result of subtracting the absolute values of the quadruple-
  8096. | precision floating-point values `a' and `b'. If `zSign' is 1, the
  8097. | difference is negated before being returned. `zSign' is ignored if the
  8098. | result is a NaN. The subtraction is performed according to the IEC/IEEE
  8099. | Standard for Binary Floating-Point Arithmetic.
  8100. *----------------------------------------------------------------------------*}
  8101. function subFloat128Sigs( a, b : float128; zSign : flag): float128;
  8102. var
  8103. aExp, bExp, zExp: int32;
  8104. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits64;
  8105. expDiff: int32;
  8106. z: float128;
  8107. label
  8108. aExpBigger,bExpBigger,aBigger,bBigger,normalizeRoundAndPack;
  8109. begin
  8110. aSig1 := extractFloat128Frac1( a );
  8111. aSig0 := extractFloat128Frac0( a );
  8112. aExp := extractFloat128Exp( a );
  8113. bSig1 := extractFloat128Frac1( b );
  8114. bSig0 := extractFloat128Frac0( b );
  8115. bExp := extractFloat128Exp( b );
  8116. expDiff := aExp - bExp;
  8117. shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );
  8118. shortShift128Left( bSig0, bSig1, 14, bSig0, bSig1 );
  8119. if ( 0 < expDiff ) then goto aExpBigger;
  8120. if ( expDiff < 0 ) then goto bExpBigger;
  8121. if ( aExp = $7FFF ) then begin
  8122. if ( aSig0 or aSig1 or bSig0 or bSig1 )<>0 then begin
  8123. result := propagateFloat128NaN( a, b );
  8124. exit;
  8125. end;
  8126. float_raise( float_flag_invalid );
  8127. z.low := float128_default_nan_low;
  8128. z.high := float128_default_nan_high;
  8129. result := z;
  8130. exit;
  8131. end;
  8132. if ( aExp = 0 ) then begin
  8133. aExp := 1;
  8134. bExp := 1;
  8135. end;
  8136. if ( bSig0 < aSig0 ) then goto aBigger;
  8137. if ( aSig0 < bSig0 ) then goto bBigger;
  8138. if ( bSig1 < aSig1 ) then goto aBigger;
  8139. if ( aSig1 < bSig1 ) then goto bBigger;
  8140. result := packFloat128( ord(softfloat_rounding_mode = float_round_down), 0, 0, 0 );
  8141. exit;
  8142. bExpBigger:
  8143. if ( bExp = $7FFF ) then begin
  8144. if ( bSig0 or bSig1 )<>0 then
  8145. begin
  8146. result := propagateFloat128NaN( a, b );
  8147. exit;
  8148. end;
  8149. result := packFloat128( zSign xor 1, $7FFF, 0, 0 );
  8150. exit;
  8151. end;
  8152. if ( aExp = 0 ) then begin
  8153. inc(expDiff);
  8154. end
  8155. else begin
  8156. aSig0 := aSig0 or int64( $4000000000000000 );
  8157. end;
  8158. shift128RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  8159. bSig0 := bSig0 or int64( $4000000000000000 );
  8160. bBigger:
  8161. sub128( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
  8162. zExp := bExp;
  8163. zSign := zSign xor 1;
  8164. goto normalizeRoundAndPack;
  8165. aExpBigger:
  8166. if ( aExp = $7FFF ) then begin
  8167. if ( aSig0 or aSig1 )<>0 then
  8168. begin
  8169. result := propagateFloat128NaN( a, b );
  8170. exit;
  8171. end;
  8172. result := a;
  8173. exit;
  8174. end;
  8175. if ( bExp = 0 ) then begin
  8176. dec(expDiff);
  8177. end
  8178. else begin
  8179. bSig0 := bSig0 or int64( $4000000000000000 );
  8180. end;
  8181. shift128RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
  8182. aSig0 := aSig0 or int64( $4000000000000000 );
  8183. aBigger:
  8184. sub128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
  8185. zExp := aExp;
  8186. normalizeRoundAndPack:
  8187. dec(zExp);
  8188. result := normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );
  8189. end;
  8190. {*----------------------------------------------------------------------------
  8191. | Returns the result of adding the quadruple-precision floating-point values
  8192. | `a' and `b'. The operation is performed according to the IEC/IEEE Standard
  8193. | for Binary Floating-Point Arithmetic.
  8194. *----------------------------------------------------------------------------*}
  8195. function float128_add(a: float128; b: float128): float128;
  8196. var
  8197. aSign, bSign: flag;
  8198. begin
  8199. aSign := extractFloat128Sign( a );
  8200. bSign := extractFloat128Sign( b );
  8201. if ( aSign = bSign ) then begin
  8202. result := addFloat128Sigs( a, b, aSign );
  8203. end
  8204. else begin
  8205. result := subFloat128Sigs( a, b, aSign );
  8206. end;
  8207. end;
  8208. {*----------------------------------------------------------------------------
  8209. | Returns the result of subtracting the quadruple-precision floating-point
  8210. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  8211. | Standard for Binary Floating-Point Arithmetic.
  8212. *----------------------------------------------------------------------------*}
  8213. function float128_sub(a: float128; b: float128): float128;
  8214. var
  8215. aSign, bSign: flag;
  8216. begin
  8217. aSign := extractFloat128Sign( a );
  8218. bSign := extractFloat128Sign( b );
  8219. if ( aSign = bSign ) then begin
  8220. result := subFloat128Sigs( a, b, aSign );
  8221. end
  8222. else begin
  8223. result := addFloat128Sigs( a, b, aSign );
  8224. end;
  8225. end;
  8226. {*----------------------------------------------------------------------------
  8227. | Returns the result of multiplying the quadruple-precision floating-point
  8228. | values `a' and `b'. The operation is performed according to the IEC/IEEE
  8229. | Standard for Binary Floating-Point Arithmetic.
  8230. *----------------------------------------------------------------------------*}
  8231. function float128_mul(a: float128; b: float128): float128;
  8232. var
  8233. aSign, bSign, zSign: flag;
  8234. aExp, bExp, zExp: int32;
  8235. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits64;
  8236. z: float128;
  8237. label
  8238. invalid;
  8239. begin
  8240. aSig1 := extractFloat128Frac1( a );
  8241. aSig0 := extractFloat128Frac0( a );
  8242. aExp := extractFloat128Exp( a );
  8243. aSign := extractFloat128Sign( a );
  8244. bSig1 := extractFloat128Frac1( b );
  8245. bSig0 := extractFloat128Frac0( b );
  8246. bExp := extractFloat128Exp( b );
  8247. bSign := extractFloat128Sign( b );
  8248. zSign := aSign xor bSign;
  8249. if ( aExp = $7FFF ) then begin
  8250. if ( (( aSig0 or aSig1 )<>0)
  8251. or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin
  8252. result := propagateFloat128NaN( a, b );
  8253. exit;
  8254. end;
  8255. if ( ( bExp or bSig0 or bSig1 ) = 0 ) then goto invalid;
  8256. result := packFloat128( zSign, $7FFF, 0, 0 );
  8257. exit;
  8258. end;
  8259. if ( bExp = $7FFF ) then begin
  8260. if ( bSig0 or bSig1 )<>0 then
  8261. begin
  8262. result := propagateFloat128NaN( a, b );
  8263. exit;
  8264. end;
  8265. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin
  8266. invalid:
  8267. float_raise( float_flag_invalid );
  8268. z.low := float128_default_nan_low;
  8269. z.high := float128_default_nan_high;
  8270. result := z;
  8271. exit;
  8272. end;
  8273. result := packFloat128( zSign, $7FFF, 0, 0 );
  8274. exit;
  8275. end;
  8276. if ( aExp = 0 ) then begin
  8277. if ( ( aSig0 or aSig1 ) = 0 ) then
  8278. begin
  8279. result := packFloat128( zSign, 0, 0, 0 );
  8280. exit;
  8281. end;
  8282. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8283. end;
  8284. if ( bExp = 0 ) then begin
  8285. if ( ( bSig0 or bSig1 ) = 0 ) then
  8286. begin
  8287. result := packFloat128( zSign, 0, 0, 0 );
  8288. exit;
  8289. end;
  8290. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  8291. end;
  8292. zExp := aExp + bExp - $4000;
  8293. aSig0 := aSig0 or int64( $0001000000000000 );
  8294. shortShift128Left( bSig0, bSig1, 16, bSig0, bSig1 );
  8295. mul128To256( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
  8296. add128( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
  8297. zSig2 := zSig2 or ord( zSig3 <> 0 );
  8298. if ( int64( $0002000000000000 ) <= zSig0 ) then begin
  8299. shift128ExtraRightJamming(
  8300. zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
  8301. inc(zExp);
  8302. end;
  8303. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  8304. end;
  8305. {*----------------------------------------------------------------------------
  8306. | Returns the result of dividing the quadruple-precision floating-point value
  8307. | `a' by the corresponding value `b'. The operation is performed according to
  8308. | the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8309. *----------------------------------------------------------------------------*}
  8310. function float128_div(a: float128; b: float128): float128;
  8311. var
  8312. aSign, bSign, zSign: flag;
  8313. aExp, bExp, zExp: int32;
  8314. aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
  8315. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  8316. z: float128;
  8317. label
  8318. invalid;
  8319. begin
  8320. aSig1 := extractFloat128Frac1( a );
  8321. aSig0 := extractFloat128Frac0( a );
  8322. aExp := extractFloat128Exp( a );
  8323. aSign := extractFloat128Sign( a );
  8324. bSig1 := extractFloat128Frac1( b );
  8325. bSig0 := extractFloat128Frac0( b );
  8326. bExp := extractFloat128Exp( b );
  8327. bSign := extractFloat128Sign( b );
  8328. zSign := aSign xor bSign;
  8329. if ( aExp = $7FFF ) then begin
  8330. if ( aSig0 or aSig1 )<>0 then
  8331. begin
  8332. result := propagateFloat128NaN( a, b );
  8333. exit;
  8334. end;
  8335. if ( bExp = $7FFF ) then begin
  8336. if ( bSig0 or bSig1 )<>0 then
  8337. begin
  8338. result := propagateFloat128NaN( a, b );
  8339. exit;
  8340. end;
  8341. goto invalid;
  8342. end;
  8343. result := packFloat128( zSign, $7FFF, 0, 0 );
  8344. exit;
  8345. end;
  8346. if ( bExp = $7FFF ) then begin
  8347. if ( bSig0 or bSig1 )<>0 then
  8348. begin
  8349. result := propagateFloat128NaN( a, b );
  8350. exit;
  8351. end;
  8352. result := packFloat128( zSign, 0, 0, 0 );
  8353. exit;
  8354. end;
  8355. if ( bExp = 0 ) then begin
  8356. if ( ( bSig0 or bSig1 ) = 0 ) then begin
  8357. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then begin
  8358. invalid:
  8359. float_raise( float_flag_invalid );
  8360. z.low := float128_default_nan_low;
  8361. z.high := float128_default_nan_high;
  8362. result := z;
  8363. exit;
  8364. end;
  8365. float_raise( float_flag_divbyzero );
  8366. result := packFloat128( zSign, $7FFF, 0, 0 );
  8367. exit;
  8368. end;
  8369. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  8370. end;
  8371. if ( aExp = 0 ) then begin
  8372. if ( ( aSig0 or aSig1 ) = 0 ) then
  8373. begin
  8374. result := packFloat128( zSign, 0, 0, 0 );
  8375. exit;
  8376. end;
  8377. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8378. end;
  8379. zExp := aExp - bExp + $3FFD;
  8380. shortShift128Left(
  8381. aSig0 or int64( $0001000000000000 ), aSig1, 15, aSig0, aSig1 );
  8382. shortShift128Left(
  8383. bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );
  8384. if ( le128( bSig0, bSig1, aSig0, aSig1 )<>0 ) then begin
  8385. shift128Right( aSig0, aSig1, 1, aSig0, aSig1 );
  8386. inc(zExp);
  8387. end;
  8388. zSig0 := estimateDiv128To64( aSig0, aSig1, bSig0 );
  8389. mul128By64To192( bSig0, bSig1, zSig0, term0, term1, term2 );
  8390. sub192( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
  8391. while ( sbits64(rem0) < 0 ) do begin
  8392. dec(zSig0);
  8393. add192( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
  8394. end;
  8395. zSig1 := estimateDiv128To64( rem1, rem2, bSig0 );
  8396. if ( ( zSig1 and $3FFF ) <= 4 ) then begin
  8397. mul128By64To192( bSig0, bSig1, zSig1, term1, term2, term3 );
  8398. sub192( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
  8399. while ( sbits64(rem1) < 0 ) do begin
  8400. dec(zSig1);
  8401. add192( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
  8402. end;
  8403. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  8404. end;
  8405. shift128ExtraRightJamming( zSig0, zSig1, 0, 15, zSig0, zSig1, zSig2 );
  8406. result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
  8407. end;
  8408. {*----------------------------------------------------------------------------
  8409. | Returns the remainder of the quadruple-precision floating-point value `a'
  8410. | with respect to the corresponding value `b'. The operation is performed
  8411. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8412. *----------------------------------------------------------------------------*}
  8413. function float128_rem(a: float128; b: float128): float128;
  8414. var
  8415. aSign, zSign: flag;
  8416. aExp, bExp, expDiff: int32;
  8417. aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits64;
  8418. allZero, alternateASig0, alternateASig1, sigMean1: bits64;
  8419. sigMean0: sbits64;
  8420. z: float128;
  8421. label
  8422. invalid;
  8423. begin
  8424. aSig1 := extractFloat128Frac1( a );
  8425. aSig0 := extractFloat128Frac0( a );
  8426. aExp := extractFloat128Exp( a );
  8427. aSign := extractFloat128Sign( a );
  8428. bSig1 := extractFloat128Frac1( b );
  8429. bSig0 := extractFloat128Frac0( b );
  8430. bExp := extractFloat128Exp( b );
  8431. if ( aExp = $7FFF ) then begin
  8432. if ( (( aSig0 or aSig1 )<>0)
  8433. or ( ( bExp = $7FFF ) and (( bSig0 or bSig1 )<>0) ) ) then begin
  8434. result := propagateFloat128NaN( a, b );
  8435. exit;
  8436. end;
  8437. goto invalid;
  8438. end;
  8439. if ( bExp = $7FFF ) then begin
  8440. if ( bSig0 or bSig1 )<>0 then
  8441. begin
  8442. result := propagateFloat128NaN( a, b );
  8443. exit;
  8444. end;
  8445. result := a;
  8446. exit;
  8447. end;
  8448. if ( bExp = 0 ) then begin
  8449. if ( ( bSig0 or bSig1 ) = 0 ) then begin
  8450. invalid:
  8451. float_raise( float_flag_invalid );
  8452. z.low := float128_default_nan_low;
  8453. z.high := float128_default_nan_high;
  8454. result := z;
  8455. exit;
  8456. end;
  8457. normalizeFloat128Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
  8458. end;
  8459. if ( aExp = 0 ) then begin
  8460. if ( ( aSig0 or aSig1 ) = 0 ) then
  8461. begin
  8462. result := a;
  8463. exit;
  8464. end;
  8465. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8466. end;
  8467. expDiff := aExp - bExp;
  8468. if ( expDiff < -1 ) then
  8469. begin
  8470. result := a;
  8471. exit;
  8472. end;
  8473. shortShift128Left(
  8474. aSig0 or int64( $0001000000000000 ),
  8475. aSig1,
  8476. 15 - ord( expDiff < 0 ),
  8477. aSig0,
  8478. aSig1
  8479. );
  8480. shortShift128Left(
  8481. bSig0 or int64( $0001000000000000 ), bSig1, 15, bSig0, bSig1 );
  8482. q := le128( bSig0, bSig1, aSig0, aSig1 );
  8483. if ( q )<>0 then sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  8484. dec(expDiff,64);
  8485. while ( 0 < expDiff ) do begin
  8486. q := estimateDiv128To64( aSig0, aSig1, bSig0 );
  8487. if ( 4 < q ) then
  8488. q := q - 4
  8489. else
  8490. q := 0;
  8491. mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );
  8492. shortShift192Left( term0, term1, term2, 61, term1, term2, allZero );
  8493. shortShift128Left( aSig0, aSig1, 61, aSig0, allZero );
  8494. sub128( aSig0, 0, term1, term2, aSig0, aSig1 );
  8495. dec(expDiff,61);
  8496. end;
  8497. if ( -64 < expDiff ) then begin
  8498. q := estimateDiv128To64( aSig0, aSig1, bSig0 );
  8499. if ( 4 < q ) then
  8500. q := q - 4
  8501. else
  8502. q := 0;
  8503. q := q shr (- expDiff);
  8504. shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );
  8505. inc(expDiff,52);
  8506. if ( expDiff < 0 ) then begin
  8507. shift128Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
  8508. end
  8509. else begin
  8510. shortShift128Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
  8511. end;
  8512. mul128By64To192( bSig0, bSig1, q, term0, term1, term2 );
  8513. sub128( aSig0, aSig1, term1, term2, aSig0, aSig1 );
  8514. end
  8515. else begin
  8516. shift128Right( aSig0, aSig1, 12, aSig0, aSig1 );
  8517. shift128Right( bSig0, bSig1, 12, bSig0, bSig1 );
  8518. end;
  8519. repeat
  8520. alternateASig0 := aSig0;
  8521. alternateASig1 := aSig1;
  8522. inc(q);
  8523. sub128( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
  8524. until not( 0 <= sbits64(aSig0) );
  8525. add128(
  8526. aSig0, aSig1, alternateASig0, alternateASig1, bits64(sigMean0), sigMean1 );
  8527. if ( ( sigMean0 < 0 )
  8528. or ( ( ( sigMean0 or sigMean1 ) = 0 ) and (( q and 1 )<>0) ) ) then begin
  8529. aSig0 := alternateASig0;
  8530. aSig1 := alternateASig1;
  8531. end;
  8532. zSign := ord( sbits64(aSig0) < 0 );
  8533. if ( zSign<>0 ) then sub128( 0, 0, aSig0, aSig1, aSig0, aSig1 );
  8534. result :=
  8535. normalizeRoundAndPackFloat128( aSign xor zSign, bExp - 4, aSig0, aSig1 );
  8536. end;
  8537. {*----------------------------------------------------------------------------
  8538. | Returns the square root of the quadruple-precision floating-point value `a'.
  8539. | The operation is performed according to the IEC/IEEE Standard for Binary
  8540. | Floating-Point Arithmetic.
  8541. *----------------------------------------------------------------------------*}
  8542. function float128_sqrt(a: float128): float128;
  8543. var
  8544. aSign: flag;
  8545. aExp, zExp: int32;
  8546. aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits64;
  8547. rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
  8548. z: float128;
  8549. label
  8550. invalid;
  8551. begin
  8552. aSig1 := extractFloat128Frac1( a );
  8553. aSig0 := extractFloat128Frac0( a );
  8554. aExp := extractFloat128Exp( a );
  8555. aSign := extractFloat128Sign( a );
  8556. if ( aExp = $7FFF ) then begin
  8557. if ( aSig0 or aSig1 )<>0 then
  8558. begin
  8559. result := propagateFloat128NaN( a, a );
  8560. exit;
  8561. end;
  8562. if ( aSign=0 ) then
  8563. begin
  8564. result := a;
  8565. exit;
  8566. end;
  8567. goto invalid;
  8568. end;
  8569. if ( aSign<>0 ) then begin
  8570. if ( ( aExp or aSig0 or aSig1 ) = 0 ) then
  8571. begin
  8572. result := a;
  8573. exit;
  8574. end;
  8575. invalid:
  8576. float_raise( float_flag_invalid );
  8577. z.low := float128_default_nan_low;
  8578. z.high := float128_default_nan_high;
  8579. result := z;
  8580. exit;
  8581. end;
  8582. if ( aExp = 0 ) then begin
  8583. if ( ( aSig0 or aSig1 ) = 0 ) then
  8584. begin
  8585. result := packFloat128( 0, 0, 0, 0 );
  8586. exit;
  8587. end;
  8588. normalizeFloat128Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
  8589. end;
  8590. zExp := ( ( aExp - $3FFF ) shr 1 ) + $3FFE;
  8591. aSig0 := aSig0 or int64( $0001000000000000 );
  8592. zSig0 := estimateSqrt32( aExp, aSig0 shr 17 );
  8593. shortShift128Left( aSig0, aSig1, 13 - ( aExp and 1 ), aSig0, aSig1 );
  8594. zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
  8595. doubleZSig0 := zSig0 shl 1;
  8596. mul64To128( zSig0, zSig0, term0, term1 );
  8597. sub128( aSig0, aSig1, term0, term1, rem0, rem1 );
  8598. while ( sbits64(rem0) < 0 ) do begin
  8599. dec(zSig0);
  8600. dec(doubleZSig0,2);
  8601. add128( rem0, rem1, zSig0 shr 63, doubleZSig0 or 1, rem0, rem1 );
  8602. end;
  8603. zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
  8604. if ( ( zSig1 and $1FFF ) <= 5 ) then begin
  8605. if ( zSig1 = 0 ) then zSig1 := 1;
  8606. mul64To128( doubleZSig0, zSig1, term1, term2 );
  8607. sub128( rem1, 0, term1, term2, rem1, rem2 );
  8608. mul64To128( zSig1, zSig1, term2, term3 );
  8609. sub192( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
  8610. while ( sbits64(rem1) < 0 ) do begin
  8611. dec(zSig1);
  8612. shortShift128Left( 0, zSig1, 1, term2, term3 );
  8613. term3 := term3 or 1;
  8614. term2 := term2 or doubleZSig0;
  8615. add192( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
  8616. end;
  8617. zSig1 := zSig1 or ord( ( rem1 or rem2 or rem3 ) <> 0 );
  8618. end;
  8619. shift128ExtraRightJamming( zSig0, zSig1, 0, 14, zSig0, zSig1, zSig2 );
  8620. result := roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 );
  8621. end;
  8622. {*----------------------------------------------------------------------------
  8623. | Returns 1 if the quadruple-precision floating-point value `a' is equal to
  8624. | the corresponding value `b', and 0 otherwise. The comparison is performed
  8625. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8626. *----------------------------------------------------------------------------*}
  8627. function float128_eq(a: float128; b: float128): flag;
  8628. begin
  8629. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8630. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8631. or ( ( extractFloat128Exp( b ) = $7FFF )
  8632. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8633. ) then begin
  8634. if ( (float128_is_signaling_nan( a )<>0)
  8635. or (float128_is_signaling_nan( b )<>0) ) then begin
  8636. float_raise( float_flag_invalid );
  8637. end;
  8638. result := 0;
  8639. exit;
  8640. end;
  8641. result := ord(
  8642. ( a.low = b.low )
  8643. and ( ( a.high = b.high )
  8644. or ( ( a.low = 0 )
  8645. and ( bits64( ( a.high or b.high ) shl 1 ) = 0 ) )
  8646. ));
  8647. end;
  8648. {*----------------------------------------------------------------------------
  8649. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8650. | or equal to the corresponding value `b', and 0 otherwise. The comparison
  8651. | is performed according to the IEC/IEEE Standard for Binary Floating-Point
  8652. | Arithmetic.
  8653. *----------------------------------------------------------------------------*}
  8654. function float128_le(a: float128; b: float128): flag;
  8655. var
  8656. aSign, bSign: flag;
  8657. begin
  8658. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8659. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8660. or ( ( extractFloat128Exp( b ) = $7FFF )
  8661. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8662. ) then begin
  8663. float_raise( float_flag_invalid );
  8664. result := 0;
  8665. exit;
  8666. end;
  8667. aSign := extractFloat128Sign( a );
  8668. bSign := extractFloat128Sign( b );
  8669. if ( aSign <> bSign ) then begin
  8670. result := ord(
  8671. (aSign<>0)
  8672. or ( ( ( bits64 ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8673. = 0 ));
  8674. exit;
  8675. end;
  8676. if aSign<>0 then
  8677. result := le128( b.high, b.low, a.high, a.low )
  8678. else
  8679. result := le128( a.high, a.low, b.high, b.low );
  8680. end;
  8681. {*----------------------------------------------------------------------------
  8682. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8683. | the corresponding value `b', and 0 otherwise. The comparison is performed
  8684. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8685. *----------------------------------------------------------------------------*}
  8686. function float128_lt(a: float128; b: float128): flag;
  8687. var
  8688. aSign, bSign: flag;
  8689. begin
  8690. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8691. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8692. or ( ( extractFloat128Exp( b ) = $7FFF )
  8693. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8694. ) then begin
  8695. float_raise( float_flag_invalid );
  8696. result := 0;
  8697. exit;
  8698. end;
  8699. aSign := extractFloat128Sign( a );
  8700. bSign := extractFloat128Sign( b );
  8701. if ( aSign <> bSign ) then begin
  8702. result := ord(
  8703. (aSign<>0)
  8704. and ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8705. <> 0 ));
  8706. exit;
  8707. end;
  8708. if aSign<>0 then
  8709. result := lt128( b.high, b.low, a.high, a.low )
  8710. else
  8711. result := lt128( a.high, a.low, b.high, b.low );
  8712. end;
  8713. {*----------------------------------------------------------------------------
  8714. | Returns 1 if the quadruple-precision floating-point value `a' is equal to
  8715. | the corresponding value `b', and 0 otherwise. The invalid exception is
  8716. | raised if either operand is a NaN. Otherwise, the comparison is performed
  8717. | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8718. *----------------------------------------------------------------------------*}
  8719. function float128_eq_signaling(a: float128; b: float128): flag;
  8720. begin
  8721. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8722. and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8723. or ( ( extractFloat128Exp( b ) = $7FFF )
  8724. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8725. ) then begin
  8726. float_raise( float_flag_invalid );
  8727. result := 0;
  8728. exit;
  8729. end;
  8730. result := ord(
  8731. ( a.low = b.low )
  8732. and ( ( a.high = b.high )
  8733. or ( ( a.low = 0 )
  8734. and ( bits64 ( ( a.high or b.high ) shl 1 ) = 0 ) )
  8735. ));
  8736. end;
  8737. {*----------------------------------------------------------------------------
  8738. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8739. | or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
  8740. | cause an exception. Otherwise, the comparison is performed according to the
  8741. | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
  8742. *----------------------------------------------------------------------------*}
  8743. function float128_le_quiet(a: float128; b: float128): flag;
  8744. var
  8745. aSign, bSign: flag;
  8746. begin
  8747. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8748. and ( ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8749. or ( ( extractFloat128Exp( b ) = $7FFF )
  8750. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8751. ) then begin
  8752. if ( (float128_is_signaling_nan( a )<>0)
  8753. or (float128_is_signaling_nan( b )<>0) ) then begin
  8754. float_raise( float_flag_invalid );
  8755. end;
  8756. result := 0;
  8757. exit;
  8758. end;
  8759. aSign := extractFloat128Sign( a );
  8760. bSign := extractFloat128Sign( b );
  8761. if ( aSign <> bSign ) then begin
  8762. result := ord(
  8763. (aSign<>0)
  8764. or ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8765. = 0 ));
  8766. exit;
  8767. end;
  8768. if aSign<>0 then
  8769. result := le128( b.high, b.low, a.high, a.low )
  8770. else
  8771. result := le128( a.high, a.low, b.high, b.low );
  8772. end;
  8773. {*----------------------------------------------------------------------------
  8774. | Returns 1 if the quadruple-precision floating-point value `a' is less than
  8775. | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
  8776. | exception. Otherwise, the comparison is performed according to the IEC/IEEE
  8777. | Standard for Binary Floating-Point Arithmetic.
  8778. *----------------------------------------------------------------------------*}
  8779. function float128_lt_quiet(a: float128; b: float128): flag;
  8780. var
  8781. aSign, bSign: flag;
  8782. begin
  8783. if ( ( ( extractFloat128Exp( a ) = $7FFF )
  8784. and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ))<>0 ) )
  8785. or ( ( extractFloat128Exp( b ) = $7FFF )
  8786. and ( (extractFloat128Frac0( b ) or extractFloat128Frac1( b ))<>0 ) )
  8787. ) then begin
  8788. if ( (float128_is_signaling_nan( a )<>0)
  8789. or (float128_is_signaling_nan( b )<>0) ) then begin
  8790. float_raise( float_flag_invalid );
  8791. end;
  8792. result := 0;
  8793. exit;
  8794. end;
  8795. aSign := extractFloat128Sign( a );
  8796. bSign := extractFloat128Sign( b );
  8797. if ( aSign <> bSign ) then begin
  8798. result := ord(
  8799. (aSign<>0)
  8800. and ( ( ( bits64( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
  8801. <> 0 ));
  8802. exit;
  8803. end;
  8804. if aSign<>0 then
  8805. result:=lt128( b.high, b.low, a.high, a.low )
  8806. else
  8807. result:=lt128( a.high, a.low, b.high, b.low );
  8808. end;
  8809. {----------------------------------------------------------------------------
  8810. | Returns the result of converting the double-precision floating-point value
  8811. | `a' to the quadruple-precision floating-point format. The conversion is
  8812. | performed according to the IEC/IEEE Standard for Binary Floating-Point
  8813. | Arithmetic.
  8814. *----------------------------------------------------------------------------}
  8815. function float64_to_float128( a : float64) : float128;
  8816. var
  8817. aSign : flag;
  8818. aExp : int16;
  8819. aSig, zSig0, zSig1 : bits64;
  8820. begin
  8821. aSig := extractFloat64Frac( a );
  8822. aExp := extractFloat64Exp( a );
  8823. aSign := extractFloat64Sign( a );
  8824. if ( aExp = $7FF ) then begin
  8825. if ( aSig<>0 ) then begin
  8826. result:=commonNaNToFloat128( float64ToCommonNaN( a ) );
  8827. exit;
  8828. end;
  8829. result:=packFloat128( aSign, $7FFF, 0, 0 );
  8830. exit;
  8831. end;
  8832. if ( aExp = 0 ) then begin
  8833. if ( aSig = 0 ) then
  8834. begin
  8835. result:=packFloat128( aSign, 0, 0, 0 );
  8836. exit;
  8837. end;
  8838. normalizeFloat64Subnormal( aSig, aExp, aSig );
  8839. dec(aExp);
  8840. end;
  8841. shift128Right( aSig, 0, 4, zSig0, zSig1 );
  8842. result:=packFloat128( aSign, aExp + $3C00, zSig0, zSig1 );
  8843. end;
  8844. {$endif FPC_SOFTFLOAT_FLOAT128}
  8845. {$endif not(defined(fpc_softfpu_interface))}
  8846. {$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
  8847. end.
  8848. {$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}