aasmcpu.pas 202 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512
  1. {
  2. Copyright (c) 2003 by Florian Klaempfl
  3. Contains the assembler object for the ARM
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit aasmcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,globals,verbose,
  22. aasmbase,aasmtai,aasmdata,aasmsym,
  23. ogbase,
  24. symtype,
  25. cpubase,cpuinfo,cgbase,cgutils,
  26. sysutils;
  27. const
  28. { "mov reg,reg" source operand number }
  29. O_MOV_SOURCE = 1;
  30. { "mov reg,reg" source operand number }
  31. O_MOV_DEST = 0;
  32. { Operand types }
  33. OT_NONE = $00000000;
  34. OT_BITS8 = $00000001; { size, and other attributes, of the operand }
  35. OT_BITS16 = $00000002;
  36. OT_BITS32 = $00000004;
  37. OT_BITS64 = $00000008; { FPU only }
  38. OT_BITS80 = $00000010;
  39. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  40. OT_NEAR = $00000040;
  41. OT_SHORT = $00000080;
  42. OT_BITSTINY = $00000100; { fpu constant }
  43. OT_BITSSHIFTER =
  44. $00000200;
  45. OT_SIZE_MASK = $000003FF; { all the size attributes }
  46. OT_NON_SIZE = $0FFFF800;
  47. OT_OPT_SIZE = $F0000000;
  48. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  49. OT_TO = $00000200; { operand is followed by a colon }
  50. { reverse effect in FADD, FSUB &c }
  51. OT_COLON = $00000400;
  52. OT_SHIFTEROP = $00000800;
  53. OT_REGISTER = $00001000;
  54. OT_IMMEDIATE = $00002000;
  55. OT_REGLIST = $00008000;
  56. OT_IMM8 = $00002001;
  57. OT_IMM24 = $00002002;
  58. OT_IMM32 = $00002004;
  59. OT_IMM64 = $00002008;
  60. OT_IMM80 = $00002010;
  61. OT_IMMTINY = $00002100;
  62. OT_IMMSHIFTER= $00002200;
  63. OT_IMMEDIATEZERO = $10002200;
  64. OT_IMMEDIATE24 = OT_IMM24;
  65. OT_SHIFTIMM = OT_SHIFTEROP or OT_IMMSHIFTER;
  66. OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
  67. OT_IMMEDIATESHIFTER = OT_IMMSHIFTER;
  68. OT_IMMEDIATEFPU = OT_IMMTINY;
  69. OT_REGMEM = $00200000; { for r/m, ie EA, operands }
  70. OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
  71. OT_REG8 = $00201001;
  72. OT_REG16 = $00201002;
  73. OT_REG32 = $00201004;
  74. OT_REGLO = $10201004; { lower reg (r0-r7) }
  75. OT_REGSP = $20201004;
  76. OT_REG64 = $00201008;
  77. OT_VREG = $00201010; { vector register }
  78. OT_REGF = $00201020; { coproc register }
  79. OT_REGS = $00201040; { special register with mask }
  80. OT_MEMORY = $00204000; { register number in 'basereg' }
  81. OT_MEM8 = $00204001;
  82. OT_MEM16 = $00204002;
  83. OT_MEM32 = $00204004;
  84. OT_MEM64 = $00204008;
  85. OT_MEM80 = $00204010;
  86. { word/byte load/store }
  87. OT_AM2 = $00010000;
  88. { misc ld/st operations, thumb reg indexed }
  89. OT_AM3 = $00020000;
  90. { multiple ld/st operations or thumb imm indexed }
  91. OT_AM4 = $00040000;
  92. { co proc. ld/st operations or thumb sp+imm indexed }
  93. OT_AM5 = $00080000;
  94. { exclusive ld/st operations or thumb pc+imm indexed }
  95. OT_AM6 = $00100000;
  96. OT_AMMASK = $001f0000;
  97. { IT instruction }
  98. OT_CONDITION = $00200000;
  99. OT_MODEFLAGS = $00400000;
  100. OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
  101. OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
  102. OT_MEMORYAM4 = OT_MEMORY or OT_AM4;
  103. OT_MEMORYAM5 = OT_MEMORY or OT_AM5;
  104. OT_MEMORYAM6 = OT_MEMORY or OT_AM6;
  105. OT_FPUREG = $01000000; { floating point stack registers }
  106. OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
  107. { a mask for the following }
  108. OT_MEM_OFFS = $00604000; { special type of EA }
  109. { simple [address] offset }
  110. OT_ONENESS = $00800000; { special type of immediate operand }
  111. { so UNITY == IMMEDIATE | ONENESS }
  112. OT_UNITY = $00802000; { for shift/rotate instructions }
  113. instabentries = {$i armnop.inc}
  114. maxinfolen = 5;
  115. IF_NONE = $00000000;
  116. IF_ARMMASK = $000F0000;
  117. IF_ARM32 = $00010000;
  118. IF_THUMB = $00020000;
  119. IF_THUMB32 = $00040000;
  120. IF_WIDE = $00080000;
  121. IF_ARMvMASK = $0FF00000;
  122. IF_ARMv4 = $00100000;
  123. IF_ARMv4T = $00200000;
  124. IF_ARMv5 = $00300000;
  125. IF_ARMv5T = $00400000;
  126. IF_ARMv5TE = $00500000;
  127. IF_ARMv5TEJ = $00600000;
  128. IF_ARMv6 = $00700000;
  129. IF_ARMv6K = $00800000;
  130. IF_ARMv6T2 = $00900000;
  131. IF_ARMv6Z = $00A00000;
  132. IF_ARMv6M = $00B00000;
  133. IF_ARMv7 = $00C00000;
  134. IF_ARMv7A = $00D00000;
  135. IF_ARMv7R = $00E00000;
  136. IF_ARMv7M = $00F00000;
  137. IF_ARMv7EM = $01000000;
  138. IF_FPMASK = $F0000000;
  139. IF_FPA = $10000000;
  140. IF_VFPv2 = $20000000;
  141. IF_VFPv3 = $40000000;
  142. IF_VFPv4 = $80000000;
  143. { if the instruction can change in a second pass }
  144. IF_PASS2 = longint($80000000);
  145. type
  146. TInsTabCache=array[TasmOp] of longint;
  147. PInsTabCache=^TInsTabCache;
  148. tinsentry = record
  149. opcode : tasmop;
  150. ops : byte;
  151. optypes : array[0..5] of longint;
  152. code : array[0..maxinfolen] of char;
  153. flags : longword;
  154. end;
  155. pinsentry=^tinsentry;
  156. const
  157. InsTab : array[0..instabentries-1] of TInsEntry={$i armtab.inc}
  158. var
  159. InsTabCache : PInsTabCache;
  160. type
  161. taicpu = class(tai_cpu_abstract_sym)
  162. oppostfix : TOpPostfix;
  163. wideformat : boolean;
  164. roundingmode : troundingmode;
  165. procedure loadshifterop(opidx:longint;const so:tshifterop);
  166. procedure loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset; ausermode: boolean=false);
  167. procedure loadconditioncode(opidx:longint;const cond:tasmcond);
  168. procedure loadmodeflags(opidx:longint;const flags:tcpumodeflags);
  169. procedure loadspecialreg(opidx:longint;const areg:tregister; const aflags:tspecialregflags);
  170. constructor op_none(op : tasmop);
  171. constructor op_reg(op : tasmop;_op1 : tregister);
  172. constructor op_ref(op : tasmop;const _op1 : treference);
  173. constructor op_const(op : tasmop;_op1 : longint);
  174. constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  175. constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  176. constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  177. constructor op_regset(op:tasmop; regtype: tregistertype; subreg: tsubregister; _op1: tcpuregisterset);
  178. constructor op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
  179. constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  180. constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  181. constructor op_reg_const_const(op : tasmop;_op1 : tregister; _op2,_op3: aint);
  182. constructor op_reg_reg_const_const(op : tasmop;_op1,_op2 : tregister; _op3,_op4: aint);
  183. constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  184. constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  185. constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  186. constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
  187. { SFM/LFM }
  188. constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
  189. { ITxxx }
  190. constructor op_cond(op: tasmop; cond: tasmcond);
  191. { CPSxx }
  192. constructor op_modeflags(op: tasmop; flags: tcpumodeflags);
  193. constructor op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint);
  194. { MSR }
  195. constructor op_specialreg_reg(op: tasmop; specialreg: tregister; specialregflags: tspecialregflags; _op2: tregister);
  196. { *M*LL }
  197. constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  198. { this is for Jmp instructions }
  199. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  200. constructor op_sym(op : tasmop;_op1 : tasmsymbol);
  201. constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  202. constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  203. constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  204. function is_same_reg_move(regtype: Tregistertype):boolean; override;
  205. function spilling_get_operation_type(opnr: longint): topertype;override;
  206. function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
  207. { assembler }
  208. public
  209. { the next will reset all instructions that can change in pass 2 }
  210. procedure ResetPass1;override;
  211. procedure ResetPass2;override;
  212. function CheckIfValid:boolean;
  213. function GetString:string;
  214. function Pass1(objdata:TObjData):longint;override;
  215. procedure Pass2(objdata:TObjData);override;
  216. protected
  217. procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
  218. procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
  219. procedure ppubuildderefimploper(var o:toper);override;
  220. procedure ppuderefoper(var o:toper);override;
  221. private
  222. { pass1 info }
  223. inIT,
  224. lastinIT: boolean;
  225. { arm version info }
  226. fArmVMask,
  227. fArmMask : longint;
  228. { next fields are filled in pass1, so pass2 is faster }
  229. inssize : shortint;
  230. insoffset : longint;
  231. LastInsOffset : longint; { need to be public to be reset }
  232. insentry : PInsEntry;
  233. procedure BuildArmMasks;
  234. function InsEnd:longint;
  235. procedure create_ot(objdata:TObjData);
  236. function Matches(p:PInsEntry):longint;
  237. function calcsize(p:PInsEntry):shortint;
  238. procedure gencode(objdata:TObjData);
  239. function NeedAddrPrefix(opidx:byte):boolean;
  240. procedure Swapoperands;
  241. function FindInsentry(objdata:TObjData):boolean;
  242. end;
  243. tai_align = class(tai_align_abstract)
  244. { nothing to add }
  245. end;
  246. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  247. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  248. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  249. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  250. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  251. { inserts pc relative symbols at places where they are reachable
  252. and transforms special instructions to valid instruction encodings }
  253. procedure finalizearmcode(list,listtoinsert : TAsmList);
  254. { inserts .pdata section and dummy function prolog needed for arm-wince exception handling }
  255. procedure InsertPData;
  256. procedure InitAsm;
  257. procedure DoneAsm;
  258. implementation
  259. uses
  260. itcpugas,aoptcpu,
  261. systems;
  262. procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
  263. begin
  264. allocate_oper(opidx+1);
  265. with oper[opidx]^ do
  266. begin
  267. if typ<>top_shifterop then
  268. begin
  269. clearop(opidx);
  270. new(shifterop);
  271. end;
  272. shifterop^:=so;
  273. typ:=top_shifterop;
  274. if assigned(add_reg_instruction_hook) then
  275. add_reg_instruction_hook(self,shifterop^.rs);
  276. end;
  277. end;
  278. procedure taicpu.loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset; ausermode: boolean);
  279. var
  280. i : byte;
  281. begin
  282. allocate_oper(opidx+1);
  283. with oper[opidx]^ do
  284. begin
  285. if typ<>top_regset then
  286. begin
  287. clearop(opidx);
  288. new(regset);
  289. end;
  290. regset^:=s;
  291. regtyp:=regsetregtype;
  292. subreg:=regsetsubregtype;
  293. usermode:=ausermode;
  294. typ:=top_regset;
  295. case regsetregtype of
  296. R_INTREGISTER:
  297. for i:=RS_R0 to RS_R15 do
  298. begin
  299. if assigned(add_reg_instruction_hook) and (i in regset^) then
  300. add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,regsetsubregtype));
  301. end;
  302. R_MMREGISTER:
  303. { both RS_S0 and RS_D0 range from 0 to 31 }
  304. for i:=RS_D0 to RS_D31 do
  305. begin
  306. if assigned(add_reg_instruction_hook) and (i in regset^) then
  307. add_reg_instruction_hook(self,newreg(R_MMREGISTER,i,regsetsubregtype));
  308. end;
  309. end;
  310. end;
  311. end;
  312. procedure taicpu.loadconditioncode(opidx:longint;const cond:tasmcond);
  313. begin
  314. allocate_oper(opidx+1);
  315. with oper[opidx]^ do
  316. begin
  317. if typ<>top_conditioncode then
  318. clearop(opidx);
  319. cc:=cond;
  320. typ:=top_conditioncode;
  321. end;
  322. end;
  323. procedure taicpu.loadmodeflags(opidx: longint; const flags: tcpumodeflags);
  324. begin
  325. allocate_oper(opidx+1);
  326. with oper[opidx]^ do
  327. begin
  328. if typ<>top_modeflags then
  329. clearop(opidx);
  330. modeflags:=flags;
  331. typ:=top_modeflags;
  332. end;
  333. end;
  334. procedure taicpu.loadspecialreg(opidx: longint; const areg: tregister; const aflags: tspecialregflags);
  335. begin
  336. allocate_oper(opidx+1);
  337. with oper[opidx]^ do
  338. begin
  339. if typ<>top_specialreg then
  340. clearop(opidx);
  341. specialreg:=areg;
  342. specialflags:=aflags;
  343. typ:=top_specialreg;
  344. end;
  345. end;
  346. {*****************************************************************************
  347. taicpu Constructors
  348. *****************************************************************************}
  349. constructor taicpu.op_none(op : tasmop);
  350. begin
  351. inherited create(op);
  352. end;
  353. { for pld }
  354. constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
  355. begin
  356. inherited create(op);
  357. ops:=1;
  358. loadref(0,_op1);
  359. end;
  360. constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
  361. begin
  362. inherited create(op);
  363. ops:=1;
  364. loadreg(0,_op1);
  365. end;
  366. constructor taicpu.op_const(op : tasmop;_op1 : longint);
  367. begin
  368. inherited create(op);
  369. ops:=1;
  370. loadconst(0,aint(_op1));
  371. end;
  372. constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  373. begin
  374. inherited create(op);
  375. ops:=2;
  376. loadreg(0,_op1);
  377. loadreg(1,_op2);
  378. end;
  379. constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  380. begin
  381. inherited create(op);
  382. ops:=2;
  383. loadreg(0,_op1);
  384. loadconst(1,aint(_op2));
  385. end;
  386. constructor taicpu.op_regset(op: tasmop; regtype: tregistertype; subreg: tsubregister; _op1: tcpuregisterset);
  387. begin
  388. inherited create(op);
  389. ops:=1;
  390. loadregset(0,regtype,subreg,_op1);
  391. end;
  392. constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
  393. begin
  394. inherited create(op);
  395. ops:=2;
  396. loadref(0,_op1);
  397. loadregset(1,regtype,subreg,_op2);
  398. end;
  399. constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  400. begin
  401. inherited create(op);
  402. ops:=2;
  403. loadreg(0,_op1);
  404. loadref(1,_op2);
  405. end;
  406. constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  407. begin
  408. inherited create(op);
  409. ops:=3;
  410. loadreg(0,_op1);
  411. loadreg(1,_op2);
  412. loadreg(2,_op3);
  413. end;
  414. constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  415. begin
  416. inherited create(op);
  417. ops:=4;
  418. loadreg(0,_op1);
  419. loadreg(1,_op2);
  420. loadreg(2,_op3);
  421. loadreg(3,_op4);
  422. end;
  423. constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  424. begin
  425. inherited create(op);
  426. ops:=3;
  427. loadreg(0,_op1);
  428. loadreg(1,_op2);
  429. loadconst(2,aint(_op3));
  430. end;
  431. constructor taicpu.op_reg_const_const(op : tasmop;_op1 : tregister; _op2,_op3: aint);
  432. begin
  433. inherited create(op);
  434. ops:=3;
  435. loadreg(0,_op1);
  436. loadconst(1,aint(_op2));
  437. loadconst(2,aint(_op3));
  438. end;
  439. constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
  440. begin
  441. inherited create(op);
  442. ops:=4;
  443. loadreg(0,_op1);
  444. loadreg(1,_op2);
  445. loadconst(2,aint(_op3));
  446. loadconst(3,aint(_op4));
  447. end;
  448. constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
  449. begin
  450. inherited create(op);
  451. ops:=3;
  452. loadreg(0,_op1);
  453. loadconst(1,_op2);
  454. loadref(2,_op3);
  455. end;
  456. constructor taicpu.op_cond(op: tasmop; cond: tasmcond);
  457. begin
  458. inherited create(op);
  459. ops:=1;
  460. loadconditioncode(0, cond);
  461. end;
  462. constructor taicpu.op_modeflags(op: tasmop; flags: tcpumodeflags);
  463. begin
  464. inherited create(op);
  465. ops := 1;
  466. loadmodeflags(0,flags);
  467. end;
  468. constructor taicpu.op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint);
  469. begin
  470. inherited create(op);
  471. ops := 2;
  472. loadmodeflags(0,flags);
  473. loadconst(1,a);
  474. end;
  475. constructor taicpu.op_specialreg_reg(op: tasmop; specialreg: tregister; specialregflags: tspecialregflags; _op2: tregister);
  476. begin
  477. inherited create(op);
  478. ops:=2;
  479. loadspecialreg(0,specialreg,specialregflags);
  480. loadreg(1,_op2);
  481. end;
  482. constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  483. begin
  484. inherited create(op);
  485. ops:=3;
  486. loadreg(0,_op1);
  487. loadreg(1,_op2);
  488. loadsymbol(0,_op3,_op3ofs);
  489. end;
  490. constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  491. begin
  492. inherited create(op);
  493. ops:=3;
  494. loadreg(0,_op1);
  495. loadreg(1,_op2);
  496. loadref(2,_op3);
  497. end;
  498. constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  499. begin
  500. inherited create(op);
  501. ops:=3;
  502. loadreg(0,_op1);
  503. loadreg(1,_op2);
  504. loadshifterop(2,_op3);
  505. end;
  506. constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
  507. begin
  508. inherited create(op);
  509. ops:=4;
  510. loadreg(0,_op1);
  511. loadreg(1,_op2);
  512. loadreg(2,_op3);
  513. loadshifterop(3,_op4);
  514. end;
  515. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  516. begin
  517. inherited create(op);
  518. condition:=cond;
  519. ops:=1;
  520. loadsymbol(0,_op1,0);
  521. end;
  522. constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
  523. begin
  524. inherited create(op);
  525. ops:=1;
  526. loadsymbol(0,_op1,0);
  527. end;
  528. constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  529. begin
  530. inherited create(op);
  531. ops:=1;
  532. loadsymbol(0,_op1,_op1ofs);
  533. end;
  534. constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  535. begin
  536. inherited create(op);
  537. ops:=2;
  538. loadreg(0,_op1);
  539. loadsymbol(1,_op2,_op2ofs);
  540. end;
  541. constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  542. begin
  543. inherited create(op);
  544. ops:=2;
  545. loadsymbol(0,_op1,_op1ofs);
  546. loadref(1,_op2);
  547. end;
  548. function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
  549. begin
  550. { allow the register allocator to remove unnecessary moves }
  551. result:=(
  552. ((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
  553. ((opcode=A_MVF) and (regtype = R_FPUREGISTER)) or
  554. ((opcode in [A_FCPYS, A_FCPYD]) and (regtype = R_MMREGISTER)) or
  555. ((opcode in [A_VMOV]) and (regtype = R_MMREGISTER) and (oppostfix in [PF_F32,PF_F64]))
  556. ) and
  557. ((oppostfix in [PF_None,PF_D]) or (opcode = A_VMOV)) and
  558. (condition=C_None) and
  559. (ops=2) and
  560. (oper[0]^.typ=top_reg) and
  561. (oper[1]^.typ=top_reg) and
  562. (oper[0]^.reg=oper[1]^.reg);
  563. end;
  564. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  565. begin
  566. case getregtype(r) of
  567. R_INTREGISTER :
  568. result:=taicpu.op_reg_ref(A_LDR,r,ref);
  569. R_FPUREGISTER :
  570. { use lfm because we don't know the current internal format
  571. and avoid exceptions
  572. }
  573. result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref);
  574. R_MMREGISTER :
  575. result:=taicpu.op_reg_ref(A_VLDR,r,ref);
  576. else
  577. internalerror(200401041);
  578. end;
  579. end;
  580. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  581. begin
  582. case getregtype(r) of
  583. R_INTREGISTER :
  584. result:=taicpu.op_reg_ref(A_STR,r,ref);
  585. R_FPUREGISTER :
  586. { use sfm because we don't know the current internal format
  587. and avoid exceptions
  588. }
  589. result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref);
  590. R_MMREGISTER :
  591. result:=taicpu.op_reg_ref(A_VSTR,r,ref);
  592. else
  593. internalerror(200401041);
  594. end;
  595. end;
  596. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  597. begin
  598. case opcode of
  599. A_ADC,A_ADD,A_AND,A_BIC,
  600. A_EOR,A_CLZ,A_RBIT,
  601. A_LDR,A_LDRB,A_LDRBT,A_LDRH,A_LDRSB,
  602. A_LDRSH,A_LDRT,
  603. A_MOV,A_MVN,A_MLA,A_MUL,
  604. A_ORR,A_RSB,A_RSC,A_SBC,A_SUB,
  605. A_SWP,A_SWPB,
  606. A_LDF,A_FLT,A_FIX,
  607. A_ADF,A_DVF,A_FDV,A_FML,
  608. A_RFS,A_RFC,A_RDF,
  609. A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS,
  610. A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN,
  611. A_LFM,
  612. A_FLDS,A_FLDD,
  613. A_FMRX,A_FMXR,A_FMSTAT,
  614. A_FMSR,A_FMRS,A_FMDRR,
  615. A_FCPYS,A_FCPYD,A_FCVTSD,A_FCVTDS,
  616. A_FABSS,A_FABSD,A_FSQRTS,A_FSQRTD,A_FMULS,A_FMULD,
  617. A_FADDS,A_FADDD,A_FSUBS,A_FSUBD,A_FDIVS,A_FDIVD,
  618. A_FMACS,A_FMACD,A_FMSCS,A_FMSCD,A_FNMACS,A_FNMACD,
  619. A_FNMSCS,A_FNMSCD,A_FNMULS,A_FNMULD,
  620. A_FMDHR,A_FMRDH,A_FMDLR,A_FMRDL,
  621. A_FNEGS,A_FNEGD,
  622. A_FSITOS,A_FSITOD,A_FTOSIS,A_FTOSID,
  623. A_FTOUIS,A_FTOUID,A_FUITOS,A_FUITOD,
  624. A_SXTB16,A_UXTB16,
  625. A_UXTB,A_UXTH,A_SXTB,A_SXTH,
  626. A_NEG,
  627. A_VABS,A_VADD,A_VCVT,A_VDIV,A_VLDR,A_VMOV,A_VMUL,A_VNEG,A_VSQRT,A_VSUB,
  628. A_MRS,A_MSR:
  629. if opnr=0 then
  630. result:=operand_write
  631. else
  632. result:=operand_read;
  633. A_BKPT,A_B,A_BL,A_BLX,A_BX,
  634. A_CMN,A_CMP,A_TEQ,A_TST,
  635. A_CMF,A_CMFE,A_WFS,A_CNF,
  636. A_FCMPS,A_FCMPD,A_FCMPES,A_FCMPED,A_FCMPEZS,A_FCMPEZD,
  637. A_FCMPZS,A_FCMPZD,
  638. A_VCMP,A_VCMPE:
  639. result:=operand_read;
  640. A_SMLAL,A_UMLAL:
  641. if opnr in [0,1] then
  642. result:=operand_readwrite
  643. else
  644. result:=operand_read;
  645. A_SMULL,A_UMULL,
  646. A_FMRRD:
  647. if opnr in [0,1] then
  648. result:=operand_write
  649. else
  650. result:=operand_read;
  651. A_STR,A_STRB,A_STRBT,
  652. A_STRH,A_STRT,A_STF,A_SFM,
  653. A_FSTS,A_FSTD,
  654. A_VSTR:
  655. { important is what happens with the involved registers }
  656. if opnr=0 then
  657. result := operand_read
  658. else
  659. { check for pre/post indexed }
  660. result := operand_read;
  661. //Thumb2
  662. A_LSL, A_LSR, A_ROR, A_ASR, A_SDIV, A_UDIV, A_MOVW, A_MOVT, A_MLS, A_BFI,
  663. A_SMMLA,A_SMMLS:
  664. if opnr in [0] then
  665. result:=operand_write
  666. else
  667. result:=operand_read;
  668. A_BFC:
  669. if opnr in [0] then
  670. result:=operand_readwrite
  671. else
  672. result:=operand_read;
  673. A_LDREX:
  674. if opnr in [0] then
  675. result:=operand_write
  676. else
  677. result:=operand_read;
  678. A_STREX:
  679. result:=operand_write;
  680. else
  681. internalerror(200403151);
  682. end;
  683. end;
  684. function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
  685. begin
  686. result := operand_read;
  687. if (oper[opnr]^.ref^.base = reg) and
  688. (oper[opnr]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
  689. result := operand_readwrite;
  690. end;
  691. procedure BuildInsTabCache;
  692. var
  693. i : longint;
  694. begin
  695. new(instabcache);
  696. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  697. i:=0;
  698. while (i<InsTabEntries) do
  699. begin
  700. if InsTabCache^[InsTab[i].Opcode]=-1 then
  701. InsTabCache^[InsTab[i].Opcode]:=i;
  702. inc(i);
  703. end;
  704. end;
  705. procedure InitAsm;
  706. begin
  707. if not assigned(instabcache) then
  708. BuildInsTabCache;
  709. end;
  710. procedure DoneAsm;
  711. begin
  712. if assigned(instabcache) then
  713. begin
  714. dispose(instabcache);
  715. instabcache:=nil;
  716. end;
  717. end;
  718. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  719. begin
  720. i.oppostfix:=pf;
  721. result:=i;
  722. end;
  723. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  724. begin
  725. i.roundingmode:=rm;
  726. result:=i;
  727. end;
  728. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  729. begin
  730. i.condition:=c;
  731. result:=i;
  732. end;
  733. Function SimpleGetNextInstruction(Current: tai; Var Next: tai): Boolean;
  734. Begin
  735. Current:=tai(Current.Next);
  736. While Assigned(Current) And (Current.typ In SkipInstr) Do
  737. Current:=tai(Current.Next);
  738. Next:=Current;
  739. If Assigned(Next) And Not(Next.typ In SkipInstr) Then
  740. Result:=True
  741. Else
  742. Begin
  743. Next:=Nil;
  744. Result:=False;
  745. End;
  746. End;
  747. (*
  748. function armconstequal(hp1,hp2: tai): boolean;
  749. begin
  750. result:=false;
  751. if hp1.typ<>hp2.typ then
  752. exit;
  753. case hp1.typ of
  754. tai_const:
  755. result:=
  756. (tai_const(hp2).sym=tai_const(hp).sym) and
  757. (tai_const(hp2).value=tai_const(hp).value) and
  758. (tai(hp2.previous).typ=ait_label);
  759. tai_const:
  760. result:=
  761. (tai_const(hp2).sym=tai_const(hp).sym) and
  762. (tai_const(hp2).value=tai_const(hp).value) and
  763. (tai(hp2.previous).typ=ait_label);
  764. end;
  765. end;
  766. *)
  767. procedure insertpcrelativedata(list,listtoinsert : TAsmList);
  768. var
  769. limit: longint;
  770. { FLD/FST VFP instructions have a limit of +/- 1024, not 4096, this
  771. function checks the next count instructions if the limit must be
  772. decreased }
  773. procedure CheckLimit(hp : tai;count : integer);
  774. var
  775. i : Integer;
  776. begin
  777. for i:=1 to count do
  778. if SimpleGetNextInstruction(hp,hp) and
  779. (tai(hp).typ=ait_instruction) and
  780. ((taicpu(hp).opcode=A_FLDS) or
  781. (taicpu(hp).opcode=A_FLDD) or
  782. (taicpu(hp).opcode=A_VLDR) or
  783. (taicpu(hp).opcode=A_LDF) or
  784. (taicpu(hp).opcode=A_STF)) then
  785. limit:=254;
  786. end;
  787. function is_case_dispatch(hp: taicpu): boolean;
  788. begin
  789. result:=
  790. ((taicpu(hp).opcode in [A_ADD,A_LDR]) and
  791. not(GenerateThumbCode or GenerateThumb2Code) and
  792. (taicpu(hp).oper[0]^.typ=top_reg) and
  793. (taicpu(hp).oper[0]^.reg=NR_PC)) or
  794. ((taicpu(hp).opcode=A_MOV) and (GenerateThumbCode) and
  795. (taicpu(hp).oper[0]^.typ=top_reg) and
  796. (taicpu(hp).oper[0]^.reg=NR_PC)) or
  797. (taicpu(hp).opcode=A_TBH) or
  798. (taicpu(hp).opcode=A_TBB);
  799. end;
  800. var
  801. curinspos,
  802. penalty,
  803. lastinspos,
  804. { increased for every data element > 4 bytes inserted }
  805. extradataoffset,
  806. curop : longint;
  807. curtai,
  808. inserttai : tai;
  809. curdatatai,hp,hp2 : tai;
  810. curdata : TAsmList;
  811. l : tasmlabel;
  812. doinsert,
  813. removeref : boolean;
  814. multiplier : byte;
  815. begin
  816. curdata:=TAsmList.create;
  817. lastinspos:=-1;
  818. curinspos:=0;
  819. extradataoffset:=0;
  820. if GenerateThumbCode then
  821. begin
  822. multiplier:=2;
  823. limit:=504;
  824. end
  825. else
  826. begin
  827. limit:=1016;
  828. multiplier:=1;
  829. end;
  830. curtai:=tai(list.first);
  831. doinsert:=false;
  832. while assigned(curtai) do
  833. begin
  834. { instruction? }
  835. case curtai.typ of
  836. ait_instruction:
  837. begin
  838. { walk through all operand of the instruction }
  839. for curop:=0 to taicpu(curtai).ops-1 do
  840. begin
  841. { reference? }
  842. if (taicpu(curtai).oper[curop]^.typ=top_ref) then
  843. begin
  844. { pc relative symbol? }
  845. curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
  846. if assigned(curdatatai) then
  847. begin
  848. { create a new copy of a data entry on arm thumb if the entry has been inserted already
  849. before because arm thumb does not allow pc relative negative offsets }
  850. if (GenerateThumbCode) and
  851. tai_label(curdatatai).inserted then
  852. begin
  853. current_asmdata.getjumplabel(l);
  854. hp:=tai_label.create(l);
  855. listtoinsert.Concat(hp);
  856. hp2:=tai(curdatatai.Next.GetCopy);
  857. hp2.Next:=nil;
  858. hp2.Previous:=nil;
  859. listtoinsert.Concat(hp2);
  860. taicpu(curtai).oper[curop]^.ref^.symboldata:=hp;
  861. taicpu(curtai).oper[curop]^.ref^.symbol:=l;
  862. curdatatai:=hp;
  863. end;
  864. { move only if we're at the first reference of a label }
  865. if not(tai_label(curdatatai).moved) then
  866. begin
  867. tai_label(curdatatai).moved:=true;
  868. { check if symbol already used. }
  869. { if yes, reuse the symbol }
  870. hp:=tai(curdatatai.next);
  871. removeref:=false;
  872. if assigned(hp) then
  873. begin
  874. case hp.typ of
  875. ait_const:
  876. begin
  877. if (tai_const(hp).consttype=aitconst_64bit) then
  878. inc(extradataoffset,multiplier);
  879. end;
  880. ait_realconst:
  881. begin
  882. inc(extradataoffset,multiplier*(((tai_realconst(hp).savesize-4)+3) div 4));
  883. end;
  884. end;
  885. { check if the same constant has been already inserted into the currently handled list,
  886. if yes, reuse it }
  887. if (hp.typ=ait_const) then
  888. begin
  889. hp2:=tai(curdata.first);
  890. while assigned(hp2) do
  891. begin
  892. if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
  893. and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label)
  894. then
  895. begin
  896. with taicpu(curtai).oper[curop]^.ref^ do
  897. begin
  898. symboldata:=hp2.previous;
  899. symbol:=tai_label(hp2.previous).labsym;
  900. end;
  901. removeref:=true;
  902. break;
  903. end;
  904. hp2:=tai(hp2.next);
  905. end;
  906. end;
  907. end;
  908. { move or remove symbol reference }
  909. repeat
  910. hp:=tai(curdatatai.next);
  911. listtoinsert.remove(curdatatai);
  912. if removeref then
  913. curdatatai.free
  914. else
  915. curdata.concat(curdatatai);
  916. curdatatai:=hp;
  917. until (curdatatai=nil) or (curdatatai.typ=ait_label);
  918. if lastinspos=-1 then
  919. lastinspos:=curinspos;
  920. end;
  921. end;
  922. end;
  923. end;
  924. inc(curinspos,multiplier);
  925. end;
  926. ait_align:
  927. begin
  928. { code is always 4 byte aligned, so we don't have to take care of .align 2 which would
  929. requires also incrementing curinspos by 1 }
  930. inc(curinspos,(tai_align(curtai).aligntype div 4)*multiplier);
  931. end;
  932. ait_const:
  933. begin
  934. inc(curinspos,multiplier);
  935. if (tai_const(curtai).consttype=aitconst_64bit) then
  936. inc(curinspos,multiplier);
  937. end;
  938. ait_realconst:
  939. begin
  940. inc(curinspos,multiplier*((tai_realconst(hp).savesize+3) div 4));
  941. end;
  942. end;
  943. { special case for case jump tables }
  944. penalty:=0;
  945. if SimpleGetNextInstruction(curtai,hp) and
  946. (tai(hp).typ=ait_instruction) then
  947. begin
  948. case taicpu(hp).opcode of
  949. A_MOV,
  950. A_LDR,
  951. A_ADD,
  952. A_TBH,
  953. A_TBB:
  954. { approximation if we hit a case jump table }
  955. if is_case_dispatch(taicpu(hp)) then
  956. begin
  957. penalty:=multiplier;
  958. hp:=tai(hp.next);
  959. { skip register allocations and comments inserted by the optimizer as well as a label
  960. as jump tables for thumb might have }
  961. while assigned(hp) and (hp.typ in [ait_comment,ait_regalloc,ait_label]) do
  962. hp:=tai(hp.next);
  963. while assigned(hp) and (hp.typ=ait_const) do
  964. begin
  965. inc(penalty,multiplier);
  966. hp:=tai(hp.next);
  967. end;
  968. end;
  969. A_IT:
  970. begin
  971. if GenerateThumb2Code then
  972. penalty:=multiplier;
  973. { check if the next instruction fits as well
  974. or if we splitted after the it so split before }
  975. CheckLimit(hp,1);
  976. end;
  977. A_ITE,
  978. A_ITT:
  979. begin
  980. if GenerateThumb2Code then
  981. penalty:=2*multiplier;
  982. { check if the next two instructions fit as well
  983. or if we splitted them so split before }
  984. CheckLimit(hp,2);
  985. end;
  986. A_ITEE,
  987. A_ITTE,
  988. A_ITET,
  989. A_ITTT:
  990. begin
  991. if GenerateThumb2Code then
  992. penalty:=3*multiplier;
  993. { check if the next three instructions fit as well
  994. or if we splitted them so split before }
  995. CheckLimit(hp,3);
  996. end;
  997. A_ITEEE,
  998. A_ITTEE,
  999. A_ITETE,
  1000. A_ITTTE,
  1001. A_ITEET,
  1002. A_ITTET,
  1003. A_ITETT,
  1004. A_ITTTT:
  1005. begin
  1006. if GenerateThumb2Code then
  1007. penalty:=4*multiplier;
  1008. { check if the next three instructions fit as well
  1009. or if we splitted them so split before }
  1010. CheckLimit(hp,4);
  1011. end;
  1012. end;
  1013. end;
  1014. CheckLimit(curtai,1);
  1015. { don't miss an insert }
  1016. doinsert:=doinsert or
  1017. (not(curdata.empty) and
  1018. (curinspos-lastinspos+penalty+extradataoffset>limit));
  1019. { split only at real instructions else the test below fails }
  1020. if doinsert and (curtai.typ=ait_instruction) and
  1021. (
  1022. { don't split loads of pc to lr and the following move }
  1023. not(
  1024. (taicpu(curtai).opcode=A_MOV) and
  1025. (taicpu(curtai).oper[0]^.typ=top_reg) and
  1026. (taicpu(curtai).oper[0]^.reg=NR_R14) and
  1027. (taicpu(curtai).oper[1]^.typ=top_reg) and
  1028. (taicpu(curtai).oper[1]^.reg=NR_PC)
  1029. )
  1030. ) and
  1031. (
  1032. { do not insert data after a B instruction due to their limited range }
  1033. not((GenerateThumbCode) and
  1034. (taicpu(curtai).opcode=A_B)
  1035. )
  1036. ) then
  1037. begin
  1038. lastinspos:=-1;
  1039. extradataoffset:=0;
  1040. if GenerateThumbCode then
  1041. limit:=502
  1042. else
  1043. limit:=1016;
  1044. { if this is an add/tbh/tbb-based jumptable, go back to the
  1045. previous instruction, because inserting data between the
  1046. dispatch instruction and the table would mess up the
  1047. addresses }
  1048. inserttai:=curtai;
  1049. if is_case_dispatch(taicpu(inserttai)) and
  1050. ((taicpu(inserttai).opcode=A_ADD) or
  1051. (taicpu(inserttai).opcode=A_TBH) or
  1052. (taicpu(inserttai).opcode=A_TBB)) then
  1053. begin
  1054. repeat
  1055. inserttai:=tai(inserttai.previous);
  1056. until inserttai.typ=ait_instruction;
  1057. { if it's an add-based jump table, then also skip the
  1058. pc-relative load }
  1059. if taicpu(curtai).opcode=A_ADD then
  1060. repeat
  1061. inserttai:=tai(inserttai.previous);
  1062. until inserttai.typ=ait_instruction;
  1063. end
  1064. else
  1065. { on arm thumb, insert the data always after all labels etc. following an instruction so it
  1066. is prevent that a bxx yyy; bl xxx; yyyy: sequence gets separated ( we never insert on arm thumb after
  1067. bxx) and the distance of bxx gets too long }
  1068. if GenerateThumbCode then
  1069. while assigned(tai(inserttai.Next)) and (tai(inserttai.Next).typ in SkipInstr+[ait_label]) do
  1070. inserttai:=tai(inserttai.next);
  1071. doinsert:=false;
  1072. current_asmdata.getjumplabel(l);
  1073. { align jump in thumb .text section to 4 bytes }
  1074. if not(curdata.empty) and (GenerateThumbCode) then
  1075. curdata.Insert(tai_align.Create(4));
  1076. curdata.insert(taicpu.op_sym(A_B,l));
  1077. curdata.concat(tai_label.create(l));
  1078. { mark all labels as inserted, arm thumb
  1079. needs this, so data referencing an already inserted label can be
  1080. duplicated because arm thumb does not allow negative pc relative offset }
  1081. hp2:=tai(curdata.first);
  1082. while assigned(hp2) do
  1083. begin
  1084. if hp2.typ=ait_label then
  1085. tai_label(hp2).inserted:=true;
  1086. hp2:=tai(hp2.next);
  1087. end;
  1088. { continue with the last inserted label because we use later
  1089. on SimpleGetNextInstruction, so if we used curtai.next (which
  1090. is then equal curdata.last.previous) we could over see one
  1091. instruction }
  1092. hp:=tai(curdata.Last);
  1093. list.insertlistafter(inserttai,curdata);
  1094. curtai:=hp;
  1095. end
  1096. else
  1097. curtai:=tai(curtai.next);
  1098. end;
  1099. { align jump in thumb .text section to 4 bytes }
  1100. if not(curdata.empty) and (GenerateThumbCode or GenerateThumb2Code) then
  1101. curdata.Insert(tai_align.Create(4));
  1102. list.concatlist(curdata);
  1103. curdata.free;
  1104. end;
  1105. procedure ensurethumb2encodings(list: TAsmList);
  1106. var
  1107. curtai: tai;
  1108. op2reg: TRegister;
  1109. begin
  1110. { Do Thumb-2 16bit -> 32bit transformations }
  1111. curtai:=tai(list.first);
  1112. while assigned(curtai) do
  1113. begin
  1114. case curtai.typ of
  1115. ait_instruction:
  1116. begin
  1117. case taicpu(curtai).opcode of
  1118. A_ADD:
  1119. begin
  1120. { Set wide flag for ADD Rd,Rn,Rm where registers are over R7(high register set) }
  1121. if taicpu(curtai).ops = 3 then
  1122. begin
  1123. if taicpu(curtai).oper[2]^.typ in [top_reg,top_shifterop] then
  1124. begin
  1125. if taicpu(curtai).oper[2]^.typ = top_reg then
  1126. op2reg := taicpu(curtai).oper[2]^.reg
  1127. else if taicpu(curtai).oper[2]^.shifterop^.rs <> NR_NO then
  1128. op2reg := taicpu(curtai).oper[2]^.shifterop^.rs
  1129. else
  1130. op2reg := NR_NO;
  1131. if op2reg <> NR_NO then
  1132. begin
  1133. if (taicpu(curtai).oper[0]^.reg >= NR_R8) or
  1134. (taicpu(curtai).oper[1]^.reg >= NR_R8) or
  1135. (op2reg >= NR_R8) then
  1136. begin
  1137. taicpu(curtai).wideformat:=true;
  1138. { Handle special cases where register rules are violated by optimizer/user }
  1139. { if d == 13 || (d == 15 && S == ‘0’) || n == 15 || m IN [13,15] then UNPREDICTABLE; }
  1140. { Transform ADD.W Rx, Ry, R13 into ADD.W Rx, R13, Ry }
  1141. if (op2reg = NR_R13) and (taicpu(curtai).oper[2]^.typ = top_reg) then
  1142. begin
  1143. taicpu(curtai).oper[2]^.reg := taicpu(curtai).oper[1]^.reg;
  1144. taicpu(curtai).oper[1]^.reg := op2reg;
  1145. end;
  1146. end;
  1147. end;
  1148. end;
  1149. end;
  1150. end;
  1151. end;
  1152. end;
  1153. end;
  1154. curtai:=tai(curtai.Next);
  1155. end;
  1156. end;
  1157. procedure ensurethumbencodings(list: TAsmList);
  1158. var
  1159. curtai: tai;
  1160. begin
  1161. { Do Thumb 16bit transformations to form valid instruction forms }
  1162. curtai:=tai(list.first);
  1163. while assigned(curtai) do
  1164. begin
  1165. case curtai.typ of
  1166. ait_instruction:
  1167. begin
  1168. case taicpu(curtai).opcode of
  1169. A_ADD,
  1170. A_AND,A_EOR,A_ORR,A_BIC,
  1171. A_LSL,A_LSR,A_ASR,A_ROR,
  1172. A_ADC,A_SBC:
  1173. begin
  1174. if (taicpu(curtai).ops = 3) and
  1175. (taicpu(curtai).oper[2]^.typ=top_reg) and
  1176. (taicpu(curtai).oper[0]^.reg=taicpu(curtai).oper[1]^.reg) and
  1177. (taicpu(curtai).oper[0]^.reg<>NR_STACK_POINTER_REG) then
  1178. begin
  1179. taicpu(curtai).oper[1]^.reg:=taicpu(curtai).oper[2]^.reg;
  1180. taicpu(curtai).ops:=2;
  1181. end;
  1182. end;
  1183. end;
  1184. end;
  1185. end;
  1186. curtai:=tai(curtai.Next);
  1187. end;
  1188. end;
  1189. function getMergedInstruction(FirstOp,LastOp:TAsmOp;InvertLast:boolean) : TAsmOp;
  1190. const
  1191. opTable: array[A_IT..A_ITTTT] of string =
  1192. ('T','TE','TT','TEE','TTE','TET','TTT',
  1193. 'TEEE','TTEE','TETE','TTTE',
  1194. 'TEET','TTET','TETT','TTTT');
  1195. invertedOpTable: array[A_IT..A_ITTTT] of string =
  1196. ('E','ET','EE','ETT','EET','ETE','EEE',
  1197. 'ETTT','EETT','ETET','EEET',
  1198. 'ETTE','EETE','ETEE','EEEE');
  1199. var
  1200. resStr : string;
  1201. i : TAsmOp;
  1202. begin
  1203. if InvertLast then
  1204. resStr := opTable[FirstOp]+invertedOpTable[LastOp]
  1205. else
  1206. resStr := opTable[FirstOp]+opTable[LastOp];
  1207. if length(resStr) > 4 then
  1208. internalerror(2012100805);
  1209. for i := low(opTable) to high(opTable) do
  1210. if opTable[i] = resStr then
  1211. exit(i);
  1212. internalerror(2012100806);
  1213. end;
  1214. procedure foldITInstructions(list: TAsmList);
  1215. var
  1216. curtai,hp1 : tai;
  1217. levels,i : LongInt;
  1218. begin
  1219. curtai:=tai(list.First);
  1220. while assigned(curtai) do
  1221. begin
  1222. case curtai.typ of
  1223. ait_instruction:
  1224. if IsIT(taicpu(curtai).opcode) then
  1225. begin
  1226. levels := GetITLevels(taicpu(curtai).opcode);
  1227. if levels < 4 then
  1228. begin
  1229. i:=levels;
  1230. hp1:=tai(curtai.Next);
  1231. while assigned(hp1) and
  1232. (i > 0) do
  1233. begin
  1234. if hp1.typ=ait_instruction then
  1235. begin
  1236. dec(i);
  1237. if (i = 0) and
  1238. mustbelast(hp1) then
  1239. begin
  1240. hp1:=nil;
  1241. break;
  1242. end;
  1243. end;
  1244. hp1:=tai(hp1.Next);
  1245. end;
  1246. if assigned(hp1) then
  1247. begin
  1248. // We are pointing at the first instruction after the IT block
  1249. while assigned(hp1) and
  1250. (hp1.typ<>ait_instruction) do
  1251. hp1:=tai(hp1.Next);
  1252. if assigned(hp1) and
  1253. (hp1.typ=ait_instruction) and
  1254. IsIT(taicpu(hp1).opcode) then
  1255. begin
  1256. if (levels+GetITLevels(taicpu(hp1).opcode) <= 4) and
  1257. ((taicpu(curtai).oper[0]^.cc=taicpu(hp1).oper[0]^.cc) or
  1258. (taicpu(curtai).oper[0]^.cc=inverse_cond(taicpu(hp1).oper[0]^.cc))) then
  1259. begin
  1260. taicpu(curtai).opcode:=getMergedInstruction(taicpu(curtai).opcode,
  1261. taicpu(hp1).opcode,
  1262. taicpu(curtai).oper[0]^.cc=inverse_cond(taicpu(hp1).oper[0]^.cc));
  1263. list.Remove(hp1);
  1264. hp1.Free;
  1265. end;
  1266. end;
  1267. end;
  1268. end;
  1269. end;
  1270. end;
  1271. curtai:=tai(curtai.Next);
  1272. end;
  1273. end;
  1274. procedure fix_invalid_imms(list: TAsmList);
  1275. var
  1276. curtai: tai;
  1277. sh: byte;
  1278. begin
  1279. curtai:=tai(list.First);
  1280. while assigned(curtai) do
  1281. begin
  1282. case curtai.typ of
  1283. ait_instruction:
  1284. begin
  1285. if (taicpu(curtai).opcode in [A_AND,A_BIC]) and
  1286. (taicpu(curtai).ops=3) and
  1287. (taicpu(curtai).oper[2]^.typ=top_const) and
  1288. (not is_shifter_const(taicpu(curtai).oper[2]^.val,sh)) and
  1289. is_shifter_const((not taicpu(curtai).oper[2]^.val) and $FFFFFFFF,sh) then
  1290. begin
  1291. case taicpu(curtai).opcode of
  1292. A_AND: taicpu(curtai).opcode:=A_BIC;
  1293. A_BIC: taicpu(curtai).opcode:=A_AND;
  1294. end;
  1295. taicpu(curtai).oper[2]^.val:=(not taicpu(curtai).oper[2]^.val) and $FFFFFFFF;
  1296. end
  1297. else if (taicpu(curtai).opcode in [A_SUB,A_ADD]) and
  1298. (taicpu(curtai).ops=3) and
  1299. (taicpu(curtai).oper[2]^.typ=top_const) and
  1300. (not is_shifter_const(taicpu(curtai).oper[2]^.val,sh)) and
  1301. is_shifter_const(-taicpu(curtai).oper[2]^.val,sh) then
  1302. begin
  1303. case taicpu(curtai).opcode of
  1304. A_ADD: taicpu(curtai).opcode:=A_SUB;
  1305. A_SUB: taicpu(curtai).opcode:=A_ADD;
  1306. end;
  1307. taicpu(curtai).oper[2]^.val:=-taicpu(curtai).oper[2]^.val;
  1308. end;
  1309. end;
  1310. end;
  1311. curtai:=tai(curtai.Next);
  1312. end;
  1313. end;
  1314. procedure gather_it_info(list: TAsmList);
  1315. var
  1316. curtai: tai;
  1317. in_it: boolean;
  1318. it_count: longint;
  1319. begin
  1320. in_it:=false;
  1321. it_count:=0;
  1322. curtai:=tai(list.First);
  1323. while assigned(curtai) do
  1324. begin
  1325. case curtai.typ of
  1326. ait_instruction:
  1327. begin
  1328. case taicpu(curtai).opcode of
  1329. A_IT..A_ITTTT:
  1330. begin
  1331. if in_it then
  1332. Message1(asmw_e_invalid_opcode_and_operands, 'ITxx instruction is inside another ITxx instruction')
  1333. else
  1334. begin
  1335. in_it:=true;
  1336. it_count:=GetITLevels(taicpu(curtai).opcode);
  1337. end;
  1338. end;
  1339. else
  1340. begin
  1341. taicpu(curtai).inIT:=in_it;
  1342. taicpu(curtai).lastinIT:=in_it and (it_count=1);
  1343. if in_it then
  1344. begin
  1345. dec(it_count);
  1346. if it_count <= 0 then
  1347. in_it:=false;
  1348. end;
  1349. end;
  1350. end;
  1351. end;
  1352. end;
  1353. curtai:=tai(curtai.Next);
  1354. end;
  1355. end;
  1356. { Expands pseudo instructions ( mov r1,r2,lsl #4 -> lsl r1,r2,#4) }
  1357. procedure expand_instructions(list: TAsmList);
  1358. var
  1359. curtai: tai;
  1360. begin
  1361. curtai:=tai(list.First);
  1362. while assigned(curtai) do
  1363. begin
  1364. case curtai.typ of
  1365. ait_instruction:
  1366. begin
  1367. case taicpu(curtai).opcode of
  1368. A_MOV:
  1369. begin
  1370. if (taicpu(curtai).ops=3) and
  1371. (taicpu(curtai).oper[2]^.typ=top_shifterop) then
  1372. begin
  1373. case taicpu(curtai).oper[2]^.shifterop^.shiftmode of
  1374. SM_LSL: taicpu(curtai).opcode:=A_LSL;
  1375. SM_LSR: taicpu(curtai).opcode:=A_LSR;
  1376. SM_ASR: taicpu(curtai).opcode:=A_ASR;
  1377. SM_ROR: taicpu(curtai).opcode:=A_ROR;
  1378. SM_RRX: taicpu(curtai).opcode:=A_RRX;
  1379. end;
  1380. if taicpu(curtai).oper[2]^.shifterop^.shiftmode=SM_RRX then
  1381. taicpu(curtai).ops:=2;
  1382. if taicpu(curtai).oper[2]^.shifterop^.rs=NR_NO then
  1383. taicpu(curtai).loadconst(2, taicpu(curtai).oper[2]^.shifterop^.shiftimm)
  1384. else
  1385. taicpu(curtai).loadreg(2, taicpu(curtai).oper[2]^.shifterop^.rs);
  1386. end;
  1387. end;
  1388. A_NEG:
  1389. begin
  1390. taicpu(curtai).opcode:=A_RSB;
  1391. taicpu(curtai).oppostfix:=PF_S; // NEG should always set flags (according to documentation NEG<c> = RSBS<c>)
  1392. if taicpu(curtai).ops=2 then
  1393. begin
  1394. taicpu(curtai).loadconst(2,0);
  1395. taicpu(curtai).ops:=3;
  1396. end
  1397. else
  1398. begin
  1399. taicpu(curtai).loadconst(1,0);
  1400. taicpu(curtai).ops:=2;
  1401. end;
  1402. end;
  1403. A_SWI:
  1404. begin
  1405. taicpu(curtai).opcode:=A_SVC;
  1406. end;
  1407. end;
  1408. end;
  1409. end;
  1410. curtai:=tai(curtai.Next);
  1411. end;
  1412. end;
  1413. procedure finalizearmcode(list, listtoinsert: TAsmList);
  1414. begin
  1415. { Don't expand pseudo instructions when using GAS, it breaks on some thumb instructions }
  1416. if target_asm.id<>as_gas then
  1417. expand_instructions(list);
  1418. { Do Thumb-2 16bit -> 32bit transformations }
  1419. if GenerateThumb2Code then
  1420. begin
  1421. ensurethumbencodings(list);
  1422. ensurethumb2encodings(list);
  1423. foldITInstructions(list);
  1424. end
  1425. else if GenerateThumbCode then
  1426. ensurethumbencodings(list);
  1427. gather_it_info(list);
  1428. fix_invalid_imms(list);
  1429. insertpcrelativedata(list, listtoinsert);
  1430. end;
  1431. procedure InsertPData;
  1432. var
  1433. prolog: TAsmList;
  1434. begin
  1435. prolog:=TAsmList.create;
  1436. new_section(prolog,sec_code,'FPC_EH_PROLOG',sizeof(pint),secorder_begin);
  1437. prolog.concat(Tai_const.Createname('_ARM_ExceptionHandler', 0));
  1438. prolog.concat(Tai_const.Create_32bit(0));
  1439. prolog.concat(Tai_symbol.Createname_global('FPC_EH_CODE_START',AT_DATA,0));
  1440. { dummy function }
  1441. prolog.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14));
  1442. current_asmdata.asmlists[al_start].insertList(prolog);
  1443. prolog.Free;
  1444. new_section(current_asmdata.asmlists[al_end],sec_pdata,'',sizeof(pint));
  1445. current_asmdata.asmlists[al_end].concat(Tai_const.Createname('FPC_EH_CODE_START', 0));
  1446. current_asmdata.asmlists[al_end].concat(Tai_const.Create_32bit(longint($ffffff01)));
  1447. end;
  1448. (*
  1449. Floating point instruction format information, taken from the linux kernel
  1450. ARM Floating Point Instruction Classes
  1451. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1452. |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
  1453. |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
  1454. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1455. |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
  1456. |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
  1457. |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
  1458. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1459. CPDT data transfer instructions
  1460. LDF, STF, LFM (copro 2), SFM (copro 2)
  1461. CPDO dyadic arithmetic instructions
  1462. ADF, MUF, SUF, RSF, DVF, RDF,
  1463. POW, RPW, RMF, FML, FDV, FRD, POL
  1464. CPDO monadic arithmetic instructions
  1465. MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
  1466. SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
  1467. CPRT joint arithmetic/data transfer instructions
  1468. FIX (arithmetic followed by load/store)
  1469. FLT (load/store followed by arithmetic)
  1470. CMF, CNF CMFE, CNFE (comparisons)
  1471. WFS, RFS (write/read floating point status register)
  1472. WFC, RFC (write/read floating point control register)
  1473. cond condition codes
  1474. P pre/post index bit: 0 = postindex, 1 = preindex
  1475. U up/down bit: 0 = stack grows down, 1 = stack grows up
  1476. W write back bit: 1 = update base register (Rn)
  1477. L load/store bit: 0 = store, 1 = load
  1478. Rn base register
  1479. Rd destination/source register
  1480. Fd floating point destination register
  1481. Fn floating point source register
  1482. Fm floating point source register or floating point constant
  1483. uv transfer length (TABLE 1)
  1484. wx register count (TABLE 2)
  1485. abcd arithmetic opcode (TABLES 3 & 4)
  1486. ef destination size (rounding precision) (TABLE 5)
  1487. gh rounding mode (TABLE 6)
  1488. j dyadic/monadic bit: 0 = dyadic, 1 = monadic
  1489. i constant bit: 1 = constant (TABLE 6)
  1490. */
  1491. /*
  1492. TABLE 1
  1493. +-------------------------+---+---+---------+---------+
  1494. | Precision | u | v | FPSR.EP | length |
  1495. +-------------------------+---+---+---------+---------+
  1496. | Single | 0 | 0 | x | 1 words |
  1497. | Double | 1 | 1 | x | 2 words |
  1498. | Extended | 1 | 1 | x | 3 words |
  1499. | Packed decimal | 1 | 1 | 0 | 3 words |
  1500. | Expanded packed decimal | 1 | 1 | 1 | 4 words |
  1501. +-------------------------+---+---+---------+---------+
  1502. Note: x = don't care
  1503. */
  1504. /*
  1505. TABLE 2
  1506. +---+---+---------------------------------+
  1507. | w | x | Number of registers to transfer |
  1508. +---+---+---------------------------------+
  1509. | 0 | 1 | 1 |
  1510. | 1 | 0 | 2 |
  1511. | 1 | 1 | 3 |
  1512. | 0 | 0 | 4 |
  1513. +---+---+---------------------------------+
  1514. */
  1515. /*
  1516. TABLE 3: Dyadic Floating Point Opcodes
  1517. +---+---+---+---+----------+-----------------------+-----------------------+
  1518. | a | b | c | d | Mnemonic | Description | Operation |
  1519. +---+---+---+---+----------+-----------------------+-----------------------+
  1520. | 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
  1521. | 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
  1522. | 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
  1523. | 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
  1524. | 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
  1525. | 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
  1526. | 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
  1527. | 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
  1528. | 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
  1529. | 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
  1530. | 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
  1531. | 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
  1532. | 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
  1533. | 1 | 1 | 0 | 1 | | undefined instruction | trap |
  1534. | 1 | 1 | 1 | 0 | | undefined instruction | trap |
  1535. | 1 | 1 | 1 | 1 | | undefined instruction | trap |
  1536. +---+---+---+---+----------+-----------------------+-----------------------+
  1537. Note: POW, RPW, POL are deprecated, and are available for backwards
  1538. compatibility only.
  1539. */
  1540. /*
  1541. TABLE 4: Monadic Floating Point Opcodes
  1542. +---+---+---+---+----------+-----------------------+-----------------------+
  1543. | a | b | c | d | Mnemonic | Description | Operation |
  1544. +---+---+---+---+----------+-----------------------+-----------------------+
  1545. | 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
  1546. | 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
  1547. | 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
  1548. | 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
  1549. | 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
  1550. | 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
  1551. | 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
  1552. | 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
  1553. | 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
  1554. | 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
  1555. | 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
  1556. | 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
  1557. | 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
  1558. | 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
  1559. | 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
  1560. | 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
  1561. +---+---+---+---+----------+-----------------------+-----------------------+
  1562. Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
  1563. available for backwards compatibility only.
  1564. */
  1565. /*
  1566. TABLE 5
  1567. +-------------------------+---+---+
  1568. | Rounding Precision | e | f |
  1569. +-------------------------+---+---+
  1570. | IEEE Single precision | 0 | 0 |
  1571. | IEEE Double precision | 0 | 1 |
  1572. | IEEE Extended precision | 1 | 0 |
  1573. | undefined (trap) | 1 | 1 |
  1574. +-------------------------+---+---+
  1575. */
  1576. /*
  1577. TABLE 5
  1578. +---------------------------------+---+---+
  1579. | Rounding Mode | g | h |
  1580. +---------------------------------+---+---+
  1581. | Round to nearest (default) | 0 | 0 |
  1582. | Round toward plus infinity | 0 | 1 |
  1583. | Round toward negative infinity | 1 | 0 |
  1584. | Round toward zero | 1 | 1 |
  1585. +---------------------------------+---+---+
  1586. *)
  1587. function taicpu.GetString:string;
  1588. var
  1589. i : longint;
  1590. s : string;
  1591. addsize : boolean;
  1592. begin
  1593. s:='['+gas_op2str[opcode];
  1594. for i:=0 to ops-1 do
  1595. begin
  1596. with oper[i]^ do
  1597. begin
  1598. if i=0 then
  1599. s:=s+' '
  1600. else
  1601. s:=s+',';
  1602. { type }
  1603. addsize:=false;
  1604. if (ot and OT_VREG)=OT_VREG then
  1605. s:=s+'vreg'
  1606. else
  1607. if (ot and OT_FPUREG)=OT_FPUREG then
  1608. s:=s+'fpureg'
  1609. else
  1610. if (ot and OT_REGS)=OT_REGS then
  1611. s:=s+'sreg'
  1612. else
  1613. if (ot and OT_REGF)=OT_REGF then
  1614. s:=s+'creg'
  1615. else
  1616. if (ot and OT_REGISTER)=OT_REGISTER then
  1617. begin
  1618. s:=s+'reg';
  1619. addsize:=true;
  1620. end
  1621. else
  1622. if (ot and OT_REGLIST)=OT_REGLIST then
  1623. begin
  1624. s:=s+'reglist';
  1625. addsize:=false;
  1626. end
  1627. else
  1628. if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  1629. begin
  1630. s:=s+'imm';
  1631. addsize:=true;
  1632. end
  1633. else
  1634. if (ot and OT_MEMORY)=OT_MEMORY then
  1635. begin
  1636. s:=s+'mem';
  1637. addsize:=true;
  1638. if (ot and OT_AM2)<>0 then
  1639. s:=s+' am2 '
  1640. else if (ot and OT_AM6)<>0 then
  1641. s:=s+' am2 ';
  1642. end
  1643. else
  1644. if (ot and OT_SHIFTEROP)=OT_SHIFTEROP then
  1645. begin
  1646. s:=s+'shifterop';
  1647. addsize:=false;
  1648. end
  1649. else
  1650. s:=s+'???';
  1651. { size }
  1652. if addsize then
  1653. begin
  1654. if (ot and OT_BITS8)<>0 then
  1655. s:=s+'8'
  1656. else
  1657. if (ot and OT_BITS16)<>0 then
  1658. s:=s+'24'
  1659. else
  1660. if (ot and OT_BITS32)<>0 then
  1661. s:=s+'32'
  1662. else
  1663. if (ot and OT_BITSSHIFTER)<>0 then
  1664. s:=s+'shifter'
  1665. else
  1666. s:=s+'??';
  1667. { signed }
  1668. if (ot and OT_SIGNED)<>0 then
  1669. s:=s+'s';
  1670. end;
  1671. end;
  1672. end;
  1673. GetString:=s+']';
  1674. end;
  1675. procedure taicpu.ResetPass1;
  1676. begin
  1677. { we need to reset everything here, because the choosen insentry
  1678. can be invalid for a new situation where the previously optimized
  1679. insentry is not correct }
  1680. InsEntry:=nil;
  1681. InsSize:=0;
  1682. LastInsOffset:=-1;
  1683. end;
  1684. procedure taicpu.ResetPass2;
  1685. begin
  1686. { we are here in a second pass, check if the instruction can be optimized }
  1687. if assigned(InsEntry) and
  1688. ((InsEntry^.flags and IF_PASS2)<>0) then
  1689. begin
  1690. InsEntry:=nil;
  1691. InsSize:=0;
  1692. end;
  1693. LastInsOffset:=-1;
  1694. end;
  1695. function taicpu.CheckIfValid:boolean;
  1696. begin
  1697. Result:=False; { unimplemented }
  1698. end;
  1699. function taicpu.Pass1(objdata:TObjData):longint;
  1700. var
  1701. ldr2op : array[PF_B..PF_T] of tasmop = (
  1702. A_LDRB,A_LDRSB,A_LDRBT,A_LDRH,A_LDRSH,A_LDRT);
  1703. str2op : array[PF_B..PF_T] of tasmop = (
  1704. A_STRB,A_None,A_STRBT,A_STRH,A_None,A_STRT);
  1705. begin
  1706. Pass1:=0;
  1707. { Save the old offset and set the new offset }
  1708. InsOffset:=ObjData.CurrObjSec.Size;
  1709. { Error? }
  1710. if (Insentry=nil) and (InsSize=-1) then
  1711. exit;
  1712. { set the file postion }
  1713. current_filepos:=fileinfo;
  1714. { tranlate LDR+postfix to complete opcode }
  1715. if (opcode=A_LDR) and (oppostfix=PF_D) then
  1716. begin
  1717. opcode:=A_LDRD;
  1718. oppostfix:=PF_None;
  1719. end
  1720. else if (opcode=A_LDR) and (oppostfix<>PF_None) then
  1721. begin
  1722. if (oppostfix in [low(ldr2op)..high(ldr2op)]) then
  1723. opcode:=ldr2op[oppostfix]
  1724. else
  1725. internalerror(2005091001);
  1726. if opcode=A_None then
  1727. internalerror(2005091004);
  1728. { postfix has been added to opcode }
  1729. oppostfix:=PF_None;
  1730. end
  1731. else if (opcode=A_STR) and (oppostfix=PF_D) then
  1732. begin
  1733. opcode:=A_STRD;
  1734. oppostfix:=PF_None;
  1735. end
  1736. else if (opcode=A_STR) and (oppostfix<>PF_None) then
  1737. begin
  1738. if (oppostfix in [low(str2op)..high(str2op)]) then
  1739. opcode:=str2op[oppostfix]
  1740. else
  1741. internalerror(2005091002);
  1742. if opcode=A_None then
  1743. internalerror(2005091003);
  1744. { postfix has been added to opcode }
  1745. oppostfix:=PF_None;
  1746. end;
  1747. { Get InsEntry }
  1748. if FindInsEntry(objdata) then
  1749. begin
  1750. InsSize:=4;
  1751. if insentry^.code[0] in [#$60..#$6C] then
  1752. InsSize:=2;
  1753. LastInsOffset:=InsOffset;
  1754. Pass1:=InsSize;
  1755. exit;
  1756. end;
  1757. LastInsOffset:=-1;
  1758. end;
  1759. procedure taicpu.Pass2(objdata:TObjData);
  1760. begin
  1761. { error in pass1 ? }
  1762. if insentry=nil then
  1763. exit;
  1764. current_filepos:=fileinfo;
  1765. { Generate the instruction }
  1766. GenCode(objdata);
  1767. end;
  1768. procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
  1769. begin
  1770. end;
  1771. procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
  1772. begin
  1773. end;
  1774. procedure taicpu.ppubuildderefimploper(var o:toper);
  1775. begin
  1776. end;
  1777. procedure taicpu.ppuderefoper(var o:toper);
  1778. begin
  1779. end;
  1780. procedure taicpu.BuildArmMasks;
  1781. const
  1782. Masks: array[tcputype] of longint =
  1783. (
  1784. IF_NONE,
  1785. IF_ARMv4,
  1786. IF_ARMv4,
  1787. IF_ARMv4T or IF_ARMv4,
  1788. IF_ARMv4T or IF_ARMv4 or IF_ARMv5,
  1789. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T,
  1790. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE,
  1791. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ,
  1792. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6,
  1793. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K,
  1794. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2,
  1795. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z,
  1796. IF_ARMv4T or IF_ARMv5T or IF_ARMv6M,
  1797. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7,
  1798. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7 or IF_ARMv7A,
  1799. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7 or IF_ARMv7A or IF_ARMv7R,
  1800. IF_ARMv4T or IF_ARMv5T or IF_ARMv6T2 or IF_ARMv7M,
  1801. IF_ARMv4T or IF_ARMv5T or IF_ARMv6T2 or IF_ARMv7M or IF_ARMv7EM
  1802. );
  1803. FPUMasks: array[tfputype] of longword =
  1804. (
  1805. IF_NONE,
  1806. IF_NONE,
  1807. IF_NONE,
  1808. IF_FPA,
  1809. IF_FPA,
  1810. IF_FPA,
  1811. IF_VFPv2,
  1812. IF_VFPv2 or IF_VFPv3,
  1813. IF_VFPv2 or IF_VFPv3,
  1814. IF_NONE,
  1815. IF_VFPv2 or IF_VFPv3 or IF_VFPv4
  1816. );
  1817. begin
  1818. fArmVMask:=Masks[current_settings.cputype] or FPUMasks[current_settings.fputype];
  1819. if current_settings.instructionset=is_thumb then
  1820. begin
  1821. fArmMask:=IF_THUMB;
  1822. if CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype] then
  1823. fArmMask:=fArmMask or IF_THUMB32;
  1824. end
  1825. else
  1826. fArmMask:=IF_ARM32;
  1827. end;
  1828. function taicpu.InsEnd:longint;
  1829. begin
  1830. Result:=0; { unimplemented }
  1831. end;
  1832. procedure taicpu.create_ot(objdata:TObjData);
  1833. var
  1834. i,l,relsize : longint;
  1835. dummy : byte;
  1836. currsym : TObjSymbol;
  1837. begin
  1838. if ops=0 then
  1839. exit;
  1840. { update oper[].ot field }
  1841. for i:=0 to ops-1 do
  1842. with oper[i]^ do
  1843. begin
  1844. case typ of
  1845. top_regset:
  1846. begin
  1847. ot:=OT_REGLIST;
  1848. end;
  1849. top_reg :
  1850. begin
  1851. case getregtype(reg) of
  1852. R_INTREGISTER:
  1853. begin
  1854. ot:=OT_REG32 or OT_SHIFTEROP;
  1855. if getsupreg(reg)<8 then
  1856. ot:=ot or OT_REGLO
  1857. else if reg=NR_STACK_POINTER_REG then
  1858. ot:=ot or OT_REGSP;
  1859. end;
  1860. R_FPUREGISTER:
  1861. ot:=OT_FPUREG;
  1862. R_MMREGISTER:
  1863. ot:=OT_VREG;
  1864. R_SPECIALREGISTER:
  1865. ot:=OT_REGF;
  1866. else
  1867. internalerror(2005090901);
  1868. end;
  1869. end;
  1870. top_ref :
  1871. begin
  1872. if ref^.refaddr=addr_no then
  1873. begin
  1874. { create ot field }
  1875. { we should get the size here dependend on the
  1876. instruction }
  1877. if (ot and OT_SIZE_MASK)=0 then
  1878. ot:=OT_MEMORY or OT_BITS32
  1879. else
  1880. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  1881. if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
  1882. ot:=ot or OT_MEM_OFFS;
  1883. { if we need to fix a reference, we do it here }
  1884. { pc relative addressing }
  1885. if (ref^.base=NR_NO) and
  1886. (ref^.index=NR_NO) and
  1887. (ref^.shiftmode=SM_None)
  1888. { at least we should check if the destination symbol
  1889. is in a text section }
  1890. { and
  1891. (ref^.symbol^.owner="text") } then
  1892. ref^.base:=NR_PC;
  1893. { determine possible address modes }
  1894. if GenerateThumbCode or
  1895. GenerateThumb2Code then
  1896. begin
  1897. if (ref^.addressmode<>AM_OFFSET) then
  1898. ot:=ot or OT_AM2
  1899. else if (ref^.base=NR_PC) then
  1900. ot:=ot or OT_AM6
  1901. else if (ref^.base=NR_STACK_POINTER_REG) then
  1902. ot:=ot or OT_AM5
  1903. else if ref^.index=NR_NO then
  1904. ot:=ot or OT_AM4
  1905. else
  1906. ot:=ot or OT_AM3;
  1907. end;
  1908. if (ref^.base<>NR_NO) and
  1909. (opcode in [A_LDREX,A_LDREXB,A_LDREXH,A_LDREXD,
  1910. A_STREX,A_STREXB,A_STREXH,A_STREXD]) and
  1911. (
  1912. (ref^.addressmode=AM_OFFSET) and
  1913. (ref^.index=NR_NO) and
  1914. (ref^.shiftmode=SM_None) and
  1915. (ref^.offset=0)
  1916. ) then
  1917. ot:=ot or OT_AM6
  1918. else if (ref^.base<>NR_NO) and
  1919. (
  1920. (
  1921. (ref^.index=NR_NO) and
  1922. (ref^.shiftmode=SM_None) and
  1923. (ref^.offset>=-4097) and
  1924. (ref^.offset<=4097)
  1925. ) or
  1926. (
  1927. (ref^.shiftmode=SM_None) and
  1928. (ref^.offset=0)
  1929. ) or
  1930. (
  1931. (ref^.index<>NR_NO) and
  1932. (ref^.shiftmode<>SM_None) and
  1933. (ref^.shiftimm<=32) and
  1934. (ref^.offset=0)
  1935. )
  1936. ) then
  1937. ot:=ot or OT_AM2;
  1938. if (ref^.index<>NR_NO) and
  1939. (oppostfix in [PF_None,PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
  1940. PF_IAD,PF_DBD,PF_FDD,PF_EAD,
  1941. PF_IAS,PF_DBS,PF_FDS,PF_EAS,
  1942. PF_IAX,PF_DBX,PF_FDX,PF_EAX]) and
  1943. (
  1944. (ref^.base=NR_NO) and
  1945. (ref^.shiftmode=SM_None) and
  1946. (ref^.offset=0)
  1947. ) then
  1948. ot:=ot or OT_AM4;
  1949. end
  1950. else
  1951. begin
  1952. l:=ref^.offset;
  1953. currsym:=ObjData.symbolref(ref^.symbol);
  1954. if assigned(currsym) then
  1955. inc(l,currsym.address);
  1956. relsize:=(InsOffset+2)-l;
  1957. if (relsize<-33554428) or (relsize>33554428) then
  1958. ot:=OT_IMM32
  1959. else
  1960. ot:=OT_IMM24;
  1961. end;
  1962. end;
  1963. top_local :
  1964. begin
  1965. { we should get the size here dependend on the
  1966. instruction }
  1967. if (ot and OT_SIZE_MASK)=0 then
  1968. ot:=OT_MEMORY or OT_BITS32
  1969. else
  1970. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  1971. end;
  1972. top_const :
  1973. begin
  1974. ot:=OT_IMMEDIATE;
  1975. if (val=0) then
  1976. ot:=ot_immediatezero
  1977. else if is_shifter_const(val,dummy) then
  1978. ot:=OT_IMMSHIFTER
  1979. else if GenerateThumb2Code and is_thumb32_imm(val) then
  1980. ot:=OT_IMMSHIFTER
  1981. else
  1982. ot:=OT_IMM32
  1983. end;
  1984. top_none :
  1985. begin
  1986. { generated when there was an error in the
  1987. assembler reader. It never happends when generating
  1988. assembler }
  1989. end;
  1990. top_shifterop:
  1991. begin
  1992. ot:=OT_SHIFTEROP;
  1993. end;
  1994. top_conditioncode:
  1995. begin
  1996. ot:=OT_CONDITION;
  1997. end;
  1998. top_specialreg:
  1999. begin
  2000. ot:=OT_REGS;
  2001. end;
  2002. top_modeflags:
  2003. begin
  2004. ot:=OT_MODEFLAGS;
  2005. end;
  2006. else
  2007. internalerror(2004022623);
  2008. end;
  2009. end;
  2010. end;
  2011. function taicpu.Matches(p:PInsEntry):longint;
  2012. { * IF_SM stands for Size Match: any operand whose size is not
  2013. * explicitly specified by the template is `really' intended to be
  2014. * the same size as the first size-specified operand.
  2015. * Non-specification is tolerated in the input instruction, but
  2016. * _wrong_ specification is not.
  2017. *
  2018. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  2019. * three-operand instructions such as SHLD: it implies that the
  2020. * first two operands must match in size, but that the third is
  2021. * required to be _unspecified_.
  2022. *
  2023. * IF_SB invokes Size Byte: operands with unspecified size in the
  2024. * template are really bytes, and so no non-byte specification in
  2025. * the input instruction will be tolerated. IF_SW similarly invokes
  2026. * Size Word, and IF_SD invokes Size Doubleword.
  2027. *
  2028. * (The default state if neither IF_SM nor IF_SM2 is specified is
  2029. * that any operand with unspecified size in the template is
  2030. * required to have unspecified size in the instruction too...)
  2031. }
  2032. var
  2033. i{,j,asize,oprs} : longint;
  2034. {siz : array[0..3] of longint;}
  2035. begin
  2036. Matches:=100;
  2037. { Check the opcode and operands }
  2038. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  2039. begin
  2040. Matches:=0;
  2041. exit;
  2042. end;
  2043. { check ARM instruction version }
  2044. if (p^.flags and fArmVMask)=0 then
  2045. begin
  2046. Matches:=0;
  2047. exit;
  2048. end;
  2049. { check ARM instruction type }
  2050. if (p^.flags and fArmMask)=0 then
  2051. begin
  2052. Matches:=0;
  2053. exit;
  2054. end;
  2055. { Check wideformat flag }
  2056. if wideformat and ((p^.flags and IF_WIDE)=0) then
  2057. begin
  2058. matches:=0;
  2059. exit;
  2060. end;
  2061. { Check that no spurious colons or TOs are present }
  2062. for i:=0 to p^.ops-1 do
  2063. if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  2064. begin
  2065. Matches:=0;
  2066. exit;
  2067. end;
  2068. { Check that the operand flags all match up }
  2069. for i:=0 to p^.ops-1 do
  2070. begin
  2071. if ((p^.optypes[i] and (not oper[i]^.ot)) or
  2072. ((p^.optypes[i] and OT_SIZE_MASK) and
  2073. ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
  2074. begin
  2075. if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
  2076. (oper[i]^.ot and OT_SIZE_MASK))<>0 then
  2077. begin
  2078. Matches:=0;
  2079. exit;
  2080. end
  2081. else if ((p^.optypes[i] and OT_OPT_SIZE)<>0) and
  2082. ((p^.optypes[i] and OT_OPT_SIZE)<>(oper[i]^.ot and OT_OPT_SIZE)) then
  2083. begin
  2084. Matches:=0;
  2085. exit;
  2086. end
  2087. else
  2088. Matches:=1;
  2089. end;
  2090. end;
  2091. { check postfixes:
  2092. the existance of a certain postfix requires a
  2093. particular code }
  2094. { update condition flags
  2095. or floating point single }
  2096. if (oppostfix=PF_S) and
  2097. not(p^.code[0] in [#$04..#$0F,#$14..#$16,#$29,#$30,#$60..#$6B,#$80..#$82,#$A0..#$A2,#$44,#$94,#$42,#$92]) then
  2098. begin
  2099. Matches:=0;
  2100. exit;
  2101. end;
  2102. { floating point size }
  2103. if (oppostfix in [PF_D,PF_E,PF_P,PF_EP]) and
  2104. not(p^.code[0] in [
  2105. // FPA
  2106. #$A0..#$A2,
  2107. // old-school VFP
  2108. #$42,#$92,
  2109. // vldm/vstm
  2110. #$44,#$94]) then
  2111. begin
  2112. Matches:=0;
  2113. exit;
  2114. end;
  2115. { multiple load/store address modes }
  2116. if (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and
  2117. not(p^.code[0] in [
  2118. // ldr,str,ldrb,strb
  2119. #$17,
  2120. // stm,ldm
  2121. #$26,#$69,#$8C,
  2122. // vldm/vstm
  2123. #$44,#$94
  2124. ]) then
  2125. begin
  2126. Matches:=0;
  2127. exit;
  2128. end;
  2129. { we shouldn't see any opsize prefixes here }
  2130. if (oppostfix in [PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T]) then
  2131. begin
  2132. Matches:=0;
  2133. exit;
  2134. end;
  2135. if (roundingmode<>RM_None) and not(p^.code[0] in []) then
  2136. begin
  2137. Matches:=0;
  2138. exit;
  2139. end;
  2140. { Check thumb flags }
  2141. if p^.code[0] in [#$60..#$61] then
  2142. begin
  2143. if (p^.code[0]=#$60) and
  2144. (GenerateThumb2Code and
  2145. ((not inIT) and (oppostfix<>PF_S)) or
  2146. (inIT and (condition=C_None))) then
  2147. begin
  2148. Matches:=0;
  2149. exit;
  2150. end
  2151. else if (p^.code[0]=#$61) and
  2152. (oppostfix=PF_S) then
  2153. begin
  2154. Matches:=0;
  2155. exit;
  2156. end;
  2157. end
  2158. else if p^.code[0]=#$62 then
  2159. begin
  2160. if (GenerateThumb2Code and
  2161. (condition<>C_None) and
  2162. (not inIT) and
  2163. (not lastinIT)) then
  2164. begin
  2165. Matches:=0;
  2166. exit;
  2167. end;
  2168. end
  2169. else if p^.code[0]=#$63 then
  2170. begin
  2171. if inIT then
  2172. begin
  2173. Matches:=0;
  2174. exit;
  2175. end;
  2176. end
  2177. else if p^.code[0]=#$64 then
  2178. begin
  2179. if (opcode=A_MUL) then
  2180. begin
  2181. if (ops=3) and
  2182. ((oper[2]^.typ<>top_reg) or
  2183. (oper[0]^.reg<>oper[2]^.reg)) then
  2184. begin
  2185. matches:=0;
  2186. exit;
  2187. end;
  2188. end;
  2189. end
  2190. else if p^.code[0]=#$6B then
  2191. begin
  2192. if inIT or
  2193. (oppostfix<>PF_S) then
  2194. begin
  2195. Matches:=0;
  2196. exit;
  2197. end;
  2198. end;
  2199. { Check operand sizes }
  2200. { as default an untyped size can get all the sizes, this is different
  2201. from nasm, but else we need to do a lot checking which opcodes want
  2202. size or not with the automatic size generation }
  2203. (*
  2204. asize:=longint($ffffffff);
  2205. if (p^.flags and IF_SB)<>0 then
  2206. asize:=OT_BITS8
  2207. else if (p^.flags and IF_SW)<>0 then
  2208. asize:=OT_BITS16
  2209. else if (p^.flags and IF_SD)<>0 then
  2210. asize:=OT_BITS32;
  2211. if (p^.flags and IF_ARMASK)<>0 then
  2212. begin
  2213. siz[0]:=0;
  2214. siz[1]:=0;
  2215. siz[2]:=0;
  2216. if (p^.flags and IF_AR0)<>0 then
  2217. siz[0]:=asize
  2218. else if (p^.flags and IF_AR1)<>0 then
  2219. siz[1]:=asize
  2220. else if (p^.flags and IF_AR2)<>0 then
  2221. siz[2]:=asize;
  2222. end
  2223. else
  2224. begin
  2225. { we can leave because the size for all operands is forced to be
  2226. the same
  2227. but not if IF_SB IF_SW or IF_SD is set PM }
  2228. if asize=-1 then
  2229. exit;
  2230. siz[0]:=asize;
  2231. siz[1]:=asize;
  2232. siz[2]:=asize;
  2233. end;
  2234. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  2235. begin
  2236. if (p^.flags and IF_SM2)<>0 then
  2237. oprs:=2
  2238. else
  2239. oprs:=p^.ops;
  2240. for i:=0 to oprs-1 do
  2241. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  2242. begin
  2243. for j:=0 to oprs-1 do
  2244. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  2245. break;
  2246. end;
  2247. end
  2248. else
  2249. oprs:=2;
  2250. { Check operand sizes }
  2251. for i:=0 to p^.ops-1 do
  2252. begin
  2253. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  2254. ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  2255. { Immediates can always include smaller size }
  2256. ((oper[i]^.ot and OT_IMMEDIATE)=0) and
  2257. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
  2258. Matches:=2;
  2259. end;
  2260. *)
  2261. end;
  2262. function taicpu.calcsize(p:PInsEntry):shortint;
  2263. begin
  2264. result:=4;
  2265. end;
  2266. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  2267. begin
  2268. Result:=False; { unimplemented }
  2269. end;
  2270. procedure taicpu.Swapoperands;
  2271. begin
  2272. end;
  2273. function taicpu.FindInsentry(objdata:TObjData):boolean;
  2274. var
  2275. i : longint;
  2276. begin
  2277. result:=false;
  2278. { Things which may only be done once, not when a second pass is done to
  2279. optimize }
  2280. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  2281. begin
  2282. { create the .ot fields }
  2283. create_ot(objdata);
  2284. BuildArmMasks;
  2285. { set the file postion }
  2286. current_filepos:=fileinfo;
  2287. end
  2288. else
  2289. begin
  2290. { we've already an insentry so it's valid }
  2291. result:=true;
  2292. exit;
  2293. end;
  2294. { Lookup opcode in the table }
  2295. InsSize:=-1;
  2296. i:=instabcache^[opcode];
  2297. if i=-1 then
  2298. begin
  2299. Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
  2300. exit;
  2301. end;
  2302. insentry:=@instab[i];
  2303. while (insentry^.opcode=opcode) do
  2304. begin
  2305. if matches(insentry)=100 then
  2306. begin
  2307. result:=true;
  2308. exit;
  2309. end;
  2310. inc(i);
  2311. insentry:=@instab[i];
  2312. end;
  2313. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  2314. { No instruction found, set insentry to nil and inssize to -1 }
  2315. insentry:=nil;
  2316. inssize:=-1;
  2317. end;
  2318. procedure taicpu.gencode(objdata:TObjData);
  2319. const
  2320. CondVal : array[TAsmCond] of byte=(
  2321. $E, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $A,
  2322. $B, $C, $D, $E, 0);
  2323. var
  2324. bytes, rd, rm, rn, d, m, n : dword;
  2325. bytelen : longint;
  2326. dp_operation : boolean;
  2327. i_field : byte;
  2328. currsym : TObjSymbol;
  2329. offset : longint;
  2330. refoper : poper;
  2331. msb : longint;
  2332. r: byte;
  2333. procedure setshifterop(op : byte);
  2334. var
  2335. r : byte;
  2336. imm : dword;
  2337. count : integer;
  2338. begin
  2339. case oper[op]^.typ of
  2340. top_const:
  2341. begin
  2342. i_field:=1;
  2343. if oper[op]^.val and $ff=oper[op]^.val then
  2344. bytes:=bytes or dword(oper[op]^.val)
  2345. else
  2346. begin
  2347. { calc rotate and adjust imm }
  2348. count:=0;
  2349. r:=0;
  2350. imm:=dword(oper[op]^.val);
  2351. repeat
  2352. imm:=RolDWord(imm, 2);
  2353. inc(r);
  2354. inc(count);
  2355. if count > 32 then
  2356. begin
  2357. message1(asmw_e_invalid_opcode_and_operands, 'invalid shifter imm');
  2358. exit;
  2359. end;
  2360. until (imm and $ff)=imm;
  2361. bytes:=bytes or (r shl 8) or imm;
  2362. end;
  2363. end;
  2364. top_reg:
  2365. begin
  2366. i_field:=0;
  2367. bytes:=bytes or getsupreg(oper[op]^.reg);
  2368. { does a real shifter op follow? }
  2369. if (op+1<opercnt) and (oper[op+1]^.typ=top_shifterop) then
  2370. with oper[op+1]^.shifterop^ do
  2371. begin
  2372. bytes:=bytes or ((shiftimm and $1F) shl 7);
  2373. if shiftmode<>SM_RRX then
  2374. bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
  2375. else
  2376. bytes:=bytes or (3 shl 5);
  2377. if getregtype(rs) <> R_INVALIDREGISTER then
  2378. begin
  2379. bytes:=bytes or (1 shl 4);
  2380. bytes:=bytes or (getsupreg(rs) shl 8);
  2381. end
  2382. end;
  2383. end;
  2384. else
  2385. internalerror(2005091103);
  2386. end;
  2387. end;
  2388. function MakeRegList(reglist: tcpuregisterset): word;
  2389. var
  2390. i, w: word;
  2391. begin
  2392. result:=0;
  2393. w:=1;
  2394. for i:=RS_R0 to RS_R15 do
  2395. begin
  2396. if i in reglist then
  2397. result:=result or w;
  2398. w:=w shl 1
  2399. end;
  2400. end;
  2401. function getcoproc(reg: tregister): byte;
  2402. begin
  2403. if reg=NR_p15 then
  2404. result:=15
  2405. else
  2406. begin
  2407. Message1(asmw_e_invalid_opcode_and_operands,'Invalid coprocessor port');
  2408. result:=0;
  2409. end;
  2410. end;
  2411. function getcoprocreg(reg: tregister): byte;
  2412. var
  2413. tmpr: tregister;
  2414. begin
  2415. { FIXME: temp variable r is needed here to avoid Internal error 20060521 }
  2416. { while compiling the compiler. }
  2417. tmpr:=NR_CR0;
  2418. result:=getsupreg(reg)-getsupreg(tmpr);
  2419. end;
  2420. function getmmreg(reg: tregister): byte;
  2421. begin
  2422. case reg of
  2423. NR_D0: result:=0;
  2424. NR_D1: result:=1;
  2425. NR_D2: result:=2;
  2426. NR_D3: result:=3;
  2427. NR_D4: result:=4;
  2428. NR_D5: result:=5;
  2429. NR_D6: result:=6;
  2430. NR_D7: result:=7;
  2431. NR_D8: result:=8;
  2432. NR_D9: result:=9;
  2433. NR_D10: result:=10;
  2434. NR_D11: result:=11;
  2435. NR_D12: result:=12;
  2436. NR_D13: result:=13;
  2437. NR_D14: result:=14;
  2438. NR_D15: result:=15;
  2439. NR_D16: result:=16;
  2440. NR_D17: result:=17;
  2441. NR_D18: result:=18;
  2442. NR_D19: result:=19;
  2443. NR_D20: result:=20;
  2444. NR_D21: result:=21;
  2445. NR_D22: result:=22;
  2446. NR_D23: result:=23;
  2447. NR_D24: result:=24;
  2448. NR_D25: result:=25;
  2449. NR_D26: result:=26;
  2450. NR_D27: result:=27;
  2451. NR_D28: result:=28;
  2452. NR_D29: result:=29;
  2453. NR_D30: result:=30;
  2454. NR_D31: result:=31;
  2455. NR_S0: result:=0;
  2456. NR_S1: result:=1;
  2457. NR_S2: result:=2;
  2458. NR_S3: result:=3;
  2459. NR_S4: result:=4;
  2460. NR_S5: result:=5;
  2461. NR_S6: result:=6;
  2462. NR_S7: result:=7;
  2463. NR_S8: result:=8;
  2464. NR_S9: result:=9;
  2465. NR_S10: result:=10;
  2466. NR_S11: result:=11;
  2467. NR_S12: result:=12;
  2468. NR_S13: result:=13;
  2469. NR_S14: result:=14;
  2470. NR_S15: result:=15;
  2471. NR_S16: result:=16;
  2472. NR_S17: result:=17;
  2473. NR_S18: result:=18;
  2474. NR_S19: result:=19;
  2475. NR_S20: result:=20;
  2476. NR_S21: result:=21;
  2477. NR_S22: result:=22;
  2478. NR_S23: result:=23;
  2479. NR_S24: result:=24;
  2480. NR_S25: result:=25;
  2481. NR_S26: result:=26;
  2482. NR_S27: result:=27;
  2483. NR_S28: result:=28;
  2484. NR_S29: result:=29;
  2485. NR_S30: result:=30;
  2486. NR_S31: result:=31;
  2487. else
  2488. result:=0;
  2489. end;
  2490. end;
  2491. procedure encodethumbimm(imm: longword);
  2492. var
  2493. imm12, tmp: tcgint;
  2494. shift: integer;
  2495. found: boolean;
  2496. begin
  2497. found:=true;
  2498. if (imm and $FF) = imm then
  2499. imm12:=imm
  2500. else if ((imm shr 16)=(imm and $FFFF)) and
  2501. ((imm and $FF00FF00) = 0) then
  2502. imm12:=(imm and $ff) or ($1 shl 8)
  2503. else if ((imm shr 16)=(imm and $FFFF)) and
  2504. ((imm and $00FF00FF) = 0) then
  2505. imm12:=((imm shr 8) and $ff) or ($2 shl 8)
  2506. else if ((imm shr 16)=(imm and $FFFF)) and
  2507. (((imm shr 8) and $FF)=(imm and $FF)) then
  2508. imm12:=(imm and $ff) or ($3 shl 8)
  2509. else
  2510. begin
  2511. found:=false;
  2512. imm12:=0;
  2513. for shift:=1 to 31 do
  2514. begin
  2515. tmp:=RolDWord(imm,shift);
  2516. if ((tmp and $FF)=tmp) and
  2517. ((tmp and $80)=$80) then
  2518. begin
  2519. imm12:=(tmp and $7F) or (shift shl 7);
  2520. found:=true;
  2521. break;
  2522. end;
  2523. end;
  2524. end;
  2525. if found then
  2526. begin
  2527. bytes:=bytes or (imm12 and $FF);
  2528. bytes:=bytes or (((imm12 shr 8) and $7) shl 12);
  2529. bytes:=bytes or (((imm12 shr 11) and $1) shl 26);
  2530. end
  2531. else
  2532. Message1(asmw_e_value_exceeds_bounds, IntToStr(imm));
  2533. end;
  2534. procedure setthumbshift(op: byte; is_sat: boolean = false);
  2535. var
  2536. shift,typ: byte;
  2537. begin
  2538. shift:=0;
  2539. typ:=0;
  2540. case oper[op]^.shifterop^.shiftmode of
  2541. SM_LSL: begin typ:=0; shift:=oper[op]^.shifterop^.shiftimm; end;
  2542. SM_LSR: begin typ:=1; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
  2543. SM_ASR: begin typ:=2; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
  2544. SM_ROR: begin typ:=3; shift:=oper[op]^.shifterop^.shiftimm; if shift=0 then message(asmw_e_invalid_opcode_and_operands); end;
  2545. SM_RRX: begin typ:=3; shift:=0; end;
  2546. end;
  2547. if is_sat then
  2548. begin
  2549. bytes:=bytes or ((typ and 1) shl 5);
  2550. bytes:=bytes or ((typ shr 1) shl 21);
  2551. end
  2552. else
  2553. bytes:=bytes or (typ shl 4);
  2554. bytes:=bytes or (shift and $3) shl 6;
  2555. bytes:=bytes or ((shift and $1C) shr 2) shl 12;
  2556. end;
  2557. begin
  2558. bytes:=$0;
  2559. bytelen:=4;
  2560. i_field:=0;
  2561. { evaluate and set condition code }
  2562. bytes:=bytes or (CondVal[condition] shl 28);
  2563. { condition code allowed? }
  2564. { setup rest of the instruction }
  2565. case insentry^.code[0] of
  2566. #$01: // B/BL
  2567. begin
  2568. { set instruction code }
  2569. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2570. { set offset }
  2571. if oper[0]^.typ=top_const then
  2572. bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
  2573. else
  2574. begin
  2575. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  2576. if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
  2577. begin
  2578. objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24);
  2579. bytes:=bytes or $fffffe; // TODO: Not sure this is right, but it matches the output of gas
  2580. end
  2581. else
  2582. bytes:=bytes or (((currsym.offset-insoffset-8) shr 2) and $ffffff);
  2583. end;
  2584. end;
  2585. #$02:
  2586. begin
  2587. { set instruction code }
  2588. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2589. { set code }
  2590. bytes:=bytes or (oper[0]^.val and $FFFFFF);
  2591. end;
  2592. #$03:
  2593. begin // BLX/BX
  2594. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2595. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2596. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  2597. bytes:=bytes or ord(insentry^.code[4]);
  2598. bytes:=bytes or getsupreg(oper[0]^.reg);
  2599. end;
  2600. #$04..#$07: // SUB
  2601. begin
  2602. { set instruction code }
  2603. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2604. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2605. { set destination }
  2606. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  2607. { set Rn }
  2608. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  2609. { create shifter op }
  2610. setshifterop(2);
  2611. { set I field }
  2612. bytes:=bytes or (i_field shl 25);
  2613. { set S if necessary }
  2614. if oppostfix=PF_S then
  2615. bytes:=bytes or (1 shl 20);
  2616. end;
  2617. #$08,#$0A,#$0B: // MOV
  2618. begin
  2619. { set instruction code }
  2620. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2621. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2622. { set destination }
  2623. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  2624. { create shifter op }
  2625. setshifterop(1);
  2626. { set I field }
  2627. bytes:=bytes or (i_field shl 25);
  2628. { set S if necessary }
  2629. if oppostfix=PF_S then
  2630. bytes:=bytes or (1 shl 20);
  2631. end;
  2632. #$0C,#$0E,#$0F: // CMP
  2633. begin
  2634. { set instruction code }
  2635. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2636. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2637. { set destination }
  2638. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  2639. { create shifter op }
  2640. setshifterop(1);
  2641. { set I field }
  2642. bytes:=bytes or (i_field shl 25);
  2643. { always set S bit }
  2644. bytes:=bytes or (1 shl 20);
  2645. end;
  2646. #$10: // MRS
  2647. begin
  2648. { set instruction code }
  2649. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2650. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2651. { set destination }
  2652. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  2653. case oper[1]^.reg of
  2654. NR_APSR,NR_CPSR:;
  2655. NR_SPSR:
  2656. begin
  2657. bytes:=bytes or (1 shl 22);
  2658. end;
  2659. else
  2660. Message(asmw_e_invalid_opcode_and_operands);
  2661. end;
  2662. end;
  2663. #$12,#$13: // MSR
  2664. begin
  2665. { set instruction code }
  2666. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2667. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2668. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  2669. { set destination }
  2670. if oper[0]^.typ=top_specialreg then
  2671. begin
  2672. if (oper[0]^.specialreg<>NR_CPSR) and
  2673. (oper[0]^.specialreg<>NR_SPSR) then
  2674. Message1(asmw_e_invalid_opcode_and_operands, '"Invalid special reg"');
  2675. if srC in oper[0]^.specialflags then
  2676. bytes:=bytes or (1 shl 16);
  2677. if srX in oper[0]^.specialflags then
  2678. bytes:=bytes or (1 shl 17);
  2679. if srS in oper[0]^.specialflags then
  2680. bytes:=bytes or (1 shl 18);
  2681. if srF in oper[0]^.specialflags then
  2682. bytes:=bytes or (1 shl 19);
  2683. { Set R bit }
  2684. if oper[0]^.specialreg=NR_SPSR then
  2685. bytes:=bytes or (1 shl 22);
  2686. end
  2687. else
  2688. case oper[0]^.reg of
  2689. NR_APSR_nzcvq: bytes:=bytes or (2 shl 18);
  2690. NR_APSR_g: bytes:=bytes or (1 shl 18);
  2691. NR_APSR_nzcvqg: bytes:=bytes or (3 shl 18);
  2692. else
  2693. Message1(asmw_e_invalid_opcode_and_operands, 'Invalid combination APSR bits used');
  2694. end;
  2695. setshifterop(1);
  2696. end;
  2697. #$14: // MUL/MLA r1,r2,r3
  2698. begin
  2699. { set instruction code }
  2700. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2701. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2702. bytes:=bytes or ord(insentry^.code[3]);
  2703. { set regs }
  2704. bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
  2705. bytes:=bytes or getsupreg(oper[1]^.reg);
  2706. bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
  2707. if oppostfix in [PF_S] then
  2708. bytes:=bytes or (1 shl 20);
  2709. end;
  2710. #$15: // MUL/MLA r1,r2,r3,r4
  2711. begin
  2712. { set instruction code }
  2713. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2714. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2715. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2716. { set regs }
  2717. bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
  2718. bytes:=bytes or getsupreg(oper[1]^.reg);
  2719. bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
  2720. if ops>3 then
  2721. bytes:=bytes or getsupreg(oper[3]^.reg) shl 12
  2722. else
  2723. bytes:=bytes or ord(insentry^.code[4]) shl 12;
  2724. if oppostfix in [PF_R,PF_X] then
  2725. bytes:=bytes or (1 shl 5);
  2726. if oppostfix in [PF_S] then
  2727. bytes:=bytes or (1 shl 20);
  2728. end;
  2729. #$16: // MULL r1,r2,r3,r4
  2730. begin
  2731. { set instruction code }
  2732. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2733. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2734. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2735. { set regs }
  2736. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2737. if (ops=3) and (opcode=A_PKHTB) then
  2738. begin
  2739. bytes:=bytes or getsupreg(oper[1]^.reg);
  2740. bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
  2741. end
  2742. else
  2743. begin
  2744. bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
  2745. bytes:=bytes or getsupreg(oper[2]^.reg);
  2746. end;
  2747. if ops=4 then
  2748. begin
  2749. if oper[3]^.typ=top_shifterop then
  2750. begin
  2751. if opcode in [A_PKHBT,A_PKHTB] then
  2752. begin
  2753. if ((opcode=A_PKHTB) and
  2754. (oper[3]^.shifterop^.shiftmode <> SM_ASR)) or
  2755. ((opcode=A_PKHBT) and
  2756. (oper[3]^.shifterop^.shiftmode <> SM_LSL)) or
  2757. (oper[3]^.shifterop^.rs<>NR_NO) then
  2758. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  2759. bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
  2760. end
  2761. else
  2762. begin
  2763. if (oper[3]^.shifterop^.shiftmode<>sm_ror) or
  2764. (oper[3]^.shifterop^.rs<>NR_NO) or
  2765. (not (oper[3]^.shifterop^.shiftimm in [0,8,16,24])) then
  2766. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  2767. bytes:=bytes or (((oper[3]^.shifterop^.shiftimm shr 3) and $3) shl 10);
  2768. end;
  2769. end
  2770. else
  2771. bytes:=bytes or getsupreg(oper[3]^.reg) shl 8;
  2772. end;
  2773. if PF_S=oppostfix then
  2774. bytes:=bytes or (1 shl 20);
  2775. if PF_X=oppostfix then
  2776. bytes:=bytes or (1 shl 5);
  2777. end;
  2778. #$17: // LDR/STR
  2779. begin
  2780. { set instruction code }
  2781. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2782. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2783. { set Rn and Rd }
  2784. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2785. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  2786. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  2787. begin
  2788. { set offset }
  2789. offset:=0;
  2790. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  2791. if assigned(currsym) then
  2792. offset:=currsym.offset-insoffset-8;
  2793. offset:=offset+oper[1]^.ref^.offset;
  2794. if offset>=0 then
  2795. { set U flag }
  2796. bytes:=bytes or (1 shl 23)
  2797. else
  2798. offset:=-offset;
  2799. bytes:=bytes or (offset and $FFF);
  2800. end
  2801. else
  2802. begin
  2803. { set U flag }
  2804. if oper[1]^.ref^.signindex>=0 then
  2805. bytes:=bytes or (1 shl 23);
  2806. { set I flag }
  2807. bytes:=bytes or (1 shl 25);
  2808. bytes:=bytes or getsupreg(oper[1]^.ref^.index);
  2809. { set shift }
  2810. with oper[1]^.ref^ do
  2811. if shiftmode<>SM_None then
  2812. begin
  2813. bytes:=bytes or ((shiftimm and $1F) shl 7);
  2814. if shiftmode<>SM_RRX then
  2815. bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
  2816. else
  2817. bytes:=bytes or (3 shl 5);
  2818. end
  2819. end;
  2820. { set W bit }
  2821. if oper[1]^.ref^.addressmode=AM_PREINDEXED then
  2822. bytes:=bytes or (1 shl 21);
  2823. { set P bit if necessary }
  2824. if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
  2825. bytes:=bytes or (1 shl 24);
  2826. end;
  2827. #$18: // LDREX/STREX
  2828. begin
  2829. { set instruction code }
  2830. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2831. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2832. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  2833. bytes:=bytes or ord(insentry^.code[4]);
  2834. { set Rn and Rd }
  2835. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2836. if (ops=3) then
  2837. begin
  2838. if opcode<>A_LDREXD then
  2839. bytes:=bytes or getsupreg(oper[1]^.reg);
  2840. bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
  2841. end
  2842. else if (ops=4) then // STREXD
  2843. begin
  2844. if opcode<>A_LDREXD then
  2845. bytes:=bytes or getsupreg(oper[1]^.reg);
  2846. bytes:=bytes or (getsupreg(oper[3]^.ref^.base) shl 16);
  2847. end
  2848. else
  2849. bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 16);
  2850. end;
  2851. #$19: // LDRD/STRD
  2852. begin
  2853. { set instruction code }
  2854. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2855. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2856. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  2857. bytes:=bytes or ord(insentry^.code[4]);
  2858. { set Rn and Rd }
  2859. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2860. refoper:=oper[1];
  2861. if ops=3 then
  2862. refoper:=oper[2];
  2863. bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
  2864. if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
  2865. begin
  2866. bytes:=bytes or (1 shl 22);
  2867. { set offset }
  2868. offset:=0;
  2869. currsym:=objdata.symbolref(refoper^.ref^.symbol);
  2870. if assigned(currsym) then
  2871. offset:=currsym.offset-insoffset-8;
  2872. offset:=offset+refoper^.ref^.offset;
  2873. if offset>=0 then
  2874. { set U flag }
  2875. bytes:=bytes or (1 shl 23)
  2876. else
  2877. offset:=-offset;
  2878. bytes:=bytes or (offset and $F);
  2879. bytes:=bytes or ((offset and $F0) shl 4);
  2880. end
  2881. else
  2882. begin
  2883. { set U flag }
  2884. if refoper^.ref^.signindex>=0 then
  2885. bytes:=bytes or (1 shl 23);
  2886. bytes:=bytes or getsupreg(refoper^.ref^.index);
  2887. end;
  2888. { set W bit }
  2889. if refoper^.ref^.addressmode=AM_PREINDEXED then
  2890. bytes:=bytes or (1 shl 21);
  2891. { set P bit if necessary }
  2892. if refoper^.ref^.addressmode<>AM_POSTINDEXED then
  2893. bytes:=bytes or (1 shl 24);
  2894. end;
  2895. #$1A: // QADD/QSUB
  2896. begin
  2897. { set instruction code }
  2898. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2899. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2900. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2901. { set regs }
  2902. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2903. bytes:=bytes or getsupreg(oper[1]^.reg) shl 0;
  2904. bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
  2905. end;
  2906. #$1B:
  2907. begin
  2908. { set instruction code }
  2909. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2910. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2911. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2912. { set regs }
  2913. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2914. bytes:=bytes or getsupreg(oper[1]^.reg);
  2915. if ops=3 then
  2916. begin
  2917. if (oper[2]^.shifterop^.shiftmode<>sm_ror) or
  2918. (oper[2]^.shifterop^.rs<>NR_NO) or
  2919. (not (oper[2]^.shifterop^.shiftimm in [0,8,16,24])) then
  2920. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  2921. bytes:=bytes or (((oper[2]^.shifterop^.shiftimm shr 3) and $3) shl 10);
  2922. end;
  2923. end;
  2924. #$1C: // MCR/MRC
  2925. begin
  2926. { set instruction code }
  2927. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2928. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2929. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2930. { set regs and operands }
  2931. bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
  2932. bytes:=bytes or ((oper[1]^.val and $7) shl 21);
  2933. bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
  2934. bytes:=bytes or getcoprocreg(oper[3]^.reg) shl 16;
  2935. bytes:=bytes or getcoprocreg(oper[4]^.reg);
  2936. if ops > 5 then
  2937. bytes:=bytes or ((oper[5]^.val and $7) shl 5);
  2938. end;
  2939. #$1D: // MCRR/MRRC
  2940. begin
  2941. { set instruction code }
  2942. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2943. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2944. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2945. { set regs and operands }
  2946. bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
  2947. bytes:=bytes or ((oper[1]^.val and $7) shl 4);
  2948. bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
  2949. bytes:=bytes or getsupreg(oper[3]^.reg) shl 16;
  2950. bytes:=bytes or getcoprocreg(oper[4]^.reg);
  2951. end;
  2952. #$1E: // LDRHT/STRHT
  2953. begin
  2954. { set instruction code }
  2955. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2956. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2957. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  2958. bytes:=bytes or ord(insentry^.code[4]);
  2959. { set Rn and Rd }
  2960. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2961. refoper:=oper[1];
  2962. bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
  2963. if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
  2964. begin
  2965. bytes:=bytes or (1 shl 22);
  2966. { set offset }
  2967. offset:=0;
  2968. currsym:=objdata.symbolref(refoper^.ref^.symbol);
  2969. if assigned(currsym) then
  2970. offset:=currsym.offset-insoffset-8;
  2971. offset:=offset+refoper^.ref^.offset;
  2972. if offset>=0 then
  2973. { set U flag }
  2974. bytes:=bytes or (1 shl 23)
  2975. else
  2976. offset:=-offset;
  2977. bytes:=bytes or (offset and $F);
  2978. bytes:=bytes or ((offset and $F0) shl 4);
  2979. end
  2980. else
  2981. begin
  2982. { set U flag }
  2983. if refoper^.ref^.signindex>=0 then
  2984. bytes:=bytes or (1 shl 23);
  2985. bytes:=bytes or getsupreg(refoper^.ref^.index);
  2986. end;
  2987. end;
  2988. #$22: // LDRH/STRH
  2989. begin
  2990. { set instruction code }
  2991. bytes:=bytes or (ord(insentry^.code[1]) shl 16);
  2992. bytes:=bytes or ord(insentry^.code[2]);
  2993. { src/dest register (Rd) }
  2994. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2995. { base register (Rn) }
  2996. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  2997. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  2998. begin
  2999. bytes:=bytes or (1 shl 22); // with immediate offset
  3000. offset:=oper[1]^.ref^.offset;
  3001. if offset>=0 then
  3002. { set U flag }
  3003. bytes:=bytes or (1 shl 23)
  3004. else
  3005. offset:=-offset;
  3006. bytes:=bytes or (offset and $F);
  3007. bytes:=bytes or ((offset and $F0) shl 4);
  3008. end
  3009. else
  3010. begin
  3011. { set U flag }
  3012. if oper[1]^.ref^.signindex>=0 then
  3013. bytes:=bytes or (1 shl 23);
  3014. bytes:=bytes or getsupreg(oper[1]^.ref^.index);
  3015. end;
  3016. { set W bit }
  3017. if oper[1]^.ref^.addressmode=AM_PREINDEXED then
  3018. bytes:=bytes or (1 shl 21);
  3019. { set P bit if necessary }
  3020. if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
  3021. bytes:=bytes or (1 shl 24);
  3022. end;
  3023. #$25: // PLD/PLI
  3024. begin
  3025. { set instruction code }
  3026. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3027. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3028. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3029. bytes:=bytes or ord(insentry^.code[4]);
  3030. { set Rn and Rd }
  3031. bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
  3032. if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
  3033. begin
  3034. { set offset }
  3035. offset:=0;
  3036. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  3037. if assigned(currsym) then
  3038. offset:=currsym.offset-insoffset-8;
  3039. offset:=offset+oper[0]^.ref^.offset;
  3040. if offset>=0 then
  3041. begin
  3042. { set U flag }
  3043. bytes:=bytes or (1 shl 23);
  3044. bytes:=bytes or offset
  3045. end
  3046. else
  3047. begin
  3048. offset:=-offset;
  3049. bytes:=bytes or offset
  3050. end;
  3051. end
  3052. else
  3053. begin
  3054. bytes:=bytes or (1 shl 25);
  3055. { set U flag }
  3056. if oper[0]^.ref^.signindex>=0 then
  3057. bytes:=bytes or (1 shl 23);
  3058. bytes:=bytes or getsupreg(oper[0]^.ref^.index);
  3059. { set shift }
  3060. with oper[0]^.ref^ do
  3061. if shiftmode<>SM_None then
  3062. begin
  3063. bytes:=bytes or ((shiftimm and $1F) shl 7);
  3064. if shiftmode<>SM_RRX then
  3065. bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
  3066. else
  3067. bytes:=bytes or (3 shl 5);
  3068. end
  3069. end;
  3070. end;
  3071. #$26: // LDM/STM
  3072. begin
  3073. { set instruction code }
  3074. bytes:=bytes or (ord(insentry^.code[1]) shl 20);
  3075. if ops>1 then
  3076. begin
  3077. if oper[0]^.typ=top_ref then
  3078. begin
  3079. { set W bit }
  3080. if oper[0]^.ref^.addressmode=AM_PREINDEXED then
  3081. bytes:=bytes or (1 shl 21);
  3082. { set Rn }
  3083. bytes:=bytes or (getsupreg(oper[0]^.ref^.index) shl 16);
  3084. end
  3085. else { typ=top_reg }
  3086. begin
  3087. { set Rn }
  3088. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  3089. end;
  3090. if oper[1]^.usermode then
  3091. begin
  3092. if (oper[0]^.typ=top_ref) then
  3093. begin
  3094. if (opcode=A_LDM) and
  3095. (RS_PC in oper[1]^.regset^) then
  3096. begin
  3097. // Valid exception return
  3098. end
  3099. else
  3100. Message(asmw_e_invalid_opcode_and_operands);
  3101. end;
  3102. bytes:=bytes or (1 shl 22);
  3103. end;
  3104. { reglist }
  3105. bytes:=bytes or MakeRegList(oper[1]^.regset^);
  3106. end
  3107. else
  3108. begin
  3109. { push/pop }
  3110. { Set W and Rn to SP }
  3111. if opcode=A_PUSH then
  3112. bytes:=bytes or (1 shl 21);
  3113. bytes:=bytes or ($D shl 16);
  3114. { reglist }
  3115. bytes:=bytes or MakeRegList(oper[0]^.regset^);
  3116. end;
  3117. { set P bit }
  3118. if (opcode=A_LDM) and (oppostfix in [PF_ED,PF_EA,PF_IB,PF_DB])
  3119. or (opcode=A_STM) and (oppostfix in [PF_FA,PF_FD,PF_IB,PF_DB])
  3120. or (opcode=A_PUSH) then
  3121. bytes:=bytes or (1 shl 24);
  3122. { set U bit }
  3123. if (opcode=A_LDM) and (oppostfix in [PF_None,PF_ED,PF_FD,PF_IB,PF_IA])
  3124. or (opcode=A_STM) and (oppostfix in [PF_None,PF_FA,PF_EA,PF_IB,PF_IA])
  3125. or (opcode=A_POP) then
  3126. bytes:=bytes or (1 shl 23);
  3127. end;
  3128. #$27: // SWP/SWPB
  3129. begin
  3130. { set instruction code }
  3131. bytes:=bytes or (ord(insentry^.code[1]) shl 20);
  3132. bytes:=bytes or (ord(insentry^.code[2]) shl 4);
  3133. { set regs }
  3134. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3135. bytes:=bytes or getsupreg(oper[1]^.reg);
  3136. if ops=3 then
  3137. bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
  3138. end;
  3139. #$28: // BX/BLX
  3140. begin
  3141. { set instruction code }
  3142. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3143. { set offset }
  3144. if oper[0]^.typ=top_const then
  3145. bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
  3146. else
  3147. begin
  3148. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  3149. if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
  3150. begin
  3151. bytes:=bytes or $fffffe; // TODO: Not sure this is right, but it matches the output of gas
  3152. objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
  3153. end
  3154. else
  3155. begin
  3156. offset:=((currsym.offset-insoffset-8) and $3fffffe);
  3157. { Turn BLX into BL if the destination isn't odd, could happen with recursion }
  3158. if not odd(offset shr 1) then
  3159. bytes:=(bytes and $EB000000) or $EB000000;
  3160. bytes:=bytes or ((offset shr 2) and $ffffff);
  3161. bytes:=bytes or ((offset shr 1) and $1) shl 24;
  3162. end;
  3163. end;
  3164. end;
  3165. #$29: // SUB
  3166. begin
  3167. { set instruction code }
  3168. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3169. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3170. { set regs }
  3171. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3172. { set S if necessary }
  3173. if oppostfix=PF_S then
  3174. bytes:=bytes or (1 shl 20);
  3175. end;
  3176. #$2A:
  3177. begin
  3178. { set instruction code }
  3179. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3180. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3181. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3182. bytes:=bytes or ord(insentry^.code[4]);
  3183. { set opers }
  3184. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3185. if opcode in [A_SSAT, A_SSAT16] then
  3186. bytes:=bytes or (((oper[1]^.val-1) and $1F) shl 16)
  3187. else
  3188. bytes:=bytes or ((oper[1]^.val and $1F) shl 16);
  3189. bytes:=bytes or getsupreg(oper[2]^.reg);
  3190. if (ops>3) and
  3191. (oper[3]^.typ=top_shifterop) and
  3192. (oper[3]^.shifterop^.rs=NR_NO) then
  3193. begin
  3194. bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
  3195. if oper[3]^.shifterop^.shiftmode=SM_ASR then
  3196. bytes:=bytes or (1 shl 6)
  3197. else if oper[3]^.shifterop^.shiftmode<>SM_LSL then
  3198. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  3199. end;
  3200. end;
  3201. #$2B: // SETEND
  3202. begin
  3203. { set instruction code }
  3204. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3205. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3206. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3207. bytes:=bytes or ord(insentry^.code[4]);
  3208. { set endian specifier }
  3209. bytes:=bytes or ((oper[0]^.val and 1) shl 9);
  3210. end;
  3211. #$2C: // MOVW
  3212. begin
  3213. { set instruction code }
  3214. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3215. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3216. { set destination }
  3217. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3218. { set imm }
  3219. bytes:=bytes or (oper[1]^.val and $FFF);
  3220. bytes:=bytes or ((oper[1]^.val and $F000) shl 4);
  3221. end;
  3222. #$2D: // BFX
  3223. begin
  3224. { set instruction code }
  3225. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3226. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3227. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3228. bytes:=bytes or ord(insentry^.code[4]);
  3229. if ops=3 then
  3230. begin
  3231. msb:=(oper[1]^.val+oper[2]^.val-1);
  3232. { set destination }
  3233. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3234. { set immediates }
  3235. bytes:=bytes or ((oper[1]^.val and $1F) shl 7);
  3236. bytes:=bytes or ((msb and $1F) shl 16);
  3237. end
  3238. else
  3239. begin
  3240. if opcode in [A_BFC,A_BFI] then
  3241. msb:=(oper[2]^.val+oper[3]^.val-1)
  3242. else
  3243. msb:=oper[3]^.val-1;
  3244. { set destination }
  3245. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3246. bytes:=bytes or getsupreg(oper[1]^.reg);
  3247. { set immediates }
  3248. bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
  3249. bytes:=bytes or ((msb and $1F) shl 16);
  3250. end;
  3251. end;
  3252. #$2E: // Cache stuff
  3253. begin
  3254. { set instruction code }
  3255. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3256. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3257. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3258. bytes:=bytes or ord(insentry^.code[4]);
  3259. { set code }
  3260. bytes:=bytes or (oper[0]^.val and $F);
  3261. end;
  3262. #$2F: // Nop
  3263. begin
  3264. { set instruction code }
  3265. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3266. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3267. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3268. bytes:=bytes or ord(insentry^.code[4]);
  3269. end;
  3270. #$30: // Shifts
  3271. begin
  3272. { set instruction code }
  3273. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3274. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3275. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3276. bytes:=bytes or ord(insentry^.code[4]);
  3277. { set destination }
  3278. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3279. bytes:=bytes or getsupreg(oper[1]^.reg);
  3280. if ops>2 then
  3281. begin
  3282. { set shift }
  3283. if oper[2]^.typ=top_reg then
  3284. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 8)
  3285. else
  3286. bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
  3287. end;
  3288. { set S if necessary }
  3289. if oppostfix=PF_S then
  3290. bytes:=bytes or (1 shl 20);
  3291. end;
  3292. #$31: // BKPT
  3293. begin
  3294. { set instruction code }
  3295. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3296. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3297. bytes:=bytes or (ord(insentry^.code[3]) shl 0);
  3298. { set imm }
  3299. bytes:=bytes or (oper[0]^.val and $FFF0) shl 4;
  3300. bytes:=bytes or (oper[0]^.val and $F);
  3301. end;
  3302. #$32: // CLZ/REV
  3303. begin
  3304. { set instruction code }
  3305. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3306. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3307. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3308. bytes:=bytes or ord(insentry^.code[4]);
  3309. { set regs }
  3310. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3311. bytes:=bytes or getsupreg(oper[1]^.reg);
  3312. end;
  3313. #$33:
  3314. begin
  3315. { set instruction code }
  3316. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3317. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3318. { set regs }
  3319. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3320. if oper[1]^.typ=top_ref then
  3321. begin
  3322. { set offset }
  3323. offset:=0;
  3324. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  3325. if assigned(currsym) then
  3326. offset:=currsym.offset-insoffset-8;
  3327. offset:=offset+oper[1]^.ref^.offset;
  3328. if offset>=0 then
  3329. begin
  3330. { set U flag }
  3331. bytes:=bytes or (1 shl 23);
  3332. bytes:=bytes or offset
  3333. end
  3334. else
  3335. begin
  3336. bytes:=bytes or (1 shl 22);
  3337. offset:=-offset;
  3338. bytes:=bytes or offset
  3339. end;
  3340. end
  3341. else
  3342. begin
  3343. if is_shifter_const(oper[1]^.val,r) then
  3344. begin
  3345. setshifterop(1);
  3346. bytes:=bytes or (1 shl 23);
  3347. end
  3348. else
  3349. begin
  3350. bytes:=bytes or (1 shl 22);
  3351. oper[1]^.val:=-oper[1]^.val;
  3352. setshifterop(1);
  3353. end;
  3354. end;
  3355. end;
  3356. #$40,#$90: // VMOV
  3357. begin
  3358. { set instruction code }
  3359. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3360. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3361. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3362. bytes:=bytes or ord(insentry^.code[4]);
  3363. { set regs }
  3364. Rd:=0;
  3365. Rn:=0;
  3366. Rm:=0;
  3367. case oppostfix of
  3368. PF_None:
  3369. begin
  3370. if ops=4 then
  3371. begin
  3372. if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
  3373. (getregtype(oper[2]^.reg)=R_INTREGISTER) then
  3374. begin
  3375. Rd:=getmmreg(oper[0]^.reg);
  3376. Rm:=getsupreg(oper[2]^.reg);
  3377. Rn:=getsupreg(oper[3]^.reg);
  3378. end
  3379. else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
  3380. (getregtype(oper[2]^.reg)=R_MMREGISTER) then
  3381. begin
  3382. Rm:=getsupreg(oper[0]^.reg);
  3383. Rn:=getsupreg(oper[1]^.reg);
  3384. Rd:=getmmreg(oper[2]^.reg);
  3385. end
  3386. else
  3387. message(asmw_e_invalid_opcode_and_operands);
  3388. bytes:=bytes or (((Rd and $1E) shr 1) shl 0);
  3389. bytes:=bytes or ((Rd and $1) shl 5);
  3390. bytes:=bytes or (Rm shl 12);
  3391. bytes:=bytes or (Rn shl 16);
  3392. end
  3393. else if ops=3 then
  3394. begin
  3395. if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
  3396. (getregtype(oper[1]^.reg)=R_INTREGISTER) then
  3397. begin
  3398. Rd:=getmmreg(oper[0]^.reg);
  3399. Rm:=getsupreg(oper[1]^.reg);
  3400. Rn:=getsupreg(oper[2]^.reg);
  3401. end
  3402. else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
  3403. (getregtype(oper[2]^.reg)=R_MMREGISTER) then
  3404. begin
  3405. Rm:=getsupreg(oper[0]^.reg);
  3406. Rn:=getsupreg(oper[1]^.reg);
  3407. Rd:=getmmreg(oper[2]^.reg);
  3408. end
  3409. else
  3410. message(asmw_e_invalid_opcode_and_operands);
  3411. bytes:=bytes or ((Rd and $F) shl 0);
  3412. bytes:=bytes or ((Rd and $10) shl 1);
  3413. bytes:=bytes or (Rm shl 12);
  3414. bytes:=bytes or (Rn shl 16);
  3415. end
  3416. else if ops=2 then
  3417. begin
  3418. if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
  3419. (getregtype(oper[1]^.reg)=R_INTREGISTER) then
  3420. begin
  3421. Rd:=getmmreg(oper[0]^.reg);
  3422. Rm:=getsupreg(oper[1]^.reg);
  3423. end
  3424. else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
  3425. (getregtype(oper[1]^.reg)=R_MMREGISTER) then
  3426. begin
  3427. Rm:=getsupreg(oper[0]^.reg);
  3428. Rd:=getmmreg(oper[1]^.reg);
  3429. end
  3430. else
  3431. message(asmw_e_invalid_opcode_and_operands);
  3432. bytes:=bytes or (((Rd and $1E) shr 1) shl 16);
  3433. bytes:=bytes or ((Rd and $1) shl 7);
  3434. bytes:=bytes or (Rm shl 12);
  3435. end;
  3436. end;
  3437. PF_F32:
  3438. begin
  3439. if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
  3440. (getregtype(oper[1]^.reg)<>R_MMREGISTER) then
  3441. Message(asmw_e_invalid_opcode_and_operands);
  3442. Rd:=getmmreg(oper[0]^.reg);
  3443. Rm:=getmmreg(oper[1]^.reg);
  3444. bytes:=bytes or (((Rd and $1E) shr 1) shl 12);
  3445. bytes:=bytes or ((Rd and $1) shl 22);
  3446. bytes:=bytes or (((Rm and $1E) shr 1) shl 0);
  3447. bytes:=bytes or ((Rm and $1) shl 5);
  3448. end;
  3449. PF_F64:
  3450. begin
  3451. if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
  3452. (getregtype(oper[1]^.reg)<>R_MMREGISTER) then
  3453. Message(asmw_e_invalid_opcode_and_operands);
  3454. Rd:=getmmreg(oper[0]^.reg);
  3455. Rm:=getmmreg(oper[1]^.reg);
  3456. bytes:=bytes or (1 shl 8);
  3457. bytes:=bytes or ((Rd and $F) shl 12);
  3458. bytes:=bytes or (((Rd and $10) shr 4) shl 22);
  3459. bytes:=bytes or (Rm and $F);
  3460. bytes:=bytes or ((Rm and $10) shl 1);
  3461. end;
  3462. end;
  3463. end;
  3464. #$41,#$91: // VMRS/VMSR
  3465. begin
  3466. { set instruction code }
  3467. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3468. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3469. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3470. bytes:=bytes or ord(insentry^.code[4]);
  3471. { set regs }
  3472. if (opcode=A_VMRS) or
  3473. (opcode=A_FMRX) then
  3474. begin
  3475. case oper[1]^.reg of
  3476. NR_FPSID: Rn:=$0;
  3477. NR_FPSCR: Rn:=$1;
  3478. NR_MVFR1: Rn:=$6;
  3479. NR_MVFR0: Rn:=$7;
  3480. NR_FPEXC: Rn:=$8;
  3481. else
  3482. Rn:=0;
  3483. message(asmw_e_invalid_opcode_and_operands);
  3484. end;
  3485. bytes:=bytes or (Rn shl 16);
  3486. if oper[0]^.reg=NR_APSR_nzcv then
  3487. bytes:=bytes or ($F shl 12)
  3488. else
  3489. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3490. end
  3491. else
  3492. begin
  3493. case oper[0]^.reg of
  3494. NR_FPSID: Rn:=$0;
  3495. NR_FPSCR: Rn:=$1;
  3496. NR_FPEXC: Rn:=$8;
  3497. else
  3498. Rn:=0;
  3499. message(asmw_e_invalid_opcode_and_operands);
  3500. end;
  3501. bytes:=bytes or (Rn shl 16);
  3502. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
  3503. end;
  3504. end;
  3505. #$42,#$92: // VMUL
  3506. begin
  3507. { set instruction code }
  3508. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3509. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3510. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3511. bytes:=bytes or ord(insentry^.code[4]);
  3512. { set regs }
  3513. if ops=3 then
  3514. begin
  3515. Rd:=getmmreg(oper[0]^.reg);
  3516. Rn:=getmmreg(oper[1]^.reg);
  3517. Rm:=getmmreg(oper[2]^.reg);
  3518. end
  3519. else if ops=1 then
  3520. begin
  3521. Rd:=getmmreg(oper[0]^.reg);
  3522. Rn:=0;
  3523. Rm:=0;
  3524. end
  3525. else if oper[1]^.typ=top_const then
  3526. begin
  3527. Rd:=getmmreg(oper[0]^.reg);
  3528. Rn:=0;
  3529. Rm:=0;
  3530. end
  3531. else
  3532. begin
  3533. Rd:=getmmreg(oper[0]^.reg);
  3534. Rn:=0;
  3535. Rm:=getmmreg(oper[1]^.reg);
  3536. end;
  3537. if (oppostfix=PF_F32) or (insentry^.code[5]=#1) then
  3538. begin
  3539. D:=rd and $1; Rd:=Rd shr 1;
  3540. N:=rn and $1; Rn:=Rn shr 1;
  3541. M:=rm and $1; Rm:=Rm shr 1;
  3542. end
  3543. else
  3544. begin
  3545. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3546. N:=(rn shr 4) and $1; Rn:=Rn and $F;
  3547. M:=(rm shr 4) and $1; Rm:=Rm and $F;
  3548. bytes:=bytes or (1 shl 8);
  3549. end;
  3550. bytes:=bytes or (Rd shl 12);
  3551. bytes:=bytes or (Rn shl 16);
  3552. bytes:=bytes or (Rm shl 0);
  3553. bytes:=bytes or (D shl 22);
  3554. bytes:=bytes or (N shl 7);
  3555. bytes:=bytes or (M shl 5);
  3556. end;
  3557. #$43,#$93: // VCVT
  3558. begin
  3559. { set instruction code }
  3560. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3561. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3562. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3563. bytes:=bytes or ord(insentry^.code[4]);
  3564. { set regs }
  3565. Rd:=getmmreg(oper[0]^.reg);
  3566. Rm:=getmmreg(oper[1]^.reg);
  3567. if (ops=2) and
  3568. (oppostfix in [PF_F32F64,PF_F64F32]) then
  3569. begin
  3570. if oppostfix=PF_F32F64 then
  3571. begin
  3572. bytes:=bytes or (1 shl 8);
  3573. D:=rd and $1; Rd:=Rd shr 1;
  3574. M:=(rm shr 4) and $1; Rm:=Rm and $F;
  3575. end
  3576. else
  3577. begin
  3578. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3579. M:=rm and $1; Rm:=Rm shr 1;
  3580. end;
  3581. bytes:=bytes and $FFF0FFFF;
  3582. bytes:=bytes or ($7 shl 16);
  3583. bytes:=bytes or (Rd shl 12);
  3584. bytes:=bytes or (Rm shl 0);
  3585. bytes:=bytes or (D shl 22);
  3586. bytes:=bytes or (M shl 5);
  3587. end
  3588. else if (ops=2) and
  3589. (oppostfix=PF_None) then
  3590. begin
  3591. d:=0;
  3592. case getsubreg(oper[0]^.reg) of
  3593. R_SUBNONE:
  3594. rd:=getsupreg(oper[0]^.reg);
  3595. R_SUBFS:
  3596. begin
  3597. rd:=getmmreg(oper[0]^.reg);
  3598. d:=rd and 1;
  3599. rd:=rd shr 1;
  3600. end;
  3601. R_SUBFD:
  3602. begin
  3603. rd:=getmmreg(oper[0]^.reg);
  3604. d:=(rd shr 4) and 1;
  3605. rd:=rd and $F;
  3606. end;
  3607. end;
  3608. m:=0;
  3609. case getsubreg(oper[1]^.reg) of
  3610. R_SUBNONE:
  3611. rm:=getsupreg(oper[1]^.reg);
  3612. R_SUBFS:
  3613. begin
  3614. rm:=getmmreg(oper[1]^.reg);
  3615. m:=rm and 1;
  3616. rm:=rm shr 1;
  3617. end;
  3618. R_SUBFD:
  3619. begin
  3620. rm:=getmmreg(oper[1]^.reg);
  3621. m:=(rm shr 4) and 1;
  3622. rm:=rm and $F;
  3623. end;
  3624. end;
  3625. bytes:=bytes or (Rd shl 12);
  3626. bytes:=bytes or (Rm shl 0);
  3627. bytes:=bytes or (D shl 22);
  3628. bytes:=bytes or (M shl 5);
  3629. end
  3630. else if ops=2 then
  3631. begin
  3632. case oppostfix of
  3633. PF_S32F64,
  3634. PF_U32F64,
  3635. PF_F64S32,
  3636. PF_F64U32:
  3637. bytes:=bytes or (1 shl 8);
  3638. end;
  3639. if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64] then
  3640. begin
  3641. case oppostfix of
  3642. PF_S32F64,
  3643. PF_S32F32:
  3644. bytes:=bytes or (1 shl 16);
  3645. end;
  3646. bytes:=bytes or (1 shl 18);
  3647. D:=rd and $1; Rd:=Rd shr 1;
  3648. if oppostfix in [PF_S32F64,PF_U32F64] then
  3649. begin
  3650. M:=(rm shr 4) and $1; Rm:=Rm and $F;
  3651. end
  3652. else
  3653. begin
  3654. M:=rm and $1; Rm:=Rm shr 1;
  3655. end;
  3656. end
  3657. else
  3658. begin
  3659. case oppostfix of
  3660. PF_F64S32,
  3661. PF_F32S32:
  3662. bytes:=bytes or (1 shl 7);
  3663. else
  3664. bytes:=bytes and $FFFFFF7F;
  3665. end;
  3666. M:=rm and $1; Rm:=Rm shr 1;
  3667. if oppostfix in [PF_F64S32,PF_F64U32] then
  3668. begin
  3669. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3670. end
  3671. else
  3672. begin
  3673. D:=rd and $1; Rd:=Rd shr 1;
  3674. end
  3675. end;
  3676. bytes:=bytes or (Rd shl 12);
  3677. bytes:=bytes or (Rm shl 0);
  3678. bytes:=bytes or (D shl 22);
  3679. bytes:=bytes or (M shl 5);
  3680. end
  3681. else
  3682. begin
  3683. if rd<>rm then
  3684. message(asmw_e_invalid_opcode_and_operands);
  3685. case oppostfix of
  3686. PF_S32F32,PF_U32F32,
  3687. PF_F32S32,PF_F32U32,
  3688. PF_S32F64,PF_U32F64,
  3689. PF_F64S32,PF_F64U32:
  3690. begin
  3691. if not (oper[2]^.val in [1..32]) then
  3692. message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 1-32');
  3693. bytes:=bytes or (1 shl 7);
  3694. rn:=32;
  3695. end;
  3696. PF_S16F64,PF_U16F64,
  3697. PF_F64S16,PF_F64U16,
  3698. PF_S16F32,PF_U16F32,
  3699. PF_F32S16,PF_F32U16:
  3700. begin
  3701. if not (oper[2]^.val in [0..16]) then
  3702. message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 0-16');
  3703. rn:=16;
  3704. end;
  3705. else
  3706. Rn:=0;
  3707. message(asmw_e_invalid_opcode_and_operands);
  3708. end;
  3709. case oppostfix of
  3710. PF_S16F64,PF_U16F64,
  3711. PF_S32F64,PF_U32F64,
  3712. PF_F64S16,PF_F64U16,
  3713. PF_F64S32,PF_F64U32:
  3714. begin
  3715. bytes:=bytes or (1 shl 8);
  3716. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3717. end;
  3718. else
  3719. begin
  3720. D:=rd and $1; Rd:=Rd shr 1;
  3721. end;
  3722. end;
  3723. case oppostfix of
  3724. PF_U16F64,PF_U16F32,
  3725. PF_U32F32,PF_U32F64,
  3726. PF_F64U16,PF_F32U16,
  3727. PF_F32U32,PF_F64U32:
  3728. bytes:=bytes or (1 shl 16);
  3729. end;
  3730. if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64,PF_S16F32,PF_S16F64,PF_U16F32,PF_U16F64] then
  3731. bytes:=bytes or (1 shl 18);
  3732. bytes:=bytes or (Rd shl 12);
  3733. bytes:=bytes or (D shl 22);
  3734. rn:=rn-oper[2]^.val;
  3735. bytes:=bytes or ((rn and $1) shl 5);
  3736. bytes:=bytes or ((rn and $1E) shr 1);
  3737. end;
  3738. end;
  3739. #$44,#$94: // VLDM/VSTM/VPUSH/VPOP
  3740. begin
  3741. { set instruction code }
  3742. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3743. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3744. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3745. { set regs }
  3746. if ops=2 then
  3747. begin
  3748. if oper[0]^.typ=top_ref then
  3749. begin
  3750. Rn:=getsupreg(oper[0]^.ref^.index);
  3751. if oper[0]^.ref^.addressmode<>AM_OFFSET then
  3752. begin
  3753. { set W }
  3754. bytes:=bytes or (1 shl 21);
  3755. end
  3756. else if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
  3757. message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
  3758. end
  3759. else
  3760. begin
  3761. Rn:=getsupreg(oper[0]^.reg);
  3762. if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
  3763. message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
  3764. end;
  3765. bytes:=bytes or (Rn shl 16);
  3766. { Set PU bits }
  3767. case oppostfix of
  3768. PF_None,
  3769. PF_IA,PF_IAS,PF_IAD,PF_IAX:
  3770. bytes:=bytes or (1 shl 23);
  3771. PF_DB,PF_DBS,PF_DBD,PF_DBX:
  3772. bytes:=bytes or (2 shl 23);
  3773. end;
  3774. case oppostfix of
  3775. PF_IAX,PF_DBX,PF_FDX,PF_EAX:
  3776. begin
  3777. bytes:=bytes or (1 shl 8);
  3778. bytes:=bytes or (1 shl 0); // Offset is odd
  3779. end;
  3780. end;
  3781. dp_operation:=(oper[1]^.subreg=R_SUBFD);
  3782. if oper[1]^.regset^=[] then
  3783. message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
  3784. rd:=0;
  3785. for r:=0 to 31 do
  3786. if r in oper[1]^.regset^ then
  3787. begin
  3788. rd:=r;
  3789. break;
  3790. end;
  3791. rn:=32-rd;
  3792. for r:=rd+1 to 31 do
  3793. if not(r in oper[1]^.regset^) then
  3794. begin
  3795. rn:=r-rd;
  3796. break;
  3797. end;
  3798. if dp_operation then
  3799. begin
  3800. bytes:=bytes or (1 shl 8);
  3801. bytes:=bytes or (rn*2);
  3802. bytes:=bytes or ((rd and $F) shl 12);
  3803. bytes:=bytes or (((rd and $10) shr 4) shl 22);
  3804. end
  3805. else
  3806. begin
  3807. bytes:=bytes or rn;
  3808. bytes:=bytes or ((rd and $1) shl 22);
  3809. bytes:=bytes or (((rd and $1E) shr 1) shl 12);
  3810. end;
  3811. end
  3812. else { VPUSH/VPOP }
  3813. begin
  3814. dp_operation:=(oper[0]^.subreg=R_SUBFD);
  3815. if oper[0]^.regset^=[] then
  3816. message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
  3817. rd:=0;
  3818. for r:=0 to 31 do
  3819. if r in oper[0]^.regset^ then
  3820. begin
  3821. rd:=r;
  3822. break;
  3823. end;
  3824. rn:=32-rd;
  3825. for r:=rd+1 to 31 do
  3826. if not(r in oper[0]^.regset^) then
  3827. begin
  3828. rn:=r-rd;
  3829. break;
  3830. end;
  3831. if dp_operation then
  3832. begin
  3833. bytes:=bytes or (1 shl 8);
  3834. bytes:=bytes or (rn*2);
  3835. bytes:=bytes or ((rd and $F) shl 12);
  3836. bytes:=bytes or (((rd and $10) shr 4) shl 22);
  3837. end
  3838. else
  3839. begin
  3840. bytes:=bytes or rn;
  3841. bytes:=bytes or ((rd and $1) shl 22);
  3842. bytes:=bytes or (((rd and $1E) shr 1) shl 12);
  3843. end;
  3844. end;
  3845. end;
  3846. #$45,#$95: // VLDR/VSTR
  3847. begin
  3848. { set instruction code }
  3849. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3850. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3851. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3852. { set regs }
  3853. rd:=getmmreg(oper[0]^.reg);
  3854. if getsubreg(oper[0]^.reg)=R_SUBFD then
  3855. begin
  3856. bytes:=bytes or (1 shl 8);
  3857. bytes:=bytes or ((rd and $F) shl 12);
  3858. bytes:=bytes or (((rd and $10) shr 4) shl 22);
  3859. end
  3860. else
  3861. begin
  3862. bytes:=bytes or (((rd and $1E) shr 1) shl 12);
  3863. bytes:=bytes or ((rd and $1) shl 22);
  3864. end;
  3865. { set ref }
  3866. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  3867. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  3868. begin
  3869. { set offset }
  3870. offset:=0;
  3871. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  3872. if assigned(currsym) then
  3873. offset:=currsym.offset-insoffset-8;
  3874. offset:=offset+oper[1]^.ref^.offset;
  3875. offset:=offset div 4;
  3876. if offset>=0 then
  3877. begin
  3878. { set U flag }
  3879. bytes:=bytes or (1 shl 23);
  3880. bytes:=bytes or offset
  3881. end
  3882. else
  3883. begin
  3884. offset:=-offset;
  3885. bytes:=bytes or offset
  3886. end;
  3887. end
  3888. else
  3889. message(asmw_e_invalid_opcode_and_operands);
  3890. end;
  3891. #$46: { System instructions }
  3892. begin
  3893. { set instruction code }
  3894. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3895. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3896. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3897. { set regs }
  3898. if (oper[0]^.typ=top_modeflags) then
  3899. begin
  3900. if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 8);
  3901. if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
  3902. if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
  3903. end;
  3904. if (ops=2) then
  3905. bytes:=bytes or (oper[1]^.val and $1F)
  3906. else if (ops=1) and
  3907. (oper[0]^.typ=top_const) then
  3908. bytes:=bytes or (oper[0]^.val and $1F);
  3909. end;
  3910. #$60: { Thumb }
  3911. begin
  3912. bytelen:=2;
  3913. bytes:=0;
  3914. { set opcode }
  3915. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  3916. bytes:=bytes or ord(insentry^.code[2]);
  3917. { set regs }
  3918. if ops=2 then
  3919. begin
  3920. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  3921. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
  3922. if (oper[1]^.typ=top_reg) then
  3923. bytes:=bytes or ((getsupreg(oper[1]^.reg) and $7) shl 6)
  3924. else
  3925. bytes:=bytes or ((oper[1]^.val and $1F) shl 6);
  3926. end
  3927. else if ops=3 then
  3928. begin
  3929. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  3930. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  3931. if (oper[2]^.typ=top_reg) then
  3932. bytes:=bytes or ((getsupreg(oper[2]^.reg) and $7) shl 6)
  3933. else
  3934. bytes:=bytes or ((oper[2]^.val and $1F) shl 6);
  3935. end
  3936. else if ops=1 then
  3937. begin
  3938. if oper[0]^.typ=top_const then
  3939. bytes:=bytes or (oper[0]^.val and $FF);
  3940. end;
  3941. end;
  3942. #$61: { Thumb }
  3943. begin
  3944. bytelen:=2;
  3945. bytes:=0;
  3946. { set opcode }
  3947. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  3948. bytes:=bytes or ord(insentry^.code[2]);
  3949. { set regs }
  3950. if ops=2 then
  3951. begin
  3952. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  3953. bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
  3954. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  3955. end
  3956. else if ops=1 then
  3957. begin
  3958. if oper[0]^.typ=top_const then
  3959. bytes:=bytes or (oper[0]^.val and $FF);
  3960. end;
  3961. end;
  3962. #$62..#$63: { Thumb branches }
  3963. begin
  3964. bytelen:=2;
  3965. bytes:=0;
  3966. { set opcode }
  3967. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  3968. bytes:=bytes or ord(insentry^.code[2]);
  3969. if insentry^.code[0]=#$63 then
  3970. bytes:=bytes or (CondVal[condition] shl 8);
  3971. if oper[0]^.typ=top_const then
  3972. begin
  3973. if insentry^.code[0]=#$63 then
  3974. bytes:=bytes or (((oper[0]^.val shr 1)-1) and $FF)
  3975. else
  3976. bytes:=bytes or (((oper[0]^.val shr 1)-1) and $3FF);
  3977. end
  3978. else if oper[0]^.typ=top_reg then
  3979. begin
  3980. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
  3981. end
  3982. else if oper[0]^.typ=top_ref then
  3983. begin
  3984. offset:=0;
  3985. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  3986. if assigned(currsym) then
  3987. offset:=currsym.offset-insoffset-8;
  3988. offset:=offset+oper[0]^.ref^.offset;
  3989. if insentry^.code[0]=#$63 then
  3990. bytes:=bytes or (((offset+4) shr 1) and $FF)
  3991. else
  3992. bytes:=bytes or (((offset+4) shr 1) and $7FF);
  3993. end
  3994. end;
  3995. #$64: { Thumb: Special encodings }
  3996. begin
  3997. bytelen:=2;
  3998. bytes:=0;
  3999. { set opcode }
  4000. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4001. bytes:=bytes or ord(insentry^.code[2]);
  4002. case opcode of
  4003. A_SUB:
  4004. begin
  4005. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4006. if (ops=3) and
  4007. (oper[2]^.typ=top_const) then
  4008. bytes:=bytes or ((oper[2]^.val shr 2) and $7F)
  4009. else if (ops=2) and
  4010. (oper[1]^.typ=top_const) then
  4011. bytes:=bytes or ((oper[1]^.val shr 2) and $7F);
  4012. end;
  4013. A_MUL:
  4014. if (ops in [2,3]) then
  4015. begin
  4016. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4017. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  4018. end;
  4019. A_ADD:
  4020. begin
  4021. if ops=2 then
  4022. begin
  4023. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4024. bytes:=bytes or (getsupreg(oper[1]^.reg) shl $3);
  4025. end
  4026. else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
  4027. (oper[2]^.typ=top_const) then
  4028. begin
  4029. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7) shl 8;
  4030. bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
  4031. end
  4032. else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
  4033. (oper[2]^.typ=top_reg) then
  4034. begin
  4035. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4036. bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
  4037. end
  4038. else
  4039. begin
  4040. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4041. bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
  4042. end;
  4043. end;
  4044. end;
  4045. end;
  4046. #$65: { Thumb load/store }
  4047. begin
  4048. bytelen:=2;
  4049. bytes:=0;
  4050. { set opcode }
  4051. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4052. bytes:=bytes or ord(insentry^.code[2]);
  4053. { set regs }
  4054. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4055. bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
  4056. bytes:=bytes or (getsupreg(oper[1]^.ref^.index) shl 6);
  4057. end;
  4058. #$66: { Thumb load/store }
  4059. begin
  4060. bytelen:=2;
  4061. bytes:=0;
  4062. { set opcode }
  4063. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4064. bytes:=bytes or ord(insentry^.code[2]);
  4065. { set regs }
  4066. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4067. bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
  4068. { set offset }
  4069. offset:=0;
  4070. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4071. if assigned(currsym) then
  4072. offset:=currsym.offset-(insoffset+4) and (not longword(3));
  4073. offset:=(offset+oper[1]^.ref^.offset);
  4074. bytes:=bytes or (((offset shr ord(insentry^.code[3])) and $1F) shl 6);
  4075. end;
  4076. #$67: { Thumb load/store }
  4077. begin
  4078. bytelen:=2;
  4079. bytes:=0;
  4080. { set opcode }
  4081. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4082. bytes:=bytes or ord(insentry^.code[2]);
  4083. { set regs }
  4084. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4085. if oper[1]^.typ=top_ref then
  4086. begin
  4087. { set offset }
  4088. offset:=0;
  4089. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4090. if assigned(currsym) then
  4091. offset:=currsym.offset-(insoffset+4) and (not longword(3));
  4092. offset:=(offset+oper[1]^.ref^.offset);
  4093. bytes:=bytes or ((offset shr ord(insentry^.code[3])) and $FF);
  4094. end
  4095. else
  4096. bytes:=bytes or ((oper[1]^.val shr ord(insentry^.code[3])) and $FF);
  4097. end;
  4098. #$68: { Thumb CB[N]Z }
  4099. begin
  4100. bytelen:=2;
  4101. bytes:=0;
  4102. { set opcode }
  4103. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4104. { set opers }
  4105. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4106. if oper[1]^.typ=top_ref then
  4107. begin
  4108. offset:=0;
  4109. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4110. if assigned(currsym) then
  4111. offset:=currsym.offset-insoffset-8;
  4112. offset:=offset+oper[1]^.ref^.offset;
  4113. offset:=offset div 2;
  4114. end
  4115. else
  4116. offset:=oper[1]^.val div 2;
  4117. bytes:=bytes or ((offset) and $1F) shl 3;
  4118. bytes:=bytes or ((offset shr 5) and 1) shl 9;
  4119. end;
  4120. #$69: { Thumb: Push/Pop/Stm/Ldm }
  4121. begin
  4122. bytelen:=2;
  4123. bytes:=0;
  4124. { set opcode }
  4125. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4126. case opcode of
  4127. A_PUSH:
  4128. begin
  4129. for r:=0 to 7 do
  4130. if r in oper[0]^.regset^ then
  4131. bytes:=bytes or (1 shl r);
  4132. if RS_R14 in oper[0]^.regset^ then
  4133. bytes:=bytes or (1 shl 8);
  4134. end;
  4135. A_POP:
  4136. begin
  4137. for r:=0 to 7 do
  4138. if r in oper[0]^.regset^ then
  4139. bytes:=bytes or (1 shl r);
  4140. if RS_R15 in oper[0]^.regset^ then
  4141. bytes:=bytes or (1 shl 8);
  4142. end;
  4143. A_STM:
  4144. begin
  4145. for r:=0 to 7 do
  4146. if r in oper[1]^.regset^ then
  4147. bytes:=bytes or (1 shl r);
  4148. if oper[0]^.typ=top_ref then
  4149. bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 8)
  4150. else
  4151. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4152. end;
  4153. A_LDM:
  4154. begin
  4155. for r:=0 to 7 do
  4156. if r in oper[1]^.regset^ then
  4157. bytes:=bytes or (1 shl r);
  4158. if oper[0]^.typ=top_ref then
  4159. bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 8)
  4160. else
  4161. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4162. end;
  4163. end;
  4164. end;
  4165. #$6A: { Thumb: IT }
  4166. begin
  4167. bytelen:=2;
  4168. bytes:=0;
  4169. { set opcode }
  4170. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4171. bytes:=bytes or (ord(insentry^.code[2]) shl 0);
  4172. bytes:=bytes or (CondVal[oper[0]^.cc] shl 4);
  4173. i_field:=(bytes shr 4) and 1;
  4174. i_field:=(i_field shl 1) or i_field;
  4175. i_field:=(i_field shl 2) or i_field;
  4176. bytes:=bytes or ((i_field and ord(insentry^.code[3])) xor (ord(insentry^.code[3]) shr 4));
  4177. end;
  4178. #$6B: { Thumb: Data processing (misc) }
  4179. begin
  4180. bytelen:=2;
  4181. bytes:=0;
  4182. { set opcode }
  4183. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4184. bytes:=bytes or ord(insentry^.code[2]);
  4185. { set regs }
  4186. if ops>=2 then
  4187. begin
  4188. if oper[1]^.typ=top_const then
  4189. begin
  4190. bytes:=bytes or ((getsupreg(oper[0]^.reg) and $7) shl 8);
  4191. bytes:=bytes or (oper[1]^.val and $FF);
  4192. end
  4193. else if oper[1]^.typ=top_reg then
  4194. begin
  4195. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4196. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  4197. end;
  4198. end
  4199. else if ops=1 then
  4200. begin
  4201. if oper[0]^.typ=top_const then
  4202. bytes:=bytes or (oper[0]^.val and $FF);
  4203. end;
  4204. end;
  4205. #$6C: { Thumb: CPS }
  4206. begin
  4207. bytelen:=2;
  4208. bytes:=0;
  4209. { set opcode }
  4210. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4211. bytes:=bytes or ord(insentry^.code[2]);
  4212. if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 2);
  4213. if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 1);
  4214. if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 0);
  4215. end;
  4216. #$80: { Thumb-2: Dataprocessing }
  4217. begin
  4218. bytes:=0;
  4219. { set instruction code }
  4220. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4221. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4222. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4223. bytes:=bytes or ord(insentry^.code[4]);
  4224. if ops=1 then
  4225. begin
  4226. if oper[0]^.typ=top_reg then
  4227. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
  4228. else if oper[0]^.typ=top_const then
  4229. bytes:=bytes or (oper[0]^.val and $F);
  4230. end
  4231. else if (ops=2) and
  4232. (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
  4233. begin
  4234. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4235. if oper[1]^.typ=top_const then
  4236. encodethumbimm(oper[1]^.val)
  4237. else if oper[1]^.typ=top_reg then
  4238. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4239. end
  4240. else if (ops=3) and
  4241. (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
  4242. begin
  4243. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4244. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4245. if oper[2]^.typ=top_shifterop then
  4246. setthumbshift(2)
  4247. else if oper[2]^.typ=top_reg then
  4248. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 12);
  4249. end
  4250. else if (ops=2) and
  4251. (opcode in [A_REV,A_RBIT,A_REV16,A_REVSH,A_CLZ]) then
  4252. begin
  4253. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4254. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4255. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4256. end
  4257. else if ops=2 then
  4258. begin
  4259. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4260. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4261. if oper[1]^.typ=top_const then
  4262. encodethumbimm(oper[1]^.val)
  4263. else if oper[1]^.typ=top_reg then
  4264. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4265. end
  4266. else if ops=3 then
  4267. begin
  4268. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4269. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4270. if oper[2]^.typ=top_const then
  4271. encodethumbimm(oper[2]^.val)
  4272. else if oper[2]^.typ=top_reg then
  4273. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4274. end
  4275. else if ops=4 then
  4276. begin
  4277. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4278. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4279. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4280. if oper[3]^.typ=top_shifterop then
  4281. setthumbshift(3)
  4282. else if oper[3]^.typ=top_reg then
  4283. bytes:=bytes or (getsupreg(oper[3]^.reg) shl 12);
  4284. end;
  4285. if oppostfix=PF_S then
  4286. bytes:=bytes or (1 shl 20)
  4287. else if oppostfix=PF_X then
  4288. bytes:=bytes or (1 shl 4)
  4289. else if oppostfix=PF_R then
  4290. bytes:=bytes or (1 shl 4);
  4291. end;
  4292. #$81: { Thumb-2: Dataprocessing misc }
  4293. begin
  4294. bytes:=0;
  4295. { set instruction code }
  4296. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4297. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4298. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4299. bytes:=bytes or ord(insentry^.code[4]);
  4300. if ops=3 then
  4301. begin
  4302. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4303. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4304. if oper[2]^.typ=top_const then
  4305. begin
  4306. bytes:=bytes or (oper[2]^.val and $FF);
  4307. bytes:=bytes or ((oper[2]^.val and $700) shr 8) shl 12;
  4308. bytes:=bytes or ((oper[2]^.val and $800) shr 11) shl 26;
  4309. end;
  4310. end
  4311. else if ops=2 then
  4312. begin
  4313. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4314. offset:=0;
  4315. if oper[1]^.typ=top_const then
  4316. begin
  4317. offset:=oper[1]^.val;
  4318. end
  4319. else if oper[1]^.typ=top_ref then
  4320. begin
  4321. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4322. if assigned(currsym) then
  4323. offset:=currsym.offset-insoffset-8;
  4324. offset:=offset+oper[1]^.ref^.offset;
  4325. offset:=offset;
  4326. end;
  4327. bytes:=bytes or (offset and $FF);
  4328. bytes:=bytes or ((offset and $700) shr 8) shl 12;
  4329. bytes:=bytes or ((offset and $800) shr 11) shl 26;
  4330. bytes:=bytes or ((offset and $F000) shr 12) shl 16;
  4331. end;
  4332. if oppostfix=PF_S then
  4333. bytes:=bytes or (1 shl 20);
  4334. end;
  4335. #$82: { Thumb-2: Shifts }
  4336. begin
  4337. bytes:=0;
  4338. { set instruction code }
  4339. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4340. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4341. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4342. bytes:=bytes or ord(insentry^.code[4]);
  4343. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4344. if oper[1]^.typ=top_reg then
  4345. begin
  4346. offset:=2;
  4347. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4348. end
  4349. else
  4350. begin
  4351. offset:=1;
  4352. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 0);
  4353. end;
  4354. if oper[offset]^.typ=top_const then
  4355. begin
  4356. bytes:=bytes or (oper[offset]^.val and $3) shl 6;
  4357. bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
  4358. end
  4359. else if oper[offset]^.typ=top_reg then
  4360. bytes:=bytes or (getsupreg(oper[offset]^.reg) shl 16);
  4361. if (ops>=(offset+2)) and
  4362. (oper[offset+1]^.typ=top_const) then
  4363. bytes:=bytes or (oper[offset+1]^.val and $1F);
  4364. if oppostfix=PF_S then
  4365. bytes:=bytes or (1 shl 20);
  4366. end;
  4367. #$84: { Thumb-2: Shifts(width-1) }
  4368. begin
  4369. bytes:=0;
  4370. { set instruction code }
  4371. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4372. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4373. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4374. bytes:=bytes or ord(insentry^.code[4]);
  4375. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4376. if oper[1]^.typ=top_reg then
  4377. begin
  4378. offset:=2;
  4379. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4380. end
  4381. else
  4382. offset:=1;
  4383. if oper[offset]^.typ=top_const then
  4384. begin
  4385. bytes:=bytes or (oper[offset]^.val and $3) shl 6;
  4386. bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
  4387. end;
  4388. if (ops>=(offset+2)) and
  4389. (oper[offset+1]^.typ=top_const) then
  4390. begin
  4391. if opcode in [A_BFI,A_BFC] then
  4392. i_field:=oper[offset+1]^.val+oper[offset]^.val-1
  4393. else
  4394. i_field:=oper[offset+1]^.val-1;
  4395. bytes:=bytes or (i_field and $1F);
  4396. end;
  4397. if oppostfix=PF_S then
  4398. bytes:=bytes or (1 shl 20);
  4399. end;
  4400. #$83: { Thumb-2: Saturation }
  4401. begin
  4402. bytes:=0;
  4403. { set instruction code }
  4404. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4405. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4406. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4407. bytes:=bytes or ord(insentry^.code[4]);
  4408. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4409. bytes:=bytes or (oper[1]^.val and $1F);
  4410. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
  4411. if ops=4 then
  4412. setthumbshift(3,true);
  4413. end;
  4414. #$85: { Thumb-2: Long multiplications }
  4415. begin
  4416. bytes:=0;
  4417. { set instruction code }
  4418. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4419. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4420. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4421. bytes:=bytes or ord(insentry^.code[4]);
  4422. if ops=4 then
  4423. begin
  4424. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  4425. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 8);
  4426. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
  4427. bytes:=bytes or (getsupreg(oper[3]^.reg) shl 0);
  4428. end;
  4429. if oppostfix=PF_S then
  4430. bytes:=bytes or (1 shl 20)
  4431. else if oppostfix=PF_X then
  4432. bytes:=bytes or (1 shl 4);
  4433. end;
  4434. #$86: { Thumb-2: Extension ops }
  4435. begin
  4436. bytes:=0;
  4437. { set instruction code }
  4438. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4439. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4440. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4441. bytes:=bytes or ord(insentry^.code[4]);
  4442. if ops=2 then
  4443. begin
  4444. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4445. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4446. end
  4447. else if ops=3 then
  4448. begin
  4449. if oper[2]^.typ=top_shifterop then
  4450. begin
  4451. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4452. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4453. bytes:=bytes or ((oper[2]^.shifterop^.shiftimm shr 3) shl 4);
  4454. end
  4455. else
  4456. begin
  4457. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4458. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4459. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4460. end;
  4461. end
  4462. else if ops=4 then
  4463. begin
  4464. if oper[3]^.typ=top_shifterop then
  4465. begin
  4466. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4467. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4468. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4469. bytes:=bytes or ((oper[3]^.shifterop^.shiftimm shr 3) shl 4);
  4470. end;
  4471. end;
  4472. end;
  4473. #$87: { Thumb-2: PLD/PLI }
  4474. begin
  4475. { set instruction code }
  4476. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4477. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4478. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4479. bytes:=bytes or ord(insentry^.code[4]);
  4480. { set Rn and Rd }
  4481. bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
  4482. if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
  4483. begin
  4484. { set offset }
  4485. offset:=0;
  4486. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  4487. if assigned(currsym) then
  4488. offset:=currsym.offset-insoffset-8;
  4489. offset:=offset+oper[0]^.ref^.offset;
  4490. if offset>=0 then
  4491. begin
  4492. { set U flag }
  4493. bytes:=bytes or (1 shl 23);
  4494. bytes:=bytes or (offset and $FFF);
  4495. end
  4496. else
  4497. begin
  4498. bytes:=bytes or ($3 shl 10);
  4499. offset:=-offset;
  4500. bytes:=bytes or (offset and $FF);
  4501. end;
  4502. end
  4503. else
  4504. begin
  4505. bytes:=bytes or getsupreg(oper[0]^.ref^.index);
  4506. { set shift }
  4507. with oper[0]^.ref^ do
  4508. if shiftmode=SM_LSL then
  4509. bytes:=bytes or ((shiftimm and $1F) shl 4);
  4510. end;
  4511. end;
  4512. #$88: { Thumb-2: LDR/STR }
  4513. begin
  4514. { set instruction code }
  4515. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4516. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4517. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4518. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4519. { set Rn and Rd }
  4520. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4521. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4522. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  4523. begin
  4524. { set offset }
  4525. offset:=0;
  4526. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4527. if assigned(currsym) then
  4528. offset:=currsym.offset-insoffset-8;
  4529. offset:=(offset+oper[1]^.ref^.offset) shr ord(insentry^.code[5]);
  4530. if offset>=0 then
  4531. begin
  4532. if (offset>255) and
  4533. (not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT])) then
  4534. bytes:=bytes or (1 shl 23);
  4535. { set U flag }
  4536. if (oper[1]^.ref^.addressmode<>AM_OFFSET) then
  4537. begin
  4538. bytes:=bytes or (1 shl 9);
  4539. bytes:=bytes or (1 shl 11);
  4540. end;
  4541. bytes:=bytes or offset
  4542. end
  4543. else
  4544. begin
  4545. bytes:=bytes or (1 shl 11);
  4546. offset:=-offset;
  4547. bytes:=bytes or offset
  4548. end;
  4549. end
  4550. else
  4551. begin
  4552. { set I flag }
  4553. bytes:=bytes or (1 shl 25);
  4554. bytes:=bytes or getsupreg(oper[1]^.ref^.index);
  4555. { set shift }
  4556. with oper[1]^.ref^ do
  4557. if shiftmode<>SM_None then
  4558. bytes:=bytes or ((shiftimm and $1F) shl 4);
  4559. end;
  4560. if not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT]) then
  4561. begin
  4562. { set W bit }
  4563. if oper[1]^.ref^.addressmode<>AM_OFFSET then
  4564. bytes:=bytes or (1 shl 8);
  4565. { set P bit if necessary }
  4566. if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
  4567. bytes:=bytes or (1 shl 10);
  4568. end;
  4569. end;
  4570. #$89: { Thumb-2: LDRD/STRD }
  4571. begin
  4572. { set instruction code }
  4573. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4574. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4575. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4576. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4577. { set Rn and Rd }
  4578. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4579. bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
  4580. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4581. if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
  4582. begin
  4583. { set offset }
  4584. offset:=0;
  4585. currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
  4586. if assigned(currsym) then
  4587. offset:=currsym.offset-insoffset-8;
  4588. offset:=(offset+oper[2]^.ref^.offset) div 4;
  4589. if offset>=0 then
  4590. begin
  4591. { set U flag }
  4592. bytes:=bytes or (1 shl 23);
  4593. bytes:=bytes or offset
  4594. end
  4595. else
  4596. begin
  4597. offset:=-offset;
  4598. bytes:=bytes or offset
  4599. end;
  4600. end
  4601. else
  4602. begin
  4603. message(asmw_e_invalid_opcode_and_operands);
  4604. end;
  4605. { set W bit }
  4606. if oper[2]^.ref^.addressmode<>AM_OFFSET then
  4607. bytes:=bytes or (1 shl 21);
  4608. { set P bit if necessary }
  4609. if oper[2]^.ref^.addressmode<>AM_POSTINDEXED then
  4610. bytes:=bytes or (1 shl 24);
  4611. end;
  4612. #$8A: { Thumb-2: LDREX }
  4613. begin
  4614. { set instruction code }
  4615. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4616. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4617. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4618. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4619. { set Rn and Rd }
  4620. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4621. if (ops=2) and (opcode in [A_LDREX]) then
  4622. begin
  4623. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4624. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  4625. begin
  4626. { set offset }
  4627. offset:=0;
  4628. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4629. if assigned(currsym) then
  4630. offset:=currsym.offset-insoffset-8;
  4631. offset:=(offset+oper[1]^.ref^.offset) div 4;
  4632. if offset>=0 then
  4633. begin
  4634. bytes:=bytes or offset
  4635. end
  4636. else
  4637. begin
  4638. message(asmw_e_invalid_opcode_and_operands);
  4639. end;
  4640. end
  4641. else
  4642. begin
  4643. message(asmw_e_invalid_opcode_and_operands);
  4644. end;
  4645. end
  4646. else if (ops=2) then
  4647. begin
  4648. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4649. end
  4650. else
  4651. begin
  4652. bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
  4653. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4654. end;
  4655. end;
  4656. #$8B: { Thumb-2: STREX }
  4657. begin
  4658. { set instruction code }
  4659. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4660. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4661. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4662. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4663. { set Rn and Rd }
  4664. if (ops=3) and (opcode in [A_STREX]) then
  4665. begin
  4666. bytes:=bytes or getsupreg(oper[0]^.reg) shl 8;
  4667. bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
  4668. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4669. if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
  4670. begin
  4671. { set offset }
  4672. offset:=0;
  4673. currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
  4674. if assigned(currsym) then
  4675. offset:=currsym.offset-insoffset-8;
  4676. offset:=(offset+oper[2]^.ref^.offset) div 4;
  4677. if offset>=0 then
  4678. begin
  4679. bytes:=bytes or offset
  4680. end
  4681. else
  4682. begin
  4683. message(asmw_e_invalid_opcode_and_operands);
  4684. end;
  4685. end
  4686. else
  4687. begin
  4688. message(asmw_e_invalid_opcode_and_operands);
  4689. end;
  4690. end
  4691. else if (ops=3) then
  4692. begin
  4693. bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
  4694. bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
  4695. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4696. end
  4697. else
  4698. begin
  4699. bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
  4700. bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
  4701. bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
  4702. bytes:=bytes or getsupreg(oper[3]^.ref^.base) shl 16;
  4703. end;
  4704. end;
  4705. #$8C: { Thumb-2: LDM/STM }
  4706. begin
  4707. { set instruction code }
  4708. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4709. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4710. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4711. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4712. if oper[0]^.typ=top_reg then
  4713. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
  4714. else
  4715. begin
  4716. bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 16);
  4717. if oper[0]^.ref^.addressmode<>AM_OFFSET then
  4718. bytes:=bytes or (1 shl 21);
  4719. end;
  4720. for r:=0 to 15 do
  4721. if r in oper[1]^.regset^ then
  4722. bytes:=bytes or (1 shl r);
  4723. case oppostfix of
  4724. PF_None,PF_IA,PF_FD: bytes:=bytes or ($1 shl 23);
  4725. PF_DB,PF_EA: bytes:=bytes or ($2 shl 23);
  4726. end;
  4727. end;
  4728. #$8D: { Thumb-2: BL/BLX }
  4729. begin
  4730. { set instruction code }
  4731. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4732. bytes:=bytes or (ord(insentry^.code[2]) shl 8);
  4733. { set offset }
  4734. if oper[0]^.typ=top_const then
  4735. offset:=(oper[0]^.val shr 1) and $FFFFFF
  4736. else
  4737. begin
  4738. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  4739. if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
  4740. begin
  4741. objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
  4742. offset:=$FFFFFE
  4743. end
  4744. else
  4745. offset:=((currsym.offset-insoffset-8) shr 1) and $FFFFFF;
  4746. end;
  4747. bytes:=bytes or ((offset shr 00) and $7FF) shl 0;
  4748. bytes:=bytes or ((offset shr 11) and $3FF) shl 16;
  4749. bytes:=bytes or (((offset shr 21) xor (offset shr 23) xor 1) and $1) shl 11;
  4750. bytes:=bytes or (((offset shr 22) xor (offset shr 23) xor 1) and $1) shl 13;
  4751. bytes:=bytes or ((offset shr 23) and $1) shl 26;
  4752. end;
  4753. #$8E: { Thumb-2: TBB/TBH }
  4754. begin
  4755. { set instruction code }
  4756. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4757. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4758. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4759. bytes:=bytes or ord(insentry^.code[4]);
  4760. { set Rn and Rm }
  4761. bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
  4762. if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
  4763. message(asmw_e_invalid_effective_address)
  4764. else
  4765. begin
  4766. bytes:=bytes or getsupreg(oper[0]^.ref^.index);
  4767. if (opcode=A_TBH) and
  4768. (oper[0]^.ref^.shiftmode<>SM_LSL) and
  4769. (oper[0]^.ref^.shiftimm<>1) then
  4770. message(asmw_e_invalid_effective_address);
  4771. end;
  4772. end;
  4773. #$8F: { Thumb-2: CPSxx }
  4774. begin
  4775. { set opcode }
  4776. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4777. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4778. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4779. bytes:=bytes or ord(insentry^.code[4]);
  4780. if (oper[0]^.typ=top_modeflags) then
  4781. begin
  4782. if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
  4783. if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
  4784. if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 5);
  4785. end;
  4786. if (ops=2) then
  4787. bytes:=bytes or (oper[1]^.val and $1F)
  4788. else if (ops=1) and
  4789. (oper[0]^.typ=top_const) then
  4790. bytes:=bytes or (oper[0]^.val and $1F);
  4791. end;
  4792. #$96: { Thumb-2: MSR/MRS }
  4793. begin
  4794. { set instruction code }
  4795. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4796. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4797. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4798. bytes:=bytes or ord(insentry^.code[4]);
  4799. if opcode=A_MRS then
  4800. begin
  4801. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4802. case oper[1]^.reg of
  4803. NR_MSP: bytes:=bytes or $08;
  4804. NR_PSP: bytes:=bytes or $09;
  4805. NR_IPSR: bytes:=bytes or $05;
  4806. NR_EPSR: bytes:=bytes or $06;
  4807. NR_APSR: bytes:=bytes or $00;
  4808. NR_PRIMASK: bytes:=bytes or $10;
  4809. NR_BASEPRI: bytes:=bytes or $11;
  4810. NR_BASEPRI_MAX: bytes:=bytes or $12;
  4811. NR_FAULTMASK: bytes:=bytes or $13;
  4812. NR_CONTROL: bytes:=bytes or $14;
  4813. else
  4814. Message(asmw_e_invalid_opcode_and_operands);
  4815. end;
  4816. end
  4817. else
  4818. begin
  4819. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4820. case oper[0]^.reg of
  4821. NR_APSR,
  4822. NR_APSR_nzcvqg: bytes:=bytes or $C00;
  4823. NR_APSR_g: bytes:=bytes or $400;
  4824. NR_APSR_nzcvq: bytes:=bytes or $800;
  4825. NR_MSP: bytes:=bytes or $08;
  4826. NR_PSP: bytes:=bytes or $09;
  4827. NR_PRIMASK: bytes:=bytes or $10;
  4828. NR_BASEPRI: bytes:=bytes or $11;
  4829. NR_BASEPRI_MAX: bytes:=bytes or $12;
  4830. NR_FAULTMASK: bytes:=bytes or $13;
  4831. NR_CONTROL: bytes:=bytes or $14;
  4832. else
  4833. Message(asmw_e_invalid_opcode_and_operands);
  4834. end;
  4835. end;
  4836. end;
  4837. #$A0: { FPA: CPDT(LDF/STF) }
  4838. begin
  4839. { set instruction code }
  4840. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4841. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4842. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4843. bytes:=bytes or ord(insentry^.code[4]);
  4844. if ops=2 then
  4845. begin
  4846. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4847. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4848. bytes:=bytes or ((oper[1]^.ref^.offset shr 2) and $FF);
  4849. if oper[1]^.ref^.offset>=0 then
  4850. bytes:=bytes or (1 shl 23);
  4851. if oper[1]^.ref^.addressmode<>AM_OFFSET then
  4852. bytes:=bytes or (1 shl 21);
  4853. if oper[1]^.ref^.addressmode=AM_PREINDEXED then
  4854. bytes:=bytes or (1 shl 24);
  4855. case oppostfix of
  4856. PF_D: bytes:=bytes or (0 shl 22) or (1 shl 15);
  4857. PF_E: bytes:=bytes or (1 shl 22) or (0 shl 15);
  4858. PF_P: bytes:=bytes or (1 shl 22) or (1 shl 15);
  4859. end;
  4860. end
  4861. else
  4862. begin
  4863. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4864. case oper[1]^.val of
  4865. 1: bytes:=bytes or (1 shl 15);
  4866. 2: bytes:=bytes or (1 shl 22);
  4867. 3: bytes:=bytes or (1 shl 22) or (1 shl 15);
  4868. 4: ;
  4869. else
  4870. message1(asmw_e_invalid_opcode_and_operands, 'Invalid count for LFM/SFM');
  4871. end;
  4872. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4873. bytes:=bytes or ((oper[2]^.ref^.offset shr 2) and $FF);
  4874. if oper[2]^.ref^.offset>=0 then
  4875. bytes:=bytes or (1 shl 23);
  4876. if oper[2]^.ref^.addressmode<>AM_OFFSET then
  4877. bytes:=bytes or (1 shl 21);
  4878. if oper[2]^.ref^.addressmode=AM_PREINDEXED then
  4879. bytes:=bytes or (1 shl 24);
  4880. end;
  4881. end;
  4882. #$A1: { FPA: CPDO }
  4883. begin
  4884. { set instruction code }
  4885. bytes:=bytes or ($E shl 24);
  4886. bytes:=bytes or (ord(insentry^.code[1]) shl 15);
  4887. bytes:=bytes or ((ord(insentry^.code[2]) shr 1) shl 20);
  4888. bytes:=bytes or (1 shl 8);
  4889. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4890. if ops=2 then
  4891. begin
  4892. if oper[1]^.typ=top_reg then
  4893. bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
  4894. else
  4895. case oper[1]^.val of
  4896. 0: bytes:=bytes or $8;
  4897. 1: bytes:=bytes or $9;
  4898. 2: bytes:=bytes or $A;
  4899. 3: bytes:=bytes or $B;
  4900. 4: bytes:=bytes or $C;
  4901. 5: bytes:=bytes or $D;
  4902. //0.5: bytes:=bytes or $E;
  4903. 10: bytes:=bytes or $F;
  4904. else
  4905. Message(asmw_e_invalid_opcode_and_operands);
  4906. end;
  4907. end
  4908. else
  4909. begin
  4910. bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
  4911. if oper[2]^.typ=top_reg then
  4912. bytes:=bytes or getsupreg(oper[2]^.reg) shl 0
  4913. else
  4914. case oper[2]^.val of
  4915. 0: bytes:=bytes or $8;
  4916. 1: bytes:=bytes or $9;
  4917. 2: bytes:=bytes or $A;
  4918. 3: bytes:=bytes or $B;
  4919. 4: bytes:=bytes or $C;
  4920. 5: bytes:=bytes or $D;
  4921. //0.5: bytes:=bytes or $E;
  4922. 10: bytes:=bytes or $F;
  4923. else
  4924. Message(asmw_e_invalid_opcode_and_operands);
  4925. end;
  4926. end;
  4927. case roundingmode of
  4928. RM_P: bytes:=bytes or (1 shl 5);
  4929. RM_M: bytes:=bytes or (2 shl 5);
  4930. RM_Z: bytes:=bytes or (3 shl 5);
  4931. end;
  4932. case oppostfix of
  4933. PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
  4934. PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
  4935. PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
  4936. else
  4937. message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
  4938. end;
  4939. end;
  4940. #$A2: { FPA: CPDO }
  4941. begin
  4942. { set instruction code }
  4943. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4944. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4945. bytes:=bytes or ($11 shl 4);
  4946. case opcode of
  4947. A_FLT:
  4948. begin
  4949. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4950. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
  4951. case roundingmode of
  4952. RM_P: bytes:=bytes or (1 shl 5);
  4953. RM_M: bytes:=bytes or (2 shl 5);
  4954. RM_Z: bytes:=bytes or (3 shl 5);
  4955. end;
  4956. case oppostfix of
  4957. PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
  4958. PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
  4959. PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
  4960. else
  4961. message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
  4962. end;
  4963. end;
  4964. A_FIX:
  4965. begin
  4966. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  4967. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4968. case roundingmode of
  4969. RM_P: bytes:=bytes or (1 shl 5);
  4970. RM_M: bytes:=bytes or (2 shl 5);
  4971. RM_Z: bytes:=bytes or (3 shl 5);
  4972. end;
  4973. end;
  4974. A_WFS,A_RFS,A_WFC,A_RFC:
  4975. begin
  4976. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  4977. end;
  4978. A_CMF,A_CNF,A_CMFE,A_CNFE:
  4979. begin
  4980. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4981. if oper[1]^.typ=top_reg then
  4982. bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
  4983. else
  4984. case oper[1]^.val of
  4985. 0: bytes:=bytes or $8;
  4986. 1: bytes:=bytes or $9;
  4987. 2: bytes:=bytes or $A;
  4988. 3: bytes:=bytes or $B;
  4989. 4: bytes:=bytes or $C;
  4990. 5: bytes:=bytes or $D;
  4991. //0.5: bytes:=bytes or $E;
  4992. 10: bytes:=bytes or $F;
  4993. else
  4994. Message(asmw_e_invalid_opcode_and_operands);
  4995. end;
  4996. end;
  4997. end;
  4998. end;
  4999. #$fe: // No written data
  5000. begin
  5001. exit;
  5002. end;
  5003. #$ff:
  5004. internalerror(2005091101);
  5005. else
  5006. begin
  5007. writeln(ord(insentry^.code[0]), ' - ', opcode);
  5008. internalerror(2005091102);
  5009. end;
  5010. end;
  5011. { Todo: Decide whether the code above should take care of writing data in an order that makes senes }
  5012. if (insentry^.code[0] in [#$80..#$96]) and (bytelen=4) then
  5013. bytes:=((bytes shr 16) and $FFFF) or ((bytes and $FFFF) shl 16);
  5014. { we're finished, write code }
  5015. objdata.writebytes(bytes,bytelen);
  5016. end;
  5017. begin
  5018. cai_align:=tai_align;
  5019. end.