]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/obj/riscv/obj.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / cmd / internal / obj / riscv / obj.go
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
21 package riscv
22
23 import (
24         "cmd/internal/obj"
25         "cmd/internal/objabi"
26         "cmd/internal/sys"
27         "fmt"
28         "internal/abi"
29         "log"
30         "math/bits"
31 )
32
33 func buildop(ctxt *obj.Link) {}
34
35 func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) {
36         switch p.As {
37         case obj.ACALL, obj.AJMP, obj.ARET, obj.ADUFFZERO, obj.ADUFFCOPY:
38         default:
39                 ctxt.Diag("unexpected Prog in jalToSym: %v", p)
40                 return
41         }
42
43         p.As = AJAL
44         p.Mark |= NEED_JAL_RELOC
45         p.From.Type = obj.TYPE_REG
46         p.From.Reg = lr
47         p.Reg = obj.REG_NONE
48 }
49
50 // progedit is called individually for each *obj.Prog. It normalizes instruction
51 // formats and eliminates as many pseudo-instructions as possible.
52 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
53
54         // Expand binary instructions to ternary ones.
55         if p.Reg == obj.REG_NONE {
56                 switch p.As {
57                 case AADDI, ASLTI, ASLTIU, AANDI, AORI, AXORI, ASLLI, ASRLI, ASRAI,
58                         AADDIW, ASLLIW, ASRLIW, ASRAIW, AADDW, ASUBW, ASLLW, ASRLW, ASRAW,
59                         AADD, AAND, AOR, AXOR, ASLL, ASRL, ASUB, ASRA,
60                         AMUL, AMULH, AMULHU, AMULHSU, AMULW, ADIV, ADIVU, ADIVW, ADIVUW,
61                         AREM, AREMU, AREMW, AREMUW:
62                         p.Reg = p.To.Reg
63                 }
64         }
65
66         // Rewrite instructions with constant operands to refer to the immediate
67         // form of the instruction.
68         if p.From.Type == obj.TYPE_CONST {
69                 switch p.As {
70                 case AADD:
71                         p.As = AADDI
72                 case ASUB:
73                         p.As, p.From.Offset = AADDI, -p.From.Offset
74                 case ASLT:
75                         p.As = ASLTI
76                 case ASLTU:
77                         p.As = ASLTIU
78                 case AAND:
79                         p.As = AANDI
80                 case AOR:
81                         p.As = AORI
82                 case AXOR:
83                         p.As = AXORI
84                 case ASLL:
85                         p.As = ASLLI
86                 case ASRL:
87                         p.As = ASRLI
88                 case ASRA:
89                         p.As = ASRAI
90                 case AADDW:
91                         p.As = AADDIW
92                 case ASUBW:
93                         p.As, p.From.Offset = AADDIW, -p.From.Offset
94                 case ASLLW:
95                         p.As = ASLLIW
96                 case ASRLW:
97                         p.As = ASRLIW
98                 case ASRAW:
99                         p.As = ASRAIW
100                 }
101         }
102
103         switch p.As {
104         case obj.AJMP:
105                 // Turn JMP into JAL ZERO or JALR ZERO.
106                 p.From.Type = obj.TYPE_REG
107                 p.From.Reg = REG_ZERO
108
109                 switch p.To.Type {
110                 case obj.TYPE_BRANCH:
111                         p.As = AJAL
112                 case obj.TYPE_MEM:
113                         switch p.To.Name {
114                         case obj.NAME_NONE:
115                                 p.As = AJALR
116                         case obj.NAME_EXTERN, obj.NAME_STATIC:
117                                 // Handled in preprocess.
118                         default:
119                                 ctxt.Diag("unsupported name %d for %v", p.To.Name, p)
120                         }
121                 default:
122                         panic(fmt.Sprintf("unhandled type %+v", p.To.Type))
123                 }
124
125         case obj.ACALL:
126                 switch p.To.Type {
127                 case obj.TYPE_MEM:
128                         // Handled in preprocess.
129                 case obj.TYPE_REG:
130                         p.As = AJALR
131                         p.From.Type = obj.TYPE_REG
132                         p.From.Reg = REG_LR
133                 default:
134                         ctxt.Diag("unknown destination type %+v in CALL: %v", p.To.Type, p)
135                 }
136
137         case obj.AUNDEF:
138                 p.As = AEBREAK
139
140         case ASCALL:
141                 // SCALL is the old name for ECALL.
142                 p.As = AECALL
143
144         case ASBREAK:
145                 // SBREAK is the old name for EBREAK.
146                 p.As = AEBREAK
147
148         case AMOV:
149                 if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE && int64(int32(p.From.Offset)) != p.From.Offset {
150                         ctz := bits.TrailingZeros64(uint64(p.From.Offset))
151                         val := p.From.Offset >> ctz
152                         if int64(int32(val)) == val {
153                                 // It's ok. We can handle constants with many trailing zeros.
154                                 break
155                         }
156                         // Put >32-bit constants in memory and load them.
157                         p.From.Type = obj.TYPE_MEM
158                         p.From.Sym = ctxt.Int64Sym(p.From.Offset)
159                         p.From.Name = obj.NAME_EXTERN
160                         p.From.Offset = 0
161                 }
162         }
163 }
164
165 // addrToReg extracts the register from an Addr, handling special Addr.Names.
166 func addrToReg(a obj.Addr) int16 {
167         switch a.Name {
168         case obj.NAME_PARAM, obj.NAME_AUTO:
169                 return REG_SP
170         }
171         return a.Reg
172 }
173
174 // movToLoad converts a MOV mnemonic into the corresponding load instruction.
175 func movToLoad(mnemonic obj.As) obj.As {
176         switch mnemonic {
177         case AMOV:
178                 return ALD
179         case AMOVB:
180                 return ALB
181         case AMOVH:
182                 return ALH
183         case AMOVW:
184                 return ALW
185         case AMOVBU:
186                 return ALBU
187         case AMOVHU:
188                 return ALHU
189         case AMOVWU:
190                 return ALWU
191         case AMOVF:
192                 return AFLW
193         case AMOVD:
194                 return AFLD
195         default:
196                 panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
197         }
198 }
199
200 // movToStore converts a MOV mnemonic into the corresponding store instruction.
201 func movToStore(mnemonic obj.As) obj.As {
202         switch mnemonic {
203         case AMOV:
204                 return ASD
205         case AMOVB:
206                 return ASB
207         case AMOVH:
208                 return ASH
209         case AMOVW:
210                 return ASW
211         case AMOVF:
212                 return AFSW
213         case AMOVD:
214                 return AFSD
215         default:
216                 panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
217         }
218 }
219
220 // markRelocs marks an obj.Prog that specifies a MOV pseudo-instruction and
221 // requires relocation.
222 func markRelocs(p *obj.Prog) {
223         switch p.As {
224         case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
225                 switch {
226                 case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
227                         switch p.From.Name {
228                         case obj.NAME_EXTERN, obj.NAME_STATIC:
229                                 p.Mark |= NEED_PCREL_ITYPE_RELOC
230                         }
231                 case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
232                         switch p.From.Name {
233                         case obj.NAME_EXTERN, obj.NAME_STATIC:
234                                 p.Mark |= NEED_PCREL_ITYPE_RELOC
235                         }
236                 case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
237                         switch p.To.Name {
238                         case obj.NAME_EXTERN, obj.NAME_STATIC:
239                                 p.Mark |= NEED_PCREL_STYPE_RELOC
240                         }
241                 }
242         }
243 }
244
245 // InvertBranch inverts the condition of a conditional branch.
246 func InvertBranch(as obj.As) obj.As {
247         switch as {
248         case ABEQ:
249                 return ABNE
250         case ABEQZ:
251                 return ABNEZ
252         case ABGE:
253                 return ABLT
254         case ABGEU:
255                 return ABLTU
256         case ABGEZ:
257                 return ABLTZ
258         case ABGT:
259                 return ABLE
260         case ABGTU:
261                 return ABLEU
262         case ABGTZ:
263                 return ABLEZ
264         case ABLE:
265                 return ABGT
266         case ABLEU:
267                 return ABGTU
268         case ABLEZ:
269                 return ABGTZ
270         case ABLT:
271                 return ABGE
272         case ABLTU:
273                 return ABGEU
274         case ABLTZ:
275                 return ABGEZ
276         case ABNE:
277                 return ABEQ
278         case ABNEZ:
279                 return ABEQZ
280         default:
281                 panic("InvertBranch: not a branch")
282         }
283 }
284
285 // containsCall reports whether the symbol contains a CALL (or equivalent)
286 // instruction. Must be called after progedit.
287 func containsCall(sym *obj.LSym) bool {
288         // CALLs are CALL or JAL(R) with link register LR.
289         for p := sym.Func().Text; p != nil; p = p.Link {
290                 switch p.As {
291                 case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
292                         return true
293                 case AJAL, AJALR:
294                         if p.From.Type == obj.TYPE_REG && p.From.Reg == REG_LR {
295                                 return true
296                         }
297                 }
298         }
299
300         return false
301 }
302
303 // setPCs sets the Pc field in all instructions reachable from p.
304 // It uses pc as the initial value and returns the next available pc.
305 func setPCs(p *obj.Prog, pc int64) int64 {
306         for ; p != nil; p = p.Link {
307                 p.Pc = pc
308                 for _, ins := range instructionsForProg(p) {
309                         pc += int64(ins.length())
310                 }
311         }
312         return pc
313 }
314
315 // stackOffset updates Addr offsets based on the current stack size.
316 //
317 // The stack looks like:
318 // -------------------
319 // |                 |
320 // |      PARAMs     |
321 // |                 |
322 // |                 |
323 // -------------------
324 // |    Parent RA    |   SP on function entry
325 // -------------------
326 // |                 |
327 // |                 |
328 // |       AUTOs     |
329 // |                 |
330 // |                 |
331 // -------------------
332 // |        RA       |   SP during function execution
333 // -------------------
334 //
335 // FixedFrameSize makes other packages aware of the space allocated for RA.
336 //
337 // A nicer version of this diagram can be found on slide 21 of the presentation
338 // attached to https://golang.org/issue/16922#issuecomment-243748180.
339 func stackOffset(a *obj.Addr, stacksize int64) {
340         switch a.Name {
341         case obj.NAME_AUTO:
342                 // Adjust to the top of AUTOs.
343                 a.Offset += stacksize
344         case obj.NAME_PARAM:
345                 // Adjust to the bottom of PARAMs.
346                 a.Offset += stacksize + 8
347         }
348 }
349
350 // preprocess generates prologue and epilogue code, computes PC-relative branch
351 // and jump offsets, and resolves pseudo-registers.
352 //
353 // preprocess is called once per linker symbol.
354 //
355 // When preprocess finishes, all instructions in the symbol are either
356 // concrete, real RISC-V instructions or directive pseudo-ops like TEXT,
357 // PCDATA, and FUNCDATA.
358 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
359         if cursym.Func().Text == nil || cursym.Func().Text.Link == nil {
360                 return
361         }
362
363         // Generate the prologue.
364         text := cursym.Func().Text
365         if text.As != obj.ATEXT {
366                 ctxt.Diag("preprocess: found symbol that does not start with TEXT directive")
367                 return
368         }
369
370         stacksize := text.To.Offset
371         if stacksize == -8 {
372                 // Historical way to mark NOFRAME.
373                 text.From.Sym.Set(obj.AttrNoFrame, true)
374                 stacksize = 0
375         }
376         if stacksize < 0 {
377                 ctxt.Diag("negative frame size %d - did you mean NOFRAME?", stacksize)
378         }
379         if text.From.Sym.NoFrame() {
380                 if stacksize != 0 {
381                         ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", stacksize)
382                 }
383         }
384
385         if !containsCall(cursym) {
386                 text.From.Sym.Set(obj.AttrLeaf, true)
387                 if stacksize == 0 {
388                         // A leaf function with no locals has no frame.
389                         text.From.Sym.Set(obj.AttrNoFrame, true)
390                 }
391         }
392
393         // Save LR unless there is no frame.
394         if !text.From.Sym.NoFrame() {
395                 stacksize += ctxt.Arch.FixedFrameSize
396         }
397
398         cursym.Func().Args = text.To.Val.(int32)
399         cursym.Func().Locals = int32(stacksize)
400
401         prologue := text
402
403         if !cursym.Func().Text.From.Sym.NoSplit() {
404                 prologue = stacksplit(ctxt, prologue, cursym, newprog, stacksize) // emit split check
405         }
406
407         if stacksize != 0 {
408                 prologue = ctxt.StartUnsafePoint(prologue, newprog)
409
410                 // Actually save LR.
411                 prologue = obj.Appendp(prologue, newprog)
412                 prologue.As = AMOV
413                 prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
414                 prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -stacksize}
415
416                 // Insert stack adjustment.
417                 prologue = obj.Appendp(prologue, newprog)
418                 prologue.As = AADDI
419                 prologue.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -stacksize}
420                 prologue.Reg = REG_SP
421                 prologue.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
422                 prologue.Spadj = int32(stacksize)
423
424                 prologue = ctxt.EndUnsafePoint(prologue, newprog, -1)
425
426                 // On Linux, in a cgo binary we may get a SIGSETXID signal early on
427                 // before the signal stack is set, as glibc doesn't allow us to block
428                 // SIGSETXID. So a signal may land on the current stack and clobber
429                 // the content below the SP. We store the LR again after the SP is
430                 // decremented.
431                 prologue = obj.Appendp(prologue, newprog)
432                 prologue.As = AMOV
433                 prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
434                 prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
435         }
436
437         if cursym.Func().Text.From.Sym.Wrapper() {
438                 // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
439                 //
440                 //   MOV g_panic(g), X5
441                 //   BNE X5, ZERO, adjust
442                 // end:
443                 //   NOP
444                 // ...rest of function..
445                 // adjust:
446                 //   MOV panic_argp(X5), X6
447                 //   ADD $(autosize+FIXED_FRAME), SP, X7
448                 //   BNE X6, X7, end
449                 //   ADD $FIXED_FRAME, SP, X6
450                 //   MOV X6, panic_argp(X5)
451                 //   JMP end
452                 //
453                 // The NOP is needed to give the jumps somewhere to land.
454
455                 ldpanic := obj.Appendp(prologue, newprog)
456
457                 ldpanic.As = AMOV
458                 ldpanic.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGG, Offset: 4 * int64(ctxt.Arch.PtrSize)} // G.panic
459                 ldpanic.Reg = obj.REG_NONE
460                 ldpanic.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
461
462                 bneadj := obj.Appendp(ldpanic, newprog)
463                 bneadj.As = ABNE
464                 bneadj.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
465                 bneadj.Reg = REG_ZERO
466                 bneadj.To.Type = obj.TYPE_BRANCH
467
468                 endadj := obj.Appendp(bneadj, newprog)
469                 endadj.As = obj.ANOP
470
471                 last := endadj
472                 for last.Link != nil {
473                         last = last.Link
474                 }
475
476                 getargp := obj.Appendp(last, newprog)
477                 getargp.As = AMOV
478                 getargp.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
479                 getargp.Reg = obj.REG_NONE
480                 getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
481
482                 bneadj.To.SetTarget(getargp)
483
484                 calcargp := obj.Appendp(getargp, newprog)
485                 calcargp.As = AADDI
486                 calcargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize + ctxt.Arch.FixedFrameSize}
487                 calcargp.Reg = REG_SP
488                 calcargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X7}
489
490                 testargp := obj.Appendp(calcargp, newprog)
491                 testargp.As = ABNE
492                 testargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
493                 testargp.Reg = REG_X7
494                 testargp.To.Type = obj.TYPE_BRANCH
495                 testargp.To.SetTarget(endadj)
496
497                 adjargp := obj.Appendp(testargp, newprog)
498                 adjargp.As = AADDI
499                 adjargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(ctxt.Arch.PtrSize)}
500                 adjargp.Reg = REG_SP
501                 adjargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
502
503                 setargp := obj.Appendp(adjargp, newprog)
504                 setargp.As = AMOV
505                 setargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
506                 setargp.Reg = obj.REG_NONE
507                 setargp.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
508
509                 godone := obj.Appendp(setargp, newprog)
510                 godone.As = AJAL
511                 godone.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
512                 godone.To.Type = obj.TYPE_BRANCH
513                 godone.To.SetTarget(endadj)
514         }
515
516         // Update stack-based offsets.
517         for p := cursym.Func().Text; p != nil; p = p.Link {
518                 stackOffset(&p.From, stacksize)
519                 stackOffset(&p.To, stacksize)
520         }
521
522         // Additional instruction rewriting.
523         for p := cursym.Func().Text; p != nil; p = p.Link {
524                 switch p.As {
525                 case obj.AGETCALLERPC:
526                         if cursym.Leaf() {
527                                 // MOV LR, Rd
528                                 p.As = AMOV
529                                 p.From.Type = obj.TYPE_REG
530                                 p.From.Reg = REG_LR
531                         } else {
532                                 // MOV (RSP), Rd
533                                 p.As = AMOV
534                                 p.From.Type = obj.TYPE_MEM
535                                 p.From.Reg = REG_SP
536                         }
537
538                 case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
539                         switch p.To.Type {
540                         case obj.TYPE_MEM:
541                                 jalToSym(ctxt, p, REG_LR)
542                         }
543
544                 case obj.AJMP:
545                         switch p.To.Type {
546                         case obj.TYPE_MEM:
547                                 switch p.To.Name {
548                                 case obj.NAME_EXTERN, obj.NAME_STATIC:
549                                         jalToSym(ctxt, p, REG_ZERO)
550                                 }
551                         }
552
553                 case obj.ARET:
554                         // Replace RET with epilogue.
555                         retJMP := p.To.Sym
556
557                         if stacksize != 0 {
558                                 // Restore LR.
559                                 p.As = AMOV
560                                 p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
561                                 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
562                                 p = obj.Appendp(p, newprog)
563
564                                 p.As = AADDI
565                                 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize}
566                                 p.Reg = REG_SP
567                                 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
568                                 p.Spadj = int32(-stacksize)
569                                 p = obj.Appendp(p, newprog)
570                         }
571
572                         if retJMP != nil {
573                                 p.As = obj.ARET
574                                 p.To.Sym = retJMP
575                                 jalToSym(ctxt, p, REG_ZERO)
576                         } else {
577                                 p.As = AJALR
578                                 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
579                                 p.Reg = obj.REG_NONE
580                                 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
581                         }
582
583                         // "Add back" the stack removed in the previous instruction.
584                         //
585                         // This is to avoid confusing pctospadj, which sums
586                         // Spadj from function entry to each PC, and shouldn't
587                         // count adjustments from earlier epilogues, since they
588                         // won't affect later PCs.
589                         p.Spadj = int32(stacksize)
590
591                 case AADDI:
592                         // Refine Spadjs account for adjustment via ADDI instruction.
593                         if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SP && p.From.Type == obj.TYPE_CONST {
594                                 p.Spadj = int32(-p.From.Offset)
595                         }
596                 }
597
598                 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
599                         f := cursym.Func()
600                         if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
601                                 f.FuncFlag |= abi.FuncFlagSPWrite
602                                 if ctxt.Debugvlog || !ctxt.IsAsm {
603                                         ctxt.Logf("auto-SPWRITE: %s %v\n", cursym.Name, p)
604                                         if !ctxt.IsAsm {
605                                                 ctxt.Diag("invalid auto-SPWRITE in non-assembly")
606                                                 ctxt.DiagFlush()
607                                                 log.Fatalf("bad SPWRITE")
608                                         }
609                                 }
610                         }
611                 }
612         }
613
614         var callCount int
615         for p := cursym.Func().Text; p != nil; p = p.Link {
616                 markRelocs(p)
617                 if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
618                         callCount++
619                 }
620         }
621         const callTrampSize = 8 // 2 machine instructions.
622         maxTrampSize := int64(callCount * callTrampSize)
623
624         // Compute instruction addresses.  Once we do that, we need to check for
625         // overextended jumps and branches.  Within each iteration, Pc differences
626         // are always lower bounds (since the program gets monotonically longer,
627         // a fixed point will be reached).  No attempt to handle functions > 2GiB.
628         for {
629                 big, rescan := false, false
630                 maxPC := setPCs(cursym.Func().Text, 0)
631                 if maxPC+maxTrampSize > (1 << 20) {
632                         big = true
633                 }
634
635                 for p := cursym.Func().Text; p != nil; p = p.Link {
636                         switch p.As {
637                         case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
638                                 if p.To.Type != obj.TYPE_BRANCH {
639                                         panic("assemble: instruction with branch-like opcode lacks destination")
640                                 }
641                                 offset := p.To.Target().Pc - p.Pc
642                                 if offset < -4096 || 4096 <= offset {
643                                         // Branch is long.  Replace it with a jump.
644                                         jmp := obj.Appendp(p, newprog)
645                                         jmp.As = AJAL
646                                         jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
647                                         jmp.To = obj.Addr{Type: obj.TYPE_BRANCH}
648                                         jmp.To.SetTarget(p.To.Target())
649
650                                         p.As = InvertBranch(p.As)
651                                         p.To.SetTarget(jmp.Link)
652
653                                         // We may have made previous branches too long,
654                                         // so recheck them.
655                                         rescan = true
656                                 }
657                         case AJAL:
658                                 // Linker will handle the intersymbol case and trampolines.
659                                 if p.To.Target() == nil {
660                                         if !big {
661                                                 break
662                                         }
663                                         // This function is going to be too large for JALs
664                                         // to reach trampolines. Replace with AUIPC+JALR.
665                                         jmp := obj.Appendp(p, newprog)
666                                         jmp.As = AJALR
667                                         jmp.From = p.From
668                                         jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
669
670                                         p.As = AAUIPC
671                                         p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC
672                                         p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym})
673                                         p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
674                                         p.Reg = obj.REG_NONE
675                                         p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
676
677                                         rescan = true
678                                         break
679                                 }
680                                 offset := p.To.Target().Pc - p.Pc
681                                 if offset < -(1<<20) || (1<<20) <= offset {
682                                         // Replace with 2-instruction sequence. This assumes
683                                         // that TMP is not live across J instructions, since
684                                         // it is reserved by SSA.
685                                         jmp := obj.Appendp(p, newprog)
686                                         jmp.As = AJALR
687                                         jmp.From = p.From
688                                         jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
689
690                                         // p.From is not generally valid, however will be
691                                         // fixed up in the next loop.
692                                         p.As = AAUIPC
693                                         p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym}
694                                         p.From.SetTarget(p.To.Target())
695                                         p.Reg = obj.REG_NONE
696                                         p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
697
698                                         rescan = true
699                                 }
700                         }
701                 }
702
703                 if !rescan {
704                         break
705                 }
706         }
707
708         // Now that there are no long branches, resolve branch and jump targets.
709         // At this point, instruction rewriting which changes the number of
710         // instructions will break everything--don't do it!
711         for p := cursym.Func().Text; p != nil; p = p.Link {
712                 switch p.As {
713                 case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
714                         switch p.To.Type {
715                         case obj.TYPE_BRANCH:
716                                 p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
717                         case obj.TYPE_MEM:
718                                 panic("unhandled type")
719                         }
720
721                 case AJAL:
722                         // Linker will handle the intersymbol case and trampolines.
723                         if p.To.Target() != nil {
724                                 p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
725                         }
726
727                 case AAUIPC:
728                         if p.From.Type == obj.TYPE_BRANCH {
729                                 low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc)
730                                 if err != nil {
731                                         ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
732                                 }
733                                 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
734                                 p.Link.To.Offset = low
735                         }
736                 }
737         }
738
739         // Validate all instructions - this provides nice error messages.
740         for p := cursym.Func().Text; p != nil; p = p.Link {
741                 for _, ins := range instructionsForProg(p) {
742                         ins.validate(ctxt)
743                 }
744         }
745 }
746
747 func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgAlloc, framesize int64) *obj.Prog {
748         // Leaf function with no frame is effectively NOSPLIT.
749         if framesize == 0 {
750                 return p
751         }
752
753         if ctxt.Flag_maymorestack != "" {
754                 // Save LR and REGCTXT
755                 const frameSize = 16
756                 p = ctxt.StartUnsafePoint(p, newprog)
757
758                 // Spill Arguments. This has to happen before we open
759                 // any more frame space.
760                 p = cursym.Func().SpillRegisterArgs(p, newprog)
761
762                 // MOV LR, -16(SP)
763                 p = obj.Appendp(p, newprog)
764                 p.As = AMOV
765                 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
766                 p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize}
767                 // ADDI $-16, SP
768                 p = obj.Appendp(p, newprog)
769                 p.As = AADDI
770                 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize}
771                 p.Reg = REG_SP
772                 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
773                 p.Spadj = frameSize
774                 // MOV REGCTXT, 8(SP)
775                 p = obj.Appendp(p, newprog)
776                 p.As = AMOV
777                 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
778                 p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
779
780                 // CALL maymorestack
781                 p = obj.Appendp(p, newprog)
782                 p.As = obj.ACALL
783                 p.To.Type = obj.TYPE_BRANCH
784                 // See ../x86/obj6.go
785                 p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI())
786                 jalToSym(ctxt, p, REG_X5)
787
788                 // Restore LR and REGCTXT
789
790                 // MOV 8(SP), REGCTXT
791                 p = obj.Appendp(p, newprog)
792                 p.As = AMOV
793                 p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
794                 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
795                 // MOV (SP), LR
796                 p = obj.Appendp(p, newprog)
797                 p.As = AMOV
798                 p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
799                 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
800                 // ADDI $16, SP
801                 p = obj.Appendp(p, newprog)
802                 p.As = AADDI
803                 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize}
804                 p.Reg = REG_SP
805                 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
806                 p.Spadj = -frameSize
807
808                 // Unspill arguments
809                 p = cursym.Func().UnspillRegisterArgs(p, newprog)
810                 p = ctxt.EndUnsafePoint(p, newprog, -1)
811         }
812
813         // Jump back to here after morestack returns.
814         startPred := p
815
816         // MOV  g_stackguard(g), X6
817         p = obj.Appendp(p, newprog)
818         p.As = AMOV
819         p.From.Type = obj.TYPE_MEM
820         p.From.Reg = REGG
821         p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
822         if cursym.CFunc() {
823                 p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
824         }
825         p.To.Type = obj.TYPE_REG
826         p.To.Reg = REG_X6
827
828         // Mark the stack bound check and morestack call async nonpreemptible.
829         // If we get preempted here, when resumed the preemption request is
830         // cleared, but we'll still call morestack, which will double the stack
831         // unnecessarily. See issue #35470.
832         p = ctxt.StartUnsafePoint(p, newprog)
833
834         var to_done, to_more *obj.Prog
835
836         if framesize <= abi.StackSmall {
837                 // small stack
838                 //      // if SP > stackguard { goto done }
839                 //      BLTU    stackguard, SP, done
840                 p = obj.Appendp(p, newprog)
841                 p.As = ABLTU
842                 p.From.Type = obj.TYPE_REG
843                 p.From.Reg = REG_X6
844                 p.Reg = REG_SP
845                 p.To.Type = obj.TYPE_BRANCH
846                 to_done = p
847         } else {
848                 // large stack: SP-framesize < stackguard-StackSmall
849                 offset := int64(framesize) - abi.StackSmall
850                 if framesize > abi.StackBig {
851                         // Such a large stack we need to protect against underflow.
852                         // The runtime guarantees SP > objabi.StackBig, but
853                         // framesize is large enough that SP-framesize may
854                         // underflow, causing a direct comparison with the
855                         // stack guard to incorrectly succeed. We explicitly
856                         // guard against underflow.
857                         //
858                         //      MOV     $(framesize-StackSmall), X7
859                         //      BLTU    SP, X7, label-of-call-to-morestack
860
861                         p = obj.Appendp(p, newprog)
862                         p.As = AMOV
863                         p.From.Type = obj.TYPE_CONST
864                         p.From.Offset = offset
865                         p.To.Type = obj.TYPE_REG
866                         p.To.Reg = REG_X7
867
868                         p = obj.Appendp(p, newprog)
869                         p.As = ABLTU
870                         p.From.Type = obj.TYPE_REG
871                         p.From.Reg = REG_SP
872                         p.Reg = REG_X7
873                         p.To.Type = obj.TYPE_BRANCH
874                         to_more = p
875                 }
876
877                 // Check against the stack guard. We've ensured this won't underflow.
878                 //      ADD     $-(framesize-StackSmall), SP, X7
879                 //      // if X7 > stackguard { goto done }
880                 //      BLTU    stackguard, X7, done
881                 p = obj.Appendp(p, newprog)
882                 p.As = AADDI
883                 p.From.Type = obj.TYPE_CONST
884                 p.From.Offset = -offset
885                 p.Reg = REG_SP
886                 p.To.Type = obj.TYPE_REG
887                 p.To.Reg = REG_X7
888
889                 p = obj.Appendp(p, newprog)
890                 p.As = ABLTU
891                 p.From.Type = obj.TYPE_REG
892                 p.From.Reg = REG_X6
893                 p.Reg = REG_X7
894                 p.To.Type = obj.TYPE_BRANCH
895                 to_done = p
896         }
897
898         // Spill the register args that could be clobbered by the
899         // morestack code
900         p = ctxt.EmitEntryStackMap(cursym, p, newprog)
901         p = cursym.Func().SpillRegisterArgs(p, newprog)
902
903         // CALL runtime.morestack(SB)
904         p = obj.Appendp(p, newprog)
905         p.As = obj.ACALL
906         p.To.Type = obj.TYPE_BRANCH
907
908         if cursym.CFunc() {
909                 p.To.Sym = ctxt.Lookup("runtime.morestackc")
910         } else if !cursym.Func().Text.From.Sym.NeedCtxt() {
911                 p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt")
912         } else {
913                 p.To.Sym = ctxt.Lookup("runtime.morestack")
914         }
915         if to_more != nil {
916                 to_more.To.SetTarget(p)
917         }
918         jalToSym(ctxt, p, REG_X5)
919
920         // The instructions which unspill regs should be preemptible.
921         p = ctxt.EndUnsafePoint(p, newprog, -1)
922         p = cursym.Func().UnspillRegisterArgs(p, newprog)
923
924         // JMP start
925         p = obj.Appendp(p, newprog)
926         p.As = AJAL
927         p.To = obj.Addr{Type: obj.TYPE_BRANCH}
928         p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
929         p.To.SetTarget(startPred.Link)
930
931         // placeholder for to_done's jump target
932         p = obj.Appendp(p, newprog)
933         p.As = obj.ANOP // zero-width place holder
934         to_done.To.SetTarget(p)
935
936         return p
937 }
938
939 // signExtend sign extends val starting at bit bit.
940 func signExtend(val int64, bit uint) int64 {
941         return val << (64 - bit) >> (64 - bit)
942 }
943
944 // Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
945 // upper immediate and a signed 12-bit lower immediate to be added to the upper
946 // result. For example, high may be used in LUI and low in a following ADDI to
947 // generate a full 32-bit constant.
948 func Split32BitImmediate(imm int64) (low, high int64, err error) {
949         if err := immIFits(imm, 32); err != nil {
950                 return 0, 0, err
951         }
952
953         // Nothing special needs to be done if the immediate fits in 12 bits.
954         if err := immIFits(imm, 12); err == nil {
955                 return imm, 0, nil
956         }
957
958         high = imm >> 12
959
960         // The bottom 12 bits will be treated as signed.
961         //
962         // If that will result in a negative 12 bit number, add 1 to
963         // our upper bits to adjust for the borrow.
964         //
965         // It is not possible for this increment to overflow. To
966         // overflow, the 20 top bits would be 1, and the sign bit for
967         // the low 12 bits would be set, in which case the entire 32
968         // bit pattern fits in a 12 bit signed value.
969         if imm&(1<<11) != 0 {
970                 high++
971         }
972
973         low = signExtend(imm, 12)
974         high = signExtend(high, 20)
975
976         return low, high, nil
977 }
978
979 func regVal(r, min, max uint32) uint32 {
980         if r < min || r > max {
981                 panic(fmt.Sprintf("register out of range, want %d <= %d <= %d", min, r, max))
982         }
983         return r - min
984 }
985
986 // regI returns an integer register.
987 func regI(r uint32) uint32 {
988         return regVal(r, REG_X0, REG_X31)
989 }
990
991 // regF returns a float register.
992 func regF(r uint32) uint32 {
993         return regVal(r, REG_F0, REG_F31)
994 }
995
996 // regAddr extracts a register from an Addr.
997 func regAddr(a obj.Addr, min, max uint32) uint32 {
998         if a.Type != obj.TYPE_REG {
999                 panic(fmt.Sprintf("ill typed: %+v", a))
1000         }
1001         return regVal(uint32(a.Reg), min, max)
1002 }
1003
1004 // regIAddr extracts the integer register from an Addr.
1005 func regIAddr(a obj.Addr) uint32 {
1006         return regAddr(a, REG_X0, REG_X31)
1007 }
1008
1009 // regFAddr extracts the float register from an Addr.
1010 func regFAddr(a obj.Addr) uint32 {
1011         return regAddr(a, REG_F0, REG_F31)
1012 }
1013
1014 // immEven checks that the immediate is a multiple of two. If it
1015 // is not, an error is returned.
1016 func immEven(x int64) error {
1017         if x&1 != 0 {
1018                 return fmt.Errorf("immediate %#x is not a multiple of two", x)
1019         }
1020         return nil
1021 }
1022
1023 // immIFits checks whether the immediate value x fits in nbits bits
1024 // as a signed integer. If it does not, an error is returned.
1025 func immIFits(x int64, nbits uint) error {
1026         nbits--
1027         min := int64(-1) << nbits
1028         max := int64(1)<<nbits - 1
1029         if x < min || x > max {
1030                 if nbits <= 16 {
1031                         return fmt.Errorf("signed immediate %d must be in range [%d, %d] (%d bits)", x, min, max, nbits)
1032                 }
1033                 return fmt.Errorf("signed immediate %#x must be in range [%#x, %#x] (%d bits)", x, min, max, nbits)
1034         }
1035         return nil
1036 }
1037
1038 // immI extracts the signed integer of the specified size from an immediate.
1039 func immI(as obj.As, imm int64, nbits uint) uint32 {
1040         if err := immIFits(imm, nbits); err != nil {
1041                 panic(fmt.Sprintf("%v: %v", as, err))
1042         }
1043         return uint32(imm)
1044 }
1045
1046 func wantImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
1047         if err := immIFits(imm, nbits); err != nil {
1048                 ctxt.Diag("%v: %v", ins, err)
1049         }
1050 }
1051
1052 func wantReg(ctxt *obj.Link, ins *instruction, 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: expected %s register in %s position%s", ins, descr, pos, suffix)
1059         }
1060 }
1061
1062 func wantNoneReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1063         if r != obj.REG_NONE {
1064                 ctxt.Diag("%v: expected no register in %s but got register %s", ins, pos, RegName(int(r)))
1065         }
1066 }
1067
1068 // wantIntReg checks that r is an integer register.
1069 func wantIntReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1070         wantReg(ctxt, ins, pos, "integer", r, REG_X0, REG_X31)
1071 }
1072
1073 // wantFloatReg checks that r is a floating-point register.
1074 func wantFloatReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1075         wantReg(ctxt, ins, pos, "float", r, REG_F0, REG_F31)
1076 }
1077
1078 // wantEvenOffset checks that the offset is a multiple of two.
1079 func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) {
1080         if err := immEven(offset); err != nil {
1081                 ctxt.Diag("%v: %v", ins, err)
1082         }
1083 }
1084
1085 func validateRIII(ctxt *obj.Link, ins *instruction) {
1086         wantIntReg(ctxt, ins, "rd", ins.rd)
1087         wantIntReg(ctxt, ins, "rs1", ins.rs1)
1088         wantIntReg(ctxt, ins, "rs2", ins.rs2)
1089         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1090 }
1091
1092 func validateRFFF(ctxt *obj.Link, ins *instruction) {
1093         wantFloatReg(ctxt, ins, "rd", ins.rd)
1094         wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1095         wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1096         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1097 }
1098
1099 func validateRFFFF(ctxt *obj.Link, ins *instruction) {
1100         wantFloatReg(ctxt, ins, "rd", ins.rd)
1101         wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1102         wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1103         wantFloatReg(ctxt, ins, "rs3", ins.rs3)
1104 }
1105
1106 func validateRFFI(ctxt *obj.Link, ins *instruction) {
1107         wantIntReg(ctxt, ins, "rd", ins.rd)
1108         wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1109         wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1110         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1111 }
1112
1113 func validateRFI(ctxt *obj.Link, ins *instruction) {
1114         wantIntReg(ctxt, ins, "rd", ins.rd)
1115         wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1116         wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1117         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1118 }
1119
1120 func validateRIF(ctxt *obj.Link, ins *instruction) {
1121         wantFloatReg(ctxt, ins, "rd", ins.rd)
1122         wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1123         wantIntReg(ctxt, ins, "rs2", ins.rs2)
1124         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1125 }
1126
1127 func validateRFF(ctxt *obj.Link, ins *instruction) {
1128         wantFloatReg(ctxt, ins, "rd", ins.rd)
1129         wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1130         wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1131         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1132 }
1133
1134 func validateII(ctxt *obj.Link, ins *instruction) {
1135         wantImmI(ctxt, ins, ins.imm, 12)
1136         wantIntReg(ctxt, ins, "rd", ins.rd)
1137         wantIntReg(ctxt, ins, "rs1", ins.rs1)
1138         wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1139         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1140 }
1141
1142 func validateIF(ctxt *obj.Link, ins *instruction) {
1143         wantImmI(ctxt, ins, ins.imm, 12)
1144         wantFloatReg(ctxt, ins, "rd", ins.rd)
1145         wantIntReg(ctxt, ins, "rs1", ins.rs1)
1146         wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1147         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1148 }
1149
1150 func validateSI(ctxt *obj.Link, ins *instruction) {
1151         wantImmI(ctxt, ins, ins.imm, 12)
1152         wantIntReg(ctxt, ins, "rd", ins.rd)
1153         wantIntReg(ctxt, ins, "rs1", ins.rs1)
1154         wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1155         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1156 }
1157
1158 func validateSF(ctxt *obj.Link, ins *instruction) {
1159         wantImmI(ctxt, ins, ins.imm, 12)
1160         wantIntReg(ctxt, ins, "rd", ins.rd)
1161         wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1162         wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1163         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1164 }
1165
1166 func validateB(ctxt *obj.Link, ins *instruction) {
1167         // Offsets are multiples of two, so accept 13 bit immediates for the
1168         // 12 bit slot. We implicitly drop the least significant bit in encodeB.
1169         wantEvenOffset(ctxt, ins, ins.imm)
1170         wantImmI(ctxt, ins, ins.imm, 13)
1171         wantNoneReg(ctxt, ins, "rd", ins.rd)
1172         wantIntReg(ctxt, ins, "rs1", ins.rs1)
1173         wantIntReg(ctxt, ins, "rs2", ins.rs2)
1174         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1175 }
1176
1177 func validateU(ctxt *obj.Link, ins *instruction) {
1178         wantImmI(ctxt, ins, ins.imm, 20)
1179         wantIntReg(ctxt, ins, "rd", ins.rd)
1180         wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1181         wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1182         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1183 }
1184
1185 func validateJ(ctxt *obj.Link, ins *instruction) {
1186         // Offsets are multiples of two, so accept 21 bit immediates for the
1187         // 20 bit slot. We implicitly drop the least significant bit in encodeJ.
1188         wantEvenOffset(ctxt, ins, ins.imm)
1189         wantImmI(ctxt, ins, ins.imm, 21)
1190         wantIntReg(ctxt, ins, "rd", ins.rd)
1191         wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1192         wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1193         wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1194 }
1195
1196 func validateRaw(ctxt *obj.Link, ins *instruction) {
1197         // Treat the raw value specially as a 32-bit unsigned integer.
1198         // Nobody wants to enter negative machine code.
1199         if ins.imm < 0 || 1<<32 <= ins.imm {
1200                 ctxt.Diag("%v: immediate %d in raw position cannot be larger than 32 bits", ins.as, ins.imm)
1201         }
1202 }
1203
1204 // extractBitAndShift extracts the specified bit from the given immediate,
1205 // before shifting it to the requested position and returning it.
1206 func extractBitAndShift(imm uint32, bit, pos int) uint32 {
1207         return ((imm >> bit) & 1) << pos
1208 }
1209
1210 // encodeR encodes an R-type RISC-V instruction.
1211 func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
1212         enc := encode(as)
1213         if enc == nil {
1214                 panic("encodeR: could not encode instruction")
1215         }
1216         if enc.rs2 != 0 && rs2 != 0 {
1217                 panic("encodeR: instruction uses rs2, but rs2 was nonzero")
1218         }
1219         return funct7<<25 | enc.funct7<<25 | enc.rs2<<20 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
1220 }
1221
1222 // encodeR4 encodes an R4-type RISC-V instruction.
1223 func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
1224         enc := encode(as)
1225         if enc == nil {
1226                 panic("encodeR4: could not encode instruction")
1227         }
1228         if enc.rs2 != 0 {
1229                 panic("encodeR4: instruction uses rs2")
1230         }
1231         funct2 |= enc.funct7
1232         if funct2&^3 != 0 {
1233                 panic("encodeR4: funct2 requires more than 2 bits")
1234         }
1235         return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
1236 }
1237
1238 func encodeRIII(ins *instruction) uint32 {
1239         return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1240 }
1241
1242 func encodeRFFF(ins *instruction) uint32 {
1243         return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
1244 }
1245
1246 func encodeRFFFF(ins *instruction) uint32 {
1247         return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7)
1248 }
1249
1250 func encodeRFFI(ins *instruction) uint32 {
1251         return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1252 }
1253
1254 func encodeRFI(ins *instruction) uint32 {
1255         return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
1256 }
1257
1258 func encodeRIF(ins *instruction) uint32 {
1259         return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
1260 }
1261
1262 func encodeRFF(ins *instruction) uint32 {
1263         return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
1264 }
1265
1266 // encodeI encodes an I-type RISC-V instruction.
1267 func encodeI(as obj.As, rs1, rd, imm uint32) uint32 {
1268         enc := encode(as)
1269         if enc == nil {
1270                 panic("encodeI: could not encode instruction")
1271         }
1272         imm |= uint32(enc.csr)
1273         return imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
1274 }
1275
1276 func encodeII(ins *instruction) uint32 {
1277         return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm))
1278 }
1279
1280 func encodeIF(ins *instruction) uint32 {
1281         return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm))
1282 }
1283
1284 // encodeS encodes an S-type RISC-V instruction.
1285 func encodeS(as obj.As, rs1, rs2, imm uint32) uint32 {
1286         enc := encode(as)
1287         if enc == nil {
1288                 panic("encodeS: could not encode instruction")
1289         }
1290         return (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
1291 }
1292
1293 func encodeSI(ins *instruction) uint32 {
1294         return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm))
1295 }
1296
1297 func encodeSF(ins *instruction) uint32 {
1298         return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm))
1299 }
1300
1301 // encodeBImmediate encodes an immediate for a B-type RISC-V instruction.
1302 func encodeBImmediate(imm uint32) uint32 {
1303         return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
1304 }
1305
1306 // encodeB encodes a B-type RISC-V instruction.
1307 func encodeB(ins *instruction) uint32 {
1308         imm := immI(ins.as, ins.imm, 13)
1309         rs2 := regI(ins.rs1)
1310         rs1 := regI(ins.rs2)
1311         enc := encode(ins.as)
1312         if enc == nil {
1313                 panic("encodeB: could not encode instruction")
1314         }
1315         return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
1316 }
1317
1318 // encodeU encodes a U-type RISC-V instruction.
1319 func encodeU(ins *instruction) uint32 {
1320         // The immediates for encodeU are the upper 20 bits of a 32 bit value.
1321         // Rather than have the user/compiler generate a 32 bit constant, the
1322         // bottommost bits of which must all be zero, instead accept just the
1323         // top bits.
1324         imm := immI(ins.as, ins.imm, 20)
1325         rd := regI(ins.rd)
1326         enc := encode(ins.as)
1327         if enc == nil {
1328                 panic("encodeU: could not encode instruction")
1329         }
1330         return imm<<12 | rd<<7 | enc.opcode
1331 }
1332
1333 // encodeJImmediate encodes an immediate for a J-type RISC-V instruction.
1334 func encodeJImmediate(imm uint32) uint32 {
1335         return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12
1336 }
1337
1338 // encodeJ encodes a J-type RISC-V instruction.
1339 func encodeJ(ins *instruction) uint32 {
1340         imm := immI(ins.as, ins.imm, 21)
1341         rd := regI(ins.rd)
1342         enc := encode(ins.as)
1343         if enc == nil {
1344                 panic("encodeJ: could not encode instruction")
1345         }
1346         return encodeJImmediate(imm) | rd<<7 | enc.opcode
1347 }
1348
1349 // encodeCBImmediate encodes an immediate for a CB-type RISC-V instruction.
1350 func encodeCBImmediate(imm uint32) uint32 {
1351         // Bit order - [8|4:3|7:6|2:1|5]
1352         bits := extractBitAndShift(imm, 8, 7)
1353         bits |= extractBitAndShift(imm, 4, 6)
1354         bits |= extractBitAndShift(imm, 3, 5)
1355         bits |= extractBitAndShift(imm, 7, 4)
1356         bits |= extractBitAndShift(imm, 6, 3)
1357         bits |= extractBitAndShift(imm, 2, 2)
1358         bits |= extractBitAndShift(imm, 1, 1)
1359         bits |= extractBitAndShift(imm, 5, 0)
1360         return (bits>>5)<<10 | (bits&0x1f)<<2
1361 }
1362
1363 // encodeCJImmediate encodes an immediate for a CJ-type RISC-V instruction.
1364 func encodeCJImmediate(imm uint32) uint32 {
1365         // Bit order - [11|4|9:8|10|6|7|3:1|5]
1366         bits := extractBitAndShift(imm, 11, 10)
1367         bits |= extractBitAndShift(imm, 4, 9)
1368         bits |= extractBitAndShift(imm, 9, 8)
1369         bits |= extractBitAndShift(imm, 8, 7)
1370         bits |= extractBitAndShift(imm, 10, 6)
1371         bits |= extractBitAndShift(imm, 6, 5)
1372         bits |= extractBitAndShift(imm, 7, 4)
1373         bits |= extractBitAndShift(imm, 3, 3)
1374         bits |= extractBitAndShift(imm, 2, 2)
1375         bits |= extractBitAndShift(imm, 1, 1)
1376         bits |= extractBitAndShift(imm, 5, 0)
1377         return bits << 2
1378 }
1379
1380 func encodeRawIns(ins *instruction) uint32 {
1381         // Treat the raw value specially as a 32-bit unsigned integer.
1382         // Nobody wants to enter negative machine code.
1383         if ins.imm < 0 || 1<<32 <= ins.imm {
1384                 panic(fmt.Sprintf("immediate %d cannot fit in 32 bits", ins.imm))
1385         }
1386         return uint32(ins.imm)
1387 }
1388
1389 func EncodeBImmediate(imm int64) (int64, error) {
1390         if err := immIFits(imm, 13); err != nil {
1391                 return 0, err
1392         }
1393         if err := immEven(imm); err != nil {
1394                 return 0, err
1395         }
1396         return int64(encodeBImmediate(uint32(imm))), nil
1397 }
1398
1399 func EncodeCBImmediate(imm int64) (int64, error) {
1400         if err := immIFits(imm, 9); err != nil {
1401                 return 0, err
1402         }
1403         if err := immEven(imm); err != nil {
1404                 return 0, err
1405         }
1406         return int64(encodeCBImmediate(uint32(imm))), nil
1407 }
1408
1409 func EncodeCJImmediate(imm int64) (int64, error) {
1410         if err := immIFits(imm, 12); err != nil {
1411                 return 0, err
1412         }
1413         if err := immEven(imm); err != nil {
1414                 return 0, err
1415         }
1416         return int64(encodeCJImmediate(uint32(imm))), nil
1417 }
1418
1419 func EncodeIImmediate(imm int64) (int64, error) {
1420         if err := immIFits(imm, 12); err != nil {
1421                 return 0, err
1422         }
1423         return imm << 20, nil
1424 }
1425
1426 func EncodeJImmediate(imm int64) (int64, error) {
1427         if err := immIFits(imm, 21); err != nil {
1428                 return 0, err
1429         }
1430         if err := immEven(imm); err != nil {
1431                 return 0, err
1432         }
1433         return int64(encodeJImmediate(uint32(imm))), nil
1434 }
1435
1436 func EncodeSImmediate(imm int64) (int64, error) {
1437         if err := immIFits(imm, 12); err != nil {
1438                 return 0, err
1439         }
1440         return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
1441 }
1442
1443 func EncodeUImmediate(imm int64) (int64, error) {
1444         if err := immIFits(imm, 20); err != nil {
1445                 return 0, err
1446         }
1447         return imm << 12, nil
1448 }
1449
1450 type encoding struct {
1451         encode   func(*instruction) uint32     // encode returns the machine code for an instruction
1452         validate func(*obj.Link, *instruction) // validate validates an instruction
1453         length   int                           // length of encoded instruction; 0 for pseudo-ops, 4 otherwise
1454 }
1455
1456 var (
1457         // Encodings have the following naming convention:
1458         //
1459         //  1. the instruction encoding (R/I/S/B/U/J), in lowercase
1460         //  2. zero or more register operand identifiers (I = integer
1461         //     register, F = float register), in uppercase
1462         //  3. the word "Encoding"
1463         //
1464         // For example, rIIIEncoding indicates an R-type instruction with two
1465         // integer register inputs and an integer register output; sFEncoding
1466         // indicates an S-type instruction with rs2 being a float register.
1467
1468         rIIIEncoding  = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
1469         rFFFEncoding  = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
1470         rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
1471         rFFIEncoding  = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
1472         rFIEncoding   = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
1473         rIFEncoding   = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
1474         rFFEncoding   = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
1475
1476         iIEncoding = encoding{encode: encodeII, validate: validateII, length: 4}
1477         iFEncoding = encoding{encode: encodeIF, validate: validateIF, length: 4}
1478
1479         sIEncoding = encoding{encode: encodeSI, validate: validateSI, length: 4}
1480         sFEncoding = encoding{encode: encodeSF, validate: validateSF, length: 4}
1481
1482         bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
1483         uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
1484         jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
1485
1486         // rawEncoding encodes a raw instruction byte sequence.
1487         rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
1488
1489         // pseudoOpEncoding panics if encoding is attempted, but does no validation.
1490         pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
1491
1492         // badEncoding is used when an invalid op is encountered.
1493         // An error has already been generated, so let anything else through.
1494         badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
1495 )
1496
1497 // encodings contains the encodings for RISC-V instructions.
1498 // Instructions are masked with obj.AMask to keep indices small.
1499 var encodings = [ALAST & obj.AMask]encoding{
1500
1501         // Unprivileged ISA
1502
1503         // 2.4: Integer Computational Instructions
1504         AADDI & obj.AMask:  iIEncoding,
1505         ASLTI & obj.AMask:  iIEncoding,
1506         ASLTIU & obj.AMask: iIEncoding,
1507         AANDI & obj.AMask:  iIEncoding,
1508         AORI & obj.AMask:   iIEncoding,
1509         AXORI & obj.AMask:  iIEncoding,
1510         ASLLI & obj.AMask:  iIEncoding,
1511         ASRLI & obj.AMask:  iIEncoding,
1512         ASRAI & obj.AMask:  iIEncoding,
1513         ALUI & obj.AMask:   uEncoding,
1514         AAUIPC & obj.AMask: uEncoding,
1515         AADD & obj.AMask:   rIIIEncoding,
1516         ASLT & obj.AMask:   rIIIEncoding,
1517         ASLTU & obj.AMask:  rIIIEncoding,
1518         AAND & obj.AMask:   rIIIEncoding,
1519         AOR & obj.AMask:    rIIIEncoding,
1520         AXOR & obj.AMask:   rIIIEncoding,
1521         ASLL & obj.AMask:   rIIIEncoding,
1522         ASRL & obj.AMask:   rIIIEncoding,
1523         ASUB & obj.AMask:   rIIIEncoding,
1524         ASRA & obj.AMask:   rIIIEncoding,
1525
1526         // 2.5: Control Transfer Instructions
1527         AJAL & obj.AMask:  jEncoding,
1528         AJALR & obj.AMask: iIEncoding,
1529         ABEQ & obj.AMask:  bEncoding,
1530         ABNE & obj.AMask:  bEncoding,
1531         ABLT & obj.AMask:  bEncoding,
1532         ABLTU & obj.AMask: bEncoding,
1533         ABGE & obj.AMask:  bEncoding,
1534         ABGEU & obj.AMask: bEncoding,
1535
1536         // 2.6: Load and Store Instructions
1537         ALW & obj.AMask:  iIEncoding,
1538         ALWU & obj.AMask: iIEncoding,
1539         ALH & obj.AMask:  iIEncoding,
1540         ALHU & obj.AMask: iIEncoding,
1541         ALB & obj.AMask:  iIEncoding,
1542         ALBU & obj.AMask: iIEncoding,
1543         ASW & obj.AMask:  sIEncoding,
1544         ASH & obj.AMask:  sIEncoding,
1545         ASB & obj.AMask:  sIEncoding,
1546
1547         // 2.7: Memory Ordering
1548         AFENCE & obj.AMask: iIEncoding,
1549
1550         // 5.2: Integer Computational Instructions (RV64I)
1551         AADDIW & obj.AMask: iIEncoding,
1552         ASLLIW & obj.AMask: iIEncoding,
1553         ASRLIW & obj.AMask: iIEncoding,
1554         ASRAIW & obj.AMask: iIEncoding,
1555         AADDW & obj.AMask:  rIIIEncoding,
1556         ASLLW & obj.AMask:  rIIIEncoding,
1557         ASRLW & obj.AMask:  rIIIEncoding,
1558         ASUBW & obj.AMask:  rIIIEncoding,
1559         ASRAW & obj.AMask:  rIIIEncoding,
1560
1561         // 5.3: Load and Store Instructions (RV64I)
1562         ALD & obj.AMask: iIEncoding,
1563         ASD & obj.AMask: sIEncoding,
1564
1565         // 7.1: Multiplication Operations
1566         AMUL & obj.AMask:    rIIIEncoding,
1567         AMULH & obj.AMask:   rIIIEncoding,
1568         AMULHU & obj.AMask:  rIIIEncoding,
1569         AMULHSU & obj.AMask: rIIIEncoding,
1570         AMULW & obj.AMask:   rIIIEncoding,
1571         ADIV & obj.AMask:    rIIIEncoding,
1572         ADIVU & obj.AMask:   rIIIEncoding,
1573         AREM & obj.AMask:    rIIIEncoding,
1574         AREMU & obj.AMask:   rIIIEncoding,
1575         ADIVW & obj.AMask:   rIIIEncoding,
1576         ADIVUW & obj.AMask:  rIIIEncoding,
1577         AREMW & obj.AMask:   rIIIEncoding,
1578         AREMUW & obj.AMask:  rIIIEncoding,
1579
1580         // 8.2: Load-Reserved/Store-Conditional
1581         ALRW & obj.AMask: rIIIEncoding,
1582         ALRD & obj.AMask: rIIIEncoding,
1583         ASCW & obj.AMask: rIIIEncoding,
1584         ASCD & obj.AMask: rIIIEncoding,
1585
1586         // 8.3: Atomic Memory Operations
1587         AAMOSWAPW & obj.AMask: rIIIEncoding,
1588         AAMOSWAPD & obj.AMask: rIIIEncoding,
1589         AAMOADDW & obj.AMask:  rIIIEncoding,
1590         AAMOADDD & obj.AMask:  rIIIEncoding,
1591         AAMOANDW & obj.AMask:  rIIIEncoding,
1592         AAMOANDD & obj.AMask:  rIIIEncoding,
1593         AAMOORW & obj.AMask:   rIIIEncoding,
1594         AAMOORD & obj.AMask:   rIIIEncoding,
1595         AAMOXORW & obj.AMask:  rIIIEncoding,
1596         AAMOXORD & obj.AMask:  rIIIEncoding,
1597         AAMOMAXW & obj.AMask:  rIIIEncoding,
1598         AAMOMAXD & obj.AMask:  rIIIEncoding,
1599         AAMOMAXUW & obj.AMask: rIIIEncoding,
1600         AAMOMAXUD & obj.AMask: rIIIEncoding,
1601         AAMOMINW & obj.AMask:  rIIIEncoding,
1602         AAMOMIND & obj.AMask:  rIIIEncoding,
1603         AAMOMINUW & obj.AMask: rIIIEncoding,
1604         AAMOMINUD & obj.AMask: rIIIEncoding,
1605
1606         // 10.1: Base Counters and Timers
1607         ARDCYCLE & obj.AMask:   iIEncoding,
1608         ARDTIME & obj.AMask:    iIEncoding,
1609         ARDINSTRET & obj.AMask: iIEncoding,
1610
1611         // 11.5: Single-Precision Load and Store Instructions
1612         AFLW & obj.AMask: iFEncoding,
1613         AFSW & obj.AMask: sFEncoding,
1614
1615         // 11.6: Single-Precision Floating-Point Computational Instructions
1616         AFADDS & obj.AMask:   rFFFEncoding,
1617         AFSUBS & obj.AMask:   rFFFEncoding,
1618         AFMULS & obj.AMask:   rFFFEncoding,
1619         AFDIVS & obj.AMask:   rFFFEncoding,
1620         AFMINS & obj.AMask:   rFFFEncoding,
1621         AFMAXS & obj.AMask:   rFFFEncoding,
1622         AFSQRTS & obj.AMask:  rFFFEncoding,
1623         AFMADDS & obj.AMask:  rFFFFEncoding,
1624         AFMSUBS & obj.AMask:  rFFFFEncoding,
1625         AFNMSUBS & obj.AMask: rFFFFEncoding,
1626         AFNMADDS & obj.AMask: rFFFFEncoding,
1627
1628         // 11.7: Single-Precision Floating-Point Conversion and Move Instructions
1629         AFCVTWS & obj.AMask:  rFIEncoding,
1630         AFCVTLS & obj.AMask:  rFIEncoding,
1631         AFCVTSW & obj.AMask:  rIFEncoding,
1632         AFCVTSL & obj.AMask:  rIFEncoding,
1633         AFCVTWUS & obj.AMask: rFIEncoding,
1634         AFCVTLUS & obj.AMask: rFIEncoding,
1635         AFCVTSWU & obj.AMask: rIFEncoding,
1636         AFCVTSLU & obj.AMask: rIFEncoding,
1637         AFSGNJS & obj.AMask:  rFFFEncoding,
1638         AFSGNJNS & obj.AMask: rFFFEncoding,
1639         AFSGNJXS & obj.AMask: rFFFEncoding,
1640         AFMVXS & obj.AMask:   rFIEncoding,
1641         AFMVSX & obj.AMask:   rIFEncoding,
1642         AFMVXW & obj.AMask:   rFIEncoding,
1643         AFMVWX & obj.AMask:   rIFEncoding,
1644
1645         // 11.8: Single-Precision Floating-Point Compare Instructions
1646         AFEQS & obj.AMask: rFFIEncoding,
1647         AFLTS & obj.AMask: rFFIEncoding,
1648         AFLES & obj.AMask: rFFIEncoding,
1649
1650         // 11.9: Single-Precision Floating-Point Classify Instruction
1651         AFCLASSS & obj.AMask: rFIEncoding,
1652
1653         // 12.3: Double-Precision Load and Store Instructions
1654         AFLD & obj.AMask: iFEncoding,
1655         AFSD & obj.AMask: sFEncoding,
1656
1657         // 12.4: Double-Precision Floating-Point Computational Instructions
1658         AFADDD & obj.AMask:   rFFFEncoding,
1659         AFSUBD & obj.AMask:   rFFFEncoding,
1660         AFMULD & obj.AMask:   rFFFEncoding,
1661         AFDIVD & obj.AMask:   rFFFEncoding,
1662         AFMIND & obj.AMask:   rFFFEncoding,
1663         AFMAXD & obj.AMask:   rFFFEncoding,
1664         AFSQRTD & obj.AMask:  rFFFEncoding,
1665         AFMADDD & obj.AMask:  rFFFFEncoding,
1666         AFMSUBD & obj.AMask:  rFFFFEncoding,
1667         AFNMSUBD & obj.AMask: rFFFFEncoding,
1668         AFNMADDD & obj.AMask: rFFFFEncoding,
1669
1670         // 12.5: Double-Precision Floating-Point Conversion and Move Instructions
1671         AFCVTWD & obj.AMask:  rFIEncoding,
1672         AFCVTLD & obj.AMask:  rFIEncoding,
1673         AFCVTDW & obj.AMask:  rIFEncoding,
1674         AFCVTDL & obj.AMask:  rIFEncoding,
1675         AFCVTWUD & obj.AMask: rFIEncoding,
1676         AFCVTLUD & obj.AMask: rFIEncoding,
1677         AFCVTDWU & obj.AMask: rIFEncoding,
1678         AFCVTDLU & obj.AMask: rIFEncoding,
1679         AFCVTSD & obj.AMask:  rFFEncoding,
1680         AFCVTDS & obj.AMask:  rFFEncoding,
1681         AFSGNJD & obj.AMask:  rFFFEncoding,
1682         AFSGNJND & obj.AMask: rFFFEncoding,
1683         AFSGNJXD & obj.AMask: rFFFEncoding,
1684         AFMVXD & obj.AMask:   rFIEncoding,
1685         AFMVDX & obj.AMask:   rIFEncoding,
1686
1687         // 12.6: Double-Precision Floating-Point Compare Instructions
1688         AFEQD & obj.AMask: rFFIEncoding,
1689         AFLTD & obj.AMask: rFFIEncoding,
1690         AFLED & obj.AMask: rFFIEncoding,
1691
1692         // 12.7: Double-Precision Floating-Point Classify Instruction
1693         AFCLASSD & obj.AMask: rFIEncoding,
1694
1695         // Privileged ISA
1696
1697         // 3.2.1: Environment Call and Breakpoint
1698         AECALL & obj.AMask:  iIEncoding,
1699         AEBREAK & obj.AMask: iIEncoding,
1700
1701         // Escape hatch
1702         AWORD & obj.AMask: rawEncoding,
1703
1704         // Pseudo-operations
1705         obj.AFUNCDATA: pseudoOpEncoding,
1706         obj.APCDATA:   pseudoOpEncoding,
1707         obj.ATEXT:     pseudoOpEncoding,
1708         obj.ANOP:      pseudoOpEncoding,
1709         obj.ADUFFZERO: pseudoOpEncoding,
1710         obj.ADUFFCOPY: pseudoOpEncoding,
1711 }
1712
1713 // encodingForAs returns the encoding for an obj.As.
1714 func encodingForAs(as obj.As) (encoding, error) {
1715         if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
1716                 return badEncoding, fmt.Errorf("encodingForAs: not a RISC-V instruction %s", as)
1717         }
1718         asi := as & obj.AMask
1719         if int(asi) >= len(encodings) {
1720                 return badEncoding, fmt.Errorf("encodingForAs: bad RISC-V instruction %s", as)
1721         }
1722         enc := encodings[asi]
1723         if enc.validate == nil {
1724                 return badEncoding, fmt.Errorf("encodingForAs: no encoding for instruction %s", as)
1725         }
1726         return enc, nil
1727 }
1728
1729 type instruction struct {
1730         p      *obj.Prog // Prog that instruction is for
1731         as     obj.As    // Assembler opcode
1732         rd     uint32    // Destination register
1733         rs1    uint32    // Source register 1
1734         rs2    uint32    // Source register 2
1735         rs3    uint32    // Source register 3
1736         imm    int64     // Immediate
1737         funct3 uint32    // Function 3
1738         funct7 uint32    // Function 7 (or Function 2)
1739 }
1740
1741 func (ins *instruction) String() string {
1742         if ins.p == nil {
1743                 return ins.as.String()
1744         }
1745         var suffix string
1746         if ins.p.As != ins.as {
1747                 suffix = fmt.Sprintf(" (%v)", ins.as)
1748         }
1749         return fmt.Sprintf("%v%v", ins.p, suffix)
1750 }
1751
1752 func (ins *instruction) encode() (uint32, error) {
1753         enc, err := encodingForAs(ins.as)
1754         if err != nil {
1755                 return 0, err
1756         }
1757         if enc.length <= 0 {
1758                 return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
1759         }
1760         return enc.encode(ins), nil
1761 }
1762
1763 func (ins *instruction) length() int {
1764         enc, err := encodingForAs(ins.as)
1765         if err != nil {
1766                 return 0
1767         }
1768         return enc.length
1769 }
1770
1771 func (ins *instruction) validate(ctxt *obj.Link) {
1772         enc, err := encodingForAs(ins.as)
1773         if err != nil {
1774                 ctxt.Diag(err.Error())
1775                 return
1776         }
1777         enc.validate(ctxt, ins)
1778 }
1779
1780 func (ins *instruction) usesRegTmp() bool {
1781         return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
1782 }
1783
1784 // instructionForProg returns the default *obj.Prog to instruction mapping.
1785 func instructionForProg(p *obj.Prog) *instruction {
1786         ins := &instruction{
1787                 as:  p.As,
1788                 rd:  uint32(p.To.Reg),
1789                 rs1: uint32(p.Reg),
1790                 rs2: uint32(p.From.Reg),
1791                 imm: p.From.Offset,
1792         }
1793         if len(p.RestArgs) == 1 {
1794                 ins.rs3 = uint32(p.RestArgs[0].Reg)
1795         }
1796         return ins
1797 }
1798
1799 // instructionsForOpImmediate returns the machine instructions for an immediate
1800 // operand. The instruction is specified by as and the source register is
1801 // specified by rs, instead of the obj.Prog.
1802 func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
1803         // <opi> $imm, REG, TO
1804         ins := instructionForProg(p)
1805         ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
1806
1807         low, high, err := Split32BitImmediate(ins.imm)
1808         if err != nil {
1809                 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err)
1810                 return nil
1811         }
1812         if high == 0 {
1813                 return []*instruction{ins}
1814         }
1815
1816         // Split into two additions, if possible.
1817         // Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong.
1818         if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
1819                 imm0 := ins.imm / 2
1820                 imm1 := ins.imm - imm0
1821
1822                 // ADDI $(imm/2), REG, TO
1823                 // ADDI $(imm-imm/2), TO, TO
1824                 ins.imm = imm0
1825                 insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
1826                 return []*instruction{ins, insADDI}
1827         }
1828
1829         // LUI $high, TMP
1830         // ADDIW $low, TMP, TMP
1831         // <op> TMP, REG, TO
1832         insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
1833         insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
1834         switch ins.as {
1835         case AADDI:
1836                 ins.as = AADD
1837         case AANDI:
1838                 ins.as = AAND
1839         case AORI:
1840                 ins.as = AOR
1841         case AXORI:
1842                 ins.as = AXOR
1843         default:
1844                 p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
1845                 return nil
1846         }
1847         ins.rs2 = REG_TMP
1848         if low == 0 {
1849                 return []*instruction{insLUI, ins}
1850         }
1851         return []*instruction{insLUI, insADDIW, ins}
1852 }
1853
1854 // instructionsForLoad returns the machine instructions for a load. The load
1855 // instruction is specified by as and the base/source register is specified
1856 // by rs, instead of the obj.Prog.
1857 func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
1858         if p.From.Type != obj.TYPE_MEM {
1859                 p.Ctxt.Diag("%v requires memory for source", p)
1860                 return nil
1861         }
1862
1863         switch as {
1864         case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
1865         default:
1866                 p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
1867                 return nil
1868         }
1869
1870         // <load> $imm, REG, TO (load $imm+(REG), TO)
1871         ins := instructionForProg(p)
1872         ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
1873         ins.imm = p.From.Offset
1874
1875         low, high, err := Split32BitImmediate(ins.imm)
1876         if err != nil {
1877                 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
1878                 return nil
1879         }
1880         if high == 0 {
1881                 return []*instruction{ins}
1882         }
1883
1884         // LUI $high, TMP
1885         // ADD TMP, REG, TMP
1886         // <load> $low, TMP, TO
1887         insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
1888         insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
1889         ins.rs1, ins.imm = REG_TMP, low
1890
1891         return []*instruction{insLUI, insADD, ins}
1892 }
1893
1894 // instructionsForStore returns the machine instructions for a store. The store
1895 // instruction is specified by as and the target/source register is specified
1896 // by rd, instead of the obj.Prog.
1897 func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
1898         if p.To.Type != obj.TYPE_MEM {
1899                 p.Ctxt.Diag("%v requires memory for destination", p)
1900                 return nil
1901         }
1902
1903         switch as {
1904         case ASW, ASH, ASB, ASD, AFSW, AFSD:
1905         default:
1906                 p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
1907                 return nil
1908         }
1909
1910         // <store> $imm, REG, TO (store $imm+(TO), REG)
1911         ins := instructionForProg(p)
1912         ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
1913         ins.imm = p.To.Offset
1914
1915         low, high, err := Split32BitImmediate(ins.imm)
1916         if err != nil {
1917                 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
1918                 return nil
1919         }
1920         if high == 0 {
1921                 return []*instruction{ins}
1922         }
1923
1924         // LUI $high, TMP
1925         // ADD TMP, TO, TMP
1926         // <store> $low, REG, TMP
1927         insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
1928         insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
1929         ins.rd, ins.imm = REG_TMP, low
1930
1931         return []*instruction{insLUI, insADD, ins}
1932 }
1933
1934 func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
1935         insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
1936
1937         var inss []*instruction
1938         if p.Ctxt.Flag_shared {
1939                 // TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
1940                 // register, then load from or store to the resulting memory location.
1941                 insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
1942                 insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
1943                 inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
1944         } else {
1945                 // TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
1946                 // add the thread pointer register, then load from or store to the resulting
1947                 // memory location. Note that this differs from the suggested three
1948                 // instruction sequence, as the Go linker does not currently have an
1949                 // easy way to handle relocation across 12 bytes of machine code.
1950                 insLUI := &instruction{as: ALUI, rd: REG_TMP}
1951                 insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
1952                 inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
1953         }
1954         return inss
1955 }
1956
1957 func instructionsForTLSLoad(p *obj.Prog) []*instruction {
1958         if p.From.Sym.Type != objabi.STLSBSS {
1959                 p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
1960                 return nil
1961         }
1962
1963         ins := instructionForProg(p)
1964         ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
1965
1966         return instructionsForTLS(p, ins)
1967 }
1968
1969 func instructionsForTLSStore(p *obj.Prog) []*instruction {
1970         if p.To.Sym.Type != objabi.STLSBSS {
1971                 p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
1972                 return nil
1973         }
1974
1975         ins := instructionForProg(p)
1976         ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
1977
1978         return instructionsForTLS(p, ins)
1979 }
1980
1981 // instructionsForMOV returns the machine instructions for an *obj.Prog that
1982 // uses a MOV pseudo-instruction.
1983 func instructionsForMOV(p *obj.Prog) []*instruction {
1984         ins := instructionForProg(p)
1985         inss := []*instruction{ins}
1986
1987         if p.Reg != 0 {
1988                 p.Ctxt.Diag("%v: illegal MOV instruction", p)
1989                 return nil
1990         }
1991
1992         switch {
1993         case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
1994                 // Handle constant to register moves.
1995                 if p.As != AMOV {
1996                         p.Ctxt.Diag("%v: unsupported constant load", p)
1997                         return nil
1998                 }
1999
2000                 // For constants larger than 32 bits in size that have trailing zeros,
2001                 // use the value with the trailing zeros removed and then use a SLLI
2002                 // instruction to restore the original constant.
2003                 // For example:
2004                 //      MOV $0x8000000000000000, X10
2005                 // becomes
2006                 //      MOV $1, X10
2007                 //      SLLI $63, X10, X10
2008                 var insSLLI *instruction
2009                 if err := immIFits(ins.imm, 32); err != nil {
2010                         ctz := bits.TrailingZeros64(uint64(ins.imm))
2011                         if err := immIFits(ins.imm>>ctz, 32); err == nil {
2012                                 ins.imm = ins.imm >> ctz
2013                                 insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(ctz)}
2014                         }
2015                 }
2016
2017                 low, high, err := Split32BitImmediate(ins.imm)
2018                 if err != nil {
2019                         p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
2020                         return nil
2021                 }
2022
2023                 // MOV $c, R -> ADD $c, ZERO, R
2024                 ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
2025
2026                 // LUI is only necessary if the constant does not fit in 12 bits.
2027                 if high != 0 {
2028                         // LUI top20bits(c), R
2029                         // ADD bottom12bits(c), R, R
2030                         insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
2031                         inss = []*instruction{insLUI}
2032                         if low != 0 {
2033                                 ins.as, ins.rs1 = AADDIW, ins.rd
2034                                 inss = append(inss, ins)
2035                         }
2036                 }
2037                 if insSLLI != nil {
2038                         inss = append(inss, insSLLI)
2039                 }
2040
2041         case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
2042                 p.Ctxt.Diag("%v: constant load must target register", p)
2043                 return nil
2044
2045         case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
2046                 // Handle register to register moves.
2047                 switch p.As {
2048                 case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb
2049                         ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
2050                 case AMOVW: // MOVW Ra, Rb -> ADDIW $0, Ra, Rb
2051                         ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
2052                 case AMOVBU: // MOVBU Ra, Rb -> ANDI $255, Ra, Rb
2053                         ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
2054                 case AMOVF: // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
2055                         ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
2056                 case AMOVD: // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
2057                         ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
2058                 case AMOVB, AMOVH:
2059                         // Use SLLI/SRAI to extend.
2060                         ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
2061                         if p.As == AMOVB {
2062                                 ins.imm = 56
2063                         } else if p.As == AMOVH {
2064                                 ins.imm = 48
2065                         }
2066                         ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
2067                         inss = append(inss, ins2)
2068                 case AMOVHU, AMOVWU:
2069                         // Use SLLI/SRLI to extend.
2070                         ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
2071                         if p.As == AMOVHU {
2072                                 ins.imm = 48
2073                         } else if p.As == AMOVWU {
2074                                 ins.imm = 32
2075                         }
2076                         ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
2077                         inss = append(inss, ins2)
2078                 }
2079
2080         case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
2081                 // Memory to register loads.
2082                 switch p.From.Name {
2083                 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
2084                         // MOV c(Rs), Rd -> L $c, Rs, Rd
2085                         inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
2086
2087                 case obj.NAME_EXTERN, obj.NAME_STATIC:
2088                         if p.From.Sym.Type == objabi.STLSBSS {
2089                                 return instructionsForTLSLoad(p)
2090                         }
2091
2092                         // Note that the values for $off_hi and $off_lo are currently
2093                         // zero and will be assigned during relocation.
2094                         //
2095                         // AUIPC $off_hi, Rd
2096                         // L $off_lo, Rd, Rd
2097                         insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
2098                         ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), ins.rd, obj.REG_NONE, 0
2099                         inss = []*instruction{insAUIPC, ins}
2100
2101                 default:
2102                         p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
2103                         return nil
2104                 }
2105
2106         case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
2107                 // Register to memory stores.
2108                 switch p.As {
2109                 case AMOVBU, AMOVHU, AMOVWU:
2110                         p.Ctxt.Diag("%v: unsupported unsigned store", p)
2111                         return nil
2112                 }
2113                 switch p.To.Name {
2114                 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
2115                         // MOV Rs, c(Rd) -> S $c, Rs, Rd
2116                         inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
2117
2118                 case obj.NAME_EXTERN, obj.NAME_STATIC:
2119                         if p.To.Sym.Type == objabi.STLSBSS {
2120                                 return instructionsForTLSStore(p)
2121                         }
2122
2123                         // Note that the values for $off_hi and $off_lo are currently
2124                         // zero and will be assigned during relocation.
2125                         //
2126                         // AUIPC $off_hi, Rtmp
2127                         // S $off_lo, Rtmp, Rd
2128                         insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
2129                         ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
2130                         inss = []*instruction{insAUIPC, ins}
2131
2132                 default:
2133                         p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
2134                         return nil
2135                 }
2136
2137         case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
2138                 // MOV $sym+off(SP/SB), R
2139                 if p.As != AMOV {
2140                         p.Ctxt.Diag("%v: unsupported address load", p)
2141                         return nil
2142                 }
2143                 switch p.From.Name {
2144                 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
2145                         inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
2146
2147                 case obj.NAME_EXTERN, obj.NAME_STATIC:
2148                         // Note that the values for $off_hi and $off_lo are currently
2149                         // zero and will be assigned during relocation.
2150                         //
2151                         // AUIPC $off_hi, R
2152                         // ADDI $off_lo, R
2153                         insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
2154                         ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
2155                         inss = []*instruction{insAUIPC, ins}
2156
2157                 default:
2158                         p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
2159                         return nil
2160                 }
2161
2162         case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
2163                 p.Ctxt.Diag("%v: address load must target register", p)
2164                 return nil
2165
2166         default:
2167                 p.Ctxt.Diag("%v: unsupported MOV", p)
2168                 return nil
2169         }
2170
2171         return inss
2172 }
2173
2174 // instructionsForProg returns the machine instructions for an *obj.Prog.
2175 func instructionsForProg(p *obj.Prog) []*instruction {
2176         ins := instructionForProg(p)
2177         inss := []*instruction{ins}
2178
2179         if len(p.RestArgs) > 1 {
2180                 p.Ctxt.Diag("too many source registers")
2181                 return nil
2182         }
2183
2184         switch ins.as {
2185         case AJAL, AJALR:
2186                 ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
2187                 ins.imm = p.To.Offset
2188
2189         case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
2190                 switch ins.as {
2191                 case ABEQZ:
2192                         ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
2193                 case ABGEZ:
2194                         ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
2195                 case ABGT:
2196                         ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
2197                 case ABGTU:
2198                         ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
2199                 case ABGTZ:
2200                         ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
2201                 case ABLE:
2202                         ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
2203                 case ABLEU:
2204                         ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
2205                 case ABLEZ:
2206                         ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
2207                 case ABLTZ:
2208                         ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
2209                 case ABNEZ:
2210                         ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
2211                 }
2212                 ins.imm = p.To.Offset
2213
2214         case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
2215                 inss = instructionsForMOV(p)
2216
2217         case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
2218                 inss = instructionsForLoad(p, ins.as, p.From.Reg)
2219
2220         case ASW, ASH, ASB, ASD, AFSW, AFSD:
2221                 inss = instructionsForStore(p, ins.as, p.To.Reg)
2222
2223         case ALRW, ALRD:
2224                 // Set aq to use acquire access ordering
2225                 ins.funct7 = 2
2226                 ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
2227
2228         case AADDI, AANDI, AORI, AXORI:
2229                 inss = instructionsForOpImmediate(p, ins.as, p.Reg)
2230
2231         case ASCW, ASCD:
2232                 // Set release access ordering
2233                 ins.funct7 = 1
2234                 ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
2235
2236         case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
2237                 AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
2238                 // Set aqrl to use acquire & release access ordering
2239                 ins.funct7 = 3
2240                 ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
2241
2242         case AECALL, AEBREAK, ARDCYCLE, ARDTIME, ARDINSTRET:
2243                 insEnc := encode(p.As)
2244                 if p.To.Type == obj.TYPE_NONE {
2245                         ins.rd = REG_ZERO
2246                 }
2247                 ins.rs1 = REG_ZERO
2248                 ins.imm = insEnc.csr
2249
2250         case AFENCE:
2251                 ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
2252                 ins.imm = 0x0ff
2253
2254         case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
2255                 // Set the rounding mode in funct3 to round to zero.
2256                 ins.funct3 = 1
2257
2258         case AFNES, AFNED:
2259                 // Replace FNE[SD] with FEQ[SD] and NOT.
2260                 if p.To.Type != obj.TYPE_REG {
2261                         p.Ctxt.Diag("%v needs an integer register output", p)
2262                         return nil
2263                 }
2264                 if ins.as == AFNES {
2265                         ins.as = AFEQS
2266                 } else {
2267                         ins.as = AFEQD
2268                 }
2269                 ins2 := &instruction{
2270                         as:  AXORI, // [bit] xor 1 = not [bit]
2271                         rd:  ins.rd,
2272                         rs1: ins.rd,
2273                         imm: 1,
2274                 }
2275                 inss = append(inss, ins2)
2276
2277         case AFSQRTS, AFSQRTD:
2278                 // These instructions expect a zero (i.e. float register 0)
2279                 // to be the second input operand.
2280                 ins.rs1 = uint32(p.From.Reg)
2281                 ins.rs2 = REG_F0
2282
2283         case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
2284                 AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
2285                 // Swap the first two operands so that the operands are in the same
2286                 // order as they are in the specification: RS1, RS2, RS3, RD.
2287                 ins.rs1, ins.rs2 = ins.rs2, ins.rs1
2288
2289         case ANEG, ANEGW:
2290                 // NEG rs, rd -> SUB rs, X0, rd
2291                 ins.as = ASUB
2292                 if p.As == ANEGW {
2293                         ins.as = ASUBW
2294                 }
2295                 ins.rs1 = REG_ZERO
2296                 if ins.rd == obj.REG_NONE {
2297                         ins.rd = ins.rs2
2298                 }
2299
2300         case ANOT:
2301                 // NOT rs, rd -> XORI $-1, rs, rd
2302                 ins.as = AXORI
2303                 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
2304                 if ins.rd == obj.REG_NONE {
2305                         ins.rd = ins.rs1
2306                 }
2307                 ins.imm = -1
2308
2309         case ASEQZ:
2310                 // SEQZ rs, rd -> SLTIU $1, rs, rd
2311                 ins.as = ASLTIU
2312                 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
2313                 ins.imm = 1
2314
2315         case ASNEZ:
2316                 // SNEZ rs, rd -> SLTU rs, x0, rd
2317                 ins.as = ASLTU
2318                 ins.rs1 = REG_ZERO
2319
2320         case AFABSS:
2321                 // FABSS rs, rd -> FSGNJXS rs, rs, rd
2322                 ins.as = AFSGNJXS
2323                 ins.rs1 = uint32(p.From.Reg)
2324
2325         case AFABSD:
2326                 // FABSD rs, rd -> FSGNJXD rs, rs, rd
2327                 ins.as = AFSGNJXD
2328                 ins.rs1 = uint32(p.From.Reg)
2329
2330         case AFNEGS:
2331                 // FNEGS rs, rd -> FSGNJNS rs, rs, rd
2332                 ins.as = AFSGNJNS
2333                 ins.rs1 = uint32(p.From.Reg)
2334
2335         case AFNEGD:
2336                 // FNEGD rs, rd -> FSGNJND rs, rs, rd
2337                 ins.as = AFSGNJND
2338                 ins.rs1 = uint32(p.From.Reg)
2339
2340         case ASLLI, ASRLI, ASRAI:
2341                 if ins.imm < 0 || ins.imm > 63 {
2342                         p.Ctxt.Diag("%v: shift amount out of range 0 to 63", p)
2343                 }
2344
2345         case ASLLIW, ASRLIW, ASRAIW:
2346                 if ins.imm < 0 || ins.imm > 31 {
2347                         p.Ctxt.Diag("%v: shift amount out of range 0 to 31", p)
2348                 }
2349         }
2350
2351         for _, ins := range inss {
2352                 ins.p = p
2353         }
2354
2355         return inss
2356 }
2357
2358 // assemble emits machine code.
2359 // It is called at the very end of the assembly process.
2360 func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
2361         if ctxt.Retpoline {
2362                 ctxt.Diag("-spectre=ret not supported on riscv")
2363                 ctxt.Retpoline = false // don't keep printing
2364         }
2365
2366         // If errors were encountered during preprocess/validation, proceeding
2367         // and attempting to encode said instructions will only lead to panics.
2368         if ctxt.Errors > 0 {
2369                 return
2370         }
2371
2372         for p := cursym.Func().Text; p != nil; p = p.Link {
2373                 switch p.As {
2374                 case AJAL:
2375                         if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
2376                                 rel := obj.Addrel(cursym)
2377                                 rel.Off = int32(p.Pc)
2378                                 rel.Siz = 4
2379                                 rel.Sym = p.To.Sym
2380                                 rel.Add = p.To.Offset
2381                                 rel.Type = objabi.R_RISCV_JAL
2382                         }
2383                 case AJALR:
2384                         if p.To.Sym != nil {
2385                                 ctxt.Diag("%v: unexpected AJALR with to symbol", p)
2386                         }
2387
2388                 case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
2389                         var addr *obj.Addr
2390                         var rt objabi.RelocType
2391                         if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
2392                                 rt = objabi.R_RISCV_CALL
2393                                 addr = &p.From
2394                         } else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
2395                                 rt = objabi.R_RISCV_PCREL_ITYPE
2396                                 addr = &p.From
2397                         } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
2398                                 rt = objabi.R_RISCV_PCREL_STYPE
2399                                 addr = &p.To
2400                         } else {
2401                                 break
2402                         }
2403                         if p.As == AAUIPC {
2404                                 if p.Link == nil {
2405                                         ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
2406                                         break
2407                                 }
2408                                 addr = &p.RestArgs[0].Addr
2409                         }
2410                         if addr.Sym == nil {
2411                                 ctxt.Diag("PC-relative relocation missing symbol")
2412                                 break
2413                         }
2414                         if addr.Sym.Type == objabi.STLSBSS {
2415                                 if ctxt.Flag_shared {
2416                                         rt = objabi.R_RISCV_TLS_IE
2417                                 } else {
2418                                         rt = objabi.R_RISCV_TLS_LE
2419                                 }
2420                         }
2421
2422                         rel := obj.Addrel(cursym)
2423                         rel.Off = int32(p.Pc)
2424                         rel.Siz = 8
2425                         rel.Sym = addr.Sym
2426                         rel.Add = addr.Offset
2427                         rel.Type = rt
2428                 }
2429
2430                 offset := p.Pc
2431                 for _, ins := range instructionsForProg(p) {
2432                         if ic, err := ins.encode(); err == nil {
2433                                 cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
2434                                 offset += int64(ins.length())
2435                         }
2436                         if ins.usesRegTmp() {
2437                                 p.Mark |= USES_REG_TMP
2438                         }
2439                 }
2440         }
2441
2442         obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
2443 }
2444
2445 func isUnsafePoint(p *obj.Prog) bool {
2446         return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
2447 }
2448
2449 var LinkRISCV64 = obj.LinkArch{
2450         Arch:           sys.ArchRISCV64,
2451         Init:           buildop,
2452         Preprocess:     preprocess,
2453         Assemble:       assemble,
2454         Progedit:       progedit,
2455         UnaryDst:       unaryDst,
2456         DWARFRegisters: RISCV64DWARFRegisters,
2457 }