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