asm5.go 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096
  1. // Inferno utils/5l/span.c
  2. // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/span.c
  3. //
  4. // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
  5. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
  6. // Portions Copyright © 1997-1999 Vita Nuova Limited
  7. // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
  8. // Portions Copyright © 2004,2006 Bruce Ellis
  9. // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
  10. // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
  11. // Portions Copyright © 2009 The Go Authors. All rights reserved.
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining a copy
  14. // of this software and associated documentation files (the "Software"), to deal
  15. // in the Software without restriction, including without limitation the rights
  16. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17. // copies of the Software, and to permit persons to whom the Software is
  18. // furnished to do so, subject to the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be included in
  21. // all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  26. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  28. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  29. // THE SOFTWARE.
  30. package arm
  31. import (
  32. "github.com/twitchyliquid64/golang-asm/obj"
  33. "github.com/twitchyliquid64/golang-asm/objabi"
  34. "fmt"
  35. "log"
  36. "math"
  37. "sort"
  38. )
  39. // ctxt5 holds state while assembling a single function.
  40. // Each function gets a fresh ctxt5.
  41. // This allows for multiple functions to be safely concurrently assembled.
  42. type ctxt5 struct {
  43. ctxt *obj.Link
  44. newprog obj.ProgAlloc
  45. cursym *obj.LSym
  46. printp *obj.Prog
  47. blitrl *obj.Prog
  48. elitrl *obj.Prog
  49. autosize int64
  50. instoffset int64
  51. pc int64
  52. pool struct {
  53. start uint32
  54. size uint32
  55. extra uint32
  56. }
  57. }
  58. type Optab struct {
  59. as obj.As
  60. a1 uint8
  61. a2 int8
  62. a3 uint8
  63. type_ uint8
  64. size int8
  65. param int16
  66. flag int8
  67. pcrelsiz uint8
  68. scond uint8 // optional flags accepted by the instruction
  69. }
  70. type Opcross [32][2][32]uint8
  71. const (
  72. LFROM = 1 << 0
  73. LTO = 1 << 1
  74. LPOOL = 1 << 2
  75. LPCREL = 1 << 3
  76. )
  77. var optab = []Optab{
  78. /* struct Optab:
  79. OPCODE, from, prog->reg, to, type, size, param, flag, extra data size, optional suffix */
  80. {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0, 0},
  81. {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  82. {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  83. {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  84. {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  85. {AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  86. {AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  87. {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  88. {AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
  89. {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0, 0},
  90. {AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
  91. {AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
  92. {AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
  93. {AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
  94. {AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
  95. {AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
  96. {AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
  97. {AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
  98. {ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0, 0},
  99. {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
  100. {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
  101. {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
  102. {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
  103. {AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
  104. {AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
  105. {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
  106. {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0, 0},
  107. {AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0, C_SBIT},
  108. {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0, 0},
  109. {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
  110. {ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0, 0},
  111. {ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
  112. {ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // prediction hinted form, hint ignored
  113. {AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0, 0},
  114. {ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
  115. {ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
  116. {ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0, 0},
  117. {ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0, 0},
  118. {ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0, C_SBIT},
  119. {ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0, C_SBIT},
  120. {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0, C_SBIT},
  121. {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0, C_SBIT},
  122. {ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0, 0},
  123. {ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0, 0},
  124. {AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0, 0},
  125. {AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0, 0},
  126. {AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0, 0},
  127. {AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0, 0},
  128. {AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0, 0},
  129. {AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
  130. {AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
  131. {AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0, 0},
  132. {AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4, 0},
  133. {AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
  134. {AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  135. {AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  136. {AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  137. {AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  138. {AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  139. {AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  140. {ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
  141. {AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  142. {AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  143. {AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  144. {AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  145. {AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  146. {AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
  147. {AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, 0},
  148. {ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
  149. {AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
  150. {AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
  151. {AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
  152. {AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
  153. {AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0, 0},
  154. {AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0, 0},
  155. {AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
  156. {AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
  157. {AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
  158. {AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
  159. {AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
  160. {AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
  161. {AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, 0},
  162. {ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0, 0},
  163. {AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
  164. {AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
  165. {AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0, 0},
  166. {AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
  167. {AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
  168. {AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
  169. {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0, C_SBIT},
  170. {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0, C_SBIT},
  171. {ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0, 0},
  172. {ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0, 0},
  173. {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0, 0},
  174. {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0, 0},
  175. {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0, C_SBIT},
  176. {ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3
  177. {ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3
  178. {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  179. {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  180. {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  181. {AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  182. {AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  183. {AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  184. {AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  185. {AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  186. {AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  187. {AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  188. {AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  189. {AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  190. {AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0, 0},
  191. {AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0, 0},
  192. {AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, C_SBIT},
  193. {AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
  194. {AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
  195. {AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
  196. {AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
  197. {AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
  198. {AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
  199. {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  200. {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  201. {AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  202. {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  203. {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  204. {AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  205. {AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  206. {AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  207. {AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  208. {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  209. {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  210. {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  211. {AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0, 0},
  212. {AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0, 0},
  213. {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  214. {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  215. {AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  216. {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  217. {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  218. {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  219. {AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0, C_SBIT},
  220. {AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0, 0},
  221. {AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0, 0},
  222. {AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0, 0},
  223. {AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  224. {AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  225. {ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0, 0},
  226. {ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0, 0},
  227. {AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  228. {AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  229. {AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  230. {AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  231. {AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  232. {AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  233. {AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  234. {AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  235. {AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  236. {AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  237. {AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0, 0},
  238. {AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0, 0},
  239. {AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
  240. {ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
  241. {AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0, 0},
  242. {AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0, 0},
  243. {AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  244. {AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  245. {AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  246. {AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  247. {AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  248. {AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  249. {AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  250. {AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  251. {AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  252. {AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  253. {AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  254. {AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  255. {AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  256. {AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  257. {AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  258. {AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  259. {AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  260. {AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  261. {AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  262. {AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  263. {AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  264. {AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  265. {AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  266. {AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  267. {AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  268. {AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  269. {AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  270. {AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  271. {AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  272. {AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
  273. {AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  274. {AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  275. {AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  276. {AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  277. {AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  278. {AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  279. {AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  280. {AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
  281. {AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  282. {AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  283. {AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  284. {AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  285. {AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  286. {AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  287. {AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  288. {AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  289. {AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  290. {AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  291. {AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  292. {AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  293. {AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  294. {AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  295. {AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
  296. {AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
  297. {ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0, 0},
  298. {ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0, 0},
  299. {ADMB, C_NONE, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
  300. {ADMB, C_LCON, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
  301. {ADMB, C_SPR, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
  302. {AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0, 0},
  303. {AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0, 0},
  304. {ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0, 0},
  305. {ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0, 0},
  306. {AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0, C_UBIT},
  307. {AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0, C_UBIT},
  308. {AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0, C_UBIT},
  309. {AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0, C_UBIT},
  310. {AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0},
  311. {AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0},
  312. {ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0},
  313. {ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0},
  314. {APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0},
  315. {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0},
  316. {ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0},
  317. {AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0, 0},
  318. {AMULA, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, C_SBIT},
  319. {AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, 0},
  320. {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0, 0},
  321. {obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0, 0},
  322. {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
  323. {obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, // nop variants, see #40689
  324. {obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
  325. {obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
  326. {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
  327. {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
  328. {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0, 0},
  329. }
  330. var mbOp = []struct {
  331. reg int16
  332. enc uint32
  333. }{
  334. {REG_MB_SY, 15},
  335. {REG_MB_ST, 14},
  336. {REG_MB_ISH, 11},
  337. {REG_MB_ISHST, 10},
  338. {REG_MB_NSH, 7},
  339. {REG_MB_NSHST, 6},
  340. {REG_MB_OSH, 3},
  341. {REG_MB_OSHST, 2},
  342. }
  343. var oprange [ALAST & obj.AMask][]Optab
  344. var xcmp [C_GOK + 1][C_GOK + 1]bool
  345. var (
  346. deferreturn *obj.LSym
  347. symdiv *obj.LSym
  348. symdivu *obj.LSym
  349. symmod *obj.LSym
  350. symmodu *obj.LSym
  351. )
  352. // Note about encoding: Prog.scond holds the condition encoding,
  353. // but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0.
  354. // The code that shifts the value << 28 has the responsibility
  355. // for XORing with C_SCOND_XOR too.
  356. func checkSuffix(c *ctxt5, p *obj.Prog, o *Optab) {
  357. if p.Scond&C_SBIT != 0 && o.scond&C_SBIT == 0 {
  358. c.ctxt.Diag("invalid .S suffix: %v", p)
  359. }
  360. if p.Scond&C_PBIT != 0 && o.scond&C_PBIT == 0 {
  361. c.ctxt.Diag("invalid .P suffix: %v", p)
  362. }
  363. if p.Scond&C_WBIT != 0 && o.scond&C_WBIT == 0 {
  364. c.ctxt.Diag("invalid .W suffix: %v", p)
  365. }
  366. if p.Scond&C_UBIT != 0 && o.scond&C_UBIT == 0 {
  367. c.ctxt.Diag("invalid .U suffix: %v", p)
  368. }
  369. }
  370. func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  371. if ctxt.Retpoline {
  372. ctxt.Diag("-spectre=ret not supported on arm")
  373. ctxt.Retpoline = false // don't keep printing
  374. }
  375. var p *obj.Prog
  376. var op *obj.Prog
  377. p = cursym.Func.Text
  378. if p == nil || p.Link == nil { // handle external functions and ELF section symbols
  379. return
  380. }
  381. if oprange[AAND&obj.AMask] == nil {
  382. ctxt.Diag("arm ops not initialized, call arm.buildop first")
  383. }
  384. c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4}
  385. pc := int32(0)
  386. op = p
  387. p = p.Link
  388. var m int
  389. var o *Optab
  390. for ; p != nil || c.blitrl != nil; op, p = p, p.Link {
  391. if p == nil {
  392. if c.checkpool(op, pc) {
  393. p = op
  394. continue
  395. }
  396. // can't happen: blitrl is not nil, but checkpool didn't flushpool
  397. ctxt.Diag("internal inconsistency")
  398. break
  399. }
  400. p.Pc = int64(pc)
  401. o = c.oplook(p)
  402. m = int(o.size)
  403. if m%4 != 0 || p.Pc%4 != 0 {
  404. ctxt.Diag("!pc invalid: %v size=%d", p, m)
  405. }
  406. // must check literal pool here in case p generates many instructions
  407. if c.blitrl != nil {
  408. // Emit the constant pool just before p if p
  409. // would push us over the immediate size limit.
  410. if c.checkpool(op, pc+int32(m)) {
  411. // Back up to the instruction just
  412. // before the pool and continue with
  413. // the first instruction of the pool.
  414. p = op
  415. continue
  416. }
  417. }
  418. if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) {
  419. ctxt.Diag("zero-width instruction\n%v", p)
  420. continue
  421. }
  422. switch o.flag & (LFROM | LTO | LPOOL) {
  423. case LFROM:
  424. c.addpool(p, &p.From)
  425. case LTO:
  426. c.addpool(p, &p.To)
  427. case LPOOL:
  428. if p.Scond&C_SCOND == C_SCOND_NONE {
  429. c.flushpool(p, 0, 0)
  430. }
  431. }
  432. if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE {
  433. c.flushpool(p, 0, 0)
  434. }
  435. pc += int32(m)
  436. }
  437. c.cursym.Size = int64(pc)
  438. /*
  439. * if any procedure is large enough to
  440. * generate a large SBRA branch, then
  441. * generate extra passes putting branches
  442. * around jmps to fix. this is rare.
  443. */
  444. times := 0
  445. var bflag int
  446. var opc int32
  447. var out [6 + 3]uint32
  448. for {
  449. bflag = 0
  450. pc = 0
  451. times++
  452. c.cursym.Func.Text.Pc = 0 // force re-layout the code.
  453. for p = c.cursym.Func.Text; p != nil; p = p.Link {
  454. o = c.oplook(p)
  455. if int64(pc) > p.Pc {
  456. p.Pc = int64(pc)
  457. }
  458. /* very large branches
  459. if(o->type == 6 && p->pcond) {
  460. otxt = p->pcond->pc - c;
  461. if(otxt < 0)
  462. otxt = -otxt;
  463. if(otxt >= (1L<<17) - 10) {
  464. q = emallocz(sizeof(Prog));
  465. q->link = p->link;
  466. p->link = q;
  467. q->as = AB;
  468. q->to.type = TYPE_BRANCH;
  469. q->pcond = p->pcond;
  470. p->pcond = q;
  471. q = emallocz(sizeof(Prog));
  472. q->link = p->link;
  473. p->link = q;
  474. q->as = AB;
  475. q->to.type = TYPE_BRANCH;
  476. q->pcond = q->link->link;
  477. bflag = 1;
  478. }
  479. }
  480. */
  481. opc = int32(p.Pc)
  482. m = int(o.size)
  483. if p.Pc != int64(opc) {
  484. bflag = 1
  485. }
  486. //print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times);
  487. pc = int32(p.Pc + int64(m))
  488. if m%4 != 0 || p.Pc%4 != 0 {
  489. ctxt.Diag("pc invalid: %v size=%d", p, m)
  490. }
  491. if m/4 > len(out) {
  492. ctxt.Diag("instruction size too large: %d > %d", m/4, len(out))
  493. }
  494. if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) {
  495. if p.As == obj.ATEXT {
  496. c.autosize = p.To.Offset + 4
  497. continue
  498. }
  499. ctxt.Diag("zero-width instruction\n%v", p)
  500. continue
  501. }
  502. }
  503. c.cursym.Size = int64(pc)
  504. if bflag == 0 {
  505. break
  506. }
  507. }
  508. if pc%4 != 0 {
  509. ctxt.Diag("sym->size=%d, invalid", pc)
  510. }
  511. /*
  512. * lay out the code. all the pc-relative code references,
  513. * even cross-function, are resolved now;
  514. * only data references need to be relocated.
  515. * with more work we could leave cross-function
  516. * code references to be relocated too, and then
  517. * perhaps we'd be able to parallelize the span loop above.
  518. */
  519. p = c.cursym.Func.Text
  520. c.autosize = p.To.Offset + 4
  521. c.cursym.Grow(c.cursym.Size)
  522. bp := c.cursym.P
  523. pc = int32(p.Pc) // even p->link might need extra padding
  524. var v int
  525. for p = p.Link; p != nil; p = p.Link {
  526. c.pc = p.Pc
  527. o = c.oplook(p)
  528. opc = int32(p.Pc)
  529. c.asmout(p, o, out[:])
  530. m = int(o.size)
  531. if m%4 != 0 || p.Pc%4 != 0 {
  532. ctxt.Diag("final stage: pc invalid: %v size=%d", p, m)
  533. }
  534. if int64(pc) > p.Pc {
  535. ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p)
  536. }
  537. for int64(pc) != p.Pc {
  538. // emit 0xe1a00000 (MOVW R0, R0)
  539. bp[0] = 0x00
  540. bp = bp[1:]
  541. bp[0] = 0x00
  542. bp = bp[1:]
  543. bp[0] = 0xa0
  544. bp = bp[1:]
  545. bp[0] = 0xe1
  546. bp = bp[1:]
  547. pc += 4
  548. }
  549. for i := 0; i < m/4; i++ {
  550. v = int(out[i])
  551. bp[0] = byte(v)
  552. bp = bp[1:]
  553. bp[0] = byte(v >> 8)
  554. bp = bp[1:]
  555. bp[0] = byte(v >> 16)
  556. bp = bp[1:]
  557. bp[0] = byte(v >> 24)
  558. bp = bp[1:]
  559. }
  560. pc += int32(m)
  561. }
  562. }
  563. // checkpool flushes the literal pool when the first reference to
  564. // it threatens to go out of range of a 12-bit PC-relative offset.
  565. //
  566. // nextpc is the tentative next PC at which the pool could be emitted.
  567. // checkpool should be called *before* emitting the instruction that
  568. // would cause the PC to reach nextpc.
  569. // If nextpc is too far from the first pool reference, checkpool will
  570. // flush the pool immediately after p.
  571. // The caller should resume processing a p.Link.
  572. func (c *ctxt5) checkpool(p *obj.Prog, nextpc int32) bool {
  573. poolLast := nextpc
  574. poolLast += 4 // the AB instruction to jump around the pool
  575. poolLast += int32(c.pool.size) - 4 // the offset of the last pool entry
  576. refPC := int32(c.pool.start) // PC of the first pool reference
  577. v := poolLast - refPC - 8 // 12-bit PC-relative offset (see omvl)
  578. if c.pool.size >= 0xff0 || immaddr(v) == 0 {
  579. return c.flushpool(p, 1, 0)
  580. } else if p.Link == nil {
  581. return c.flushpool(p, 2, 0)
  582. }
  583. return false
  584. }
  585. func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool {
  586. if c.blitrl != nil {
  587. if skip != 0 {
  588. if false && skip == 1 {
  589. fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
  590. }
  591. q := c.newprog()
  592. q.As = AB
  593. q.To.Type = obj.TYPE_BRANCH
  594. q.To.SetTarget(p.Link)
  595. q.Link = c.blitrl
  596. q.Pos = p.Pos
  597. c.blitrl = q
  598. } else if force == 0 && (p.Pc+int64(c.pool.size)-int64(c.pool.start) < 2048) {
  599. return false
  600. }
  601. // The line number for constant pool entries doesn't really matter.
  602. // We set it to the line number of the preceding instruction so that
  603. // there are no deltas to encode in the pc-line tables.
  604. for q := c.blitrl; q != nil; q = q.Link {
  605. q.Pos = p.Pos
  606. }
  607. c.elitrl.Link = p.Link
  608. p.Link = c.blitrl
  609. c.blitrl = nil /* BUG: should refer back to values until out-of-range */
  610. c.elitrl = nil
  611. c.pool.size = 0
  612. c.pool.start = 0
  613. c.pool.extra = 0
  614. return true
  615. }
  616. return false
  617. }
  618. func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) {
  619. t := c.newprog()
  620. t.As = AWORD
  621. switch c.aclass(a) {
  622. default:
  623. t.To.Offset = a.Offset
  624. t.To.Sym = a.Sym
  625. t.To.Type = a.Type
  626. t.To.Name = a.Name
  627. if c.ctxt.Flag_shared && t.To.Sym != nil {
  628. t.Rel = p
  629. }
  630. case C_SROREG,
  631. C_LOREG,
  632. C_ROREG,
  633. C_FOREG,
  634. C_SOREG,
  635. C_HOREG,
  636. C_FAUTO,
  637. C_SAUTO,
  638. C_LAUTO,
  639. C_LACON:
  640. t.To.Type = obj.TYPE_CONST
  641. t.To.Offset = c.instoffset
  642. }
  643. if t.Rel == nil {
  644. for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
  645. if q.Rel == nil && q.To == t.To {
  646. p.Pool = q
  647. return
  648. }
  649. }
  650. }
  651. q := c.newprog()
  652. *q = *t
  653. q.Pc = int64(c.pool.size)
  654. if c.blitrl == nil {
  655. c.blitrl = q
  656. c.pool.start = uint32(p.Pc)
  657. } else {
  658. c.elitrl.Link = q
  659. }
  660. c.elitrl = q
  661. c.pool.size += 4
  662. // Store the link to the pool entry in Pool.
  663. p.Pool = q
  664. }
  665. func (c *ctxt5) regoff(a *obj.Addr) int32 {
  666. c.instoffset = 0
  667. c.aclass(a)
  668. return int32(c.instoffset)
  669. }
  670. func immrot(v uint32) int32 {
  671. for i := 0; i < 16; i++ {
  672. if v&^0xff == 0 {
  673. return int32(uint32(int32(i)<<8) | v | 1<<25)
  674. }
  675. v = v<<2 | v>>30
  676. }
  677. return 0
  678. }
  679. // immrot2a returns bits encoding the immediate constant fields of two instructions,
  680. // such that the encoded constants x, y satisfy x|y==v, x&y==0.
  681. // Returns 0,0 if no such decomposition of v exists.
  682. func immrot2a(v uint32) (uint32, uint32) {
  683. for i := uint(1); i < 32; i++ {
  684. m := uint32(1<<i - 1)
  685. if x, y := immrot(v&m), immrot(v&^m); x != 0 && y != 0 {
  686. return uint32(x), uint32(y)
  687. }
  688. }
  689. // TODO: handle some more cases, like where
  690. // the wraparound from the rotate could help.
  691. return 0, 0
  692. }
  693. // immrot2s returns bits encoding the immediate constant fields of two instructions,
  694. // such that the encoded constants y, x satisfy y-x==v, y&x==0.
  695. // Returns 0,0 if no such decomposition of v exists.
  696. func immrot2s(v uint32) (uint32, uint32) {
  697. if immrot(v) != 0 {
  698. return v, 0
  699. }
  700. // suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00}
  701. // omit trailing 00
  702. var i uint32
  703. for i = 2; i < 32; i += 2 {
  704. if v&(1<<i-1) != 0 {
  705. break
  706. }
  707. }
  708. // i must be <= 24, then adjust i just above lower 8 effective bits of v
  709. i += 6
  710. // let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v
  711. x := 1<<i - v&(1<<i-1)
  712. y := v + x
  713. if y, x = uint32(immrot(y)), uint32(immrot(x)); y != 0 && x != 0 {
  714. return y, x
  715. }
  716. return 0, 0
  717. }
  718. func immaddr(v int32) int32 {
  719. if v >= 0 && v <= 0xfff {
  720. return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */
  721. }
  722. if v >= -0xfff && v < 0 {
  723. return -v&0xfff | 1<<24 /* pre indexing */
  724. }
  725. return 0
  726. }
  727. func immfloat(v int32) bool {
  728. return v&0xC03 == 0 /* offset will fit in floating-point load/store */
  729. }
  730. func immhalf(v int32) bool {
  731. if v >= 0 && v <= 0xff {
  732. return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */
  733. }
  734. if v >= -0xff && v < 0 {
  735. return -v&0xff|1<<24 != 0 /* pre indexing */
  736. }
  737. return false
  738. }
  739. func (c *ctxt5) aclass(a *obj.Addr) int {
  740. switch a.Type {
  741. case obj.TYPE_NONE:
  742. return C_NONE
  743. case obj.TYPE_REG:
  744. c.instoffset = 0
  745. if REG_R0 <= a.Reg && a.Reg <= REG_R15 {
  746. return C_REG
  747. }
  748. if REG_F0 <= a.Reg && a.Reg <= REG_F15 {
  749. return C_FREG
  750. }
  751. if a.Reg == REG_FPSR || a.Reg == REG_FPCR {
  752. return C_FCR
  753. }
  754. if a.Reg == REG_CPSR || a.Reg == REG_SPSR {
  755. return C_PSR
  756. }
  757. if a.Reg >= REG_SPECIAL {
  758. return C_SPR
  759. }
  760. return C_GOK
  761. case obj.TYPE_REGREG:
  762. return C_REGREG
  763. case obj.TYPE_REGREG2:
  764. return C_REGREG2
  765. case obj.TYPE_REGLIST:
  766. return C_REGLIST
  767. case obj.TYPE_SHIFT:
  768. if a.Reg == 0 {
  769. // register shift R>>i
  770. return C_SHIFT
  771. } else {
  772. // memory address with shifted offset R>>i(R)
  773. return C_SHIFTADDR
  774. }
  775. case obj.TYPE_MEM:
  776. switch a.Name {
  777. case obj.NAME_EXTERN,
  778. obj.NAME_GOTREF,
  779. obj.NAME_STATIC:
  780. if a.Sym == nil || a.Sym.Name == "" {
  781. fmt.Printf("null sym external\n")
  782. return C_GOK
  783. }
  784. c.instoffset = 0 // s.b. unused but just in case
  785. if a.Sym.Type == objabi.STLSBSS {
  786. if c.ctxt.Flag_shared {
  787. return C_TLS_IE
  788. } else {
  789. return C_TLS_LE
  790. }
  791. }
  792. return C_ADDR
  793. case obj.NAME_AUTO:
  794. if a.Reg == REGSP {
  795. // unset base register for better printing, since
  796. // a.Offset is still relative to pseudo-SP.
  797. a.Reg = obj.REG_NONE
  798. }
  799. c.instoffset = c.autosize + a.Offset
  800. if t := immaddr(int32(c.instoffset)); t != 0 {
  801. if immhalf(int32(c.instoffset)) {
  802. if immfloat(t) {
  803. return C_HFAUTO
  804. }
  805. return C_HAUTO
  806. }
  807. if immfloat(t) {
  808. return C_FAUTO
  809. }
  810. return C_SAUTO
  811. }
  812. return C_LAUTO
  813. case obj.NAME_PARAM:
  814. if a.Reg == REGSP {
  815. // unset base register for better printing, since
  816. // a.Offset is still relative to pseudo-FP.
  817. a.Reg = obj.REG_NONE
  818. }
  819. c.instoffset = c.autosize + a.Offset + 4
  820. if t := immaddr(int32(c.instoffset)); t != 0 {
  821. if immhalf(int32(c.instoffset)) {
  822. if immfloat(t) {
  823. return C_HFAUTO
  824. }
  825. return C_HAUTO
  826. }
  827. if immfloat(t) {
  828. return C_FAUTO
  829. }
  830. return C_SAUTO
  831. }
  832. return C_LAUTO
  833. case obj.NAME_NONE:
  834. c.instoffset = a.Offset
  835. if t := immaddr(int32(c.instoffset)); t != 0 {
  836. if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */
  837. if immfloat(t) {
  838. return C_HFOREG
  839. }
  840. return C_HOREG
  841. }
  842. if immfloat(t) {
  843. return C_FOREG /* n.b. that it will also satisfy immrot */
  844. }
  845. if immrot(uint32(c.instoffset)) != 0 {
  846. return C_SROREG
  847. }
  848. if immhalf(int32(c.instoffset)) {
  849. return C_HOREG
  850. }
  851. return C_SOREG
  852. }
  853. if immrot(uint32(c.instoffset)) != 0 {
  854. return C_ROREG
  855. }
  856. return C_LOREG
  857. }
  858. return C_GOK
  859. case obj.TYPE_FCONST:
  860. if c.chipzero5(a.Val.(float64)) >= 0 {
  861. return C_ZFCON
  862. }
  863. if c.chipfloat5(a.Val.(float64)) >= 0 {
  864. return C_SFCON
  865. }
  866. return C_LFCON
  867. case obj.TYPE_TEXTSIZE:
  868. return C_TEXTSIZE
  869. case obj.TYPE_CONST,
  870. obj.TYPE_ADDR:
  871. switch a.Name {
  872. case obj.NAME_NONE:
  873. c.instoffset = a.Offset
  874. if a.Reg != 0 {
  875. return c.aconsize()
  876. }
  877. if immrot(uint32(c.instoffset)) != 0 {
  878. return C_RCON
  879. }
  880. if immrot(^uint32(c.instoffset)) != 0 {
  881. return C_NCON
  882. }
  883. if uint32(c.instoffset) <= 0xffff && objabi.GOARM == 7 {
  884. return C_SCON
  885. }
  886. if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 {
  887. return C_RCON2A
  888. }
  889. if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 {
  890. return C_RCON2S
  891. }
  892. return C_LCON
  893. case obj.NAME_EXTERN,
  894. obj.NAME_GOTREF,
  895. obj.NAME_STATIC:
  896. s := a.Sym
  897. if s == nil {
  898. break
  899. }
  900. c.instoffset = 0 // s.b. unused but just in case
  901. return C_LCONADDR
  902. case obj.NAME_AUTO:
  903. if a.Reg == REGSP {
  904. // unset base register for better printing, since
  905. // a.Offset is still relative to pseudo-SP.
  906. a.Reg = obj.REG_NONE
  907. }
  908. c.instoffset = c.autosize + a.Offset
  909. return c.aconsize()
  910. case obj.NAME_PARAM:
  911. if a.Reg == REGSP {
  912. // unset base register for better printing, since
  913. // a.Offset is still relative to pseudo-FP.
  914. a.Reg = obj.REG_NONE
  915. }
  916. c.instoffset = c.autosize + a.Offset + 4
  917. return c.aconsize()
  918. }
  919. return C_GOK
  920. case obj.TYPE_BRANCH:
  921. return C_SBRA
  922. }
  923. return C_GOK
  924. }
  925. func (c *ctxt5) aconsize() int {
  926. if immrot(uint32(c.instoffset)) != 0 {
  927. return C_RACON
  928. }
  929. if immrot(uint32(-c.instoffset)) != 0 {
  930. return C_RACON
  931. }
  932. return C_LACON
  933. }
  934. func (c *ctxt5) oplook(p *obj.Prog) *Optab {
  935. a1 := int(p.Optab)
  936. if a1 != 0 {
  937. return &optab[a1-1]
  938. }
  939. a1 = int(p.From.Class)
  940. if a1 == 0 {
  941. a1 = c.aclass(&p.From) + 1
  942. p.From.Class = int8(a1)
  943. }
  944. a1--
  945. a3 := int(p.To.Class)
  946. if a3 == 0 {
  947. a3 = c.aclass(&p.To) + 1
  948. p.To.Class = int8(a3)
  949. }
  950. a3--
  951. a2 := C_NONE
  952. if p.Reg != 0 {
  953. switch {
  954. case REG_F0 <= p.Reg && p.Reg <= REG_F15:
  955. a2 = C_FREG
  956. case REG_R0 <= p.Reg && p.Reg <= REG_R15:
  957. a2 = C_REG
  958. default:
  959. c.ctxt.Diag("invalid register in %v", p)
  960. }
  961. }
  962. // check illegal base register
  963. switch a1 {
  964. case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
  965. if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg {
  966. c.ctxt.Diag("illegal base register: %v", p)
  967. }
  968. default:
  969. }
  970. switch a3 {
  971. case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
  972. if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg {
  973. c.ctxt.Diag("illegal base register: %v", p)
  974. }
  975. default:
  976. }
  977. // If current instruction has a .S suffix (flags update),
  978. // we must use the constant pool instead of splitting it.
  979. if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 {
  980. a1 = C_LCON
  981. }
  982. if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 {
  983. a3 = C_LCON
  984. }
  985. if false { /*debug['O']*/
  986. fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
  987. fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  988. }
  989. ops := oprange[p.As&obj.AMask]
  990. c1 := &xcmp[a1]
  991. c3 := &xcmp[a3]
  992. for i := range ops {
  993. op := &ops[i]
  994. if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
  995. p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  996. checkSuffix(c, p, op)
  997. return op
  998. }
  999. }
  1000. c.ctxt.Diag("illegal combination %v; %v %v %v; from %d %d; to %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.From.Name, p.To.Type, p.To.Name)
  1001. if ops == nil {
  1002. ops = optab
  1003. }
  1004. return &ops[0]
  1005. }
  1006. func cmp(a int, b int) bool {
  1007. if a == b {
  1008. return true
  1009. }
  1010. switch a {
  1011. case C_LCON:
  1012. if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S {
  1013. return true
  1014. }
  1015. case C_LACON:
  1016. if b == C_RACON {
  1017. return true
  1018. }
  1019. case C_LFCON:
  1020. if b == C_ZFCON || b == C_SFCON {
  1021. return true
  1022. }
  1023. case C_HFAUTO:
  1024. return b == C_HAUTO || b == C_FAUTO
  1025. case C_FAUTO, C_HAUTO:
  1026. return b == C_HFAUTO
  1027. case C_SAUTO:
  1028. return cmp(C_HFAUTO, b)
  1029. case C_LAUTO:
  1030. return cmp(C_SAUTO, b)
  1031. case C_HFOREG:
  1032. return b == C_HOREG || b == C_FOREG
  1033. case C_FOREG, C_HOREG:
  1034. return b == C_HFOREG
  1035. case C_SROREG:
  1036. return cmp(C_SOREG, b) || cmp(C_ROREG, b)
  1037. case C_SOREG, C_ROREG:
  1038. return b == C_SROREG || cmp(C_HFOREG, b)
  1039. case C_LOREG:
  1040. return cmp(C_SROREG, b)
  1041. case C_LBRA:
  1042. if b == C_SBRA {
  1043. return true
  1044. }
  1045. case C_HREG:
  1046. return cmp(C_SP, b) || cmp(C_PC, b)
  1047. }
  1048. return false
  1049. }
  1050. type ocmp []Optab
  1051. func (x ocmp) Len() int {
  1052. return len(x)
  1053. }
  1054. func (x ocmp) Swap(i, j int) {
  1055. x[i], x[j] = x[j], x[i]
  1056. }
  1057. func (x ocmp) Less(i, j int) bool {
  1058. p1 := &x[i]
  1059. p2 := &x[j]
  1060. n := int(p1.as) - int(p2.as)
  1061. if n != 0 {
  1062. return n < 0
  1063. }
  1064. n = int(p1.a1) - int(p2.a1)
  1065. if n != 0 {
  1066. return n < 0
  1067. }
  1068. n = int(p1.a2) - int(p2.a2)
  1069. if n != 0 {
  1070. return n < 0
  1071. }
  1072. n = int(p1.a3) - int(p2.a3)
  1073. if n != 0 {
  1074. return n < 0
  1075. }
  1076. return false
  1077. }
  1078. func opset(a, b0 obj.As) {
  1079. oprange[a&obj.AMask] = oprange[b0]
  1080. }
  1081. func buildop(ctxt *obj.Link) {
  1082. if oprange[AAND&obj.AMask] != nil {
  1083. // Already initialized; stop now.
  1084. // This happens in the cmd/asm tests,
  1085. // each of which re-initializes the arch.
  1086. return
  1087. }
  1088. deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal)
  1089. symdiv = ctxt.Lookup("runtime._div")
  1090. symdivu = ctxt.Lookup("runtime._divu")
  1091. symmod = ctxt.Lookup("runtime._mod")
  1092. symmodu = ctxt.Lookup("runtime._modu")
  1093. var n int
  1094. for i := 0; i < C_GOK; i++ {
  1095. for n = 0; n < C_GOK; n++ {
  1096. if cmp(n, i) {
  1097. xcmp[i][n] = true
  1098. }
  1099. }
  1100. }
  1101. for n = 0; optab[n].as != obj.AXXX; n++ {
  1102. if optab[n].flag&LPCREL != 0 {
  1103. if ctxt.Flag_shared {
  1104. optab[n].size += int8(optab[n].pcrelsiz)
  1105. } else {
  1106. optab[n].flag &^= LPCREL
  1107. }
  1108. }
  1109. }
  1110. sort.Sort(ocmp(optab[:n]))
  1111. for i := 0; i < n; i++ {
  1112. r := optab[i].as
  1113. r0 := r & obj.AMask
  1114. start := i
  1115. for optab[i].as == r {
  1116. i++
  1117. }
  1118. oprange[r0] = optab[start:i]
  1119. i--
  1120. switch r {
  1121. default:
  1122. ctxt.Diag("unknown op in build: %v", r)
  1123. ctxt.DiagFlush()
  1124. log.Fatalf("bad code")
  1125. case AADD:
  1126. opset(ASUB, r0)
  1127. opset(ARSB, r0)
  1128. opset(AADC, r0)
  1129. opset(ASBC, r0)
  1130. opset(ARSC, r0)
  1131. case AORR:
  1132. opset(AEOR, r0)
  1133. opset(ABIC, r0)
  1134. case ACMP:
  1135. opset(ATEQ, r0)
  1136. opset(ACMN, r0)
  1137. opset(ATST, r0)
  1138. case AMVN:
  1139. break
  1140. case ABEQ:
  1141. opset(ABNE, r0)
  1142. opset(ABCS, r0)
  1143. opset(ABHS, r0)
  1144. opset(ABCC, r0)
  1145. opset(ABLO, r0)
  1146. opset(ABMI, r0)
  1147. opset(ABPL, r0)
  1148. opset(ABVS, r0)
  1149. opset(ABVC, r0)
  1150. opset(ABHI, r0)
  1151. opset(ABLS, r0)
  1152. opset(ABGE, r0)
  1153. opset(ABLT, r0)
  1154. opset(ABGT, r0)
  1155. opset(ABLE, r0)
  1156. case ASLL:
  1157. opset(ASRL, r0)
  1158. opset(ASRA, r0)
  1159. case AMUL:
  1160. opset(AMULU, r0)
  1161. case ADIV:
  1162. opset(AMOD, r0)
  1163. opset(AMODU, r0)
  1164. opset(ADIVU, r0)
  1165. case ADIVHW:
  1166. opset(ADIVUHW, r0)
  1167. case AMOVW,
  1168. AMOVB,
  1169. AMOVBS,
  1170. AMOVBU,
  1171. AMOVH,
  1172. AMOVHS,
  1173. AMOVHU:
  1174. break
  1175. case ASWPW:
  1176. opset(ASWPBU, r0)
  1177. case AB,
  1178. ABL,
  1179. ABX,
  1180. ABXRET,
  1181. obj.ADUFFZERO,
  1182. obj.ADUFFCOPY,
  1183. ASWI,
  1184. AWORD,
  1185. AMOVM,
  1186. ARFE,
  1187. obj.ATEXT:
  1188. break
  1189. case AADDF:
  1190. opset(AADDD, r0)
  1191. opset(ASUBF, r0)
  1192. opset(ASUBD, r0)
  1193. opset(AMULF, r0)
  1194. opset(AMULD, r0)
  1195. opset(ANMULF, r0)
  1196. opset(ANMULD, r0)
  1197. opset(AMULAF, r0)
  1198. opset(AMULAD, r0)
  1199. opset(AMULSF, r0)
  1200. opset(AMULSD, r0)
  1201. opset(ANMULAF, r0)
  1202. opset(ANMULAD, r0)
  1203. opset(ANMULSF, r0)
  1204. opset(ANMULSD, r0)
  1205. opset(AFMULAF, r0)
  1206. opset(AFMULAD, r0)
  1207. opset(AFMULSF, r0)
  1208. opset(AFMULSD, r0)
  1209. opset(AFNMULAF, r0)
  1210. opset(AFNMULAD, r0)
  1211. opset(AFNMULSF, r0)
  1212. opset(AFNMULSD, r0)
  1213. opset(ADIVF, r0)
  1214. opset(ADIVD, r0)
  1215. case ANEGF:
  1216. opset(ANEGD, r0)
  1217. opset(ASQRTF, r0)
  1218. opset(ASQRTD, r0)
  1219. opset(AMOVFD, r0)
  1220. opset(AMOVDF, r0)
  1221. opset(AABSF, r0)
  1222. opset(AABSD, r0)
  1223. case ACMPF:
  1224. opset(ACMPD, r0)
  1225. case AMOVF:
  1226. opset(AMOVD, r0)
  1227. case AMOVFW:
  1228. opset(AMOVDW, r0)
  1229. case AMOVWF:
  1230. opset(AMOVWD, r0)
  1231. case AMULL:
  1232. opset(AMULAL, r0)
  1233. opset(AMULLU, r0)
  1234. opset(AMULALU, r0)
  1235. case AMULWT:
  1236. opset(AMULWB, r0)
  1237. opset(AMULBB, r0)
  1238. opset(AMMUL, r0)
  1239. case AMULAWT:
  1240. opset(AMULAWB, r0)
  1241. opset(AMULABB, r0)
  1242. opset(AMULS, r0)
  1243. opset(AMMULA, r0)
  1244. opset(AMMULS, r0)
  1245. case ABFX:
  1246. opset(ABFXU, r0)
  1247. opset(ABFC, r0)
  1248. opset(ABFI, r0)
  1249. case ACLZ:
  1250. opset(AREV, r0)
  1251. opset(AREV16, r0)
  1252. opset(AREVSH, r0)
  1253. opset(ARBIT, r0)
  1254. case AXTAB:
  1255. opset(AXTAH, r0)
  1256. opset(AXTABU, r0)
  1257. opset(AXTAHU, r0)
  1258. case ALDREX,
  1259. ASTREX,
  1260. ALDREXD,
  1261. ASTREXD,
  1262. ADMB,
  1263. APLD,
  1264. AAND,
  1265. AMULA,
  1266. obj.AUNDEF,
  1267. obj.AFUNCDATA,
  1268. obj.APCDATA,
  1269. obj.ANOP:
  1270. break
  1271. }
  1272. }
  1273. }
  1274. func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1275. c.printp = p
  1276. o1 := uint32(0)
  1277. o2 := uint32(0)
  1278. o3 := uint32(0)
  1279. o4 := uint32(0)
  1280. o5 := uint32(0)
  1281. o6 := uint32(0)
  1282. if false { /*debug['P']*/
  1283. fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  1284. }
  1285. switch o.type_ {
  1286. default:
  1287. c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  1288. case 0: /* pseudo ops */
  1289. if false { /*debug['G']*/
  1290. fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name)
  1291. }
  1292. case 1: /* op R,[R],R */
  1293. o1 = c.oprrr(p, p.As, int(p.Scond))
  1294. rf := int(p.From.Reg)
  1295. rt := int(p.To.Reg)
  1296. r := int(p.Reg)
  1297. if p.To.Type == obj.TYPE_NONE {
  1298. rt = 0
  1299. }
  1300. if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
  1301. r = 0
  1302. } else if r == 0 {
  1303. r = rt
  1304. }
  1305. o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1306. case 2: /* movbu $I,[R],R */
  1307. c.aclass(&p.From)
  1308. o1 = c.oprrr(p, p.As, int(p.Scond))
  1309. o1 |= uint32(immrot(uint32(c.instoffset)))
  1310. rt := int(p.To.Reg)
  1311. r := int(p.Reg)
  1312. if p.To.Type == obj.TYPE_NONE {
  1313. rt = 0
  1314. }
  1315. if p.As == AMOVW || p.As == AMVN {
  1316. r = 0
  1317. } else if r == 0 {
  1318. r = rt
  1319. }
  1320. o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1321. case 106: /* op $I,R,R where I can be decomposed into 2 immediates */
  1322. c.aclass(&p.From)
  1323. r := int(p.Reg)
  1324. rt := int(p.To.Reg)
  1325. if r == 0 {
  1326. r = rt
  1327. }
  1328. x, y := immrot2a(uint32(c.instoffset))
  1329. var as2 obj.As
  1330. switch p.As {
  1331. case AADD, ASUB, AORR, AEOR, ABIC:
  1332. as2 = p.As // ADD, SUB, ORR, EOR, BIC
  1333. case ARSB:
  1334. as2 = AADD // RSB -> RSB/ADD pair
  1335. case AADC:
  1336. as2 = AADD // ADC -> ADC/ADD pair
  1337. case ASBC:
  1338. as2 = ASUB // SBC -> SBC/SUB pair
  1339. case ARSC:
  1340. as2 = AADD // RSC -> RSC/ADD pair
  1341. default:
  1342. c.ctxt.Diag("unknown second op for %v", p)
  1343. }
  1344. o1 = c.oprrr(p, p.As, int(p.Scond))
  1345. o2 = c.oprrr(p, as2, int(p.Scond))
  1346. o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1347. o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
  1348. o1 |= x
  1349. o2 |= y
  1350. case 107: /* op $I,R,R where I can be decomposed into 2 immediates */
  1351. c.aclass(&p.From)
  1352. r := int(p.Reg)
  1353. rt := int(p.To.Reg)
  1354. if r == 0 {
  1355. r = rt
  1356. }
  1357. y, x := immrot2s(uint32(c.instoffset))
  1358. var as2 obj.As
  1359. switch p.As {
  1360. case AADD:
  1361. as2 = ASUB // ADD -> ADD/SUB pair
  1362. case ASUB:
  1363. as2 = AADD // SUB -> SUB/ADD pair
  1364. case ARSB:
  1365. as2 = ASUB // RSB -> RSB/SUB pair
  1366. case AADC:
  1367. as2 = ASUB // ADC -> ADC/SUB pair
  1368. case ASBC:
  1369. as2 = AADD // SBC -> SBC/ADD pair
  1370. case ARSC:
  1371. as2 = ASUB // RSC -> RSC/SUB pair
  1372. default:
  1373. c.ctxt.Diag("unknown second op for %v", p)
  1374. }
  1375. o1 = c.oprrr(p, p.As, int(p.Scond))
  1376. o2 = c.oprrr(p, as2, int(p.Scond))
  1377. o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1378. o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
  1379. o1 |= y
  1380. o2 |= x
  1381. case 3: /* add R<<[IR],[R],R */
  1382. o1 = c.mov(p)
  1383. case 4: /* MOVW $off(R), R -> add $off,[R],R */
  1384. c.aclass(&p.From)
  1385. if c.instoffset < 0 {
  1386. o1 = c.oprrr(p, ASUB, int(p.Scond))
  1387. o1 |= uint32(immrot(uint32(-c.instoffset)))
  1388. } else {
  1389. o1 = c.oprrr(p, AADD, int(p.Scond))
  1390. o1 |= uint32(immrot(uint32(c.instoffset)))
  1391. }
  1392. r := int(p.From.Reg)
  1393. if r == 0 {
  1394. r = int(o.param)
  1395. }
  1396. o1 |= (uint32(r) & 15) << 16
  1397. o1 |= (uint32(p.To.Reg) & 15) << 12
  1398. case 5: /* bra s */
  1399. o1 = c.opbra(p, p.As, int(p.Scond))
  1400. v := int32(-8)
  1401. if p.To.Sym != nil {
  1402. rel := obj.Addrel(c.cursym)
  1403. rel.Off = int32(c.pc)
  1404. rel.Siz = 4
  1405. rel.Sym = p.To.Sym
  1406. v += int32(p.To.Offset)
  1407. rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
  1408. rel.Type = objabi.R_CALLARM
  1409. break
  1410. }
  1411. if p.To.Target() != nil {
  1412. v = int32((p.To.Target().Pc - c.pc) - 8)
  1413. }
  1414. o1 |= (uint32(v) >> 2) & 0xffffff
  1415. case 6: /* b ,O(R) -> add $O,R,PC */
  1416. c.aclass(&p.To)
  1417. o1 = c.oprrr(p, AADD, int(p.Scond))
  1418. o1 |= uint32(immrot(uint32(c.instoffset)))
  1419. o1 |= (uint32(p.To.Reg) & 15) << 16
  1420. o1 |= (REGPC & 15) << 12
  1421. case 7: /* bl (R) -> blx R */
  1422. c.aclass(&p.To)
  1423. if c.instoffset != 0 {
  1424. c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset)
  1425. }
  1426. o1 = c.oprrr(p, ABL, int(p.Scond))
  1427. o1 |= (uint32(p.To.Reg) & 15) << 0
  1428. rel := obj.Addrel(c.cursym)
  1429. rel.Off = int32(c.pc)
  1430. rel.Siz = 0
  1431. rel.Type = objabi.R_CALLIND
  1432. case 8: /* sll $c,[R],R -> mov (R<<$c),R */
  1433. c.aclass(&p.From)
  1434. o1 = c.oprrr(p, p.As, int(p.Scond))
  1435. r := int(p.Reg)
  1436. if r == 0 {
  1437. r = int(p.To.Reg)
  1438. }
  1439. o1 |= (uint32(r) & 15) << 0
  1440. o1 |= uint32((c.instoffset & 31) << 7)
  1441. o1 |= (uint32(p.To.Reg) & 15) << 12
  1442. case 9: /* sll R,[R],R -> mov (R<<R),R */
  1443. o1 = c.oprrr(p, p.As, int(p.Scond))
  1444. r := int(p.Reg)
  1445. if r == 0 {
  1446. r = int(p.To.Reg)
  1447. }
  1448. o1 |= (uint32(r) & 15) << 0
  1449. o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4
  1450. o1 |= (uint32(p.To.Reg) & 15) << 12
  1451. case 10: /* swi [$con] */
  1452. o1 = c.oprrr(p, p.As, int(p.Scond))
  1453. if p.To.Type != obj.TYPE_NONE {
  1454. c.aclass(&p.To)
  1455. o1 |= uint32(c.instoffset & 0xffffff)
  1456. }
  1457. case 11: /* word */
  1458. c.aclass(&p.To)
  1459. o1 = uint32(c.instoffset)
  1460. if p.To.Sym != nil {
  1461. // This case happens with words generated
  1462. // in the PC stream as part of the literal pool (c.pool).
  1463. rel := obj.Addrel(c.cursym)
  1464. rel.Off = int32(c.pc)
  1465. rel.Siz = 4
  1466. rel.Sym = p.To.Sym
  1467. rel.Add = p.To.Offset
  1468. if c.ctxt.Flag_shared {
  1469. if p.To.Name == obj.NAME_GOTREF {
  1470. rel.Type = objabi.R_GOTPCREL
  1471. } else {
  1472. rel.Type = objabi.R_PCREL
  1473. }
  1474. rel.Add += c.pc - p.Rel.Pc - 8
  1475. } else {
  1476. rel.Type = objabi.R_ADDR
  1477. }
  1478. o1 = 0
  1479. }
  1480. case 12: /* movw $lcon, reg */
  1481. if o.a1 == C_SCON {
  1482. o1 = c.omvs(p, &p.From, int(p.To.Reg))
  1483. } else if p.As == AMVN {
  1484. o1 = c.omvr(p, &p.From, int(p.To.Reg))
  1485. } else {
  1486. o1 = c.omvl(p, &p.From, int(p.To.Reg))
  1487. }
  1488. if o.flag&LPCREL != 0 {
  1489. o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12
  1490. }
  1491. case 13: /* op $lcon, [R], R */
  1492. if o.a1 == C_SCON {
  1493. o1 = c.omvs(p, &p.From, REGTMP)
  1494. } else {
  1495. o1 = c.omvl(p, &p.From, REGTMP)
  1496. }
  1497. if o1 == 0 {
  1498. break
  1499. }
  1500. o2 = c.oprrr(p, p.As, int(p.Scond))
  1501. o2 |= REGTMP & 15
  1502. r := int(p.Reg)
  1503. if p.As == AMVN {
  1504. r = 0
  1505. } else if r == 0 {
  1506. r = int(p.To.Reg)
  1507. }
  1508. o2 |= (uint32(r) & 15) << 16
  1509. if p.To.Type != obj.TYPE_NONE {
  1510. o2 |= (uint32(p.To.Reg) & 15) << 12
  1511. }
  1512. case 14: /* movb/movbu/movh/movhu R,R */
  1513. o1 = c.oprrr(p, ASLL, int(p.Scond))
  1514. if p.As == AMOVBU || p.As == AMOVHU {
  1515. o2 = c.oprrr(p, ASRL, int(p.Scond))
  1516. } else {
  1517. o2 = c.oprrr(p, ASRA, int(p.Scond))
  1518. }
  1519. r := int(p.To.Reg)
  1520. o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12
  1521. o2 |= uint32(r)&15 | (uint32(r)&15)<<12
  1522. if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
  1523. o1 |= 24 << 7
  1524. o2 |= 24 << 7
  1525. } else {
  1526. o1 |= 16 << 7
  1527. o2 |= 16 << 7
  1528. }
  1529. case 15: /* mul r,[r,]r */
  1530. o1 = c.oprrr(p, p.As, int(p.Scond))
  1531. rf := int(p.From.Reg)
  1532. rt := int(p.To.Reg)
  1533. r := int(p.Reg)
  1534. if r == 0 {
  1535. r = rt
  1536. }
  1537. o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
  1538. case 16: /* div r,[r,]r */
  1539. o1 = 0xf << 28
  1540. o2 = 0
  1541. case 17:
  1542. o1 = c.oprrr(p, p.As, int(p.Scond))
  1543. rf := int(p.From.Reg)
  1544. rt := int(p.To.Reg)
  1545. rt2 := int(p.To.Offset)
  1546. r := int(p.Reg)
  1547. o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
  1548. case 18: /* BFX/BFXU/BFC/BFI */
  1549. o1 = c.oprrr(p, p.As, int(p.Scond))
  1550. rt := int(p.To.Reg)
  1551. r := int(p.Reg)
  1552. if r == 0 {
  1553. r = rt
  1554. } else if p.As == ABFC { // only "BFC $width, $lsb, Reg" is accepted, p.Reg must be 0
  1555. c.ctxt.Diag("illegal combination: %v", p)
  1556. }
  1557. if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST {
  1558. c.ctxt.Diag("%v: missing or wrong LSB", p)
  1559. break
  1560. }
  1561. lsb := p.GetFrom3().Offset
  1562. width := p.From.Offset
  1563. if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 32 {
  1564. c.ctxt.Diag("%v: wrong width or LSB", p)
  1565. }
  1566. switch p.As {
  1567. case ABFX, ABFXU: // (width-1) is encoded
  1568. o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
  1569. case ABFC, ABFI: // MSB is encoded
  1570. o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16
  1571. default:
  1572. c.ctxt.Diag("illegal combination: %v", p)
  1573. }
  1574. case 20: /* mov/movb/movbu R,O(R) */
  1575. c.aclass(&p.To)
  1576. r := int(p.To.Reg)
  1577. if r == 0 {
  1578. r = int(o.param)
  1579. }
  1580. o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
  1581. case 21: /* mov/movbu O(R),R -> lr */
  1582. c.aclass(&p.From)
  1583. r := int(p.From.Reg)
  1584. if r == 0 {
  1585. r = int(o.param)
  1586. }
  1587. o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
  1588. if p.As != AMOVW {
  1589. o1 |= 1 << 22
  1590. }
  1591. case 22: /* XTAB R@>i, [R], R */
  1592. o1 = c.oprrr(p, p.As, int(p.Scond))
  1593. switch p.From.Offset &^ 0xf {
  1594. // only 0/8/16/24 bits rotation is accepted
  1595. case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
  1596. o1 |= uint32(p.From.Offset) & 0xc0f
  1597. default:
  1598. c.ctxt.Diag("illegal shift: %v", p)
  1599. }
  1600. rt := p.To.Reg
  1601. r := p.Reg
  1602. if r == 0 {
  1603. r = rt
  1604. }
  1605. o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16
  1606. case 23: /* MOVW/MOVB/MOVH R@>i, R */
  1607. switch p.As {
  1608. case AMOVW:
  1609. o1 = c.mov(p)
  1610. case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH:
  1611. o1 = c.movxt(p)
  1612. default:
  1613. c.ctxt.Diag("illegal combination: %v", p)
  1614. }
  1615. case 30: /* mov/movb/movbu R,L(R) */
  1616. o1 = c.omvl(p, &p.To, REGTMP)
  1617. if o1 == 0 {
  1618. break
  1619. }
  1620. r := int(p.To.Reg)
  1621. if r == 0 {
  1622. r = int(o.param)
  1623. }
  1624. o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
  1625. if p.As != AMOVW {
  1626. o2 |= 1 << 22
  1627. }
  1628. case 31: /* mov/movbu L(R),R -> lr[b] */
  1629. o1 = c.omvl(p, &p.From, REGTMP)
  1630. if o1 == 0 {
  1631. break
  1632. }
  1633. r := int(p.From.Reg)
  1634. if r == 0 {
  1635. r = int(o.param)
  1636. }
  1637. o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
  1638. if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
  1639. o2 |= 1 << 22
  1640. }
  1641. case 34: /* mov $lacon,R */
  1642. o1 = c.omvl(p, &p.From, REGTMP)
  1643. if o1 == 0 {
  1644. break
  1645. }
  1646. o2 = c.oprrr(p, AADD, int(p.Scond))
  1647. o2 |= REGTMP & 15
  1648. r := int(p.From.Reg)
  1649. if r == 0 {
  1650. r = int(o.param)
  1651. }
  1652. o2 |= (uint32(r) & 15) << 16
  1653. if p.To.Type != obj.TYPE_NONE {
  1654. o2 |= (uint32(p.To.Reg) & 15) << 12
  1655. }
  1656. case 35: /* mov PSR,R */
  1657. o1 = 2<<23 | 0xf<<16 | 0<<0
  1658. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  1659. o1 |= (uint32(p.From.Reg) & 1) << 22
  1660. o1 |= (uint32(p.To.Reg) & 15) << 12
  1661. case 36: /* mov R,PSR */
  1662. o1 = 2<<23 | 0x2cf<<12 | 0<<4
  1663. if p.Scond&C_FBIT != 0 {
  1664. o1 ^= 0x010 << 12
  1665. }
  1666. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  1667. o1 |= (uint32(p.To.Reg) & 1) << 22
  1668. o1 |= (uint32(p.From.Reg) & 15) << 0
  1669. case 37: /* mov $con,PSR */
  1670. c.aclass(&p.From)
  1671. o1 = 2<<23 | 0x2cf<<12 | 0<<4
  1672. if p.Scond&C_FBIT != 0 {
  1673. o1 ^= 0x010 << 12
  1674. }
  1675. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  1676. o1 |= uint32(immrot(uint32(c.instoffset)))
  1677. o1 |= (uint32(p.To.Reg) & 1) << 22
  1678. o1 |= (uint32(p.From.Reg) & 15) << 0
  1679. case 38, 39:
  1680. switch o.type_ {
  1681. case 38: /* movm $con,oreg -> stm */
  1682. o1 = 0x4 << 25
  1683. o1 |= uint32(p.From.Offset & 0xffff)
  1684. o1 |= (uint32(p.To.Reg) & 15) << 16
  1685. c.aclass(&p.To)
  1686. case 39: /* movm oreg,$con -> ldm */
  1687. o1 = 0x4<<25 | 1<<20
  1688. o1 |= uint32(p.To.Offset & 0xffff)
  1689. o1 |= (uint32(p.From.Reg) & 15) << 16
  1690. c.aclass(&p.From)
  1691. }
  1692. if c.instoffset != 0 {
  1693. c.ctxt.Diag("offset must be zero in MOVM; %v", p)
  1694. }
  1695. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  1696. if p.Scond&C_PBIT != 0 {
  1697. o1 |= 1 << 24
  1698. }
  1699. if p.Scond&C_UBIT != 0 {
  1700. o1 |= 1 << 23
  1701. }
  1702. if p.Scond&C_WBIT != 0 {
  1703. o1 |= 1 << 21
  1704. }
  1705. case 40: /* swp oreg,reg,reg */
  1706. c.aclass(&p.From)
  1707. if c.instoffset != 0 {
  1708. c.ctxt.Diag("offset must be zero in SWP")
  1709. }
  1710. o1 = 0x2<<23 | 0x9<<4
  1711. if p.As != ASWPW {
  1712. o1 |= 1 << 22
  1713. }
  1714. o1 |= (uint32(p.From.Reg) & 15) << 16
  1715. o1 |= (uint32(p.Reg) & 15) << 0
  1716. o1 |= (uint32(p.To.Reg) & 15) << 12
  1717. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  1718. case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
  1719. o1 = 0xe8fd8000
  1720. case 50: /* floating point store */
  1721. v := c.regoff(&p.To)
  1722. r := int(p.To.Reg)
  1723. if r == 0 {
  1724. r = int(o.param)
  1725. }
  1726. o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p)
  1727. case 51: /* floating point load */
  1728. v := c.regoff(&p.From)
  1729. r := int(p.From.Reg)
  1730. if r == 0 {
  1731. r = int(o.param)
  1732. }
  1733. o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
  1734. case 52: /* floating point store, int32 offset UGLY */
  1735. o1 = c.omvl(p, &p.To, REGTMP)
  1736. if o1 == 0 {
  1737. break
  1738. }
  1739. r := int(p.To.Reg)
  1740. if r == 0 {
  1741. r = int(o.param)
  1742. }
  1743. o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
  1744. o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
  1745. case 53: /* floating point load, int32 offset UGLY */
  1746. o1 = c.omvl(p, &p.From, REGTMP)
  1747. if o1 == 0 {
  1748. break
  1749. }
  1750. r := int(p.From.Reg)
  1751. if r == 0 {
  1752. r = int(o.param)
  1753. }
  1754. o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
  1755. o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
  1756. case 54: /* floating point arith */
  1757. o1 = c.oprrr(p, p.As, int(p.Scond))
  1758. rf := int(p.From.Reg)
  1759. rt := int(p.To.Reg)
  1760. r := int(p.Reg)
  1761. if r == 0 {
  1762. switch p.As {
  1763. case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD,
  1764. AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD:
  1765. c.ctxt.Diag("illegal combination: %v", p)
  1766. default:
  1767. r = rt
  1768. }
  1769. }
  1770. o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1771. case 55: /* negf freg, freg */
  1772. o1 = c.oprrr(p, p.As, int(p.Scond))
  1773. rf := int(p.From.Reg)
  1774. rt := int(p.To.Reg)
  1775. o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12
  1776. case 56: /* move to FP[CS]R */
  1777. o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4
  1778. o1 |= (uint32(p.From.Reg) & 15) << 12
  1779. case 57: /* move from FP[CS]R */
  1780. o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4
  1781. o1 |= (uint32(p.To.Reg) & 15) << 12
  1782. case 58: /* movbu R,R */
  1783. o1 = c.oprrr(p, AAND, int(p.Scond))
  1784. o1 |= uint32(immrot(0xff))
  1785. rt := int(p.To.Reg)
  1786. r := int(p.From.Reg)
  1787. if p.To.Type == obj.TYPE_NONE {
  1788. rt = 0
  1789. }
  1790. if r == 0 {
  1791. r = rt
  1792. }
  1793. o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  1794. case 59: /* movw/bu R<<I(R),R -> ldr indexed */
  1795. if p.From.Reg == 0 {
  1796. c.ctxt.Diag("source operand is not a memory address: %v", p)
  1797. break
  1798. }
  1799. if p.From.Offset&(1<<4) != 0 {
  1800. c.ctxt.Diag("bad shift in LDR")
  1801. break
  1802. }
  1803. o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
  1804. if p.As == AMOVBU {
  1805. o1 |= 1 << 22
  1806. }
  1807. case 60: /* movb R(R),R -> ldrsb indexed */
  1808. if p.From.Reg == 0 {
  1809. c.ctxt.Diag("source operand is not a memory address: %v", p)
  1810. break
  1811. }
  1812. if p.From.Offset&(^0xf) != 0 {
  1813. c.ctxt.Diag("bad shift: %v", p)
  1814. break
  1815. }
  1816. o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
  1817. switch p.As {
  1818. case AMOVB, AMOVBS:
  1819. o1 ^= 1<<5 | 1<<6
  1820. case AMOVH, AMOVHS:
  1821. o1 ^= 1 << 6
  1822. default:
  1823. }
  1824. if p.Scond&C_UBIT != 0 {
  1825. o1 &^= 1 << 23
  1826. }
  1827. case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
  1828. if p.To.Reg == 0 {
  1829. c.ctxt.Diag("MOV to shifter operand")
  1830. }
  1831. o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
  1832. if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
  1833. o1 |= 1 << 22
  1834. }
  1835. case 62: /* MOVH/MOVHS/MOVHU Reg, Reg<<0(Reg) -> strh */
  1836. if p.To.Reg == 0 {
  1837. c.ctxt.Diag("MOV to shifter operand")
  1838. }
  1839. if p.To.Offset&(^0xf) != 0 {
  1840. c.ctxt.Diag("bad shift: %v", p)
  1841. }
  1842. o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond))
  1843. o1 ^= 1 << 20
  1844. if p.Scond&C_UBIT != 0 {
  1845. o1 &^= 1 << 23
  1846. }
  1847. /* reloc ops */
  1848. case 64: /* mov/movb/movbu R,addr */
  1849. o1 = c.omvl(p, &p.To, REGTMP)
  1850. if o1 == 0 {
  1851. break
  1852. }
  1853. o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond))
  1854. if o.flag&LPCREL != 0 {
  1855. o3 = o2
  1856. o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  1857. }
  1858. case 65: /* mov/movbu addr,R */
  1859. o1 = c.omvl(p, &p.From, REGTMP)
  1860. if o1 == 0 {
  1861. break
  1862. }
  1863. o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond))
  1864. if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
  1865. o2 |= 1 << 22
  1866. }
  1867. if o.flag&LPCREL != 0 {
  1868. o3 = o2
  1869. o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  1870. }
  1871. case 101: /* movw tlsvar,R, local exec*/
  1872. o1 = c.omvl(p, &p.From, int(p.To.Reg))
  1873. case 102: /* movw tlsvar,R, initial exec*/
  1874. o1 = c.omvl(p, &p.From, int(p.To.Reg))
  1875. o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
  1876. case 103: /* word tlsvar, local exec */
  1877. if p.To.Sym == nil {
  1878. c.ctxt.Diag("nil sym in tls %v", p)
  1879. }
  1880. if p.To.Offset != 0 {
  1881. c.ctxt.Diag("offset against tls var in %v", p)
  1882. }
  1883. // This case happens with words generated in the PC stream as part of
  1884. // the literal c.pool.
  1885. rel := obj.Addrel(c.cursym)
  1886. rel.Off = int32(c.pc)
  1887. rel.Siz = 4
  1888. rel.Sym = p.To.Sym
  1889. rel.Type = objabi.R_TLS_LE
  1890. o1 = 0
  1891. case 104: /* word tlsvar, initial exec */
  1892. if p.To.Sym == nil {
  1893. c.ctxt.Diag("nil sym in tls %v", p)
  1894. }
  1895. if p.To.Offset != 0 {
  1896. c.ctxt.Diag("offset against tls var in %v", p)
  1897. }
  1898. rel := obj.Addrel(c.cursym)
  1899. rel.Off = int32(c.pc)
  1900. rel.Siz = 4
  1901. rel.Sym = p.To.Sym
  1902. rel.Type = objabi.R_TLS_IE
  1903. rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz)
  1904. case 68: /* floating point store -> ADDR */
  1905. o1 = c.omvl(p, &p.To, REGTMP)
  1906. if o1 == 0 {
  1907. break
  1908. }
  1909. o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
  1910. if o.flag&LPCREL != 0 {
  1911. o3 = o2
  1912. o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  1913. }
  1914. case 69: /* floating point load <- ADDR */
  1915. o1 = c.omvl(p, &p.From, REGTMP)
  1916. if o1 == 0 {
  1917. break
  1918. }
  1919. o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
  1920. if o.flag&LPCREL != 0 {
  1921. o3 = o2
  1922. o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  1923. }
  1924. /* ArmV4 ops: */
  1925. case 70: /* movh/movhu R,O(R) -> strh */
  1926. c.aclass(&p.To)
  1927. r := int(p.To.Reg)
  1928. if r == 0 {
  1929. r = int(o.param)
  1930. }
  1931. o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
  1932. case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
  1933. c.aclass(&p.From)
  1934. r := int(p.From.Reg)
  1935. if r == 0 {
  1936. r = int(o.param)
  1937. }
  1938. o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
  1939. if p.As == AMOVB || p.As == AMOVBS {
  1940. o1 ^= 1<<5 | 1<<6
  1941. } else if p.As == AMOVH || p.As == AMOVHS {
  1942. o1 ^= (1 << 6)
  1943. }
  1944. case 72: /* movh/movhu R,L(R) -> strh */
  1945. o1 = c.omvl(p, &p.To, REGTMP)
  1946. if o1 == 0 {
  1947. break
  1948. }
  1949. r := int(p.To.Reg)
  1950. if r == 0 {
  1951. r = int(o.param)
  1952. }
  1953. o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
  1954. case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
  1955. o1 = c.omvl(p, &p.From, REGTMP)
  1956. if o1 == 0 {
  1957. break
  1958. }
  1959. r := int(p.From.Reg)
  1960. if r == 0 {
  1961. r = int(o.param)
  1962. }
  1963. o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
  1964. if p.As == AMOVB || p.As == AMOVBS {
  1965. o2 ^= 1<<5 | 1<<6
  1966. } else if p.As == AMOVH || p.As == AMOVHS {
  1967. o2 ^= (1 << 6)
  1968. }
  1969. case 74: /* bx $I */
  1970. c.ctxt.Diag("ABX $I")
  1971. case 75: /* bx O(R) */
  1972. c.aclass(&p.To)
  1973. if c.instoffset != 0 {
  1974. c.ctxt.Diag("non-zero offset in ABX")
  1975. }
  1976. /*
  1977. o1 = c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR
  1978. o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R
  1979. */
  1980. // p->to.reg may be REGLINK
  1981. o1 = c.oprrr(p, AADD, int(p.Scond))
  1982. o1 |= uint32(immrot(uint32(c.instoffset)))
  1983. o1 |= (uint32(p.To.Reg) & 15) << 16
  1984. o1 |= (REGTMP & 15) << 12
  1985. o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR
  1986. o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15 // BX Rtmp
  1987. case 76: /* bx O(R) when returning from fn*/
  1988. c.ctxt.Diag("ABXRET")
  1989. case 77: /* ldrex oreg,reg */
  1990. c.aclass(&p.From)
  1991. if c.instoffset != 0 {
  1992. c.ctxt.Diag("offset must be zero in LDREX")
  1993. }
  1994. o1 = 0x19<<20 | 0xf9f
  1995. o1 |= (uint32(p.From.Reg) & 15) << 16
  1996. o1 |= (uint32(p.To.Reg) & 15) << 12
  1997. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  1998. case 78: /* strex reg,oreg,reg */
  1999. c.aclass(&p.From)
  2000. if c.instoffset != 0 {
  2001. c.ctxt.Diag("offset must be zero in STREX")
  2002. }
  2003. if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg {
  2004. c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
  2005. }
  2006. o1 = 0x18<<20 | 0xf90
  2007. o1 |= (uint32(p.From.Reg) & 15) << 16
  2008. o1 |= (uint32(p.Reg) & 15) << 0
  2009. o1 |= (uint32(p.To.Reg) & 15) << 12
  2010. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2011. case 80: /* fmov zfcon,freg */
  2012. if p.As == AMOVD {
  2013. o1 = 0xeeb00b00 // VMOV imm 64
  2014. o2 = c.oprrr(p, ASUBD, int(p.Scond))
  2015. } else {
  2016. o1 = 0x0eb00a00 // VMOV imm 32
  2017. o2 = c.oprrr(p, ASUBF, int(p.Scond))
  2018. }
  2019. v := int32(0x70) // 1.0
  2020. r := (int(p.To.Reg) & 15) << 0
  2021. // movf $1.0, r
  2022. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2023. o1 |= (uint32(r) & 15) << 12
  2024. o1 |= (uint32(v) & 0xf) << 0
  2025. o1 |= (uint32(v) & 0xf0) << 12
  2026. // subf r,r,r
  2027. o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12
  2028. case 81: /* fmov sfcon,freg */
  2029. o1 = 0x0eb00a00 // VMOV imm 32
  2030. if p.As == AMOVD {
  2031. o1 = 0xeeb00b00 // VMOV imm 64
  2032. }
  2033. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2034. o1 |= (uint32(p.To.Reg) & 15) << 12
  2035. v := int32(c.chipfloat5(p.From.Val.(float64)))
  2036. o1 |= (uint32(v) & 0xf) << 0
  2037. o1 |= (uint32(v) & 0xf0) << 12
  2038. case 82: /* fcmp freg,freg, */
  2039. o1 = c.oprrr(p, p.As, int(p.Scond))
  2040. o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0
  2041. o2 = 0x0ef1fa10 // VMRS R15
  2042. o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2043. case 83: /* fcmp freg,, */
  2044. o1 = c.oprrr(p, p.As, int(p.Scond))
  2045. o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16
  2046. o2 = 0x0ef1fa10 // VMRS R15
  2047. o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2048. case 84: /* movfw freg,freg - truncate float-to-fix */
  2049. o1 = c.oprrr(p, p.As, int(p.Scond))
  2050. o1 |= (uint32(p.From.Reg) & 15) << 0
  2051. o1 |= (uint32(p.To.Reg) & 15) << 12
  2052. case 85: /* movwf freg,freg - fix-to-float */
  2053. o1 = c.oprrr(p, p.As, int(p.Scond))
  2054. o1 |= (uint32(p.From.Reg) & 15) << 0
  2055. o1 |= (uint32(p.To.Reg) & 15) << 12
  2056. // macro for movfw freg,FTMP; movw FTMP,reg
  2057. case 86: /* movfw freg,reg - truncate float-to-fix */
  2058. o1 = c.oprrr(p, p.As, int(p.Scond))
  2059. o1 |= (uint32(p.From.Reg) & 15) << 0
  2060. o1 |= (FREGTMP & 15) << 12
  2061. o2 = c.oprrr(p, -AMOVFW, int(p.Scond))
  2062. o2 |= (FREGTMP & 15) << 16
  2063. o2 |= (uint32(p.To.Reg) & 15) << 12
  2064. // macro for movw reg,FTMP; movwf FTMP,freg
  2065. case 87: /* movwf reg,freg - fix-to-float */
  2066. o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
  2067. o1 |= (uint32(p.From.Reg) & 15) << 12
  2068. o1 |= (FREGTMP & 15) << 16
  2069. o2 = c.oprrr(p, p.As, int(p.Scond))
  2070. o2 |= (FREGTMP & 15) << 0
  2071. o2 |= (uint32(p.To.Reg) & 15) << 12
  2072. case 88: /* movw reg,freg */
  2073. o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
  2074. o1 |= (uint32(p.From.Reg) & 15) << 12
  2075. o1 |= (uint32(p.To.Reg) & 15) << 16
  2076. case 89: /* movw freg,reg */
  2077. o1 = c.oprrr(p, -AMOVFW, int(p.Scond))
  2078. o1 |= (uint32(p.From.Reg) & 15) << 16
  2079. o1 |= (uint32(p.To.Reg) & 15) << 12
  2080. case 91: /* ldrexd oreg,reg */
  2081. c.aclass(&p.From)
  2082. if c.instoffset != 0 {
  2083. c.ctxt.Diag("offset must be zero in LDREX")
  2084. }
  2085. o1 = 0x1b<<20 | 0xf9f
  2086. o1 |= (uint32(p.From.Reg) & 15) << 16
  2087. o1 |= (uint32(p.To.Reg) & 15) << 12
  2088. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2089. case 92: /* strexd reg,oreg,reg */
  2090. c.aclass(&p.From)
  2091. if c.instoffset != 0 {
  2092. c.ctxt.Diag("offset must be zero in STREX")
  2093. }
  2094. if p.Reg&1 != 0 {
  2095. c.ctxt.Diag("source register must be even in STREXD: %v", p)
  2096. }
  2097. if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 {
  2098. c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
  2099. }
  2100. o1 = 0x1a<<20 | 0xf90
  2101. o1 |= (uint32(p.From.Reg) & 15) << 16
  2102. o1 |= (uint32(p.Reg) & 15) << 0
  2103. o1 |= (uint32(p.To.Reg) & 15) << 12
  2104. o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2105. case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
  2106. o1 = c.omvl(p, &p.From, REGTMP)
  2107. if o1 == 0 {
  2108. break
  2109. }
  2110. o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond))
  2111. if p.As == AMOVB || p.As == AMOVBS {
  2112. o2 ^= 1<<5 | 1<<6
  2113. } else if p.As == AMOVH || p.As == AMOVHS {
  2114. o2 ^= (1 << 6)
  2115. }
  2116. if o.flag&LPCREL != 0 {
  2117. o3 = o2
  2118. o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2119. }
  2120. case 94: /* movh/movhu R,addr -> strh */
  2121. o1 = c.omvl(p, &p.To, REGTMP)
  2122. if o1 == 0 {
  2123. break
  2124. }
  2125. o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond))
  2126. if o.flag&LPCREL != 0 {
  2127. o3 = o2
  2128. o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
  2129. }
  2130. case 95: /* PLD off(reg) */
  2131. o1 = 0xf5d0f000
  2132. o1 |= (uint32(p.From.Reg) & 15) << 16
  2133. if p.From.Offset < 0 {
  2134. o1 &^= (1 << 23)
  2135. o1 |= uint32((-p.From.Offset) & 0xfff)
  2136. } else {
  2137. o1 |= uint32(p.From.Offset & 0xfff)
  2138. }
  2139. // This is supposed to be something that stops execution.
  2140. // It's not supposed to be reached, ever, but if it is, we'd
  2141. // like to be able to tell how we got there. Assemble as
  2142. // 0xf7fabcfd which is guaranteed to raise undefined instruction
  2143. // exception.
  2144. case 96: /* UNDEF */
  2145. o1 = 0xf7fabcfd
  2146. case 97: /* CLZ Rm, Rd */
  2147. o1 = c.oprrr(p, p.As, int(p.Scond))
  2148. o1 |= (uint32(p.To.Reg) & 15) << 12
  2149. o1 |= (uint32(p.From.Reg) & 15) << 0
  2150. case 98: /* MULW{T,B} Rs, Rm, Rd */
  2151. o1 = c.oprrr(p, p.As, int(p.Scond))
  2152. o1 |= (uint32(p.To.Reg) & 15) << 16
  2153. o1 |= (uint32(p.From.Reg) & 15) << 8
  2154. o1 |= (uint32(p.Reg) & 15) << 0
  2155. case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
  2156. o1 = c.oprrr(p, p.As, int(p.Scond))
  2157. o1 |= (uint32(p.To.Reg) & 15) << 16
  2158. o1 |= (uint32(p.From.Reg) & 15) << 8
  2159. o1 |= (uint32(p.Reg) & 15) << 0
  2160. o1 |= uint32((p.To.Offset & 15) << 12)
  2161. case 105: /* divhw r,[r,]r */
  2162. o1 = c.oprrr(p, p.As, int(p.Scond))
  2163. rf := int(p.From.Reg)
  2164. rt := int(p.To.Reg)
  2165. r := int(p.Reg)
  2166. if r == 0 {
  2167. r = rt
  2168. }
  2169. o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
  2170. case 110: /* dmb [mbop | $con] */
  2171. o1 = 0xf57ff050
  2172. mbop := uint32(0)
  2173. switch c.aclass(&p.From) {
  2174. case C_SPR:
  2175. for _, f := range mbOp {
  2176. if f.reg == p.From.Reg {
  2177. mbop = f.enc
  2178. break
  2179. }
  2180. }
  2181. case C_RCON:
  2182. for _, f := range mbOp {
  2183. enc := uint32(c.instoffset)
  2184. if f.enc == enc {
  2185. mbop = enc
  2186. break
  2187. }
  2188. }
  2189. case C_NONE:
  2190. mbop = 0xf
  2191. }
  2192. if mbop == 0 {
  2193. c.ctxt.Diag("illegal mb option:\n%v", p)
  2194. }
  2195. o1 |= mbop
  2196. }
  2197. out[0] = o1
  2198. out[1] = o2
  2199. out[2] = o3
  2200. out[3] = o4
  2201. out[4] = o5
  2202. out[5] = o6
  2203. }
  2204. func (c *ctxt5) movxt(p *obj.Prog) uint32 {
  2205. o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2206. switch p.As {
  2207. case AMOVB, AMOVBS:
  2208. o1 |= 0x6af<<16 | 0x7<<4
  2209. case AMOVH, AMOVHS:
  2210. o1 |= 0x6bf<<16 | 0x7<<4
  2211. case AMOVBU:
  2212. o1 |= 0x6ef<<16 | 0x7<<4
  2213. case AMOVHU:
  2214. o1 |= 0x6ff<<16 | 0x7<<4
  2215. default:
  2216. c.ctxt.Diag("illegal combination: %v", p)
  2217. }
  2218. switch p.From.Offset &^ 0xf {
  2219. // only 0/8/16/24 bits rotation is accepted
  2220. case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
  2221. o1 |= uint32(p.From.Offset) & 0xc0f
  2222. default:
  2223. c.ctxt.Diag("illegal shift: %v", p)
  2224. }
  2225. o1 |= (uint32(p.To.Reg) & 15) << 12
  2226. return o1
  2227. }
  2228. func (c *ctxt5) mov(p *obj.Prog) uint32 {
  2229. c.aclass(&p.From)
  2230. o1 := c.oprrr(p, p.As, int(p.Scond))
  2231. o1 |= uint32(p.From.Offset)
  2232. rt := int(p.To.Reg)
  2233. if p.To.Type == obj.TYPE_NONE {
  2234. rt = 0
  2235. }
  2236. r := int(p.Reg)
  2237. if p.As == AMOVW || p.As == AMVN {
  2238. r = 0
  2239. } else if r == 0 {
  2240. r = rt
  2241. }
  2242. o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
  2243. return o1
  2244. }
  2245. func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
  2246. o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2247. if sc&C_SBIT != 0 {
  2248. o |= 1 << 20
  2249. }
  2250. switch a {
  2251. case ADIVHW:
  2252. return o | 0x71<<20 | 0xf<<12 | 0x1<<4
  2253. case ADIVUHW:
  2254. return o | 0x73<<20 | 0xf<<12 | 0x1<<4
  2255. case AMMUL:
  2256. return o | 0x75<<20 | 0xf<<12 | 0x1<<4
  2257. case AMULS:
  2258. return o | 0x6<<20 | 0x9<<4
  2259. case AMMULA:
  2260. return o | 0x75<<20 | 0x1<<4
  2261. case AMMULS:
  2262. return o | 0x75<<20 | 0xd<<4
  2263. case AMULU, AMUL:
  2264. return o | 0x0<<21 | 0x9<<4
  2265. case AMULA:
  2266. return o | 0x1<<21 | 0x9<<4
  2267. case AMULLU:
  2268. return o | 0x4<<21 | 0x9<<4
  2269. case AMULL:
  2270. return o | 0x6<<21 | 0x9<<4
  2271. case AMULALU:
  2272. return o | 0x5<<21 | 0x9<<4
  2273. case AMULAL:
  2274. return o | 0x7<<21 | 0x9<<4
  2275. case AAND:
  2276. return o | 0x0<<21
  2277. case AEOR:
  2278. return o | 0x1<<21
  2279. case ASUB:
  2280. return o | 0x2<<21
  2281. case ARSB:
  2282. return o | 0x3<<21
  2283. case AADD:
  2284. return o | 0x4<<21
  2285. case AADC:
  2286. return o | 0x5<<21
  2287. case ASBC:
  2288. return o | 0x6<<21
  2289. case ARSC:
  2290. return o | 0x7<<21
  2291. case ATST:
  2292. return o | 0x8<<21 | 1<<20
  2293. case ATEQ:
  2294. return o | 0x9<<21 | 1<<20
  2295. case ACMP:
  2296. return o | 0xa<<21 | 1<<20
  2297. case ACMN:
  2298. return o | 0xb<<21 | 1<<20
  2299. case AORR:
  2300. return o | 0xc<<21
  2301. case AMOVB, AMOVH, AMOVW:
  2302. if sc&(C_PBIT|C_WBIT) != 0 {
  2303. c.ctxt.Diag("invalid .P/.W suffix: %v", p)
  2304. }
  2305. return o | 0xd<<21
  2306. case ABIC:
  2307. return o | 0xe<<21
  2308. case AMVN:
  2309. return o | 0xf<<21
  2310. case ASLL:
  2311. return o | 0xd<<21 | 0<<5
  2312. case ASRL:
  2313. return o | 0xd<<21 | 1<<5
  2314. case ASRA:
  2315. return o | 0xd<<21 | 2<<5
  2316. case ASWI:
  2317. return o | 0xf<<24
  2318. case AADDD:
  2319. return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
  2320. case AADDF:
  2321. return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
  2322. case ASUBD:
  2323. return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
  2324. case ASUBF:
  2325. return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
  2326. case AMULD:
  2327. return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
  2328. case AMULF:
  2329. return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
  2330. case ANMULD:
  2331. return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4
  2332. case ANMULF:
  2333. return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4
  2334. case AMULAD:
  2335. return o | 0xe<<24 | 0xb<<8
  2336. case AMULAF:
  2337. return o | 0xe<<24 | 0xa<<8
  2338. case AMULSD:
  2339. return o | 0xe<<24 | 0xb<<8 | 0x4<<4
  2340. case AMULSF:
  2341. return o | 0xe<<24 | 0xa<<8 | 0x4<<4
  2342. case ANMULAD:
  2343. return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4
  2344. case ANMULAF:
  2345. return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4
  2346. case ANMULSD:
  2347. return o | 0xe<<24 | 0x1<<20 | 0xb<<8
  2348. case ANMULSF:
  2349. return o | 0xe<<24 | 0x1<<20 | 0xa<<8
  2350. case AFMULAD:
  2351. return o | 0xe<<24 | 0xa<<20 | 0xb<<8
  2352. case AFMULAF:
  2353. return o | 0xe<<24 | 0xa<<20 | 0xa<<8
  2354. case AFMULSD:
  2355. return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4
  2356. case AFMULSF:
  2357. return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4
  2358. case AFNMULAD:
  2359. return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4
  2360. case AFNMULAF:
  2361. return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4
  2362. case AFNMULSD:
  2363. return o | 0xe<<24 | 0x9<<20 | 0xb<<8
  2364. case AFNMULSF:
  2365. return o | 0xe<<24 | 0x9<<20 | 0xa<<8
  2366. case ADIVD:
  2367. return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
  2368. case ADIVF:
  2369. return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
  2370. case ASQRTD:
  2371. return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
  2372. case ASQRTF:
  2373. return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
  2374. case AABSD:
  2375. return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
  2376. case AABSF:
  2377. return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
  2378. case ANEGD:
  2379. return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4
  2380. case ANEGF:
  2381. return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4
  2382. case ACMPD:
  2383. return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
  2384. case ACMPF:
  2385. return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
  2386. case AMOVF:
  2387. return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
  2388. case AMOVD:
  2389. return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
  2390. case AMOVDF:
  2391. return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
  2392. case AMOVFD:
  2393. return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
  2394. case AMOVWF:
  2395. if sc&C_UBIT == 0 {
  2396. o |= 1 << 7 /* signed */
  2397. }
  2398. return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
  2399. case AMOVWD:
  2400. if sc&C_UBIT == 0 {
  2401. o |= 1 << 7 /* signed */
  2402. }
  2403. return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
  2404. case AMOVFW:
  2405. if sc&C_UBIT == 0 {
  2406. o |= 1 << 16 /* signed */
  2407. }
  2408. return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
  2409. case AMOVDW:
  2410. if sc&C_UBIT == 0 {
  2411. o |= 1 << 16 /* signed */
  2412. }
  2413. return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
  2414. case -AMOVWF: // copy WtoF
  2415. return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
  2416. case -AMOVFW: // copy FtoW
  2417. return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
  2418. case -ACMP: // cmp imm
  2419. return o | 0x3<<24 | 0x5<<20
  2420. case ABFX:
  2421. return o | 0x3d<<21 | 0x5<<4
  2422. case ABFXU:
  2423. return o | 0x3f<<21 | 0x5<<4
  2424. case ABFC:
  2425. return o | 0x3e<<21 | 0x1f
  2426. case ABFI:
  2427. return o | 0x3e<<21 | 0x1<<4
  2428. case AXTAB:
  2429. return o | 0x6a<<20 | 0x7<<4
  2430. case AXTAH:
  2431. return o | 0x6b<<20 | 0x7<<4
  2432. case AXTABU:
  2433. return o | 0x6e<<20 | 0x7<<4
  2434. case AXTAHU:
  2435. return o | 0x6f<<20 | 0x7<<4
  2436. // CLZ doesn't support .nil
  2437. case ACLZ:
  2438. return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
  2439. case AREV:
  2440. return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4
  2441. case AREV16:
  2442. return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4
  2443. case AREVSH:
  2444. return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4
  2445. case ARBIT:
  2446. return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4
  2447. case AMULWT:
  2448. return o&(0xf<<28) | 0x12<<20 | 0xe<<4
  2449. case AMULWB:
  2450. return o&(0xf<<28) | 0x12<<20 | 0xa<<4
  2451. case AMULBB:
  2452. return o&(0xf<<28) | 0x16<<20 | 0x8<<4
  2453. case AMULAWT:
  2454. return o&(0xf<<28) | 0x12<<20 | 0xc<<4
  2455. case AMULAWB:
  2456. return o&(0xf<<28) | 0x12<<20 | 0x8<<4
  2457. case AMULABB:
  2458. return o&(0xf<<28) | 0x10<<20 | 0x8<<4
  2459. case ABL: // BLX REG
  2460. return o&(0xf<<28) | 0x12fff3<<4
  2461. }
  2462. c.ctxt.Diag("%v: bad rrr %d", p, a)
  2463. return 0
  2464. }
  2465. func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
  2466. sc &= C_SCOND
  2467. sc ^= C_SCOND_XOR
  2468. if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
  2469. return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
  2470. }
  2471. if sc != 0xe {
  2472. c.ctxt.Diag("%v: .COND on bcond instruction", p)
  2473. }
  2474. switch a {
  2475. case ABEQ:
  2476. return 0x0<<28 | 0x5<<25
  2477. case ABNE:
  2478. return 0x1<<28 | 0x5<<25
  2479. case ABCS:
  2480. return 0x2<<28 | 0x5<<25
  2481. case ABHS:
  2482. return 0x2<<28 | 0x5<<25
  2483. case ABCC:
  2484. return 0x3<<28 | 0x5<<25
  2485. case ABLO:
  2486. return 0x3<<28 | 0x5<<25
  2487. case ABMI:
  2488. return 0x4<<28 | 0x5<<25
  2489. case ABPL:
  2490. return 0x5<<28 | 0x5<<25
  2491. case ABVS:
  2492. return 0x6<<28 | 0x5<<25
  2493. case ABVC:
  2494. return 0x7<<28 | 0x5<<25
  2495. case ABHI:
  2496. return 0x8<<28 | 0x5<<25
  2497. case ABLS:
  2498. return 0x9<<28 | 0x5<<25
  2499. case ABGE:
  2500. return 0xa<<28 | 0x5<<25
  2501. case ABLT:
  2502. return 0xb<<28 | 0x5<<25
  2503. case ABGT:
  2504. return 0xc<<28 | 0x5<<25
  2505. case ABLE:
  2506. return 0xd<<28 | 0x5<<25
  2507. case AB:
  2508. return 0xe<<28 | 0x5<<25
  2509. }
  2510. c.ctxt.Diag("%v: bad bra %v", p, a)
  2511. return 0
  2512. }
  2513. func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
  2514. o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2515. if sc&C_PBIT == 0 {
  2516. o |= 1 << 24
  2517. }
  2518. if sc&C_UBIT == 0 {
  2519. o |= 1 << 23
  2520. }
  2521. if sc&C_WBIT != 0 {
  2522. o |= 1 << 21
  2523. }
  2524. o |= 1<<26 | 1<<20
  2525. if v < 0 {
  2526. if sc&C_UBIT != 0 {
  2527. c.ctxt.Diag(".U on neg offset")
  2528. }
  2529. v = -v
  2530. o ^= 1 << 23
  2531. }
  2532. if v >= 1<<12 || v < 0 {
  2533. c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
  2534. }
  2535. o |= uint32(v)
  2536. o |= (uint32(b) & 15) << 16
  2537. o |= (uint32(r) & 15) << 12
  2538. return o
  2539. }
  2540. func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 {
  2541. o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2542. if sc&C_PBIT == 0 {
  2543. o |= 1 << 24
  2544. }
  2545. if sc&C_WBIT != 0 {
  2546. o |= 1 << 21
  2547. }
  2548. o |= 1<<23 | 1<<20 | 0xb<<4
  2549. if v < 0 {
  2550. v = -v
  2551. o ^= 1 << 23
  2552. }
  2553. if v >= 1<<8 || v < 0 {
  2554. c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
  2555. }
  2556. o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
  2557. o |= (uint32(b) & 15) << 16
  2558. o |= (uint32(r) & 15) << 12
  2559. return o
  2560. }
  2561. func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 {
  2562. o := c.olr(v, b, r, sc) ^ (1 << 20)
  2563. if a != AMOVW {
  2564. o |= 1 << 22
  2565. }
  2566. return o
  2567. }
  2568. func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 {
  2569. o := c.olhr(v, b, r, sc) ^ (1 << 20)
  2570. return o
  2571. }
  2572. func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 {
  2573. return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20)
  2574. }
  2575. func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 {
  2576. return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20)
  2577. }
  2578. func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 {
  2579. return c.olr(int32(i), b, r, sc) ^ (1 << 25)
  2580. }
  2581. func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
  2582. return c.olhr(int32(i), b, r, sc) ^ (1 << 22)
  2583. }
  2584. func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
  2585. o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
  2586. if sc&C_PBIT == 0 {
  2587. o |= 1 << 24
  2588. }
  2589. if sc&C_WBIT != 0 {
  2590. o |= 1 << 21
  2591. }
  2592. o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
  2593. if v < 0 {
  2594. v = -v
  2595. o ^= 1 << 23
  2596. }
  2597. if v&3 != 0 {
  2598. c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
  2599. } else if v >= 1<<10 || v < 0 {
  2600. c.ctxt.Diag("literal span too large: %d\n%v", v, p)
  2601. }
  2602. o |= (uint32(v) >> 2) & 0xFF
  2603. o |= (uint32(b) & 15) << 16
  2604. o |= (uint32(r) & 15) << 12
  2605. switch a {
  2606. default:
  2607. c.ctxt.Diag("bad fst %v", a)
  2608. fallthrough
  2609. case AMOVD:
  2610. o |= 1 << 8
  2611. fallthrough
  2612. case AMOVF:
  2613. break
  2614. }
  2615. return o
  2616. }
  2617. // MOVW $"lower 16-bit", Reg
  2618. func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  2619. o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
  2620. o1 |= 0x30 << 20
  2621. o1 |= (uint32(dr) & 15) << 12
  2622. o1 |= uint32(a.Offset) & 0x0fff
  2623. o1 |= (uint32(a.Offset) & 0xf000) << 4
  2624. return o1
  2625. }
  2626. // MVN $C_NCON, Reg -> MOVW $C_RCON, Reg
  2627. func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  2628. o1 := c.oprrr(p, AMOVW, int(p.Scond))
  2629. o1 |= (uint32(dr) & 15) << 12
  2630. v := immrot(^uint32(a.Offset))
  2631. if v == 0 {
  2632. c.ctxt.Diag("%v: missing literal", p)
  2633. return 0
  2634. }
  2635. o1 |= uint32(v)
  2636. return o1
  2637. }
  2638. func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
  2639. var o1 uint32
  2640. if p.Pool == nil {
  2641. c.aclass(a)
  2642. v := immrot(^uint32(c.instoffset))
  2643. if v == 0 {
  2644. c.ctxt.Diag("%v: missing literal", p)
  2645. return 0
  2646. }
  2647. o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND)
  2648. o1 |= uint32(v)
  2649. o1 |= (uint32(dr) & 15) << 12
  2650. } else {
  2651. v := int32(p.Pool.Pc - p.Pc - 8)
  2652. o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
  2653. }
  2654. return o1
  2655. }
  2656. func (c *ctxt5) chipzero5(e float64) int {
  2657. // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
  2658. if objabi.GOARM < 7 || math.Float64bits(e) != 0 {
  2659. return -1
  2660. }
  2661. return 0
  2662. }
  2663. func (c *ctxt5) chipfloat5(e float64) int {
  2664. // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
  2665. if objabi.GOARM < 7 {
  2666. return -1
  2667. }
  2668. ei := math.Float64bits(e)
  2669. l := uint32(ei)
  2670. h := uint32(ei >> 32)
  2671. if l != 0 || h&0xffff != 0 {
  2672. return -1
  2673. }
  2674. h1 := h & 0x7fc00000
  2675. if h1 != 0x40000000 && h1 != 0x3fc00000 {
  2676. return -1
  2677. }
  2678. n := 0
  2679. // sign bit (a)
  2680. if h&0x80000000 != 0 {
  2681. n |= 1 << 7
  2682. }
  2683. // exp sign bit (b)
  2684. if h1 == 0x3fc00000 {
  2685. n |= 1 << 6
  2686. }
  2687. // rest of exp and mantissa (cd-efgh)
  2688. n |= int((h >> 16) & 0x3f)
  2689. //print("match %.8lux %.8lux %d\n", l, h, n);
  2690. return n
  2691. }
  2692. func nocache(p *obj.Prog) {
  2693. p.Optab = 0
  2694. p.From.Class = 0
  2695. if p.GetFrom3() != nil {
  2696. p.GetFrom3().Class = 0
  2697. }
  2698. p.To.Class = 0
  2699. }