asm0.go 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108
  1. // cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
  2. //
  3. // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
  4. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
  5. // Portions Copyright © 1997-1999 Vita Nuova Limited
  6. // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
  7. // Portions Copyright © 2004,2006 Bruce Ellis
  8. // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
  9. // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
  10. // Portions Copyright © 2009 The Go Authors. All rights reserved.
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining a copy
  13. // of this software and associated documentation files (the "Software"), to deal
  14. // in the Software without restriction, including without limitation the rights
  15. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16. // copies of the Software, and to permit persons to whom the Software is
  17. // furnished to do so, subject to the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be included in
  20. // all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  28. // THE SOFTWARE.
  29. package mips
  30. import (
  31. "github.com/twitchyliquid64/golang-asm/obj"
  32. "github.com/twitchyliquid64/golang-asm/objabi"
  33. "github.com/twitchyliquid64/golang-asm/sys"
  34. "fmt"
  35. "log"
  36. "sort"
  37. )
  38. // ctxt0 holds state while assembling a single function.
  39. // Each function gets a fresh ctxt0.
  40. // This allows for multiple functions to be safely concurrently assembled.
  41. type ctxt0 struct {
  42. ctxt *obj.Link
  43. newprog obj.ProgAlloc
  44. cursym *obj.LSym
  45. autosize int32
  46. instoffset int64
  47. pc int64
  48. }
  49. // Instruction layout.
  50. const (
  51. mips64FuncAlign = 8
  52. )
  53. const (
  54. r0iszero = 1
  55. )
  56. type Optab struct {
  57. as obj.As
  58. a1 uint8
  59. a2 uint8
  60. a3 uint8
  61. type_ int8
  62. size int8
  63. param int16
  64. family sys.ArchFamily // 0 means both sys.MIPS and sys.MIPS64
  65. flag uint8
  66. }
  67. const (
  68. // Optab.flag
  69. NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
  70. )
  71. var optab = []Optab{
  72. {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0, sys.MIPS64, 0},
  73. {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
  74. {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  75. {AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0, sys.MIPS64, 0},
  76. {AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0, 0, NOTUSETMP},
  77. {AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0, 0, 0},
  78. {AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0, sys.MIPS64, NOTUSETMP},
  79. {ASUB, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
  80. {ASUBV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
  81. {AADD, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
  82. {AADDV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
  83. {AAND, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
  84. {ASUB, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
  85. {ASUBV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
  86. {AADD, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
  87. {AADDV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
  88. {AAND, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
  89. {ACMOVN, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
  90. {ANEGW, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
  91. {ANEGV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
  92. {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
  93. {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
  94. {ASLLV, C_REG, C_NONE, C_REG, 9, 4, 0, sys.MIPS64, 0},
  95. {ASLLV, C_REG, C_REG, C_REG, 9, 4, 0, sys.MIPS64, 0},
  96. {ACLO, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
  97. {AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0, 0, 0},
  98. {AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0, 0, 0},
  99. {ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0, 0, 0},
  100. {AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
  101. {AMOVVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, sys.MIPS64, 0},
  102. {AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
  103. {AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
  104. {AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
  105. {AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
  106. {AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
  107. {AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
  108. {AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
  109. {AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
  110. {AMOVVL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
  111. {AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
  112. {AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
  113. {AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
  114. {AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
  115. {AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
  116. {AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
  117. {AMOVVL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
  118. {AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
  119. {AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
  120. {AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
  121. {AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
  122. {AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
  123. {AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
  124. {AMOVVL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
  125. {ASC, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
  126. {ASCV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
  127. {AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
  128. {AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
  129. {AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
  130. {AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
  131. {AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
  132. {AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
  133. {AMOVVL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
  134. {AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
  135. {AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
  136. {AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
  137. {AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
  138. {AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
  139. {AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
  140. {AMOVVL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
  141. {AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
  142. {AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
  143. {AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
  144. {AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
  145. {AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
  146. {AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
  147. {AMOVVL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
  148. {ALL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
  149. {ALLV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
  150. {AMOVW, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
  151. {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
  152. {AMOVV, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
  153. {AMOVB, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
  154. {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
  155. {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
  156. {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
  157. {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
  158. {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
  159. {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
  160. {AMOVW, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
  161. {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
  162. {AMOVV, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
  163. {AMOVB, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
  164. {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
  165. {ASC, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
  166. {AMOVW, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
  167. {AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
  168. {AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
  169. {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
  170. {AMOVB, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
  171. {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
  172. {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
  173. {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
  174. {AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
  175. {AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
  176. {AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
  177. {AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
  178. {AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
  179. {AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
  180. {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
  181. {AMOVV, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
  182. {AMOVB, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
  183. {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
  184. {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
  185. {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
  186. {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
  187. {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
  188. {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
  189. {AMOVW, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
  190. {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
  191. {AMOVV, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
  192. {AMOVB, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
  193. {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
  194. {AMOVW, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
  195. {AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
  196. {AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
  197. {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
  198. {AMOVB, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
  199. {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
  200. {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
  201. {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
  202. {AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
  203. {AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
  204. {AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
  205. {AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
  206. {AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
  207. {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
  208. {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
  209. {AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP, 0, 0},
  210. {AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP, sys.MIPS64, 0},
  211. {AMOVW, C_LECON, C_NONE, C_REG, 52, 8, REGSB, sys.MIPS, NOTUSETMP},
  212. {AMOVW, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
  213. {AMOVV, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
  214. {AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP, 0, 0},
  215. {AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP, sys.MIPS64, 0},
  216. {AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
  217. {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
  218. {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
  219. {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
  220. {AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0, 0, NOTUSETMP},
  221. {AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0, sys.MIPS64, NOTUSETMP},
  222. {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0, 0, 0},
  223. {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0, sys.MIPS64, 0},
  224. {AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0, 0, NOTUSETMP},
  225. {AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0, sys.MIPS64, NOTUSETMP},
  226. {AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0, 0, 0},
  227. {AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
  228. {AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0, 0, 0},
  229. {AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
  230. {AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0, 0, 0},
  231. {AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0, sys.MIPS64, 0},
  232. {AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0, 0, 0},
  233. {AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0, sys.MIPS64, 0},
  234. {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0, 0, 0},
  235. {AMUL, C_REG, C_REG, C_REG, 22, 4, 0, 0, 0},
  236. {AMULV, C_REG, C_REG, C_NONE, 22, 4, 0, sys.MIPS64, 0},
  237. {AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
  238. {AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
  239. {AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
  240. {AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
  241. {AADDV, C_ADD0CON, C_REG, C_REG, 4, 4, 0, sys.MIPS64, 0},
  242. {AADDV, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, sys.MIPS64, 0},
  243. {AADDV, C_ANDCON, C_REG, C_REG, 10, 8, 0, sys.MIPS64, 0},
  244. {AADDV, C_ANDCON, C_NONE, C_REG, 10, 8, 0, sys.MIPS64, 0},
  245. {AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
  246. {AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
  247. {AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
  248. {AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
  249. {AADD, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
  250. {AADD, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
  251. {AADDV, C_UCON, C_REG, C_REG, 25, 8, 0, sys.MIPS64, 0},
  252. {AADDV, C_UCON, C_NONE, C_REG, 25, 8, 0, sys.MIPS64, 0},
  253. {AAND, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
  254. {AAND, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
  255. {AADD, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
  256. {AADDV, C_LCON, C_NONE, C_REG, 23, 12, 0, sys.MIPS64, 0},
  257. {AAND, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
  258. {AADD, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
  259. {AADDV, C_LCON, C_REG, C_REG, 23, 12, 0, sys.MIPS64, 0},
  260. {AAND, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
  261. {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0, 0, 0},
  262. {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0, 0, 0},
  263. {ASLLV, C_SCON, C_REG, C_REG, 16, 4, 0, sys.MIPS64, 0},
  264. {ASLLV, C_SCON, C_NONE, C_REG, 16, 4, 0, sys.MIPS64, 0},
  265. {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
  266. {ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0, 0, 0},
  267. {ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
  268. {ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
  269. {ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0, 0, NOTUSETMP},
  270. {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
  271. {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
  272. {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO, 0, 0},
  273. {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK, 0, 0},
  274. {AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
  275. {AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
  276. {AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
  277. {AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, sys.MIPS64, 0},
  278. {AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
  279. {AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
  280. {AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, sys.MIPS64, 0},
  281. {AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
  282. {AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
  283. {AMOVW, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
  284. {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
  285. {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
  286. {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, sys.MIPS64, 0},
  287. {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
  288. {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
  289. {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, sys.MIPS64, 0},
  290. {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
  291. {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
  292. {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
  293. {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
  294. {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
  295. {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
  296. {AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
  297. {AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
  298. {AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
  299. {AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, sys.MIPS64, 0},
  300. {AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
  301. {AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
  302. {AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, sys.MIPS64, 0},
  303. {AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
  304. {AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
  305. {AMOVW, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
  306. {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
  307. {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
  308. {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, sys.MIPS64, 0},
  309. {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
  310. {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
  311. {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, sys.MIPS64, 0},
  312. {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
  313. {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
  314. {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
  315. {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
  316. {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
  317. {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
  318. {AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0, 0, 0},
  319. {AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0, 0, 0},
  320. {AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0, sys.MIPS64, 0},
  321. {AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0, sys.MIPS64, 0},
  322. {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
  323. {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
  324. {AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0, 0, 0},
  325. {AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0, sys.MIPS64, 0},
  326. {AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0, 0, 0},
  327. {AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0, sys.MIPS64, 0},
  328. {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0, 0, 0},
  329. {AMOVW, C_REG, C_NONE, C_FCREG, 41, 4, 0, 0, 0},
  330. {AMOVV, C_REG, C_NONE, C_FCREG, 41, 4, 0, sys.MIPS64, 0},
  331. {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0, 0, 0},
  332. {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0, sys.MIPS64, 0},
  333. {ATEQ, C_SCON, C_REG, C_REG, 15, 4, 0, 0, 0},
  334. {ATEQ, C_SCON, C_NONE, C_REG, 15, 4, 0, 0, 0},
  335. {ACMOVT, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0},
  336. {AVMOVB, C_SCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
  337. {AVMOVB, C_ADDCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
  338. {AVMOVB, C_SOREG, C_NONE, C_WREG, 57, 4, 0, sys.MIPS64, 0},
  339. {AVMOVB, C_WREG, C_NONE, C_SOREG, 58, 4, 0, sys.MIPS64, 0},
  340. {ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0}, /* really CACHE instruction */
  341. {ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
  342. {ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
  343. {ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
  344. {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0},
  345. {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
  346. {obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
  347. {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
  348. {obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
  349. {obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0},
  350. {obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0},
  351. {obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
  352. {obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
  353. {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
  354. }
  355. var oprange [ALAST & obj.AMask][]Optab
  356. var xcmp [C_NCLASS][C_NCLASS]bool
  357. func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  358. if ctxt.Retpoline {
  359. ctxt.Diag("-spectre=ret not supported on mips")
  360. ctxt.Retpoline = false // don't keep printing
  361. }
  362. p := cursym.Func.Text
  363. if p == nil || p.Link == nil { // handle external functions and ELF section symbols
  364. return
  365. }
  366. c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset + ctxt.FixedFrameSize())}
  367. if oprange[AOR&obj.AMask] == nil {
  368. c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
  369. }
  370. pc := int64(0)
  371. p.Pc = pc
  372. var m int
  373. var o *Optab
  374. for p = p.Link; p != nil; p = p.Link {
  375. p.Pc = pc
  376. o = c.oplook(p)
  377. m = int(o.size)
  378. if m == 0 {
  379. if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
  380. c.ctxt.Diag("zero-width instruction\n%v", p)
  381. }
  382. continue
  383. }
  384. pc += int64(m)
  385. }
  386. c.cursym.Size = pc
  387. /*
  388. * if any procedure is large enough to
  389. * generate a large SBRA branch, then
  390. * generate extra passes putting branches
  391. * around jmps to fix. this is rare.
  392. */
  393. bflag := 1
  394. var otxt int64
  395. var q *obj.Prog
  396. for bflag != 0 {
  397. bflag = 0
  398. pc = 0
  399. for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
  400. p.Pc = pc
  401. o = c.oplook(p)
  402. // very large conditional branches
  403. if o.type_ == 6 && p.To.Target() != nil {
  404. otxt = p.To.Target().Pc - pc
  405. if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
  406. q = c.newprog()
  407. q.Link = p.Link
  408. p.Link = q
  409. q.As = AJMP
  410. q.Pos = p.Pos
  411. q.To.Type = obj.TYPE_BRANCH
  412. q.To.SetTarget(p.To.Target())
  413. p.To.SetTarget(q)
  414. q = c.newprog()
  415. q.Link = p.Link
  416. p.Link = q
  417. q.As = AJMP
  418. q.Pos = p.Pos
  419. q.To.Type = obj.TYPE_BRANCH
  420. q.To.SetTarget(q.Link.Link)
  421. c.addnop(p.Link)
  422. c.addnop(p)
  423. bflag = 1
  424. }
  425. }
  426. m = int(o.size)
  427. if m == 0 {
  428. if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
  429. c.ctxt.Diag("zero-width instruction\n%v", p)
  430. }
  431. continue
  432. }
  433. pc += int64(m)
  434. }
  435. c.cursym.Size = pc
  436. }
  437. if c.ctxt.Arch.Family == sys.MIPS64 {
  438. pc += -pc & (mips64FuncAlign - 1)
  439. }
  440. c.cursym.Size = pc
  441. /*
  442. * lay out the code, emitting code and data relocations.
  443. */
  444. c.cursym.Grow(c.cursym.Size)
  445. bp := c.cursym.P
  446. var i int32
  447. var out [4]uint32
  448. for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
  449. c.pc = p.Pc
  450. o = c.oplook(p)
  451. if int(o.size) > 4*len(out) {
  452. log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
  453. }
  454. c.asmout(p, o, out[:])
  455. for i = 0; i < int32(o.size/4); i++ {
  456. c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
  457. bp = bp[4:]
  458. }
  459. }
  460. // Mark nonpreemptible instruction sequences.
  461. // We use REGTMP as a scratch register during call injection,
  462. // so instruction sequences that use REGTMP are unsafe to
  463. // preempt asynchronously.
  464. obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, c.isRestartable)
  465. }
  466. // isUnsafePoint returns whether p is an unsafe point.
  467. func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
  468. // If p explicitly uses REGTMP, it's unsafe to preempt, because the
  469. // preemption sequence clobbers REGTMP.
  470. return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
  471. }
  472. // isRestartable returns whether p is a multi-instruction sequence that,
  473. // if preempted, can be restarted.
  474. func (c *ctxt0) isRestartable(p *obj.Prog) bool {
  475. if c.isUnsafePoint(p) {
  476. return false
  477. }
  478. // If p is a multi-instruction sequence with uses REGTMP inserted by
  479. // the assembler in order to materialize a large constant/offset, we
  480. // can restart p (at the start of the instruction sequence), recompute
  481. // the content of REGTMP, upon async preemption. Currently, all cases
  482. // of assembler-inserted REGTMP fall into this category.
  483. // If p doesn't use REGTMP, it can be simply preempted, so we don't
  484. // mark it.
  485. o := c.oplook(p)
  486. return o.size > 4 && o.flag&NOTUSETMP == 0
  487. }
  488. func isint32(v int64) bool {
  489. return int64(int32(v)) == v
  490. }
  491. func isuint32(v uint64) bool {
  492. return uint64(uint32(v)) == v
  493. }
  494. func (c *ctxt0) aclass(a *obj.Addr) int {
  495. switch a.Type {
  496. case obj.TYPE_NONE:
  497. return C_NONE
  498. case obj.TYPE_REG:
  499. if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
  500. return C_REG
  501. }
  502. if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
  503. return C_FREG
  504. }
  505. if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
  506. return C_MREG
  507. }
  508. if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
  509. return C_FCREG
  510. }
  511. if REG_W0 <= a.Reg && a.Reg <= REG_W31 {
  512. return C_WREG
  513. }
  514. if a.Reg == REG_LO {
  515. return C_LO
  516. }
  517. if a.Reg == REG_HI {
  518. return C_HI
  519. }
  520. return C_GOK
  521. case obj.TYPE_MEM:
  522. switch a.Name {
  523. case obj.NAME_EXTERN,
  524. obj.NAME_STATIC:
  525. if a.Sym == nil {
  526. break
  527. }
  528. c.instoffset = a.Offset
  529. if a.Sym != nil { // use relocation
  530. if a.Sym.Type == objabi.STLSBSS {
  531. return C_TLS
  532. }
  533. return C_ADDR
  534. }
  535. return C_LEXT
  536. case obj.NAME_AUTO:
  537. if a.Reg == REGSP {
  538. // unset base register for better printing, since
  539. // a.Offset is still relative to pseudo-SP.
  540. a.Reg = obj.REG_NONE
  541. }
  542. c.instoffset = int64(c.autosize) + a.Offset
  543. if c.instoffset >= -BIG && c.instoffset < BIG {
  544. return C_SAUTO
  545. }
  546. return C_LAUTO
  547. case obj.NAME_PARAM:
  548. if a.Reg == REGSP {
  549. // unset base register for better printing, since
  550. // a.Offset is still relative to pseudo-FP.
  551. a.Reg = obj.REG_NONE
  552. }
  553. c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
  554. if c.instoffset >= -BIG && c.instoffset < BIG {
  555. return C_SAUTO
  556. }
  557. return C_LAUTO
  558. case obj.NAME_NONE:
  559. c.instoffset = a.Offset
  560. if c.instoffset == 0 {
  561. return C_ZOREG
  562. }
  563. if c.instoffset >= -BIG && c.instoffset < BIG {
  564. return C_SOREG
  565. }
  566. return C_LOREG
  567. }
  568. return C_GOK
  569. case obj.TYPE_TEXTSIZE:
  570. return C_TEXTSIZE
  571. case obj.TYPE_CONST,
  572. obj.TYPE_ADDR:
  573. switch a.Name {
  574. case obj.NAME_NONE:
  575. c.instoffset = a.Offset
  576. if a.Reg != 0 {
  577. if -BIG <= c.instoffset && c.instoffset <= BIG {
  578. return C_SACON
  579. }
  580. if isint32(c.instoffset) {
  581. return C_LACON
  582. }
  583. return C_DACON
  584. }
  585. case obj.NAME_EXTERN,
  586. obj.NAME_STATIC:
  587. s := a.Sym
  588. if s == nil {
  589. return C_GOK
  590. }
  591. c.instoffset = a.Offset
  592. if s.Type == objabi.STLSBSS {
  593. return C_STCON // address of TLS variable
  594. }
  595. return C_LECON
  596. case obj.NAME_AUTO:
  597. if a.Reg == REGSP {
  598. // unset base register for better printing, since
  599. // a.Offset is still relative to pseudo-SP.
  600. a.Reg = obj.REG_NONE
  601. }
  602. c.instoffset = int64(c.autosize) + a.Offset
  603. if c.instoffset >= -BIG && c.instoffset < BIG {
  604. return C_SACON
  605. }
  606. return C_LACON
  607. case obj.NAME_PARAM:
  608. if a.Reg == REGSP {
  609. // unset base register for better printing, since
  610. // a.Offset is still relative to pseudo-FP.
  611. a.Reg = obj.REG_NONE
  612. }
  613. c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
  614. if c.instoffset >= -BIG && c.instoffset < BIG {
  615. return C_SACON
  616. }
  617. return C_LACON
  618. default:
  619. return C_GOK
  620. }
  621. if c.instoffset >= 0 {
  622. if c.instoffset == 0 {
  623. return C_ZCON
  624. }
  625. if c.instoffset <= 0x7fff {
  626. return C_SCON
  627. }
  628. if c.instoffset <= 0xffff {
  629. return C_ANDCON
  630. }
  631. if c.instoffset&0xffff == 0 && isuint32(uint64(c.instoffset)) { /* && (instoffset & (1<<31)) == 0) */
  632. return C_UCON
  633. }
  634. if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
  635. return C_LCON
  636. }
  637. return C_LCON // C_DCON
  638. }
  639. if c.instoffset >= -0x8000 {
  640. return C_ADDCON
  641. }
  642. if c.instoffset&0xffff == 0 && isint32(c.instoffset) {
  643. return C_UCON
  644. }
  645. if isint32(c.instoffset) {
  646. return C_LCON
  647. }
  648. return C_LCON // C_DCON
  649. case obj.TYPE_BRANCH:
  650. return C_SBRA
  651. }
  652. return C_GOK
  653. }
  654. func prasm(p *obj.Prog) {
  655. fmt.Printf("%v\n", p)
  656. }
  657. func (c *ctxt0) oplook(p *obj.Prog) *Optab {
  658. if oprange[AOR&obj.AMask] == nil {
  659. c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
  660. }
  661. a1 := int(p.Optab)
  662. if a1 != 0 {
  663. return &optab[a1-1]
  664. }
  665. a1 = int(p.From.Class)
  666. if a1 == 0 {
  667. a1 = c.aclass(&p.From) + 1
  668. p.From.Class = int8(a1)
  669. }
  670. a1--
  671. a3 := int(p.To.Class)
  672. if a3 == 0 {
  673. a3 = c.aclass(&p.To) + 1
  674. p.To.Class = int8(a3)
  675. }
  676. a3--
  677. a2 := C_NONE
  678. if p.Reg != 0 {
  679. a2 = C_REG
  680. }
  681. ops := oprange[p.As&obj.AMask]
  682. c1 := &xcmp[a1]
  683. c3 := &xcmp[a3]
  684. for i := range ops {
  685. op := &ops[i]
  686. if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] && (op.family == 0 || c.ctxt.Arch.Family == op.family) {
  687. p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  688. return op
  689. }
  690. }
  691. c.ctxt.Diag("illegal combination %v %v %v %v", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
  692. prasm(p)
  693. // Turn illegal instruction into an UNDEF, avoid crashing in asmout.
  694. return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0}
  695. }
  696. func cmp(a int, b int) bool {
  697. if a == b {
  698. return true
  699. }
  700. switch a {
  701. case C_LCON:
  702. if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
  703. return true
  704. }
  705. case C_ADD0CON:
  706. if b == C_ADDCON {
  707. return true
  708. }
  709. fallthrough
  710. case C_ADDCON:
  711. if b == C_ZCON || b == C_SCON {
  712. return true
  713. }
  714. case C_AND0CON:
  715. if b == C_ANDCON {
  716. return true
  717. }
  718. fallthrough
  719. case C_ANDCON:
  720. if b == C_ZCON || b == C_SCON {
  721. return true
  722. }
  723. case C_UCON:
  724. if b == C_ZCON {
  725. return true
  726. }
  727. case C_SCON:
  728. if b == C_ZCON {
  729. return true
  730. }
  731. case C_LACON:
  732. if b == C_SACON {
  733. return true
  734. }
  735. case C_LBRA:
  736. if b == C_SBRA {
  737. return true
  738. }
  739. case C_LEXT:
  740. if b == C_SEXT {
  741. return true
  742. }
  743. case C_LAUTO:
  744. if b == C_SAUTO {
  745. return true
  746. }
  747. case C_REG:
  748. if b == C_ZCON {
  749. return r0iszero != 0 /*TypeKind(100016)*/
  750. }
  751. case C_LOREG:
  752. if b == C_ZOREG || b == C_SOREG {
  753. return true
  754. }
  755. case C_SOREG:
  756. if b == C_ZOREG {
  757. return true
  758. }
  759. }
  760. return false
  761. }
  762. type ocmp []Optab
  763. func (x ocmp) Len() int {
  764. return len(x)
  765. }
  766. func (x ocmp) Swap(i, j int) {
  767. x[i], x[j] = x[j], x[i]
  768. }
  769. func (x ocmp) Less(i, j int) bool {
  770. p1 := &x[i]
  771. p2 := &x[j]
  772. n := int(p1.as) - int(p2.as)
  773. if n != 0 {
  774. return n < 0
  775. }
  776. n = int(p1.a1) - int(p2.a1)
  777. if n != 0 {
  778. return n < 0
  779. }
  780. n = int(p1.a2) - int(p2.a2)
  781. if n != 0 {
  782. return n < 0
  783. }
  784. n = int(p1.a3) - int(p2.a3)
  785. if n != 0 {
  786. return n < 0
  787. }
  788. return false
  789. }
  790. func opset(a, b0 obj.As) {
  791. oprange[a&obj.AMask] = oprange[b0]
  792. }
  793. func buildop(ctxt *obj.Link) {
  794. if oprange[AOR&obj.AMask] != nil {
  795. // Already initialized; stop now.
  796. // This happens in the cmd/asm tests,
  797. // each of which re-initializes the arch.
  798. return
  799. }
  800. var n int
  801. for i := 0; i < C_NCLASS; i++ {
  802. for n = 0; n < C_NCLASS; n++ {
  803. if cmp(n, i) {
  804. xcmp[i][n] = true
  805. }
  806. }
  807. }
  808. for n = 0; optab[n].as != obj.AXXX; n++ {
  809. }
  810. sort.Sort(ocmp(optab[:n]))
  811. for i := 0; i < n; i++ {
  812. r := optab[i].as
  813. r0 := r & obj.AMask
  814. start := i
  815. for optab[i].as == r {
  816. i++
  817. }
  818. oprange[r0] = optab[start:i]
  819. i--
  820. switch r {
  821. default:
  822. ctxt.Diag("unknown op in build: %v", r)
  823. ctxt.DiagFlush()
  824. log.Fatalf("bad code")
  825. case AABSF:
  826. opset(AMOVFD, r0)
  827. opset(AMOVDF, r0)
  828. opset(AMOVWF, r0)
  829. opset(AMOVFW, r0)
  830. opset(AMOVWD, r0)
  831. opset(AMOVDW, r0)
  832. opset(ANEGF, r0)
  833. opset(ANEGD, r0)
  834. opset(AABSD, r0)
  835. opset(ATRUNCDW, r0)
  836. opset(ATRUNCFW, r0)
  837. opset(ASQRTF, r0)
  838. opset(ASQRTD, r0)
  839. case AMOVVF:
  840. opset(AMOVVD, r0)
  841. opset(AMOVFV, r0)
  842. opset(AMOVDV, r0)
  843. opset(ATRUNCDV, r0)
  844. opset(ATRUNCFV, r0)
  845. case AADD:
  846. opset(ASGT, r0)
  847. opset(ASGTU, r0)
  848. opset(AADDU, r0)
  849. case AADDV:
  850. opset(AADDVU, r0)
  851. case AADDF:
  852. opset(ADIVF, r0)
  853. opset(ADIVD, r0)
  854. opset(AMULF, r0)
  855. opset(AMULD, r0)
  856. opset(ASUBF, r0)
  857. opset(ASUBD, r0)
  858. opset(AADDD, r0)
  859. case AAND:
  860. opset(AOR, r0)
  861. opset(AXOR, r0)
  862. case ABEQ:
  863. opset(ABNE, r0)
  864. case ABLEZ:
  865. opset(ABGEZ, r0)
  866. opset(ABGEZAL, r0)
  867. opset(ABLTZ, r0)
  868. opset(ABLTZAL, r0)
  869. opset(ABGTZ, r0)
  870. case AMOVB:
  871. opset(AMOVH, r0)
  872. case AMOVBU:
  873. opset(AMOVHU, r0)
  874. case AMUL:
  875. opset(AREM, r0)
  876. opset(AREMU, r0)
  877. opset(ADIVU, r0)
  878. opset(AMULU, r0)
  879. opset(ADIV, r0)
  880. opset(AMADD, r0)
  881. opset(AMSUB, r0)
  882. case AMULV:
  883. opset(ADIVV, r0)
  884. opset(ADIVVU, r0)
  885. opset(AMULVU, r0)
  886. opset(AREMV, r0)
  887. opset(AREMVU, r0)
  888. case ASLL:
  889. opset(ASRL, r0)
  890. opset(ASRA, r0)
  891. case ASLLV:
  892. opset(ASRAV, r0)
  893. opset(ASRLV, r0)
  894. case ASUB:
  895. opset(ASUBU, r0)
  896. opset(ANOR, r0)
  897. case ASUBV:
  898. opset(ASUBVU, r0)
  899. case ASYSCALL:
  900. opset(ASYNC, r0)
  901. opset(ANOOP, r0)
  902. opset(ATLBP, r0)
  903. opset(ATLBR, r0)
  904. opset(ATLBWI, r0)
  905. opset(ATLBWR, r0)
  906. case ACMPEQF:
  907. opset(ACMPGTF, r0)
  908. opset(ACMPGTD, r0)
  909. opset(ACMPGEF, r0)
  910. opset(ACMPGED, r0)
  911. opset(ACMPEQD, r0)
  912. case ABFPT:
  913. opset(ABFPF, r0)
  914. case AMOVWL:
  915. opset(AMOVWR, r0)
  916. case AMOVVL:
  917. opset(AMOVVR, r0)
  918. case AVMOVB:
  919. opset(AVMOVH, r0)
  920. opset(AVMOVW, r0)
  921. opset(AVMOVD, r0)
  922. case AMOVW,
  923. AMOVD,
  924. AMOVF,
  925. AMOVV,
  926. ABREAK,
  927. ARFE,
  928. AJAL,
  929. AJMP,
  930. AMOVWU,
  931. ALL,
  932. ALLV,
  933. ASC,
  934. ASCV,
  935. ANEGW,
  936. ANEGV,
  937. AWORD,
  938. obj.ANOP,
  939. obj.ATEXT,
  940. obj.AUNDEF,
  941. obj.AFUNCDATA,
  942. obj.APCDATA,
  943. obj.ADUFFZERO,
  944. obj.ADUFFCOPY:
  945. break
  946. case ACMOVN:
  947. opset(ACMOVZ, r0)
  948. case ACMOVT:
  949. opset(ACMOVF, r0)
  950. case ACLO:
  951. opset(ACLZ, r0)
  952. case ATEQ:
  953. opset(ATNE, r0)
  954. }
  955. }
  956. }
  957. func OP(x uint32, y uint32) uint32 {
  958. return x<<3 | y<<0
  959. }
  960. func SP(x uint32, y uint32) uint32 {
  961. return x<<29 | y<<26
  962. }
  963. func BCOND(x uint32, y uint32) uint32 {
  964. return x<<19 | y<<16
  965. }
  966. func MMU(x uint32, y uint32) uint32 {
  967. return SP(2, 0) | 16<<21 | x<<3 | y<<0
  968. }
  969. func FPF(x uint32, y uint32) uint32 {
  970. return SP(2, 1) | 16<<21 | x<<3 | y<<0
  971. }
  972. func FPD(x uint32, y uint32) uint32 {
  973. return SP(2, 1) | 17<<21 | x<<3 | y<<0
  974. }
  975. func FPW(x uint32, y uint32) uint32 {
  976. return SP(2, 1) | 20<<21 | x<<3 | y<<0
  977. }
  978. func FPV(x uint32, y uint32) uint32 {
  979. return SP(2, 1) | 21<<21 | x<<3 | y<<0
  980. }
  981. func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  982. return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
  983. }
  984. func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  985. return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
  986. }
  987. func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
  988. return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
  989. }
  990. func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  991. return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
  992. }
  993. func OP_JMP(op uint32, i uint32) uint32 {
  994. return op | i&0x3FFFFFF
  995. }
  996. func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
  997. return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
  998. }
  999. func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
  1000. return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
  1001. }
  1002. func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1003. o1 := uint32(0)
  1004. o2 := uint32(0)
  1005. o3 := uint32(0)
  1006. o4 := uint32(0)
  1007. add := AADDU
  1008. if c.ctxt.Arch.Family == sys.MIPS64 {
  1009. add = AADDVU
  1010. }
  1011. switch o.type_ {
  1012. default:
  1013. c.ctxt.Diag("unknown type %d %v", o.type_)
  1014. prasm(p)
  1015. case 0: /* pseudo ops */
  1016. break
  1017. case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
  1018. a := AOR
  1019. if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
  1020. // on MIPS64, most of the 32-bit instructions have unpredictable behavior,
  1021. // but SLL is special that the result is always sign-extended to 64-bit.
  1022. a = ASLL
  1023. }
  1024. o1 = OP_RRR(c.oprrr(a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
  1025. case 2: /* add/sub r1,[r2],r3 */
  1026. r := int(p.Reg)
  1027. if p.As == ANEGW || p.As == ANEGV {
  1028. r = REGZERO
  1029. }
  1030. if r == 0 {
  1031. r = int(p.To.Reg)
  1032. }
  1033. o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1034. case 3: /* mov $soreg, r ==> or/add $i,o,r */
  1035. v := c.regoff(&p.From)
  1036. r := int(p.From.Reg)
  1037. if r == 0 {
  1038. r = int(o.param)
  1039. }
  1040. a := add
  1041. if o.a1 == C_ANDCON {
  1042. a = AOR
  1043. }
  1044. o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1045. case 4: /* add $scon,[r1],r2 */
  1046. v := c.regoff(&p.From)
  1047. r := int(p.Reg)
  1048. if r == 0 {
  1049. r = int(p.To.Reg)
  1050. }
  1051. o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1052. case 5: /* syscall */
  1053. o1 = c.oprrr(p.As)
  1054. case 6: /* beq r1,[r2],sbra */
  1055. v := int32(0)
  1056. if p.To.Target() == nil {
  1057. v = int32(-4) >> 2
  1058. } else {
  1059. v = int32(p.To.Target().Pc-p.Pc-4) >> 2
  1060. }
  1061. if (v<<16)>>16 != v {
  1062. c.ctxt.Diag("short branch too far\n%v", p)
  1063. }
  1064. o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
  1065. // for ABFPT and ABFPF only: always fill delay slot with 0
  1066. // see comments in func preprocess for details.
  1067. o2 = 0
  1068. case 7: /* mov r, soreg ==> sw o(r) */
  1069. r := int(p.To.Reg)
  1070. if r == 0 {
  1071. r = int(o.param)
  1072. }
  1073. v := c.regoff(&p.To)
  1074. o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
  1075. case 8: /* mov soreg, r ==> lw o(r) */
  1076. r := int(p.From.Reg)
  1077. if r == 0 {
  1078. r = int(o.param)
  1079. }
  1080. v := c.regoff(&p.From)
  1081. o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1082. case 9: /* sll r1,[r2],r3 */
  1083. r := int(p.Reg)
  1084. if r == 0 {
  1085. r = int(p.To.Reg)
  1086. }
  1087. o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
  1088. case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
  1089. v := c.regoff(&p.From)
  1090. a := AOR
  1091. if v < 0 {
  1092. a = AADDU
  1093. }
  1094. o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1095. r := int(p.Reg)
  1096. if r == 0 {
  1097. r = int(p.To.Reg)
  1098. }
  1099. o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1100. case 11: /* jmp lbra */
  1101. v := int32(0)
  1102. if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
  1103. // use PC-relative branch for short branches
  1104. // BEQ R0, R0, sbra
  1105. if p.To.Target() == nil {
  1106. v = int32(-4) >> 2
  1107. } else {
  1108. v = int32(p.To.Target().Pc-p.Pc-4) >> 2
  1109. }
  1110. if (v<<16)>>16 == v {
  1111. o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
  1112. break
  1113. }
  1114. }
  1115. if p.To.Target() == nil {
  1116. v = int32(p.Pc) >> 2
  1117. } else {
  1118. v = int32(p.To.Target().Pc) >> 2
  1119. }
  1120. o1 = OP_JMP(c.opirr(p.As), uint32(v))
  1121. if p.To.Sym == nil {
  1122. p.To.Sym = c.cursym.Func.Text.From.Sym
  1123. p.To.Offset = p.To.Target().Pc
  1124. }
  1125. rel := obj.Addrel(c.cursym)
  1126. rel.Off = int32(c.pc)
  1127. rel.Siz = 4
  1128. rel.Sym = p.To.Sym
  1129. rel.Add = p.To.Offset
  1130. if p.As == AJAL {
  1131. rel.Type = objabi.R_CALLMIPS
  1132. } else {
  1133. rel.Type = objabi.R_JMPMIPS
  1134. }
  1135. case 12: /* movbs r,r */
  1136. // NOTE: this case does not use REGTMP. If it ever does,
  1137. // remove the NOTUSETMP flag in optab.
  1138. v := 16
  1139. if p.As == AMOVB {
  1140. v = 24
  1141. }
  1142. o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
  1143. o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1144. case 13: /* movbu r,r */
  1145. if p.As == AMOVBU {
  1146. o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
  1147. } else {
  1148. o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
  1149. }
  1150. case 14: /* movwu r,r */
  1151. // NOTE: this case does not use REGTMP. If it ever does,
  1152. // remove the NOTUSETMP flag in optab.
  1153. o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  1154. o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1155. case 15: /* teq $c r,r */
  1156. v := c.regoff(&p.From)
  1157. r := int(p.Reg)
  1158. if r == 0 {
  1159. r = REGZERO
  1160. }
  1161. /* only use 10 bits of trap code */
  1162. o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(r), uint32(p.To.Reg))
  1163. case 16: /* sll $c,[r1],r2 */
  1164. v := c.regoff(&p.From)
  1165. r := int(p.Reg)
  1166. if r == 0 {
  1167. r = int(p.To.Reg)
  1168. }
  1169. /* OP_SRR will use only the low 5 bits of the shift value */
  1170. if v >= 32 && vshift(p.As) {
  1171. o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
  1172. } else {
  1173. o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1174. }
  1175. case 17:
  1176. o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  1177. case 18: /* jmp [r1],0(r2) */
  1178. r := int(p.Reg)
  1179. if r == 0 {
  1180. r = int(o.param)
  1181. }
  1182. o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
  1183. if p.As == obj.ACALL {
  1184. rel := obj.Addrel(c.cursym)
  1185. rel.Off = int32(c.pc)
  1186. rel.Siz = 0
  1187. rel.Type = objabi.R_CALLIND
  1188. }
  1189. case 19: /* mov $lcon,r ==> lu+or */
  1190. // NOTE: this case does not use REGTMP. If it ever does,
  1191. // remove the NOTUSETMP flag in optab.
  1192. v := c.regoff(&p.From)
  1193. o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
  1194. o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1195. case 20: /* mov lo/hi,r */
  1196. a := OP(2, 0) /* mfhi */
  1197. if p.From.Reg == REG_LO {
  1198. a = OP(2, 2) /* mflo */
  1199. }
  1200. o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
  1201. case 21: /* mov r,lo/hi */
  1202. a := OP(2, 1) /* mthi */
  1203. if p.To.Reg == REG_LO {
  1204. a = OP(2, 3) /* mtlo */
  1205. }
  1206. o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
  1207. case 22: /* mul r1,r2 [r3]*/
  1208. if p.To.Reg != 0 {
  1209. r := int(p.Reg)
  1210. if r == 0 {
  1211. r = int(p.To.Reg)
  1212. }
  1213. a := SP(3, 4) | 2 /* mul */
  1214. o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1215. } else {
  1216. o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
  1217. }
  1218. case 23: /* add $lcon,r1,r2 ==> lu+or+add */
  1219. v := c.regoff(&p.From)
  1220. o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1221. o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1222. r := int(p.Reg)
  1223. if r == 0 {
  1224. r = int(p.To.Reg)
  1225. }
  1226. o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1227. case 24: /* mov $ucon,r ==> lu r */
  1228. v := c.regoff(&p.From)
  1229. o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
  1230. case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
  1231. v := c.regoff(&p.From)
  1232. o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1233. r := int(p.Reg)
  1234. if r == 0 {
  1235. r = int(p.To.Reg)
  1236. }
  1237. o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1238. case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
  1239. v := c.regoff(&p.From)
  1240. o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1241. o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1242. r := int(p.From.Reg)
  1243. if r == 0 {
  1244. r = int(o.param)
  1245. }
  1246. o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1247. case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
  1248. v := c.regoff(&p.From)
  1249. r := int(p.From.Reg)
  1250. if r == 0 {
  1251. r = int(o.param)
  1252. }
  1253. a := -AMOVF
  1254. if p.As == AMOVD {
  1255. a = -AMOVD
  1256. }
  1257. switch o.size {
  1258. case 12:
  1259. o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1260. o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1261. o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1262. case 4:
  1263. o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1264. }
  1265. case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
  1266. v := c.regoff(&p.To)
  1267. r := int(p.To.Reg)
  1268. if r == 0 {
  1269. r = int(o.param)
  1270. }
  1271. a := AMOVF
  1272. if p.As == AMOVD {
  1273. a = AMOVD
  1274. }
  1275. switch o.size {
  1276. case 12:
  1277. o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1278. o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1279. o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1280. case 4:
  1281. o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
  1282. }
  1283. case 30: /* movw r,fr */
  1284. a := SP(2, 1) | (4 << 21) /* mtc1 */
  1285. o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1286. case 31: /* movw fr,r */
  1287. a := SP(2, 1) | (0 << 21) /* mtc1 */
  1288. o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1289. case 32: /* fadd fr1,[fr2],fr3 */
  1290. r := int(p.Reg)
  1291. if r == 0 {
  1292. r = int(p.To.Reg)
  1293. }
  1294. o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1295. case 33: /* fabs fr1, fr3 */
  1296. o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  1297. case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
  1298. v := c.regoff(&p.From)
  1299. a := AADDU
  1300. if o.a1 == C_ANDCON {
  1301. a = AOR
  1302. }
  1303. o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1304. o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
  1305. case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
  1306. v := c.regoff(&p.To)
  1307. r := int(p.To.Reg)
  1308. if r == 0 {
  1309. r = int(o.param)
  1310. }
  1311. o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1312. o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1313. o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1314. case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
  1315. v := c.regoff(&p.From)
  1316. r := int(p.From.Reg)
  1317. if r == 0 {
  1318. r = int(o.param)
  1319. }
  1320. o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1321. o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1322. o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1323. case 37: /* movw r,mr */
  1324. a := SP(2, 0) | (4 << 21) /* mtc0 */
  1325. if p.As == AMOVV {
  1326. a = SP(2, 0) | (5 << 21) /* dmtc0 */
  1327. }
  1328. o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1329. case 38: /* movw mr,r */
  1330. a := SP(2, 0) | (0 << 21) /* mfc0 */
  1331. if p.As == AMOVV {
  1332. a = SP(2, 0) | (1 << 21) /* dmfc0 */
  1333. }
  1334. o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1335. case 40: /* word */
  1336. o1 = uint32(c.regoff(&p.From))
  1337. case 41: /* movw f,fcr */
  1338. o1 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
  1339. case 42: /* movw fcr,r */
  1340. o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
  1341. case 47: /* movv r,fr */
  1342. a := SP(2, 1) | (5 << 21) /* dmtc1 */
  1343. o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1344. case 48: /* movv fr,r */
  1345. a := SP(2, 1) | (1 << 21) /* dmtc1 */
  1346. o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1347. case 49: /* undef */
  1348. o1 = 52 /* trap -- teq r0, r0 */
  1349. /* relocation operations */
  1350. case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
  1351. o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
  1352. rel := obj.Addrel(c.cursym)
  1353. rel.Off = int32(c.pc)
  1354. rel.Siz = 4
  1355. rel.Sym = p.To.Sym
  1356. rel.Add = p.To.Offset
  1357. rel.Type = objabi.R_ADDRMIPSU
  1358. o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  1359. rel2 := obj.Addrel(c.cursym)
  1360. rel2.Off = int32(c.pc + 4)
  1361. rel2.Siz = 4
  1362. rel2.Sym = p.To.Sym
  1363. rel2.Add = p.To.Offset
  1364. rel2.Type = objabi.R_ADDRMIPS
  1365. if o.size == 12 {
  1366. o3 = o2
  1367. o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
  1368. rel2.Off += 4
  1369. }
  1370. case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
  1371. o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
  1372. rel := obj.Addrel(c.cursym)
  1373. rel.Off = int32(c.pc)
  1374. rel.Siz = 4
  1375. rel.Sym = p.From.Sym
  1376. rel.Add = p.From.Offset
  1377. rel.Type = objabi.R_ADDRMIPSU
  1378. o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  1379. rel2 := obj.Addrel(c.cursym)
  1380. rel2.Off = int32(c.pc + 4)
  1381. rel2.Siz = 4
  1382. rel2.Sym = p.From.Sym
  1383. rel2.Add = p.From.Offset
  1384. rel2.Type = objabi.R_ADDRMIPS
  1385. if o.size == 12 {
  1386. o3 = o2
  1387. o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
  1388. rel2.Off += 4
  1389. }
  1390. case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
  1391. // NOTE: this case does not use REGTMP. If it ever does,
  1392. // remove the NOTUSETMP flag in optab.
  1393. o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
  1394. rel := obj.Addrel(c.cursym)
  1395. rel.Off = int32(c.pc)
  1396. rel.Siz = 4
  1397. rel.Sym = p.From.Sym
  1398. rel.Add = p.From.Offset
  1399. rel.Type = objabi.R_ADDRMIPSU
  1400. o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1401. rel2 := obj.Addrel(c.cursym)
  1402. rel2.Off = int32(c.pc + 4)
  1403. rel2.Siz = 4
  1404. rel2.Sym = p.From.Sym
  1405. rel2.Add = p.From.Offset
  1406. rel2.Type = objabi.R_ADDRMIPS
  1407. if o.size == 12 {
  1408. o3 = o2
  1409. o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
  1410. rel2.Off += 4
  1411. }
  1412. case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
  1413. // clobbers R3 !
  1414. // load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
  1415. // NOTE: this case does not use REGTMP. If it ever does,
  1416. // remove the NOTUSETMP flag in optab.
  1417. o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1418. o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
  1419. rel := obj.Addrel(c.cursym)
  1420. rel.Off = int32(c.pc + 4)
  1421. rel.Siz = 4
  1422. rel.Sym = p.To.Sym
  1423. rel.Add = p.To.Offset
  1424. rel.Type = objabi.R_ADDRMIPSTLS
  1425. case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
  1426. // clobbers R3 !
  1427. // NOTE: this case does not use REGTMP. If it ever does,
  1428. // remove the NOTUSETMP flag in optab.
  1429. o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1430. o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
  1431. rel := obj.Addrel(c.cursym)
  1432. rel.Off = int32(c.pc + 4)
  1433. rel.Siz = 4
  1434. rel.Sym = p.From.Sym
  1435. rel.Add = p.From.Offset
  1436. rel.Type = objabi.R_ADDRMIPSTLS
  1437. case 55: /* mov $tlsvar, r ==> rdhwr + add */
  1438. // clobbers R3 !
  1439. // NOTE: this case does not use REGTMP. If it ever does,
  1440. // remove the NOTUSETMP flag in optab.
  1441. o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1442. o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
  1443. rel := obj.Addrel(c.cursym)
  1444. rel.Off = int32(c.pc + 4)
  1445. rel.Siz = 4
  1446. rel.Sym = p.From.Sym
  1447. rel.Add = p.From.Offset
  1448. rel.Type = objabi.R_ADDRMIPSTLS
  1449. case 56: /* vmov{b,h,w,d} $scon, wr */
  1450. v := c.regoff(&p.From)
  1451. o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
  1452. case 57: /* vld $soreg, wr */
  1453. v := c.lsoffset(p.As, c.regoff(&p.From))
  1454. o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
  1455. case 58: /* vst wr, $soreg */
  1456. v := c.lsoffset(p.As, c.regoff(&p.To))
  1457. o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
  1458. }
  1459. out[0] = o1
  1460. out[1] = o2
  1461. out[2] = o3
  1462. out[3] = o4
  1463. }
  1464. func (c *ctxt0) vregoff(a *obj.Addr) int64 {
  1465. c.instoffset = 0
  1466. c.aclass(a)
  1467. return c.instoffset
  1468. }
  1469. func (c *ctxt0) regoff(a *obj.Addr) int32 {
  1470. return int32(c.vregoff(a))
  1471. }
  1472. func (c *ctxt0) oprrr(a obj.As) uint32 {
  1473. switch a {
  1474. case AADD:
  1475. return OP(4, 0)
  1476. case AADDU:
  1477. return OP(4, 1)
  1478. case ASGT:
  1479. return OP(5, 2)
  1480. case ASGTU:
  1481. return OP(5, 3)
  1482. case AAND:
  1483. return OP(4, 4)
  1484. case AOR:
  1485. return OP(4, 5)
  1486. case AXOR:
  1487. return OP(4, 6)
  1488. case ASUB:
  1489. return OP(4, 2)
  1490. case ASUBU, ANEGW:
  1491. return OP(4, 3)
  1492. case ANOR:
  1493. return OP(4, 7)
  1494. case ASLL:
  1495. return OP(0, 4)
  1496. case ASRL:
  1497. return OP(0, 6)
  1498. case ASRA:
  1499. return OP(0, 7)
  1500. case ASLLV:
  1501. return OP(2, 4)
  1502. case ASRLV:
  1503. return OP(2, 6)
  1504. case ASRAV:
  1505. return OP(2, 7)
  1506. case AADDV:
  1507. return OP(5, 4)
  1508. case AADDVU:
  1509. return OP(5, 5)
  1510. case ASUBV:
  1511. return OP(5, 6)
  1512. case ASUBVU, ANEGV:
  1513. return OP(5, 7)
  1514. case AREM,
  1515. ADIV:
  1516. return OP(3, 2)
  1517. case AREMU,
  1518. ADIVU:
  1519. return OP(3, 3)
  1520. case AMUL:
  1521. return OP(3, 0)
  1522. case AMULU:
  1523. return OP(3, 1)
  1524. case AREMV,
  1525. ADIVV:
  1526. return OP(3, 6)
  1527. case AREMVU,
  1528. ADIVVU:
  1529. return OP(3, 7)
  1530. case AMULV:
  1531. return OP(3, 4)
  1532. case AMULVU:
  1533. return OP(3, 5)
  1534. case AJMP:
  1535. return OP(1, 0)
  1536. case AJAL:
  1537. return OP(1, 1)
  1538. case ABREAK:
  1539. return OP(1, 5)
  1540. case ASYSCALL:
  1541. return OP(1, 4)
  1542. case ATLBP:
  1543. return MMU(1, 0)
  1544. case ATLBR:
  1545. return MMU(0, 1)
  1546. case ATLBWI:
  1547. return MMU(0, 2)
  1548. case ATLBWR:
  1549. return MMU(0, 6)
  1550. case ARFE:
  1551. return MMU(2, 0)
  1552. case ADIVF:
  1553. return FPF(0, 3)
  1554. case ADIVD:
  1555. return FPD(0, 3)
  1556. case AMULF:
  1557. return FPF(0, 2)
  1558. case AMULD:
  1559. return FPD(0, 2)
  1560. case ASUBF:
  1561. return FPF(0, 1)
  1562. case ASUBD:
  1563. return FPD(0, 1)
  1564. case AADDF:
  1565. return FPF(0, 0)
  1566. case AADDD:
  1567. return FPD(0, 0)
  1568. case ATRUNCFV:
  1569. return FPF(1, 1)
  1570. case ATRUNCDV:
  1571. return FPD(1, 1)
  1572. case ATRUNCFW:
  1573. return FPF(1, 5)
  1574. case ATRUNCDW:
  1575. return FPD(1, 5)
  1576. case AMOVFV:
  1577. return FPF(4, 5)
  1578. case AMOVDV:
  1579. return FPD(4, 5)
  1580. case AMOVVF:
  1581. return FPV(4, 0)
  1582. case AMOVVD:
  1583. return FPV(4, 1)
  1584. case AMOVFW:
  1585. return FPF(4, 4)
  1586. case AMOVDW:
  1587. return FPD(4, 4)
  1588. case AMOVWF:
  1589. return FPW(4, 0)
  1590. case AMOVDF:
  1591. return FPD(4, 0)
  1592. case AMOVWD:
  1593. return FPW(4, 1)
  1594. case AMOVFD:
  1595. return FPF(4, 1)
  1596. case AABSF:
  1597. return FPF(0, 5)
  1598. case AABSD:
  1599. return FPD(0, 5)
  1600. case AMOVF:
  1601. return FPF(0, 6)
  1602. case AMOVD:
  1603. return FPD(0, 6)
  1604. case ANEGF:
  1605. return FPF(0, 7)
  1606. case ANEGD:
  1607. return FPD(0, 7)
  1608. case ACMPEQF:
  1609. return FPF(6, 2)
  1610. case ACMPEQD:
  1611. return FPD(6, 2)
  1612. case ACMPGTF:
  1613. return FPF(7, 4)
  1614. case ACMPGTD:
  1615. return FPD(7, 4)
  1616. case ACMPGEF:
  1617. return FPF(7, 6)
  1618. case ACMPGED:
  1619. return FPD(7, 6)
  1620. case ASQRTF:
  1621. return FPF(0, 4)
  1622. case ASQRTD:
  1623. return FPD(0, 4)
  1624. case ASYNC:
  1625. return OP(1, 7)
  1626. case ANOOP:
  1627. return 0
  1628. case ACMOVN:
  1629. return OP(1, 3)
  1630. case ACMOVZ:
  1631. return OP(1, 2)
  1632. case ACMOVT:
  1633. return OP(0, 1) | (1 << 16)
  1634. case ACMOVF:
  1635. return OP(0, 1) | (0 << 16)
  1636. case ACLO:
  1637. return SP(3, 4) | OP(4, 1)
  1638. case ACLZ:
  1639. return SP(3, 4) | OP(4, 0)
  1640. case AMADD:
  1641. return SP(3, 4) | OP(0, 0)
  1642. case AMSUB:
  1643. return SP(3, 4) | OP(0, 4)
  1644. }
  1645. if a < 0 {
  1646. c.ctxt.Diag("bad rrr opcode -%v", -a)
  1647. } else {
  1648. c.ctxt.Diag("bad rrr opcode %v", a)
  1649. }
  1650. return 0
  1651. }
  1652. func (c *ctxt0) opirr(a obj.As) uint32 {
  1653. switch a {
  1654. case AADD:
  1655. return SP(1, 0)
  1656. case AADDU:
  1657. return SP(1, 1)
  1658. case ASGT:
  1659. return SP(1, 2)
  1660. case ASGTU:
  1661. return SP(1, 3)
  1662. case AAND:
  1663. return SP(1, 4)
  1664. case AOR:
  1665. return SP(1, 5)
  1666. case AXOR:
  1667. return SP(1, 6)
  1668. case ALUI:
  1669. return SP(1, 7)
  1670. case ASLL:
  1671. return OP(0, 0)
  1672. case ASRL:
  1673. return OP(0, 2)
  1674. case ASRA:
  1675. return OP(0, 3)
  1676. case AADDV:
  1677. return SP(3, 0)
  1678. case AADDVU:
  1679. return SP(3, 1)
  1680. case AJMP:
  1681. return SP(0, 2)
  1682. case AJAL,
  1683. obj.ADUFFZERO,
  1684. obj.ADUFFCOPY:
  1685. return SP(0, 3)
  1686. case ABEQ:
  1687. return SP(0, 4)
  1688. case -ABEQ:
  1689. return SP(2, 4) /* likely */
  1690. case ABNE:
  1691. return SP(0, 5)
  1692. case -ABNE:
  1693. return SP(2, 5) /* likely */
  1694. case ABGEZ:
  1695. return SP(0, 1) | BCOND(0, 1)
  1696. case -ABGEZ:
  1697. return SP(0, 1) | BCOND(0, 3) /* likely */
  1698. case ABGEZAL:
  1699. return SP(0, 1) | BCOND(2, 1)
  1700. case -ABGEZAL:
  1701. return SP(0, 1) | BCOND(2, 3) /* likely */
  1702. case ABGTZ:
  1703. return SP(0, 7)
  1704. case -ABGTZ:
  1705. return SP(2, 7) /* likely */
  1706. case ABLEZ:
  1707. return SP(0, 6)
  1708. case -ABLEZ:
  1709. return SP(2, 6) /* likely */
  1710. case ABLTZ:
  1711. return SP(0, 1) | BCOND(0, 0)
  1712. case -ABLTZ:
  1713. return SP(0, 1) | BCOND(0, 2) /* likely */
  1714. case ABLTZAL:
  1715. return SP(0, 1) | BCOND(2, 0)
  1716. case -ABLTZAL:
  1717. return SP(0, 1) | BCOND(2, 2) /* likely */
  1718. case ABFPT:
  1719. return SP(2, 1) | (257 << 16)
  1720. case -ABFPT:
  1721. return SP(2, 1) | (259 << 16) /* likely */
  1722. case ABFPF:
  1723. return SP(2, 1) | (256 << 16)
  1724. case -ABFPF:
  1725. return SP(2, 1) | (258 << 16) /* likely */
  1726. case AMOVB,
  1727. AMOVBU:
  1728. return SP(5, 0)
  1729. case AMOVH,
  1730. AMOVHU:
  1731. return SP(5, 1)
  1732. case AMOVW,
  1733. AMOVWU:
  1734. return SP(5, 3)
  1735. case AMOVV:
  1736. return SP(7, 7)
  1737. case AMOVF:
  1738. return SP(7, 1)
  1739. case AMOVD:
  1740. return SP(7, 5)
  1741. case AMOVWL:
  1742. return SP(5, 2)
  1743. case AMOVWR:
  1744. return SP(5, 6)
  1745. case AMOVVL:
  1746. return SP(5, 4)
  1747. case AMOVVR:
  1748. return SP(5, 5)
  1749. case ABREAK:
  1750. return SP(5, 7)
  1751. case -AMOVWL:
  1752. return SP(4, 2)
  1753. case -AMOVWR:
  1754. return SP(4, 6)
  1755. case -AMOVVL:
  1756. return SP(3, 2)
  1757. case -AMOVVR:
  1758. return SP(3, 3)
  1759. case -AMOVB:
  1760. return SP(4, 0)
  1761. case -AMOVBU:
  1762. return SP(4, 4)
  1763. case -AMOVH:
  1764. return SP(4, 1)
  1765. case -AMOVHU:
  1766. return SP(4, 5)
  1767. case -AMOVW:
  1768. return SP(4, 3)
  1769. case -AMOVWU:
  1770. return SP(4, 7)
  1771. case -AMOVV:
  1772. return SP(6, 7)
  1773. case -AMOVF:
  1774. return SP(6, 1)
  1775. case -AMOVD:
  1776. return SP(6, 5)
  1777. case ASLLV:
  1778. return OP(7, 0)
  1779. case ASRLV:
  1780. return OP(7, 2)
  1781. case ASRAV:
  1782. return OP(7, 3)
  1783. case -ASLLV:
  1784. return OP(7, 4)
  1785. case -ASRLV:
  1786. return OP(7, 6)
  1787. case -ASRAV:
  1788. return OP(7, 7)
  1789. case ATEQ:
  1790. return OP(6, 4)
  1791. case ATNE:
  1792. return OP(6, 6)
  1793. case -ALL:
  1794. return SP(6, 0)
  1795. case -ALLV:
  1796. return SP(6, 4)
  1797. case ASC:
  1798. return SP(7, 0)
  1799. case ASCV:
  1800. return SP(7, 4)
  1801. }
  1802. if a < 0 {
  1803. c.ctxt.Diag("bad irr opcode -%v", -a)
  1804. } else {
  1805. c.ctxt.Diag("bad irr opcode %v", a)
  1806. }
  1807. return 0
  1808. }
  1809. func vshift(a obj.As) bool {
  1810. switch a {
  1811. case ASLLV,
  1812. ASRLV,
  1813. ASRAV:
  1814. return true
  1815. }
  1816. return false
  1817. }
  1818. // MSA Two-bit Data Format Field Encoding
  1819. func (c *ctxt0) twobitdf(a obj.As) uint32 {
  1820. switch a {
  1821. case AVMOVB:
  1822. return 0
  1823. case AVMOVH:
  1824. return 1
  1825. case AVMOVW:
  1826. return 2
  1827. case AVMOVD:
  1828. return 3
  1829. default:
  1830. c.ctxt.Diag("unsupported data format %v", a)
  1831. }
  1832. return 0
  1833. }
  1834. // MSA Load/Store offset have to be multiple of size of data format
  1835. func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
  1836. var mod int32
  1837. switch a {
  1838. case AVMOVB:
  1839. mod = 1
  1840. case AVMOVH:
  1841. mod = 2
  1842. case AVMOVW:
  1843. mod = 4
  1844. case AVMOVD:
  1845. mod = 8
  1846. default:
  1847. c.ctxt.Diag("unsupported instruction:%v", a)
  1848. }
  1849. if o%mod != 0 {
  1850. c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
  1851. }
  1852. return o / mod
  1853. }