aasmcpu.pas 184 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  3. Contains the abstract assembler implementation for the i386
  4. * Portions of this code was inspired by the NASM sources
  5. The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
  6. Julian Hall. All rights reserved.
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. unit aasmcpu;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globtype,verbose,
  25. cpubase,
  26. cgbase,cgutils,
  27. aasmbase,aasmtai,aasmsym,
  28. ogbase;
  29. const
  30. { "mov reg,reg" source operand number }
  31. O_MOV_SOURCE = 0;
  32. { "mov reg,reg" destination operand number }
  33. O_MOV_DEST = 1;
  34. { Operand types }
  35. OT_NONE = $00000000;
  36. { Bits 0..7: sizes }
  37. OT_BITS8 = $00000001;
  38. OT_BITS16 = $00000002;
  39. OT_BITS32 = $00000004;
  40. OT_BITS64 = $00000008; { x86_64 and FPU }
  41. //OT_BITS128 = $10000000; { 16 byte SSE }
  42. //OT_BITS256 = $20000000; { 32 byte AVX }
  43. //OT_BITS512 = $40000000; { 64 byte AVX512 }
  44. OT_BITS128 = $20000000; { 16 byte SSE }
  45. OT_BITS256 = $40000000; { 32 byte AVX }
  46. OT_BITS512 = $80000000; { 64 byte AVX512 }
  47. OT_VECTORMASK = $1000000000; { OPTIONAL VECTORMASK AVX512}
  48. OT_VECTORZERO = $2000000000; { OPTIONAL ZERO-FLAG AVX512}
  49. OT_VECTORBCST = $4000000000; { BROADCAST-MEM-FLAG AVX512}
  50. OT_VECTORSAE = $8000000000; { OPTIONAL SAE-FLAG AVX512}
  51. OT_VECTORER = $10000000000; { OPTIONAL ER-FLAG-FLAG AVX512}
  52. OT_BITSB32 = OT_BITS32 or OT_VECTORBCST;
  53. OT_BITSB64 = OT_BITS64 or OT_VECTORBCST;
  54. OT_VECTOR_EXT_MASK = OT_VECTORMASK or OT_VECTORZERO or OT_VECTORBCST;
  55. OT_BITS80 = $00000010; { FPU only }
  56. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  57. OT_NEAR = $00000040;
  58. OT_SHORT = $00000080;
  59. { TODO: FAR/NEAR/SHORT are sizes too, they should be included into size mask,
  60. but this requires adjusting the opcode table }
  61. //OT_SIZE_MASK = $3000001F; { all the size attributes }
  62. OT_SIZE_MASK = $E000001F; { all the size attributes }
  63. OT_NON_SIZE = longint(not OT_SIZE_MASK);
  64. { Bits 8..11: modifiers }
  65. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  66. OT_TO = $00000200; { reverse effect in FADD, FSUB &c }
  67. OT_COLON = $00000400; { operand is followed by a colon }
  68. OT_MODIFIER_MASK = $00000F00;
  69. { Bits 12..15: type of operand }
  70. OT_REGISTER = $00001000;
  71. OT_IMMEDIATE = $00002000;
  72. OT_MEMORY = $0000C000; { always includes 'OT_REGMEM' bit as well }
  73. OT_REGMEM = $00008000; { for r/m, ie EA, operands }
  74. OT_TYPE_MASK = OT_REGISTER or OT_IMMEDIATE or OT_MEMORY or OT_REGMEM;
  75. OT_REGNORM = OT_REGISTER or OT_REGMEM; { 'normal' reg, qualifies as EA }
  76. { Bits 20..22, 24..26: register classes
  77. otf_* consts are not used alone, only to build other constants. }
  78. otf_reg_cdt = $00100000;
  79. otf_reg_gpr = $00200000;
  80. otf_reg_sreg = $00400000;
  81. otf_reg_k = $00800000;
  82. otf_reg_fpu = $01000000;
  83. otf_reg_mmx = $02000000;
  84. otf_reg_xmm = $04000000;
  85. otf_reg_ymm = $08000000;
  86. otf_reg_zmm = $10000000;
  87. otf_reg_extra_mask = $0F000000;
  88. { Bits 16..19: subclasses, meaning depends on classes field }
  89. otf_sub0 = $00010000;
  90. otf_sub1 = $00020000;
  91. otf_sub2 = $00040000;
  92. otf_sub3 = $00080000;
  93. OT_REG_SMASK = otf_sub0 or otf_sub1 or otf_sub2 or otf_sub3;
  94. //OT_REG_EXTRA_MASK = $0F000000;
  95. OT_REG_EXTRA_MASK = $1F000000;
  96. OT_REG_TYPMASK = otf_reg_cdt or otf_reg_gpr or otf_reg_sreg or otf_reg_k or otf_reg_extra_mask;
  97. { register class 0: CRx, DRx and TRx }
  98. {$ifdef x86_64}
  99. OT_REG_CDT = OT_REGISTER or otf_reg_cdt or OT_BITS64;
  100. {$else x86_64}
  101. OT_REG_CDT = OT_REGISTER or otf_reg_cdt or OT_BITS32;
  102. {$endif x86_64}
  103. OT_REG_CREG = OT_REG_CDT or otf_sub0; { CRn }
  104. OT_REG_DREG = OT_REG_CDT or otf_sub1; { DRn }
  105. OT_REG_TREG = OT_REG_CDT or otf_sub2; { TRn }
  106. OT_REG_CR4 = OT_REG_CDT or otf_sub3; { CR4 (Pentium only) }
  107. { register class 1: general-purpose registers }
  108. OT_REG_GPR = OT_REGNORM or otf_reg_gpr;
  109. OT_RM_GPR = OT_REGMEM or otf_reg_gpr;
  110. OT_REG8 = OT_REG_GPR or OT_BITS8; { 8-bit GPR }
  111. OT_REG16 = OT_REG_GPR or OT_BITS16;
  112. OT_REG32 = OT_REG_GPR or OT_BITS32;
  113. OT_REG64 = OT_REG_GPR or OT_BITS64;
  114. { GPR subclass 0: accumulator: AL, AX, EAX or RAX }
  115. OT_REG_ACCUM = OT_REG_GPR or otf_sub0;
  116. OT_REG_AL = OT_REG_ACCUM or OT_BITS8;
  117. OT_REG_AX = OT_REG_ACCUM or OT_BITS16;
  118. OT_REG_EAX = OT_REG_ACCUM or OT_BITS32;
  119. {$ifdef x86_64}
  120. OT_REG_RAX = OT_REG_ACCUM or OT_BITS64;
  121. {$endif x86_64}
  122. { GPR subclass 1: counter: CL, CX, ECX or RCX }
  123. OT_REG_COUNT = OT_REG_GPR or otf_sub1;
  124. OT_REG_CL = OT_REG_COUNT or OT_BITS8;
  125. OT_REG_CX = OT_REG_COUNT or OT_BITS16;
  126. OT_REG_ECX = OT_REG_COUNT or OT_BITS32;
  127. {$ifdef x86_64}
  128. OT_REG_RCX = OT_REG_COUNT or OT_BITS64;
  129. {$endif x86_64}
  130. { GPR subclass 2: data register: DL, DX, EDX or RDX }
  131. OT_REG_DX = OT_REG_GPR or otf_sub2 or OT_BITS16;
  132. OT_REG_EDX = OT_REG_GPR or otf_sub2 or OT_BITS32;
  133. { register class 2: Segment registers }
  134. OT_REG_SREG = OT_REGISTER or otf_reg_sreg or OT_BITS16;
  135. OT_REG_CS = OT_REG_SREG or otf_sub0; { CS }
  136. OT_REG_DESS = OT_REG_SREG or otf_sub1; { DS, ES, SS (non-CS 86 registers) }
  137. OT_REG_FSGS = OT_REG_SREG or otf_sub2; { FS, GS (386 extended registers) }
  138. { register class 3: FPU registers }
  139. OT_FPUREG = OT_REGISTER or otf_reg_fpu;
  140. OT_FPU0 = OT_FPUREG or otf_sub0; { FPU stack register zero }
  141. { register class 4: MMX (both reg and r/m) }
  142. OT_MMXREG = OT_REGNORM or otf_reg_mmx;
  143. OT_MMXRM = OT_REGMEM or otf_reg_mmx;
  144. { register class 5: XMM (both reg and r/m) }
  145. OT_XMMREG = OT_REGNORM or otf_reg_xmm;
  146. OT_XMMRM = OT_REGMEM or otf_reg_xmm;
  147. OT_XMEM32 = OT_REGNORM or otf_reg_xmm or otf_reg_gpr or OT_BITS32;
  148. OT_XMEM32_M = OT_XMEM32 or OT_VECTORMASK;
  149. OT_XMEM64 = OT_REGNORM or otf_reg_xmm or otf_reg_gpr or OT_BITS64;
  150. OT_XMEM64_M = OT_XMEM64 or OT_VECTORMASK;
  151. OT_XMMREG_M = OT_XMMREG or OT_VECTORMASK;
  152. OT_XMMREG_MZ = OT_XMMREG or OT_VECTORMASK or OT_VECTORZERO;
  153. OT_XMMRM_MZ = OT_XMMRM or OT_VECTORMASK or OT_VECTORZERO;
  154. OT_XMMREG_SAE = OT_XMMREG or OT_VECTORSAE;
  155. OT_XMMRM_SAE = OT_XMMRM or OT_VECTORSAE;
  156. OT_XMMREG_ER = OT_XMMREG or OT_VECTORER;
  157. OT_XMMRM_ER = OT_XMMRM or OT_VECTORER;
  158. { register class 5: YMM (both reg and r/m) }
  159. OT_YMMREG = OT_REGNORM or otf_reg_ymm;
  160. OT_YMMRM = OT_REGMEM or otf_reg_ymm;
  161. OT_YMEM32 = OT_REGNORM or otf_reg_ymm or otf_reg_gpr or OT_BITS32;
  162. OT_YMEM32_M = OT_YMEM32 or OT_VECTORMASK;
  163. OT_YMEM64 = OT_REGNORM or otf_reg_ymm or otf_reg_gpr or OT_BITS64;
  164. OT_YMEM64_M = OT_YMEM64 or OT_VECTORMASK;
  165. OT_YMMREG_M = OT_YMMREG or OT_VECTORMASK;
  166. OT_YMMREG_MZ = OT_YMMREG or OT_VECTORMASK or OT_VECTORZERO;
  167. OT_YMMRM_MZ = OT_YMMRM or OT_VECTORMASK or OT_VECTORZERO;
  168. OT_YMMREG_SAE = OT_YMMREG or OT_VECTORSAE;
  169. OT_YMMRM_SAE = OT_YMMRM or OT_VECTORSAE;
  170. OT_YMMREG_ER = OT_YMMREG or OT_VECTORER;
  171. OT_YMMRM_ER = OT_YMMRM or OT_VECTORER;
  172. { register class 5: ZMM (both reg and r/m) }
  173. OT_ZMMREG = OT_REGNORM or otf_reg_zmm;
  174. OT_ZMMRM = OT_REGMEM or otf_reg_zmm;
  175. OT_ZMEM32 = OT_REGNORM or otf_reg_zmm or otf_reg_gpr or OT_BITS32;
  176. OT_ZMEM32_M = OT_ZMEM32 or OT_VECTORMASK;
  177. OT_ZMEM64 = OT_REGNORM or otf_reg_zmm or otf_reg_gpr or OT_BITS64;
  178. OT_ZMEM64_M = OT_ZMEM64 or OT_VECTORMASK;
  179. OT_ZMMREG_M = OT_ZMMREG or OT_VECTORMASK;
  180. OT_ZMMREG_MZ = OT_ZMMREG or OT_VECTORMASK or OT_VECTORZERO;
  181. OT_ZMMRM_MZ = OT_ZMMRM or OT_VECTORMASK or OT_VECTORZERO;
  182. OT_ZMMREG_SAE = OT_ZMMREG or OT_VECTORSAE;
  183. OT_ZMMRM_SAE = OT_ZMMRM or OT_VECTORSAE;
  184. OT_ZMMREG_ER = OT_ZMMREG or OT_VECTORER;
  185. OT_ZMMRM_ER = OT_ZMMRM or OT_VECTORER;
  186. OT_KREG = OT_REGNORM or otf_reg_k;
  187. OT_KREG_M = OT_KREG or OT_VECTORMASK;
  188. { Vector-Memory operands }
  189. OT_VMEM_ANY = OT_XMEM32 or OT_XMEM64 or OT_YMEM32 or OT_YMEM64 or OT_ZMEM32 or OT_ZMEM64;
  190. { Memory operands }
  191. OT_MEM8 = OT_MEMORY or OT_BITS8;
  192. OT_MEM16 = OT_MEMORY or OT_BITS16;
  193. OT_MEM16_M = OT_MEM16 or OT_VECTORMASK;
  194. OT_MEM32 = OT_MEMORY or OT_BITS32;
  195. OT_MEM32_M = OT_MEMORY or OT_BITS32 or OT_VECTORMASK;
  196. OT_BMEM32 = OT_MEMORY or OT_BITS32 or OT_VECTORBCST;
  197. OT_BMEM32_SAE= OT_MEMORY or OT_BITS32 or OT_VECTORBCST or OT_VECTORSAE;
  198. OT_MEM64 = OT_MEMORY or OT_BITS64;
  199. OT_MEM64_M = OT_MEMORY or OT_BITS64 or OT_VECTORMASK;
  200. OT_BMEM64 = OT_MEMORY or OT_BITS64 or OT_VECTORBCST;
  201. OT_BMEM64_SAE= OT_MEMORY or OT_BITS64 or OT_VECTORBCST or OT_VECTORSAE;
  202. OT_MEM128 = OT_MEMORY or OT_BITS128;
  203. OT_MEM128_M = OT_MEMORY or OT_BITS128 or OT_VECTORMASK;
  204. OT_MEM256 = OT_MEMORY or OT_BITS256;
  205. OT_MEM256_M = OT_MEMORY or OT_BITS256 or OT_VECTORMASK;
  206. OT_MEM512 = OT_MEMORY or OT_BITS512;
  207. OT_MEM512_M = OT_MEMORY or OT_BITS512 or OT_VECTORMASK;
  208. OT_MEM80 = OT_MEMORY or OT_BITS80;
  209. OT_MEM_OFFS = OT_MEMORY or otf_sub0; { special type of EA }
  210. { simple [address] offset }
  211. { Matches any type of r/m operand }
  212. OT_MEMORY_ANY = OT_MEMORY or OT_RM_GPR or OT_XMMRM or OT_MMXRM or OT_YMMRM or OT_ZMMRM or OT_REG_EXTRA_MASK;
  213. { Immediate operands }
  214. OT_IMM8 = OT_IMMEDIATE or OT_BITS8;
  215. OT_IMM16 = OT_IMMEDIATE or OT_BITS16;
  216. OT_IMM32 = OT_IMMEDIATE or OT_BITS32;
  217. OT_IMM64 = OT_IMMEDIATE or OT_BITS64;
  218. OT_ONENESS = otf_sub0; { special type of immediate operand }
  219. OT_UNITY = OT_IMMEDIATE or OT_ONENESS; { for shift/rotate instructions }
  220. OTVE_VECTOR_SAE = 1 shl 8;
  221. OTVE_VECTOR_ER = 1 shl 9;
  222. OTVE_VECTOR_ZERO = 1 shl 10;
  223. OTVE_VECTOR_WRITEMASK = 1 shl 11;
  224. OTVE_VECTOR_BCST = 1 shl 12;
  225. OTVE_VECTOR_BCST2 = 0;
  226. OTVE_VECTOR_BCST4 = 1 shl 4;
  227. OTVE_VECTOR_BCST8 = 1 shl 5;
  228. OTVE_VECTOR_BCST16 = 3 shl 4;
  229. OTVE_VECTOR_RNSAE = OTVE_VECTOR_ER or 0;
  230. OTVE_VECTOR_RDSAE = OTVE_VECTOR_ER or 1 shl 6;
  231. OTVE_VECTOR_RUSAE = OTVE_VECTOR_ER or 1 shl 7;
  232. OTVE_VECTOR_RZSAE = OTVE_VECTOR_ER or 3 shl 6;
  233. OTVE_VECTOR_BCST_MASK = OTVE_VECTOR_BCST2 or OTVE_VECTOR_BCST4 or OTVE_VECTOR_BCST8 or OTVE_VECTOR_BCST16;
  234. OTVE_VECTOR_ER_MASK = OTVE_VECTOR_RNSAE or OTVE_VECTOR_RDSAE or OTVE_VECTOR_RUSAE or OTVE_VECTOR_RZSAE;
  235. OTVE_VECTOR_MASK = OTVE_VECTOR_SAE or OTVE_VECTOR_ER or OTVE_VECTOR_ZERO or OTVE_VECTOR_WRITEMASK or OTVE_VECTOR_BCST;
  236. { Size of the instruction table converted by nasmconv.pas }
  237. {$if defined(x86_64)}
  238. instabentries = {$i x8664nop.inc}
  239. {$elseif defined(i386)}
  240. instabentries = {$i i386nop.inc}
  241. {$elseif defined(i8086)}
  242. instabentries = {$i i8086nop.inc}
  243. {$endif}
  244. maxinfolen = 10;
  245. type
  246. { What an instruction can change. Needed for optimizer and spilling code.
  247. Note: The order of this enumeration is should not be changed! }
  248. TInsChange = (Ch_None,
  249. {Read from a register}
  250. Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
  251. {write from a register}
  252. Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
  253. {read and write from/to a register}
  254. Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
  255. {modify the contents of a register with the purpose of using
  256. this changed content afterwards (add/sub/..., but e.g. not rep
  257. or movsd)}
  258. Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
  259. {read individual flag bits from the flags register}
  260. Ch_RCarryFlag,Ch_RParityFlag,Ch_RAuxiliaryFlag,Ch_RZeroFlag,Ch_RSignFlag,Ch_ROverflowFlag,
  261. {write individual flag bits to the flags register}
  262. Ch_WCarryFlag,Ch_WParityFlag,Ch_WAuxiliaryFlag,Ch_WZeroFlag,Ch_WSignFlag,Ch_WOverflowFlag,
  263. {set individual flag bits to 0 in the flags register}
  264. Ch_W0CarryFlag,Ch_W0ParityFlag,Ch_W0AuxiliaryFlag,Ch_W0ZeroFlag,Ch_W0SignFlag,Ch_W0OverflowFlag,
  265. {set individual flag bits to 1 in the flags register}
  266. Ch_W1CarryFlag,Ch_W1ParityFlag,Ch_W1AuxiliaryFlag,Ch_W1ZeroFlag,Ch_W1SignFlag,Ch_W1OverflowFlag,
  267. {write an undefined value to individual flag bits in the flags register}
  268. Ch_WUCarryFlag,Ch_WUParityFlag,Ch_WUAuxiliaryFlag,Ch_WUZeroFlag,Ch_WUSignFlag,Ch_WUOverflowFlag,
  269. {read and write flag bits}
  270. Ch_RWCarryFlag,Ch_RWParityFlag,Ch_RWAuxiliaryFlag,Ch_RWZeroFlag,Ch_RWSignFlag,Ch_RWOverflowFlag,
  271. {more specialized flag bits (not considered part of NR_DEFAULTFLAGS by the compiler)}
  272. Ch_RDirFlag,Ch_W0DirFlag,Ch_W1DirFlag,Ch_W0IntFlag,Ch_W1IntFlag,
  273. {instruction reads flag bits, according to its condition (used by Jcc/SETcc/CMOVcc)}
  274. Ch_RFLAGScc,
  275. {read/write/read+write the entire flags/eflags/rflags register}
  276. Ch_RFlags, Ch_WFlags, Ch_RWFlags,
  277. Ch_FPU,
  278. Ch_Rop1, Ch_Wop1, Ch_RWop1, Ch_Mop1,
  279. Ch_Rop2, Ch_Wop2, Ch_RWop2, Ch_Mop2,
  280. Ch_Rop3, Ch_WOp3, Ch_RWOp3, Ch_Mop3,
  281. Ch_Rop4, Ch_WOp4, Ch_RWOp4, Ch_Mop4,
  282. { instruction doesn't read it's input register, in case both parameters
  283. are the same register (e.g. xor eax,eax; sub eax,eax; sbb eax,eax (reads flags only), etc.) }
  284. Ch_NoReadIfEqualRegs,
  285. Ch_RMemEDI,Ch_WMemEDI,
  286. Ch_All,
  287. { x86_64 registers }
  288. Ch_RRAX, Ch_RRCX, Ch_RRDX, Ch_RRBX, Ch_RRSP, Ch_RRBP, Ch_RRSI, Ch_RRDI,
  289. Ch_WRAX, Ch_WRCX, Ch_WRDX, Ch_WRBX, Ch_WRSP, Ch_WRBP, Ch_WRSI, Ch_WRDI,
  290. Ch_RWRAX, Ch_RWRCX, Ch_RWRDX, Ch_RWRBX, Ch_RWRSP, Ch_RWRBP, Ch_RWRSI, Ch_RWRDI,
  291. Ch_MRAX, Ch_MRCX, Ch_MRDX, Ch_MRBX, Ch_MRSP, Ch_MRBP, Ch_MRSI, Ch_MRDI
  292. );
  293. TInsProp = packed record
  294. Ch : set of TInsChange;
  295. end;
  296. TMemRefSizeInfo = (msiUnkown, msiUnsupported, msiNoSize,
  297. msiMultiple, msiMultiple8, msiMultiple16, msiMultiple32,
  298. msiMultiple64, msiMultiple128, msiMultiple256, msiMultiple512,
  299. msiMemRegSize, msiMemRegx16y32, msiMemRegx16y32z64, msiMemRegx32y64, msiMemRegx32y64z128, msiMemRegx64y128, msiMemRegx64y128z256,
  300. msiMemRegx64y256, msiMemRegx64y256z512,
  301. msiMem8, msiMem16, msiMem32, msiBMem32, msiMem64, msiBMem64, msiMem128, msiMem256, msiMem512,
  302. msiXMem32, msiXMem64, msiYMem32, msiYMem64, msiZMem32, msiZMem64,
  303. msiVMemMultiple, msiVMemRegSize,
  304. msiMemRegConst128,msiMemRegConst256,msiMemRegConst512);
  305. TMemRefSizeInfoBCST = (msbUnknown, msbBCST32, msbBCST64, msbMultiple);
  306. TMemRefSizeInfoBCSTType = (btUnknown, bt1to2, bt1to4, bt1to8, bt1to16);
  307. TConstSizeInfo = (csiUnkown, csiMultiple, csiNoSize, csiMem8, csiMem16, csiMem32, csiMem64);
  308. TInsTabMemRefSizeInfoRec = record
  309. MemRefSize : TMemRefSizeInfo;
  310. MemRefSizeBCST : TMemRefSizeInfoBCST;
  311. BCSTXMMMultiplicator : byte;
  312. ExistsSSEAVX : boolean;
  313. ConstSize : TConstSizeInfo;
  314. BCSTTypes : Set of TMemRefSizeInfoBCSTType;
  315. end;
  316. const
  317. MemRefMultiples: set of TMemRefSizeInfo = [msiMultiple, msiMultiple8,
  318. msiMultiple16, msiMultiple32,
  319. msiMultiple64, msiMultiple128,
  320. msiMultiple256, msiMultiple512,
  321. msiVMemMultiple];
  322. MemRefSizeInfoVMems: Set of TMemRefSizeInfo = [msiXMem32, msiXMem64, msiYMem32, msiYMem64,
  323. msiZMem32, msiZMem64,
  324. msiVMemMultiple, msiVMemRegSize];
  325. InsProp : array[tasmop] of TInsProp =
  326. {$if defined(x86_64)}
  327. {$i x8664pro.inc}
  328. {$elseif defined(i386)}
  329. {$i i386prop.inc}
  330. {$elseif defined(i8086)}
  331. {$i i8086prop.inc}
  332. {$endif}
  333. type
  334. TOperandOrder = (op_intel,op_att);
  335. {Instruction flags }
  336. tinsflag = (
  337. { please keep these in order and in sync with IF_SMASK }
  338. IF_SM, { size match first two operands }
  339. IF_SM2,
  340. IF_SB, { unsized operands can't be non-byte }
  341. IF_SW, { unsized operands can't be non-word }
  342. IF_SD, { unsized operands can't be nondword }
  343. { unsized argument spec }
  344. { please keep these in order and in sync with IF_ARMASK }
  345. IF_AR0, { SB, SW, SD applies to argument 0 }
  346. IF_AR1, { SB, SW, SD applies to argument 1 }
  347. IF_AR2, { SB, SW, SD applies to argument 2 }
  348. IF_PRIV, { it's a privileged instruction }
  349. IF_SMM, { it's only valid in SMM }
  350. IF_PROT, { it's protected mode only }
  351. IF_NOX86_64, { removed instruction in x86_64 }
  352. IF_UNDOC, { it's an undocumented instruction }
  353. IF_FPU, { it's an FPU instruction }
  354. IF_MMX, { it's an MMX instruction }
  355. { it's a 3DNow! instruction }
  356. IF_3DNOW,
  357. { it's a SSE (KNI, MMX2) instruction }
  358. IF_SSE,
  359. { SSE2 instructions }
  360. IF_SSE2,
  361. { SSE3 instructions }
  362. IF_SSE3,
  363. { SSE64 instructions }
  364. IF_SSE64,
  365. { SVM instructions }
  366. IF_SVM,
  367. { SSE4 instructions }
  368. IF_SSE4,
  369. IF_SSSE3,
  370. IF_SSE41,
  371. IF_SSE42,
  372. IF_AVX,
  373. IF_AVX2,
  374. IF_AVX512,
  375. IF_BMI1,
  376. IF_BMI2,
  377. IF_16BITONLY,
  378. IF_FMA,
  379. IF_FMA4,
  380. IF_TSX,
  381. IF_RAND,
  382. IF_XSAVE,
  383. IF_PREFETCHWT1,
  384. { mask for processor level }
  385. { please keep these in order and in sync with IF_PLEVEL }
  386. IF_8086, { 8086 instruction }
  387. IF_186, { 186+ instruction }
  388. IF_286, { 286+ instruction }
  389. IF_386, { 386+ instruction }
  390. IF_486, { 486+ instruction }
  391. IF_PENT, { Pentium instruction }
  392. IF_P6, { P6 instruction }
  393. IF_KATMAI, { Katmai instructions }
  394. IF_WILLAMETTE, { Willamette instructions }
  395. IF_PRESCOTT, { Prescott instructions }
  396. IF_X86_64,
  397. IF_SANDYBRIDGE, { Sandybridge-specific instruction }
  398. IF_NEC, { NEC V20/V30 instruction }
  399. { the following are not strictly part of the processor level, because
  400. they are never used standalone, but always in combination with a
  401. separate processor level flag. Therefore, they use bits outside of
  402. IF_PLEVEL, otherwise they would mess up the processor level they're
  403. used in combination with.
  404. The following combinations are currently used:
  405. [IF_AMD, IF_P6],
  406. [IF_CYRIX, IF_486],
  407. [IF_CYRIX, IF_PENT],
  408. [IF_CYRIX, IF_P6] }
  409. IF_CYRIX, { Cyrix, Centaur or VIA-specific instruction }
  410. IF_AMD, { AMD-specific instruction }
  411. { added flags }
  412. IF_PRE, { it's a prefix instruction }
  413. IF_PASS2, { if the instruction can change in a second pass }
  414. IF_IMM4, { immediate operand is a nibble (must be in range [0..15]) }
  415. IF_IMM3, { immediate operand is a triad (must be in range [0..7]) }
  416. { avx512 flags }
  417. IF_BCST2,
  418. IF_BCST4,
  419. IF_BCST8,
  420. IF_BCST16
  421. );
  422. tinsflags=set of tinsflag;
  423. const
  424. IF_SMASK=[IF_SM,IF_SM2,IF_SB,IF_SW,IF_SD];
  425. IF_ARMASK=[IF_AR0,IF_AR1,IF_AR2]; { mask for unsized argument spec }
  426. IF_PLEVEL=[IF_8086..IF_NEC]; { mask for processor level }
  427. type
  428. tinsentry=packed record
  429. opcode : tasmop;
  430. ops : byte;
  431. //optypes : array[0..max_operands-1] of longint;
  432. optypes : array[0..max_operands-1] of int64; //TG
  433. code : array[0..maxinfolen] of char;
  434. flags : tinsflags;
  435. end;
  436. pinsentry=^tinsentry;
  437. { alignment for operator }
  438. tai_align = class(tai_align_abstract)
  439. reg : tregister;
  440. constructor create(b:byte);override;
  441. constructor create_op(b: byte; _op: byte);override;
  442. function calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;override;
  443. end;
  444. { taicpu }
  445. taicpu = class(tai_cpu_abstract_sym)
  446. opsize : topsize;
  447. constructor op_none(op : tasmop);
  448. constructor op_none(op : tasmop;_size : topsize);
  449. constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  450. constructor op_const(op : tasmop;_size : topsize;_op1 : aint);
  451. constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
  452. constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  453. constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
  454. constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
  455. constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
  456. constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
  457. constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
  458. constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
  459. constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  460. constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
  461. constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
  462. constructor op_ref_reg_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2,_op3 : tregister);
  463. constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
  464. constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
  465. constructor op_const_reg_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2, _op3, _op4 : tregister);
  466. { this is for Jmp instructions }
  467. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  468. constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  469. constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  470. constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  471. constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  472. procedure changeopsize(siz:topsize);
  473. function GetString:string;
  474. { This is a workaround for the GAS non commutative fpu instruction braindamage.
  475. Early versions of the UnixWare assembler had a bug where some fpu instructions
  476. were reversed and GAS still keeps this "feature" for compatibility.
  477. for details: http://sourceware.org/binutils/docs/as/i386_002dBugs.html#i386_002dBugs
  478. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=372528
  479. http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax#Caveats
  480. Since FPC is "GAS centric" due to its history it generates instructions with the same operand order so
  481. when generating output for other assemblers, the opcodes must be fixed before writing them.
  482. This function returns the fixed opcodes. Changing the opcodes permanently is no good idea
  483. because in case of smartlinking assembler is generated twice so at the second run wrong
  484. assembler is generated.
  485. }
  486. function FixNonCommutativeOpcodes: tasmop;
  487. private
  488. FOperandOrder : TOperandOrder;
  489. procedure init(_size : topsize); { this need to be called by all constructor }
  490. public
  491. { the next will reset all instructions that can change in pass 2 }
  492. procedure ResetPass1;override;
  493. procedure ResetPass2;override;
  494. function CheckIfValid:boolean;
  495. function Pass1(objdata:TObjData):longint;override;
  496. procedure Pass2(objdata:TObjData);override;
  497. procedure SetOperandOrder(order:TOperandOrder);
  498. function is_same_reg_move(regtype: Tregistertype):boolean;override;
  499. { register spilling code }
  500. function spilling_get_operation_type(opnr: longint): topertype;override;
  501. {$ifdef i8086}
  502. procedure loadsegsymbol(opidx:longint;s:tasmsymbol);
  503. {$endif i8086}
  504. property OperandOrder : TOperandOrder read FOperandOrder;
  505. private
  506. { next fields are filled in pass1, so pass2 is faster }
  507. insentry : PInsEntry;
  508. insoffset : longint;
  509. LastInsOffset : longint; { need to be public to be reset }
  510. inssize : shortint;
  511. {$ifdef x86_64}
  512. rex : byte;
  513. {$endif x86_64}
  514. function InsEnd:longint;
  515. procedure create_ot(objdata:TObjData);
  516. function Matches(p:PInsEntry):boolean;
  517. function calcsize(p:PInsEntry):shortint;
  518. procedure gencode(objdata:TObjData);
  519. function NeedAddrPrefix(opidx:byte):boolean;
  520. function NeedAddrPrefix:boolean;
  521. procedure write0x66prefix(objdata:TObjData);
  522. procedure write0x67prefix(objdata:TObjData);
  523. procedure Swapoperands;
  524. function FindInsentry(objdata:TObjData):boolean;
  525. function CheckUseEVEX: boolean;
  526. end;
  527. function is_64_bit_ref(const ref:treference):boolean;
  528. function is_32_bit_ref(const ref:treference):boolean;
  529. function is_16_bit_ref(const ref:treference):boolean;
  530. function get_ref_address_size(const ref:treference):byte;
  531. function get_default_segment_of_ref(const ref:treference):tregister;
  532. procedure optimize_ref(var ref:treference; inlineasm: boolean);
  533. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  534. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  535. function MemRefInfo(aAsmop: TAsmOp): TInsTabMemRefSizeInfoRec;
  536. procedure InitAsm;
  537. procedure DoneAsm;
  538. {*****************************************************************************
  539. External Symbol Chain
  540. used for agx86nsm and agx86int
  541. *****************************************************************************}
  542. type
  543. PExternChain = ^TExternChain;
  544. TExternChain = Record
  545. psym : pshortstring;
  546. is_defined : boolean;
  547. next : PExternChain;
  548. end;
  549. const
  550. FEC : PExternChain = nil;
  551. procedure AddSymbol(symname : string; defined : boolean);
  552. procedure FreeExternChainList;
  553. implementation
  554. uses
  555. cutils,
  556. globals,
  557. systems,
  558. itcpugas,
  559. cpuinfo;
  560. procedure AddSymbol(symname : string; defined : boolean);
  561. var
  562. EC : PExternChain;
  563. begin
  564. EC:=FEC;
  565. while assigned(EC) do
  566. begin
  567. if EC^.psym^=symname then
  568. begin
  569. if defined then
  570. EC^.is_defined:=true;
  571. exit;
  572. end;
  573. EC:=EC^.next;
  574. end;
  575. New(EC);
  576. EC^.next:=FEC;
  577. FEC:=EC;
  578. FEC^.psym:=stringdup(symname);
  579. FEC^.is_defined := defined;
  580. end;
  581. procedure FreeExternChainList;
  582. var
  583. EC : PExternChain;
  584. begin
  585. EC:=FEC;
  586. while assigned(EC) do
  587. begin
  588. FEC:=EC^.next;
  589. stringdispose(EC^.psym);
  590. Dispose(EC);
  591. EC:=FEC;
  592. end;
  593. end;
  594. {*****************************************************************************
  595. Instruction table
  596. *****************************************************************************}
  597. type
  598. TInsTabCache=array[TasmOp] of longint;
  599. PInsTabCache=^TInsTabCache;
  600. TInsTabMemRefSizeInfoCache=array[TasmOp] of TInsTabMemRefSizeInfoRec;
  601. PInsTabMemRefSizeInfoCache=^TInsTabMemRefSizeInfoCache;
  602. const
  603. {$if defined(x86_64)}
  604. InsTab:array[0..instabentries-1] of TInsEntry={$i x8664tab.inc}
  605. {$elseif defined(i386)}
  606. InsTab:array[0..instabentries-1] of TInsEntry={$i i386tab.inc}
  607. {$elseif defined(i8086)}
  608. InsTab:array[0..instabentries-1] of TInsEntry={$i i8086tab.inc}
  609. {$endif}
  610. var
  611. InsTabCache : PInsTabCache;
  612. InsTabMemRefSizeInfoCache: PInsTabMemRefSizeInfoCache;
  613. const
  614. {$if defined(x86_64)}
  615. { Intel style operands ! }
  616. //TG opsize_2_type:array[0..2,topsize] of longint=(
  617. opsize_2_type:array[0..2,topsize] of int64=(
  618. (OT_NONE,
  619. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,OT_BITS64,OT_BITS64,OT_BITS64,
  620. OT_BITS16,OT_BITS32,OT_BITS64,
  621. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  622. OT_BITS64,
  623. OT_NEAR,OT_FAR,OT_SHORT,
  624. OT_NONE,
  625. OT_BITS128,
  626. OT_BITS256,
  627. OT_BITS512
  628. ),
  629. (OT_NONE,
  630. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,OT_BITS8,OT_BITS16,OT_BITS32,
  631. OT_BITS16,OT_BITS32,OT_BITS64,
  632. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  633. OT_BITS64,
  634. OT_NEAR,OT_FAR,OT_SHORT,
  635. OT_NONE,
  636. OT_BITS128,
  637. OT_BITS256,
  638. OT_BITS512
  639. ),
  640. (OT_NONE,
  641. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,
  642. OT_BITS16,OT_BITS32,OT_BITS64,
  643. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  644. OT_BITS64,
  645. OT_NEAR,OT_FAR,OT_SHORT,
  646. OT_NONE,
  647. OT_BITS128,
  648. OT_BITS256,
  649. OT_BITS512
  650. )
  651. );
  652. reg_ot_table : array[tregisterindex] of longint = (
  653. {$i r8664ot.inc}
  654. );
  655. {$elseif defined(i386)}
  656. { Intel style operands ! }
  657. opsize_2_type:array[0..2,topsize] of int64=(
  658. (OT_NONE,
  659. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,
  660. OT_BITS16,OT_BITS32,OT_BITS64,
  661. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  662. OT_BITS64,
  663. OT_NEAR,OT_FAR,OT_SHORT,
  664. OT_NONE,
  665. OT_BITS128,
  666. OT_BITS256,
  667. OT_BITS512
  668. ),
  669. (OT_NONE,
  670. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,
  671. OT_BITS16,OT_BITS32,OT_BITS64,
  672. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  673. OT_BITS64,
  674. OT_NEAR,OT_FAR,OT_SHORT,
  675. OT_NONE,
  676. OT_BITS128,
  677. OT_BITS256,
  678. OT_BITS512
  679. ),
  680. (OT_NONE,
  681. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,
  682. OT_BITS16,OT_BITS32,OT_BITS64,
  683. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  684. OT_BITS64,
  685. OT_NEAR,OT_FAR,OT_SHORT,
  686. OT_NONE,
  687. OT_BITS128,
  688. OT_BITS256,
  689. OT_BITS512
  690. )
  691. );
  692. reg_ot_table : array[tregisterindex] of longint = (
  693. {$i r386ot.inc}
  694. );
  695. {$elseif defined(i8086)}
  696. { Intel style operands ! }
  697. opsize_2_type:array[0..2,topsize] of int64=(
  698. (OT_NONE,
  699. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,
  700. OT_BITS16,OT_BITS32,OT_BITS64,
  701. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  702. OT_BITS64,
  703. OT_NEAR,OT_FAR,OT_SHORT,
  704. OT_NONE,
  705. OT_BITS128,
  706. OT_BITS256,
  707. OT_BITS512
  708. ),
  709. (OT_NONE,
  710. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,
  711. OT_BITS16,OT_BITS32,OT_BITS64,
  712. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  713. OT_BITS64,
  714. OT_NEAR,OT_FAR,OT_SHORT,
  715. OT_NONE,
  716. OT_BITS128,
  717. OT_BITS256,
  718. OT_BITS512
  719. ),
  720. (OT_NONE,
  721. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,
  722. OT_BITS16,OT_BITS32,OT_BITS64,
  723. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
  724. OT_BITS64,
  725. OT_NEAR,OT_FAR,OT_SHORT,
  726. OT_NONE,
  727. OT_BITS128,
  728. OT_BITS256,
  729. OT_BITS512
  730. )
  731. );
  732. reg_ot_table : array[tregisterindex] of longint = (
  733. {$i r8086ot.inc}
  734. );
  735. {$endif}
  736. function MemRefInfo(aAsmop: TAsmOp): TInsTabMemRefSizeInfoRec;
  737. begin
  738. result := InsTabMemRefSizeInfoCache^[aAsmop];
  739. end;
  740. { Operation type for spilling code }
  741. type
  742. toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
  743. var
  744. operation_type_table : ^toperation_type_table;
  745. {****************************************************************************
  746. TAI_ALIGN
  747. ****************************************************************************}
  748. constructor tai_align.create(b: byte);
  749. begin
  750. inherited create(b);
  751. reg:=NR_ECX;
  752. end;
  753. constructor tai_align.create_op(b: byte; _op: byte);
  754. begin
  755. inherited create_op(b,_op);
  756. reg:=NR_NO;
  757. end;
  758. function tai_align.calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;
  759. const
  760. { Updated according to
  761. Software Optimization Guide for AMD Family 15h Processors, Verison 3.08, January 2014
  762. and
  763. Intel 64 and IA-32 Architectures Software Developer’s Manual
  764. Volume 2B: Instruction Set Reference, N-Z, January 2015
  765. }
  766. alignarray_cmovcpus:array[0..10] of string[11]=(
  767. #$66#$66#$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
  768. #$66#$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
  769. #$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
  770. #$0F#$1F#$84#$00#$00#$00#$00#$00,
  771. #$0F#$1F#$80#$00#$00#$00#$00,
  772. #$66#$0F#$1F#$44#$00#$00,
  773. #$0F#$1F#$44#$00#$00,
  774. #$0F#$1F#$40#$00,
  775. #$0F#$1F#$00,
  776. #$66#$90,
  777. #$90);
  778. {$ifdef i8086}
  779. alignarray:array[0..5] of string[8]=(
  780. #$90#$90#$90#$90#$90#$90#$90,
  781. #$90#$90#$90#$90#$90#$90,
  782. #$90#$90#$90#$90,
  783. #$90#$90#$90,
  784. #$90#$90,
  785. #$90);
  786. {$else i8086}
  787. alignarray:array[0..5] of string[8]=(
  788. #$8D#$B4#$26#$00#$00#$00#$00,
  789. #$8D#$B6#$00#$00#$00#$00,
  790. #$8D#$74#$26#$00,
  791. #$8D#$76#$00,
  792. #$89#$F6,
  793. #$90);
  794. {$endif i8086}
  795. var
  796. bufptr : pchar;
  797. j : longint;
  798. localsize: byte;
  799. begin
  800. inherited calculatefillbuf(buf,executable);
  801. if not(use_op) and executable then
  802. begin
  803. bufptr:=pchar(@buf);
  804. { fillsize may still be used afterwards, so don't modify }
  805. { e.g. writebytes(hp.calculatefillbuf(buf)^,hp.fillsize) }
  806. localsize:=fillsize;
  807. while (localsize>0) do
  808. begin
  809. {$ifndef i8086}
  810. if CPUX86_HAS_CMOV in cpu_capabilities[current_settings.cputype] then
  811. begin
  812. for j:=low(alignarray_cmovcpus) to high(alignarray_cmovcpus) do
  813. if (localsize>=length(alignarray_cmovcpus[j])) then
  814. break;
  815. move(alignarray_cmovcpus[j][1],bufptr^,length(alignarray_cmovcpus[j]));
  816. inc(bufptr,length(alignarray_cmovcpus[j]));
  817. dec(localsize,length(alignarray_cmovcpus[j]));
  818. end
  819. else
  820. {$endif not i8086}
  821. begin
  822. for j:=low(alignarray) to high(alignarray) do
  823. if (localsize>=length(alignarray[j])) then
  824. break;
  825. move(alignarray[j][1],bufptr^,length(alignarray[j]));
  826. inc(bufptr,length(alignarray[j]));
  827. dec(localsize,length(alignarray[j]));
  828. end
  829. end;
  830. end;
  831. calculatefillbuf:=pchar(@buf);
  832. end;
  833. {*****************************************************************************
  834. Taicpu Constructors
  835. *****************************************************************************}
  836. procedure taicpu.changeopsize(siz:topsize);
  837. begin
  838. opsize:=siz;
  839. end;
  840. procedure taicpu.init(_size : topsize);
  841. begin
  842. { default order is att }
  843. FOperandOrder:=op_att;
  844. segprefix:=NR_NO;
  845. opsize:=_size;
  846. insentry:=nil;
  847. LastInsOffset:=-1;
  848. InsOffset:=0;
  849. InsSize:=0;
  850. end;
  851. constructor taicpu.op_none(op : tasmop);
  852. begin
  853. inherited create(op);
  854. init(S_NO);
  855. end;
  856. constructor taicpu.op_none(op : tasmop;_size : topsize);
  857. begin
  858. inherited create(op);
  859. init(_size);
  860. end;
  861. constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  862. begin
  863. inherited create(op);
  864. init(_size);
  865. ops:=1;
  866. loadreg(0,_op1);
  867. end;
  868. constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aint);
  869. begin
  870. inherited create(op);
  871. init(_size);
  872. ops:=1;
  873. loadconst(0,_op1);
  874. end;
  875. constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
  876. begin
  877. inherited create(op);
  878. init(_size);
  879. ops:=1;
  880. loadref(0,_op1);
  881. end;
  882. constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  883. begin
  884. inherited create(op);
  885. init(_size);
  886. ops:=2;
  887. loadreg(0,_op1);
  888. loadreg(1,_op2);
  889. end;
  890. constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
  891. begin
  892. inherited create(op);
  893. init(_size);
  894. ops:=2;
  895. loadreg(0,_op1);
  896. loadconst(1,_op2);
  897. end;
  898. constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
  899. begin
  900. inherited create(op);
  901. init(_size);
  902. ops:=2;
  903. loadreg(0,_op1);
  904. loadref(1,_op2);
  905. end;
  906. constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
  907. begin
  908. inherited create(op);
  909. init(_size);
  910. ops:=2;
  911. loadconst(0,_op1);
  912. loadreg(1,_op2);
  913. end;
  914. constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
  915. begin
  916. inherited create(op);
  917. init(_size);
  918. ops:=2;
  919. loadconst(0,_op1);
  920. loadconst(1,_op2);
  921. end;
  922. constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
  923. begin
  924. inherited create(op);
  925. init(_size);
  926. ops:=2;
  927. loadconst(0,_op1);
  928. loadref(1,_op2);
  929. end;
  930. constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
  931. begin
  932. inherited create(op);
  933. init(_size);
  934. ops:=2;
  935. loadref(0,_op1);
  936. loadreg(1,_op2);
  937. end;
  938. constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  939. begin
  940. inherited create(op);
  941. init(_size);
  942. ops:=3;
  943. loadreg(0,_op1);
  944. loadreg(1,_op2);
  945. loadreg(2,_op3);
  946. end;
  947. constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
  948. begin
  949. inherited create(op);
  950. init(_size);
  951. ops:=3;
  952. loadconst(0,_op1);
  953. loadreg(1,_op2);
  954. loadreg(2,_op3);
  955. end;
  956. constructor taicpu.op_ref_reg_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2,_op3 : tregister);
  957. begin
  958. inherited create(op);
  959. init(_size);
  960. ops:=3;
  961. loadref(0,_op1);
  962. loadreg(1,_op2);
  963. loadreg(2,_op3);
  964. end;
  965. constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
  966. begin
  967. inherited create(op);
  968. init(_size);
  969. ops:=3;
  970. loadconst(0,_op1);
  971. loadref(1,_op2);
  972. loadreg(2,_op3);
  973. end;
  974. constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
  975. begin
  976. inherited create(op);
  977. init(_size);
  978. ops:=3;
  979. loadconst(0,_op1);
  980. loadreg(1,_op2);
  981. loadref(2,_op3);
  982. end;
  983. constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
  984. begin
  985. inherited create(op);
  986. init(_size);
  987. ops:=3;
  988. loadreg(0,_op1);
  989. loadreg(1,_op2);
  990. loadref(2,_op3);
  991. end;
  992. constructor taicpu.op_const_reg_reg_reg(op : tasmop; _size : topsize; _op1 : aint; _op2, _op3, _op4 : tregister);
  993. begin
  994. inherited create(op);
  995. init(_size);
  996. ops:=4;
  997. loadconst(0,_op1);
  998. loadreg(1,_op2);
  999. loadreg(2,_op3);
  1000. loadreg(3,_op4);
  1001. end;
  1002. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
  1003. begin
  1004. inherited create(op);
  1005. init(_size);
  1006. condition:=cond;
  1007. ops:=1;
  1008. loadsymbol(0,_op1,0);
  1009. end;
  1010. constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  1011. begin
  1012. inherited create(op);
  1013. init(_size);
  1014. ops:=1;
  1015. loadsymbol(0,_op1,0);
  1016. end;
  1017. constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  1018. begin
  1019. inherited create(op);
  1020. init(_size);
  1021. ops:=1;
  1022. loadsymbol(0,_op1,_op1ofs);
  1023. end;
  1024. constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  1025. begin
  1026. inherited create(op);
  1027. init(_size);
  1028. ops:=2;
  1029. loadsymbol(0,_op1,_op1ofs);
  1030. loadreg(1,_op2);
  1031. end;
  1032. constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  1033. begin
  1034. inherited create(op);
  1035. init(_size);
  1036. ops:=2;
  1037. loadsymbol(0,_op1,_op1ofs);
  1038. loadref(1,_op2);
  1039. end;
  1040. function taicpu.GetString:string;
  1041. var
  1042. i : longint;
  1043. s : string;
  1044. regnr: string;
  1045. addsize : boolean;
  1046. begin
  1047. s:='['+std_op2str[opcode];
  1048. for i:=0 to ops-1 do
  1049. begin
  1050. with oper[i]^ do
  1051. begin
  1052. if i=0 then
  1053. s:=s+' '
  1054. else
  1055. s:=s+',';
  1056. { type }
  1057. addsize:=false;
  1058. regnr := '';
  1059. if getregtype(reg) = R_MMREGISTER then
  1060. str(getsupreg(reg),regnr);
  1061. if (ot and OT_XMMREG)=OT_XMMREG then
  1062. s:=s+'xmmreg' + regnr
  1063. else
  1064. if (ot and OT_YMMREG)=OT_YMMREG then
  1065. s:=s+'ymmreg' + regnr
  1066. else
  1067. if (ot and OT_ZMMREG)=OT_ZMMREG then
  1068. s:=s+'zmmreg' + regnr
  1069. else
  1070. if (ot and OT_REG_EXTRA_MASK)=OT_MMXREG then
  1071. s:=s+'mmxreg'
  1072. else
  1073. if (ot and OT_REG_EXTRA_MASK)=OT_FPUREG then
  1074. s:=s+'fpureg'
  1075. else
  1076. if (ot and OT_REGISTER)=OT_REGISTER then
  1077. begin
  1078. s:=s+'reg';
  1079. addsize:=true;
  1080. end
  1081. else
  1082. if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  1083. begin
  1084. s:=s+'imm';
  1085. addsize:=true;
  1086. end
  1087. else
  1088. if (ot and OT_MEMORY)=OT_MEMORY then
  1089. begin
  1090. s:=s+'mem';
  1091. addsize:=true;
  1092. end
  1093. else
  1094. s:=s+'???';
  1095. { size }
  1096. if addsize then
  1097. begin
  1098. if (ot and OT_BITS8)<>0 then
  1099. s:=s+'8'
  1100. else
  1101. if (ot and OT_BITS16)<>0 then
  1102. s:=s+'16'
  1103. else
  1104. if (ot and OT_BITS32)<>0 then
  1105. s:=s+'32'
  1106. else
  1107. if (ot and OT_BITS64)<>0 then
  1108. s:=s+'64'
  1109. else
  1110. if (ot and OT_BITS128)<>0 then
  1111. s:=s+'128'
  1112. else
  1113. if (ot and OT_BITS256)<>0 then
  1114. s:=s+'256'
  1115. else
  1116. if (ot and OT_BITS512)<>0 then
  1117. s:=s+'512'
  1118. else
  1119. s:=s+'??';
  1120. { signed }
  1121. if (ot and OT_SIGNED)<>0 then
  1122. s:=s+'s';
  1123. end;
  1124. if vopext <> 0 then
  1125. begin
  1126. str(vopext and $07, regnr);
  1127. if vopext and OTVE_VECTOR_WRITEMASK = OTVE_VECTOR_WRITEMASK then
  1128. s := s + ' {k' + regnr + '}';
  1129. if vopext and OTVE_VECTOR_ZERO = OTVE_VECTOR_ZERO then
  1130. s := s + ' {z}';
  1131. if vopext and OTVE_VECTOR_SAE = OTVE_VECTOR_SAE then
  1132. s := s + ' {sae}';
  1133. if vopext and OTVE_VECTOR_BCST = OTVE_VECTOR_BCST then
  1134. case vopext and OTVE_VECTOR_BCST_MASK of
  1135. OTVE_VECTOR_BCST2: s := s + ' {1to2}';
  1136. OTVE_VECTOR_BCST4: s := s + ' {1to4}';
  1137. OTVE_VECTOR_BCST8: s := s + ' {1to8}';
  1138. OTVE_VECTOR_BCST16: s := s + ' {1to16}';
  1139. end;
  1140. if vopext and OTVE_VECTOR_ER = OTVE_VECTOR_ER then
  1141. case vopext and OTVE_VECTOR_ER_MASK of
  1142. OTVE_VECTOR_RNSAE: s := s + ' {rn-sae}';
  1143. OTVE_VECTOR_RDSAE: s := s + ' {rd-sae}';
  1144. OTVE_VECTOR_RUSAE: s := s + ' {ru-sae}';
  1145. OTVE_VECTOR_RZSAE: s := s + ' {rz-sae}';
  1146. end;
  1147. end;
  1148. end;
  1149. end;
  1150. GetString:=s+']';
  1151. end;
  1152. procedure taicpu.Swapoperands;
  1153. var
  1154. p : POper;
  1155. begin
  1156. { Fix the operands which are in AT&T style and we need them in Intel style }
  1157. case ops of
  1158. 0,1:
  1159. ;
  1160. 2 : begin
  1161. { 0,1 -> 1,0 }
  1162. p:=oper[0];
  1163. oper[0]:=oper[1];
  1164. oper[1]:=p;
  1165. end;
  1166. 3 : begin
  1167. { 0,1,2 -> 2,1,0 }
  1168. p:=oper[0];
  1169. oper[0]:=oper[2];
  1170. oper[2]:=p;
  1171. end;
  1172. 4 : begin
  1173. { 0,1,2,3 -> 3,2,1,0 }
  1174. p:=oper[0];
  1175. oper[0]:=oper[3];
  1176. oper[3]:=p;
  1177. p:=oper[1];
  1178. oper[1]:=oper[2];
  1179. oper[2]:=p;
  1180. end;
  1181. else
  1182. internalerror(201108141);
  1183. end;
  1184. end;
  1185. procedure taicpu.SetOperandOrder(order:TOperandOrder);
  1186. begin
  1187. if FOperandOrder<>order then
  1188. begin
  1189. Swapoperands;
  1190. FOperandOrder:=order;
  1191. end;
  1192. end;
  1193. function taicpu.FixNonCommutativeOpcodes: tasmop;
  1194. begin
  1195. result:=opcode;
  1196. { we need ATT order }
  1197. SetOperandOrder(op_att);
  1198. if (
  1199. (ops=2) and
  1200. (oper[0]^.typ=top_reg) and
  1201. (oper[1]^.typ=top_reg) and
  1202. { if the first is ST and the second is also a register
  1203. it is necessarily ST1 .. ST7 }
  1204. ((oper[0]^.reg=NR_ST) or
  1205. (oper[0]^.reg=NR_ST0))
  1206. ) or
  1207. { ((ops=1) and
  1208. (oper[0]^.typ=top_reg) and
  1209. (oper[0]^.reg in [R_ST1..R_ST7])) or}
  1210. (ops=0) then
  1211. begin
  1212. if opcode=A_FSUBR then
  1213. result:=A_FSUB
  1214. else if opcode=A_FSUB then
  1215. result:=A_FSUBR
  1216. else if opcode=A_FDIVR then
  1217. result:=A_FDIV
  1218. else if opcode=A_FDIV then
  1219. result:=A_FDIVR
  1220. else if opcode=A_FSUBRP then
  1221. result:=A_FSUBP
  1222. else if opcode=A_FSUBP then
  1223. result:=A_FSUBRP
  1224. else if opcode=A_FDIVRP then
  1225. result:=A_FDIVP
  1226. else if opcode=A_FDIVP then
  1227. result:=A_FDIVRP;
  1228. end;
  1229. if (
  1230. (ops=1) and
  1231. (oper[0]^.typ=top_reg) and
  1232. (getregtype(oper[0]^.reg)=R_FPUREGISTER) and
  1233. (oper[0]^.reg<>NR_ST)
  1234. ) then
  1235. begin
  1236. if opcode=A_FSUBRP then
  1237. result:=A_FSUBP
  1238. else if opcode=A_FSUBP then
  1239. result:=A_FSUBRP
  1240. else if opcode=A_FDIVRP then
  1241. result:=A_FDIVP
  1242. else if opcode=A_FDIVP then
  1243. result:=A_FDIVRP;
  1244. end;
  1245. end;
  1246. {*****************************************************************************
  1247. Assembler
  1248. *****************************************************************************}
  1249. type
  1250. ea = packed record
  1251. sib_present : boolean;
  1252. bytes : byte;
  1253. size : byte;
  1254. modrm : byte;
  1255. sib : byte;
  1256. {$ifdef x86_64}
  1257. rex : byte;
  1258. {$endif x86_64}
  1259. end;
  1260. procedure taicpu.create_ot(objdata:TObjData);
  1261. {
  1262. this function will also fix some other fields which only needs to be once
  1263. }
  1264. var
  1265. i,l,relsize : longint;
  1266. currsym : TObjSymbol;
  1267. begin
  1268. if ops=0 then
  1269. exit;
  1270. { update oper[].ot field }
  1271. for i:=0 to ops-1 do
  1272. with oper[i]^ do
  1273. begin
  1274. case typ of
  1275. top_reg :
  1276. begin
  1277. ot:=reg_ot_table[findreg_by_number(reg)];
  1278. end;
  1279. top_ref :
  1280. begin
  1281. if (ref^.refaddr=addr_no)
  1282. {$ifdef i386}
  1283. or (
  1284. (ref^.refaddr in [addr_pic]) and
  1285. (ref^.base<>NR_NO)
  1286. )
  1287. {$endif i386}
  1288. {$ifdef x86_64}
  1289. or (
  1290. (ref^.refaddr in [addr_pic,addr_pic_no_got]) and
  1291. (ref^.base<>NR_NO)
  1292. )
  1293. {$endif x86_64}
  1294. then
  1295. begin
  1296. { create ot field }
  1297. if (reg_ot_table[findreg_by_number(ref^.base)] and OT_REG_GPR = OT_REG_GPR) and
  1298. ((reg_ot_table[findreg_by_number(ref^.index)] = OT_XMMREG) or
  1299. (reg_ot_table[findreg_by_number(ref^.index)] = OT_YMMREG) or
  1300. (reg_ot_table[findreg_by_number(ref^.index)] = OT_ZMMREG)
  1301. ) then
  1302. // AVX2 - vector-memory-referenz (e.g. vgatherdpd xmm0, [rax xmm1], xmm2)
  1303. ot := (reg_ot_table[findreg_by_number(ref^.base)] and OT_REG_GPR) or
  1304. (reg_ot_table[findreg_by_number(ref^.index)])
  1305. else if (ref^.base = NR_NO) and
  1306. ((reg_ot_table[findreg_by_number(ref^.index)] = OT_XMMREG) or
  1307. (reg_ot_table[findreg_by_number(ref^.index)] = OT_YMMREG) or
  1308. (reg_ot_table[findreg_by_number(ref^.index)] = OT_ZMMREG)
  1309. ) then
  1310. // AVX2 - vector-memory-referenz without base-register (e.g. vgatherdpd xmm0, [xmm1], xmm2)
  1311. ot := (OT_REG_GPR) or
  1312. (reg_ot_table[findreg_by_number(ref^.index)])
  1313. else if (ot and OT_SIZE_MASK)=0 then
  1314. ot:=OT_MEMORY_ANY or opsize_2_type[i,opsize]
  1315. else
  1316. ot:=OT_MEMORY_ANY or (ot and OT_SIZE_MASK);
  1317. if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
  1318. ot:=ot or OT_MEM_OFFS;
  1319. { fix scalefactor }
  1320. if (ref^.index=NR_NO) then
  1321. ref^.scalefactor:=0
  1322. else
  1323. if (ref^.scalefactor=0) then
  1324. ref^.scalefactor:=1;
  1325. end
  1326. else
  1327. begin
  1328. { Jumps use a relative offset which can be 8bit,
  1329. for other opcodes we always need to generate the full
  1330. 32bit address }
  1331. if assigned(objdata) and
  1332. is_jmp then
  1333. begin
  1334. currsym:=objdata.symbolref(ref^.symbol);
  1335. l:=ref^.offset;
  1336. {$push}
  1337. {$r-,q-} { disable also overflow as address returns a qword for x86_64 }
  1338. if assigned(currsym) then
  1339. inc(l,currsym.address);
  1340. {$pop}
  1341. { when it is a forward jump we need to compensate the
  1342. offset of the instruction since the previous time,
  1343. because the symbol address is then still using the
  1344. 'old-style' addressing.
  1345. For backwards jumps this is not required because the
  1346. address of the symbol is already adjusted to the
  1347. new offset }
  1348. if (l>InsOffset) and (LastInsOffset<>-1) then
  1349. inc(l,InsOffset-LastInsOffset);
  1350. { instruction size will then always become 2 (PFV) }
  1351. relsize:=(InsOffset+2)-l;
  1352. if (relsize>=-128) and (relsize<=127) and
  1353. (
  1354. not assigned(currsym) or
  1355. (currsym.objsection=objdata.currobjsec)
  1356. ) then
  1357. ot:=OT_IMM8 or OT_SHORT
  1358. else
  1359. {$ifdef i8086}
  1360. ot:=OT_IMM16 or OT_NEAR;
  1361. {$else i8086}
  1362. ot:=OT_IMM32 or OT_NEAR;
  1363. {$endif i8086}
  1364. end
  1365. else
  1366. {$ifdef i8086}
  1367. if opsize=S_FAR then
  1368. ot:=OT_IMM16 or OT_FAR
  1369. else
  1370. ot:=OT_IMM16 or OT_NEAR;
  1371. {$else i8086}
  1372. ot:=OT_IMM32 or OT_NEAR;
  1373. {$endif i8086}
  1374. end;
  1375. end;
  1376. top_local :
  1377. begin
  1378. if (ot and OT_SIZE_MASK)=0 then
  1379. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  1380. else
  1381. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  1382. end;
  1383. top_const :
  1384. begin
  1385. // if opcode is a SSE or AVX-instruction then we need a
  1386. // special handling (opsize can different from const-size)
  1387. // (e.g. "pextrw reg/m16, xmmreg, imm8" =>> opsize (16 bit), const-size (8 bit)
  1388. if (InsTabMemRefSizeInfoCache^[opcode].ExistsSSEAVX) and
  1389. (not(InsTabMemRefSizeInfoCache^[opcode].ConstSize in [csiMultiple, csiUnkown])) then
  1390. begin
  1391. case InsTabMemRefSizeInfoCache^[opcode].ConstSize of
  1392. csiNoSize: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE;
  1393. csiMem8: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS8;
  1394. csiMem16: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS16;
  1395. csiMem32: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS32;
  1396. csiMem64: ot := ot and (not(OT_SIZE_MASK)) or OT_IMMEDIATE or OT_BITS64;
  1397. end;
  1398. end
  1399. else
  1400. begin
  1401. { allow 2nd, 3rd or 4th operand being a constant and expect no size for shuf* etc. }
  1402. { further, allow AAD and AAM with imm. operand }
  1403. if (opsize=S_NO) and not((i in [1,2,3])
  1404. {$ifndef x86_64}
  1405. or ((i=0) and (opcode in [A_AAD,A_AAM]))
  1406. {$endif x86_64}
  1407. ) then
  1408. message(asmr_e_invalid_opcode_and_operand);
  1409. if
  1410. {$ifdef i8086}
  1411. (longint(val)>=-128) and (val<=127) then
  1412. {$else i8086}
  1413. (opsize<>S_W) and
  1414. (aint(val)>=-128) and (val<=127) then
  1415. {$endif not i8086}
  1416. ot:=OT_IMM8 or OT_SIGNED
  1417. else
  1418. ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
  1419. if (val=1) and (i=1) then
  1420. ot := ot or OT_ONENESS;
  1421. end;
  1422. end;
  1423. top_none :
  1424. begin
  1425. { generated when there was an error in the
  1426. assembler reader. It never happends when generating
  1427. assembler }
  1428. end;
  1429. else
  1430. internalerror(200402266);
  1431. end;
  1432. end;
  1433. end;
  1434. function taicpu.InsEnd:longint;
  1435. begin
  1436. InsEnd:=InsOffset+InsSize;
  1437. end;
  1438. function taicpu.Matches(p:PInsEntry):boolean;
  1439. { * IF_SM stands for Size Match: any operand whose size is not
  1440. * explicitly specified by the template is `really' intended to be
  1441. * the same size as the first size-specified operand.
  1442. * Non-specification is tolerated in the input instruction, but
  1443. * _wrong_ specification is not.
  1444. *
  1445. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  1446. * three-operand instructions such as SHLD: it implies that the
  1447. * first two operands must match in size, but that the third is
  1448. * required to be _unspecified_.
  1449. *
  1450. * IF_SB invokes Size Byte: operands with unspecified size in the
  1451. * template are really bytes, and so no non-byte specification in
  1452. * the input instruction will be tolerated. IF_SW similarly invokes
  1453. * Size Word, and IF_SD invokes Size Doubleword.
  1454. *
  1455. * (The default state if neither IF_SM nor IF_SM2 is specified is
  1456. * that any operand with unspecified size in the template is
  1457. * required to have unspecified size in the instruction too...)
  1458. }
  1459. var
  1460. insot,
  1461. currot: int64;
  1462. i,j,asize,oprs : longint;
  1463. insflags:tinsflags;
  1464. vopext: int64;
  1465. siz : array[0..max_operands-1] of longint;
  1466. begin
  1467. result:=false;
  1468. { Check the opcode and operands }
  1469. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  1470. exit;
  1471. {$ifdef i8086}
  1472. { On i8086, we need to skip the i386+ version of Jcc near, if the target
  1473. cpu is earlier than 386. There's another entry, later in the table for
  1474. i8086, which simulates it with i8086 instructions:
  1475. JNcc short +3
  1476. JMP near target }
  1477. if (p^.opcode=A_Jcc) and (current_settings.cputype<cpu_386) and
  1478. (IF_386 in p^.flags) then
  1479. exit;
  1480. {$endif i8086}
  1481. for i:=0 to p^.ops-1 do
  1482. begin
  1483. insot:=p^.optypes[i];
  1484. currot:=oper[i]^.ot;
  1485. { Check the operand flags }
  1486. if (insot and (not currot) and OT_NON_SIZE)<>0 then
  1487. exit;
  1488. { Check if the passed operand size matches with one of
  1489. the supported operand sizes }
  1490. if ((insot and OT_SIZE_MASK)<>0) and
  1491. ((insot and currot and OT_SIZE_MASK)<>(currot and OT_SIZE_MASK)) then
  1492. exit;
  1493. { "far" matches only with "far" }
  1494. if (insot and OT_FAR)<>(currot and OT_FAR) then
  1495. exit;
  1496. end;
  1497. { Check operand sizes }
  1498. insflags:=p^.flags;
  1499. if (insflags*IF_SMASK)<>[] then
  1500. begin
  1501. { as default an untyped size can get all the sizes, this is different
  1502. from nasm, but else we need to do a lot checking which opcodes want
  1503. size or not with the automatic size generation }
  1504. asize:=-1;
  1505. if IF_SB in insflags then
  1506. asize:=OT_BITS8
  1507. else if IF_SW in insflags then
  1508. asize:=OT_BITS16
  1509. else if IF_SD in insflags then
  1510. asize:=OT_BITS32;
  1511. if insflags*IF_ARMASK<>[] then
  1512. begin
  1513. siz[0]:=-1;
  1514. siz[1]:=-1;
  1515. siz[2]:=-1;
  1516. if IF_AR0 in insflags then
  1517. siz[0]:=asize
  1518. else if IF_AR1 in insflags then
  1519. siz[1]:=asize
  1520. else if IF_AR2 in insflags then
  1521. siz[2]:=asize
  1522. else
  1523. internalerror(2017092101);
  1524. end
  1525. else
  1526. begin
  1527. siz[0]:=asize;
  1528. siz[1]:=asize;
  1529. siz[2]:=asize;
  1530. end;
  1531. if insflags*[IF_SM,IF_SM2]<>[] then
  1532. begin
  1533. if IF_SM2 in insflags then
  1534. oprs:=2
  1535. else
  1536. oprs:=p^.ops;
  1537. for i:=0 to oprs-1 do
  1538. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  1539. begin
  1540. for j:=0 to oprs-1 do
  1541. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  1542. break;
  1543. end;
  1544. end
  1545. else
  1546. oprs:=2;
  1547. { Check operand sizes }
  1548. for i:=0 to p^.ops-1 do
  1549. begin
  1550. insot:=p^.optypes[i];
  1551. currot:=oper[i]^.ot;
  1552. if ((insot and OT_SIZE_MASK)=0) and
  1553. ((currot and OT_SIZE_MASK and (not siz[i]))<>0) and
  1554. { Immediates can always include smaller size }
  1555. ((currot and OT_IMMEDIATE)=0) and
  1556. (((insot and OT_SIZE_MASK) or siz[i])<(currot and OT_SIZE_MASK)) then
  1557. exit;
  1558. if (insot and OT_FAR)<>(currot and OT_FAR) then
  1559. exit;
  1560. end;
  1561. end;
  1562. if (InsTabMemRefSizeInfoCache^[opcode].MemRefSize in MemRefMultiples) and
  1563. (InsTabMemRefSizeInfoCache^[opcode].ExistsSSEAVX) then
  1564. begin
  1565. for i:=0 to p^.ops-1 do
  1566. begin
  1567. insot:=p^.optypes[i];
  1568. if ((insot and (OT_XMMRM or OT_REG_EXTRA_MASK)) = OT_XMMRM) OR
  1569. ((insot and (OT_YMMRM or OT_REG_EXTRA_MASK)) = OT_YMMRM) OR
  1570. ((insot and (OT_ZMMRM or OT_REG_EXTRA_MASK)) = OT_ZMMRM) then
  1571. begin
  1572. if (insot and OT_SIZE_MASK) = 0 then
  1573. begin
  1574. case insot and (OT_XMMRM or OT_YMMRM or OT_ZMMRM or OT_REG_EXTRA_MASK) of
  1575. OT_XMMRM: insot := insot or OT_BITS128;
  1576. OT_YMMRM: insot := insot or OT_BITS256;
  1577. OT_ZMMRM: insot := insot or OT_BITS512;
  1578. end;
  1579. end;
  1580. end;
  1581. currot:=oper[i]^.ot;
  1582. { Check the operand flags }
  1583. if (insot and (not currot) and OT_NON_SIZE)<>0 then
  1584. exit;
  1585. { Check if the passed operand size matches with one of
  1586. the supported operand sizes }
  1587. if ((insot and OT_SIZE_MASK)<>0) and
  1588. ((insot and currot and OT_SIZE_MASK)<>(currot and OT_SIZE_MASK)) then
  1589. exit;
  1590. end;
  1591. end;
  1592. if (InsTabMemRefSizeInfoCache^[opcode].ExistsSSEAVX) then
  1593. begin
  1594. for i:=0 to p^.ops-1 do
  1595. begin
  1596. // check vectoroperand-extention e.g. {k1} {z}
  1597. vopext := 0;
  1598. if (oper[i]^.vopext and OTVE_VECTOR_WRITEMASK) = OTVE_VECTOR_WRITEMASK then
  1599. begin
  1600. vopext := vopext or OT_VECTORMASK;
  1601. if (oper[i]^.vopext and OTVE_VECTOR_ZERO) = OTVE_VECTOR_ZERO then
  1602. vopext := vopext or OT_VECTORZERO;
  1603. end;
  1604. if (oper[i]^.vopext and OTVE_VECTOR_BCST) = OTVE_VECTOR_BCST then
  1605. begin
  1606. vopext := vopext or OT_VECTORBCST;
  1607. if (InsTabMemRefSizeInfoCache^[opcode].BCSTTypes <> []) then
  1608. begin
  1609. // any opcodes needs a special handling
  1610. // default broadcast calculation is
  1611. // bmem32
  1612. // xmmreg: {1to4}
  1613. // ymmreg: {1to8}
  1614. // zmmreg: {1to16}
  1615. // bmem64
  1616. // xmmreg: {1to2}
  1617. // ymmreg: {1to4}
  1618. // zmmreg: {1to8}
  1619. // in any opcodes not exists a mmregister
  1620. // e.g. vfpclasspd k1, [RAX] {1to8}, 0
  1621. // =>> check flags
  1622. case oper[i]^.vopext and (OTVE_VECTOR_BCST2 or OTVE_VECTOR_BCST4 or OTVE_VECTOR_BCST8 or OTVE_VECTOR_BCST16) of
  1623. OTVE_VECTOR_BCST2: if not(IF_BCST2 in p^.flags) then exit;
  1624. OTVE_VECTOR_BCST4: if not(IF_BCST4 in p^.flags) then exit;
  1625. OTVE_VECTOR_BCST8: if not(IF_BCST8 in p^.flags) then exit;
  1626. OTVE_VECTOR_BCST16: if not(IF_BCST16 in p^.flags) then exit;
  1627. else exit; //TG TODO errormsg
  1628. end;
  1629. end;
  1630. end;
  1631. if (oper[i]^.vopext and OTVE_VECTOR_ER) = OTVE_VECTOR_ER then
  1632. vopext := vopext or OT_VECTORER;
  1633. if (oper[i]^.vopext and OTVE_VECTOR_SAE) = OTVE_VECTOR_SAE then
  1634. vopext := vopext or OT_VECTORSAE;
  1635. if p^.optypes[i] and vopext <> vopext then
  1636. exit;
  1637. end;
  1638. end;
  1639. result:=true;
  1640. end;
  1641. procedure taicpu.ResetPass1;
  1642. begin
  1643. { we need to reset everything here, because the choosen insentry
  1644. can be invalid for a new situation where the previously optimized
  1645. insentry is not correct }
  1646. InsEntry:=nil;
  1647. InsSize:=0;
  1648. LastInsOffset:=-1;
  1649. end;
  1650. procedure taicpu.ResetPass2;
  1651. begin
  1652. { we are here in a second pass, check if the instruction can be optimized }
  1653. if assigned(InsEntry) and
  1654. (IF_PASS2 in InsEntry^.flags) then
  1655. begin
  1656. InsEntry:=nil;
  1657. InsSize:=0;
  1658. end;
  1659. LastInsOffset:=-1;
  1660. end;
  1661. function taicpu.CheckIfValid:boolean;
  1662. begin
  1663. result:=FindInsEntry(nil);
  1664. end;
  1665. function taicpu.FindInsentry(objdata:TObjData):boolean;
  1666. var
  1667. i : longint;
  1668. //TG TODO delete
  1669. p: pInsentry;
  1670. begin
  1671. result:=false;
  1672. { Things which may only be done once, not when a second pass is done to
  1673. optimize }
  1674. //TG TODO delete
  1675. p := Insentry;
  1676. if (Insentry=nil) or (IF_PASS2 in InsEntry^.flags) then
  1677. begin
  1678. current_filepos:=fileinfo;
  1679. { We need intel style operands }
  1680. SetOperandOrder(op_intel);
  1681. { create the .ot fields }
  1682. create_ot(objdata);
  1683. { set the file postion }
  1684. end
  1685. else
  1686. begin
  1687. { we've already an insentry so it's valid }
  1688. result:=true;
  1689. exit;
  1690. end;
  1691. { Lookup opcode in the table }
  1692. InsSize:=-1;
  1693. i:=instabcache^[opcode];
  1694. if i=-1 then
  1695. begin
  1696. Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
  1697. exit;
  1698. end;
  1699. insentry:=@instab[i];
  1700. while (insentry^.opcode=opcode) do
  1701. begin
  1702. if matches(insentry) then
  1703. begin
  1704. result:=true;
  1705. exit;
  1706. end;
  1707. inc(insentry);
  1708. end;
  1709. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  1710. { No instruction found, set insentry to nil and inssize to -1 }
  1711. insentry:=nil;
  1712. inssize:=-1;
  1713. end;
  1714. function taicpu.CheckUseEVEX: boolean;
  1715. var
  1716. i: integer;
  1717. begin
  1718. result := false;
  1719. for i := 0 to ops - 1 do
  1720. begin
  1721. if (oper[i]^.typ=top_reg) and
  1722. (getregtype(oper[i]^.reg) = R_MMREGISTER) then
  1723. if getsupreg(oper[i]^.reg)>=16 then
  1724. result := true;
  1725. if (oper[i]^.vopext and OTVE_VECTOR_MASK) <> 0 then
  1726. result := true;
  1727. end;
  1728. end;
  1729. function taicpu.Pass1(objdata:TObjData):longint;
  1730. begin
  1731. Pass1:=0;
  1732. { Save the old offset and set the new offset }
  1733. InsOffset:=ObjData.CurrObjSec.Size;
  1734. { Error? }
  1735. if (Insentry=nil) and (InsSize=-1) then
  1736. exit;
  1737. { set the file postion }
  1738. current_filepos:=fileinfo;
  1739. { Get InsEntry }
  1740. if FindInsEntry(ObjData) then
  1741. begin
  1742. { Calculate instruction size }
  1743. InsSize:=calcsize(insentry);
  1744. if segprefix<>NR_NO then
  1745. inc(InsSize);
  1746. if NeedAddrPrefix then
  1747. inc(InsSize);
  1748. { Fix opsize if size if forced }
  1749. if insentry^.flags*[IF_SB,IF_SW,IF_SD]<>[] then
  1750. begin
  1751. if insentry^.flags*IF_ARMASK=[] then
  1752. begin
  1753. if IF_SB in insentry^.flags then
  1754. begin
  1755. if opsize=S_NO then
  1756. opsize:=S_B;
  1757. end
  1758. else if IF_SW in insentry^.flags then
  1759. begin
  1760. if opsize=S_NO then
  1761. opsize:=S_W;
  1762. end
  1763. else if IF_SD in insentry^.flags then
  1764. begin
  1765. if opsize=S_NO then
  1766. opsize:=S_L;
  1767. end;
  1768. end;
  1769. end;
  1770. LastInsOffset:=InsOffset;
  1771. Pass1:=InsSize;
  1772. exit;
  1773. end;
  1774. LastInsOffset:=-1;
  1775. end;
  1776. const
  1777. segprefixes: array[NR_ES..NR_GS] of Byte=(
  1778. // es cs ss ds fs gs
  1779. $26, $2E, $36, $3E, $64, $65
  1780. );
  1781. procedure taicpu.Pass2(objdata:TObjData);
  1782. begin
  1783. { error in pass1 ? }
  1784. if insentry=nil then
  1785. exit;
  1786. current_filepos:=fileinfo;
  1787. { Segment override }
  1788. if (segprefix>=NR_ES) and (segprefix<=NR_GS) then
  1789. begin
  1790. {$ifdef i8086}
  1791. if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) and
  1792. ((segprefix=NR_FS) or (segprefix=NR_GS)) then
  1793. Message(asmw_e_instruction_not_supported_by_cpu);
  1794. {$endif i8086}
  1795. objdata.writebytes(segprefixes[segprefix],1);
  1796. { fix the offset for GenNode }
  1797. inc(InsOffset);
  1798. end
  1799. else if segprefix<>NR_NO then
  1800. InternalError(201001071);
  1801. { Address size prefix? }
  1802. if NeedAddrPrefix then
  1803. begin
  1804. write0x67prefix(objdata);
  1805. { fix the offset for GenNode }
  1806. inc(InsOffset);
  1807. end;
  1808. { Generate the instruction }
  1809. GenCode(objdata);
  1810. end;
  1811. function is_64_bit_ref(const ref:treference):boolean;
  1812. begin
  1813. {$if defined(x86_64)}
  1814. result:=not is_32_bit_ref(ref);
  1815. {$elseif defined(i386) or defined(i8086)}
  1816. result:=false;
  1817. {$endif}
  1818. end;
  1819. function is_32_bit_ref(const ref:treference):boolean;
  1820. begin
  1821. {$if defined(x86_64)}
  1822. result:=(ref.refaddr=addr_no) and
  1823. (ref.base<>NR_RIP) and
  1824. (
  1825. ((ref.index<>NR_NO) and (getsubreg(ref.index)=R_SUBD)) or
  1826. ((ref.base<>NR_NO) and (getsubreg(ref.base)=R_SUBD))
  1827. );
  1828. {$elseif defined(i386) or defined(i8086)}
  1829. result:=not is_16_bit_ref(ref);
  1830. {$endif}
  1831. end;
  1832. function is_16_bit_ref(const ref:treference):boolean;
  1833. var
  1834. ir,br : Tregister;
  1835. isub,bsub : tsubregister;
  1836. begin
  1837. if (ref.index<>NR_NO) and (getregtype(ref.index)=R_MMREGISTER) then
  1838. exit(false);
  1839. ir:=ref.index;
  1840. br:=ref.base;
  1841. isub:=getsubreg(ir);
  1842. bsub:=getsubreg(br);
  1843. { it's a direct address }
  1844. if (br=NR_NO) and (ir=NR_NO) then
  1845. begin
  1846. {$ifdef i8086}
  1847. result:=true;
  1848. {$else i8086}
  1849. result:=false;
  1850. {$endif}
  1851. end
  1852. else
  1853. { it's an indirection }
  1854. begin
  1855. result := ((ir<>NR_NO) and (isub=R_SUBW)) or
  1856. ((br<>NR_NO) and (bsub=R_SUBW));
  1857. end;
  1858. end;
  1859. function get_ref_address_size(const ref:treference):byte;
  1860. begin
  1861. if is_64_bit_ref(ref) then
  1862. result:=64
  1863. else if is_32_bit_ref(ref) then
  1864. result:=32
  1865. else if is_16_bit_ref(ref) then
  1866. result:=16
  1867. else
  1868. internalerror(2017101601);
  1869. end;
  1870. function get_default_segment_of_ref(const ref:treference):tregister;
  1871. begin
  1872. { for 16-bit registers, we allow base and index to be swapped, that's
  1873. why we also we check whether ref.index=NR_BP. For 32-bit registers,
  1874. however, index=NR_EBP is encoded differently than base=NR_EBP and has
  1875. a different default segment. }
  1876. if (ref.base=NR_BP) or (ref.index=NR_BP) or
  1877. (ref.base=NR_EBP) or (ref.base=NR_ESP)
  1878. {$ifdef x86_64}
  1879. or (ref.base=NR_RBP) or (ref.base=NR_RSP)
  1880. {$endif x86_64}
  1881. then
  1882. result:=NR_SS
  1883. else
  1884. result:=NR_DS;
  1885. end;
  1886. procedure optimize_ref(var ref:treference; inlineasm: boolean);
  1887. var
  1888. ss_equals_ds: boolean;
  1889. tmpreg: TRegister;
  1890. begin
  1891. {$ifdef x86_64}
  1892. { x86_64 in long mode ignores all segment base, limit and access rights
  1893. checks for the DS, ES and SS registers, so we can set ss_equals_ds to
  1894. true (and thus, perform stronger optimizations on the reference),
  1895. regardless of whether this is inline asm or not (so, even if the user
  1896. is doing tricks by loading different values into DS and SS, it still
  1897. doesn't matter while the processor is in long mode) }
  1898. ss_equals_ds:=True;
  1899. {$else x86_64}
  1900. { for i8086 and i386 inline asm, we assume SS<>DS, even if we're
  1901. compiling for a memory model, where SS=DS, because the user might be
  1902. doing something tricky with the segment registers (and may have
  1903. temporarily set them differently) }
  1904. if inlineasm then
  1905. ss_equals_ds:=False
  1906. else
  1907. ss_equals_ds:=segment_regs_equal(NR_DS,NR_SS);
  1908. {$endif x86_64}
  1909. { remove redundant segment overrides }
  1910. if (ref.segment<>NR_NO) and
  1911. ((inlineasm and (ref.segment=get_default_segment_of_ref(ref))) or
  1912. ((not inlineasm) and (segment_regs_equal(ref.segment,get_default_segment_of_ref(ref))))) then
  1913. ref.segment:=NR_NO;
  1914. if not is_16_bit_ref(ref) then
  1915. begin
  1916. { Switching index to base position gives shorter assembler instructions.
  1917. Converting index*2 to base+index also gives shorter instructions. }
  1918. if (ref.base=NR_NO) and (ref.index<>NR_NO) and (ref.scalefactor<=2) and
  1919. (ss_equals_ds or (ref.segment<>NR_NO) or (ref.index<>NR_EBP)) then
  1920. begin
  1921. ref.base:=ref.index;
  1922. if ref.scalefactor=2 then
  1923. ref.scalefactor:=1
  1924. else
  1925. begin
  1926. ref.index:=NR_NO;
  1927. ref.scalefactor:=0;
  1928. end;
  1929. end;
  1930. { Switching rBP+reg to reg+rBP sometimes gives shorter instructions (if there's no offset)
  1931. On x86_64 this also works for switching r13+reg to reg+r13. }
  1932. if ((ref.base=NR_EBP) {$ifdef x86_64}or (ref.base=NR_RBP) or (ref.base=NR_R13) or (ref.base=NR_R13D){$endif}) and
  1933. (ref.index<>NR_NO) and
  1934. (ref.index<>NR_EBP) and {$ifdef x86_64}(ref.index<>NR_RBP) and (ref.index<>NR_R13) and (ref.index<>NR_R13D) and{$endif}
  1935. (ref.scalefactor<=1) and (ref.offset=0) and (ref.refaddr=addr_no) and
  1936. (ss_equals_ds or (ref.segment<>NR_NO)) then
  1937. begin
  1938. tmpreg:=ref.base;
  1939. ref.base:=ref.index;
  1940. ref.index:=tmpreg;
  1941. end;
  1942. end;
  1943. { remove redundant segment overrides again }
  1944. if (ref.segment<>NR_NO) and
  1945. ((inlineasm and (ref.segment=get_default_segment_of_ref(ref))) or
  1946. ((not inlineasm) and (segment_regs_equal(ref.segment,get_default_segment_of_ref(ref))))) then
  1947. ref.segment:=NR_NO;
  1948. end;
  1949. function taicpu.NeedAddrPrefix(opidx: byte): boolean;
  1950. begin
  1951. {$if defined(x86_64)}
  1952. result:=(oper[opidx]^.typ=top_ref) and is_32_bit_ref(oper[opidx]^.ref^);
  1953. {$elseif defined(i386)}
  1954. result:=(oper[opidx]^.typ=top_ref) and is_16_bit_ref(oper[opidx]^.ref^);
  1955. {$elseif defined(i8086)}
  1956. result:=(oper[opidx]^.typ=top_ref) and is_32_bit_ref(oper[opidx]^.ref^);
  1957. {$endif}
  1958. end;
  1959. function taicpu.NeedAddrPrefix:boolean;
  1960. var
  1961. i: Integer;
  1962. begin
  1963. for i:=0 to ops-1 do
  1964. if needaddrprefix(i) then
  1965. exit(true);
  1966. result:=false;
  1967. end;
  1968. procedure badreg(r:Tregister);
  1969. begin
  1970. Message1(asmw_e_invalid_register,generic_regname(r));
  1971. end;
  1972. function regval(r:Tregister):byte;
  1973. const
  1974. intsupreg2opcode: array[0..7] of byte=
  1975. // ax cx dx bx si di bp sp -- in x86reg.dat
  1976. // ax cx dx bx sp bp si di -- needed order
  1977. (0, 1, 2, 3, 6, 7, 5, 4);
  1978. maxsupreg: array[tregistertype] of tsuperregister=
  1979. {$ifdef x86_64}
  1980. //(0, 16, 9, 8, 16, 32, 0, 0);
  1981. (0, 16, 9, 8, 32, 32, 8, 0); //TG
  1982. {$else x86_64}
  1983. (0, 8, 9, 8, 8, 32, 8, 0);
  1984. {$endif x86_64}
  1985. var
  1986. rs: tsuperregister;
  1987. rt: tregistertype;
  1988. begin
  1989. rs:=getsupreg(r);
  1990. rt:=getregtype(r);
  1991. if (rs>=maxsupreg[rt]) then
  1992. badreg(r);
  1993. result:=rs and 7;
  1994. if (rt=R_INTREGISTER) then
  1995. begin
  1996. if (rs<8) then
  1997. result:=intsupreg2opcode[rs];
  1998. if getsubreg(r)=R_SUBH then
  1999. inc(result,4);
  2000. end;
  2001. end;
  2002. {$if defined(x86_64)}
  2003. function rexbits(r: tregister): byte;
  2004. begin
  2005. result:=0;
  2006. case getregtype(r) of
  2007. R_INTREGISTER:
  2008. if (getsupreg(r)>=RS_R8) then
  2009. { Either B,X or R bits can be set, depending on register role in instruction.
  2010. Set all three bits here, caller will discard unnecessary ones. }
  2011. result:=result or $47
  2012. else if (getsubreg(r)=R_SUBL) and
  2013. (getsupreg(r) in [RS_RDI,RS_RSI,RS_RBP,RS_RSP]) then
  2014. result:=result or $40
  2015. else if (getsubreg(r)=R_SUBH) then
  2016. { Not an actual REX bit, used to detect incompatible usage of
  2017. AH/BH/CH/DH }
  2018. result:=result or $80;
  2019. R_MMREGISTER:
  2020. //if getsupreg(r)>=RS_XMM8 then
  2021. // AVX512 = 32 register
  2022. // rexbit = 0 => MMRegister 0..7 or 16..23
  2023. // rexbit = 1 => MMRegister 8..15 or 24..31
  2024. if (getsupreg(r) and $08) = $08 then
  2025. result:=result or $47;
  2026. end;
  2027. end;
  2028. function process_ea_ref_64_32(const input:toper;var output:ea;rfield:longint; uselargeoffset: boolean):boolean;
  2029. var
  2030. sym : tasmsymbol;
  2031. md,s : byte;
  2032. base,index,scalefactor,
  2033. o : longint;
  2034. ir,br : Tregister;
  2035. isub,bsub : tsubregister;
  2036. begin
  2037. result:=false;
  2038. ir:=input.ref^.index;
  2039. br:=input.ref^.base;
  2040. isub:=getsubreg(ir);
  2041. bsub:=getsubreg(br);
  2042. s:=input.ref^.scalefactor;
  2043. o:=input.ref^.offset;
  2044. sym:=input.ref^.symbol;
  2045. //if ((ir<>NR_NO) and (getregtype(ir)<>R_INTREGISTER)) or
  2046. // ((br<>NR_NO) and (br<>NR_RIP) and (getregtype(br)<>R_INTREGISTER)) then
  2047. if ((ir<>NR_NO) and (getregtype(ir)=R_MMREGISTER) and (br<>NR_NO) and (getregtype(br)<>R_INTREGISTER)) or // vector memory (AVX2)
  2048. ((ir<>NR_NO) and (getregtype(ir)<>R_INTREGISTER) and (getregtype(ir)<>R_MMREGISTER)) or
  2049. ((br<>NR_NO) and (br<>NR_RIP) and (getregtype(br)<>R_INTREGISTER)) then
  2050. internalerror(200301081);
  2051. { it's direct address }
  2052. if (br=NR_NO) and (ir=NR_NO) then
  2053. begin
  2054. output.sib_present:=true;
  2055. output.bytes:=4;
  2056. output.modrm:=4 or (rfield shl 3);
  2057. output.sib:=$25;
  2058. end
  2059. else if (br=NR_RIP) and (ir=NR_NO) then
  2060. begin
  2061. { rip based }
  2062. output.sib_present:=false;
  2063. output.bytes:=4;
  2064. output.modrm:=5 or (rfield shl 3);
  2065. end
  2066. else
  2067. { it's an indirection }
  2068. begin
  2069. { 16 bit? }
  2070. if ((ir<>NR_NO) and (isub in [R_SUBMMX,R_SUBMMY,R_SUBMMZ]) and
  2071. (br<>NR_NO) and (bsub=R_SUBQ)
  2072. ) then
  2073. begin
  2074. // vector memory (AVX2) =>> ignore
  2075. end
  2076. else if ((ir<>NR_NO) and (isub<>R_SUBQ) and (isub<>R_SUBD)) or
  2077. ((br<>NR_NO) and (bsub<>R_SUBQ) and (bsub<>R_SUBD)) then
  2078. begin
  2079. message(asmw_e_16bit_32bit_not_supported);
  2080. end;
  2081. { wrong, for various reasons }
  2082. if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
  2083. exit;
  2084. output.rex:=output.rex or (rexbits(br) and $F1) or (rexbits(ir) and $F2);
  2085. result:=true;
  2086. { base }
  2087. case br of
  2088. NR_R8D,
  2089. NR_EAX,
  2090. NR_R8,
  2091. NR_RAX : base:=0;
  2092. NR_R9D,
  2093. NR_ECX,
  2094. NR_R9,
  2095. NR_RCX : base:=1;
  2096. NR_R10D,
  2097. NR_EDX,
  2098. NR_R10,
  2099. NR_RDX : base:=2;
  2100. NR_R11D,
  2101. NR_EBX,
  2102. NR_R11,
  2103. NR_RBX : base:=3;
  2104. NR_R12D,
  2105. NR_ESP,
  2106. NR_R12,
  2107. NR_RSP : base:=4;
  2108. NR_R13D,
  2109. NR_EBP,
  2110. NR_R13,
  2111. NR_NO,
  2112. NR_RBP : base:=5;
  2113. NR_R14D,
  2114. NR_ESI,
  2115. NR_R14,
  2116. NR_RSI : base:=6;
  2117. NR_R15D,
  2118. NR_EDI,
  2119. NR_R15,
  2120. NR_RDI : base:=7;
  2121. else
  2122. exit;
  2123. end;
  2124. { index }
  2125. case ir of
  2126. NR_R8D,
  2127. NR_EAX,
  2128. NR_R8,
  2129. NR_RAX,
  2130. NR_XMM0,
  2131. NR_XMM8,
  2132. NR_XMM16,
  2133. NR_XMM24,
  2134. NR_YMM0,
  2135. NR_YMM8,
  2136. NR_YMM16,
  2137. NR_YMM24,
  2138. NR_ZMM0,
  2139. NR_ZMM8,
  2140. NR_ZMM16,
  2141. NR_ZMM24: index:=0;
  2142. NR_R9D,
  2143. NR_ECX,
  2144. NR_R9,
  2145. NR_RCX,
  2146. NR_XMM1,
  2147. NR_XMM9,
  2148. NR_XMM17,
  2149. NR_XMM25,
  2150. NR_YMM1,
  2151. NR_YMM9,
  2152. NR_YMM17,
  2153. NR_YMM25,
  2154. NR_ZMM1,
  2155. NR_ZMM9,
  2156. NR_ZMM17,
  2157. NR_ZMM25: index:=1;
  2158. NR_R10D,
  2159. NR_EDX,
  2160. NR_R10,
  2161. NR_RDX,
  2162. NR_XMM2,
  2163. NR_XMM10,
  2164. NR_XMM18,
  2165. NR_XMM26,
  2166. NR_YMM2,
  2167. NR_YMM10,
  2168. NR_YMM18,
  2169. NR_YMM26,
  2170. NR_ZMM2,
  2171. NR_ZMM10,
  2172. NR_ZMM18,
  2173. NR_ZMM26: index:=2;
  2174. NR_R11D,
  2175. NR_EBX,
  2176. NR_R11,
  2177. NR_RBX,
  2178. NR_XMM3,
  2179. NR_XMM11,
  2180. NR_XMM19,
  2181. NR_XMM27,
  2182. NR_YMM3,
  2183. NR_YMM11,
  2184. NR_YMM19,
  2185. NR_YMM27,
  2186. NR_ZMM3,
  2187. NR_ZMM11,
  2188. NR_ZMM19,
  2189. NR_ZMM27: index:=3;
  2190. NR_R12D,
  2191. NR_ESP,
  2192. NR_R12,
  2193. NR_NO,
  2194. NR_XMM4,
  2195. NR_XMM12,
  2196. NR_XMM20,
  2197. NR_XMM28,
  2198. NR_YMM4,
  2199. NR_YMM12,
  2200. NR_YMM20,
  2201. NR_YMM28,
  2202. NR_ZMM4,
  2203. NR_ZMM12,
  2204. NR_ZMM20,
  2205. NR_ZMM28: index:=4;
  2206. NR_R13D,
  2207. NR_EBP,
  2208. NR_R13,
  2209. NR_RBP,
  2210. NR_XMM5,
  2211. NR_XMM13,
  2212. NR_XMM21,
  2213. NR_XMM29,
  2214. NR_YMM5,
  2215. NR_YMM13,
  2216. NR_YMM21,
  2217. NR_YMM29,
  2218. NR_ZMM5,
  2219. NR_ZMM13,
  2220. NR_ZMM21,
  2221. NR_ZMM29: index:=5;
  2222. NR_R14D,
  2223. NR_ESI,
  2224. NR_R14,
  2225. NR_RSI,
  2226. NR_XMM6,
  2227. NR_XMM14,
  2228. NR_XMM22,
  2229. NR_XMM30,
  2230. NR_YMM6,
  2231. NR_YMM14,
  2232. NR_YMM22,
  2233. NR_YMM30,
  2234. NR_ZMM6,
  2235. NR_ZMM14,
  2236. NR_ZMM22,
  2237. NR_ZMM30: index:=6;
  2238. NR_R15D,
  2239. NR_EDI,
  2240. NR_R15,
  2241. NR_RDI,
  2242. NR_XMM7,
  2243. NR_XMM15,
  2244. NR_XMM23,
  2245. NR_XMM31,
  2246. NR_YMM7,
  2247. NR_YMM15,
  2248. NR_YMM23,
  2249. NR_YMM31,
  2250. NR_ZMM7,
  2251. NR_ZMM15,
  2252. NR_ZMM23,
  2253. NR_ZMM31: index:=7;
  2254. else
  2255. exit;
  2256. end;
  2257. case s of
  2258. 0,
  2259. 1 : scalefactor:=0;
  2260. 2 : scalefactor:=1;
  2261. 4 : scalefactor:=2;
  2262. 8 : scalefactor:=3;
  2263. else
  2264. exit;
  2265. end;
  2266. { If rbp or r13 is used we must always include an offset }
  2267. if (br=NR_NO) or
  2268. ((br<>NR_RBP) and (br<>NR_R13) and (br<>NR_EBP) and (br<>NR_R13D) and (o=0) and (sym=nil)) then
  2269. md:=0
  2270. else
  2271. if ((o>=-128) and (o<=127) and (sym=nil) and (not(uselargeoffset) or (o = 0))) then
  2272. md:=1
  2273. else
  2274. md:=2;
  2275. if (br=NR_NO) or (md=2) then
  2276. output.bytes:=4
  2277. else
  2278. output.bytes:=md;
  2279. { SIB needed ? }
  2280. if (ir=NR_NO) and (br<>NR_RSP) and (br<>NR_R12) and (br<>NR_ESP) and (br<>NR_R12D) then
  2281. begin
  2282. output.sib_present:=false;
  2283. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  2284. end
  2285. else
  2286. begin
  2287. output.sib_present:=true;
  2288. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  2289. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  2290. end;
  2291. end;
  2292. output.size:=1+ord(output.sib_present)+output.bytes;
  2293. result:=true;
  2294. end;
  2295. {$elseif defined(i386) or defined(i8086)}
  2296. function process_ea_ref_32(const input:toper;out output:ea;rfield:longint; uselargeoffset: boolean):boolean;
  2297. var
  2298. sym : tasmsymbol;
  2299. md,s : byte;
  2300. base,index,scalefactor,
  2301. o : longint;
  2302. ir,br : Tregister;
  2303. isub,bsub : tsubregister;
  2304. begin
  2305. result:=false;
  2306. if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)=R_MMREGISTER) and (input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) or // vector memory (AVX2)
  2307. ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER) and (getregtype(input.ref^.index)<>R_MMREGISTER)) or
  2308. ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
  2309. internalerror(200301081);
  2310. ir:=input.ref^.index;
  2311. br:=input.ref^.base;
  2312. isub:=getsubreg(ir);
  2313. bsub:=getsubreg(br);
  2314. s:=input.ref^.scalefactor;
  2315. o:=input.ref^.offset;
  2316. sym:=input.ref^.symbol;
  2317. { it's direct address }
  2318. if (br=NR_NO) and (ir=NR_NO) then
  2319. begin
  2320. { it's a pure offset }
  2321. output.sib_present:=false;
  2322. output.bytes:=4;
  2323. output.modrm:=5 or (rfield shl 3);
  2324. end
  2325. else
  2326. { it's an indirection }
  2327. begin
  2328. { 16 bit address? }
  2329. if ((ir<>NR_NO) and (isub in [R_SUBMMX,R_SUBMMY,R_SUBMMZ]) and
  2330. (br<>NR_NO) and (bsub=R_SUBD)
  2331. ) then
  2332. begin
  2333. // vector memory (AVX2) =>> ignore
  2334. end
  2335. else if ((ir<>NR_NO) and (isub<>R_SUBD)) or
  2336. ((br<>NR_NO) and (bsub<>R_SUBD)) then
  2337. message(asmw_e_16bit_not_supported);
  2338. {$ifdef OPTEA}
  2339. { make single reg base }
  2340. if (br=NR_NO) and (s=1) then
  2341. begin
  2342. br:=ir;
  2343. ir:=NR_NO;
  2344. end;
  2345. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  2346. if (br=NR_NO) and
  2347. (((s=2) and (ir<>NR_ESP)) or
  2348. (s=3) or (s=5) or (s=9)) then
  2349. begin
  2350. br:=ir;
  2351. dec(s);
  2352. end;
  2353. { swap ESP into base if scalefactor is 1 }
  2354. if (s=1) and (ir=NR_ESP) then
  2355. begin
  2356. ir:=br;
  2357. br:=NR_ESP;
  2358. end;
  2359. {$endif OPTEA}
  2360. { wrong, for various reasons }
  2361. if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
  2362. exit;
  2363. { base }
  2364. case br of
  2365. NR_EAX : base:=0;
  2366. NR_ECX : base:=1;
  2367. NR_EDX : base:=2;
  2368. NR_EBX : base:=3;
  2369. NR_ESP : base:=4;
  2370. NR_NO,
  2371. NR_EBP : base:=5;
  2372. NR_ESI : base:=6;
  2373. NR_EDI : base:=7;
  2374. else
  2375. exit;
  2376. end;
  2377. { index }
  2378. case ir of
  2379. NR_EAX,
  2380. NR_XMM0,
  2381. NR_YMM0,
  2382. NR_ZMM0: index:=0;
  2383. NR_ECX,
  2384. NR_XMM1,
  2385. NR_YMM1,
  2386. NR_ZMM1: index:=1;
  2387. NR_EDX,
  2388. NR_XMM2,
  2389. NR_YMM2,
  2390. NR_ZMM2: index:=2;
  2391. NR_EBX,
  2392. NR_XMM3,
  2393. NR_YMM3,
  2394. NR_ZMM3: index:=3;
  2395. NR_NO,
  2396. NR_XMM4,
  2397. NR_YMM4,
  2398. NR_ZMM4: index:=4;
  2399. NR_EBP,
  2400. NR_XMM5,
  2401. NR_YMM5,
  2402. NR_ZMM5: index:=5;
  2403. NR_ESI,
  2404. NR_XMM6,
  2405. NR_YMM6,
  2406. NR_ZMM6: index:=6;
  2407. NR_EDI,
  2408. NR_XMM7,
  2409. NR_YMM7,
  2410. NR_ZMM7: index:=7;
  2411. else
  2412. exit;
  2413. end;
  2414. case s of
  2415. 0,
  2416. 1 : scalefactor:=0;
  2417. 2 : scalefactor:=1;
  2418. 4 : scalefactor:=2;
  2419. 8 : scalefactor:=3;
  2420. else
  2421. exit;
  2422. end;
  2423. if (br=NR_NO) or
  2424. ((br<>NR_EBP) and (o=0) and (sym=nil)) then
  2425. md:=0
  2426. else
  2427. if ((o>=-128) and (o<=127) and (sym=nil) and (not(uselargeoffset) or (o = 0))) then
  2428. md:=1
  2429. else
  2430. md:=2;
  2431. if (br=NR_NO) or (md=2) then
  2432. output.bytes:=4
  2433. else
  2434. output.bytes:=md;
  2435. { SIB needed ? }
  2436. if (ir=NR_NO) and (br<>NR_ESP) then
  2437. begin
  2438. output.sib_present:=false;
  2439. output.modrm:=(longint(md) shl 6) or (rfield shl 3) or base;
  2440. end
  2441. else
  2442. begin
  2443. output.sib_present:=true;
  2444. output.modrm:=(longint(md) shl 6) or (rfield shl 3) or 4;
  2445. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  2446. end;
  2447. end;
  2448. if output.sib_present then
  2449. output.size:=2+output.bytes
  2450. else
  2451. output.size:=1+output.bytes;
  2452. result:=true;
  2453. end;
  2454. procedure maybe_swap_index_base(var br,ir:Tregister);
  2455. var
  2456. tmpreg: Tregister;
  2457. begin
  2458. if ((br=NR_NO) or (br=NR_SI) or (br=NR_DI)) and
  2459. ((ir=NR_NO) or (ir=NR_BP) or (ir=NR_BX)) then
  2460. begin
  2461. tmpreg:=br;
  2462. br:=ir;
  2463. ir:=tmpreg;
  2464. end;
  2465. end;
  2466. function process_ea_ref_16(const input:toper;out output:ea;rfield:longint; uselargeoffset: boolean):boolean;
  2467. var
  2468. sym : tasmsymbol;
  2469. md,s,rv : byte;
  2470. base,
  2471. o : longint;
  2472. ir,br : Tregister;
  2473. isub,bsub : tsubregister;
  2474. begin
  2475. result:=false;
  2476. if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
  2477. ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
  2478. internalerror(200301081);
  2479. ir:=input.ref^.index;
  2480. br:=input.ref^.base;
  2481. isub:=getsubreg(ir);
  2482. bsub:=getsubreg(br);
  2483. s:=input.ref^.scalefactor;
  2484. o:=input.ref^.offset;
  2485. sym:=input.ref^.symbol;
  2486. { it's a direct address }
  2487. if (br=NR_NO) and (ir=NR_NO) then
  2488. begin
  2489. { it's a pure offset }
  2490. output.bytes:=2;
  2491. output.modrm:=6 or (rfield shl 3);
  2492. end
  2493. else
  2494. { it's an indirection }
  2495. begin
  2496. { 32 bit address? }
  2497. if ((ir<>NR_NO) and (isub<>R_SUBW)) or
  2498. ((br<>NR_NO) and (bsub<>R_SUBW)) then
  2499. message(asmw_e_32bit_not_supported);
  2500. { scalefactor can only be 1 in 16-bit addresses }
  2501. if (s<>1) and (ir<>NR_NO) then
  2502. exit;
  2503. maybe_swap_index_base(br,ir);
  2504. if (br=NR_BX) and (ir=NR_SI) then
  2505. base:=0
  2506. else if (br=NR_BX) and (ir=NR_DI) then
  2507. base:=1
  2508. else if (br=NR_BP) and (ir=NR_SI) then
  2509. base:=2
  2510. else if (br=NR_BP) and (ir=NR_DI) then
  2511. base:=3
  2512. else if (br=NR_NO) and (ir=NR_SI) then
  2513. base:=4
  2514. else if (br=NR_NO) and (ir=NR_DI) then
  2515. base:=5
  2516. else if (br=NR_BP) and (ir=NR_NO) then
  2517. base:=6
  2518. else if (br=NR_BX) and (ir=NR_NO) then
  2519. base:=7
  2520. else
  2521. exit;
  2522. if (base<>6) and (o=0) and (sym=nil) then
  2523. md:=0
  2524. else if ((o>=-128) and (o<=127) and (sym=nil) and (not(uselargeoffset) or (o = 0))) then
  2525. md:=1
  2526. else
  2527. md:=2;
  2528. output.bytes:=md;
  2529. output.modrm:=(longint(md) shl 6) or (rfield shl 3) or base;
  2530. end;
  2531. output.size:=1+output.bytes;
  2532. output.sib_present:=false;
  2533. result:=true;
  2534. end;
  2535. {$endif}
  2536. function process_ea(const input:toper;out output:ea;rfield:longint; uselargeoffset: boolean):boolean;
  2537. var
  2538. rv : byte;
  2539. begin
  2540. result:=false;
  2541. fillchar(output,sizeof(output),0);
  2542. {Register ?}
  2543. if (input.typ=top_reg) then
  2544. begin
  2545. rv:=regval(input.reg);
  2546. output.modrm:=$c0 or (rfield shl 3) or rv;
  2547. output.size:=1;
  2548. {$ifdef x86_64}
  2549. output.rex:=output.rex or (rexbits(input.reg) and $F1);
  2550. {$endif x86_64}
  2551. result:=true;
  2552. exit;
  2553. end;
  2554. {No register, so memory reference.}
  2555. if input.typ<>top_ref then
  2556. internalerror(200409263);
  2557. {$if defined(x86_64)}
  2558. result:=process_ea_ref_64_32(input,output,rfield, uselargeoffset);
  2559. {$elseif defined(i386) or defined(i8086)}
  2560. if is_16_bit_ref(input.ref^) then
  2561. result:=process_ea_ref_16(input,output,rfield, uselargeoffset)
  2562. else
  2563. result:=process_ea_ref_32(input,output,rfield, uselargeoffset);
  2564. {$endif}
  2565. end;
  2566. function taicpu.calcsize(p:PInsEntry):shortint;
  2567. var
  2568. codes : pchar;
  2569. c : byte;
  2570. len : shortint;
  2571. len_ea_data: shortint;
  2572. len_ea_data_evex: shortint;
  2573. ea_data : ea;
  2574. exists_evex: boolean;
  2575. exists_vex: boolean;
  2576. exists_vex_extension: boolean;
  2577. exists_prefix_66: boolean;
  2578. exists_prefix_F2: boolean;
  2579. exists_prefix_F3: boolean;
  2580. {$ifdef x86_64}
  2581. omit_rexw : boolean;
  2582. {$endif x86_64}
  2583. begin
  2584. //TG TODO delete
  2585. if p^.opcode = a_VADDPS then
  2586. begin
  2587. len:=0;
  2588. end;
  2589. len:=0;
  2590. len_ea_data := 0;
  2591. len_ea_data_evex:= 0;
  2592. codes:=@p^.code[0];
  2593. exists_vex := false;
  2594. exists_vex_extension := false;
  2595. exists_prefix_66 := false;
  2596. exists_prefix_F2 := false;
  2597. exists_prefix_F3 := false;
  2598. exists_evex := false;
  2599. {$ifdef x86_64}
  2600. rex:=0;
  2601. omit_rexw:=false;
  2602. {$endif x86_64}
  2603. repeat
  2604. c:=ord(codes^);
  2605. inc(codes);
  2606. case c of
  2607. &0 :
  2608. break;
  2609. &1,&2,&3 :
  2610. begin
  2611. inc(codes,c);
  2612. inc(len,c);
  2613. end;
  2614. &10,&11,&12 :
  2615. begin
  2616. {$ifdef x86_64}
  2617. rex:=rex or (rexbits(oper[c-&10]^.reg) and $F1);
  2618. {$endif x86_64}
  2619. inc(codes);
  2620. inc(len);
  2621. end;
  2622. &13,&23 :
  2623. begin
  2624. inc(codes);
  2625. inc(len);
  2626. end;
  2627. &4,&5,&6,&7 :
  2628. begin
  2629. if opsize={$ifdef i8086}S_L{$else}S_W{$endif} then
  2630. inc(len,2)
  2631. else
  2632. inc(len);
  2633. end;
  2634. &14,&15,&16,
  2635. &20,&21,&22,
  2636. &24,&25,&26,&27,
  2637. &50,&51,&52 :
  2638. inc(len);
  2639. &30,&31,&32,
  2640. &37,
  2641. &60,&61,&62 :
  2642. inc(len,2);
  2643. &34,&35,&36:
  2644. begin
  2645. {$ifdef i8086}
  2646. inc(len,2);
  2647. {$else i8086}
  2648. if opsize=S_Q then
  2649. inc(len,8)
  2650. else
  2651. inc(len,4);
  2652. {$endif i8086}
  2653. end;
  2654. &44,&45,&46:
  2655. inc(len,sizeof(pint));
  2656. &54,&55,&56:
  2657. inc(len,8);
  2658. &40,&41,&42,
  2659. &70,&71,&72,
  2660. &254,&255,&256 :
  2661. inc(len,4);
  2662. &64,&65,&66:
  2663. {$ifdef i8086}
  2664. inc(len,2);
  2665. {$else i8086}
  2666. inc(len,4);
  2667. {$endif i8086}
  2668. &74,&75,&76,&77: ; // ignore vex-coded operand-idx
  2669. &320,&321,&322 :
  2670. begin
  2671. case (oper[c-&320]^.ot and OT_SIZE_MASK) of
  2672. {$if defined(i386) or defined(x86_64)}
  2673. OT_BITS16 :
  2674. {$elseif defined(i8086)}
  2675. OT_BITS32 :
  2676. {$endif}
  2677. inc(len);
  2678. {$ifdef x86_64}
  2679. OT_BITS64:
  2680. begin
  2681. rex:=rex or $48;
  2682. end;
  2683. {$endif x86_64}
  2684. end;
  2685. end;
  2686. &310 :
  2687. {$if defined(x86_64)}
  2688. { every insentry with code 0310 must be marked with NOX86_64 }
  2689. InternalError(2011051301);
  2690. {$elseif defined(i386)}
  2691. inc(len);
  2692. {$elseif defined(i8086)}
  2693. {nothing};
  2694. {$endif}
  2695. &311 :
  2696. {$if defined(x86_64) or defined(i8086)}
  2697. inc(len)
  2698. {$endif x86_64 or i8086}
  2699. ;
  2700. &324 :
  2701. {$ifndef i8086}
  2702. inc(len)
  2703. {$endif not i8086}
  2704. ;
  2705. &326 :
  2706. begin
  2707. {$ifdef x86_64}
  2708. rex:=rex or $48;
  2709. {$endif x86_64}
  2710. end;
  2711. &312,
  2712. &323,
  2713. &327,
  2714. &331,&332: ;
  2715. &325:
  2716. {$ifdef i8086}
  2717. inc(len)
  2718. {$endif i8086}
  2719. ;
  2720. &333:
  2721. begin
  2722. inc(len);
  2723. exists_prefix_F2 := true;
  2724. end;
  2725. &334:
  2726. begin
  2727. inc(len);
  2728. exists_prefix_F3 := true;
  2729. end;
  2730. &361:
  2731. begin
  2732. {$ifndef i8086}
  2733. inc(len);
  2734. exists_prefix_66 := true;
  2735. {$endif not i8086}
  2736. end;
  2737. &335:
  2738. {$ifdef x86_64}
  2739. omit_rexw:=true
  2740. {$endif x86_64}
  2741. ;
  2742. &100..&227 :
  2743. begin
  2744. {$ifdef x86_64}
  2745. if (c<&177) then
  2746. begin
  2747. if (oper[c and 7]^.typ=top_reg) then
  2748. begin
  2749. rex:=rex or (rexbits(oper[c and 7]^.reg) and $F4);
  2750. end;
  2751. end;
  2752. {$endif x86_64}
  2753. if process_ea(oper[(c shr 3) and 7]^, ea_data, 0, true) then
  2754. len_ea_data_evex := ea_data.size;
  2755. if process_ea(oper[(c shr 3) and 7]^, ea_data, 0, false) then
  2756. begin
  2757. len_ea_data := ea_data.size;
  2758. inc(len,ea_data.size);
  2759. end
  2760. else Message(asmw_e_invalid_effective_address);
  2761. {$ifdef x86_64}
  2762. rex:=rex or ea_data.rex;
  2763. {$endif x86_64}
  2764. end;
  2765. &350:
  2766. begin
  2767. exists_evex := true;
  2768. end;
  2769. &351: ; // EVEX length bit 512
  2770. &352: ; // EVEX W1
  2771. &362: // VEX prefix for AVX (length = 2 or 3 bytes, dependens on REX.XBW or opcode-prefix ($0F38 or $0F3A))
  2772. // =>> DEFAULT = 2 Bytes
  2773. begin
  2774. //if not(exists_vex) then
  2775. //begin
  2776. // inc(len, 2);
  2777. //end;
  2778. exists_vex := true;
  2779. end;
  2780. &363: // REX.W = 1
  2781. // =>> VEX prefix length = 3
  2782. begin
  2783. if not(exists_vex_extension) then
  2784. begin
  2785. //inc(len);
  2786. exists_vex_extension := true;
  2787. end;
  2788. end;
  2789. &364: ; // VEX length bit 256
  2790. &366, // operand 2 (ymmreg) encoded immediate byte (bit 4-7)
  2791. &367: inc(len); // operand 3 (ymmreg) encoded immediate byte (bit 4-7)
  2792. &370: // VEX-Extension prefix $0F
  2793. // ignore for calculating length
  2794. ;
  2795. &371, // VEX-Extension prefix $0F38
  2796. &372: // VEX-Extension prefix $0F3A
  2797. begin
  2798. if not(exists_vex_extension) then
  2799. begin
  2800. //inc(len);
  2801. exists_vex_extension := true;
  2802. end;
  2803. end;
  2804. &300,&301,&302:
  2805. begin
  2806. {$if defined(x86_64) or defined(i8086)}
  2807. if (oper[c and 3]^.ot and OT_SIZE_MASK)=OT_BITS32 then
  2808. inc(len);
  2809. {$endif x86_64 or i8086}
  2810. end;
  2811. else
  2812. InternalError(200603141);
  2813. end;
  2814. until false;
  2815. {$ifdef x86_64}
  2816. if ((rex and $80)<>0) and ((rex and $4F)<>0) then
  2817. Message(asmw_e_bad_reg_with_rex);
  2818. rex:=rex and $4F; { reset extra bits in upper nibble }
  2819. if omit_rexw then
  2820. begin
  2821. if rex=$48 then { remove rex entirely? }
  2822. rex:=0
  2823. else
  2824. rex:=rex and $F7;
  2825. end;
  2826. if not(exists_vex or exists_evex) then
  2827. begin
  2828. if rex<>0 then
  2829. Inc(len);
  2830. end;
  2831. {$endif}
  2832. if exists_evex and
  2833. exists_vex then
  2834. begin
  2835. if CheckUseEVEX then
  2836. begin
  2837. inc(len, 4);
  2838. if len_ea_data <> len_ea_data_evex then
  2839. inc(len, len_ea_data_evex - len_ea_data);
  2840. end
  2841. else
  2842. begin
  2843. inc(len, 2);
  2844. if exists_vex_extension then inc(len);
  2845. {$ifdef x86_64}
  2846. if not(exists_vex_extension) then
  2847. if rex and $0B <> 0 then inc(len); // REX.WXB <> 0 =>> needed VEX-Extension
  2848. {$endif x86_64}
  2849. end;
  2850. if exists_prefix_66 then dec(len);
  2851. if exists_prefix_F2 then dec(len);
  2852. if exists_prefix_F3 then dec(len);
  2853. end
  2854. else if exists_evex then
  2855. begin
  2856. inc(len, 4);
  2857. if exists_prefix_66 then dec(len);
  2858. if exists_prefix_F2 then dec(len);
  2859. if exists_prefix_F3 then dec(len);
  2860. if len_ea_data <> len_ea_data_evex then
  2861. inc(len, len_ea_data_evex - len_ea_data);
  2862. end
  2863. else
  2864. begin
  2865. if exists_vex then
  2866. begin
  2867. inc(len,2);
  2868. if exists_prefix_66 then dec(len);
  2869. if exists_prefix_F2 then dec(len);
  2870. if exists_prefix_F3 then dec(len);
  2871. if exists_vex_extension then inc(len);
  2872. {$ifdef x86_64}
  2873. if not(exists_vex_extension) then
  2874. if rex and $0B <> 0 then inc(len); // REX.WXB <> 0 =>> needed VEX-Extension
  2875. {$endif x86_64}
  2876. end;
  2877. end;
  2878. calcsize:=len;
  2879. end;
  2880. procedure taicpu.write0x66prefix(objdata:TObjData);
  2881. const
  2882. b66: Byte=$66;
  2883. begin
  2884. {$ifdef i8086}
  2885. if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
  2886. Message(asmw_e_instruction_not_supported_by_cpu);
  2887. {$endif i8086}
  2888. objdata.writebytes(b66,1);
  2889. end;
  2890. procedure taicpu.write0x67prefix(objdata:TObjData);
  2891. const
  2892. b67: Byte=$67;
  2893. begin
  2894. {$ifdef i8086}
  2895. if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
  2896. Message(asmw_e_instruction_not_supported_by_cpu);
  2897. {$endif i8086}
  2898. objdata.writebytes(b67,1);
  2899. end;
  2900. procedure taicpu.gencode(objdata: TObjData);
  2901. {
  2902. * the actual codes (C syntax, i.e. octal):
  2903. * \0 - terminates the code. (Unless it's a literal of course.)
  2904. * \1, \2, \3 - that many literal bytes follow in the code stream
  2905. * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  2906. * (POP is never used for CS) depending on operand 0
  2907. * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
  2908. * on operand 0
  2909. * \10, \11, \12 - a literal byte follows in the code stream, to be added
  2910. * to the register value of operand 0, 1 or 2
  2911. * \13 - a literal byte follows in the code stream, to be added
  2912. * to the condition code value of the instruction.
  2913. * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  2914. * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  2915. * \23 - a literal byte follows in the code stream, to be added
  2916. * to the inverted condition code value of the instruction
  2917. * (inverted version of \13).
  2918. * \24, \25, \26, \27 - an unsigned byte immediate operand, from operand 0, 1, 2 or 3
  2919. * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  2920. * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  2921. * assembly mode or the address-size override on the operand
  2922. * \37 - a word constant, from the _segment_ part of operand 0
  2923. * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  2924. * \44, \45, \46 - select between \3[012], \4[012] or \5[456] depending
  2925. on the address size of instruction
  2926. * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  2927. * \54, \55, \56 - a qword immediate, from operand 0, 1 or 2
  2928. * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  2929. * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  2930. * assembly mode or the address-size override on the operand
  2931. * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  2932. * \74, \75, \76 - a vex-coded vector operand, from operand 0, 1 or 2
  2933. * \1ab - a ModRM, calculated on EA in operand a, with the spare
  2934. * field the register value of operand b.
  2935. * \2ab - a ModRM, calculated on EA in operand a, with the spare
  2936. * field equal to digit b.
  2937. * \254,\255,\256 - a signed 32-bit immediate to be extended to 64 bits
  2938. * \300,\301,\302 - might be an 0x67, depending on the address size of
  2939. * the memory reference in operand x.
  2940. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
  2941. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
  2942. * \312 - (disassembler only) invalid with non-default address size.
  2943. * \320,\321,\322 - might be an 0x66 or 0x48 byte, depending on the operand
  2944. * size of operand x.
  2945. * \324 - indicates fixed 16-bit operand size, i.e. optional 0x66.
  2946. * \325 - indicates fixed 32-bit operand size, i.e. optional 0x66.
  2947. * \326 - indicates fixed 64-bit operand size, i.e. optional 0x48.
  2948. * \327 - indicates that this instruction is only valid when the
  2949. * operand size is the default (instruction to disassembler,
  2950. * generates no code in the assembler)
  2951. * \331 - instruction not valid with REP prefix. Hint for
  2952. * disassembler only; for SSE instructions.
  2953. * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
  2954. * \333 - 0xF3 prefix for SSE instructions
  2955. * \334 - 0xF2 prefix for SSE instructions
  2956. * \335 - Indicates 64-bit operand size with REX.W not necessary
  2957. * \350 - EVEX prefix for AVX instructions
  2958. * \351 - EVEX Vector length 512
  2959. * \352 - EVEX W1
  2960. * \361 - 0x66 prefix for SSE instructions
  2961. * \362 - VEX prefix for AVX instructions
  2962. * \363 - VEX W1
  2963. * \364 - VEX Vector length 256
  2964. * \366 - operand 2 (ymmreg,zmmreg) encoded in bit 4-7 of the immediate byte
  2965. * \367 - operand 3 (ymmreg,zmmreg) encoded in bit 4-7 of the immediate byte
  2966. * \370 - VEX 0F-FLAG
  2967. * \371 - VEX 0F38-FLAG
  2968. * \372 - VEX 0F3A-FLAG
  2969. }
  2970. var
  2971. {$ifdef i8086}
  2972. currval : longint;
  2973. {$else i8086}
  2974. currval : aint;
  2975. {$endif i8086}
  2976. currsym : tobjsymbol;
  2977. currrelreloc,
  2978. currabsreloc,
  2979. currabsreloc32 : TObjRelocationType;
  2980. {$ifdef x86_64}
  2981. rexwritten : boolean;
  2982. {$endif x86_64}
  2983. procedure getvalsym(opidx:longint);
  2984. begin
  2985. case oper[opidx]^.typ of
  2986. top_ref :
  2987. begin
  2988. currval:=oper[opidx]^.ref^.offset;
  2989. currsym:=ObjData.symbolref(oper[opidx]^.ref^.symbol);
  2990. {$ifdef i8086}
  2991. if oper[opidx]^.ref^.refaddr=addr_seg then
  2992. begin
  2993. currrelreloc:=RELOC_SEGREL;
  2994. currabsreloc:=RELOC_SEG;
  2995. currabsreloc32:=RELOC_SEG;
  2996. end
  2997. else if oper[opidx]^.ref^.refaddr=addr_dgroup then
  2998. begin
  2999. currrelreloc:=RELOC_DGROUPREL;
  3000. currabsreloc:=RELOC_DGROUP;
  3001. currabsreloc32:=RELOC_DGROUP;
  3002. end
  3003. else if oper[opidx]^.ref^.refaddr=addr_fardataseg then
  3004. begin
  3005. currrelreloc:=RELOC_FARDATASEGREL;
  3006. currabsreloc:=RELOC_FARDATASEG;
  3007. currabsreloc32:=RELOC_FARDATASEG;
  3008. end
  3009. else
  3010. {$endif i8086}
  3011. {$ifdef i386}
  3012. if (oper[opidx]^.ref^.refaddr=addr_pic) and
  3013. (tf_pic_uses_got in target_info.flags) then
  3014. begin
  3015. currrelreloc:=RELOC_PLT32;
  3016. currabsreloc:=RELOC_GOT32;
  3017. currabsreloc32:=RELOC_GOT32;
  3018. end
  3019. else
  3020. {$endif i386}
  3021. {$ifdef x86_64}
  3022. if oper[opidx]^.ref^.refaddr=addr_pic then
  3023. begin
  3024. currrelreloc:=RELOC_PLT32;
  3025. currabsreloc:=RELOC_GOTPCREL;
  3026. currabsreloc32:=RELOC_GOTPCREL;
  3027. end
  3028. else if oper[opidx]^.ref^.refaddr=addr_pic_no_got then
  3029. begin
  3030. currrelreloc:=RELOC_RELATIVE;
  3031. currabsreloc:=RELOC_RELATIVE;
  3032. currabsreloc32:=RELOC_RELATIVE;
  3033. end
  3034. else
  3035. {$endif x86_64}
  3036. begin
  3037. currrelreloc:=RELOC_RELATIVE;
  3038. currabsreloc:=RELOC_ABSOLUTE;
  3039. currabsreloc32:=RELOC_ABSOLUTE32;
  3040. end;
  3041. end;
  3042. top_const :
  3043. begin
  3044. {$ifdef i8086}
  3045. currval:=longint(oper[opidx]^.val);
  3046. {$else i8086}
  3047. currval:=aint(oper[opidx]^.val);
  3048. {$endif i8086}
  3049. currsym:=nil;
  3050. currabsreloc:=RELOC_ABSOLUTE;
  3051. currabsreloc32:=RELOC_ABSOLUTE32;
  3052. end;
  3053. else
  3054. Message(asmw_e_immediate_or_reference_expected);
  3055. end;
  3056. end;
  3057. {$ifdef x86_64}
  3058. procedure maybewriterex;
  3059. begin
  3060. if (rex<>0) and not(rexwritten) then
  3061. begin
  3062. rexwritten:=true;
  3063. objdata.writebytes(rex,1);
  3064. end;
  3065. end;
  3066. {$endif x86_64}
  3067. procedure objdata_writereloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
  3068. begin
  3069. {$ifdef i386}
  3070. { Special case of '_GLOBAL_OFFSET_TABLE_'
  3071. which needs a special relocation type R_386_GOTPC }
  3072. if assigned (p) and
  3073. (p.name='_GLOBAL_OFFSET_TABLE_') and
  3074. (tf_pic_uses_got in target_info.flags) then
  3075. begin
  3076. { nothing else than a 4 byte relocation should occur
  3077. for GOT }
  3078. if len<>4 then
  3079. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  3080. Reloctype:=RELOC_GOTPC;
  3081. { We need to add the offset of the relocation
  3082. of _GLOBAL_OFFSET_TABLE symbol within
  3083. the current instruction }
  3084. inc(data,objdata.currobjsec.size-insoffset);
  3085. end;
  3086. {$endif i386}
  3087. objdata.writereloc(data,len,p,Reloctype);
  3088. end;
  3089. const
  3090. CondVal:array[TAsmCond] of byte=($0,
  3091. $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
  3092. $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
  3093. $0, $A, $A, $B, $8, $4);
  3094. var
  3095. i: integer;
  3096. c : byte;
  3097. pb : pbyte;
  3098. codes : pchar;
  3099. bytes : array[0..3] of byte;
  3100. rfield,
  3101. data,s,opidx : longint;
  3102. ea_data : ea;
  3103. relsym : TObjSymbol;
  3104. needed_VEX_Extension: boolean;
  3105. needed_VEX: boolean;
  3106. needed_EVEX: boolean;
  3107. needed_VSIB: boolean;
  3108. opmode: integer;
  3109. VEXvvvv: byte;
  3110. VEXmmmmm: byte;
  3111. VEXw : byte;
  3112. VEXpp : byte;
  3113. VEXll : byte;
  3114. EVEXvvvv: byte;
  3115. EVEXpp: byte;
  3116. EVEXr: byte;
  3117. EVEXx: byte;
  3118. EVEXv: byte;
  3119. EVEXll: byte;
  3120. EVEXw0: byte;
  3121. EVEXw1: byte;
  3122. EVEXz : byte;
  3123. EVEXaaa : byte;
  3124. EVEXb : byte;
  3125. EVEXmm : byte;
  3126. //TG delete
  3127. pins: tinsentry;
  3128. t: toptype;
  3129. begin
  3130. { safety check }
  3131. // TODO delete
  3132. i := longword(insoffset);
  3133. if objdata.currobjsec.size<>longword(insoffset) then
  3134. begin
  3135. internalerror(200130121);
  3136. end;
  3137. { those variables are initialized inside local procedures, the dfa cannot handle this yet }
  3138. currsym:=nil;
  3139. currabsreloc:=RELOC_NONE;
  3140. currabsreloc32:=RELOC_NONE;
  3141. currrelreloc:=RELOC_NONE;
  3142. currval:=0;
  3143. { check instruction's processor level }
  3144. { todo: maybe adapt and enable this code for i386 and x86_64 as well }
  3145. {$ifdef i8086}
  3146. if objdata.CPUType<>cpu_none then
  3147. begin
  3148. if IF_8086 in insentry^.flags then
  3149. else if IF_186 in insentry^.flags then
  3150. begin
  3151. if objdata.CPUType<cpu_186 then
  3152. Message(asmw_e_instruction_not_supported_by_cpu);
  3153. end
  3154. else if IF_286 in insentry^.flags then
  3155. begin
  3156. if objdata.CPUType<cpu_286 then
  3157. Message(asmw_e_instruction_not_supported_by_cpu);
  3158. end
  3159. else if IF_386 in insentry^.flags then
  3160. begin
  3161. if objdata.CPUType<cpu_386 then
  3162. Message(asmw_e_instruction_not_supported_by_cpu);
  3163. end
  3164. else if IF_486 in insentry^.flags then
  3165. begin
  3166. if objdata.CPUType<cpu_486 then
  3167. Message(asmw_e_instruction_not_supported_by_cpu);
  3168. end
  3169. else if IF_PENT in insentry^.flags then
  3170. begin
  3171. if objdata.CPUType<cpu_Pentium then
  3172. Message(asmw_e_instruction_not_supported_by_cpu);
  3173. end
  3174. else if IF_P6 in insentry^.flags then
  3175. begin
  3176. if objdata.CPUType<cpu_Pentium2 then
  3177. Message(asmw_e_instruction_not_supported_by_cpu);
  3178. end
  3179. else if IF_KATMAI in insentry^.flags then
  3180. begin
  3181. if objdata.CPUType<cpu_Pentium3 then
  3182. Message(asmw_e_instruction_not_supported_by_cpu);
  3183. end
  3184. else if insentry^.flags*[IF_WILLAMETTE,IF_PRESCOTT]<>[] then
  3185. begin
  3186. if objdata.CPUType<cpu_Pentium4 then
  3187. Message(asmw_e_instruction_not_supported_by_cpu);
  3188. end
  3189. else if IF_NEC in insentry^.flags then
  3190. begin
  3191. { the NEC V20/V30 extensions are incompatible with 386+, due to overlapping opcodes }
  3192. if objdata.CPUType>=cpu_386 then
  3193. Message(asmw_e_instruction_not_supported_by_cpu);
  3194. end
  3195. else if IF_SANDYBRIDGE in insentry^.flags then
  3196. begin
  3197. { todo: handle these properly }
  3198. end;
  3199. end;
  3200. {$endif i8086}
  3201. { load data to write }
  3202. codes:=insentry^.code;
  3203. {$ifdef x86_64}
  3204. rexwritten:=false;
  3205. {$endif x86_64}
  3206. { Force word push/pop for registers }
  3207. if (opsize={$ifdef i8086}S_L{$else}S_W{$endif}) and ((codes[0]=#4) or (codes[0]=#6) or
  3208. ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
  3209. write0x66prefix(objdata);
  3210. // needed VEX Prefix (for AVX etc.)
  3211. needed_VEX := false;
  3212. needed_EVEX := false;
  3213. needed_VEX_Extension := false;
  3214. needed_VSIB := false;
  3215. opmode := -1;
  3216. VEXvvvv := 0;
  3217. VEXmmmmm := 0;
  3218. VEXll := 0;
  3219. VEXw := 0;
  3220. VEXpp := 0;
  3221. EVEXpp := 0;
  3222. EVEXvvvv := 0;
  3223. EVEXr := 0;
  3224. EVEXx := 0;
  3225. EVEXv := 0;
  3226. EVEXll := 0;
  3227. EVEXw0 := 0;
  3228. EVEXw1 := 0;
  3229. EVEXz := 0;
  3230. EVEXaaa := 0;
  3231. EVEXb := 0;
  3232. EVEXmm := 0;
  3233. pins := insentry^;
  3234. repeat
  3235. c:=ord(codes^);
  3236. inc(codes);
  3237. case c of
  3238. &0: break;
  3239. &1,
  3240. &2,
  3241. &3: inc(codes,c);
  3242. &10,
  3243. &11,
  3244. &12: inc(codes, 1);
  3245. &74: opmode := 0;
  3246. &75: opmode := 1;
  3247. &76: opmode := 2;
  3248. &100..&227: begin
  3249. // AVX 512 - EVEX
  3250. // check operands
  3251. // TODO delete
  3252. pins := insentry^;
  3253. i := ord(c);
  3254. if (c shr 6) = 1 then
  3255. begin
  3256. opidx := c and 7;
  3257. if ops > opidx then
  3258. begin
  3259. t := oper[opidx]^.typ;
  3260. if (oper[opidx]^.typ=top_reg) then
  3261. if getsupreg(oper[opidx]^.reg) and $10 = $0 then EVEXr := 1; //TG TODO check
  3262. end
  3263. end
  3264. else EVEXr := 1; // modrm:reg not used =>> 1
  3265. opidx := (c shr 3) and 7;
  3266. if ops > opidx then
  3267. case oper[opidx]^.typ of
  3268. top_reg: if getsupreg(oper[opidx]^.reg) and $10 = $0 then EVEXx := 1; //TG TODO check
  3269. top_ref: begin
  3270. if getsupreg(oper[opidx]^.ref^.index) and $08 = $0 then EVEXx := 1; //TG TODO check
  3271. if getsubreg(oper[opidx]^.ref^.index) in [R_SUBMMX,R_SUBMMY,R_SUBMMZ] then
  3272. begin
  3273. // VSIB memory addresing
  3274. if getsupreg(oper[opidx]^.ref^.index) and $10 = $0 then EVEXv := 1; // VECTOR-Index
  3275. needed_VSIB := true;
  3276. end;
  3277. end;
  3278. end;
  3279. end;
  3280. &333: begin
  3281. VEXvvvv := VEXvvvv OR $02; // set SIMD-prefix $F3
  3282. VEXpp := $02; // set SIMD-prefix $F3
  3283. EVEXpp := $02; // set SIMD-prefix $F3
  3284. end;
  3285. &334: begin
  3286. VEXvvvv := VEXvvvv OR $03; // set SIMD-prefix $F2
  3287. VEXpp := $03; // set SIMD-prefix $F2
  3288. EVEXpp := $03; // set SIMD-prefix $F2
  3289. end;
  3290. &350: needed_EVEX := true; // AVX512 instruction or AVX128/256/512-instruction (depended on operands [x,y,z]mm16..)
  3291. &351: EVEXll := $02; // vectorlength = 512 bits AND no scalar
  3292. &352: EVEXw1 := $01;
  3293. &361: begin
  3294. VEXvvvv := VEXvvvv OR $01; // set SIMD-prefix $66
  3295. VEXpp := $01; // set SIMD-prefix $66
  3296. EVEXpp := $01; // set SIMD-prefix $66
  3297. end;
  3298. &362: needed_VEX := true;
  3299. &363: begin
  3300. needed_VEX_Extension := true;
  3301. VEXvvvv := VEXvvvv OR (1 shl 7); // set REX.W
  3302. VEXw := 1;
  3303. end;
  3304. &364: begin
  3305. VEXvvvv := VEXvvvv OR $04; // vectorlength = 256 bits AND no scalar
  3306. VEXll := $01;
  3307. EVEXll := $01;
  3308. end;
  3309. &366,
  3310. &367: begin
  3311. opidx:=c-&364; { 0366->operand 2, 0367->operand 3 }
  3312. if (ops > opidx) and
  3313. (oper[opidx]^.typ=top_reg) and
  3314. ((oper[opidx]^.ot and OT_REG_EXTRA_MASK = otf_reg_xmm) or
  3315. (oper[opidx]^.ot and OT_REG_EXTRA_MASK = otf_reg_ymm) or
  3316. (oper[opidx]^.ot and OT_REG_EXTRA_MASK = otf_reg_zmm)) then
  3317. if (getsupreg(oper[opidx]^.reg) and $10 = $0) then EVEXx := 1; //TG TODO check
  3318. end;
  3319. &370: begin
  3320. VEXmmmmm := VEXmmmmm OR $01; // set leading opcode byte $0F
  3321. EVEXmm := $01;
  3322. end;
  3323. &371: begin
  3324. needed_VEX_Extension := true;
  3325. VEXmmmmm := VEXmmmmm OR $02; // set leading opcode byte $0F38
  3326. EVEXmm := $02;
  3327. end;
  3328. &372: begin
  3329. needed_VEX_Extension := true;
  3330. VEXmmmmm := VEXmmmmm OR $03; // set leading opcode byte $0F3A
  3331. EVEXmm := $03;
  3332. end;
  3333. end;
  3334. until false;
  3335. {$ifndef x86_64}
  3336. EVEXv := 1;
  3337. EVEXx := 1;
  3338. EVEXr := 1;
  3339. {$endif}
  3340. if needed_VEX or needed_EVEX then
  3341. begin
  3342. if (opmode > ops) or
  3343. (opmode < -1) then
  3344. begin
  3345. Internalerror(777100);
  3346. end
  3347. else if opmode = -1 then
  3348. begin
  3349. VEXvvvv := VEXvvvv or ($0F shl 3); // set VEXvvvv bits (bits 6-3) to 1
  3350. EVEXvvvv := $0F;
  3351. {$ifdef x86_64}
  3352. if not(needed_vsib) then EVEXv := 1;
  3353. {$endif x86_64}
  3354. end
  3355. else if oper[opmode]^.typ = top_reg then
  3356. begin
  3357. VEXvvvv := VEXvvvv or ((not(regval(oper[opmode]^.reg)) and $07) shl 3);
  3358. EVEXvvvv := not(regval(oper[opmode]^.reg)) and $07;
  3359. {$ifdef x86_64}
  3360. if rexbits(oper[opmode]^.reg) = 0 then VEXvvvv := VEXvvvv or (1 shl 6);
  3361. if rexbits(oper[opmode]^.reg) = 0 then EVEXvvvv := EVEXvvvv or (1 shl 3);
  3362. if getsupreg(oper[opmode]^.reg) and $10 = 0 then EVEXv := 1; //TG TODO check
  3363. {$else}
  3364. VEXvvvv := VEXvvvv or (1 shl 6);
  3365. EVEXvvvv := EVEXvvvv or (1 shl 3);
  3366. {$endif x86_64}
  3367. end
  3368. else Internalerror(777101);
  3369. if not(needed_VEX_Extension) then
  3370. begin
  3371. {$ifdef x86_64}
  3372. if rex and $0B <> 0 then needed_VEX_Extension := true;
  3373. {$endif x86_64}
  3374. end;
  3375. //TG
  3376. if needed_EVEX and needed_VEX then
  3377. begin
  3378. needed_EVEX := false;
  3379. if CheckUseEVEX then
  3380. begin
  3381. // EVEX-Flags r,v,x indicate extended-MMregister
  3382. // Flag = 0 =>> [x,y,z]mm16..[x,y,z]mm31
  3383. // Flag = 1 =>> [x,y,z]mm00..[x,y,z]mm15
  3384. needed_EVEX := true;
  3385. needed_VEX := false;
  3386. needed_VEX_Extension := false; //TG TODO check
  3387. end;
  3388. end;
  3389. if needed_EVEX then
  3390. begin
  3391. EVEXaaa:= 0;
  3392. EVEXz := 0;
  3393. for i := 0 to ops - 1 do
  3394. if (oper[i]^.vopext and OTVE_VECTOR_MASK) <> 0 then
  3395. begin
  3396. if oper[i]^.vopext and OTVE_VECTOR_WRITEMASK = OTVE_VECTOR_WRITEMASK then
  3397. begin
  3398. EVEXaaa := oper[i]^.vopext and $07;
  3399. if oper[i]^.vopext and OTVE_VECTOR_ZERO = OTVE_VECTOR_ZERO then EVEXz := 1;
  3400. end;
  3401. if oper[i]^.vopext and OTVE_VECTOR_BCST = OTVE_VECTOR_BCST then
  3402. begin
  3403. EVEXb := 1;
  3404. end;
  3405. // flag EVEXb is multiple use (broadcast, sae and er)
  3406. if oper[i]^.vopext and OTVE_VECTOR_SAE = OTVE_VECTOR_SAE then
  3407. begin
  3408. EVEXb := 1;
  3409. end;
  3410. if oper[i]^.vopext and OTVE_VECTOR_ER = OTVE_VECTOR_ER then
  3411. begin
  3412. EVEXb := 1;
  3413. case oper[i]^.vopext and OTVE_VECTOR_ER_MASK of
  3414. OTVE_VECTOR_RNSAE: EVEXll := 0;
  3415. OTVE_VECTOR_RDSAE: EVEXll := 1;
  3416. OTVE_VECTOR_RUSAE: EVEXll := 2;
  3417. OTVE_VECTOR_RZSAE: EVEXll := 3;
  3418. else EVEXll := 0;
  3419. end;
  3420. end;
  3421. end;
  3422. bytes[0] := $62;
  3423. bytes[1] := ((EVEXmm and $03) shl 0) or
  3424. {$ifdef x86_64}
  3425. ((not(rex) and $05) shl 5) or
  3426. {$else}
  3427. (($05) shl 5) or
  3428. {$endif x86_64}
  3429. ((EVEXr and $01) shl 4) or
  3430. ((EVEXx and $01) shl 6);
  3431. bytes[2] := ((EVEXpp and $03) shl 0) or
  3432. ((1 and $01) shl 2) or // fixed in AVX512
  3433. ((EVEXvvvv and $0F) shl 3) or
  3434. ((EVEXw1 and $01) shl 7);
  3435. bytes[3] := ((EVEXaaa and $07) shl 0) or
  3436. ((EVEXv and $01) shl 3) or
  3437. ((EVEXb and $01) shl 4) or
  3438. ((EVEXll and $03) shl 5) or
  3439. ((EVEXz and $01) shl 7);
  3440. objdata.writebytes(bytes,4);
  3441. end
  3442. else if needed_VEX_Extension then
  3443. begin
  3444. // VEX-Prefix-Length = 3 Bytes
  3445. {$ifdef x86_64}
  3446. VEXmmmmm := VEXmmmmm or ((not(rex) and $07) shl 5); // set REX.rxb
  3447. VEXvvvv := VEXvvvv or ((rex and $08) shl 7); // set REX.w
  3448. {$else}
  3449. VEXmmmmm := VEXmmmmm or (7 shl 5); //
  3450. {$endif x86_64}
  3451. bytes[0]:=$C4;
  3452. bytes[1]:=VEXmmmmm;
  3453. bytes[2]:=VEXvvvv;
  3454. objdata.writebytes(bytes,3);
  3455. end
  3456. else
  3457. begin
  3458. // VEX-Prefix-Length = 2 Bytes
  3459. {$ifdef x86_64}
  3460. if rex and $04 = 0 then
  3461. {$endif x86_64}
  3462. begin
  3463. VEXvvvv := VEXvvvv or (1 shl 7);
  3464. end;
  3465. bytes[0]:=$C5;
  3466. bytes[1]:=VEXvvvv;
  3467. objdata.writebytes(bytes,2);
  3468. end;
  3469. end
  3470. else
  3471. begin
  3472. needed_VEX_Extension := false;
  3473. opmode := -1;
  3474. end;
  3475. if not(needed_EVEX) then
  3476. begin
  3477. for opidx := 0 to ops - 1 do
  3478. begin
  3479. if ops > opidx then
  3480. if (oper[opidx]^.typ=top_reg) and
  3481. (getregtype(oper[opidx]^.reg) = R_MMREGISTER) then
  3482. if getsupreg(oper[opidx]^.reg) and $10 = $10 then
  3483. begin
  3484. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  3485. break;
  3486. end;
  3487. //badreg(oper[opidx]^.reg);
  3488. end;
  3489. end;
  3490. { load data to write }
  3491. codes:=insentry^.code;
  3492. repeat
  3493. c:=ord(codes^);
  3494. inc(codes);
  3495. case c of
  3496. &0 :
  3497. break;
  3498. &1,&2,&3 :
  3499. begin
  3500. {$ifdef x86_64}
  3501. if not(needed_VEX or needed_EVEX) then // TG
  3502. maybewriterex;
  3503. {$endif x86_64}
  3504. objdata.writebytes(codes^,c);
  3505. inc(codes,c);
  3506. end;
  3507. &4,&6 :
  3508. begin
  3509. case oper[0]^.reg of
  3510. NR_CS:
  3511. bytes[0]:=$e;
  3512. NR_NO,
  3513. NR_DS:
  3514. bytes[0]:=$1e;
  3515. NR_ES:
  3516. bytes[0]:=$6;
  3517. NR_SS:
  3518. bytes[0]:=$16;
  3519. else
  3520. internalerror(777004);
  3521. end;
  3522. if c=&4 then
  3523. inc(bytes[0]);
  3524. objdata.writebytes(bytes,1);
  3525. end;
  3526. &5,&7 :
  3527. begin
  3528. case oper[0]^.reg of
  3529. NR_FS:
  3530. bytes[0]:=$a0;
  3531. NR_GS:
  3532. bytes[0]:=$a8;
  3533. else
  3534. internalerror(777005);
  3535. end;
  3536. if c=&5 then
  3537. inc(bytes[0]);
  3538. objdata.writebytes(bytes,1);
  3539. end;
  3540. &10,&11,&12 :
  3541. begin
  3542. {$ifdef x86_64}
  3543. if not(needed_VEX or needed_EVEX) then // TG
  3544. maybewriterex;
  3545. {$endif x86_64}
  3546. bytes[0]:=ord(codes^)+regval(oper[c-&10]^.reg);
  3547. inc(codes);
  3548. objdata.writebytes(bytes,1);
  3549. end;
  3550. &13 :
  3551. begin
  3552. bytes[0]:=ord(codes^)+condval[condition];
  3553. inc(codes);
  3554. objdata.writebytes(bytes,1);
  3555. end;
  3556. &14,&15,&16 :
  3557. begin
  3558. getvalsym(c-&14);
  3559. if (currval<-128) or (currval>127) then
  3560. Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
  3561. if assigned(currsym) then
  3562. objdata_writereloc(currval,1,currsym,currabsreloc)
  3563. else
  3564. objdata.writebytes(currval,1);
  3565. end;
  3566. &20,&21,&22 :
  3567. begin
  3568. getvalsym(c-&20);
  3569. if (currval<-256) or (currval>255) then
  3570. Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
  3571. if assigned(currsym) then
  3572. objdata_writereloc(currval,1,currsym,currabsreloc)
  3573. else
  3574. objdata.writebytes(currval,1);
  3575. end;
  3576. &23 :
  3577. begin
  3578. bytes[0]:=ord(codes^)+condval[inverse_cond(condition)];
  3579. inc(codes);
  3580. objdata.writebytes(bytes,1);
  3581. end;
  3582. &24,&25,&26,&27 :
  3583. begin
  3584. getvalsym(c-&24);
  3585. if IF_IMM3 in insentry^.flags then
  3586. begin
  3587. if (currval<0) or (currval>7) then
  3588. Message2(asmw_e_value_exceeds_bounds,'unsigned triad',tostr(currval));
  3589. end
  3590. else if IF_IMM4 in insentry^.flags then
  3591. begin
  3592. if (currval<0) or (currval>15) then
  3593. Message2(asmw_e_value_exceeds_bounds,'unsigned nibble',tostr(currval));
  3594. end
  3595. else
  3596. if (currval<0) or (currval>255) then
  3597. Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
  3598. if assigned(currsym) then
  3599. objdata_writereloc(currval,1,currsym,currabsreloc)
  3600. else
  3601. objdata.writebytes(currval,1);
  3602. end;
  3603. &30,&31,&32 : // 030..032
  3604. begin
  3605. getvalsym(c-&30);
  3606. {$ifndef i8086}
  3607. { currval is an aint so this cannot happen on i8086 and causes only a warning }
  3608. if (currval<-65536) or (currval>65535) then
  3609. Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
  3610. {$endif i8086}
  3611. if assigned(currsym)
  3612. {$ifdef i8086}
  3613. or (currabsreloc in [RELOC_DGROUP,RELOC_FARDATASEG])
  3614. {$endif i8086}
  3615. then
  3616. objdata_writereloc(currval,2,currsym,currabsreloc)
  3617. else
  3618. objdata.writebytes(currval,2);
  3619. end;
  3620. &34,&35,&36 : // 034..036
  3621. { !!! These are intended (and used in opcode table) to select depending
  3622. on address size, *not* operand size. Works by coincidence only. }
  3623. begin
  3624. getvalsym(c-&34);
  3625. {$ifdef i8086}
  3626. if assigned(currsym) then
  3627. objdata_writereloc(currval,2,currsym,currabsreloc)
  3628. else
  3629. objdata.writebytes(currval,2);
  3630. {$else i8086}
  3631. if opsize=S_Q then
  3632. begin
  3633. if assigned(currsym) then
  3634. objdata_writereloc(currval,8,currsym,currabsreloc)
  3635. else
  3636. objdata.writebytes(currval,8);
  3637. end
  3638. else
  3639. begin
  3640. if assigned(currsym) then
  3641. objdata_writereloc(currval,4,currsym,currabsreloc32)
  3642. else
  3643. objdata.writebytes(currval,4);
  3644. end
  3645. {$endif i8086}
  3646. end;
  3647. &40,&41,&42 : // 040..042
  3648. begin
  3649. getvalsym(c-&40);
  3650. if assigned(currsym)
  3651. {$ifdef i8086}
  3652. or (currabsreloc in [RELOC_DGROUP,RELOC_FARDATASEG])
  3653. {$endif i8086}
  3654. then
  3655. objdata_writereloc(currval,4,currsym,currabsreloc32)
  3656. else
  3657. objdata.writebytes(currval,4);
  3658. end;
  3659. &44,&45,&46 :// 044..046 - select between word/dword/qword depending on
  3660. begin // address size (we support only default address sizes).
  3661. getvalsym(c-&44);
  3662. {$if defined(x86_64)}
  3663. if assigned(currsym) then
  3664. objdata_writereloc(currval,8,currsym,currabsreloc)
  3665. else
  3666. objdata.writebytes(currval,8);
  3667. {$elseif defined(i386)}
  3668. if assigned(currsym) then
  3669. objdata_writereloc(currval,4,currsym,currabsreloc32)
  3670. else
  3671. objdata.writebytes(currval,4);
  3672. {$elseif defined(i8086)}
  3673. if assigned(currsym) then
  3674. objdata_writereloc(currval,2,currsym,currabsreloc)
  3675. else
  3676. objdata.writebytes(currval,2);
  3677. {$endif}
  3678. end;
  3679. &50,&51,&52 : // 050..052 - byte relative operand
  3680. begin
  3681. getvalsym(c-&50);
  3682. data:=currval-insend;
  3683. {$push}
  3684. {$r-,q-} { disable also overflow as address returns a qword for x86_64 }
  3685. if assigned(currsym) then
  3686. inc(data,currsym.address);
  3687. {$pop}
  3688. if (data>127) or (data<-128) then
  3689. Message1(asmw_e_short_jmp_out_of_range,tostr(data));
  3690. objdata.writebytes(data,1);
  3691. end;
  3692. &54,&55,&56: // 054..056 - qword immediate operand
  3693. begin
  3694. getvalsym(c-&54);
  3695. if assigned(currsym) then
  3696. objdata_writereloc(currval,8,currsym,currabsreloc)
  3697. else
  3698. objdata.writebytes(currval,8);
  3699. end;
  3700. &60,&61,&62 :
  3701. begin
  3702. getvalsym(c-&60);
  3703. {$ifdef i8086}
  3704. if assigned(currsym) then
  3705. objdata_writereloc(currval,2,currsym,currrelreloc)
  3706. else
  3707. objdata_writereloc(currval-insend,2,nil,currabsreloc)
  3708. {$else i8086}
  3709. InternalError(777006);
  3710. {$endif i8086}
  3711. end;
  3712. &64,&65,&66 : // 064..066 - select between 16/32 address mode, but we support only 32 (only 16 on i8086)
  3713. begin
  3714. getvalsym(c-&64);
  3715. {$ifdef i8086}
  3716. if assigned(currsym) then
  3717. objdata_writereloc(currval,2,currsym,currrelreloc)
  3718. else
  3719. objdata_writereloc(currval-insend,2,nil,currabsreloc)
  3720. {$else i8086}
  3721. if assigned(currsym) then
  3722. objdata_writereloc(currval,4,currsym,currrelreloc)
  3723. else
  3724. objdata_writereloc(currval-insend,4,nil,currabsreloc32)
  3725. {$endif i8086}
  3726. end;
  3727. &70,&71,&72 : // 070..072 - long relative operand
  3728. begin
  3729. getvalsym(c-&70);
  3730. if assigned(currsym) then
  3731. objdata_writereloc(currval,4,currsym,currrelreloc)
  3732. else
  3733. objdata_writereloc(currval-insend,4,nil,currabsreloc32)
  3734. end;
  3735. &74,&75,&76 : ; // 074..076 - vex-coded vector operand
  3736. // ignore
  3737. &254,&255,&256 : // 0254..0256 - dword implicitly sign-extended to 64-bit (x86_64 only)
  3738. begin
  3739. getvalsym(c-&254);
  3740. {$ifdef x86_64}
  3741. { for i386 as aint type is longint the
  3742. following test is useless }
  3743. if (currval<low(longint)) or (currval>high(longint)) then
  3744. Message2(asmw_e_value_exceeds_bounds,'signed dword',tostr(currval));
  3745. {$endif x86_64}
  3746. if assigned(currsym) then
  3747. objdata_writereloc(currval,4,currsym,currabsreloc32)
  3748. else
  3749. objdata.writebytes(currval,4);
  3750. end;
  3751. &300,&301,&302:
  3752. begin
  3753. {$if defined(x86_64) or defined(i8086)}
  3754. if (oper[c and 3]^.ot and OT_SIZE_MASK)=OT_BITS32 then
  3755. write0x67prefix(objdata);
  3756. {$endif x86_64 or i8086}
  3757. end;
  3758. &310 : { fixed 16-bit addr }
  3759. {$if defined(x86_64)}
  3760. { every insentry having code 0310 must be marked with NOX86_64 }
  3761. InternalError(2011051302);
  3762. {$elseif defined(i386)}
  3763. write0x67prefix(objdata);
  3764. {$elseif defined(i8086)}
  3765. {nothing};
  3766. {$endif}
  3767. &311 : { fixed 32-bit addr }
  3768. {$if defined(x86_64) or defined(i8086)}
  3769. write0x67prefix(objdata)
  3770. {$endif x86_64 or i8086}
  3771. ;
  3772. &320,&321,&322 :
  3773. begin
  3774. case oper[c-&320]^.ot and OT_SIZE_MASK of
  3775. {$if defined(i386) or defined(x86_64)}
  3776. OT_BITS16 :
  3777. {$elseif defined(i8086)}
  3778. OT_BITS32 :
  3779. {$endif}
  3780. write0x66prefix(objdata);
  3781. {$ifndef x86_64}
  3782. OT_BITS64 :
  3783. Message(asmw_e_64bit_not_supported);
  3784. {$endif x86_64}
  3785. end;
  3786. end;
  3787. &323 : {no action needed};
  3788. &325:
  3789. {$ifdef i8086}
  3790. write0x66prefix(objdata);
  3791. {$else i8086}
  3792. {no action needed};
  3793. {$endif i8086}
  3794. &324,
  3795. &361:
  3796. begin
  3797. {$ifndef i8086}
  3798. if not(needed_VEX or needed_EVEX) then
  3799. write0x66prefix(objdata);
  3800. {$endif not i8086}
  3801. end;
  3802. &326 :
  3803. begin
  3804. {$ifndef x86_64}
  3805. Message(asmw_e_64bit_not_supported);
  3806. {$endif x86_64}
  3807. end;
  3808. &333 :
  3809. begin
  3810. if not(needed_VEX or needed_EVEX) then
  3811. begin
  3812. bytes[0]:=$f3;
  3813. objdata.writebytes(bytes,1);
  3814. end;
  3815. end;
  3816. &334 :
  3817. begin
  3818. if not(needed_VEX or needed_EVEX) then
  3819. begin
  3820. bytes[0]:=$f2;
  3821. objdata.writebytes(bytes,1);
  3822. end;
  3823. end;
  3824. &335:
  3825. ;
  3826. &312,
  3827. &327,
  3828. &331,&332 :
  3829. begin
  3830. { these are dissambler hints or 32 bit prefixes which
  3831. are not needed }
  3832. end;
  3833. &362..&364: ; // VEX flags =>> nothing todo
  3834. &366, &367:
  3835. begin
  3836. opidx:=c-&364; { 0366->operand 2, 0367->operand 3 }
  3837. if (needed_VEX or needed_EVEX) and
  3838. (ops=4) and
  3839. (oper[opidx]^.typ=top_reg) and
  3840. (
  3841. ((oper[opidx]^.ot and OT_REG_EXTRA_MASK)=otf_reg_xmm) or
  3842. ((oper[opidx]^.ot and OT_REG_EXTRA_MASK)=otf_reg_ymm) or
  3843. ((oper[opidx]^.ot and OT_REG_EXTRA_MASK)=otf_reg_zmm)
  3844. ) then
  3845. begin
  3846. bytes[0] := ((getsupreg(oper[opidx]^.reg) and 15) shl 4);
  3847. objdata.writebytes(bytes,1);
  3848. end
  3849. else
  3850. Internalerror(2014032001);
  3851. end;
  3852. &350..&352: ; // EVEX flags =>> nothing todo
  3853. &370..&372: ; // VEX flags =>> nothing todo
  3854. &37:
  3855. begin
  3856. {$ifdef i8086}
  3857. if assigned(currsym) then
  3858. objdata_writereloc(0,2,currsym,RELOC_SEG)
  3859. else
  3860. InternalError(2015041503);
  3861. {$else i8086}
  3862. InternalError(777006);
  3863. {$endif i8086}
  3864. end;
  3865. else
  3866. begin
  3867. { rex should be written at this point }
  3868. {$ifdef x86_64}
  3869. if not(needed_VEX or needed_EVEX) then // TG
  3870. if (rex<>0) and not(rexwritten) then
  3871. internalerror(200603191);
  3872. {$endif x86_64}
  3873. if (c>=&100) and (c<=&227) then // 0100..0227
  3874. begin
  3875. if (c<&177) then // 0177
  3876. begin
  3877. if (oper[c and 7]^.typ=top_reg) then
  3878. rfield:=regval(oper[c and 7]^.reg)
  3879. else
  3880. rfield:=regval(oper[c and 7]^.ref^.base);
  3881. end
  3882. else
  3883. rfield:=c and 7;
  3884. opidx:=(c shr 3) and 7;
  3885. if not process_ea(oper[opidx]^,ea_data,rfield, needed_EVEX) then
  3886. Message(asmw_e_invalid_effective_address);
  3887. pb:=@bytes[0];
  3888. pb^:=ea_data.modrm;
  3889. inc(pb);
  3890. if ea_data.sib_present then
  3891. begin
  3892. pb^:=ea_data.sib;
  3893. inc(pb);
  3894. end;
  3895. s:=pb-@bytes[0];
  3896. objdata.writebytes(bytes,s);
  3897. case ea_data.bytes of
  3898. 0 : ;
  3899. 1 :
  3900. begin
  3901. if (oper[opidx]^.ot and OT_MEMORY)=OT_MEMORY then
  3902. begin
  3903. currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
  3904. {$ifdef i386}
  3905. if (oper[opidx]^.ref^.refaddr=addr_pic) and
  3906. (tf_pic_uses_got in target_info.flags) then
  3907. currabsreloc:=RELOC_GOT32
  3908. else
  3909. {$endif i386}
  3910. {$ifdef x86_64}
  3911. if oper[opidx]^.ref^.refaddr=addr_pic then
  3912. currabsreloc:=RELOC_GOTPCREL
  3913. else
  3914. {$endif x86_64}
  3915. currabsreloc:=RELOC_ABSOLUTE;
  3916. objdata_writereloc(oper[opidx]^.ref^.offset,1,currsym,currabsreloc);
  3917. end
  3918. else
  3919. begin
  3920. bytes[0]:=oper[opidx]^.ref^.offset;
  3921. objdata.writebytes(bytes,1);
  3922. end;
  3923. inc(s);
  3924. end;
  3925. 2,4 :
  3926. begin
  3927. currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
  3928. currval:=oper[opidx]^.ref^.offset;
  3929. {$ifdef x86_64}
  3930. if oper[opidx]^.ref^.refaddr=addr_pic then
  3931. currabsreloc:=RELOC_GOTPCREL
  3932. else
  3933. if oper[opidx]^.ref^.base=NR_RIP then
  3934. begin
  3935. currabsreloc:=RELOC_RELATIVE;
  3936. { Adjust reloc value by number of bytes following the displacement,
  3937. but not if displacement is specified by literal constant }
  3938. if Assigned(currsym) then
  3939. Dec(currval,InsEnd-objdata.CurrObjSec.Size-ea_data.bytes);
  3940. end
  3941. else
  3942. {$endif x86_64}
  3943. {$ifdef i386}
  3944. if (oper[opidx]^.ref^.refaddr=addr_pic) and
  3945. (tf_pic_uses_got in target_info.flags) then
  3946. currabsreloc:=RELOC_GOT32
  3947. else
  3948. {$endif i386}
  3949. {$ifdef i8086}
  3950. if ea_data.bytes=2 then
  3951. currabsreloc:=RELOC_ABSOLUTE
  3952. else
  3953. {$endif i8086}
  3954. currabsreloc:=RELOC_ABSOLUTE32;
  3955. if (currabsreloc in [RELOC_ABSOLUTE32{$ifdef i8086},RELOC_ABSOLUTE{$endif}]) and
  3956. (Assigned(oper[opidx]^.ref^.relsymbol)) then
  3957. begin
  3958. relsym:=objdata.symbolref(oper[opidx]^.ref^.relsymbol);
  3959. if relsym.objsection=objdata.CurrObjSec then
  3960. begin
  3961. currval:=objdata.CurrObjSec.size+ea_data.bytes-relsym.offset+currval;
  3962. {$ifdef i8086}
  3963. if ea_data.bytes=4 then
  3964. currabsreloc:=RELOC_RELATIVE32
  3965. else
  3966. {$endif i8086}
  3967. currabsreloc:=RELOC_RELATIVE;
  3968. end
  3969. else
  3970. begin
  3971. currabsreloc:=RELOC_PIC_PAIR;
  3972. currval:=relsym.offset;
  3973. end;
  3974. end;
  3975. objdata_writereloc(currval,ea_data.bytes,currsym,currabsreloc);
  3976. inc(s,ea_data.bytes);
  3977. end;
  3978. end;
  3979. end
  3980. else
  3981. InternalError(777007);
  3982. end;
  3983. end;
  3984. until false;
  3985. end;
  3986. function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
  3987. begin
  3988. result:=(((opcode=A_MOV) or (opcode=A_XCHG)) and
  3989. (regtype = R_INTREGISTER) and
  3990. (ops=2) and
  3991. (oper[0]^.typ=top_reg) and
  3992. (oper[1]^.typ=top_reg) and
  3993. (oper[0]^.reg=oper[1]^.reg)
  3994. ) or
  3995. ({ checking the opcodes is a long "or" chain, so check first the registers which is more selective }
  3996. ((regtype = R_MMREGISTER) and
  3997. (ops=2) and
  3998. (oper[0]^.typ=top_reg) and
  3999. (oper[1]^.typ=top_reg) and
  4000. (oper[0]^.reg=oper[1]^.reg)) and
  4001. (
  4002. (opcode=A_MOVSS) or (opcode=A_MOVSD) or
  4003. (opcode=A_MOVQ) or (opcode=A_MOVD) or
  4004. (opcode=A_MOVAPS) or (opcode=A_MOVAPD) or
  4005. (opcode=A_MOVUPS) or (opcode=A_MOVUPD) or
  4006. (opcode=A_MOVDQA) or (opcode=A_MOVDQU) or
  4007. (opcode=A_VMOVSS) or (opcode=A_VMOVSD) or
  4008. (opcode=A_VMOVQ) or (opcode=A_VMOVD) or
  4009. (opcode=A_VMOVAPS) or (opcode=A_VMOVAPD) or
  4010. (opcode=A_VMOVUPS) or (opcode=A_VMOVUPD) or
  4011. (opcode=A_VMOVDQA) or (opcode=A_VMOVDQU)
  4012. )
  4013. );
  4014. end;
  4015. procedure build_spilling_operation_type_table;
  4016. var
  4017. opcode : tasmop;
  4018. i : integer;
  4019. begin
  4020. new(operation_type_table);
  4021. fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
  4022. for opcode:=low(tasmop) to high(tasmop) do
  4023. with InsProp[opcode] do
  4024. begin
  4025. if Ch_Rop1 in Ch then
  4026. operation_type_table^[opcode,0]:=operand_read;
  4027. if Ch_Wop1 in Ch then
  4028. operation_type_table^[opcode,0]:=operand_write;
  4029. if [Ch_RWop1,Ch_Mop1]*Ch<>[] then
  4030. operation_type_table^[opcode,0]:=operand_readwrite;
  4031. if Ch_Rop2 in Ch then
  4032. operation_type_table^[opcode,1]:=operand_read;
  4033. if Ch_Wop2 in Ch then
  4034. operation_type_table^[opcode,1]:=operand_write;
  4035. if [Ch_RWop2,Ch_Mop2]*Ch<>[] then
  4036. operation_type_table^[opcode,1]:=operand_readwrite;
  4037. if Ch_Rop3 in Ch then
  4038. operation_type_table^[opcode,2]:=operand_read;
  4039. if Ch_Wop3 in Ch then
  4040. operation_type_table^[opcode,2]:=operand_write;
  4041. if [Ch_RWop3,Ch_Mop3]*Ch<>[] then
  4042. operation_type_table^[opcode,2]:=operand_readwrite;
  4043. if Ch_Rop4 in Ch then
  4044. operation_type_table^[opcode,3]:=operand_read;
  4045. if Ch_Wop4 in Ch then
  4046. operation_type_table^[opcode,3]:=operand_write;
  4047. if [Ch_RWop4,Ch_Mop4]*Ch<>[] then
  4048. operation_type_table^[opcode,3]:=operand_readwrite;
  4049. end;
  4050. end;
  4051. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  4052. begin
  4053. { the information in the instruction table is made for the string copy
  4054. operation MOVSD so hack here (FK)
  4055. VMOVSS and VMOVSD has two and three operand flavours, this cannot modelled by x86ins.dat
  4056. so fix it here (FK)
  4057. }
  4058. if ((opcode=A_MOVSD) or (opcode=A_VMOVSS) or (opcode=A_VMOVSD)) and (ops=2) then
  4059. begin
  4060. case opnr of
  4061. 0:
  4062. result:=operand_read;
  4063. 1:
  4064. result:=operand_write;
  4065. else
  4066. internalerror(200506055);
  4067. end
  4068. end
  4069. { IMUL has 1, 2 and 3-operand forms }
  4070. else if opcode=A_IMUL then
  4071. begin
  4072. case ops of
  4073. 1:
  4074. if opnr=0 then
  4075. result:=operand_read
  4076. else
  4077. internalerror(2014011802);
  4078. 2:
  4079. begin
  4080. case opnr of
  4081. 0:
  4082. result:=operand_read;
  4083. 1:
  4084. result:=operand_readwrite;
  4085. else
  4086. internalerror(2014011803);
  4087. end;
  4088. end;
  4089. 3:
  4090. begin
  4091. case opnr of
  4092. 0,1:
  4093. result:=operand_read;
  4094. 2:
  4095. result:=operand_write;
  4096. else
  4097. internalerror(2014011804);
  4098. end;
  4099. end;
  4100. else
  4101. internalerror(2014011805);
  4102. end;
  4103. end
  4104. else
  4105. result:=operation_type_table^[opcode,opnr];
  4106. end;
  4107. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  4108. var
  4109. tmpref: treference;
  4110. begin
  4111. tmpref:=ref;
  4112. {$ifdef i8086}
  4113. if tmpref.segment=NR_SS then
  4114. tmpref.segment:=NR_NO;
  4115. {$endif i8086}
  4116. case getregtype(r) of
  4117. R_INTREGISTER :
  4118. begin
  4119. if getsubreg(r)=R_SUBH then
  4120. inc(tmpref.offset);
  4121. { we don't need special code here for 32 bit loads on x86_64, since
  4122. those will automatically zero-extend the upper 32 bits. }
  4123. result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),tmpref,r);
  4124. end;
  4125. R_MMREGISTER :
  4126. if current_settings.fputype in fpu_avx_instructionsets then
  4127. case getsubreg(r) of
  4128. R_SUBMMD:
  4129. result:=taicpu.op_ref_reg(A_VMOVSD,S_NO,tmpref,r);
  4130. R_SUBMMS:
  4131. result:=taicpu.op_ref_reg(A_VMOVSS,S_NO,tmpref,r);
  4132. R_SUBQ,
  4133. R_SUBMMWHOLE:
  4134. result:=taicpu.op_ref_reg(A_VMOVQ,S_NO,tmpref,r);
  4135. else
  4136. internalerror(200506043);
  4137. end
  4138. else
  4139. case getsubreg(r) of
  4140. R_SUBMMD:
  4141. result:=taicpu.op_ref_reg(A_MOVSD,S_NO,tmpref,r);
  4142. R_SUBMMS:
  4143. result:=taicpu.op_ref_reg(A_MOVSS,S_NO,tmpref,r);
  4144. R_SUBQ,
  4145. R_SUBMMWHOLE:
  4146. result:=taicpu.op_ref_reg(A_MOVQ,S_NO,tmpref,r);
  4147. else
  4148. internalerror(200506043);
  4149. end;
  4150. else
  4151. internalerror(200401041);
  4152. end;
  4153. end;
  4154. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  4155. var
  4156. size: topsize;
  4157. tmpref: treference;
  4158. begin
  4159. tmpref:=ref;
  4160. {$ifdef i8086}
  4161. if tmpref.segment=NR_SS then
  4162. tmpref.segment:=NR_NO;
  4163. {$endif i8086}
  4164. case getregtype(r) of
  4165. R_INTREGISTER :
  4166. begin
  4167. if getsubreg(r)=R_SUBH then
  4168. inc(tmpref.offset);
  4169. size:=reg2opsize(r);
  4170. {$ifdef x86_64}
  4171. { even if it's a 32 bit reg, we still have to spill 64 bits
  4172. because we often perform 64 bit operations on them }
  4173. if (size=S_L) then
  4174. begin
  4175. size:=S_Q;
  4176. r:=newreg(getregtype(r),getsupreg(r),R_SUBWHOLE);
  4177. end;
  4178. {$endif x86_64}
  4179. result:=taicpu.op_reg_ref(A_MOV,size,r,tmpref);
  4180. end;
  4181. R_MMREGISTER :
  4182. if current_settings.fputype in fpu_avx_instructionsets then
  4183. case getsubreg(r) of
  4184. R_SUBMMD:
  4185. result:=taicpu.op_reg_ref(A_VMOVSD,S_NO,r,tmpref);
  4186. R_SUBMMS:
  4187. result:=taicpu.op_reg_ref(A_VMOVSS,S_NO,r,tmpref);
  4188. R_SUBQ,
  4189. R_SUBMMWHOLE:
  4190. result:=taicpu.op_reg_ref(A_VMOVQ,S_NO,r,tmpref);
  4191. else
  4192. internalerror(200506042);
  4193. end
  4194. else
  4195. case getsubreg(r) of
  4196. R_SUBMMD:
  4197. result:=taicpu.op_reg_ref(A_MOVSD,S_NO,r,tmpref);
  4198. R_SUBMMS:
  4199. result:=taicpu.op_reg_ref(A_MOVSS,S_NO,r,tmpref);
  4200. R_SUBQ,
  4201. R_SUBMMWHOLE:
  4202. result:=taicpu.op_reg_ref(A_MOVQ,S_NO,r,tmpref);
  4203. else
  4204. internalerror(200506042);
  4205. end;
  4206. else
  4207. internalerror(200401041);
  4208. end;
  4209. end;
  4210. {$ifdef i8086}
  4211. procedure taicpu.loadsegsymbol(opidx:longint;s:tasmsymbol);
  4212. var
  4213. r: treference;
  4214. begin
  4215. reference_reset_symbol(r,s,0,1,[]);
  4216. r.refaddr:=addr_seg;
  4217. loadref(opidx,r);
  4218. end;
  4219. {$endif i8086}
  4220. {*****************************************************************************
  4221. Instruction table
  4222. *****************************************************************************}
  4223. procedure BuildInsTabCache;
  4224. var
  4225. i : longint;
  4226. begin
  4227. new(instabcache);
  4228. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  4229. i:=0;
  4230. while (i<InsTabEntries) do
  4231. begin
  4232. if InsTabCache^[InsTab[i].OPcode]=-1 then
  4233. InsTabCache^[InsTab[i].OPcode]:=i;
  4234. inc(i);
  4235. end;
  4236. end;
  4237. procedure BuildInsTabMemRefSizeInfoCache;
  4238. var
  4239. AsmOp: TasmOp;
  4240. i,j: longint;
  4241. insentry : PInsEntry;
  4242. codes : pchar;
  4243. c : byte;
  4244. MRefInfo: TMemRefSizeInfo;
  4245. SConstInfo: TConstSizeInfo;
  4246. actRegSize: int64;
  4247. actMemSize: int64;
  4248. actConstSize: int64;
  4249. actRegCount: integer;
  4250. actMemCount: integer;
  4251. actConstCount: integer;
  4252. actRegTypes : int64;
  4253. actRegMemTypes: int64;
  4254. NewRegSize: int64;
  4255. actVMemCount : integer;
  4256. actVMemTypes : int64;
  4257. RegMMXSizeMask: int64;
  4258. RegXMMSizeMask: int64;
  4259. RegYMMSizeMask: int64;
  4260. RegZMMSizeMask: int64;
  4261. RegMMXConstSizeMask: int64;
  4262. RegXMMConstSizeMask: int64;
  4263. RegYMMConstSizeMask: int64;
  4264. RegZMMConstSizeMask: int64;
  4265. RegBCSTSizeMask: int64;
  4266. RegBCSTXMMSizeMask: int64;
  4267. RegBCSTYMMSizeMask: int64;
  4268. RegBCSTZMMSizeMask: int64;
  4269. bitcount: integer;
  4270. function bitcnt(aValue: int64): integer;
  4271. var
  4272. i: integer;
  4273. begin
  4274. result := 0;
  4275. for i := 0 to 63 do
  4276. begin
  4277. if (aValue mod 2) = 1 then
  4278. begin
  4279. inc(result);
  4280. end;
  4281. aValue := aValue shr 1;
  4282. end;
  4283. end;
  4284. begin
  4285. new(InsTabMemRefSizeInfoCache);
  4286. FillChar(InsTabMemRefSizeInfoCache^,sizeof(TInsTabMemRefSizeInfoCache),0);
  4287. for AsmOp := low(TAsmOp) to high(TAsmOp) do
  4288. begin
  4289. i := InsTabCache^[AsmOp];
  4290. if i >= 0 then
  4291. begin
  4292. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiUnkown;
  4293. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSizeBCST := msbUnknown;
  4294. InsTabMemRefSizeInfoCache^[AsmOp].BCSTXMMMultiplicator := 0;
  4295. InsTabMemRefSizeInfoCache^[AsmOp].ConstSize := csiUnkown;
  4296. InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := false;
  4297. InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes := [];
  4298. insentry:=@instab[i];
  4299. RegMMXSizeMask := 0;
  4300. RegXMMSizeMask := 0;
  4301. RegYMMSizeMask := 0;
  4302. RegZMMSizeMask := 0;
  4303. RegMMXConstSizeMask := 0;
  4304. RegXMMConstSizeMask := 0;
  4305. RegYMMConstSizeMask := 0;
  4306. RegZMMConstSizeMask := 0;
  4307. RegBCSTSizeMask:= 0;
  4308. RegBCSTXMMSizeMask := 0;
  4309. RegBCSTYMMSizeMask := 0;
  4310. RegBCSTZMMSizeMask := 0;
  4311. //TG TODO delete
  4312. if Asmop = A_VFPCLASSPD then
  4313. begin
  4314. MRefInfo := msiUnkown;
  4315. end;
  4316. while (insentry^.opcode=AsmOp) do
  4317. begin
  4318. MRefInfo := msiUnkown;
  4319. actRegSize := 0;
  4320. actRegCount := 0;
  4321. actRegTypes := 0;
  4322. NewRegSize := 0;
  4323. actMemSize := 0;
  4324. actMemCount := 0;
  4325. actRegMemTypes := 0;
  4326. actVMemCount := 0;
  4327. actVMemTypes := 0;
  4328. actConstSize := 0;
  4329. actConstCount := 0;
  4330. for j := 0 to insentry^.ops -1 do
  4331. begin
  4332. if ((insentry^.optypes[j] and OT_XMEM32) = OT_XMEM32) OR
  4333. ((insentry^.optypes[j] and OT_XMEM64) = OT_XMEM64) OR
  4334. ((insentry^.optypes[j] and OT_YMEM32) = OT_YMEM32) OR
  4335. ((insentry^.optypes[j] and OT_YMEM64) = OT_YMEM64) OR
  4336. ((insentry^.optypes[j] and OT_ZMEM32) = OT_ZMEM32) OR
  4337. ((insentry^.optypes[j] and OT_ZMEM64) = OT_ZMEM64) then
  4338. begin
  4339. inc(actVMemCount);
  4340. case insentry^.optypes[j] and (OT_XMEM32 OR OT_XMEM64 OR OT_YMEM32 OR OT_YMEM64 OR OT_ZMEM32 OR OT_ZMEM64) of
  4341. OT_XMEM32: actVMemTypes := actVMemTypes or OT_XMEM32;
  4342. OT_XMEM64: actVMemTypes := actVMemTypes or OT_XMEM64;
  4343. OT_YMEM32: actVMemTypes := actVMemTypes or OT_YMEM32;
  4344. OT_YMEM64: actVMemTypes := actVMemTypes or OT_YMEM64;
  4345. OT_ZMEM32: actVMemTypes := actVMemTypes or OT_ZMEM32;
  4346. OT_ZMEM64: actVMemTypes := actVMemTypes or OT_ZMEM64;
  4347. else InternalError(777206);
  4348. end;
  4349. end
  4350. else if (insentry^.optypes[j] and OT_REGISTER) = OT_REGISTER then
  4351. begin
  4352. inc(actRegCount);
  4353. NewRegSize := (insentry^.optypes[j] and OT_SIZE_MASK);
  4354. if NewRegSize = 0 then
  4355. begin
  4356. case insentry^.optypes[j] and (OT_MMXREG or OT_XMMREG or OT_YMMREG or OT_ZMMREG or OT_KREG or OT_REG_EXTRA_MASK) of
  4357. OT_MMXREG: begin
  4358. NewRegSize := OT_BITS64;
  4359. end;
  4360. OT_XMMREG: begin
  4361. NewRegSize := OT_BITS128;
  4362. InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
  4363. end;
  4364. OT_YMMREG: begin
  4365. NewRegSize := OT_BITS256;
  4366. InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
  4367. end;
  4368. OT_ZMMREG: begin
  4369. NewRegSize := OT_BITS512;
  4370. InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
  4371. end;
  4372. OT_KREG: begin
  4373. InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX := true;
  4374. end;
  4375. else NewRegSize := not(0);
  4376. end;
  4377. end;
  4378. actRegSize := actRegSize or NewRegSize;
  4379. actRegTypes := actRegTypes or (insentry^.optypes[j] and (OT_MMXREG or OT_XMMREG or OT_YMMREG or OT_ZMMREG or OT_KREG or OT_REG_EXTRA_MASK));
  4380. end
  4381. else if ((insentry^.optypes[j] and OT_MEMORY) <> 0) then
  4382. begin
  4383. inc(actMemCount);
  4384. actMemSize:=actMemSize or (insentry^.optypes[j] and (OT_SIZE_MASK OR OT_VECTORBCST));
  4385. if (insentry^.optypes[j] and OT_REGMEM) = OT_REGMEM then
  4386. begin
  4387. actRegMemTypes := actRegMemTypes or insentry^.optypes[j];
  4388. end;
  4389. end
  4390. else if ((insentry^.optypes[j] and OT_IMMEDIATE) = OT_IMMEDIATE) then
  4391. begin
  4392. inc(actConstCount);
  4393. actConstSize := actConstSize or (insentry^.optypes[j] and OT_SIZE_MASK);
  4394. end
  4395. end;
  4396. if actConstCount > 0 then
  4397. begin
  4398. case actConstSize of
  4399. 0: SConstInfo := csiNoSize;
  4400. OT_BITS8: SConstInfo := csiMem8;
  4401. OT_BITS16: SConstInfo := csiMem16;
  4402. OT_BITS32: SConstInfo := csiMem32;
  4403. OT_BITS64: SConstInfo := csiMem64;
  4404. else SConstInfo := csiMultiple;
  4405. end;
  4406. if InsTabMemRefSizeInfoCache^[AsmOp].ConstSize = csiUnkown then
  4407. begin
  4408. InsTabMemRefSizeInfoCache^[AsmOp].ConstSize := SConstInfo;
  4409. end
  4410. else if InsTabMemRefSizeInfoCache^[AsmOp].ConstSize <> SConstInfo then
  4411. begin
  4412. InsTabMemRefSizeInfoCache^[AsmOp].ConstSize := csiMultiple;
  4413. end;
  4414. end;
  4415. if actVMemCount > 0 then
  4416. begin
  4417. if actVMemCount = 1 then
  4418. begin
  4419. if actVMemTypes > 0 then
  4420. begin
  4421. case actVMemTypes of
  4422. OT_XMEM32: MRefInfo := msiXMem32;
  4423. OT_XMEM64: MRefInfo := msiXMem64;
  4424. OT_YMEM32: MRefInfo := msiYMem32;
  4425. OT_YMEM64: MRefInfo := msiYMem64;
  4426. OT_ZMEM32: MRefInfo := msiZMem32;
  4427. OT_ZMEM64: MRefInfo := msiZMem64;
  4428. else InternalError(777208);
  4429. end;
  4430. case actRegTypes of
  4431. OT_XMMREG: case MRefInfo of
  4432. msiXMem32,
  4433. msiXMem64: RegXMMSizeMask := RegXMMSizeMask or OT_BITS128;
  4434. msiYMem32,
  4435. msiYMem64: RegXMMSizeMask := RegXMMSizeMask or OT_BITS256;
  4436. msiZMem32,
  4437. msiZMem64: RegXMMSizeMask := RegXMMSizeMask or OT_BITS512;
  4438. else InternalError(777210);
  4439. end;
  4440. OT_YMMREG: case MRefInfo of
  4441. msiXMem32,
  4442. msiXMem64: RegYMMSizeMask := RegYMMSizeMask or OT_BITS128;
  4443. msiYMem32,
  4444. msiYMem64: RegYMMSizeMask := RegYMMSizeMask or OT_BITS256;
  4445. msiZMem32,
  4446. msiZMem64: RegYMMSizeMask := RegYMMSizeMask or OT_BITS512;
  4447. else InternalError(777211);
  4448. end;
  4449. OT_ZMMREG: case MRefInfo of
  4450. msiXMem32,
  4451. msiXMem64: RegZMMSizeMask := RegZMMSizeMask or OT_BITS128;
  4452. msiYMem32,
  4453. msiYMem64: RegZMMSizeMask := RegZMMSizeMask or OT_BITS256;
  4454. msiZMem32,
  4455. msiZMem64: RegZMMSizeMask := RegZMMSizeMask or OT_BITS512;
  4456. else InternalError(777211);
  4457. end;
  4458. //else InternalError(777209);
  4459. end;
  4460. if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiUnkown then
  4461. begin
  4462. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
  4463. end
  4464. else if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> MRefInfo then
  4465. begin
  4466. if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize in [msiXMem32, msiXMem64, msiYMem32, msiYMem64, msiZMem32, msiZMem64] then
  4467. begin
  4468. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiVMemMultiple;
  4469. end
  4470. else if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> msiVMemMultiple then InternalError(777212);
  4471. end;
  4472. end;
  4473. end
  4474. else InternalError(777207);
  4475. end
  4476. else
  4477. begin
  4478. if (actMemCount=2) and ((AsmOp=A_MOVS) or (AsmOp=A_CMPS)) then actMemCount:=1;
  4479. case actMemCount of
  4480. 0: ; // nothing todo
  4481. 1: begin
  4482. MRefInfo := msiUnkown;
  4483. case actRegMemTypes and (OT_MMXRM or OT_XMMRM or OT_YMMRM or OT_ZMMRM or OT_REG_EXTRA_MASK) of
  4484. OT_MMXRM: actMemSize := actMemSize or OT_BITS64;
  4485. OT_XMMRM: actMemSize := actMemSize or OT_BITS128;
  4486. OT_YMMRM: actMemSize := actMemSize or OT_BITS256;
  4487. OT_ZMMRM: actMemSize := actMemSize or OT_BITS512;
  4488. end;
  4489. case actMemSize of
  4490. 0: MRefInfo := msiNoSize;
  4491. OT_BITS8: MRefInfo := msiMem8;
  4492. OT_BITS16: MRefInfo := msiMem16;
  4493. OT_BITS32: MRefInfo := msiMem32;
  4494. OT_BITSB32: MRefInfo := msiBMem32;
  4495. OT_BITS64: MRefInfo := msiMem64;
  4496. OT_BITSB64: MRefInfo := msiBMem64;
  4497. OT_BITS128: MRefInfo := msiMem128;
  4498. OT_BITS256: MRefInfo := msiMem256;
  4499. OT_BITS512: MRefInfo := msiMem512;
  4500. OT_BITS80,
  4501. OT_FAR,
  4502. OT_NEAR,
  4503. OT_SHORT: ; // ignore
  4504. else
  4505. begin
  4506. bitcount := bitcnt(actMemSize);
  4507. if bitcount > 1 then MRefInfo := msiMultiple
  4508. else InternalError(777203);
  4509. end;
  4510. end;
  4511. if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiUnkown then
  4512. begin
  4513. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
  4514. end
  4515. else
  4516. begin
  4517. // ignore broadcast-memory
  4518. if not(MRefInfo in [msiBMem32, msiBMem64]) then
  4519. begin
  4520. if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> MRefInfo then
  4521. begin
  4522. with InsTabMemRefSizeInfoCache^[AsmOp] do
  4523. begin
  4524. if ((MemRefSize = msiMem8) OR (MRefInfo = msiMem8)) then MemRefSize := msiMultiple8
  4525. else if ((MemRefSize = msiMem16) OR (MRefInfo = msiMem16)) then MemRefSize := msiMultiple16
  4526. else if ((MemRefSize = msiMem32) OR (MRefInfo = msiMem32)) then MemRefSize := msiMultiple32
  4527. else if ((MemRefSize = msiMem64) OR (MRefInfo = msiMem64)) then MemRefSize := msiMultiple64
  4528. else if ((MemRefSize = msiMem128) OR (MRefInfo = msiMem128)) then MemRefSize := msiMultiple128
  4529. else if ((MemRefSize = msiMem256) OR (MRefInfo = msiMem256)) then MemRefSize := msiMultiple256
  4530. else if ((MemRefSize = msiMem512) OR (MRefInfo = msiMem512)) then MemRefSize := msiMultiple512
  4531. else MemRefSize := msiMultiple;
  4532. end;
  4533. end;
  4534. end;
  4535. end;
  4536. //if not(MRefInfo in [msiBMem32, msiBMem64]) and (actRegCount > 0) then
  4537. if actRegCount > 0 then
  4538. begin
  4539. if MRefInfo in [msiBMem32, msiBMem64] then
  4540. begin
  4541. if IF_BCST2 in insentry^.flags then InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes := InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes + [bt1to2];
  4542. if IF_BCST4 in insentry^.flags then InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes := InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes + [bt1to4];
  4543. if IF_BCST8 in insentry^.flags then InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes := InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes + [bt1to8];
  4544. if IF_BCST16 in insentry^.flags then InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes := InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes + [bt1to16];
  4545. //InsTabMemRefSizeInfoCache^[AsmOp].BCSTTypes
  4546. // BROADCAST - OPERAND
  4547. RegBCSTSizeMask := RegBCSTSizeMask or actMemSize;
  4548. case actRegTypes and (OT_XMMREG or OT_YMMREG or OT_ZMMREG or OT_REG_EXTRA_MASK) of
  4549. OT_XMMREG: RegBCSTXMMSizeMask := RegBCSTXMMSizeMask or actMemSize;
  4550. OT_YMMREG: RegBCSTYMMSizeMask := RegBCSTYMMSizeMask or actMemSize;
  4551. OT_ZMMREG: RegBCSTZMMSizeMask := RegBCSTZMMSizeMask or actMemSize;
  4552. else begin
  4553. RegBCSTXMMSizeMask := not(0);
  4554. RegBCSTYMMSizeMask := not(0);
  4555. RegBCSTZMMSizeMask := not(0);
  4556. end;
  4557. end;
  4558. end
  4559. else
  4560. case actRegTypes and (OT_MMXREG or OT_XMMREG or OT_YMMREG or OT_ZMMREG or OT_REG_EXTRA_MASK) of
  4561. OT_MMXREG: if actConstCount > 0 then RegMMXConstSizeMask := RegMMXConstSizeMask or actMemSize
  4562. else RegMMXSizeMask := RegMMXSizeMask or actMemSize;
  4563. OT_XMMREG: if actConstCount > 0 then RegXMMConstSizeMask := RegXMMConstSizeMask or actMemSize
  4564. else RegXMMSizeMask := RegXMMSizeMask or actMemSize;
  4565. OT_YMMREG: if actConstCount > 0 then RegYMMConstSizeMask := RegYMMConstSizeMask or actMemSize
  4566. else RegYMMSizeMask := RegYMMSizeMask or actMemSize;
  4567. OT_ZMMREG: if actConstCount > 0 then RegZMMConstSizeMask := RegZMMConstSizeMask or actMemSize
  4568. else RegZMMSizeMask := RegZMMSizeMask or actMemSize;
  4569. else begin
  4570. RegMMXSizeMask := not(0);
  4571. RegXMMSizeMask := not(0);
  4572. RegYMMSizeMask := not(0);
  4573. RegZMMSizeMask := not(0);
  4574. RegMMXConstSizeMask := not(0);
  4575. RegXMMConstSizeMask := not(0);
  4576. RegYMMConstSizeMask := not(0);
  4577. RegZMMConstSizeMask := not(0);
  4578. end;
  4579. end;
  4580. end
  4581. else
  4582. end
  4583. else InternalError(777202);
  4584. end;
  4585. end;
  4586. inc(insentry);
  4587. end;
  4588. if InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX then
  4589. begin
  4590. case RegBCSTSizeMask of
  4591. 0: ; // ignore;
  4592. OT_BITSB32: begin
  4593. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSizeBCST := msbBCST32;
  4594. InsTabMemRefSizeInfoCache^[AsmOp].BCSTXMMMultiplicator := 4;
  4595. end;
  4596. OT_BITSB64: begin
  4597. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSizeBCST := msbBCST64;
  4598. InsTabMemRefSizeInfoCache^[AsmOp].BCSTXMMMultiplicator := 2;
  4599. end;
  4600. else begin
  4601. //TG TODO - mixed broadcast
  4602. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSizeBCST := msbMultiple;
  4603. end;;
  4604. end;
  4605. end;
  4606. if (InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize in MemRefMultiples) and
  4607. (InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX)then
  4608. begin
  4609. if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiVMemMultiple then
  4610. begin
  4611. if ((RegXMMSizeMask = OT_BITS128) or (RegXMMSizeMask = 0)) and
  4612. ((RegYMMSizeMask = OT_BITS256) or (RegYMMSizeMask = 0)) and
  4613. ((RegZMMSizeMask = OT_BITS512) or (RegZMMSizeMask = 0)) and
  4614. ((RegXMMSizeMask or RegYMMSizeMask or RegZMMSizeMask) <> 0) then
  4615. begin
  4616. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiVMemRegSize;
  4617. end
  4618. else
  4619. begin
  4620. //TG TODO delete
  4621. if not((AsmOp = A_VGATHERQPS) or
  4622. (AsmOp = A_VGATHERQPS) or
  4623. (AsmOp = A_VPGATHERQD)) then
  4624. begin
  4625. RegZMMSizeMask := RegZMMSizeMask;
  4626. end;
  4627. end;
  4628. end
  4629. else if (RegMMXSizeMask or RegMMXConstSizeMask) <> 0 then
  4630. begin
  4631. if ((RegMMXSizeMask or RegMMXConstSizeMask) = OT_BITS64) and
  4632. ((RegXMMSizeMask or RegXMMConstSizeMask) = OT_BITS128) and
  4633. ((RegYMMSizeMask or RegYMMConstSizeMask) = 0) and
  4634. ((RegZMMSizeMask or RegZMMConstSizeMask) = 0) then
  4635. begin
  4636. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegSize;
  4637. end
  4638. else
  4639. begin
  4640. //TG TODO delete
  4641. if not(InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize in [msiMultiple16]) then
  4642. RegMMXSizeMask := RegMMXSizeMask;
  4643. end;
  4644. end
  4645. else if (((RegXMMSizeMask or RegXMMConstSizeMask) = OT_BITS128) or ((RegXMMSizeMask or RegXMMConstSizeMask) = 0)) and
  4646. (((RegYMMSizeMask or RegYMMConstSizeMask) = OT_BITS256) or ((RegYMMSizeMask or RegYMMConstSizeMask) = 0)) and
  4647. (((RegZMMSizeMask or RegZMMConstSizeMask) = OT_BITS512) or ((RegZMMSizeMask or RegZMMConstSizeMask) = 0)) and
  4648. (((RegXMMSizeMask or RegXMMConstSizeMask or
  4649. RegYMMSizeMask or RegYMMConstSizeMask or
  4650. RegZMMSizeMask or RegZMMConstSizeMask)) <> 0) then
  4651. begin
  4652. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegSize;
  4653. end
  4654. else if (RegXMMSizeMask or RegXMMConstSizeMask = OT_BITS16) and
  4655. (RegYMMSizeMask or RegYMMConstSizeMask = OT_BITS32) and
  4656. (RegZMMSizeMask or RegZMMConstSizeMask = 0) then
  4657. begin
  4658. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx16y32;
  4659. end
  4660. else if (RegXMMSizeMask or RegXMMConstSizeMask = OT_BITS16) and
  4661. (RegYMMSizeMask or RegYMMConstSizeMask = OT_BITS32) and
  4662. (RegZMMSizeMask or RegZMMConstSizeMask = OT_BITS64) then
  4663. begin
  4664. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx16y32z64;
  4665. end
  4666. else if ((RegXMMSizeMask or RegXMMConstSizeMask) = OT_BITS32) and
  4667. ((RegYMMSizeMask or RegYMMConstSizeMask) = OT_BITS64) then
  4668. begin
  4669. if ((RegZMMSizeMask or RegZMMConstSizeMask) = 0) then
  4670. begin
  4671. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx32y64;
  4672. end
  4673. else if ((RegZMMSizeMask or RegZMMConstSizeMask) = OT_BITS128) then
  4674. begin
  4675. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx32y64z128;
  4676. end
  4677. else
  4678. begin
  4679. //TG TODO delete
  4680. RegZMMSizeMask := RegZMMSizeMask;
  4681. end;
  4682. end
  4683. else if ((RegXMMSizeMask or RegXMMConstSizeMask) = OT_BITS64) and
  4684. ((RegYMMSizeMask or RegYMMConstSizeMask) = OT_BITS128) and
  4685. ((RegZMMSizeMask or RegZMMConstSizeMask) = 0) then
  4686. begin
  4687. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx64y128;
  4688. end
  4689. else if ((RegXMMSizeMask or RegXMMConstSizeMask) = OT_BITS64) and
  4690. ((RegYMMSizeMask or RegYMMConstSizeMask) = OT_BITS128) and
  4691. ((RegZMMSizeMask or RegZMMConstSizeMask) = OT_BITS256) then
  4692. begin
  4693. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx64y128z256;
  4694. end
  4695. else if ((RegXMMSizeMask or RegXMMConstSizeMask) = OT_BITS64) and
  4696. ((RegYMMSizeMask or RegYMMConstSizeMask) = OT_BITS256) and
  4697. ((RegZMMSizeMask or RegZMMConstSizeMask) = 0) then
  4698. begin
  4699. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx64y256;
  4700. end
  4701. else if ((RegXMMSizeMask or RegXMMConstSizeMask) = OT_BITS64) and
  4702. ((RegYMMSizeMask or RegYMMConstSizeMask) = OT_BITS256) and
  4703. ((RegZMMSizeMask or RegZMMConstSizeMask) = OT_BITS512) then
  4704. begin
  4705. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegx64y256z512;
  4706. end
  4707. else if ((RegXMMConstSizeMask = 0) or (RegXMMConstSizeMask = OT_BITS128)) and
  4708. ((RegYMMConstSizeMask = 0) or (RegYMMConstSizeMask = OT_BITS256)) and
  4709. ((RegZMMConstSizeMask = 0) or (RegZMMConstSizeMask = OT_BITS512)) and
  4710. ((RegXMMConstSizeMask or RegYMMConstSizeMask or RegZMMConstSizeMask) <> 0) and
  4711. (
  4712. ((RegXMMSizeMask or RegYMMSizeMask or RegZMMSizeMask) = OT_BITS128) or
  4713. ((RegXMMSizeMask or RegYMMSizeMask or RegZMMSizeMask) = OT_BITS256) or
  4714. ((RegXMMSizeMask or RegYMMSizeMask or RegZMMSizeMask) = OT_BITS512)
  4715. ) then
  4716. begin
  4717. case RegXMMSizeMask or RegYMMSizeMask or RegZMMSizeMask of
  4718. OT_BITS128: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegConst128;
  4719. OT_BITS256: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegConst256;
  4720. OT_BITS512: InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMemRegConst512;
  4721. else InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiMultiple;
  4722. end;
  4723. end
  4724. else
  4725. begin
  4726. if not(
  4727. (AsmOp = A_CVTSI2SS) or
  4728. (AsmOp = A_CVTSI2SD) or
  4729. (AsmOp = A_CVTPD2DQ) or
  4730. (AsmOp = A_VCVTPD2DQ) or
  4731. (AsmOp = A_VCVTPD2PS) or
  4732. (AsmOp = A_VCVTSI2SD) or
  4733. (AsmOp = A_VCVTSI2SS) or
  4734. (AsmOp = A_VCVTTPD2DQ) or
  4735. (AsmOp = A_VCVTPD2UDQ) or
  4736. (AsmOp = A_VCVTQQ2PS) or
  4737. (AsmOp = A_VCVTTPD2UDQ) or
  4738. (AsmOp = A_VCVTUQQ2PS) or
  4739. (AsmOp = A_VCVTUSI2SD) or
  4740. (AsmOp = A_VCVTUSI2SS) or
  4741. // TODO check
  4742. (AsmOp = A_VCMPSS)
  4743. ) then
  4744. InternalError(777205);
  4745. end;
  4746. end;
  4747. end;
  4748. end;
  4749. for AsmOp := low(TAsmOp) to high(TAsmOp) do
  4750. begin
  4751. // only supported intructiones with SSE- or AVX-operands
  4752. if not(InsTabMemRefSizeInfoCache^[AsmOp].ExistsSSEAVX) then
  4753. begin
  4754. InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := msiUnkown;
  4755. InsTabMemRefSizeInfoCache^[AsmOp].ConstSize := csiUnkown;
  4756. end;
  4757. end;
  4758. end;
  4759. procedure InitAsm;
  4760. begin
  4761. build_spilling_operation_type_table;
  4762. if not assigned(instabcache) then
  4763. BuildInsTabCache;
  4764. if not assigned(InsTabMemRefSizeInfoCache) then
  4765. BuildInsTabMemRefSizeInfoCache;
  4766. end;
  4767. procedure DoneAsm;
  4768. begin
  4769. if assigned(operation_type_table) then
  4770. begin
  4771. dispose(operation_type_table);
  4772. operation_type_table:=nil;
  4773. end;
  4774. if assigned(instabcache) then
  4775. begin
  4776. dispose(instabcache);
  4777. instabcache:=nil;
  4778. end;
  4779. if assigned(InsTabMemRefSizeInfoCache) then
  4780. begin
  4781. dispose(InsTabMemRefSizeInfoCache);
  4782. InsTabMemRefSizeInfoCache:=nil;
  4783. end;
  4784. end;
  4785. begin
  4786. cai_align:=tai_align;
  4787. cai_cpu:=taicpu;
  4788. end.