obj.go 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999
  1. // Copyright © 2015 The Go Authors. All rights reserved.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. package riscv
  21. import (
  22. "github.com/twitchyliquid64/golang-asm/obj"
  23. "github.com/twitchyliquid64/golang-asm/objabi"
  24. "github.com/twitchyliquid64/golang-asm/sys"
  25. "fmt"
  26. )
  27. func buildop(ctxt *obj.Link) {}
  28. // jalrToSym replaces p with a set of Progs needed to jump to the Sym in p.
  29. // lr is the link register to use for the JALR.
  30. // p must be a CALL, JMP or RET.
  31. func jalrToSym(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, lr int16) *obj.Prog {
  32. if p.As != obj.ACALL && p.As != obj.AJMP && p.As != obj.ARET {
  33. ctxt.Diag("unexpected Prog in jalrToSym: %v", p)
  34. return p
  35. }
  36. // TODO(jsing): Consider using a single JAL instruction and teaching
  37. // the linker to provide trampolines for the case where the destination
  38. // offset is too large. This would potentially reduce instructions for
  39. // the common case, but would require three instructions to go via the
  40. // trampoline.
  41. to := p.To
  42. p.As = AAUIPC
  43. p.Mark |= NEED_PCREL_ITYPE_RELOC
  44. p.RestArgs = []obj.Addr{obj.Addr{Type: obj.TYPE_CONST, Offset: to.Offset, Sym: to.Sym}}
  45. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
  46. p.Reg = 0
  47. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  48. p = obj.Appendp(p, newprog)
  49. // Leave Sym only for the CALL reloc in assemble.
  50. p.As = AJALR
  51. p.From.Type = obj.TYPE_REG
  52. p.From.Reg = lr
  53. p.Reg = 0
  54. p.To.Type = obj.TYPE_REG
  55. p.To.Reg = REG_TMP
  56. p.To.Sym = to.Sym
  57. return p
  58. }
  59. // progedit is called individually for each *obj.Prog. It normalizes instruction
  60. // formats and eliminates as many pseudo-instructions as possible.
  61. func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
  62. // Expand binary instructions to ternary ones.
  63. if p.Reg == 0 {
  64. switch p.As {
  65. case AADDI, ASLTI, ASLTIU, AANDI, AORI, AXORI, ASLLI, ASRLI, ASRAI,
  66. AADD, AAND, AOR, AXOR, ASLL, ASRL, ASUB, ASRA,
  67. AMUL, AMULH, AMULHU, AMULHSU, AMULW, ADIV, ADIVU, ADIVW, ADIVUW,
  68. AREM, AREMU, AREMW, AREMUW:
  69. p.Reg = p.To.Reg
  70. }
  71. }
  72. // Rewrite instructions with constant operands to refer to the immediate
  73. // form of the instruction.
  74. if p.From.Type == obj.TYPE_CONST {
  75. switch p.As {
  76. case AADD:
  77. p.As = AADDI
  78. case ASLT:
  79. p.As = ASLTI
  80. case ASLTU:
  81. p.As = ASLTIU
  82. case AAND:
  83. p.As = AANDI
  84. case AOR:
  85. p.As = AORI
  86. case AXOR:
  87. p.As = AXORI
  88. case ASLL:
  89. p.As = ASLLI
  90. case ASRL:
  91. p.As = ASRLI
  92. case ASRA:
  93. p.As = ASRAI
  94. }
  95. }
  96. switch p.As {
  97. case obj.AJMP:
  98. // Turn JMP into JAL ZERO or JALR ZERO.
  99. p.From.Type = obj.TYPE_REG
  100. p.From.Reg = REG_ZERO
  101. switch p.To.Type {
  102. case obj.TYPE_BRANCH:
  103. p.As = AJAL
  104. case obj.TYPE_MEM:
  105. switch p.To.Name {
  106. case obj.NAME_NONE:
  107. p.As = AJALR
  108. case obj.NAME_EXTERN:
  109. // Handled in preprocess.
  110. default:
  111. ctxt.Diag("unsupported name %d for %v", p.To.Name, p)
  112. }
  113. default:
  114. panic(fmt.Sprintf("unhandled type %+v", p.To.Type))
  115. }
  116. case obj.ACALL:
  117. switch p.To.Type {
  118. case obj.TYPE_MEM:
  119. // Handled in preprocess.
  120. case obj.TYPE_REG:
  121. p.As = AJALR
  122. p.From.Type = obj.TYPE_REG
  123. p.From.Reg = REG_LR
  124. default:
  125. ctxt.Diag("unknown destination type %+v in CALL: %v", p.To.Type, p)
  126. }
  127. case obj.AUNDEF:
  128. p.As = AEBREAK
  129. case ASCALL:
  130. // SCALL is the old name for ECALL.
  131. p.As = AECALL
  132. case ASBREAK:
  133. // SBREAK is the old name for EBREAK.
  134. p.As = AEBREAK
  135. }
  136. }
  137. // addrToReg extracts the register from an Addr, handling special Addr.Names.
  138. func addrToReg(a obj.Addr) int16 {
  139. switch a.Name {
  140. case obj.NAME_PARAM, obj.NAME_AUTO:
  141. return REG_SP
  142. }
  143. return a.Reg
  144. }
  145. // movToLoad converts a MOV mnemonic into the corresponding load instruction.
  146. func movToLoad(mnemonic obj.As) obj.As {
  147. switch mnemonic {
  148. case AMOV:
  149. return ALD
  150. case AMOVB:
  151. return ALB
  152. case AMOVH:
  153. return ALH
  154. case AMOVW:
  155. return ALW
  156. case AMOVBU:
  157. return ALBU
  158. case AMOVHU:
  159. return ALHU
  160. case AMOVWU:
  161. return ALWU
  162. case AMOVF:
  163. return AFLW
  164. case AMOVD:
  165. return AFLD
  166. default:
  167. panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
  168. }
  169. }
  170. // movToStore converts a MOV mnemonic into the corresponding store instruction.
  171. func movToStore(mnemonic obj.As) obj.As {
  172. switch mnemonic {
  173. case AMOV:
  174. return ASD
  175. case AMOVB:
  176. return ASB
  177. case AMOVH:
  178. return ASH
  179. case AMOVW:
  180. return ASW
  181. case AMOVF:
  182. return AFSW
  183. case AMOVD:
  184. return AFSD
  185. default:
  186. panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
  187. }
  188. }
  189. // rewriteMOV rewrites MOV pseudo-instructions.
  190. func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
  191. switch p.As {
  192. case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  193. default:
  194. panic(fmt.Sprintf("%+v is not a MOV pseudo-instruction", p.As))
  195. }
  196. switch p.From.Type {
  197. case obj.TYPE_MEM: // MOV c(Rs), Rd -> L $c, Rs, Rd
  198. switch p.From.Name {
  199. case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  200. if p.To.Type != obj.TYPE_REG {
  201. ctxt.Diag("unsupported load at %v", p)
  202. }
  203. p.As = movToLoad(p.As)
  204. p.From.Reg = addrToReg(p.From)
  205. case obj.NAME_EXTERN, obj.NAME_STATIC:
  206. // AUIPC $off_hi, R
  207. // L $off_lo, R
  208. as := p.As
  209. to := p.To
  210. p.As = AAUIPC
  211. p.Mark |= NEED_PCREL_ITYPE_RELOC
  212. p.RestArgs = []obj.Addr{obj.Addr{Type: obj.TYPE_CONST, Offset: p.From.Offset, Sym: p.From.Sym}}
  213. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
  214. p.Reg = 0
  215. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: to.Reg}
  216. p = obj.Appendp(p, newprog)
  217. p.As = movToLoad(as)
  218. p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: to.Reg, Offset: 0}
  219. p.To = to
  220. default:
  221. ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  222. }
  223. case obj.TYPE_REG:
  224. switch p.To.Type {
  225. case obj.TYPE_REG:
  226. switch p.As {
  227. case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb
  228. p.As = AADDI
  229. p.Reg = p.From.Reg
  230. p.From = obj.Addr{Type: obj.TYPE_CONST}
  231. case AMOVF: // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
  232. p.As = AFSGNJS
  233. p.Reg = p.From.Reg
  234. case AMOVD: // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
  235. p.As = AFSGNJD
  236. p.Reg = p.From.Reg
  237. default:
  238. ctxt.Diag("unsupported register-register move at %v", p)
  239. }
  240. case obj.TYPE_MEM: // MOV Rs, c(Rd) -> S $c, Rs, Rd
  241. switch p.As {
  242. case AMOVBU, AMOVHU, AMOVWU:
  243. ctxt.Diag("unsupported unsigned store at %v", p)
  244. }
  245. switch p.To.Name {
  246. case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  247. p.As = movToStore(p.As)
  248. p.To.Reg = addrToReg(p.To)
  249. case obj.NAME_EXTERN:
  250. // AUIPC $off_hi, TMP
  251. // S $off_lo, TMP, R
  252. as := p.As
  253. from := p.From
  254. p.As = AAUIPC
  255. p.Mark |= NEED_PCREL_STYPE_RELOC
  256. p.RestArgs = []obj.Addr{obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym}}
  257. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
  258. p.Reg = 0
  259. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  260. p = obj.Appendp(p, newprog)
  261. p.As = movToStore(as)
  262. p.From = from
  263. p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: 0}
  264. default:
  265. ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  266. }
  267. default:
  268. ctxt.Diag("unsupported MOV at %v", p)
  269. }
  270. case obj.TYPE_CONST:
  271. // MOV $c, R
  272. // If c is small enough, convert to:
  273. // ADD $c, ZERO, R
  274. // If not, convert to:
  275. // LUI top20bits(c), R
  276. // ADD bottom12bits(c), R, R
  277. if p.As != AMOV {
  278. ctxt.Diag("unsupported constant load at %v", p)
  279. }
  280. off := p.From.Offset
  281. to := p.To
  282. low, high, err := Split32BitImmediate(off)
  283. if err != nil {
  284. ctxt.Diag("%v: constant %d too large: %v", p, off, err)
  285. }
  286. // LUI is only necessary if the offset doesn't fit in 12-bits.
  287. needLUI := high != 0
  288. if needLUI {
  289. p.As = ALUI
  290. p.To = to
  291. // Pass top 20 bits to LUI.
  292. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
  293. p = obj.Appendp(p, newprog)
  294. }
  295. p.As = AADDIW
  296. p.To = to
  297. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
  298. p.Reg = REG_ZERO
  299. if needLUI {
  300. p.Reg = to.Reg
  301. }
  302. case obj.TYPE_ADDR: // MOV $sym+off(SP/SB), R
  303. if p.To.Type != obj.TYPE_REG || p.As != AMOV {
  304. ctxt.Diag("unsupported addr MOV at %v", p)
  305. }
  306. switch p.From.Name {
  307. case obj.NAME_EXTERN, obj.NAME_STATIC:
  308. // AUIPC $off_hi, R
  309. // ADDI $off_lo, R
  310. to := p.To
  311. p.As = AAUIPC
  312. p.Mark |= NEED_PCREL_ITYPE_RELOC
  313. p.RestArgs = []obj.Addr{obj.Addr{Type: obj.TYPE_CONST, Offset: p.From.Offset, Sym: p.From.Sym}}
  314. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
  315. p.Reg = 0
  316. p.To = to
  317. p = obj.Appendp(p, newprog)
  318. p.As = AADDI
  319. p.From = obj.Addr{Type: obj.TYPE_CONST}
  320. p.Reg = to.Reg
  321. p.To = to
  322. case obj.NAME_PARAM, obj.NAME_AUTO:
  323. p.As = AADDI
  324. p.Reg = REG_SP
  325. p.From.Type = obj.TYPE_CONST
  326. case obj.NAME_NONE:
  327. p.As = AADDI
  328. p.Reg = p.From.Reg
  329. p.From.Type = obj.TYPE_CONST
  330. p.From.Reg = 0
  331. default:
  332. ctxt.Diag("bad addr MOV from name %v at %v", p.From.Name, p)
  333. }
  334. default:
  335. ctxt.Diag("unsupported MOV at %v", p)
  336. }
  337. }
  338. // InvertBranch inverts the condition of a conditional branch.
  339. func InvertBranch(as obj.As) obj.As {
  340. switch as {
  341. case ABEQ:
  342. return ABNE
  343. case ABEQZ:
  344. return ABNEZ
  345. case ABGE:
  346. return ABLT
  347. case ABGEU:
  348. return ABLTU
  349. case ABGEZ:
  350. return ABLTZ
  351. case ABGT:
  352. return ABLE
  353. case ABGTU:
  354. return ABLEU
  355. case ABGTZ:
  356. return ABLEZ
  357. case ABLE:
  358. return ABGT
  359. case ABLEU:
  360. return ABGTU
  361. case ABLEZ:
  362. return ABGTZ
  363. case ABLT:
  364. return ABGE
  365. case ABLTU:
  366. return ABGEU
  367. case ABLTZ:
  368. return ABGEZ
  369. case ABNE:
  370. return ABEQ
  371. case ABNEZ:
  372. return ABEQZ
  373. default:
  374. panic("InvertBranch: not a branch")
  375. }
  376. }
  377. // containsCall reports whether the symbol contains a CALL (or equivalent)
  378. // instruction. Must be called after progedit.
  379. func containsCall(sym *obj.LSym) bool {
  380. // CALLs are CALL or JAL(R) with link register LR.
  381. for p := sym.Func.Text; p != nil; p = p.Link {
  382. switch p.As {
  383. case obj.ACALL:
  384. return true
  385. case AJAL, AJALR:
  386. if p.From.Type == obj.TYPE_REG && p.From.Reg == REG_LR {
  387. return true
  388. }
  389. }
  390. }
  391. return false
  392. }
  393. // setPCs sets the Pc field in all instructions reachable from p.
  394. // It uses pc as the initial value.
  395. func setPCs(p *obj.Prog, pc int64) {
  396. for ; p != nil; p = p.Link {
  397. p.Pc = pc
  398. for _, ins := range instructionsForProg(p) {
  399. pc += int64(ins.length())
  400. }
  401. }
  402. }
  403. // stackOffset updates Addr offsets based on the current stack size.
  404. //
  405. // The stack looks like:
  406. // -------------------
  407. // | |
  408. // | PARAMs |
  409. // | |
  410. // | |
  411. // -------------------
  412. // | Parent RA | SP on function entry
  413. // -------------------
  414. // | |
  415. // | |
  416. // | AUTOs |
  417. // | |
  418. // | |
  419. // -------------------
  420. // | RA | SP during function execution
  421. // -------------------
  422. //
  423. // FixedFrameSize makes other packages aware of the space allocated for RA.
  424. //
  425. // A nicer version of this diagram can be found on slide 21 of the presentation
  426. // attached to:
  427. //
  428. // https://golang.org/issue/16922#issuecomment-243748180
  429. //
  430. func stackOffset(a *obj.Addr, stacksize int64) {
  431. switch a.Name {
  432. case obj.NAME_AUTO:
  433. // Adjust to the top of AUTOs.
  434. a.Offset += stacksize
  435. case obj.NAME_PARAM:
  436. // Adjust to the bottom of PARAMs.
  437. a.Offset += stacksize + 8
  438. }
  439. }
  440. // preprocess generates prologue and epilogue code, computes PC-relative branch
  441. // and jump offsets, and resolves pseudo-registers.
  442. //
  443. // preprocess is called once per linker symbol.
  444. //
  445. // When preprocess finishes, all instructions in the symbol are either
  446. // concrete, real RISC-V instructions or directive pseudo-ops like TEXT,
  447. // PCDATA, and FUNCDATA.
  448. func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  449. if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
  450. return
  451. }
  452. // Generate the prologue.
  453. text := cursym.Func.Text
  454. if text.As != obj.ATEXT {
  455. ctxt.Diag("preprocess: found symbol that does not start with TEXT directive")
  456. return
  457. }
  458. stacksize := text.To.Offset
  459. if stacksize == -8 {
  460. // Historical way to mark NOFRAME.
  461. text.From.Sym.Set(obj.AttrNoFrame, true)
  462. stacksize = 0
  463. }
  464. if stacksize < 0 {
  465. ctxt.Diag("negative frame size %d - did you mean NOFRAME?", stacksize)
  466. }
  467. if text.From.Sym.NoFrame() {
  468. if stacksize != 0 {
  469. ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", stacksize)
  470. }
  471. }
  472. if !containsCall(cursym) {
  473. text.From.Sym.Set(obj.AttrLeaf, true)
  474. if stacksize == 0 {
  475. // A leaf function with no locals has no frame.
  476. text.From.Sym.Set(obj.AttrNoFrame, true)
  477. }
  478. }
  479. // Save LR unless there is no frame.
  480. if !text.From.Sym.NoFrame() {
  481. stacksize += ctxt.FixedFrameSize()
  482. }
  483. cursym.Func.Args = text.To.Val.(int32)
  484. cursym.Func.Locals = int32(stacksize)
  485. prologue := text
  486. if !cursym.Func.Text.From.Sym.NoSplit() {
  487. prologue = stacksplit(ctxt, prologue, cursym, newprog, stacksize) // emit split check
  488. }
  489. if stacksize != 0 {
  490. prologue = ctxt.StartUnsafePoint(prologue, newprog)
  491. // Actually save LR.
  492. prologue = obj.Appendp(prologue, newprog)
  493. prologue.As = AMOV
  494. prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
  495. prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -stacksize}
  496. // Insert stack adjustment.
  497. prologue = obj.Appendp(prologue, newprog)
  498. prologue.As = AADDI
  499. prologue.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -stacksize}
  500. prologue.Reg = REG_SP
  501. prologue.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
  502. prologue.Spadj = int32(stacksize)
  503. prologue = ctxt.EndUnsafePoint(prologue, newprog, -1)
  504. }
  505. if cursym.Func.Text.From.Sym.Wrapper() {
  506. // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
  507. //
  508. // MOV g_panic(g), X11
  509. // BNE X11, ZERO, adjust
  510. // end:
  511. // NOP
  512. // ...rest of function..
  513. // adjust:
  514. // MOV panic_argp(X11), X12
  515. // ADD $(autosize+FIXED_FRAME), SP, X13
  516. // BNE X12, X13, end
  517. // ADD $FIXED_FRAME, SP, X12
  518. // MOV X12, panic_argp(X11)
  519. // JMP end
  520. //
  521. // The NOP is needed to give the jumps somewhere to land.
  522. ldpanic := obj.Appendp(prologue, newprog)
  523. ldpanic.As = AMOV
  524. ldpanic.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGG, Offset: 4 * int64(ctxt.Arch.PtrSize)} // G.panic
  525. ldpanic.Reg = 0
  526. ldpanic.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X11}
  527. bneadj := obj.Appendp(ldpanic, newprog)
  528. bneadj.As = ABNE
  529. bneadj.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X11}
  530. bneadj.Reg = REG_ZERO
  531. bneadj.To.Type = obj.TYPE_BRANCH
  532. endadj := obj.Appendp(bneadj, newprog)
  533. endadj.As = obj.ANOP
  534. last := endadj
  535. for last.Link != nil {
  536. last = last.Link
  537. }
  538. getargp := obj.Appendp(last, newprog)
  539. getargp.As = AMOV
  540. getargp.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X11, Offset: 0} // Panic.argp
  541. getargp.Reg = 0
  542. getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12}
  543. bneadj.To.SetTarget(getargp)
  544. calcargp := obj.Appendp(getargp, newprog)
  545. calcargp.As = AADDI
  546. calcargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize + ctxt.FixedFrameSize()}
  547. calcargp.Reg = REG_SP
  548. calcargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X13}
  549. testargp := obj.Appendp(calcargp, newprog)
  550. testargp.As = ABNE
  551. testargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12}
  552. testargp.Reg = REG_X13
  553. testargp.To.Type = obj.TYPE_BRANCH
  554. testargp.To.SetTarget(endadj)
  555. adjargp := obj.Appendp(testargp, newprog)
  556. adjargp.As = AADDI
  557. adjargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(ctxt.Arch.PtrSize)}
  558. adjargp.Reg = REG_SP
  559. adjargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12}
  560. setargp := obj.Appendp(adjargp, newprog)
  561. setargp.As = AMOV
  562. setargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12}
  563. setargp.Reg = 0
  564. setargp.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X11, Offset: 0} // Panic.argp
  565. godone := obj.Appendp(setargp, newprog)
  566. godone.As = AJAL
  567. godone.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
  568. godone.To.Type = obj.TYPE_BRANCH
  569. godone.To.SetTarget(endadj)
  570. }
  571. // Update stack-based offsets.
  572. for p := cursym.Func.Text; p != nil; p = p.Link {
  573. stackOffset(&p.From, stacksize)
  574. stackOffset(&p.To, stacksize)
  575. }
  576. // Additional instruction rewriting.
  577. for p := cursym.Func.Text; p != nil; p = p.Link {
  578. switch p.As {
  579. case obj.AGETCALLERPC:
  580. if cursym.Leaf() {
  581. // MOV LR, Rd
  582. p.As = AMOV
  583. p.From.Type = obj.TYPE_REG
  584. p.From.Reg = REG_LR
  585. } else {
  586. // MOV (RSP), Rd
  587. p.As = AMOV
  588. p.From.Type = obj.TYPE_MEM
  589. p.From.Reg = REG_SP
  590. }
  591. case obj.ACALL:
  592. switch p.To.Type {
  593. case obj.TYPE_MEM:
  594. jalrToSym(ctxt, p, newprog, REG_LR)
  595. }
  596. case obj.AJMP:
  597. switch p.To.Type {
  598. case obj.TYPE_MEM:
  599. switch p.To.Name {
  600. case obj.NAME_EXTERN:
  601. // JMP to symbol.
  602. jalrToSym(ctxt, p, newprog, REG_ZERO)
  603. }
  604. }
  605. case obj.ARET:
  606. // Replace RET with epilogue.
  607. retJMP := p.To.Sym
  608. if stacksize != 0 {
  609. // Restore LR.
  610. p.As = AMOV
  611. p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
  612. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
  613. p = obj.Appendp(p, newprog)
  614. p.As = AADDI
  615. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize}
  616. p.Reg = REG_SP
  617. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
  618. p.Spadj = int32(-stacksize)
  619. p = obj.Appendp(p, newprog)
  620. }
  621. if retJMP != nil {
  622. p.As = obj.ARET
  623. p.To.Sym = retJMP
  624. p = jalrToSym(ctxt, p, newprog, REG_ZERO)
  625. } else {
  626. p.As = AJALR
  627. p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
  628. p.Reg = 0
  629. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
  630. }
  631. // "Add back" the stack removed in the previous instruction.
  632. //
  633. // This is to avoid confusing pctospadj, which sums
  634. // Spadj from function entry to each PC, and shouldn't
  635. // count adjustments from earlier epilogues, since they
  636. // won't affect later PCs.
  637. p.Spadj = int32(stacksize)
  638. case AADDI:
  639. // Refine Spadjs account for adjustment via ADDI instruction.
  640. if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SP && p.From.Type == obj.TYPE_CONST {
  641. p.Spadj = int32(-p.From.Offset)
  642. }
  643. }
  644. }
  645. // Rewrite MOV pseudo-instructions. This cannot be done in
  646. // progedit, as SP offsets need to be applied before we split
  647. // up some of the Addrs.
  648. for p := cursym.Func.Text; p != nil; p = p.Link {
  649. switch p.As {
  650. case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  651. rewriteMOV(ctxt, newprog, p)
  652. }
  653. }
  654. // Split immediates larger than 12-bits.
  655. for p := cursym.Func.Text; p != nil; p = p.Link {
  656. switch p.As {
  657. // <opi> $imm, REG, TO
  658. case AADDI, AANDI, AORI, AXORI:
  659. // LUI $high, TMP
  660. // ADDI $low, TMP, TMP
  661. // <op> TMP, REG, TO
  662. q := *p
  663. low, high, err := Split32BitImmediate(p.From.Offset)
  664. if err != nil {
  665. ctxt.Diag("%v: constant %d too large", p, p.From.Offset, err)
  666. }
  667. if high == 0 {
  668. break // no need to split
  669. }
  670. p.As = ALUI
  671. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
  672. p.Reg = 0
  673. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  674. p.Spadj = 0 // needed if TO is SP
  675. p = obj.Appendp(p, newprog)
  676. p.As = AADDIW
  677. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
  678. p.Reg = REG_TMP
  679. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  680. p = obj.Appendp(p, newprog)
  681. switch q.As {
  682. case AADDI:
  683. p.As = AADD
  684. case AANDI:
  685. p.As = AAND
  686. case AORI:
  687. p.As = AOR
  688. case AXORI:
  689. p.As = AXOR
  690. default:
  691. ctxt.Diag("unsupported instruction %v for splitting", q)
  692. }
  693. p.Spadj = q.Spadj
  694. p.To = q.To
  695. p.Reg = q.Reg
  696. p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  697. // <load> $imm, REG, TO (load $imm+(REG), TO)
  698. case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
  699. low, high, err := Split32BitImmediate(p.From.Offset)
  700. if err != nil {
  701. ctxt.Diag("%v: constant %d too large", p, p.From.Offset)
  702. }
  703. if high == 0 {
  704. break // no need to split
  705. }
  706. q := *p
  707. // LUI $high, TMP
  708. // ADD TMP, REG, TMP
  709. // <load> $low, TMP, TO
  710. p.As = ALUI
  711. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
  712. p.Reg = 0
  713. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  714. p.Spadj = 0 // needed if TO is SP
  715. p = obj.Appendp(p, newprog)
  716. p.As = AADD
  717. p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  718. p.Reg = q.From.Reg
  719. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  720. p = obj.Appendp(p, newprog)
  721. p.As = q.As
  722. p.To = q.To
  723. p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: low}
  724. p.Reg = obj.REG_NONE
  725. // <store> $imm, REG, TO (store $imm+(TO), REG)
  726. case ASD, ASB, ASH, ASW, AFSW, AFSD:
  727. low, high, err := Split32BitImmediate(p.To.Offset)
  728. if err != nil {
  729. ctxt.Diag("%v: constant %d too large", p, p.To.Offset)
  730. }
  731. if high == 0 {
  732. break // no need to split
  733. }
  734. q := *p
  735. // LUI $high, TMP
  736. // ADD TMP, TO, TMP
  737. // <store> $low, REG, TMP
  738. p.As = ALUI
  739. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
  740. p.Reg = 0
  741. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  742. p.Spadj = 0 // needed if TO is SP
  743. p = obj.Appendp(p, newprog)
  744. p.As = AADD
  745. p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  746. p.Reg = q.To.Reg
  747. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  748. p = obj.Appendp(p, newprog)
  749. p.As = q.As
  750. p.From = obj.Addr{Type: obj.TYPE_REG, Reg: q.From.Reg, Offset: 0}
  751. p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: low}
  752. }
  753. }
  754. // Compute instruction addresses. Once we do that, we need to check for
  755. // overextended jumps and branches. Within each iteration, Pc differences
  756. // are always lower bounds (since the program gets monotonically longer,
  757. // a fixed point will be reached). No attempt to handle functions > 2GiB.
  758. for {
  759. rescan := false
  760. setPCs(cursym.Func.Text, 0)
  761. for p := cursym.Func.Text; p != nil; p = p.Link {
  762. switch p.As {
  763. case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
  764. if p.To.Type != obj.TYPE_BRANCH {
  765. panic("assemble: instruction with branch-like opcode lacks destination")
  766. }
  767. offset := p.To.Target().Pc - p.Pc
  768. if offset < -4096 || 4096 <= offset {
  769. // Branch is long. Replace it with a jump.
  770. jmp := obj.Appendp(p, newprog)
  771. jmp.As = AJAL
  772. jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
  773. jmp.To = obj.Addr{Type: obj.TYPE_BRANCH}
  774. jmp.To.SetTarget(p.To.Target())
  775. p.As = InvertBranch(p.As)
  776. p.To.SetTarget(jmp.Link)
  777. // We may have made previous branches too long,
  778. // so recheck them.
  779. rescan = true
  780. }
  781. case AJAL:
  782. if p.To.Target() == nil {
  783. panic("intersymbol jumps should be expressed as AUIPC+JALR")
  784. }
  785. offset := p.To.Target().Pc - p.Pc
  786. if offset < -(1<<20) || (1<<20) <= offset {
  787. // Replace with 2-instruction sequence. This assumes
  788. // that TMP is not live across J instructions, since
  789. // it is reserved by SSA.
  790. jmp := obj.Appendp(p, newprog)
  791. jmp.As = AJALR
  792. jmp.From = p.From
  793. jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  794. // p.From is not generally valid, however will be
  795. // fixed up in the next loop.
  796. p.As = AAUIPC
  797. p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym}
  798. p.From.SetTarget(p.To.Target())
  799. p.Reg = 0
  800. p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
  801. rescan = true
  802. }
  803. }
  804. }
  805. if !rescan {
  806. break
  807. }
  808. }
  809. // Now that there are no long branches, resolve branch and jump targets.
  810. // At this point, instruction rewriting which changes the number of
  811. // instructions will break everything--don't do it!
  812. for p := cursym.Func.Text; p != nil; p = p.Link {
  813. switch p.As {
  814. case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ, AJAL:
  815. switch p.To.Type {
  816. case obj.TYPE_BRANCH:
  817. p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
  818. case obj.TYPE_MEM:
  819. panic("unhandled type")
  820. }
  821. case AAUIPC:
  822. if p.From.Type == obj.TYPE_BRANCH {
  823. low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc)
  824. if err != nil {
  825. ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
  826. }
  827. p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
  828. p.Link.From.Offset = low
  829. }
  830. }
  831. }
  832. // Validate all instructions - this provides nice error messages.
  833. for p := cursym.Func.Text; p != nil; p = p.Link {
  834. for _, ins := range instructionsForProg(p) {
  835. ins.validate(ctxt)
  836. }
  837. }
  838. }
  839. func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgAlloc, framesize int64) *obj.Prog {
  840. // Leaf function with no frame is effectively NOSPLIT.
  841. if framesize == 0 {
  842. return p
  843. }
  844. // MOV g_stackguard(g), X10
  845. p = obj.Appendp(p, newprog)
  846. p.As = AMOV
  847. p.From.Type = obj.TYPE_MEM
  848. p.From.Reg = REGG
  849. p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
  850. if cursym.CFunc() {
  851. p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
  852. }
  853. p.To.Type = obj.TYPE_REG
  854. p.To.Reg = REG_X10
  855. var to_done, to_more *obj.Prog
  856. if framesize <= objabi.StackSmall {
  857. // small stack: SP < stackguard
  858. // BLTU SP, stackguard, done
  859. p = obj.Appendp(p, newprog)
  860. p.As = ABLTU
  861. p.From.Type = obj.TYPE_REG
  862. p.From.Reg = REG_X10
  863. p.Reg = REG_SP
  864. p.To.Type = obj.TYPE_BRANCH
  865. to_done = p
  866. } else if framesize <= objabi.StackBig {
  867. // large stack: SP-framesize < stackguard-StackSmall
  868. // ADD $-(framesize-StackSmall), SP, X11
  869. // BLTU X11, stackguard, done
  870. p = obj.Appendp(p, newprog)
  871. // TODO(sorear): logic inconsistent with comment, but both match all non-x86 arches
  872. p.As = AADDI
  873. p.From.Type = obj.TYPE_CONST
  874. p.From.Offset = -(int64(framesize) - objabi.StackSmall)
  875. p.Reg = REG_SP
  876. p.To.Type = obj.TYPE_REG
  877. p.To.Reg = REG_X11
  878. p = obj.Appendp(p, newprog)
  879. p.As = ABLTU
  880. p.From.Type = obj.TYPE_REG
  881. p.From.Reg = REG_X10
  882. p.Reg = REG_X11
  883. p.To.Type = obj.TYPE_BRANCH
  884. to_done = p
  885. } else {
  886. // Such a large stack we need to protect against wraparound.
  887. // If SP is close to zero:
  888. // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
  889. // The +StackGuard on both sides is required to keep the left side positive:
  890. // SP is allowed to be slightly below stackguard. See stack.h.
  891. //
  892. // Preemption sets stackguard to StackPreempt, a very large value.
  893. // That breaks the math above, so we have to check for that explicitly.
  894. // // stackguard is X10
  895. // MOV $StackPreempt, X11
  896. // BEQ X10, X11, more
  897. // ADD $StackGuard, SP, X11
  898. // SUB X10, X11
  899. // MOV $(framesize+(StackGuard-StackSmall)), X10
  900. // BGTU X11, X10, done
  901. p = obj.Appendp(p, newprog)
  902. p.As = AMOV
  903. p.From.Type = obj.TYPE_CONST
  904. p.From.Offset = objabi.StackPreempt
  905. p.To.Type = obj.TYPE_REG
  906. p.To.Reg = REG_X11
  907. p = obj.Appendp(p, newprog)
  908. to_more = p
  909. p.As = ABEQ
  910. p.From.Type = obj.TYPE_REG
  911. p.From.Reg = REG_X10
  912. p.Reg = REG_X11
  913. p.To.Type = obj.TYPE_BRANCH
  914. p = obj.Appendp(p, newprog)
  915. p.As = AADDI
  916. p.From.Type = obj.TYPE_CONST
  917. p.From.Offset = int64(objabi.StackGuard)
  918. p.Reg = REG_SP
  919. p.To.Type = obj.TYPE_REG
  920. p.To.Reg = REG_X11
  921. p = obj.Appendp(p, newprog)
  922. p.As = ASUB
  923. p.From.Type = obj.TYPE_REG
  924. p.From.Reg = REG_X10
  925. p.Reg = REG_X11
  926. p.To.Type = obj.TYPE_REG
  927. p.To.Reg = REG_X11
  928. p = obj.Appendp(p, newprog)
  929. p.As = AMOV
  930. p.From.Type = obj.TYPE_CONST
  931. p.From.Offset = int64(framesize) + int64(objabi.StackGuard) - objabi.StackSmall
  932. p.To.Type = obj.TYPE_REG
  933. p.To.Reg = REG_X10
  934. p = obj.Appendp(p, newprog)
  935. p.As = ABLTU
  936. p.From.Type = obj.TYPE_REG
  937. p.From.Reg = REG_X10
  938. p.Reg = REG_X11
  939. p.To.Type = obj.TYPE_BRANCH
  940. to_done = p
  941. }
  942. p = ctxt.EmitEntryLiveness(cursym, p, newprog)
  943. // CALL runtime.morestack(SB)
  944. p = obj.Appendp(p, newprog)
  945. p.As = obj.ACALL
  946. p.To.Type = obj.TYPE_BRANCH
  947. if cursym.CFunc() {
  948. p.To.Sym = ctxt.Lookup("runtime.morestackc")
  949. } else if !cursym.Func.Text.From.Sym.NeedCtxt() {
  950. p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt")
  951. } else {
  952. p.To.Sym = ctxt.Lookup("runtime.morestack")
  953. }
  954. if to_more != nil {
  955. to_more.To.SetTarget(p)
  956. }
  957. p = jalrToSym(ctxt, p, newprog, REG_X5)
  958. // JMP start
  959. p = obj.Appendp(p, newprog)
  960. p.As = AJAL
  961. p.To = obj.Addr{Type: obj.TYPE_BRANCH}
  962. p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
  963. p.To.SetTarget(cursym.Func.Text.Link)
  964. // placeholder for to_done's jump target
  965. p = obj.Appendp(p, newprog)
  966. p.As = obj.ANOP // zero-width place holder
  967. to_done.To.SetTarget(p)
  968. return p
  969. }
  970. // signExtend sign extends val starting at bit bit.
  971. func signExtend(val int64, bit uint) int64 {
  972. return val << (64 - bit) >> (64 - bit)
  973. }
  974. // Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
  975. // upper immediate and a signed 12-bit lower immediate to be added to the upper
  976. // result. For example, high may be used in LUI and low in a following ADDI to
  977. // generate a full 32-bit constant.
  978. func Split32BitImmediate(imm int64) (low, high int64, err error) {
  979. if !immIFits(imm, 32) {
  980. return 0, 0, fmt.Errorf("immediate does not fit in 32-bits: %d", imm)
  981. }
  982. // Nothing special needs to be done if the immediate fits in 12-bits.
  983. if immIFits(imm, 12) {
  984. return imm, 0, nil
  985. }
  986. high = imm >> 12
  987. // The bottom 12 bits will be treated as signed.
  988. //
  989. // If that will result in a negative 12 bit number, add 1 to
  990. // our upper bits to adjust for the borrow.
  991. //
  992. // It is not possible for this increment to overflow. To
  993. // overflow, the 20 top bits would be 1, and the sign bit for
  994. // the low 12 bits would be set, in which case the entire 32
  995. // bit pattern fits in a 12 bit signed value.
  996. if imm&(1<<11) != 0 {
  997. high++
  998. }
  999. low = signExtend(imm, 12)
  1000. high = signExtend(high, 20)
  1001. return low, high, nil
  1002. }
  1003. func regVal(r, min, max uint32) uint32 {
  1004. if r < min || r > max {
  1005. panic(fmt.Sprintf("register out of range, want %d < %d < %d", min, r, max))
  1006. }
  1007. return r - min
  1008. }
  1009. // regI returns an integer register.
  1010. func regI(r uint32) uint32 {
  1011. return regVal(r, REG_X0, REG_X31)
  1012. }
  1013. // regF returns a float register.
  1014. func regF(r uint32) uint32 {
  1015. return regVal(r, REG_F0, REG_F31)
  1016. }
  1017. // regAddr extracts a register from an Addr.
  1018. func regAddr(a obj.Addr, min, max uint32) uint32 {
  1019. if a.Type != obj.TYPE_REG {
  1020. panic(fmt.Sprintf("ill typed: %+v", a))
  1021. }
  1022. return regVal(uint32(a.Reg), min, max)
  1023. }
  1024. // regIAddr extracts the integer register from an Addr.
  1025. func regIAddr(a obj.Addr) uint32 {
  1026. return regAddr(a, REG_X0, REG_X31)
  1027. }
  1028. // regFAddr extracts the float register from an Addr.
  1029. func regFAddr(a obj.Addr) uint32 {
  1030. return regAddr(a, REG_F0, REG_F31)
  1031. }
  1032. // immIFits reports whether immediate value x fits in nbits bits
  1033. // as a signed integer.
  1034. func immIFits(x int64, nbits uint) bool {
  1035. nbits--
  1036. var min int64 = -1 << nbits
  1037. var max int64 = 1<<nbits - 1
  1038. return min <= x && x <= max
  1039. }
  1040. // immI extracts the signed integer of the specified size from an immediate.
  1041. func immI(as obj.As, imm int64, nbits uint) uint32 {
  1042. if !immIFits(imm, nbits) {
  1043. panic(fmt.Sprintf("%v\tsigned immediate %d cannot fit in %d bits", as, imm, nbits))
  1044. }
  1045. return uint32(imm)
  1046. }
  1047. func wantImmI(ctxt *obj.Link, as obj.As, imm int64, nbits uint) {
  1048. if !immIFits(imm, nbits) {
  1049. ctxt.Diag("%v\tsigned immediate cannot be larger than %d bits but got %d", as, nbits, imm)
  1050. }
  1051. }
  1052. func wantReg(ctxt *obj.Link, as obj.As, pos string, descr string, r, min, max uint32) {
  1053. if r < min || r > max {
  1054. var suffix string
  1055. if r != obj.REG_NONE {
  1056. suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r)))
  1057. }
  1058. ctxt.Diag("%v\texpected %s register in %s position%s", as, descr, pos, suffix)
  1059. }
  1060. }
  1061. func wantNoneReg(ctxt *obj.Link, as obj.As, pos string, r uint32) {
  1062. if r != obj.REG_NONE {
  1063. ctxt.Diag("%v\texpected no register in %s but got register %s", as, pos, RegName(int(r)))
  1064. }
  1065. }
  1066. // wantIntReg checks that r is an integer register.
  1067. func wantIntReg(ctxt *obj.Link, as obj.As, pos string, r uint32) {
  1068. wantReg(ctxt, as, pos, "integer", r, REG_X0, REG_X31)
  1069. }
  1070. // wantFloatReg checks that r is a floating-point register.
  1071. func wantFloatReg(ctxt *obj.Link, as obj.As, pos string, r uint32) {
  1072. wantReg(ctxt, as, pos, "float", r, REG_F0, REG_F31)
  1073. }
  1074. // wantEvenOffset checks that the offset is a multiple of two.
  1075. func wantEvenOffset(ctxt *obj.Link, as obj.As, offset int64) {
  1076. if offset%1 != 0 {
  1077. ctxt.Diag("%v\tjump offset %v must be even", as, offset)
  1078. }
  1079. }
  1080. func validateRIII(ctxt *obj.Link, ins *instruction) {
  1081. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1082. wantIntReg(ctxt, ins.as, "rs1", ins.rs1)
  1083. wantIntReg(ctxt, ins.as, "rs2", ins.rs2)
  1084. }
  1085. func validateRFFF(ctxt *obj.Link, ins *instruction) {
  1086. wantFloatReg(ctxt, ins.as, "rd", ins.rd)
  1087. wantFloatReg(ctxt, ins.as, "rs1", ins.rs1)
  1088. wantFloatReg(ctxt, ins.as, "rs2", ins.rs2)
  1089. }
  1090. func validateRFFI(ctxt *obj.Link, ins *instruction) {
  1091. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1092. wantFloatReg(ctxt, ins.as, "rs1", ins.rs1)
  1093. wantFloatReg(ctxt, ins.as, "rs2", ins.rs2)
  1094. }
  1095. func validateRFI(ctxt *obj.Link, ins *instruction) {
  1096. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1097. wantNoneReg(ctxt, ins.as, "rs1", ins.rs1)
  1098. wantFloatReg(ctxt, ins.as, "rs2", ins.rs2)
  1099. }
  1100. func validateRIF(ctxt *obj.Link, ins *instruction) {
  1101. wantFloatReg(ctxt, ins.as, "rd", ins.rd)
  1102. wantNoneReg(ctxt, ins.as, "rs1", ins.rs1)
  1103. wantIntReg(ctxt, ins.as, "rs2", ins.rs2)
  1104. }
  1105. func validateRFF(ctxt *obj.Link, ins *instruction) {
  1106. wantFloatReg(ctxt, ins.as, "rd", ins.rd)
  1107. wantNoneReg(ctxt, ins.as, "rs1", ins.rs1)
  1108. wantFloatReg(ctxt, ins.as, "rs2", ins.rs2)
  1109. }
  1110. func validateII(ctxt *obj.Link, ins *instruction) {
  1111. wantImmI(ctxt, ins.as, ins.imm, 12)
  1112. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1113. wantIntReg(ctxt, ins.as, "rs1", ins.rs1)
  1114. }
  1115. func validateIF(ctxt *obj.Link, ins *instruction) {
  1116. wantImmI(ctxt, ins.as, ins.imm, 12)
  1117. wantFloatReg(ctxt, ins.as, "rd", ins.rd)
  1118. wantIntReg(ctxt, ins.as, "rs1", ins.rs1)
  1119. }
  1120. func validateSI(ctxt *obj.Link, ins *instruction) {
  1121. wantImmI(ctxt, ins.as, ins.imm, 12)
  1122. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1123. wantIntReg(ctxt, ins.as, "rs1", ins.rs1)
  1124. }
  1125. func validateSF(ctxt *obj.Link, ins *instruction) {
  1126. wantImmI(ctxt, ins.as, ins.imm, 12)
  1127. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1128. wantFloatReg(ctxt, ins.as, "rs1", ins.rs1)
  1129. }
  1130. func validateB(ctxt *obj.Link, ins *instruction) {
  1131. // Offsets are multiples of two, so accept 13 bit immediates for the
  1132. // 12 bit slot. We implicitly drop the least significant bit in encodeB.
  1133. wantEvenOffset(ctxt, ins.as, ins.imm)
  1134. wantImmI(ctxt, ins.as, ins.imm, 13)
  1135. wantNoneReg(ctxt, ins.as, "rd", ins.rd)
  1136. wantIntReg(ctxt, ins.as, "rs1", ins.rs1)
  1137. wantIntReg(ctxt, ins.as, "rs2", ins.rs2)
  1138. }
  1139. func validateU(ctxt *obj.Link, ins *instruction) {
  1140. wantImmI(ctxt, ins.as, ins.imm, 20)
  1141. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1142. wantNoneReg(ctxt, ins.as, "rs1", ins.rs1)
  1143. wantNoneReg(ctxt, ins.as, "rs2", ins.rs2)
  1144. }
  1145. func validateJ(ctxt *obj.Link, ins *instruction) {
  1146. // Offsets are multiples of two, so accept 21 bit immediates for the
  1147. // 20 bit slot. We implicitly drop the least significant bit in encodeJ.
  1148. wantEvenOffset(ctxt, ins.as, ins.imm)
  1149. wantImmI(ctxt, ins.as, ins.imm, 21)
  1150. wantIntReg(ctxt, ins.as, "rd", ins.rd)
  1151. wantNoneReg(ctxt, ins.as, "rs1", ins.rs1)
  1152. wantNoneReg(ctxt, ins.as, "rs2", ins.rs2)
  1153. }
  1154. func validateRaw(ctxt *obj.Link, ins *instruction) {
  1155. // Treat the raw value specially as a 32-bit unsigned integer.
  1156. // Nobody wants to enter negative machine code.
  1157. if ins.imm < 0 || 1<<32 <= ins.imm {
  1158. ctxt.Diag("%v\timmediate in raw position cannot be larger than 32 bits but got %d", ins.as, ins.imm)
  1159. }
  1160. }
  1161. // encodeR encodes an R-type RISC-V instruction.
  1162. func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
  1163. enc := encode(as)
  1164. if enc == nil {
  1165. panic("encodeR: could not encode instruction")
  1166. }
  1167. if enc.rs2 != 0 && rs2 != 0 {
  1168. panic("encodeR: instruction uses rs2, but rs2 was nonzero")
  1169. }
  1170. return funct7<<25 | enc.funct7<<25 | enc.rs2<<20 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
  1171. }
  1172. func encodeRIII(ins *instruction) uint32 {
  1173. return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1174. }
  1175. func encodeRFFF(ins *instruction) uint32 {
  1176. return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
  1177. }
  1178. func encodeRFFI(ins *instruction) uint32 {
  1179. return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1180. }
  1181. func encodeRFI(ins *instruction) uint32 {
  1182. return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1183. }
  1184. func encodeRIF(ins *instruction) uint32 {
  1185. return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1186. }
  1187. func encodeRFF(ins *instruction) uint32 {
  1188. return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1189. }
  1190. // encodeI encodes an I-type RISC-V instruction.
  1191. func encodeI(as obj.As, rs1, rd, imm uint32) uint32 {
  1192. enc := encode(as)
  1193. if enc == nil {
  1194. panic("encodeI: could not encode instruction")
  1195. }
  1196. imm |= uint32(enc.csr)
  1197. return imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  1198. }
  1199. func encodeII(ins *instruction) uint32 {
  1200. return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm))
  1201. }
  1202. func encodeIF(ins *instruction) uint32 {
  1203. return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm))
  1204. }
  1205. // encodeS encodes an S-type RISC-V instruction.
  1206. func encodeS(as obj.As, rs1, rs2, imm uint32) uint32 {
  1207. enc := encode(as)
  1208. if enc == nil {
  1209. panic("encodeS: could not encode instruction")
  1210. }
  1211. return (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
  1212. }
  1213. func encodeSI(ins *instruction) uint32 {
  1214. return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm))
  1215. }
  1216. func encodeSF(ins *instruction) uint32 {
  1217. return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm))
  1218. }
  1219. // encodeB encodes a B-type RISC-V instruction.
  1220. func encodeB(ins *instruction) uint32 {
  1221. imm := immI(ins.as, ins.imm, 13)
  1222. rs2 := regI(ins.rs1)
  1223. rs1 := regI(ins.rs2)
  1224. enc := encode(ins.as)
  1225. if enc == nil {
  1226. panic("encodeB: could not encode instruction")
  1227. }
  1228. return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7 | enc.opcode
  1229. }
  1230. // encodeU encodes a U-type RISC-V instruction.
  1231. func encodeU(ins *instruction) uint32 {
  1232. // The immediates for encodeU are the upper 20 bits of a 32 bit value.
  1233. // Rather than have the user/compiler generate a 32 bit constant, the
  1234. // bottommost bits of which must all be zero, instead accept just the
  1235. // top bits.
  1236. imm := immI(ins.as, ins.imm, 20)
  1237. rd := regI(ins.rd)
  1238. enc := encode(ins.as)
  1239. if enc == nil {
  1240. panic("encodeU: could not encode instruction")
  1241. }
  1242. return imm<<12 | rd<<7 | enc.opcode
  1243. }
  1244. // encodeJ encodes a J-type RISC-V instruction.
  1245. func encodeJ(ins *instruction) uint32 {
  1246. imm := immI(ins.as, ins.imm, 21)
  1247. rd := regI(ins.rd)
  1248. enc := encode(ins.as)
  1249. if enc == nil {
  1250. panic("encodeJ: could not encode instruction")
  1251. }
  1252. return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12 | rd<<7 | enc.opcode
  1253. }
  1254. func encodeRawIns(ins *instruction) uint32 {
  1255. // Treat the raw value specially as a 32-bit unsigned integer.
  1256. // Nobody wants to enter negative machine code.
  1257. if ins.imm < 0 || 1<<32 <= ins.imm {
  1258. panic(fmt.Sprintf("immediate %d cannot fit in 32 bits", ins.imm))
  1259. }
  1260. return uint32(ins.imm)
  1261. }
  1262. func EncodeIImmediate(imm int64) (int64, error) {
  1263. if !immIFits(imm, 12) {
  1264. return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
  1265. }
  1266. return imm << 20, nil
  1267. }
  1268. func EncodeSImmediate(imm int64) (int64, error) {
  1269. if !immIFits(imm, 12) {
  1270. return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
  1271. }
  1272. return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
  1273. }
  1274. func EncodeUImmediate(imm int64) (int64, error) {
  1275. if !immIFits(imm, 20) {
  1276. return 0, fmt.Errorf("immediate %#x does not fit in 20 bits", imm)
  1277. }
  1278. return imm << 12, nil
  1279. }
  1280. type encoding struct {
  1281. encode func(*instruction) uint32 // encode returns the machine code for an instruction
  1282. validate func(*obj.Link, *instruction) // validate validates an instruction
  1283. length int // length of encoded instruction; 0 for pseudo-ops, 4 otherwise
  1284. }
  1285. var (
  1286. // Encodings have the following naming convention:
  1287. //
  1288. // 1. the instruction encoding (R/I/S/B/U/J), in lowercase
  1289. // 2. zero or more register operand identifiers (I = integer
  1290. // register, F = float register), in uppercase
  1291. // 3. the word "Encoding"
  1292. //
  1293. // For example, rIIIEncoding indicates an R-type instruction with two
  1294. // integer register inputs and an integer register output; sFEncoding
  1295. // indicates an S-type instruction with rs2 being a float register.
  1296. rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
  1297. rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
  1298. rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
  1299. rFIEncoding = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
  1300. rIFEncoding = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
  1301. rFFEncoding = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
  1302. iIEncoding = encoding{encode: encodeII, validate: validateII, length: 4}
  1303. iFEncoding = encoding{encode: encodeIF, validate: validateIF, length: 4}
  1304. sIEncoding = encoding{encode: encodeSI, validate: validateSI, length: 4}
  1305. sFEncoding = encoding{encode: encodeSF, validate: validateSF, length: 4}
  1306. bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
  1307. uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
  1308. jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
  1309. // rawEncoding encodes a raw instruction byte sequence.
  1310. rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
  1311. // pseudoOpEncoding panics if encoding is attempted, but does no validation.
  1312. pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
  1313. // badEncoding is used when an invalid op is encountered.
  1314. // An error has already been generated, so let anything else through.
  1315. badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
  1316. )
  1317. // encodings contains the encodings for RISC-V instructions.
  1318. // Instructions are masked with obj.AMask to keep indices small.
  1319. var encodings = [ALAST & obj.AMask]encoding{
  1320. // Unprivileged ISA
  1321. // 2.4: Integer Computational Instructions
  1322. AADDI & obj.AMask: iIEncoding,
  1323. ASLTI & obj.AMask: iIEncoding,
  1324. ASLTIU & obj.AMask: iIEncoding,
  1325. AANDI & obj.AMask: iIEncoding,
  1326. AORI & obj.AMask: iIEncoding,
  1327. AXORI & obj.AMask: iIEncoding,
  1328. ASLLI & obj.AMask: iIEncoding,
  1329. ASRLI & obj.AMask: iIEncoding,
  1330. ASRAI & obj.AMask: iIEncoding,
  1331. ALUI & obj.AMask: uEncoding,
  1332. AAUIPC & obj.AMask: uEncoding,
  1333. AADD & obj.AMask: rIIIEncoding,
  1334. ASLT & obj.AMask: rIIIEncoding,
  1335. ASLTU & obj.AMask: rIIIEncoding,
  1336. AAND & obj.AMask: rIIIEncoding,
  1337. AOR & obj.AMask: rIIIEncoding,
  1338. AXOR & obj.AMask: rIIIEncoding,
  1339. ASLL & obj.AMask: rIIIEncoding,
  1340. ASRL & obj.AMask: rIIIEncoding,
  1341. ASUB & obj.AMask: rIIIEncoding,
  1342. ASRA & obj.AMask: rIIIEncoding,
  1343. // 2.5: Control Transfer Instructions
  1344. AJAL & obj.AMask: jEncoding,
  1345. AJALR & obj.AMask: iIEncoding,
  1346. ABEQ & obj.AMask: bEncoding,
  1347. ABNE & obj.AMask: bEncoding,
  1348. ABLT & obj.AMask: bEncoding,
  1349. ABLTU & obj.AMask: bEncoding,
  1350. ABGE & obj.AMask: bEncoding,
  1351. ABGEU & obj.AMask: bEncoding,
  1352. // 2.6: Load and Store Instructions
  1353. ALW & obj.AMask: iIEncoding,
  1354. ALWU & obj.AMask: iIEncoding,
  1355. ALH & obj.AMask: iIEncoding,
  1356. ALHU & obj.AMask: iIEncoding,
  1357. ALB & obj.AMask: iIEncoding,
  1358. ALBU & obj.AMask: iIEncoding,
  1359. ASW & obj.AMask: sIEncoding,
  1360. ASH & obj.AMask: sIEncoding,
  1361. ASB & obj.AMask: sIEncoding,
  1362. // 2.7: Memory Ordering
  1363. AFENCE & obj.AMask: iIEncoding,
  1364. // 5.2: Integer Computational Instructions (RV64I)
  1365. AADDIW & obj.AMask: iIEncoding,
  1366. ASLLIW & obj.AMask: iIEncoding,
  1367. ASRLIW & obj.AMask: iIEncoding,
  1368. ASRAIW & obj.AMask: iIEncoding,
  1369. AADDW & obj.AMask: rIIIEncoding,
  1370. ASLLW & obj.AMask: rIIIEncoding,
  1371. ASRLW & obj.AMask: rIIIEncoding,
  1372. ASUBW & obj.AMask: rIIIEncoding,
  1373. ASRAW & obj.AMask: rIIIEncoding,
  1374. // 5.3: Load and Store Instructions (RV64I)
  1375. ALD & obj.AMask: iIEncoding,
  1376. ASD & obj.AMask: sIEncoding,
  1377. // 7.1: Multiplication Operations
  1378. AMUL & obj.AMask: rIIIEncoding,
  1379. AMULH & obj.AMask: rIIIEncoding,
  1380. AMULHU & obj.AMask: rIIIEncoding,
  1381. AMULHSU & obj.AMask: rIIIEncoding,
  1382. AMULW & obj.AMask: rIIIEncoding,
  1383. ADIV & obj.AMask: rIIIEncoding,
  1384. ADIVU & obj.AMask: rIIIEncoding,
  1385. AREM & obj.AMask: rIIIEncoding,
  1386. AREMU & obj.AMask: rIIIEncoding,
  1387. ADIVW & obj.AMask: rIIIEncoding,
  1388. ADIVUW & obj.AMask: rIIIEncoding,
  1389. AREMW & obj.AMask: rIIIEncoding,
  1390. AREMUW & obj.AMask: rIIIEncoding,
  1391. // 8.2: Load-Reserved/Store-Conditional
  1392. ALRW & obj.AMask: rIIIEncoding,
  1393. ALRD & obj.AMask: rIIIEncoding,
  1394. ASCW & obj.AMask: rIIIEncoding,
  1395. ASCD & obj.AMask: rIIIEncoding,
  1396. // 8.3: Atomic Memory Operations
  1397. AAMOSWAPW & obj.AMask: rIIIEncoding,
  1398. AAMOSWAPD & obj.AMask: rIIIEncoding,
  1399. AAMOADDW & obj.AMask: rIIIEncoding,
  1400. AAMOADDD & obj.AMask: rIIIEncoding,
  1401. AAMOANDW & obj.AMask: rIIIEncoding,
  1402. AAMOANDD & obj.AMask: rIIIEncoding,
  1403. AAMOORW & obj.AMask: rIIIEncoding,
  1404. AAMOORD & obj.AMask: rIIIEncoding,
  1405. AAMOXORW & obj.AMask: rIIIEncoding,
  1406. AAMOXORD & obj.AMask: rIIIEncoding,
  1407. AAMOMAXW & obj.AMask: rIIIEncoding,
  1408. AAMOMAXD & obj.AMask: rIIIEncoding,
  1409. AAMOMAXUW & obj.AMask: rIIIEncoding,
  1410. AAMOMAXUD & obj.AMask: rIIIEncoding,
  1411. AAMOMINW & obj.AMask: rIIIEncoding,
  1412. AAMOMIND & obj.AMask: rIIIEncoding,
  1413. AAMOMINUW & obj.AMask: rIIIEncoding,
  1414. AAMOMINUD & obj.AMask: rIIIEncoding,
  1415. // 10.1: Base Counters and Timers
  1416. ARDCYCLE & obj.AMask: iIEncoding,
  1417. ARDTIME & obj.AMask: iIEncoding,
  1418. ARDINSTRET & obj.AMask: iIEncoding,
  1419. // 11.5: Single-Precision Load and Store Instructions
  1420. AFLW & obj.AMask: iFEncoding,
  1421. AFSW & obj.AMask: sFEncoding,
  1422. // 11.6: Single-Precision Floating-Point Computational Instructions
  1423. AFADDS & obj.AMask: rFFFEncoding,
  1424. AFSUBS & obj.AMask: rFFFEncoding,
  1425. AFMULS & obj.AMask: rFFFEncoding,
  1426. AFDIVS & obj.AMask: rFFFEncoding,
  1427. AFMINS & obj.AMask: rFFFEncoding,
  1428. AFMAXS & obj.AMask: rFFFEncoding,
  1429. AFSQRTS & obj.AMask: rFFFEncoding,
  1430. // 11.7: Single-Precision Floating-Point Conversion and Move Instructions
  1431. AFCVTWS & obj.AMask: rFIEncoding,
  1432. AFCVTLS & obj.AMask: rFIEncoding,
  1433. AFCVTSW & obj.AMask: rIFEncoding,
  1434. AFCVTSL & obj.AMask: rIFEncoding,
  1435. AFCVTWUS & obj.AMask: rFIEncoding,
  1436. AFCVTLUS & obj.AMask: rFIEncoding,
  1437. AFCVTSWU & obj.AMask: rIFEncoding,
  1438. AFCVTSLU & obj.AMask: rIFEncoding,
  1439. AFSGNJS & obj.AMask: rFFFEncoding,
  1440. AFSGNJNS & obj.AMask: rFFFEncoding,
  1441. AFSGNJXS & obj.AMask: rFFFEncoding,
  1442. AFMVXS & obj.AMask: rFIEncoding,
  1443. AFMVSX & obj.AMask: rIFEncoding,
  1444. AFMVXW & obj.AMask: rFIEncoding,
  1445. AFMVWX & obj.AMask: rIFEncoding,
  1446. // 11.8: Single-Precision Floating-Point Compare Instructions
  1447. AFEQS & obj.AMask: rFFIEncoding,
  1448. AFLTS & obj.AMask: rFFIEncoding,
  1449. AFLES & obj.AMask: rFFIEncoding,
  1450. // 11.9: Single-Precision Floating-Point Classify Instruction
  1451. AFCLASSS & obj.AMask: rFIEncoding,
  1452. // 12.3: Double-Precision Load and Store Instructions
  1453. AFLD & obj.AMask: iFEncoding,
  1454. AFSD & obj.AMask: sFEncoding,
  1455. // 12.4: Double-Precision Floating-Point Computational Instructions
  1456. AFADDD & obj.AMask: rFFFEncoding,
  1457. AFSUBD & obj.AMask: rFFFEncoding,
  1458. AFMULD & obj.AMask: rFFFEncoding,
  1459. AFDIVD & obj.AMask: rFFFEncoding,
  1460. AFMIND & obj.AMask: rFFFEncoding,
  1461. AFMAXD & obj.AMask: rFFFEncoding,
  1462. AFSQRTD & obj.AMask: rFFFEncoding,
  1463. // 12.5: Double-Precision Floating-Point Conversion and Move Instructions
  1464. AFCVTWD & obj.AMask: rFIEncoding,
  1465. AFCVTLD & obj.AMask: rFIEncoding,
  1466. AFCVTDW & obj.AMask: rIFEncoding,
  1467. AFCVTDL & obj.AMask: rIFEncoding,
  1468. AFCVTWUD & obj.AMask: rFIEncoding,
  1469. AFCVTLUD & obj.AMask: rFIEncoding,
  1470. AFCVTDWU & obj.AMask: rIFEncoding,
  1471. AFCVTDLU & obj.AMask: rIFEncoding,
  1472. AFCVTSD & obj.AMask: rFFEncoding,
  1473. AFCVTDS & obj.AMask: rFFEncoding,
  1474. AFSGNJD & obj.AMask: rFFFEncoding,
  1475. AFSGNJND & obj.AMask: rFFFEncoding,
  1476. AFSGNJXD & obj.AMask: rFFFEncoding,
  1477. AFMVXD & obj.AMask: rFIEncoding,
  1478. AFMVDX & obj.AMask: rIFEncoding,
  1479. // 12.6: Double-Precision Floating-Point Compare Instructions
  1480. AFEQD & obj.AMask: rFFIEncoding,
  1481. AFLTD & obj.AMask: rFFIEncoding,
  1482. AFLED & obj.AMask: rFFIEncoding,
  1483. // 12.7: Double-Precision Floating-Point Classify Instruction
  1484. AFCLASSD & obj.AMask: rFIEncoding,
  1485. // Privileged ISA
  1486. // 3.2.1: Environment Call and Breakpoint
  1487. AECALL & obj.AMask: iIEncoding,
  1488. AEBREAK & obj.AMask: iIEncoding,
  1489. // Escape hatch
  1490. AWORD & obj.AMask: rawEncoding,
  1491. // Pseudo-operations
  1492. obj.AFUNCDATA: pseudoOpEncoding,
  1493. obj.APCDATA: pseudoOpEncoding,
  1494. obj.ATEXT: pseudoOpEncoding,
  1495. obj.ANOP: pseudoOpEncoding,
  1496. }
  1497. // encodingForAs returns the encoding for an obj.As.
  1498. func encodingForAs(as obj.As) (encoding, error) {
  1499. if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
  1500. return badEncoding, fmt.Errorf("encodingForAs: not a RISC-V instruction %s", as)
  1501. }
  1502. asi := as & obj.AMask
  1503. if int(asi) >= len(encodings) {
  1504. return badEncoding, fmt.Errorf("encodingForAs: bad RISC-V instruction %s", as)
  1505. }
  1506. enc := encodings[asi]
  1507. if enc.validate == nil {
  1508. return badEncoding, fmt.Errorf("encodingForAs: no encoding for instruction %s", as)
  1509. }
  1510. return enc, nil
  1511. }
  1512. type instruction struct {
  1513. as obj.As // Assembler opcode
  1514. rd uint32 // Destination register
  1515. rs1 uint32 // Source register 1
  1516. rs2 uint32 // Source register 2
  1517. imm int64 // Immediate
  1518. funct3 uint32 // Function 3
  1519. funct7 uint32 // Function 7
  1520. }
  1521. func (ins *instruction) encode() (uint32, error) {
  1522. enc, err := encodingForAs(ins.as)
  1523. if err != nil {
  1524. return 0, err
  1525. }
  1526. if enc.length > 0 {
  1527. return enc.encode(ins), nil
  1528. }
  1529. return 0, fmt.Errorf("fixme")
  1530. }
  1531. func (ins *instruction) length() int {
  1532. enc, err := encodingForAs(ins.as)
  1533. if err != nil {
  1534. return 0
  1535. }
  1536. return enc.length
  1537. }
  1538. func (ins *instruction) validate(ctxt *obj.Link) {
  1539. enc, err := encodingForAs(ins.as)
  1540. if err != nil {
  1541. ctxt.Diag(err.Error())
  1542. return
  1543. }
  1544. enc.validate(ctxt, ins)
  1545. }
  1546. // instructionsForProg returns the machine instructions for an *obj.Prog.
  1547. func instructionsForProg(p *obj.Prog) []*instruction {
  1548. ins := &instruction{
  1549. as: p.As,
  1550. rd: uint32(p.To.Reg),
  1551. rs1: uint32(p.Reg),
  1552. rs2: uint32(p.From.Reg),
  1553. imm: p.From.Offset,
  1554. }
  1555. inss := []*instruction{ins}
  1556. switch ins.as {
  1557. case AJAL, AJALR:
  1558. ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
  1559. ins.imm = p.To.Offset
  1560. case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
  1561. switch ins.as {
  1562. case ABEQZ:
  1563. ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
  1564. case ABGEZ:
  1565. ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
  1566. case ABGT:
  1567. ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.Reg), uint32(p.From.Reg)
  1568. case ABGTU:
  1569. ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.Reg), uint32(p.From.Reg)
  1570. case ABGTZ:
  1571. ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
  1572. case ABLE:
  1573. ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.Reg), uint32(p.From.Reg)
  1574. case ABLEU:
  1575. ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.Reg), uint32(p.From.Reg)
  1576. case ABLEZ:
  1577. ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
  1578. case ABLTZ:
  1579. ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
  1580. case ABNEZ:
  1581. ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
  1582. }
  1583. ins.imm = p.To.Offset
  1584. case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
  1585. if p.From.Type != obj.TYPE_MEM {
  1586. p.Ctxt.Diag("%v requires memory for source", p)
  1587. return nil
  1588. }
  1589. ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  1590. ins.imm = p.From.Offset
  1591. case ASW, ASH, ASB, ASD, AFSW, AFSD:
  1592. if p.To.Type != obj.TYPE_MEM {
  1593. p.Ctxt.Diag("%v requires memory for destination", p)
  1594. return nil
  1595. }
  1596. ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  1597. ins.imm = p.To.Offset
  1598. case ALRW, ALRD:
  1599. // Set aq to use acquire access ordering, which matches Go's memory requirements.
  1600. ins.funct7 = 2
  1601. ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
  1602. case ASCW, ASCD, AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
  1603. AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
  1604. // Set aq to use acquire access ordering, which matches Go's memory requirements.
  1605. ins.funct7 = 2
  1606. ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  1607. case AECALL, AEBREAK, ARDCYCLE, ARDTIME, ARDINSTRET:
  1608. insEnc := encode(p.As)
  1609. if p.To.Type == obj.TYPE_NONE {
  1610. ins.rd = REG_ZERO
  1611. }
  1612. ins.rs1 = REG_ZERO
  1613. ins.imm = insEnc.csr
  1614. case AFENCE:
  1615. ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
  1616. ins.imm = 0x0ff
  1617. case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  1618. // Set the rounding mode in funct3 to round to zero.
  1619. ins.funct3 = 1
  1620. case AFNES, AFNED:
  1621. // Replace FNE[SD] with FEQ[SD] and NOT.
  1622. if p.To.Type != obj.TYPE_REG {
  1623. p.Ctxt.Diag("%v needs an integer register output", ins.as)
  1624. return nil
  1625. }
  1626. if ins.as == AFNES {
  1627. ins.as = AFEQS
  1628. } else {
  1629. ins.as = AFEQD
  1630. }
  1631. ins = &instruction{
  1632. as: AXORI, // [bit] xor 1 = not [bit]
  1633. rd: ins.rd,
  1634. rs1: ins.rd,
  1635. imm: 1,
  1636. }
  1637. inss = append(inss, ins)
  1638. case AFSQRTS, AFSQRTD:
  1639. // These instructions expect a zero (i.e. float register 0)
  1640. // to be the second input operand.
  1641. ins.rs1 = uint32(p.From.Reg)
  1642. ins.rs2 = REG_F0
  1643. case ANEG, ANEGW:
  1644. // NEG rs, rd -> SUB rs, X0, rd
  1645. ins.as = ASUB
  1646. if p.As == ANEGW {
  1647. ins.as = ASUBW
  1648. }
  1649. ins.rs1 = REG_ZERO
  1650. if ins.rd == obj.REG_NONE {
  1651. ins.rd = ins.rs2
  1652. }
  1653. case ANOT:
  1654. // NOT rs, rd -> XORI $-1, rs, rd
  1655. ins.as = AXORI
  1656. ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  1657. if ins.rd == obj.REG_NONE {
  1658. ins.rd = ins.rs1
  1659. }
  1660. ins.imm = -1
  1661. case ASEQZ:
  1662. // SEQZ rs, rd -> SLTIU $1, rs, rd
  1663. ins.as = ASLTIU
  1664. ins.rs1 = uint32(p.From.Reg)
  1665. ins.imm = 1
  1666. case ASNEZ:
  1667. // SNEZ rs, rd -> SLTU rs, x0, rd
  1668. ins.as = ASLTU
  1669. ins.rs1 = REG_ZERO
  1670. case AFNEGS:
  1671. // FNEGS rs, rd -> FSGNJNS rs, rs, rd
  1672. ins.as = AFSGNJNS
  1673. ins.rs1 = uint32(p.From.Reg)
  1674. case AFNEGD:
  1675. // FNEGD rs, rd -> FSGNJND rs, rs, rd
  1676. ins.as = AFSGNJND
  1677. ins.rs1 = uint32(p.From.Reg)
  1678. }
  1679. return inss
  1680. }
  1681. // assemble emits machine code.
  1682. // It is called at the very end of the assembly process.
  1683. func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  1684. if ctxt.Retpoline {
  1685. ctxt.Diag("-spectre=ret not supported on riscv")
  1686. ctxt.Retpoline = false // don't keep printing
  1687. }
  1688. var symcode []uint32
  1689. for p := cursym.Func.Text; p != nil; p = p.Link {
  1690. switch p.As {
  1691. case AJALR:
  1692. if p.To.Sym != nil {
  1693. // This is a CALL/JMP. We add a relocation only
  1694. // for linker stack checking. No actual
  1695. // relocation is needed.
  1696. rel := obj.Addrel(cursym)
  1697. rel.Off = int32(p.Pc)
  1698. rel.Siz = 4
  1699. rel.Sym = p.To.Sym
  1700. rel.Add = p.To.Offset
  1701. rel.Type = objabi.R_CALLRISCV
  1702. }
  1703. case AAUIPC:
  1704. var rt objabi.RelocType
  1705. if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
  1706. rt = objabi.R_RISCV_PCREL_ITYPE
  1707. } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
  1708. rt = objabi.R_RISCV_PCREL_STYPE
  1709. } else {
  1710. break
  1711. }
  1712. if p.Link == nil {
  1713. ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
  1714. break
  1715. }
  1716. addr := p.RestArgs[0]
  1717. if addr.Sym == nil {
  1718. ctxt.Diag("AUIPC needing PC-relative reloc missing symbol")
  1719. break
  1720. }
  1721. rel := obj.Addrel(cursym)
  1722. rel.Off = int32(p.Pc)
  1723. rel.Siz = 8
  1724. rel.Sym = addr.Sym
  1725. rel.Add = addr.Offset
  1726. rel.Type = rt
  1727. }
  1728. for _, ins := range instructionsForProg(p) {
  1729. ic, err := ins.encode()
  1730. if err == nil {
  1731. symcode = append(symcode, ic)
  1732. }
  1733. }
  1734. }
  1735. cursym.Size = int64(4 * len(symcode))
  1736. cursym.Grow(cursym.Size)
  1737. for p, i := cursym.P, 0; i < len(symcode); p, i = p[4:], i+1 {
  1738. ctxt.Arch.ByteOrder.PutUint32(p, symcode[i])
  1739. }
  1740. obj.MarkUnsafePoints(ctxt, cursym.Func.Text, newprog, isUnsafePoint, nil)
  1741. }
  1742. func isUnsafePoint(p *obj.Prog) bool {
  1743. return p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
  1744. }
  1745. var LinkRISCV64 = obj.LinkArch{
  1746. Arch: sys.ArchRISCV64,
  1747. Init: buildop,
  1748. Preprocess: preprocess,
  1749. Assemble: assemble,
  1750. Progedit: progedit,
  1751. UnaryDst: unaryDst,
  1752. DWARFRegisters: RISCV64DWARFRegisters,
  1753. }