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