1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package riscv
22
23 import (
24 "cmd/internal/obj"
25 "cmd/internal/objabi"
26 "cmd/internal/src"
27 "cmd/internal/sys"
28 "fmt"
29 "internal/abi"
30 "internal/buildcfg"
31 "log"
32 "math/bits"
33 "strings"
34 )
35
36 func buildop(ctxt *obj.Link) {}
37
38 func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) {
39 switch p.As {
40 case obj.ACALL, obj.AJMP, obj.ARET, obj.ADUFFZERO, obj.ADUFFCOPY:
41 default:
42 ctxt.Diag("unexpected Prog in jalToSym: %v", p)
43 return
44 }
45
46 p.As = AJAL
47 p.Mark |= NEED_JAL_RELOC
48 p.From.Type = obj.TYPE_REG
49 p.From.Reg = lr
50 p.Reg = obj.REG_NONE
51 }
52
53
54
55 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
56 insData, err := instructionDataForAs(p.As)
57 if err != nil {
58 panic(fmt.Sprintf("failed to lookup instruction data for %v: %v", p.As, err))
59 }
60
61
62 if p.Reg == obj.REG_NONE {
63 if insData.ternary {
64 p.Reg = p.To.Reg
65 }
66 }
67
68
69
70 if p.From.Type == obj.TYPE_CONST {
71 switch p.As {
72 case ASUB:
73 p.As, p.From.Offset = AADDI, -p.From.Offset
74 case ASUBW:
75 p.As, p.From.Offset = AADDIW, -p.From.Offset
76 default:
77 if insData.immForm != obj.AXXX {
78 p.As = insData.immForm
79 }
80 }
81 }
82
83 switch p.As {
84 case obj.AJMP:
85
86 p.From.Type = obj.TYPE_REG
87 p.From.Reg = REG_ZERO
88
89 switch p.To.Type {
90 case obj.TYPE_BRANCH:
91 p.As = AJAL
92 case obj.TYPE_MEM:
93 switch p.To.Name {
94 case obj.NAME_NONE:
95 p.As = AJALR
96 case obj.NAME_EXTERN, obj.NAME_STATIC:
97
98 default:
99 ctxt.Diag("unsupported name %d for %v", p.To.Name, p)
100 }
101 default:
102 panic(fmt.Sprintf("unhandled type %+v", p.To.Type))
103 }
104
105 case obj.ACALL:
106 switch p.To.Type {
107 case obj.TYPE_MEM:
108
109 case obj.TYPE_REG:
110 p.As = AJALR
111 p.From.Type = obj.TYPE_REG
112 p.From.Reg = REG_LR
113 default:
114 ctxt.Diag("unknown destination type %+v in CALL: %v", p.To.Type, p)
115 }
116
117 case obj.AUNDEF:
118 p.As = AEBREAK
119
120 case AFMVXS:
121
122 p.As = AFMVXW
123
124 case AFMVSX:
125
126 p.As = AFMVWX
127
128 case ASCALL:
129
130 p.As = AECALL
131
132 case ASBREAK:
133
134 p.As = AEBREAK
135
136 case AMOV:
137 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 {
138 if isShiftConst(p.From.Offset) {
139 break
140 }
141
142 p.From.Type = obj.TYPE_MEM
143 p.From.Sym = ctxt.Int64Sym(p.From.Offset)
144 p.From.Name = obj.NAME_EXTERN
145 p.From.Offset = 0
146 }
147
148 case AMOVD:
149 if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
150 f64 := p.From.Val.(float64)
151 p.From.Type = obj.TYPE_MEM
152 p.From.Sym = ctxt.Float64Sym(f64)
153 p.From.Name = obj.NAME_EXTERN
154 p.From.Offset = 0
155 }
156 }
157
158 if ctxt.Flag_dynlink {
159 rewriteToUseGot(ctxt, p, newprog)
160 }
161 }
162
163
164 func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
165 if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
166
167
168
169
170
171 var sym *obj.LSym
172 if p.As == obj.ADUFFCOPY {
173 sym = ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal)
174 } else {
175 sym = ctxt.LookupABI("runtime.duffzero", obj.ABIInternal)
176 }
177 offset := p.To.Offset
178 p.As = AMOV
179 p.From.Type = obj.TYPE_MEM
180 p.From.Name = obj.NAME_GOTREF
181 p.From.Sym = sym
182 p.To.Type = obj.TYPE_REG
183 p.To.Reg = REG_TMP
184 p.To.Name = obj.NAME_NONE
185 p.To.Offset = 0
186 p.To.Sym = nil
187
188 p1 := obj.Appendp(p, newprog)
189 p1.As = AADD
190 p1.From.Type = obj.TYPE_CONST
191 p1.From.Offset = offset
192 p1.To.Type = obj.TYPE_REG
193 p1.To.Reg = REG_TMP
194
195 p2 := obj.Appendp(p1, newprog)
196 p2.As = obj.ACALL
197 p2.To.Type = obj.TYPE_REG
198 p2.To.Reg = REG_TMP
199 }
200
201
202
203
204 if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
205
206
207 if p.As != AMOV {
208 ctxt.Diag("don't know how to handle TYPE_ADDR in %v with -dynlink", p)
209 }
210 if p.To.Type != obj.TYPE_REG {
211 ctxt.Diag("don't know how to handle LD instruction to non-register in %v with -dynlink", p)
212 }
213 p.From.Type = obj.TYPE_MEM
214 p.From.Name = obj.NAME_GOTREF
215 if p.From.Offset != 0 {
216 q := obj.Appendp(p, newprog)
217 q.As = AADD
218 q.From.Type = obj.TYPE_CONST
219 q.From.Offset = p.From.Offset
220 q.To = p.To
221 p.From.Offset = 0
222 }
223
224 }
225
226 if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
227 ctxt.Diag("don't know how to handle %v with -dynlink", p)
228 }
229
230 var source *obj.Addr
231
232
233
234 if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
235 if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
236 ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
237 }
238 source = &p.From
239 } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
240 source = &p.To
241 } else {
242 return
243 }
244 if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
245 return
246 }
247 if source.Sym.Type == objabi.STLSBSS {
248 return
249 }
250 if source.Type != obj.TYPE_MEM {
251 ctxt.Diag("don't know how to handle %v with -dynlink", p)
252 }
253 p1 := obj.Appendp(p, newprog)
254 p1.As = AMOV
255 p1.From.Type = obj.TYPE_MEM
256 p1.From.Sym = source.Sym
257 p1.From.Name = obj.NAME_GOTREF
258 p1.To.Type = obj.TYPE_REG
259 p1.To.Reg = REG_TMP
260
261 p2 := obj.Appendp(p1, newprog)
262 p2.As = p.As
263 p2.From = p.From
264 p2.To = p.To
265 if p.From.Name == obj.NAME_EXTERN {
266 p2.From.Reg = REG_TMP
267 p2.From.Name = obj.NAME_NONE
268 p2.From.Sym = nil
269 } else if p.To.Name == obj.NAME_EXTERN {
270 p2.To.Reg = REG_TMP
271 p2.To.Name = obj.NAME_NONE
272 p2.To.Sym = nil
273 } else {
274 return
275 }
276 obj.Nopout(p)
277
278 }
279
280
281 func addrToReg(a obj.Addr) int16 {
282 switch a.Name {
283 case obj.NAME_PARAM, obj.NAME_AUTO:
284 return REG_SP
285 }
286 return a.Reg
287 }
288
289
290 func movToLoad(mnemonic obj.As) obj.As {
291 switch mnemonic {
292 case AMOV:
293 return ALD
294 case AMOVB:
295 return ALB
296 case AMOVH:
297 return ALH
298 case AMOVW:
299 return ALW
300 case AMOVBU:
301 return ALBU
302 case AMOVHU:
303 return ALHU
304 case AMOVWU:
305 return ALWU
306 case AMOVF:
307 return AFLW
308 case AMOVD:
309 return AFLD
310 default:
311 panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
312 }
313 }
314
315
316 func movToStore(mnemonic obj.As) obj.As {
317 switch mnemonic {
318 case AMOV:
319 return ASD
320 case AMOVB:
321 return ASB
322 case AMOVH:
323 return ASH
324 case AMOVW:
325 return ASW
326 case AMOVF:
327 return AFSW
328 case AMOVD:
329 return AFSD
330 default:
331 panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
332 }
333 }
334
335
336
337 func markRelocs(p *obj.Prog) {
338 switch p.As {
339 case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
340 switch {
341 case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
342 switch p.From.Name {
343 case obj.NAME_EXTERN, obj.NAME_STATIC:
344 p.Mark |= NEED_PCREL_ITYPE_RELOC
345 case obj.NAME_GOTREF:
346 p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC
347 }
348 case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
349 switch p.From.Name {
350 case obj.NAME_EXTERN, obj.NAME_STATIC:
351 p.Mark |= NEED_PCREL_ITYPE_RELOC
352 case obj.NAME_GOTREF:
353 p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC
354 }
355 case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
356 switch p.To.Name {
357 case obj.NAME_EXTERN, obj.NAME_STATIC:
358 p.Mark |= NEED_PCREL_STYPE_RELOC
359 }
360 }
361 }
362 }
363
364
365 func InvertBranch(as obj.As) obj.As {
366 switch as {
367 case ABEQ:
368 return ABNE
369 case ABEQZ:
370 return ABNEZ
371 case ABGE:
372 return ABLT
373 case ABGEU:
374 return ABLTU
375 case ABGEZ:
376 return ABLTZ
377 case ABGT:
378 return ABLE
379 case ABGTU:
380 return ABLEU
381 case ABGTZ:
382 return ABLEZ
383 case ABLE:
384 return ABGT
385 case ABLEU:
386 return ABGTU
387 case ABLEZ:
388 return ABGTZ
389 case ABLT:
390 return ABGE
391 case ABLTU:
392 return ABGEU
393 case ABLTZ:
394 return ABGEZ
395 case ABNE:
396 return ABEQ
397 case ABNEZ:
398 return ABEQZ
399 default:
400 panic("InvertBranch: not a branch")
401 }
402 }
403
404
405
406 func containsCall(sym *obj.LSym) bool {
407
408 for p := sym.Func().Text; p != nil; p = p.Link {
409 switch p.As {
410 case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
411 return true
412 case AJAL, AJALR:
413 if p.From.Type == obj.TYPE_REG && p.From.Reg == REG_LR {
414 return true
415 }
416 }
417 }
418
419 return false
420 }
421
422
423
424 func setPCs(p *obj.Prog, pc int64) int64 {
425 for ; p != nil; p = p.Link {
426 p.Pc = pc
427 for _, ins := range instructionsForProg(p) {
428 pc += int64(ins.length())
429 }
430
431 if p.As == obj.APCALIGN {
432 alignedValue := p.From.Offset
433 v := pcAlignPadLength(pc, alignedValue)
434 pc += int64(v)
435 }
436 }
437 return pc
438 }
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464 func stackOffset(a *obj.Addr, stacksize int64) {
465 switch a.Name {
466 case obj.NAME_AUTO:
467
468 a.Offset += stacksize
469 case obj.NAME_PARAM:
470
471 a.Offset += stacksize + 8
472 }
473 }
474
475
476
477
478
479
480
481
482
483 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
484 if cursym.Func().Text == nil || cursym.Func().Text.Link == nil {
485 return
486 }
487
488
489 text := cursym.Func().Text
490 if text.As != obj.ATEXT {
491 ctxt.Diag("preprocess: found symbol that does not start with TEXT directive")
492 return
493 }
494
495 stacksize := text.To.Offset
496 if stacksize == -8 {
497
498 text.From.Sym.Set(obj.AttrNoFrame, true)
499 stacksize = 0
500 }
501 if stacksize < 0 {
502 ctxt.Diag("negative frame size %d - did you mean NOFRAME?", stacksize)
503 }
504 if text.From.Sym.NoFrame() {
505 if stacksize != 0 {
506 ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", stacksize)
507 }
508 }
509
510 if !containsCall(cursym) {
511 text.From.Sym.Set(obj.AttrLeaf, true)
512 if stacksize == 0 {
513
514 text.From.Sym.Set(obj.AttrNoFrame, true)
515 }
516 }
517
518
519 if !text.From.Sym.NoFrame() {
520 stacksize += ctxt.Arch.FixedFrameSize
521 }
522
523 cursym.Func().Args = text.To.Val.(int32)
524 cursym.Func().Locals = int32(stacksize)
525
526 prologue := text
527
528 if !cursym.Func().Text.From.Sym.NoSplit() {
529 prologue = stacksplit(ctxt, prologue, cursym, newprog, stacksize)
530 }
531
532 q := prologue
533
534 if stacksize != 0 {
535 prologue = ctxt.StartUnsafePoint(prologue, newprog)
536
537
538 prologue = obj.Appendp(prologue, newprog)
539 prologue.As = AMOV
540 prologue.Pos = q.Pos
541 prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
542 prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -stacksize}
543
544
545 prologue = obj.Appendp(prologue, newprog)
546 prologue.As = AADDI
547 prologue.Pos = q.Pos
548 prologue.Pos = prologue.Pos.WithXlogue(src.PosPrologueEnd)
549 prologue.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -stacksize}
550 prologue.Reg = REG_SP
551 prologue.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
552 prologue.Spadj = int32(stacksize)
553
554 prologue = ctxt.EndUnsafePoint(prologue, newprog, -1)
555
556
557
558
559
560
561 prologue = obj.Appendp(prologue, newprog)
562 prologue.As = AMOV
563 prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
564 prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
565 }
566
567
568 for p := cursym.Func().Text; p != nil; p = p.Link {
569 stackOffset(&p.From, stacksize)
570 stackOffset(&p.To, stacksize)
571 }
572
573
574 for p := cursym.Func().Text; p != nil; p = p.Link {
575 switch p.As {
576 case obj.AGETCALLERPC:
577 if cursym.Leaf() {
578
579 p.As = AMOV
580 p.From.Type = obj.TYPE_REG
581 p.From.Reg = REG_LR
582 } else {
583
584 p.As = AMOV
585 p.From.Type = obj.TYPE_MEM
586 p.From.Reg = REG_SP
587 }
588
589 case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
590 switch p.To.Type {
591 case obj.TYPE_MEM:
592 jalToSym(ctxt, p, REG_LR)
593 }
594
595 case obj.AJMP:
596 switch p.To.Type {
597 case obj.TYPE_MEM:
598 switch p.To.Name {
599 case obj.NAME_EXTERN, obj.NAME_STATIC:
600 jalToSym(ctxt, p, REG_ZERO)
601 }
602 }
603
604 case obj.ARET:
605
606 retJMP := p.To.Sym
607
608 if stacksize != 0 {
609
610 p.As = AMOV
611 p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
612 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
613 p = obj.Appendp(p, newprog)
614
615 p.As = AADDI
616 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize}
617 p.Reg = REG_SP
618 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
619 p.Spadj = int32(-stacksize)
620 p = obj.Appendp(p, newprog)
621 }
622
623 if retJMP != nil {
624 p.As = obj.ARET
625 p.To.Sym = retJMP
626 jalToSym(ctxt, p, REG_ZERO)
627 } else {
628 p.As = AJALR
629 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
630 p.Reg = obj.REG_NONE
631 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
632 }
633
634
635
636
637
638
639
640 p.Spadj = int32(stacksize)
641
642 case AADDI:
643
644 if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SP && p.From.Type == obj.TYPE_CONST {
645 p.Spadj = int32(-p.From.Offset)
646 }
647 }
648
649 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
650 f := cursym.Func()
651 if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
652 f.FuncFlag |= abi.FuncFlagSPWrite
653 if ctxt.Debugvlog || !ctxt.IsAsm {
654 ctxt.Logf("auto-SPWRITE: %s %v\n", cursym.Name, p)
655 if !ctxt.IsAsm {
656 ctxt.Diag("invalid auto-SPWRITE in non-assembly")
657 ctxt.DiagFlush()
658 log.Fatalf("bad SPWRITE")
659 }
660 }
661 }
662 }
663 }
664
665 var callCount int
666 for p := cursym.Func().Text; p != nil; p = p.Link {
667 markRelocs(p)
668 if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
669 callCount++
670 }
671 }
672 const callTrampSize = 8
673 maxTrampSize := int64(callCount * callTrampSize)
674
675
676
677
678
679 for {
680 big, rescan := false, false
681 maxPC := setPCs(cursym.Func().Text, 0)
682 if maxPC+maxTrampSize > (1 << 20) {
683 big = true
684 }
685
686 for p := cursym.Func().Text; p != nil; p = p.Link {
687 switch p.As {
688 case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
689 if p.To.Type != obj.TYPE_BRANCH {
690 ctxt.Diag("%v: instruction with branch-like opcode lacks destination", p)
691 break
692 }
693 offset := p.To.Target().Pc - p.Pc
694 if offset < -4096 || 4096 <= offset {
695
696 jmp := obj.Appendp(p, newprog)
697 jmp.As = AJAL
698 jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
699 jmp.To = obj.Addr{Type: obj.TYPE_BRANCH}
700 jmp.To.SetTarget(p.To.Target())
701
702 p.As = InvertBranch(p.As)
703 p.To.SetTarget(jmp.Link)
704
705
706
707 rescan = true
708 }
709 case AJAL:
710
711 if p.To.Target() == nil {
712 if !big {
713 break
714 }
715
716
717 jmp := obj.Appendp(p, newprog)
718 jmp.As = AJALR
719 jmp.From = p.From
720 jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
721
722 p.As = AAUIPC
723 p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC
724 p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym})
725 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
726 p.Reg = obj.REG_NONE
727 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
728
729 rescan = true
730 break
731 }
732 offset := p.To.Target().Pc - p.Pc
733 if offset < -(1<<20) || (1<<20) <= offset {
734
735
736
737 jmp := obj.Appendp(p, newprog)
738 jmp.As = AJALR
739 jmp.From = p.From
740 jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
741
742
743
744 p.As = AAUIPC
745 p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym}
746 p.From.SetTarget(p.To.Target())
747 p.Reg = obj.REG_NONE
748 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
749
750 rescan = true
751 }
752 }
753 }
754
755
756
757 if ctxt.Errors > 0 {
758 return
759 }
760 if !rescan {
761 break
762 }
763 }
764
765
766
767
768 for p := cursym.Func().Text; p != nil; p = p.Link {
769 switch p.As {
770 case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
771 switch p.To.Type {
772 case obj.TYPE_BRANCH:
773 p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
774 case obj.TYPE_MEM:
775 if ctxt.Errors == 0 {
776
777 panic("unhandled type")
778 }
779 }
780
781 case AJAL:
782
783 if p.To.Target() != nil {
784 p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
785 }
786
787 case AAUIPC:
788 if p.From.Type == obj.TYPE_BRANCH {
789 low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc)
790 if err != nil {
791 ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
792 }
793 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
794 p.Link.To.Offset = low
795 }
796
797 case obj.APCALIGN:
798 alignedValue := p.From.Offset
799 if (alignedValue&(alignedValue-1) != 0) || 4 > alignedValue || alignedValue > 2048 {
800 ctxt.Diag("alignment value of an instruction must be a power of two and in the range [4, 2048], got %d\n", alignedValue)
801 }
802
803 if int32(alignedValue) > cursym.Func().Align {
804 cursym.Func().Align = int32(alignedValue)
805 }
806 }
807 }
808
809
810 for p := cursym.Func().Text; p != nil; p = p.Link {
811 for _, ins := range instructionsForProg(p) {
812 ins.validate(ctxt)
813 }
814 }
815 }
816
817 func pcAlignPadLength(pc int64, alignedValue int64) int {
818 return int(-pc & (alignedValue - 1))
819 }
820
821 func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgAlloc, framesize int64) *obj.Prog {
822
823 if framesize == 0 {
824 return p
825 }
826
827 if ctxt.Flag_maymorestack != "" {
828
829 const frameSize = 16
830 p = ctxt.StartUnsafePoint(p, newprog)
831
832
833
834 p = cursym.Func().SpillRegisterArgs(p, newprog)
835
836
837 p = obj.Appendp(p, newprog)
838 p.As = AMOV
839 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
840 p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize}
841
842 p = obj.Appendp(p, newprog)
843 p.As = AADDI
844 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize}
845 p.Reg = REG_SP
846 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
847 p.Spadj = frameSize
848
849 p = obj.Appendp(p, newprog)
850 p.As = AMOV
851 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
852 p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
853
854
855 p = obj.Appendp(p, newprog)
856 p.As = obj.ACALL
857 p.To.Type = obj.TYPE_BRANCH
858
859 p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI())
860 jalToSym(ctxt, p, REG_X5)
861
862
863
864
865 p = obj.Appendp(p, newprog)
866 p.As = AMOV
867 p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
868 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
869
870 p = obj.Appendp(p, newprog)
871 p.As = AMOV
872 p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
873 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
874
875 p = obj.Appendp(p, newprog)
876 p.As = AADDI
877 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize}
878 p.Reg = REG_SP
879 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
880 p.Spadj = -frameSize
881
882
883 p = cursym.Func().UnspillRegisterArgs(p, newprog)
884 p = ctxt.EndUnsafePoint(p, newprog, -1)
885 }
886
887
888 startPred := p
889
890
891 p = obj.Appendp(p, newprog)
892 p.As = AMOV
893 p.From.Type = obj.TYPE_MEM
894 p.From.Reg = REGG
895 p.From.Offset = 2 * int64(ctxt.Arch.PtrSize)
896 if cursym.CFunc() {
897 p.From.Offset = 3 * int64(ctxt.Arch.PtrSize)
898 }
899 p.To.Type = obj.TYPE_REG
900 p.To.Reg = REG_X6
901
902
903
904
905
906 p = ctxt.StartUnsafePoint(p, newprog)
907
908 var to_done, to_more *obj.Prog
909
910 if framesize <= abi.StackSmall {
911
912
913
914 p = obj.Appendp(p, newprog)
915 p.As = ABLTU
916 p.From.Type = obj.TYPE_REG
917 p.From.Reg = REG_X6
918 p.Reg = REG_SP
919 p.To.Type = obj.TYPE_BRANCH
920 to_done = p
921 } else {
922
923 offset := int64(framesize) - abi.StackSmall
924 if framesize > abi.StackBig {
925
926
927
928
929
930
931
932
933
934
935 p = obj.Appendp(p, newprog)
936 p.As = AMOV
937 p.From.Type = obj.TYPE_CONST
938 p.From.Offset = offset
939 p.To.Type = obj.TYPE_REG
940 p.To.Reg = REG_X7
941
942 p = obj.Appendp(p, newprog)
943 p.As = ABLTU
944 p.From.Type = obj.TYPE_REG
945 p.From.Reg = REG_SP
946 p.Reg = REG_X7
947 p.To.Type = obj.TYPE_BRANCH
948 to_more = p
949 }
950
951
952
953
954
955 p = obj.Appendp(p, newprog)
956 p.As = AADDI
957 p.From.Type = obj.TYPE_CONST
958 p.From.Offset = -offset
959 p.Reg = REG_SP
960 p.To.Type = obj.TYPE_REG
961 p.To.Reg = REG_X7
962
963 p = obj.Appendp(p, newprog)
964 p.As = ABLTU
965 p.From.Type = obj.TYPE_REG
966 p.From.Reg = REG_X6
967 p.Reg = REG_X7
968 p.To.Type = obj.TYPE_BRANCH
969 to_done = p
970 }
971
972
973
974 p = ctxt.EmitEntryStackMap(cursym, p, newprog)
975 p = cursym.Func().SpillRegisterArgs(p, newprog)
976
977
978 p = obj.Appendp(p, newprog)
979 p.As = obj.ACALL
980 p.To.Type = obj.TYPE_BRANCH
981
982 if cursym.CFunc() {
983 p.To.Sym = ctxt.Lookup("runtime.morestackc")
984 } else if !cursym.Func().Text.From.Sym.NeedCtxt() {
985 p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt")
986 } else {
987 p.To.Sym = ctxt.Lookup("runtime.morestack")
988 }
989 if to_more != nil {
990 to_more.To.SetTarget(p)
991 }
992 jalToSym(ctxt, p, REG_X5)
993
994
995 p = ctxt.EndUnsafePoint(p, newprog, -1)
996 p = cursym.Func().UnspillRegisterArgs(p, newprog)
997
998
999 p = obj.Appendp(p, newprog)
1000 p.As = AJAL
1001 p.To = obj.Addr{Type: obj.TYPE_BRANCH}
1002 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
1003 p.To.SetTarget(startPred.Link)
1004
1005
1006 p = obj.Appendp(p, newprog)
1007 p.As = obj.ANOP
1008 to_done.To.SetTarget(p)
1009
1010 return p
1011 }
1012
1013
1014 func signExtend(val int64, bit uint) int64 {
1015 return val << (64 - bit) >> (64 - bit)
1016 }
1017
1018
1019
1020
1021
1022 func Split32BitImmediate(imm int64) (low, high int64, err error) {
1023 if err := immIFits(imm, 32); err != nil {
1024 return 0, 0, err
1025 }
1026
1027
1028 if err := immIFits(imm, 12); err == nil {
1029 return imm, 0, nil
1030 }
1031
1032 high = imm >> 12
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043 if imm&(1<<11) != 0 {
1044 high++
1045 }
1046
1047 low = signExtend(imm, 12)
1048 high = signExtend(high, 20)
1049
1050 return low, high, nil
1051 }
1052
1053 func regVal(r, min, max uint32) uint32 {
1054 if r < min || r > max {
1055 panic(fmt.Sprintf("register out of range, want %d <= %d <= %d", min, r, max))
1056 }
1057 return r - min
1058 }
1059
1060
1061 func regI(r uint32) uint32 {
1062 return regVal(r, REG_X0, REG_X31)
1063 }
1064
1065
1066 func regF(r uint32) uint32 {
1067 return regVal(r, REG_F0, REG_F31)
1068 }
1069
1070
1071 func regV(r uint32) uint32 {
1072 return regVal(r, REG_V0, REG_V31)
1073 }
1074
1075
1076
1077 func immEven(x int64) error {
1078 if x&1 != 0 {
1079 return fmt.Errorf("immediate %#x is not a multiple of two", x)
1080 }
1081 return nil
1082 }
1083
1084 func immFits(x int64, nbits uint, signed bool) error {
1085 label := "unsigned"
1086 min, max := int64(0), int64(1)<<nbits-1
1087 if signed {
1088 label = "signed"
1089 sbits := nbits - 1
1090 min, max = int64(-1)<<sbits, int64(1)<<sbits-1
1091 }
1092 if x < min || x > max {
1093 if nbits <= 16 {
1094 return fmt.Errorf("%s immediate %d must be in range [%d, %d] (%d bits)", label, x, min, max, nbits)
1095 }
1096 return fmt.Errorf("%s immediate %#x must be in range [%#x, %#x] (%d bits)", label, x, min, max, nbits)
1097 }
1098 return nil
1099 }
1100
1101
1102
1103 func immIFits(x int64, nbits uint) error {
1104 return immFits(x, nbits, true)
1105 }
1106
1107
1108 func immI(as obj.As, imm int64, nbits uint) uint32 {
1109 if err := immIFits(imm, nbits); err != nil {
1110 panic(fmt.Sprintf("%v: %v", as, err))
1111 }
1112 return uint32(imm) & ((1 << nbits) - 1)
1113 }
1114
1115 func wantImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
1116 if err := immIFits(imm, nbits); err != nil {
1117 ctxt.Diag("%v: %v", ins, err)
1118 }
1119 }
1120
1121
1122
1123 func immUFits(x int64, nbits uint) error {
1124 return immFits(x, nbits, false)
1125 }
1126
1127
1128 func immU(as obj.As, imm int64, nbits uint) uint32 {
1129 if err := immUFits(imm, nbits); err != nil {
1130 panic(fmt.Sprintf("%v: %v", as, err))
1131 }
1132 return uint32(imm) & ((1 << nbits) - 1)
1133 }
1134
1135 func wantImmU(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
1136 if err := immUFits(imm, nbits); err != nil {
1137 ctxt.Diag("%v: %v", ins, err)
1138 }
1139 }
1140
1141 func wantReg(ctxt *obj.Link, ins *instruction, pos string, descr string, r, min, max uint32) {
1142 if r < min || r > max {
1143 var suffix string
1144 if r != obj.REG_NONE {
1145 suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r)))
1146 }
1147 ctxt.Diag("%v: expected %s register in %s position%s", ins, descr, pos, suffix)
1148 }
1149 }
1150
1151 func wantNoneReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1152 if r != obj.REG_NONE {
1153 ctxt.Diag("%v: expected no register in %s but got register %s", ins, pos, RegName(int(r)))
1154 }
1155 }
1156
1157
1158 func wantIntReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1159 wantReg(ctxt, ins, pos, "integer", r, REG_X0, REG_X31)
1160 }
1161
1162
1163 func wantFloatReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1164 wantReg(ctxt, ins, pos, "float", r, REG_F0, REG_F31)
1165 }
1166
1167
1168 func wantVectorReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1169 wantReg(ctxt, ins, pos, "vector", r, REG_V0, REG_V31)
1170 }
1171
1172
1173 func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) {
1174 if err := immEven(offset); err != nil {
1175 ctxt.Diag("%v: %v", ins, err)
1176 }
1177 }
1178
1179 func validateRII(ctxt *obj.Link, ins *instruction) {
1180 wantIntReg(ctxt, ins, "rd", ins.rd)
1181 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1182 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1183 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1184 }
1185
1186 func validateRIII(ctxt *obj.Link, ins *instruction) {
1187 wantIntReg(ctxt, ins, "rd", ins.rd)
1188 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1189 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1190 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1191 }
1192
1193 func validateRFFF(ctxt *obj.Link, ins *instruction) {
1194 wantFloatReg(ctxt, ins, "rd", ins.rd)
1195 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1196 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1197 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1198 }
1199
1200 func validateRFFFF(ctxt *obj.Link, ins *instruction) {
1201 wantFloatReg(ctxt, ins, "rd", ins.rd)
1202 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1203 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1204 wantFloatReg(ctxt, ins, "rs3", ins.rs3)
1205 }
1206
1207 func validateRFFI(ctxt *obj.Link, ins *instruction) {
1208 wantIntReg(ctxt, ins, "rd", ins.rd)
1209 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1210 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1211 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1212 }
1213
1214 func validateRFI(ctxt *obj.Link, ins *instruction) {
1215 wantIntReg(ctxt, ins, "rd", ins.rd)
1216 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1217 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1218 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1219 }
1220
1221 func validateRFV(ctxt *obj.Link, ins *instruction) {
1222 wantVectorReg(ctxt, ins, "vd", ins.rd)
1223 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1224 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1225 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1226 }
1227
1228 func validateRFF(ctxt *obj.Link, ins *instruction) {
1229 wantFloatReg(ctxt, ins, "rd", ins.rd)
1230 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1231 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1232 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1233 }
1234
1235 func validateRIF(ctxt *obj.Link, ins *instruction) {
1236 wantFloatReg(ctxt, ins, "rd", ins.rd)
1237 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1238 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1239 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1240 }
1241
1242 func validateRIV(ctxt *obj.Link, ins *instruction) {
1243 wantVectorReg(ctxt, ins, "vd", ins.rd)
1244 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1245 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1246 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1247 }
1248
1249 func validateRVF(ctxt *obj.Link, ins *instruction) {
1250 wantFloatReg(ctxt, ins, "rd", ins.rd)
1251 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1252 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1253 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1254 }
1255
1256 func validateRVFV(ctxt *obj.Link, ins *instruction) {
1257 wantVectorReg(ctxt, ins, "vd", ins.rd)
1258 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1259 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1260 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1261 }
1262
1263 func validateRVI(ctxt *obj.Link, ins *instruction) {
1264 wantIntReg(ctxt, ins, "rd", ins.rd)
1265 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1266 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1267 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1268 }
1269
1270 func validateRVIV(ctxt *obj.Link, ins *instruction) {
1271 wantVectorReg(ctxt, ins, "vd", ins.rd)
1272 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1273 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1274 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1275 }
1276
1277 func validateRVV(ctxt *obj.Link, ins *instruction) {
1278 wantVectorReg(ctxt, ins, "vd", ins.rd)
1279 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1280 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1281 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1282 }
1283
1284 func validateRVVi(ctxt *obj.Link, ins *instruction) {
1285 wantImmI(ctxt, ins, ins.imm, 5)
1286 wantVectorReg(ctxt, ins, "vd", ins.rd)
1287 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1288 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1289 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1290 }
1291
1292 func validateRVVu(ctxt *obj.Link, ins *instruction) {
1293 wantImmU(ctxt, ins, ins.imm, 5)
1294 wantVectorReg(ctxt, ins, "vd", ins.rd)
1295 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1296 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1297 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1298 }
1299
1300 func validateRVVV(ctxt *obj.Link, ins *instruction) {
1301 wantVectorReg(ctxt, ins, "vd", ins.rd)
1302 wantVectorReg(ctxt, ins, "vs1", ins.rs1)
1303 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1304 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1305 }
1306
1307 func validateIII(ctxt *obj.Link, ins *instruction) {
1308 wantImmI(ctxt, ins, ins.imm, 12)
1309 wantIntReg(ctxt, ins, "rd", ins.rd)
1310 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1311 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1312 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1313 }
1314
1315 func validateIF(ctxt *obj.Link, ins *instruction) {
1316 wantImmI(ctxt, ins, ins.imm, 12)
1317 wantFloatReg(ctxt, ins, "rd", ins.rd)
1318 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1319 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1320 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1321 }
1322
1323 func validateIV(ctxt *obj.Link, ins *instruction) {
1324 wantVectorReg(ctxt, ins, "vd", ins.rd)
1325 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1326 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1327 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1328 }
1329
1330 func validateIIIV(ctxt *obj.Link, ins *instruction) {
1331 wantVectorReg(ctxt, ins, "vd", ins.rd)
1332 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1333 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1334 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1335 }
1336
1337 func validateIVIV(ctxt *obj.Link, ins *instruction) {
1338 wantVectorReg(ctxt, ins, "vd", ins.rd)
1339 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1340 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1341 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1342 }
1343
1344 func validateSI(ctxt *obj.Link, ins *instruction) {
1345 wantImmI(ctxt, ins, ins.imm, 12)
1346 wantIntReg(ctxt, ins, "rd", ins.rd)
1347 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1348 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1349 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1350 }
1351
1352 func validateSF(ctxt *obj.Link, ins *instruction) {
1353 wantImmI(ctxt, ins, ins.imm, 12)
1354 wantIntReg(ctxt, ins, "rd", ins.rd)
1355 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1356 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1357 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1358 }
1359
1360 func validateSV(ctxt *obj.Link, ins *instruction) {
1361 wantIntReg(ctxt, ins, "rd", ins.rd)
1362 wantVectorReg(ctxt, ins, "vs1", ins.rs1)
1363 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1364 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1365 }
1366
1367 func validateSVII(ctxt *obj.Link, ins *instruction) {
1368 wantVectorReg(ctxt, ins, "vd", ins.rd)
1369 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1370 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1371 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1372 }
1373
1374 func validateSVIV(ctxt *obj.Link, ins *instruction) {
1375 wantVectorReg(ctxt, ins, "vd", ins.rd)
1376 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1377 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1378 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1379 }
1380
1381 func validateB(ctxt *obj.Link, ins *instruction) {
1382
1383
1384 wantEvenOffset(ctxt, ins, ins.imm)
1385 wantImmI(ctxt, ins, ins.imm, 13)
1386 wantNoneReg(ctxt, ins, "rd", ins.rd)
1387 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1388 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1389 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1390 }
1391
1392 func validateU(ctxt *obj.Link, ins *instruction) {
1393 wantImmI(ctxt, ins, ins.imm, 20)
1394 wantIntReg(ctxt, ins, "rd", ins.rd)
1395 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1396 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1397 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1398 }
1399
1400 func validateJ(ctxt *obj.Link, ins *instruction) {
1401
1402
1403 wantEvenOffset(ctxt, ins, ins.imm)
1404 wantImmI(ctxt, ins, ins.imm, 21)
1405 wantIntReg(ctxt, ins, "rd", ins.rd)
1406 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1407 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1408 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1409 }
1410
1411 func validateVsetvli(ctxt *obj.Link, ins *instruction) {
1412 wantImmU(ctxt, ins, ins.imm, 11)
1413 wantIntReg(ctxt, ins, "rd", ins.rd)
1414 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1415 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1416 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1417 }
1418
1419 func validateVsetivli(ctxt *obj.Link, ins *instruction) {
1420 wantImmU(ctxt, ins, ins.imm, 10)
1421 wantIntReg(ctxt, ins, "rd", ins.rd)
1422 wantImmU(ctxt, ins, int64(ins.rs1), 5)
1423 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1424 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1425 }
1426
1427 func validateVsetvl(ctxt *obj.Link, ins *instruction) {
1428 wantIntReg(ctxt, ins, "rd", ins.rd)
1429 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1430 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1431 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1432 }
1433
1434 func validateRaw(ctxt *obj.Link, ins *instruction) {
1435
1436
1437 if ins.imm < 0 || 1<<32 <= ins.imm {
1438 ctxt.Diag("%v: immediate %d in raw position cannot be larger than 32 bits", ins.as, ins.imm)
1439 }
1440 }
1441
1442
1443
1444 func extractBitAndShift(imm uint32, bit, pos int) uint32 {
1445 return ((imm >> bit) & 1) << pos
1446 }
1447
1448
1449 func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
1450 enc := encode(as)
1451 if enc == nil {
1452 panic("encodeR: could not encode instruction")
1453 }
1454 if enc.rs1 != 0 && rs1 != 0 {
1455 panic("encodeR: instruction uses rs1, but rs1 is nonzero")
1456 }
1457 if enc.rs2 != 0 && rs2 != 0 {
1458 panic("encodeR: instruction uses rs2, but rs2 is nonzero")
1459 }
1460 funct3 |= enc.funct3
1461 funct7 |= enc.funct7
1462 rs1 |= enc.rs1
1463 rs2 |= enc.rs2
1464 return funct7<<25 | rs2<<20 | rs1<<15 | funct3<<12 | rd<<7 | enc.opcode
1465 }
1466
1467
1468 func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
1469 enc := encode(as)
1470 if enc == nil {
1471 panic("encodeR4: could not encode instruction")
1472 }
1473 if enc.rs2 != 0 {
1474 panic("encodeR4: instruction uses rs2")
1475 }
1476 funct2 |= enc.funct7
1477 if funct2&^3 != 0 {
1478 panic("encodeR4: funct2 requires more than 2 bits")
1479 }
1480 return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
1481 }
1482
1483 func encodeRII(ins *instruction) uint32 {
1484 return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7)
1485 }
1486
1487 func encodeRIII(ins *instruction) uint32 {
1488 return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1489 }
1490
1491 func encodeRFFF(ins *instruction) uint32 {
1492 return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
1493 }
1494
1495 func encodeRFFFF(ins *instruction) uint32 {
1496 return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7)
1497 }
1498
1499 func encodeRFFI(ins *instruction) uint32 {
1500 return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1501 }
1502
1503 func encodeRFI(ins *instruction) uint32 {
1504 return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
1505 }
1506
1507 func encodeRFF(ins *instruction) uint32 {
1508 return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
1509 }
1510
1511 func encodeRFV(ins *instruction) uint32 {
1512 return encodeR(ins.as, regF(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
1513 }
1514
1515 func encodeRIF(ins *instruction) uint32 {
1516 return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
1517 }
1518
1519 func encodeRIV(ins *instruction) uint32 {
1520 return encodeR(ins.as, regI(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
1521 }
1522
1523 func encodeRVF(ins *instruction) uint32 {
1524 return encodeR(ins.as, 0, regV(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
1525 }
1526
1527 func encodeRVFV(ins *instruction) uint32 {
1528 return encodeR(ins.as, regF(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1529 }
1530
1531 func encodeRVI(ins *instruction) uint32 {
1532 return encodeR(ins.as, 0, regV(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1533 }
1534
1535 func encodeRVIV(ins *instruction) uint32 {
1536 return encodeR(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1537 }
1538
1539 func encodeRVV(ins *instruction) uint32 {
1540 return encodeR(ins.as, 0, regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1541 }
1542
1543 func encodeRVVi(ins *instruction) uint32 {
1544 return encodeR(ins.as, immI(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1545 }
1546
1547 func encodeRVVu(ins *instruction) uint32 {
1548 return encodeR(ins.as, immU(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1549 }
1550
1551 func encodeRVVV(ins *instruction) uint32 {
1552 return encodeR(ins.as, regV(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1553 }
1554
1555
1556 func encodeI(as obj.As, rs1, rd, imm, funct7 uint32) uint32 {
1557 enc := encode(as)
1558 if enc == nil {
1559 panic("encodeI: could not encode instruction")
1560 }
1561 imm |= uint32(enc.csr)
1562 return funct7<<25 | imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
1563 }
1564
1565 func encodeIII(ins *instruction) uint32 {
1566 return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm), 0)
1567 }
1568
1569 func encodeIF(ins *instruction) uint32 {
1570 return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm), 0)
1571 }
1572
1573 func encodeIV(ins *instruction) uint32 {
1574 return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), uint32(ins.imm), ins.funct7)
1575 }
1576
1577 func encodeIIIV(ins *instruction) uint32 {
1578 return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regI(ins.rs2), ins.funct7)
1579 }
1580
1581 func encodeIVIV(ins *instruction) uint32 {
1582 return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regV(ins.rs2), ins.funct7)
1583 }
1584
1585
1586 func encodeS(as obj.As, rs1, rs2, imm, funct7 uint32) uint32 {
1587 enc := encode(as)
1588 if enc == nil {
1589 panic("encodeS: could not encode instruction")
1590 }
1591 if enc.rs2 != 0 && rs2 != 0 {
1592 panic("encodeS: instruction uses rs2, but rs2 was nonzero")
1593 }
1594 rs2 |= enc.rs2
1595 imm |= uint32(enc.csr) &^ 0x1f
1596 return funct7<<25 | (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
1597 }
1598
1599 func encodeSI(ins *instruction) uint32 {
1600 return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm), 0)
1601 }
1602
1603 func encodeSF(ins *instruction) uint32 {
1604 return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm), 0)
1605 }
1606
1607 func encodeSV(ins *instruction) uint32 {
1608 return encodeS(ins.as, regI(ins.rd), 0, regV(ins.rs1), ins.funct7)
1609 }
1610
1611 func encodeSVII(ins *instruction) uint32 {
1612 return encodeS(ins.as, regI(ins.rs1), regI(ins.rs2), regV(ins.rd), ins.funct7)
1613 }
1614
1615 func encodeSVIV(ins *instruction) uint32 {
1616 return encodeS(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct7)
1617 }
1618
1619
1620 func encodeBImmediate(imm uint32) uint32 {
1621 return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
1622 }
1623
1624
1625 func encodeB(ins *instruction) uint32 {
1626 imm := immI(ins.as, ins.imm, 13)
1627 rs2 := regI(ins.rs1)
1628 rs1 := regI(ins.rs2)
1629 enc := encode(ins.as)
1630 if enc == nil {
1631 panic("encodeB: could not encode instruction")
1632 }
1633 return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
1634 }
1635
1636
1637 func encodeU(ins *instruction) uint32 {
1638
1639
1640
1641
1642 imm := immI(ins.as, ins.imm, 20)
1643 rd := regI(ins.rd)
1644 enc := encode(ins.as)
1645 if enc == nil {
1646 panic("encodeU: could not encode instruction")
1647 }
1648 return imm<<12 | rd<<7 | enc.opcode
1649 }
1650
1651
1652 func encodeJImmediate(imm uint32) uint32 {
1653 return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12
1654 }
1655
1656
1657 func encodeJ(ins *instruction) uint32 {
1658 imm := immI(ins.as, ins.imm, 21)
1659 rd := regI(ins.rd)
1660 enc := encode(ins.as)
1661 if enc == nil {
1662 panic("encodeJ: could not encode instruction")
1663 }
1664 return encodeJImmediate(imm) | rd<<7 | enc.opcode
1665 }
1666
1667
1668 func encodeCBImmediate(imm uint32) uint32 {
1669
1670 bits := extractBitAndShift(imm, 8, 7)
1671 bits |= extractBitAndShift(imm, 4, 6)
1672 bits |= extractBitAndShift(imm, 3, 5)
1673 bits |= extractBitAndShift(imm, 7, 4)
1674 bits |= extractBitAndShift(imm, 6, 3)
1675 bits |= extractBitAndShift(imm, 2, 2)
1676 bits |= extractBitAndShift(imm, 1, 1)
1677 bits |= extractBitAndShift(imm, 5, 0)
1678 return (bits>>5)<<10 | (bits&0x1f)<<2
1679 }
1680
1681
1682 func encodeCJImmediate(imm uint32) uint32 {
1683
1684 bits := extractBitAndShift(imm, 11, 10)
1685 bits |= extractBitAndShift(imm, 4, 9)
1686 bits |= extractBitAndShift(imm, 9, 8)
1687 bits |= extractBitAndShift(imm, 8, 7)
1688 bits |= extractBitAndShift(imm, 10, 6)
1689 bits |= extractBitAndShift(imm, 6, 5)
1690 bits |= extractBitAndShift(imm, 7, 4)
1691 bits |= extractBitAndShift(imm, 3, 3)
1692 bits |= extractBitAndShift(imm, 2, 2)
1693 bits |= extractBitAndShift(imm, 1, 1)
1694 bits |= extractBitAndShift(imm, 5, 0)
1695 return bits << 2
1696 }
1697
1698 func encodeVset(as obj.As, rs1, rs2, rd uint32) uint32 {
1699 enc := encode(as)
1700 if enc == nil {
1701 panic("encodeVset: could not encode instruction")
1702 }
1703 return enc.funct7<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
1704 }
1705
1706 func encodeVsetvli(ins *instruction) uint32 {
1707 vtype := immU(ins.as, ins.imm, 11)
1708 return encodeVset(ins.as, regI(ins.rs1), vtype, regI(ins.rd))
1709 }
1710
1711 func encodeVsetivli(ins *instruction) uint32 {
1712 vtype := immU(ins.as, ins.imm, 10)
1713 avl := immU(ins.as, int64(ins.rs1), 5)
1714 return encodeVset(ins.as, avl, vtype, regI(ins.rd))
1715 }
1716
1717 func encodeVsetvl(ins *instruction) uint32 {
1718 return encodeVset(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd))
1719 }
1720
1721 func encodeRawIns(ins *instruction) uint32 {
1722
1723
1724 if ins.imm < 0 || 1<<32 <= ins.imm {
1725 panic(fmt.Sprintf("immediate %d cannot fit in 32 bits", ins.imm))
1726 }
1727 return uint32(ins.imm)
1728 }
1729
1730 func EncodeBImmediate(imm int64) (int64, error) {
1731 if err := immIFits(imm, 13); err != nil {
1732 return 0, err
1733 }
1734 if err := immEven(imm); err != nil {
1735 return 0, err
1736 }
1737 return int64(encodeBImmediate(uint32(imm))), nil
1738 }
1739
1740 func EncodeCBImmediate(imm int64) (int64, error) {
1741 if err := immIFits(imm, 9); err != nil {
1742 return 0, err
1743 }
1744 if err := immEven(imm); err != nil {
1745 return 0, err
1746 }
1747 return int64(encodeCBImmediate(uint32(imm))), nil
1748 }
1749
1750 func EncodeCJImmediate(imm int64) (int64, error) {
1751 if err := immIFits(imm, 12); err != nil {
1752 return 0, err
1753 }
1754 if err := immEven(imm); err != nil {
1755 return 0, err
1756 }
1757 return int64(encodeCJImmediate(uint32(imm))), nil
1758 }
1759
1760 func EncodeIImmediate(imm int64) (int64, error) {
1761 if err := immIFits(imm, 12); err != nil {
1762 return 0, err
1763 }
1764 return imm << 20, nil
1765 }
1766
1767 func EncodeJImmediate(imm int64) (int64, error) {
1768 if err := immIFits(imm, 21); err != nil {
1769 return 0, err
1770 }
1771 if err := immEven(imm); err != nil {
1772 return 0, err
1773 }
1774 return int64(encodeJImmediate(uint32(imm))), nil
1775 }
1776
1777 func EncodeSImmediate(imm int64) (int64, error) {
1778 if err := immIFits(imm, 12); err != nil {
1779 return 0, err
1780 }
1781 return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
1782 }
1783
1784 func EncodeUImmediate(imm int64) (int64, error) {
1785 if err := immIFits(imm, 20); err != nil {
1786 return 0, err
1787 }
1788 return imm << 12, nil
1789 }
1790
1791 func EncodeVectorType(vsew, vlmul, vtail, vmask int64) (int64, error) {
1792 vsewSO := SpecialOperand(vsew)
1793 if vsewSO < SPOP_E8 || vsewSO > SPOP_E64 {
1794 return -1, fmt.Errorf("invalid vector selected element width %q", vsewSO)
1795 }
1796 vlmulSO := SpecialOperand(vlmul)
1797 if vlmulSO < SPOP_M1 || vlmulSO > SPOP_MF8 {
1798 return -1, fmt.Errorf("invalid vector register group multiplier %q", vlmulSO)
1799 }
1800 vtailSO := SpecialOperand(vtail)
1801 if vtailSO != SPOP_TA && vtailSO != SPOP_TU {
1802 return -1, fmt.Errorf("invalid vector tail policy %q", vtailSO)
1803 }
1804 vmaskSO := SpecialOperand(vmask)
1805 if vmaskSO != SPOP_MA && vmaskSO != SPOP_MU {
1806 return -1, fmt.Errorf("invalid vector mask policy %q", vmaskSO)
1807 }
1808 vtype := vmaskSO.encode()<<7 | vtailSO.encode()<<6 | vsewSO.encode()<<3 | vlmulSO.encode()
1809 return int64(vtype), nil
1810 }
1811
1812 type encoding struct {
1813 encode func(*instruction) uint32
1814 validate func(*obj.Link, *instruction)
1815 length int
1816 }
1817
1818 var (
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830 rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
1831 rIIEncoding = encoding{encode: encodeRII, validate: validateRII, length: 4}
1832 rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
1833 rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
1834 rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
1835 rFIEncoding = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
1836 rFVEncoding = encoding{encode: encodeRFV, validate: validateRFV, length: 4}
1837 rIFEncoding = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
1838 rIVEncoding = encoding{encode: encodeRIV, validate: validateRIV, length: 4}
1839 rFFEncoding = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
1840 rVFEncoding = encoding{encode: encodeRVF, validate: validateRVF, length: 4}
1841 rVFVEncoding = encoding{encode: encodeRVFV, validate: validateRVFV, length: 4}
1842 rVIEncoding = encoding{encode: encodeRVI, validate: validateRVI, length: 4}
1843 rVIVEncoding = encoding{encode: encodeRVIV, validate: validateRVIV, length: 4}
1844 rVVEncoding = encoding{encode: encodeRVV, validate: validateRVV, length: 4}
1845 rVViEncoding = encoding{encode: encodeRVVi, validate: validateRVVi, length: 4}
1846 rVVuEncoding = encoding{encode: encodeRVVu, validate: validateRVVu, length: 4}
1847 rVVVEncoding = encoding{encode: encodeRVVV, validate: validateRVVV, length: 4}
1848
1849 iIIEncoding = encoding{encode: encodeIII, validate: validateIII, length: 4}
1850 iFEncoding = encoding{encode: encodeIF, validate: validateIF, length: 4}
1851 iVEncoding = encoding{encode: encodeIV, validate: validateIV, length: 4}
1852 iIIVEncoding = encoding{encode: encodeIIIV, validate: validateIIIV, length: 4}
1853 iVIVEncoding = encoding{encode: encodeIVIV, validate: validateIVIV, length: 4}
1854
1855 sIEncoding = encoding{encode: encodeSI, validate: validateSI, length: 4}
1856 sFEncoding = encoding{encode: encodeSF, validate: validateSF, length: 4}
1857 sVEncoding = encoding{encode: encodeSV, validate: validateSV, length: 4}
1858 sVIIEncoding = encoding{encode: encodeSVII, validate: validateSVII, length: 4}
1859 sVIVEncoding = encoding{encode: encodeSVIV, validate: validateSVIV, length: 4}
1860
1861 bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
1862 uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
1863 jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
1864
1865
1866 vsetvliEncoding = encoding{encode: encodeVsetvli, validate: validateVsetvli, length: 4}
1867 vsetivliEncoding = encoding{encode: encodeVsetivli, validate: validateVsetivli, length: 4}
1868 vsetvlEncoding = encoding{encode: encodeVsetvl, validate: validateVsetvl, length: 4}
1869
1870
1871 rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
1872
1873
1874 pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
1875
1876
1877
1878 badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
1879 )
1880
1881
1882 type instructionData struct {
1883 enc encoding
1884 immForm obj.As
1885 ternary bool
1886 }
1887
1888
1889
1890
1891 var instructions = [ALAST & obj.AMask]instructionData{
1892
1893
1894
1895
1896
1897 AADDI & obj.AMask: {enc: iIIEncoding, ternary: true},
1898 ASLTI & obj.AMask: {enc: iIIEncoding, ternary: true},
1899 ASLTIU & obj.AMask: {enc: iIIEncoding, ternary: true},
1900 AANDI & obj.AMask: {enc: iIIEncoding, ternary: true},
1901 AORI & obj.AMask: {enc: iIIEncoding, ternary: true},
1902 AXORI & obj.AMask: {enc: iIIEncoding, ternary: true},
1903 ASLLI & obj.AMask: {enc: iIIEncoding, ternary: true},
1904 ASRLI & obj.AMask: {enc: iIIEncoding, ternary: true},
1905 ASRAI & obj.AMask: {enc: iIIEncoding, ternary: true},
1906 ALUI & obj.AMask: {enc: uEncoding},
1907 AAUIPC & obj.AMask: {enc: uEncoding},
1908 AADD & obj.AMask: {enc: rIIIEncoding, immForm: AADDI, ternary: true},
1909 ASLT & obj.AMask: {enc: rIIIEncoding, immForm: ASLTI, ternary: true},
1910 ASLTU & obj.AMask: {enc: rIIIEncoding, immForm: ASLTIU, ternary: true},
1911 AAND & obj.AMask: {enc: rIIIEncoding, immForm: AANDI, ternary: true},
1912 AOR & obj.AMask: {enc: rIIIEncoding, immForm: AORI, ternary: true},
1913 AXOR & obj.AMask: {enc: rIIIEncoding, immForm: AXORI, ternary: true},
1914 ASLL & obj.AMask: {enc: rIIIEncoding, immForm: ASLLI, ternary: true},
1915 ASRL & obj.AMask: {enc: rIIIEncoding, immForm: ASRLI, ternary: true},
1916 ASUB & obj.AMask: {enc: rIIIEncoding, ternary: true},
1917 ASRA & obj.AMask: {enc: rIIIEncoding, immForm: ASRAI, ternary: true},
1918
1919
1920 AJAL & obj.AMask: {enc: jEncoding},
1921 AJALR & obj.AMask: {enc: iIIEncoding},
1922 ABEQ & obj.AMask: {enc: bEncoding},
1923 ABNE & obj.AMask: {enc: bEncoding},
1924 ABLT & obj.AMask: {enc: bEncoding},
1925 ABLTU & obj.AMask: {enc: bEncoding},
1926 ABGE & obj.AMask: {enc: bEncoding},
1927 ABGEU & obj.AMask: {enc: bEncoding},
1928
1929
1930 ALW & obj.AMask: {enc: iIIEncoding},
1931 ALWU & obj.AMask: {enc: iIIEncoding},
1932 ALH & obj.AMask: {enc: iIIEncoding},
1933 ALHU & obj.AMask: {enc: iIIEncoding},
1934 ALB & obj.AMask: {enc: iIIEncoding},
1935 ALBU & obj.AMask: {enc: iIIEncoding},
1936 ASW & obj.AMask: {enc: sIEncoding},
1937 ASH & obj.AMask: {enc: sIEncoding},
1938 ASB & obj.AMask: {enc: sIEncoding},
1939
1940
1941 AFENCE & obj.AMask: {enc: iIIEncoding},
1942
1943
1944 AADDIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1945 ASLLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1946 ASRLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1947 ASRAIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1948 AADDW & obj.AMask: {enc: rIIIEncoding, immForm: AADDIW, ternary: true},
1949 ASLLW & obj.AMask: {enc: rIIIEncoding, immForm: ASLLIW, ternary: true},
1950 ASRLW & obj.AMask: {enc: rIIIEncoding, immForm: ASRLIW, ternary: true},
1951 ASUBW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1952 ASRAW & obj.AMask: {enc: rIIIEncoding, immForm: ASRAIW, ternary: true},
1953
1954
1955 ALD & obj.AMask: {enc: iIIEncoding},
1956 ASD & obj.AMask: {enc: sIEncoding},
1957
1958
1959 ACSRRS & obj.AMask: {enc: iIIEncoding},
1960
1961
1962 AMUL & obj.AMask: {enc: rIIIEncoding, ternary: true},
1963 AMULH & obj.AMask: {enc: rIIIEncoding, ternary: true},
1964 AMULHU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1965 AMULHSU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1966 AMULW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1967 ADIV & obj.AMask: {enc: rIIIEncoding, ternary: true},
1968 ADIVU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1969 AREM & obj.AMask: {enc: rIIIEncoding, ternary: true},
1970 AREMU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1971 ADIVW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1972 ADIVUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1973 AREMW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1974 AREMUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1975
1976
1977 ALRW & obj.AMask: {enc: rIIIEncoding},
1978 ALRD & obj.AMask: {enc: rIIIEncoding},
1979 ASCW & obj.AMask: {enc: rIIIEncoding},
1980 ASCD & obj.AMask: {enc: rIIIEncoding},
1981
1982
1983 AAMOSWAPW & obj.AMask: {enc: rIIIEncoding},
1984 AAMOSWAPD & obj.AMask: {enc: rIIIEncoding},
1985 AAMOADDW & obj.AMask: {enc: rIIIEncoding},
1986 AAMOADDD & obj.AMask: {enc: rIIIEncoding},
1987 AAMOANDW & obj.AMask: {enc: rIIIEncoding},
1988 AAMOANDD & obj.AMask: {enc: rIIIEncoding},
1989 AAMOORW & obj.AMask: {enc: rIIIEncoding},
1990 AAMOORD & obj.AMask: {enc: rIIIEncoding},
1991 AAMOXORW & obj.AMask: {enc: rIIIEncoding},
1992 AAMOXORD & obj.AMask: {enc: rIIIEncoding},
1993 AAMOMAXW & obj.AMask: {enc: rIIIEncoding},
1994 AAMOMAXD & obj.AMask: {enc: rIIIEncoding},
1995 AAMOMAXUW & obj.AMask: {enc: rIIIEncoding},
1996 AAMOMAXUD & obj.AMask: {enc: rIIIEncoding},
1997 AAMOMINW & obj.AMask: {enc: rIIIEncoding},
1998 AAMOMIND & obj.AMask: {enc: rIIIEncoding},
1999 AAMOMINUW & obj.AMask: {enc: rIIIEncoding},
2000 AAMOMINUD & obj.AMask: {enc: rIIIEncoding},
2001
2002
2003 AFLW & obj.AMask: {enc: iFEncoding},
2004 AFSW & obj.AMask: {enc: sFEncoding},
2005
2006
2007 AFADDS & obj.AMask: {enc: rFFFEncoding},
2008 AFSUBS & obj.AMask: {enc: rFFFEncoding},
2009 AFMULS & obj.AMask: {enc: rFFFEncoding},
2010 AFDIVS & obj.AMask: {enc: rFFFEncoding},
2011 AFMINS & obj.AMask: {enc: rFFFEncoding},
2012 AFMAXS & obj.AMask: {enc: rFFFEncoding},
2013 AFSQRTS & obj.AMask: {enc: rFFFEncoding},
2014 AFMADDS & obj.AMask: {enc: rFFFFEncoding},
2015 AFMSUBS & obj.AMask: {enc: rFFFFEncoding},
2016 AFNMSUBS & obj.AMask: {enc: rFFFFEncoding},
2017 AFNMADDS & obj.AMask: {enc: rFFFFEncoding},
2018
2019
2020 AFCVTWS & obj.AMask: {enc: rFIEncoding},
2021 AFCVTLS & obj.AMask: {enc: rFIEncoding},
2022 AFCVTSW & obj.AMask: {enc: rIFEncoding},
2023 AFCVTSL & obj.AMask: {enc: rIFEncoding},
2024 AFCVTWUS & obj.AMask: {enc: rFIEncoding},
2025 AFCVTLUS & obj.AMask: {enc: rFIEncoding},
2026 AFCVTSWU & obj.AMask: {enc: rIFEncoding},
2027 AFCVTSLU & obj.AMask: {enc: rIFEncoding},
2028 AFSGNJS & obj.AMask: {enc: rFFFEncoding},
2029 AFSGNJNS & obj.AMask: {enc: rFFFEncoding},
2030 AFSGNJXS & obj.AMask: {enc: rFFFEncoding},
2031 AFMVXW & obj.AMask: {enc: rFIEncoding},
2032 AFMVWX & obj.AMask: {enc: rIFEncoding},
2033
2034
2035 AFEQS & obj.AMask: {enc: rFFIEncoding},
2036 AFLTS & obj.AMask: {enc: rFFIEncoding},
2037 AFLES & obj.AMask: {enc: rFFIEncoding},
2038
2039
2040 AFCLASSS & obj.AMask: {enc: rFIEncoding},
2041
2042
2043 AFLD & obj.AMask: {enc: iFEncoding},
2044 AFSD & obj.AMask: {enc: sFEncoding},
2045
2046
2047 AFADDD & obj.AMask: {enc: rFFFEncoding},
2048 AFSUBD & obj.AMask: {enc: rFFFEncoding},
2049 AFMULD & obj.AMask: {enc: rFFFEncoding},
2050 AFDIVD & obj.AMask: {enc: rFFFEncoding},
2051 AFMIND & obj.AMask: {enc: rFFFEncoding},
2052 AFMAXD & obj.AMask: {enc: rFFFEncoding},
2053 AFSQRTD & obj.AMask: {enc: rFFFEncoding},
2054 AFMADDD & obj.AMask: {enc: rFFFFEncoding},
2055 AFMSUBD & obj.AMask: {enc: rFFFFEncoding},
2056 AFNMSUBD & obj.AMask: {enc: rFFFFEncoding},
2057 AFNMADDD & obj.AMask: {enc: rFFFFEncoding},
2058
2059
2060 AFCVTWD & obj.AMask: {enc: rFIEncoding},
2061 AFCVTLD & obj.AMask: {enc: rFIEncoding},
2062 AFCVTDW & obj.AMask: {enc: rIFEncoding},
2063 AFCVTDL & obj.AMask: {enc: rIFEncoding},
2064 AFCVTWUD & obj.AMask: {enc: rFIEncoding},
2065 AFCVTLUD & obj.AMask: {enc: rFIEncoding},
2066 AFCVTDWU & obj.AMask: {enc: rIFEncoding},
2067 AFCVTDLU & obj.AMask: {enc: rIFEncoding},
2068 AFCVTSD & obj.AMask: {enc: rFFEncoding},
2069 AFCVTDS & obj.AMask: {enc: rFFEncoding},
2070 AFSGNJD & obj.AMask: {enc: rFFFEncoding},
2071 AFSGNJND & obj.AMask: {enc: rFFFEncoding},
2072 AFSGNJXD & obj.AMask: {enc: rFFFEncoding},
2073 AFMVXD & obj.AMask: {enc: rFIEncoding},
2074 AFMVDX & obj.AMask: {enc: rIFEncoding},
2075
2076
2077 AFEQD & obj.AMask: {enc: rFFIEncoding},
2078 AFLTD & obj.AMask: {enc: rFFIEncoding},
2079 AFLED & obj.AMask: {enc: rFFIEncoding},
2080
2081
2082 AFCLASSD & obj.AMask: {enc: rFIEncoding},
2083
2084
2085
2086
2087
2088
2089 AADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2090 ASH1ADD & obj.AMask: {enc: rIIIEncoding, ternary: true},
2091 ASH1ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2092 ASH2ADD & obj.AMask: {enc: rIIIEncoding, ternary: true},
2093 ASH2ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2094 ASH3ADD & obj.AMask: {enc: rIIIEncoding, ternary: true},
2095 ASH3ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2096 ASLLIUW & obj.AMask: {enc: iIIEncoding, ternary: true},
2097
2098
2099 AANDN & obj.AMask: {enc: rIIIEncoding, ternary: true},
2100 ACLZ & obj.AMask: {enc: rIIEncoding},
2101 ACLZW & obj.AMask: {enc: rIIEncoding},
2102 ACPOP & obj.AMask: {enc: rIIEncoding},
2103 ACPOPW & obj.AMask: {enc: rIIEncoding},
2104 ACTZ & obj.AMask: {enc: rIIEncoding},
2105 ACTZW & obj.AMask: {enc: rIIEncoding},
2106 AMAX & obj.AMask: {enc: rIIIEncoding, ternary: true},
2107 AMAXU & obj.AMask: {enc: rIIIEncoding, ternary: true},
2108 AMIN & obj.AMask: {enc: rIIIEncoding, ternary: true},
2109 AMINU & obj.AMask: {enc: rIIIEncoding, ternary: true},
2110 AORN & obj.AMask: {enc: rIIIEncoding, ternary: true},
2111 ASEXTB & obj.AMask: {enc: rIIEncoding},
2112 ASEXTH & obj.AMask: {enc: rIIEncoding},
2113 AXNOR & obj.AMask: {enc: rIIIEncoding, ternary: true},
2114 AZEXTH & obj.AMask: {enc: rIIEncoding},
2115
2116
2117 AROL & obj.AMask: {enc: rIIIEncoding, ternary: true},
2118 AROLW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2119 AROR & obj.AMask: {enc: rIIIEncoding, immForm: ARORI, ternary: true},
2120 ARORI & obj.AMask: {enc: iIIEncoding, ternary: true},
2121 ARORIW & obj.AMask: {enc: iIIEncoding, ternary: true},
2122 ARORW & obj.AMask: {enc: rIIIEncoding, immForm: ARORIW, ternary: true},
2123 AORCB & obj.AMask: {enc: rIIEncoding},
2124 AREV8 & obj.AMask: {enc: rIIEncoding},
2125
2126
2127 ABCLR & obj.AMask: {enc: rIIIEncoding, immForm: ABCLRI, ternary: true},
2128 ABCLRI & obj.AMask: {enc: iIIEncoding, ternary: true},
2129 ABEXT & obj.AMask: {enc: rIIIEncoding, immForm: ABEXTI, ternary: true},
2130 ABEXTI & obj.AMask: {enc: iIIEncoding, ternary: true},
2131 ABINV & obj.AMask: {enc: rIIIEncoding, immForm: ABINVI, ternary: true},
2132 ABINVI & obj.AMask: {enc: iIIEncoding, ternary: true},
2133 ABSET & obj.AMask: {enc: rIIIEncoding, immForm: ABSETI, ternary: true},
2134 ABSETI & obj.AMask: {enc: iIIEncoding, ternary: true},
2135
2136
2137
2138
2139
2140
2141 AVSETVLI & obj.AMask: {enc: vsetvliEncoding, immForm: AVSETIVLI},
2142 AVSETIVLI & obj.AMask: {enc: vsetivliEncoding},
2143 AVSETVL & obj.AMask: {enc: vsetvlEncoding},
2144
2145
2146 AVLE8V & obj.AMask: {enc: iVEncoding},
2147 AVLE16V & obj.AMask: {enc: iVEncoding},
2148 AVLE32V & obj.AMask: {enc: iVEncoding},
2149 AVLE64V & obj.AMask: {enc: iVEncoding},
2150 AVSE8V & obj.AMask: {enc: sVEncoding},
2151 AVSE16V & obj.AMask: {enc: sVEncoding},
2152 AVSE32V & obj.AMask: {enc: sVEncoding},
2153 AVSE64V & obj.AMask: {enc: sVEncoding},
2154 AVLMV & obj.AMask: {enc: iVEncoding},
2155 AVSMV & obj.AMask: {enc: sVEncoding},
2156
2157
2158 AVLSE8V & obj.AMask: {enc: iIIVEncoding},
2159 AVLSE16V & obj.AMask: {enc: iIIVEncoding},
2160 AVLSE32V & obj.AMask: {enc: iIIVEncoding},
2161 AVLSE64V & obj.AMask: {enc: iIIVEncoding},
2162 AVSSE8V & obj.AMask: {enc: sVIIEncoding},
2163 AVSSE16V & obj.AMask: {enc: sVIIEncoding},
2164 AVSSE32V & obj.AMask: {enc: sVIIEncoding},
2165 AVSSE64V & obj.AMask: {enc: sVIIEncoding},
2166
2167
2168 AVLUXEI8V & obj.AMask: {enc: iVIVEncoding},
2169 AVLUXEI16V & obj.AMask: {enc: iVIVEncoding},
2170 AVLUXEI32V & obj.AMask: {enc: iVIVEncoding},
2171 AVLUXEI64V & obj.AMask: {enc: iVIVEncoding},
2172 AVLOXEI8V & obj.AMask: {enc: iVIVEncoding},
2173 AVLOXEI16V & obj.AMask: {enc: iVIVEncoding},
2174 AVLOXEI32V & obj.AMask: {enc: iVIVEncoding},
2175 AVLOXEI64V & obj.AMask: {enc: iVIVEncoding},
2176 AVSUXEI8V & obj.AMask: {enc: sVIVEncoding},
2177 AVSUXEI16V & obj.AMask: {enc: sVIVEncoding},
2178 AVSUXEI32V & obj.AMask: {enc: sVIVEncoding},
2179 AVSUXEI64V & obj.AMask: {enc: sVIVEncoding},
2180 AVSOXEI8V & obj.AMask: {enc: sVIVEncoding},
2181 AVSOXEI16V & obj.AMask: {enc: sVIVEncoding},
2182 AVSOXEI32V & obj.AMask: {enc: sVIVEncoding},
2183 AVSOXEI64V & obj.AMask: {enc: sVIVEncoding},
2184
2185
2186 AVL1RE8V & obj.AMask: {enc: iVEncoding},
2187 AVL1RE16V & obj.AMask: {enc: iVEncoding},
2188 AVL1RE32V & obj.AMask: {enc: iVEncoding},
2189 AVL1RE64V & obj.AMask: {enc: iVEncoding},
2190 AVL2RE8V & obj.AMask: {enc: iVEncoding},
2191 AVL2RE16V & obj.AMask: {enc: iVEncoding},
2192 AVL2RE32V & obj.AMask: {enc: iVEncoding},
2193 AVL2RE64V & obj.AMask: {enc: iVEncoding},
2194 AVL4RE8V & obj.AMask: {enc: iVEncoding},
2195 AVL4RE16V & obj.AMask: {enc: iVEncoding},
2196 AVL4RE32V & obj.AMask: {enc: iVEncoding},
2197 AVL4RE64V & obj.AMask: {enc: iVEncoding},
2198 AVL8RE8V & obj.AMask: {enc: iVEncoding},
2199 AVL8RE16V & obj.AMask: {enc: iVEncoding},
2200 AVL8RE32V & obj.AMask: {enc: iVEncoding},
2201 AVL8RE64V & obj.AMask: {enc: iVEncoding},
2202 AVS1RV & obj.AMask: {enc: sVEncoding},
2203 AVS2RV & obj.AMask: {enc: sVEncoding},
2204 AVS4RV & obj.AMask: {enc: sVEncoding},
2205 AVS8RV & obj.AMask: {enc: sVEncoding},
2206
2207
2208 AVADDVV & obj.AMask: {enc: rVVVEncoding},
2209 AVADDVX & obj.AMask: {enc: rVIVEncoding},
2210 AVADDVI & obj.AMask: {enc: rVViEncoding},
2211 AVSUBVV & obj.AMask: {enc: rVVVEncoding},
2212 AVSUBVX & obj.AMask: {enc: rVIVEncoding},
2213 AVRSUBVX & obj.AMask: {enc: rVIVEncoding},
2214 AVRSUBVI & obj.AMask: {enc: rVViEncoding},
2215
2216
2217 AVWADDUVV & obj.AMask: {enc: rVVVEncoding},
2218 AVWADDUVX & obj.AMask: {enc: rVIVEncoding},
2219 AVWSUBUVV & obj.AMask: {enc: rVVVEncoding},
2220 AVWSUBUVX & obj.AMask: {enc: rVIVEncoding},
2221 AVWADDVV & obj.AMask: {enc: rVVVEncoding},
2222 AVWADDVX & obj.AMask: {enc: rVIVEncoding},
2223 AVWSUBVV & obj.AMask: {enc: rVVVEncoding},
2224 AVWSUBVX & obj.AMask: {enc: rVIVEncoding},
2225 AVWADDUWV & obj.AMask: {enc: rVVVEncoding},
2226 AVWADDUWX & obj.AMask: {enc: rVIVEncoding},
2227 AVWSUBUWV & obj.AMask: {enc: rVVVEncoding},
2228 AVWSUBUWX & obj.AMask: {enc: rVIVEncoding},
2229 AVWADDWV & obj.AMask: {enc: rVVVEncoding},
2230 AVWADDWX & obj.AMask: {enc: rVIVEncoding},
2231 AVWSUBWV & obj.AMask: {enc: rVVVEncoding},
2232 AVWSUBWX & obj.AMask: {enc: rVIVEncoding},
2233
2234
2235 AVZEXTVF2 & obj.AMask: {enc: rVVEncoding},
2236 AVSEXTVF2 & obj.AMask: {enc: rVVEncoding},
2237 AVZEXTVF4 & obj.AMask: {enc: rVVEncoding},
2238 AVSEXTVF4 & obj.AMask: {enc: rVVEncoding},
2239 AVZEXTVF8 & obj.AMask: {enc: rVVEncoding},
2240 AVSEXTVF8 & obj.AMask: {enc: rVVEncoding},
2241
2242
2243 AVADCVVM & obj.AMask: {enc: rVVVEncoding},
2244 AVADCVXM & obj.AMask: {enc: rVIVEncoding},
2245 AVADCVIM & obj.AMask: {enc: rVViEncoding},
2246 AVMADCVVM & obj.AMask: {enc: rVVVEncoding},
2247 AVMADCVXM & obj.AMask: {enc: rVIVEncoding},
2248 AVMADCVIM & obj.AMask: {enc: rVViEncoding},
2249 AVMADCVV & obj.AMask: {enc: rVVVEncoding},
2250 AVMADCVX & obj.AMask: {enc: rVIVEncoding},
2251 AVMADCVI & obj.AMask: {enc: rVViEncoding},
2252 AVSBCVVM & obj.AMask: {enc: rVVVEncoding},
2253 AVSBCVXM & obj.AMask: {enc: rVIVEncoding},
2254 AVMSBCVVM & obj.AMask: {enc: rVVVEncoding},
2255 AVMSBCVXM & obj.AMask: {enc: rVIVEncoding},
2256 AVMSBCVV & obj.AMask: {enc: rVVVEncoding},
2257 AVMSBCVX & obj.AMask: {enc: rVIVEncoding},
2258
2259
2260 AVANDVV & obj.AMask: {enc: rVVVEncoding},
2261 AVANDVX & obj.AMask: {enc: rVIVEncoding},
2262 AVANDVI & obj.AMask: {enc: rVViEncoding},
2263 AVORVV & obj.AMask: {enc: rVVVEncoding},
2264 AVORVX & obj.AMask: {enc: rVIVEncoding},
2265 AVORVI & obj.AMask: {enc: rVViEncoding},
2266 AVXORVV & obj.AMask: {enc: rVVVEncoding},
2267 AVXORVX & obj.AMask: {enc: rVIVEncoding},
2268 AVXORVI & obj.AMask: {enc: rVViEncoding},
2269
2270
2271 AVSLLVV & obj.AMask: {enc: rVVVEncoding},
2272 AVSLLVX & obj.AMask: {enc: rVIVEncoding},
2273 AVSLLVI & obj.AMask: {enc: rVVuEncoding},
2274 AVSRLVV & obj.AMask: {enc: rVVVEncoding},
2275 AVSRLVX & obj.AMask: {enc: rVIVEncoding},
2276 AVSRLVI & obj.AMask: {enc: rVVuEncoding},
2277 AVSRAVV & obj.AMask: {enc: rVVVEncoding},
2278 AVSRAVX & obj.AMask: {enc: rVIVEncoding},
2279 AVSRAVI & obj.AMask: {enc: rVVuEncoding},
2280
2281
2282 AVNSRLWV & obj.AMask: {enc: rVVVEncoding},
2283 AVNSRLWX & obj.AMask: {enc: rVIVEncoding},
2284 AVNSRLWI & obj.AMask: {enc: rVVuEncoding},
2285 AVNSRAWV & obj.AMask: {enc: rVVVEncoding},
2286 AVNSRAWX & obj.AMask: {enc: rVIVEncoding},
2287 AVNSRAWI & obj.AMask: {enc: rVVuEncoding},
2288
2289
2290 AVMSEQVV & obj.AMask: {enc: rVVVEncoding},
2291 AVMSEQVX & obj.AMask: {enc: rVIVEncoding},
2292 AVMSEQVI & obj.AMask: {enc: rVViEncoding},
2293 AVMSNEVV & obj.AMask: {enc: rVVVEncoding},
2294 AVMSNEVX & obj.AMask: {enc: rVIVEncoding},
2295 AVMSNEVI & obj.AMask: {enc: rVViEncoding},
2296 AVMSLTUVV & obj.AMask: {enc: rVVVEncoding},
2297 AVMSLTUVX & obj.AMask: {enc: rVIVEncoding},
2298 AVMSLTVV & obj.AMask: {enc: rVVVEncoding},
2299 AVMSLTVX & obj.AMask: {enc: rVIVEncoding},
2300 AVMSLEUVV & obj.AMask: {enc: rVVVEncoding},
2301 AVMSLEUVX & obj.AMask: {enc: rVIVEncoding},
2302 AVMSLEUVI & obj.AMask: {enc: rVViEncoding},
2303 AVMSLEVV & obj.AMask: {enc: rVVVEncoding},
2304 AVMSLEVX & obj.AMask: {enc: rVIVEncoding},
2305 AVMSLEVI & obj.AMask: {enc: rVViEncoding},
2306 AVMSGTUVX & obj.AMask: {enc: rVIVEncoding},
2307 AVMSGTUVI & obj.AMask: {enc: rVViEncoding},
2308 AVMSGTVX & obj.AMask: {enc: rVIVEncoding},
2309 AVMSGTVI & obj.AMask: {enc: rVViEncoding},
2310
2311
2312 AVMINUVV & obj.AMask: {enc: rVVVEncoding},
2313 AVMINUVX & obj.AMask: {enc: rVIVEncoding},
2314 AVMINVV & obj.AMask: {enc: rVVVEncoding},
2315 AVMINVX & obj.AMask: {enc: rVIVEncoding},
2316 AVMAXUVV & obj.AMask: {enc: rVVVEncoding},
2317 AVMAXUVX & obj.AMask: {enc: rVIVEncoding},
2318 AVMAXVV & obj.AMask: {enc: rVVVEncoding},
2319 AVMAXVX & obj.AMask: {enc: rVIVEncoding},
2320
2321
2322 AVMULVV & obj.AMask: {enc: rVVVEncoding},
2323 AVMULVX & obj.AMask: {enc: rVIVEncoding},
2324 AVMULHVV & obj.AMask: {enc: rVVVEncoding},
2325 AVMULHVX & obj.AMask: {enc: rVIVEncoding},
2326 AVMULHUVV & obj.AMask: {enc: rVVVEncoding},
2327 AVMULHUVX & obj.AMask: {enc: rVIVEncoding},
2328 AVMULHSUVV & obj.AMask: {enc: rVVVEncoding},
2329 AVMULHSUVX & obj.AMask: {enc: rVIVEncoding},
2330
2331
2332 AVDIVUVV & obj.AMask: {enc: rVVVEncoding},
2333 AVDIVUVX & obj.AMask: {enc: rVIVEncoding},
2334 AVDIVVV & obj.AMask: {enc: rVVVEncoding},
2335 AVDIVVX & obj.AMask: {enc: rVIVEncoding},
2336 AVREMUVV & obj.AMask: {enc: rVVVEncoding},
2337 AVREMUVX & obj.AMask: {enc: rVIVEncoding},
2338 AVREMVV & obj.AMask: {enc: rVVVEncoding},
2339 AVREMVX & obj.AMask: {enc: rVIVEncoding},
2340
2341
2342 AVWMULVV & obj.AMask: {enc: rVVVEncoding},
2343 AVWMULVX & obj.AMask: {enc: rVIVEncoding},
2344 AVWMULUVV & obj.AMask: {enc: rVVVEncoding},
2345 AVWMULUVX & obj.AMask: {enc: rVIVEncoding},
2346 AVWMULSUVV & obj.AMask: {enc: rVVVEncoding},
2347 AVWMULSUVX & obj.AMask: {enc: rVIVEncoding},
2348
2349
2350 AVMACCVV & obj.AMask: {enc: rVVVEncoding},
2351 AVMACCVX & obj.AMask: {enc: rVIVEncoding},
2352 AVNMSACVV & obj.AMask: {enc: rVVVEncoding},
2353 AVNMSACVX & obj.AMask: {enc: rVIVEncoding},
2354 AVMADDVV & obj.AMask: {enc: rVVVEncoding},
2355 AVMADDVX & obj.AMask: {enc: rVIVEncoding},
2356 AVNMSUBVV & obj.AMask: {enc: rVVVEncoding},
2357 AVNMSUBVX & obj.AMask: {enc: rVIVEncoding},
2358
2359
2360 AVWMACCUVV & obj.AMask: {enc: rVVVEncoding},
2361 AVWMACCUVX & obj.AMask: {enc: rVIVEncoding},
2362 AVWMACCVV & obj.AMask: {enc: rVVVEncoding},
2363 AVWMACCVX & obj.AMask: {enc: rVIVEncoding},
2364 AVWMACCSUVV & obj.AMask: {enc: rVVVEncoding},
2365 AVWMACCSUVX & obj.AMask: {enc: rVIVEncoding},
2366 AVWMACCUSVX & obj.AMask: {enc: rVIVEncoding},
2367
2368
2369 AVMERGEVVM & obj.AMask: {enc: rVVVEncoding},
2370 AVMERGEVXM & obj.AMask: {enc: rVIVEncoding},
2371 AVMERGEVIM & obj.AMask: {enc: rVViEncoding},
2372
2373
2374 AVMVVV & obj.AMask: {enc: rVVVEncoding},
2375 AVMVVX & obj.AMask: {enc: rVIVEncoding},
2376 AVMVVI & obj.AMask: {enc: rVViEncoding},
2377
2378
2379 AVSADDUVV & obj.AMask: {enc: rVVVEncoding},
2380 AVSADDUVX & obj.AMask: {enc: rVIVEncoding},
2381 AVSADDUVI & obj.AMask: {enc: rVViEncoding},
2382 AVSADDVV & obj.AMask: {enc: rVVVEncoding},
2383 AVSADDVX & obj.AMask: {enc: rVIVEncoding},
2384 AVSADDVI & obj.AMask: {enc: rVViEncoding},
2385 AVSSUBUVV & obj.AMask: {enc: rVVVEncoding},
2386 AVSSUBUVX & obj.AMask: {enc: rVIVEncoding},
2387 AVSSUBVV & obj.AMask: {enc: rVVVEncoding},
2388 AVSSUBVX & obj.AMask: {enc: rVIVEncoding},
2389
2390
2391 AVAADDUVV & obj.AMask: {enc: rVVVEncoding},
2392 AVAADDUVX & obj.AMask: {enc: rVIVEncoding},
2393 AVAADDVV & obj.AMask: {enc: rVVVEncoding},
2394 AVAADDVX & obj.AMask: {enc: rVIVEncoding},
2395 AVASUBUVV & obj.AMask: {enc: rVVVEncoding},
2396 AVASUBUVX & obj.AMask: {enc: rVIVEncoding},
2397 AVASUBVV & obj.AMask: {enc: rVVVEncoding},
2398 AVASUBVX & obj.AMask: {enc: rVIVEncoding},
2399
2400
2401 AVSMULVV & obj.AMask: {enc: rVVVEncoding},
2402 AVSMULVX & obj.AMask: {enc: rVIVEncoding},
2403
2404
2405 AVSSRLVV & obj.AMask: {enc: rVVVEncoding},
2406 AVSSRLVX & obj.AMask: {enc: rVIVEncoding},
2407 AVSSRLVI & obj.AMask: {enc: rVVuEncoding},
2408 AVSSRAVV & obj.AMask: {enc: rVVVEncoding},
2409 AVSSRAVX & obj.AMask: {enc: rVIVEncoding},
2410 AVSSRAVI & obj.AMask: {enc: rVVuEncoding},
2411
2412
2413 AVNCLIPUWV & obj.AMask: {enc: rVVVEncoding},
2414 AVNCLIPUWX & obj.AMask: {enc: rVIVEncoding},
2415 AVNCLIPUWI & obj.AMask: {enc: rVVuEncoding},
2416 AVNCLIPWV & obj.AMask: {enc: rVVVEncoding},
2417 AVNCLIPWX & obj.AMask: {enc: rVIVEncoding},
2418 AVNCLIPWI & obj.AMask: {enc: rVVuEncoding},
2419
2420
2421 AVFADDVV & obj.AMask: {enc: rVVVEncoding},
2422 AVFADDVF & obj.AMask: {enc: rVFVEncoding},
2423 AVFSUBVV & obj.AMask: {enc: rVVVEncoding},
2424 AVFSUBVF & obj.AMask: {enc: rVFVEncoding},
2425 AVFRSUBVF & obj.AMask: {enc: rVFVEncoding},
2426
2427
2428 AVFWADDVV & obj.AMask: {enc: rVVVEncoding},
2429 AVFWADDVF & obj.AMask: {enc: rVFVEncoding},
2430 AVFWSUBVV & obj.AMask: {enc: rVVVEncoding},
2431 AVFWSUBVF & obj.AMask: {enc: rVFVEncoding},
2432 AVFWADDWV & obj.AMask: {enc: rVVVEncoding},
2433 AVFWADDWF & obj.AMask: {enc: rVFVEncoding},
2434 AVFWSUBWV & obj.AMask: {enc: rVVVEncoding},
2435 AVFWSUBWF & obj.AMask: {enc: rVFVEncoding},
2436
2437
2438 AVFMULVV & obj.AMask: {enc: rVVVEncoding},
2439 AVFMULVF & obj.AMask: {enc: rVFVEncoding},
2440 AVFDIVVV & obj.AMask: {enc: rVVVEncoding},
2441 AVFDIVVF & obj.AMask: {enc: rVFVEncoding},
2442 AVFRDIVVF & obj.AMask: {enc: rVFVEncoding},
2443
2444
2445 AVFWMULVV & obj.AMask: {enc: rVVVEncoding},
2446 AVFWMULVF & obj.AMask: {enc: rVFVEncoding},
2447
2448
2449 AVFMACCVV & obj.AMask: {enc: rVVVEncoding},
2450 AVFMACCVF & obj.AMask: {enc: rVFVEncoding},
2451 AVFNMACCVV & obj.AMask: {enc: rVVVEncoding},
2452 AVFNMACCVF & obj.AMask: {enc: rVFVEncoding},
2453 AVFMSACVV & obj.AMask: {enc: rVVVEncoding},
2454 AVFMSACVF & obj.AMask: {enc: rVFVEncoding},
2455 AVFNMSACVV & obj.AMask: {enc: rVVVEncoding},
2456 AVFNMSACVF & obj.AMask: {enc: rVFVEncoding},
2457 AVFMADDVV & obj.AMask: {enc: rVVVEncoding},
2458 AVFMADDVF & obj.AMask: {enc: rVFVEncoding},
2459 AVFNMADDVV & obj.AMask: {enc: rVVVEncoding},
2460 AVFNMADDVF & obj.AMask: {enc: rVFVEncoding},
2461 AVFMSUBVV & obj.AMask: {enc: rVVVEncoding},
2462 AVFMSUBVF & obj.AMask: {enc: rVFVEncoding},
2463 AVFNMSUBVV & obj.AMask: {enc: rVVVEncoding},
2464 AVFNMSUBVF & obj.AMask: {enc: rVFVEncoding},
2465
2466
2467 AVFWMACCVV & obj.AMask: {enc: rVVVEncoding},
2468 AVFWMACCVF & obj.AMask: {enc: rVFVEncoding},
2469 AVFWNMACCVV & obj.AMask: {enc: rVVVEncoding},
2470 AVFWNMACCVF & obj.AMask: {enc: rVFVEncoding},
2471 AVFWMSACVV & obj.AMask: {enc: rVVVEncoding},
2472 AVFWMSACVF & obj.AMask: {enc: rVFVEncoding},
2473 AVFWNMSACVV & obj.AMask: {enc: rVVVEncoding},
2474 AVFWNMSACVF & obj.AMask: {enc: rVFVEncoding},
2475
2476
2477 AVFSQRTV & obj.AMask: {enc: rVVEncoding},
2478
2479
2480 AVFRSQRT7V & obj.AMask: {enc: rVVEncoding},
2481
2482
2483 AVFREC7V & obj.AMask: {enc: rVVEncoding},
2484
2485
2486 AVFMINVV & obj.AMask: {enc: rVVVEncoding},
2487 AVFMINVF & obj.AMask: {enc: rVFVEncoding},
2488 AVFMAXVV & obj.AMask: {enc: rVVVEncoding},
2489 AVFMAXVF & obj.AMask: {enc: rVFVEncoding},
2490
2491
2492 AVFSGNJVV & obj.AMask: {enc: rVVVEncoding},
2493 AVFSGNJVF & obj.AMask: {enc: rVFVEncoding},
2494 AVFSGNJNVV & obj.AMask: {enc: rVVVEncoding},
2495 AVFSGNJNVF & obj.AMask: {enc: rVFVEncoding},
2496 AVFSGNJXVV & obj.AMask: {enc: rVVVEncoding},
2497 AVFSGNJXVF & obj.AMask: {enc: rVFVEncoding},
2498
2499
2500 AVMFEQVV & obj.AMask: {enc: rVVVEncoding},
2501 AVMFEQVF & obj.AMask: {enc: rVFVEncoding},
2502 AVMFNEVV & obj.AMask: {enc: rVVVEncoding},
2503 AVMFNEVF & obj.AMask: {enc: rVFVEncoding},
2504 AVMFLTVV & obj.AMask: {enc: rVVVEncoding},
2505 AVMFLTVF & obj.AMask: {enc: rVFVEncoding},
2506 AVMFLEVV & obj.AMask: {enc: rVVVEncoding},
2507 AVMFLEVF & obj.AMask: {enc: rVFVEncoding},
2508 AVMFGTVF & obj.AMask: {enc: rVFVEncoding},
2509 AVMFGEVF & obj.AMask: {enc: rVFVEncoding},
2510
2511
2512 AVFCLASSV & obj.AMask: {enc: rVVEncoding},
2513
2514
2515 AVFMERGEVFM & obj.AMask: {enc: rVFVEncoding},
2516
2517
2518 AVFMVVF & obj.AMask: {enc: rVFVEncoding},
2519
2520
2521 AVFCVTXUFV & obj.AMask: {enc: rVVEncoding},
2522 AVFCVTXFV & obj.AMask: {enc: rVVEncoding},
2523 AVFCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
2524 AVFCVTRTZXFV & obj.AMask: {enc: rVVEncoding},
2525 AVFCVTFXUV & obj.AMask: {enc: rVVEncoding},
2526 AVFCVTFXV & obj.AMask: {enc: rVVEncoding},
2527
2528
2529 AVFWCVTXUFV & obj.AMask: {enc: rVVEncoding},
2530 AVFWCVTXFV & obj.AMask: {enc: rVVEncoding},
2531 AVFWCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
2532 AVFWCVTRTZXFV & obj.AMask: {enc: rVVEncoding},
2533 AVFWCVTFXUV & obj.AMask: {enc: rVVEncoding},
2534 AVFWCVTFXV & obj.AMask: {enc: rVVEncoding},
2535 AVFWCVTFFV & obj.AMask: {enc: rVVEncoding},
2536
2537
2538 AVFNCVTXUFW & obj.AMask: {enc: rVVEncoding},
2539 AVFNCVTXFW & obj.AMask: {enc: rVVEncoding},
2540 AVFNCVTRTZXUFW & obj.AMask: {enc: rVVEncoding},
2541 AVFNCVTRTZXFW & obj.AMask: {enc: rVVEncoding},
2542 AVFNCVTFXUW & obj.AMask: {enc: rVVEncoding},
2543 AVFNCVTFXW & obj.AMask: {enc: rVVEncoding},
2544 AVFNCVTFFW & obj.AMask: {enc: rVVEncoding},
2545 AVFNCVTRODFFW & obj.AMask: {enc: rVVEncoding},
2546
2547
2548 AVREDSUMVS & obj.AMask: {enc: rVVVEncoding},
2549 AVREDMAXUVS & obj.AMask: {enc: rVVVEncoding},
2550 AVREDMAXVS & obj.AMask: {enc: rVVVEncoding},
2551 AVREDMINUVS & obj.AMask: {enc: rVVVEncoding},
2552 AVREDMINVS & obj.AMask: {enc: rVVVEncoding},
2553 AVREDANDVS & obj.AMask: {enc: rVVVEncoding},
2554 AVREDORVS & obj.AMask: {enc: rVVVEncoding},
2555 AVREDXORVS & obj.AMask: {enc: rVVVEncoding},
2556
2557
2558 AVWREDSUMUVS & obj.AMask: {enc: rVVVEncoding},
2559 AVWREDSUMVS & obj.AMask: {enc: rVVVEncoding},
2560
2561
2562 AVFREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
2563 AVFREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
2564 AVFREDMAXVS & obj.AMask: {enc: rVVVEncoding},
2565 AVFREDMINVS & obj.AMask: {enc: rVVVEncoding},
2566
2567
2568 AVFWREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
2569 AVFWREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
2570
2571
2572 AVMANDMM & obj.AMask: {enc: rVVVEncoding},
2573 AVMNANDMM & obj.AMask: {enc: rVVVEncoding},
2574 AVMANDNMM & obj.AMask: {enc: rVVVEncoding},
2575 AVMXORMM & obj.AMask: {enc: rVVVEncoding},
2576 AVMORMM & obj.AMask: {enc: rVVVEncoding},
2577 AVMNORMM & obj.AMask: {enc: rVVVEncoding},
2578 AVMORNMM & obj.AMask: {enc: rVVVEncoding},
2579 AVMXNORMM & obj.AMask: {enc: rVVVEncoding},
2580 AVCPOPM & obj.AMask: {enc: rVIEncoding},
2581 AVFIRSTM & obj.AMask: {enc: rVIEncoding},
2582 AVMSBFM & obj.AMask: {enc: rVVEncoding},
2583 AVMSIFM & obj.AMask: {enc: rVVEncoding},
2584 AVMSOFM & obj.AMask: {enc: rVVEncoding},
2585 AVIOTAM & obj.AMask: {enc: rVVEncoding},
2586 AVIDV & obj.AMask: {enc: rVVEncoding},
2587
2588
2589 AVMVXS & obj.AMask: {enc: rVIEncoding},
2590 AVMVSX & obj.AMask: {enc: rIVEncoding},
2591
2592
2593 AVFMVFS & obj.AMask: {enc: rVFEncoding},
2594 AVFMVSF & obj.AMask: {enc: rFVEncoding},
2595
2596
2597 AVSLIDEUPVX & obj.AMask: {enc: rVIVEncoding},
2598 AVSLIDEUPVI & obj.AMask: {enc: rVVuEncoding},
2599 AVSLIDEDOWNVX & obj.AMask: {enc: rVIVEncoding},
2600 AVSLIDEDOWNVI & obj.AMask: {enc: rVVuEncoding},
2601 AVSLIDE1UPVX & obj.AMask: {enc: rVIVEncoding},
2602 AVFSLIDE1UPVF & obj.AMask: {enc: rVFVEncoding},
2603 AVSLIDE1DOWNVX & obj.AMask: {enc: rVIVEncoding},
2604 AVFSLIDE1DOWNVF & obj.AMask: {enc: rVFVEncoding},
2605
2606
2607 AVRGATHERVV & obj.AMask: {enc: rVVVEncoding},
2608 AVRGATHEREI16VV & obj.AMask: {enc: rVVVEncoding},
2609 AVRGATHERVX & obj.AMask: {enc: rVIVEncoding},
2610 AVRGATHERVI & obj.AMask: {enc: rVVuEncoding},
2611
2612
2613 AVCOMPRESSVM & obj.AMask: {enc: rVVVEncoding},
2614
2615
2616 AVMV1RV & obj.AMask: {enc: rVVEncoding},
2617 AVMV2RV & obj.AMask: {enc: rVVEncoding},
2618 AVMV4RV & obj.AMask: {enc: rVVEncoding},
2619 AVMV8RV & obj.AMask: {enc: rVVEncoding},
2620
2621
2622
2623
2624
2625
2626 AECALL & obj.AMask: {enc: iIIEncoding},
2627 AEBREAK & obj.AMask: {enc: iIIEncoding},
2628
2629
2630 AWORD & obj.AMask: {enc: rawEncoding},
2631
2632
2633 obj.AFUNCDATA: {enc: pseudoOpEncoding},
2634 obj.APCDATA: {enc: pseudoOpEncoding},
2635 obj.ATEXT: {enc: pseudoOpEncoding},
2636 obj.ANOP: {enc: pseudoOpEncoding},
2637 obj.ADUFFZERO: {enc: pseudoOpEncoding},
2638 obj.ADUFFCOPY: {enc: pseudoOpEncoding},
2639 obj.APCALIGN: {enc: pseudoOpEncoding},
2640 }
2641
2642
2643 func instructionDataForAs(as obj.As) (*instructionData, error) {
2644 if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
2645 return nil, fmt.Errorf("%v is not a RISC-V instruction", as)
2646 }
2647 asi := as & obj.AMask
2648 if int(asi) >= len(instructions) {
2649 return nil, fmt.Errorf("bad RISC-V instruction %v", as)
2650 }
2651 return &instructions[asi], nil
2652 }
2653
2654
2655 func encodingForAs(as obj.As) (*encoding, error) {
2656 insData, err := instructionDataForAs(as)
2657 if err != nil {
2658 return &badEncoding, err
2659 }
2660 if insData.enc.validate == nil {
2661 return &badEncoding, fmt.Errorf("no encoding for instruction %s", as)
2662 }
2663 return &insData.enc, nil
2664 }
2665
2666
2667
2668 func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) {
2669
2670 lsh = bits.TrailingZeros64(uint64(v))
2671 c := v >> lsh
2672 if int64(int32(c)) == c {
2673 return c, lsh, 0, true
2674 }
2675
2676
2677 rsh = bits.LeadingZeros64(uint64(v))
2678 ones := bits.OnesCount64((uint64(v) >> lsh) >> 11)
2679 c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
2680 if rsh+ones+lsh+11 == 64 {
2681 if lsh > 0 || c != -1 {
2682 lsh += rsh
2683 }
2684 return c, lsh, rsh, true
2685 }
2686
2687 return 0, 0, 0, false
2688 }
2689
2690
2691
2692 func isShiftConst(v int64) bool {
2693 _, lsh, rsh, ok := splitShiftConst(v)
2694 return ok && (lsh > 0 || rsh > 0)
2695 }
2696
2697 type instruction struct {
2698 p *obj.Prog
2699 as obj.As
2700 rd uint32
2701 rs1 uint32
2702 rs2 uint32
2703 rs3 uint32
2704 imm int64
2705 funct3 uint32
2706 funct7 uint32
2707 }
2708
2709 func (ins *instruction) String() string {
2710 if ins.p == nil {
2711 return ins.as.String()
2712 }
2713 var suffix string
2714 if ins.p.As != ins.as {
2715 suffix = fmt.Sprintf(" (%v)", ins.as)
2716 }
2717 return fmt.Sprintf("%v%v", ins.p, suffix)
2718 }
2719
2720 func (ins *instruction) encode() (uint32, error) {
2721 enc, err := encodingForAs(ins.as)
2722 if err != nil {
2723 return 0, err
2724 }
2725 if enc.length <= 0 {
2726 return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
2727 }
2728 return enc.encode(ins), nil
2729 }
2730
2731 func (ins *instruction) length() int {
2732 enc, err := encodingForAs(ins.as)
2733 if err != nil {
2734 return 0
2735 }
2736 return enc.length
2737 }
2738
2739 func (ins *instruction) validate(ctxt *obj.Link) {
2740 enc, err := encodingForAs(ins.as)
2741 if err != nil {
2742 ctxt.Diag(err.Error())
2743 return
2744 }
2745 enc.validate(ctxt, ins)
2746 }
2747
2748 func (ins *instruction) usesRegTmp() bool {
2749 return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
2750 }
2751
2752
2753 func instructionForProg(p *obj.Prog) *instruction {
2754 ins := &instruction{
2755 as: p.As,
2756 rd: uint32(p.To.Reg),
2757 rs1: uint32(p.Reg),
2758 rs2: uint32(p.From.Reg),
2759 imm: p.From.Offset,
2760 }
2761 if len(p.RestArgs) == 1 {
2762 ins.rs3 = uint32(p.RestArgs[0].Reg)
2763 }
2764 return ins
2765 }
2766
2767
2768
2769
2770 func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
2771
2772 ins := instructionForProg(p)
2773 ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
2774
2775 low, high, err := Split32BitImmediate(ins.imm)
2776 if err != nil {
2777 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err)
2778 return nil
2779 }
2780 if high == 0 {
2781 return []*instruction{ins}
2782 }
2783
2784
2785
2786 if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
2787 imm0 := ins.imm / 2
2788 imm1 := ins.imm - imm0
2789
2790
2791
2792 ins.imm = imm0
2793 insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
2794 return []*instruction{ins, insADDI}
2795 }
2796
2797
2798
2799
2800 insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
2801 insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
2802 switch ins.as {
2803 case AADDI:
2804 ins.as = AADD
2805 case AANDI:
2806 ins.as = AAND
2807 case AORI:
2808 ins.as = AOR
2809 case AXORI:
2810 ins.as = AXOR
2811 default:
2812 p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
2813 return nil
2814 }
2815 ins.rs2 = REG_TMP
2816 if low == 0 {
2817 return []*instruction{insLUI, ins}
2818 }
2819 return []*instruction{insLUI, insADDIW, ins}
2820 }
2821
2822
2823
2824
2825 func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
2826 if p.From.Type != obj.TYPE_MEM {
2827 p.Ctxt.Diag("%v requires memory for source", p)
2828 return nil
2829 }
2830
2831 switch as {
2832 case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
2833 default:
2834 p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
2835 return nil
2836 }
2837
2838
2839 ins := instructionForProg(p)
2840 ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
2841 ins.imm = p.From.Offset
2842
2843 low, high, err := Split32BitImmediate(ins.imm)
2844 if err != nil {
2845 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
2846 return nil
2847 }
2848 if high == 0 {
2849 return []*instruction{ins}
2850 }
2851
2852
2853
2854
2855 insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
2856 insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
2857 ins.rs1, ins.imm = REG_TMP, low
2858
2859 return []*instruction{insLUI, insADD, ins}
2860 }
2861
2862
2863
2864
2865 func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
2866 if p.To.Type != obj.TYPE_MEM {
2867 p.Ctxt.Diag("%v requires memory for destination", p)
2868 return nil
2869 }
2870
2871 switch as {
2872 case ASW, ASH, ASB, ASD, AFSW, AFSD:
2873 default:
2874 p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
2875 return nil
2876 }
2877
2878
2879 ins := instructionForProg(p)
2880 ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
2881 ins.imm = p.To.Offset
2882
2883 low, high, err := Split32BitImmediate(ins.imm)
2884 if err != nil {
2885 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
2886 return nil
2887 }
2888 if high == 0 {
2889 return []*instruction{ins}
2890 }
2891
2892
2893
2894
2895 insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
2896 insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
2897 ins.rd, ins.imm = REG_TMP, low
2898
2899 return []*instruction{insLUI, insADD, ins}
2900 }
2901
2902 func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
2903 insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
2904
2905 var inss []*instruction
2906 if p.Ctxt.Flag_shared {
2907
2908
2909 insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
2910 insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
2911 inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
2912 } else {
2913
2914
2915
2916
2917
2918 insLUI := &instruction{as: ALUI, rd: REG_TMP}
2919 insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
2920 inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
2921 }
2922 return inss
2923 }
2924
2925 func instructionsForTLSLoad(p *obj.Prog) []*instruction {
2926 if p.From.Sym.Type != objabi.STLSBSS {
2927 p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
2928 return nil
2929 }
2930
2931 ins := instructionForProg(p)
2932 ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
2933
2934 return instructionsForTLS(p, ins)
2935 }
2936
2937 func instructionsForTLSStore(p *obj.Prog) []*instruction {
2938 if p.To.Sym.Type != objabi.STLSBSS {
2939 p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
2940 return nil
2941 }
2942
2943 ins := instructionForProg(p)
2944 ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
2945
2946 return instructionsForTLS(p, ins)
2947 }
2948
2949
2950
2951 func instructionsForMOV(p *obj.Prog) []*instruction {
2952 ins := instructionForProg(p)
2953 inss := []*instruction{ins}
2954
2955 if p.Reg != 0 {
2956 p.Ctxt.Diag("%v: illegal MOV instruction", p)
2957 return nil
2958 }
2959
2960 switch {
2961 case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
2962
2963 if p.As != AMOV {
2964 p.Ctxt.Diag("%v: unsupported constant load", p)
2965 return nil
2966 }
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989 var insSLLI, insSRLI *instruction
2990 if err := immIFits(ins.imm, 32); err != nil {
2991 if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok {
2992 ins.imm = c
2993 if lsh > 0 {
2994 insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)}
2995 }
2996 if rsh > 0 {
2997 insSRLI = &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: int64(rsh)}
2998 }
2999 }
3000 }
3001
3002 low, high, err := Split32BitImmediate(ins.imm)
3003 if err != nil {
3004 p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
3005 return nil
3006 }
3007
3008
3009 ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
3010
3011
3012 if high != 0 {
3013
3014
3015 insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
3016 inss = []*instruction{insLUI}
3017 if low != 0 {
3018 ins.as, ins.rs1 = AADDIW, ins.rd
3019 inss = append(inss, ins)
3020 }
3021 }
3022 if insSLLI != nil {
3023 inss = append(inss, insSLLI)
3024 }
3025 if insSRLI != nil {
3026 inss = append(inss, insSRLI)
3027 }
3028
3029 case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
3030 p.Ctxt.Diag("%v: constant load must target register", p)
3031 return nil
3032
3033 case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
3034
3035 switch p.As {
3036 case AMOV:
3037 ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
3038 case AMOVW:
3039 ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
3040 case AMOVBU:
3041 ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
3042 case AMOVF:
3043 ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
3044 case AMOVD:
3045 ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
3046 case AMOVB, AMOVH:
3047 if buildcfg.GORISCV64 >= 22 {
3048
3049 ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE
3050 if p.As == AMOVH {
3051 ins.as = ASEXTH
3052 }
3053 } else {
3054
3055 ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
3056 if p.As == AMOVB {
3057 ins.imm = 56
3058 } else if p.As == AMOVH {
3059 ins.imm = 48
3060 }
3061 ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
3062 inss = append(inss, ins2)
3063 }
3064 case AMOVHU, AMOVWU:
3065 if buildcfg.GORISCV64 >= 22 {
3066
3067 ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0
3068 if p.As == AMOVWU {
3069 ins.as, ins.rs2 = AADDUW, REG_ZERO
3070 }
3071 } else {
3072
3073 ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
3074 if p.As == AMOVHU {
3075 ins.imm = 48
3076 } else if p.As == AMOVWU {
3077 ins.imm = 32
3078 }
3079 ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
3080 inss = append(inss, ins2)
3081 }
3082 }
3083
3084 case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
3085
3086 switch p.From.Name {
3087 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
3088
3089 inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
3090
3091 case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF:
3092 if p.From.Sym.Type == objabi.STLSBSS {
3093 return instructionsForTLSLoad(p)
3094 }
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104 addrReg := ins.rd
3105 if addrReg < REG_X0 || addrReg > REG_X31 {
3106 addrReg = REG_TMP
3107 }
3108 insAUIPC := &instruction{as: AAUIPC, rd: addrReg}
3109 ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), addrReg, obj.REG_NONE, 0
3110 inss = []*instruction{insAUIPC, ins}
3111
3112 default:
3113 p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
3114 return nil
3115 }
3116
3117 case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
3118
3119 switch p.As {
3120 case AMOVBU, AMOVHU, AMOVWU:
3121 p.Ctxt.Diag("%v: unsupported unsigned store", p)
3122 return nil
3123 }
3124 switch p.To.Name {
3125 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
3126
3127 inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
3128
3129 case obj.NAME_EXTERN, obj.NAME_STATIC:
3130 if p.To.Sym.Type == objabi.STLSBSS {
3131 return instructionsForTLSStore(p)
3132 }
3133
3134
3135
3136
3137
3138
3139 insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
3140 ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
3141 inss = []*instruction{insAUIPC, ins}
3142
3143 default:
3144 p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
3145 return nil
3146 }
3147
3148 case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
3149
3150 if p.As != AMOV {
3151 p.Ctxt.Diag("%v: unsupported address load", p)
3152 return nil
3153 }
3154 switch p.From.Name {
3155 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
3156 inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
3157
3158 case obj.NAME_EXTERN, obj.NAME_STATIC:
3159
3160
3161
3162
3163
3164 insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
3165 ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
3166 inss = []*instruction{insAUIPC, ins}
3167
3168 default:
3169 p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
3170 return nil
3171 }
3172
3173 case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
3174 p.Ctxt.Diag("%v: address load must target register", p)
3175 return nil
3176
3177 default:
3178 p.Ctxt.Diag("%v: unsupported MOV", p)
3179 return nil
3180 }
3181
3182 return inss
3183 }
3184
3185
3186 func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
3187 if buildcfg.GORISCV64 >= 22 {
3188
3189 return []*instruction{ins}
3190 }
3191
3192 switch ins.as {
3193 case AROL, AROLW, AROR, ARORW:
3194
3195
3196 sllOp, srlOp := ASLL, ASRL
3197 if ins.as == AROLW || ins.as == ARORW {
3198 sllOp, srlOp = ASLLW, ASRLW
3199 }
3200 shift1, shift2 := sllOp, srlOp
3201 if ins.as == AROR || ins.as == ARORW {
3202 shift1, shift2 = shift2, shift1
3203 }
3204 return []*instruction{
3205 &instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP},
3206 &instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP},
3207 &instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
3208 &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
3209 }
3210
3211 case ARORI, ARORIW:
3212
3213 sllOp, srlOp := ASLLI, ASRLI
3214 sllImm := int64(int8(-ins.imm) & 63)
3215 if ins.as == ARORIW {
3216 sllOp, srlOp = ASLLIW, ASRLIW
3217 sllImm = int64(int8(-ins.imm) & 31)
3218 }
3219 return []*instruction{
3220 &instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm},
3221 &instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm},
3222 &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
3223 }
3224
3225 default:
3226 p.Ctxt.Diag("%v: unknown rotation", p)
3227 return nil
3228 }
3229 }
3230
3231
3232 func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction {
3233 if buildcfg.GORISCV64 >= 22 {
3234
3235 return []*instruction{ins}
3236 }
3237
3238
3239 if ins.rs1 == ins.rs2 {
3240 ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0
3241 return []*instruction{ins}
3242 }
3243
3244
3245
3246 if ins.rs1 == ins.rd {
3247 ins.rs1, ins.rs2 = ins.rs2, ins.rs1
3248 }
3249 sltReg1, sltReg2 := ins.rs2, ins.rs1
3250
3251
3252
3253 switch ins.as {
3254 case AMIN:
3255 ins.as = ASLT
3256 case AMAX:
3257 ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1
3258 case AMINU:
3259 ins.as = ASLTU
3260 case AMAXU:
3261 ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1
3262 }
3263 return []*instruction{
3264 &instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP},
3265 &instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP},
3266 &instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
3267 &instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
3268 &instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd},
3269 }
3270 }
3271
3272
3273 func instructionsForProg(p *obj.Prog) []*instruction {
3274 ins := instructionForProg(p)
3275 inss := []*instruction{ins}
3276
3277 if ins.as == AVSETVLI || ins.as == AVSETIVLI {
3278 if len(p.RestArgs) != 4 {
3279 p.Ctxt.Diag("incorrect number of arguments for instruction")
3280 return nil
3281 }
3282 } else if len(p.RestArgs) > 1 {
3283 p.Ctxt.Diag("too many source registers")
3284 return nil
3285 }
3286
3287 switch ins.as {
3288 case AJAL, AJALR:
3289 ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
3290 ins.imm = p.To.Offset
3291
3292 case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
3293 switch ins.as {
3294 case ABEQZ:
3295 ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
3296 case ABGEZ:
3297 ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
3298 case ABGT:
3299 ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
3300 case ABGTU:
3301 ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
3302 case ABGTZ:
3303 ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
3304 case ABLE:
3305 ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
3306 case ABLEU:
3307 ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
3308 case ABLEZ:
3309 ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
3310 case ABLTZ:
3311 ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
3312 case ABNEZ:
3313 ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
3314 }
3315 ins.imm = p.To.Offset
3316
3317 case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
3318 inss = instructionsForMOV(p)
3319
3320 case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
3321 inss = instructionsForLoad(p, ins.as, p.From.Reg)
3322
3323 case ASW, ASH, ASB, ASD, AFSW, AFSD:
3324 inss = instructionsForStore(p, ins.as, p.To.Reg)
3325
3326 case ALRW, ALRD:
3327
3328 ins.funct7 = 2
3329 ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
3330
3331 case AADDI, AANDI, AORI, AXORI:
3332 inss = instructionsForOpImmediate(p, ins.as, p.Reg)
3333
3334 case ASCW, ASCD:
3335
3336 ins.funct7 = 1
3337 ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
3338
3339 case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
3340 AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
3341
3342 ins.funct7 = 3
3343 ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
3344
3345 case AECALL, AEBREAK:
3346 insEnc := encode(p.As)
3347 if p.To.Type == obj.TYPE_NONE {
3348 ins.rd = REG_ZERO
3349 }
3350 ins.rs1 = REG_ZERO
3351 ins.imm = insEnc.csr
3352
3353 case ARDCYCLE, ARDTIME, ARDINSTRET:
3354 ins.as = ACSRRS
3355 if p.To.Type == obj.TYPE_NONE {
3356 ins.rd = REG_ZERO
3357 }
3358 ins.rs1 = REG_ZERO
3359 switch p.As {
3360 case ARDCYCLE:
3361 ins.imm = -1024
3362 case ARDTIME:
3363 ins.imm = -1023
3364 case ARDINSTRET:
3365 ins.imm = -1022
3366 }
3367
3368 case AFENCE:
3369 ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
3370 ins.imm = 0x0ff
3371
3372 case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
3373
3374 if p.Scond&rmSuffixBit == 0 {
3375 ins.funct3 = uint32(RM_RTZ)
3376 } else {
3377 ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
3378 }
3379
3380 case AFNES, AFNED:
3381
3382 if p.To.Type != obj.TYPE_REG {
3383 p.Ctxt.Diag("%v needs an integer register output", p)
3384 return nil
3385 }
3386 if ins.as == AFNES {
3387 ins.as = AFEQS
3388 } else {
3389 ins.as = AFEQD
3390 }
3391 ins2 := &instruction{
3392 as: AXORI,
3393 rd: ins.rd,
3394 rs1: ins.rd,
3395 imm: 1,
3396 }
3397 inss = append(inss, ins2)
3398
3399 case AFSQRTS, AFSQRTD:
3400
3401
3402 ins.rs1 = uint32(p.From.Reg)
3403 ins.rs2 = REG_F0
3404
3405 case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
3406 AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
3407
3408
3409 ins.rs1, ins.rs2 = ins.rs2, ins.rs1
3410
3411 case ANEG, ANEGW:
3412
3413 ins.as = ASUB
3414 if p.As == ANEGW {
3415 ins.as = ASUBW
3416 }
3417 ins.rs1 = REG_ZERO
3418 if ins.rd == obj.REG_NONE {
3419 ins.rd = ins.rs2
3420 }
3421
3422 case ANOT:
3423
3424 ins.as = AXORI
3425 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
3426 if ins.rd == obj.REG_NONE {
3427 ins.rd = ins.rs1
3428 }
3429 ins.imm = -1
3430
3431 case ASEQZ:
3432
3433 ins.as = ASLTIU
3434 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
3435 ins.imm = 1
3436
3437 case ASNEZ:
3438
3439 ins.as = ASLTU
3440 ins.rs1 = REG_ZERO
3441
3442 case AFABSS:
3443
3444 ins.as = AFSGNJXS
3445 ins.rs1 = uint32(p.From.Reg)
3446
3447 case AFABSD:
3448
3449 ins.as = AFSGNJXD
3450 ins.rs1 = uint32(p.From.Reg)
3451
3452 case AFNEGS:
3453
3454 ins.as = AFSGNJNS
3455 ins.rs1 = uint32(p.From.Reg)
3456
3457 case AFNEGD:
3458
3459 ins.as = AFSGNJND
3460 ins.rs1 = uint32(p.From.Reg)
3461
3462 case AROL, AROLW, AROR, ARORW:
3463 inss = instructionsForRotate(p, ins)
3464
3465 case ARORI:
3466 if ins.imm < 0 || ins.imm > 63 {
3467 p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
3468 }
3469 inss = instructionsForRotate(p, ins)
3470
3471 case ARORIW:
3472 if ins.imm < 0 || ins.imm > 31 {
3473 p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
3474 }
3475 inss = instructionsForRotate(p, ins)
3476
3477 case ASLLI, ASRLI, ASRAI:
3478 if ins.imm < 0 || ins.imm > 63 {
3479 p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
3480 }
3481
3482 case ASLLIW, ASRLIW, ASRAIW:
3483 if ins.imm < 0 || ins.imm > 31 {
3484 p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
3485 }
3486
3487 case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
3488 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
3489
3490 case AORCB, AREV8:
3491 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3492
3493 case AANDN, AORN:
3494 if buildcfg.GORISCV64 >= 22 {
3495
3496 break
3497 }
3498
3499
3500 bitwiseOp, notReg := AAND, ins.rd
3501 if ins.as == AORN {
3502 bitwiseOp = AOR
3503 }
3504 if ins.rs1 == notReg {
3505 notReg = REG_TMP
3506 }
3507 inss = []*instruction{
3508 &instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1},
3509 &instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd},
3510 }
3511
3512 case AXNOR:
3513 if buildcfg.GORISCV64 >= 22 {
3514
3515 break
3516 }
3517
3518 ins.as = AXOR
3519 inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
3520
3521 case AMIN, AMAX, AMINU, AMAXU:
3522 inss = instructionsForMinMax(p, ins)
3523
3524 case AVSETVLI, AVSETIVLI:
3525 ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
3526 vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
3527 if err != nil {
3528 p.Ctxt.Diag("%v: %v", p, err)
3529 }
3530 ins.imm = int64(vtype)
3531 if ins.as == AVSETIVLI {
3532 if p.From.Type != obj.TYPE_CONST {
3533 p.Ctxt.Diag("%v: expected immediate value", p)
3534 }
3535 ins.rs1 = uint32(p.From.Offset)
3536 }
3537
3538 case AVLE8V, AVLE16V, AVLE32V, AVLE64V, AVSE8V, AVSE16V, AVSE32V, AVSE64V, AVLMV, AVSMV:
3539
3540 switch {
3541 case ins.rs1 == obj.REG_NONE:
3542 ins.funct7 |= 1
3543 case ins.rs1 != REG_V0:
3544 p.Ctxt.Diag("%v: invalid vector mask register", p)
3545 }
3546 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3547
3548 case AVLSE8V, AVLSE16V, AVLSE32V, AVLSE64V,
3549 AVLUXEI8V, AVLUXEI16V, AVLUXEI32V, AVLUXEI64V, AVLOXEI8V, AVLOXEI16V, AVLOXEI32V, AVLOXEI64V:
3550
3551 switch {
3552 case ins.rs3 == obj.REG_NONE:
3553 ins.funct7 |= 1
3554 case ins.rs3 != REG_V0:
3555 p.Ctxt.Diag("%v: invalid vector mask register", p)
3556 }
3557 ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rs1, obj.REG_NONE
3558
3559 case AVSSE8V, AVSSE16V, AVSSE32V, AVSSE64V,
3560 AVSUXEI8V, AVSUXEI16V, AVSUXEI32V, AVSUXEI64V, AVSOXEI8V, AVSOXEI16V, AVSOXEI32V, AVSOXEI64V:
3561
3562 switch {
3563 case ins.rs3 == obj.REG_NONE:
3564 ins.funct7 |= 1
3565 case ins.rs3 != REG_V0:
3566 p.Ctxt.Diag("%v: invalid vector mask register", p)
3567 }
3568 ins.rd, ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rd, ins.rs1, obj.REG_NONE
3569
3570 case AVL1RV, AVL1RE8V, AVL1RE16V, AVL1RE32V, AVL1RE64V, AVL2RV, AVL2RE8V, AVL2RE16V, AVL2RE32V, AVL2RE64V,
3571 AVL4RV, AVL4RE8V, AVL4RE16V, AVL4RE32V, AVL4RE64V, AVL8RV, AVL8RE8V, AVL8RE16V, AVL8RE32V, AVL8RE64V:
3572 switch ins.as {
3573 case AVL1RV:
3574 ins.as = AVL1RE8V
3575 case AVL2RV:
3576 ins.as = AVL2RE8V
3577 case AVL4RV:
3578 ins.as = AVL4RE8V
3579 case AVL8RV:
3580 ins.as = AVL8RE8V
3581 }
3582 if ins.rs1 != obj.REG_NONE {
3583 p.Ctxt.Diag("%v: too many operands for instruction", p)
3584 }
3585 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3586
3587 case AVS1RV, AVS2RV, AVS4RV, AVS8RV:
3588 if ins.rs1 != obj.REG_NONE {
3589 p.Ctxt.Diag("%v: too many operands for instruction", p)
3590 }
3591 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3592
3593 case AVADDVV, AVADDVX, AVSUBVV, AVSUBVX, AVRSUBVX, AVWADDUVV, AVWADDUVX, AVWSUBUVV, AVWSUBUVX,
3594 AVWADDVV, AVWADDVX, AVWSUBVV, AVWSUBVX, AVWADDUWV, AVWADDUWX, AVWSUBUWV, AVWSUBUWX,
3595 AVWADDWV, AVWADDWX, AVWSUBWV, AVWSUBWX, AVANDVV, AVANDVX, AVORVV, AVORVX, AVXORVV, AVXORVX,
3596 AVSLLVV, AVSLLVX, AVSRLVV, AVSRLVX, AVSRAVV, AVSRAVX,
3597 AVMSEQVV, AVMSEQVX, AVMSNEVV, AVMSNEVX, AVMSLTUVV, AVMSLTUVX, AVMSLTVV, AVMSLTVX,
3598 AVMSLEUVV, AVMSLEUVX, AVMSLEVV, AVMSLEVX, AVMSGTUVX, AVMSGTVX,
3599 AVMINUVV, AVMINUVX, AVMINVV, AVMINVX, AVMAXUVV, AVMAXUVX, AVMAXVV, AVMAXVX,
3600 AVMULVV, AVMULVX, AVMULHVV, AVMULHVX, AVMULHUVV, AVMULHUVX, AVMULHSUVV, AVMULHSUVX,
3601 AVDIVUVV, AVDIVUVX, AVDIVVV, AVDIVVX, AVREMUVV, AVREMUVX, AVREMVV, AVREMVX,
3602 AVWMULVV, AVWMULVX, AVWMULUVV, AVWMULUVX, AVWMULSUVV, AVWMULSUVX, AVNSRLWV, AVNSRLWX, AVNSRAWV, AVNSRAWX,
3603 AVSADDUVV, AVSADDUVX, AVSADDUVI, AVSADDVV, AVSADDVX, AVSADDVI, AVSSUBUVV, AVSSUBUVX, AVSSUBVV, AVSSUBVX,
3604 AVAADDUVV, AVAADDUVX, AVAADDVV, AVAADDVX, AVASUBUVV, AVASUBUVX, AVASUBVV, AVASUBVX,
3605 AVSMULVV, AVSMULVX, AVSSRLVV, AVSSRLVX, AVSSRLVI, AVSSRAVV, AVSSRAVX, AVSSRAVI,
3606 AVNCLIPUWV, AVNCLIPUWX, AVNCLIPUWI, AVNCLIPWV, AVNCLIPWX, AVNCLIPWI,
3607 AVFADDVV, AVFADDVF, AVFSUBVV, AVFSUBVF, AVFRSUBVF,
3608 AVFWADDVV, AVFWADDVF, AVFWSUBVV, AVFWSUBVF, AVFWADDWV, AVFWADDWF, AVFWSUBWV, AVFWSUBWF,
3609 AVFMULVV, AVFMULVF, AVFDIVVV, AVFDIVVF, AVFRDIVVF, AVFWMULVV, AVFWMULVF,
3610 AVFMINVV, AVFMINVF, AVFMAXVV, AVFMAXVF,
3611 AVFSGNJVV, AVFSGNJVF, AVFSGNJNVV, AVFSGNJNVF, AVFSGNJXVV, AVFSGNJXVF,
3612 AVMFEQVV, AVMFEQVF, AVMFNEVV, AVMFNEVF, AVMFLTVV, AVMFLTVF, AVMFLEVV, AVMFLEVF, AVMFGTVF, AVMFGEVF,
3613 AVREDSUMVS, AVREDMAXUVS, AVREDMAXVS, AVREDMINUVS, AVREDMINVS, AVREDANDVS, AVREDORVS, AVREDXORVS,
3614 AVWREDSUMUVS, AVWREDSUMVS, AVFREDOSUMVS, AVFREDUSUMVS, AVFREDMAXVS, AVFREDMINVS, AVFWREDOSUMVS, AVFWREDUSUMVS,
3615 AVSLIDEUPVX, AVSLIDEDOWNVX, AVSLIDE1UPVX, AVFSLIDE1UPVF, AVSLIDE1DOWNVX, AVFSLIDE1DOWNVF,
3616 AVRGATHERVV, AVRGATHEREI16VV, AVRGATHERVX:
3617
3618 switch {
3619 case ins.rs3 == obj.REG_NONE:
3620 ins.funct7 |= 1
3621 case ins.rs3 != REG_V0:
3622 p.Ctxt.Diag("%v: invalid vector mask register", p)
3623 }
3624 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
3625
3626 case AVFMACCVV, AVFMACCVF, AVFNMACCVV, AVFNMACCVF, AVFMSACVV, AVFMSACVF, AVFNMSACVV, AVFNMSACVF,
3627 AVFMADDVV, AVFMADDVF, AVFNMADDVV, AVFNMADDVF, AVFMSUBVV, AVFMSUBVF, AVFNMSUBVV, AVFNMSUBVF,
3628 AVFWMACCVV, AVFWMACCVF, AVFWNMACCVV, AVFWNMACCVF, AVFWMSACVV, AVFWMSACVF, AVFWNMSACVV, AVFWNMSACVF,
3629 AVMACCVV, AVMACCVX, AVNMSACVV, AVNMSACVX, AVMADDVV, AVMADDVX, AVNMSUBVV, AVNMSUBVX,
3630 AVWMACCUVV, AVWMACCUVX, AVWMACCVV, AVWMACCVX, AVWMACCSUVV, AVWMACCSUVX, AVWMACCUSVX:
3631 switch {
3632 case ins.rs3 == obj.REG_NONE:
3633 ins.funct7 |= 1
3634 case ins.rs3 != REG_V0:
3635 p.Ctxt.Diag("%v: invalid vector mask register", p)
3636 }
3637 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
3638
3639 case AVADDVI, AVRSUBVI, AVANDVI, AVORVI, AVXORVI, AVMSEQVI, AVMSNEVI, AVMSLEUVI, AVMSLEVI, AVMSGTUVI, AVMSGTVI,
3640 AVSLLVI, AVSRLVI, AVSRAVI, AVNSRLWI, AVNSRAWI, AVRGATHERVI, AVSLIDEUPVI, AVSLIDEDOWNVI:
3641
3642 switch {
3643 case ins.rs3 == obj.REG_NONE:
3644 ins.funct7 |= 1
3645 case ins.rs3 != REG_V0:
3646 p.Ctxt.Diag("%v: invalid vector mask register", p)
3647 }
3648 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE
3649
3650 case AVZEXTVF2, AVSEXTVF2, AVZEXTVF4, AVSEXTVF4, AVZEXTVF8, AVSEXTVF8, AVFSQRTV, AVFRSQRT7V, AVFREC7V, AVFCLASSV,
3651 AVFCVTXUFV, AVFCVTXFV, AVFCVTRTZXUFV, AVFCVTRTZXFV, AVFCVTFXUV, AVFCVTFXV,
3652 AVFWCVTXUFV, AVFWCVTXFV, AVFWCVTRTZXUFV, AVFWCVTRTZXFV, AVFWCVTFXUV, AVFWCVTFXV, AVFWCVTFFV,
3653 AVFNCVTXUFW, AVFNCVTXFW, AVFNCVTRTZXUFW, AVFNCVTRTZXFW, AVFNCVTFXUW, AVFNCVTFXW, AVFNCVTFFW, AVFNCVTRODFFW:
3654
3655 switch {
3656 case ins.rs1 == obj.REG_NONE:
3657 ins.funct7 |= 1
3658 case ins.rs1 != REG_V0:
3659 p.Ctxt.Diag("%v: invalid vector mask register", p)
3660 }
3661 ins.rs1 = obj.REG_NONE
3662
3663 case AVMVVV, AVMVVX:
3664 if ins.rs1 != obj.REG_NONE {
3665 p.Ctxt.Diag("%v: too many operands for instruction", p)
3666 }
3667 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
3668
3669 case AVMVVI:
3670 if ins.rs1 != obj.REG_NONE {
3671 p.Ctxt.Diag("%v: too many operands for instruction", p)
3672 }
3673 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), obj.REG_NONE, REG_V0
3674
3675 case AVFMVVF:
3676 ins.funct7 |= 1
3677 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
3678
3679 case AVADCVIM, AVADCVVM, AVADCVXM, AVSBCVVM, AVSBCVXM:
3680 if ins.rd == REG_V0 {
3681 p.Ctxt.Diag("%v: invalid destination register V0", p)
3682 }
3683 fallthrough
3684
3685 case AVMADCVVM, AVMADCVXM, AVMSBCVVM, AVMSBCVXM, AVMADCVIM, AVMERGEVVM, AVMERGEVXM, AVMERGEVIM, AVFMERGEVFM:
3686 if ins.rs3 != REG_V0 {
3687 p.Ctxt.Diag("%v: invalid vector mask register", p)
3688 }
3689 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
3690
3691 case AVMADCVV, AVMADCVX, AVMSBCVV, AVMSBCVX, AVMADCVI:
3692 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
3693
3694 case AVNEGV, AVWCVTXXV, AVWCVTUXXV, AVNCVTXXW:
3695
3696 switch {
3697 case ins.rs1 == obj.REG_NONE:
3698 ins.funct7 |= 1
3699 case ins.rs1 != REG_V0:
3700 p.Ctxt.Diag("%v: invalid vector mask register", p)
3701 }
3702 switch ins.as {
3703 case AVNEGV:
3704 ins.as = AVRSUBVX
3705 case AVWCVTXXV:
3706 ins.as = AVWADDVX
3707 case AVWCVTUXXV:
3708 ins.as = AVWADDUVX
3709 case AVNCVTXXW:
3710 ins.as = AVNSRLWX
3711 }
3712 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), REG_X0, uint32(p.From.Reg)
3713
3714 case AVNOTV:
3715
3716 switch {
3717 case ins.rs1 == obj.REG_NONE:
3718 ins.funct7 |= 1
3719 case ins.rs1 != REG_V0:
3720 p.Ctxt.Diag("%v: invalid vector mask register", p)
3721 }
3722 ins.as = AVXORVI
3723 ins.rd, ins.rs1, ins.rs2, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.From.Reg), -1
3724
3725 case AVMSGTVV, AVMSGTUVV, AVMSGEVV, AVMSGEUVV, AVMFGTVV, AVMFGEVV:
3726
3727 switch {
3728 case ins.rs3 == obj.REG_NONE:
3729 ins.funct7 |= 1
3730 case ins.rs3 != REG_V0:
3731 p.Ctxt.Diag("%v: invalid vector mask register", p)
3732 }
3733 switch ins.as {
3734 case AVMSGTVV:
3735 ins.as = AVMSLTVV
3736 case AVMSGTUVV:
3737 ins.as = AVMSLTUVV
3738 case AVMSGEVV:
3739 ins.as = AVMSLEVV
3740 case AVMSGEUVV:
3741 ins.as = AVMSLEUVV
3742 case AVMFGTVV:
3743 ins.as = AVMFLTVV
3744 case AVMFGEVV:
3745 ins.as = AVMFLEVV
3746 }
3747 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
3748
3749 case AVMSLTVI, AVMSLTUVI, AVMSGEVI, AVMSGEUVI:
3750
3751 switch {
3752 case ins.rs3 == obj.REG_NONE:
3753 ins.funct7 |= 1
3754 case ins.rs3 != REG_V0:
3755 p.Ctxt.Diag("%v: invalid vector mask register", p)
3756 }
3757 switch ins.as {
3758 case AVMSLTVI:
3759 ins.as = AVMSLEVI
3760 case AVMSLTUVI:
3761 ins.as = AVMSLEUVI
3762 case AVMSGEVI:
3763 ins.as = AVMSGTVI
3764 case AVMSGEUVI:
3765 ins.as = AVMSGTUVI
3766 }
3767 ins.rd, ins.rs1, ins.rs2, ins.rs3, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE, ins.imm-1
3768
3769 case AVFABSV, AVFNEGV:
3770
3771 switch {
3772 case ins.rs1 == obj.REG_NONE:
3773 ins.funct7 |= 1
3774 case ins.rs1 != REG_V0:
3775 p.Ctxt.Diag("%v: invalid vector mask register", p)
3776 }
3777 switch ins.as {
3778 case AVFABSV:
3779 ins.as = AVFSGNJXVV
3780 case AVFNEGV:
3781 ins.as = AVFSGNJNVV
3782 }
3783 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
3784
3785 case AVMANDMM, AVMNANDMM, AVMANDNMM, AVMXORMM, AVMORMM, AVMNORMM, AVMORNMM, AVMXNORMM, AVMMVM, AVMNOTM, AVCOMPRESSVM:
3786 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
3787 switch ins.as {
3788 case AVMMVM:
3789 ins.as, ins.rs2 = AVMANDMM, ins.rs1
3790 case AVMNOTM:
3791 ins.as, ins.rs2 = AVMNANDMM, ins.rs1
3792 }
3793
3794 case AVMCLRM, AVMSETM:
3795 ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
3796 switch ins.as {
3797 case AVMCLRM:
3798 ins.as = AVMXORMM
3799 case AVMSETM:
3800 ins.as = AVMXNORMM
3801 }
3802
3803 case AVCPOPM, AVFIRSTM, AVMSBFM, AVMSIFM, AVMSOFM, AVIOTAM:
3804
3805 switch {
3806 case ins.rs1 == obj.REG_NONE:
3807 ins.funct7 |= 1
3808 case ins.rs1 != REG_V0:
3809 p.Ctxt.Diag("%v: invalid vector mask register", p)
3810 }
3811 ins.rs1 = obj.REG_NONE
3812
3813 case AVIDV:
3814
3815 switch {
3816 case ins.rd == obj.REG_NONE:
3817 ins.funct7 |= 1
3818 case ins.rd != obj.REG_NONE && ins.rs2 != REG_V0:
3819 p.Ctxt.Diag("%v: invalid vector mask register", p)
3820 }
3821 if ins.rd == obj.REG_NONE {
3822 ins.rd = uint32(p.From.Reg)
3823 }
3824 ins.rs1, ins.rs2 = obj.REG_NONE, REG_V0
3825 }
3826
3827 for _, ins := range inss {
3828 ins.p = p
3829 }
3830
3831 return inss
3832 }
3833
3834
3835
3836 func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
3837 if ctxt.Retpoline {
3838 ctxt.Diag("-spectre=ret not supported on riscv")
3839 ctxt.Retpoline = false
3840 }
3841
3842
3843
3844 if ctxt.Errors > 0 {
3845 return
3846 }
3847
3848 for p := cursym.Func().Text; p != nil; p = p.Link {
3849 switch p.As {
3850 case AJAL:
3851 if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
3852 cursym.AddRel(ctxt, obj.Reloc{
3853 Type: objabi.R_RISCV_JAL,
3854 Off: int32(p.Pc),
3855 Siz: 4,
3856 Sym: p.To.Sym,
3857 Add: p.To.Offset,
3858 })
3859 }
3860 case AJALR:
3861 if p.To.Sym != nil {
3862 ctxt.Diag("%v: unexpected AJALR with to symbol", p)
3863 }
3864
3865 case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
3866 var addr *obj.Addr
3867 var rt objabi.RelocType
3868 if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
3869 rt = objabi.R_RISCV_CALL
3870 addr = &p.From
3871 } else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
3872 rt = objabi.R_RISCV_PCREL_ITYPE
3873 addr = &p.From
3874 } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
3875 rt = objabi.R_RISCV_PCREL_STYPE
3876 addr = &p.To
3877 } else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC {
3878 rt = objabi.R_RISCV_GOT_PCREL_ITYPE
3879 addr = &p.From
3880 } else {
3881 break
3882 }
3883 if p.As == AAUIPC {
3884 if p.Link == nil {
3885 ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
3886 break
3887 }
3888 addr = &p.RestArgs[0].Addr
3889 }
3890 if addr.Sym == nil {
3891 ctxt.Diag("PC-relative relocation missing symbol")
3892 break
3893 }
3894 if addr.Sym.Type == objabi.STLSBSS {
3895 if ctxt.Flag_shared {
3896 rt = objabi.R_RISCV_TLS_IE
3897 } else {
3898 rt = objabi.R_RISCV_TLS_LE
3899 }
3900 }
3901
3902 cursym.AddRel(ctxt, obj.Reloc{
3903 Type: rt,
3904 Off: int32(p.Pc),
3905 Siz: 8,
3906 Sym: addr.Sym,
3907 Add: addr.Offset,
3908 })
3909
3910 case obj.APCALIGN:
3911 alignedValue := p.From.Offset
3912 v := pcAlignPadLength(p.Pc, alignedValue)
3913 offset := p.Pc
3914 for ; v >= 4; v -= 4 {
3915
3916 cursym.WriteBytes(ctxt, offset, []byte{0x13, 0, 0, 0})
3917 offset += 4
3918 }
3919 continue
3920 }
3921
3922 offset := p.Pc
3923 for _, ins := range instructionsForProg(p) {
3924 if ic, err := ins.encode(); err == nil {
3925 cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
3926 offset += int64(ins.length())
3927 }
3928 if ins.usesRegTmp() {
3929 p.Mark |= USES_REG_TMP
3930 }
3931 }
3932 }
3933
3934 obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
3935 }
3936
3937 func isUnsafePoint(p *obj.Prog) bool {
3938 return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
3939 }
3940
3941 func ParseSuffix(prog *obj.Prog, cond string) (err error) {
3942 switch prog.As {
3943 case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
3944 prog.Scond, err = rmSuffixEncode(strings.TrimPrefix(cond, "."))
3945 }
3946 return
3947 }
3948
3949 var LinkRISCV64 = obj.LinkArch{
3950 Arch: sys.ArchRISCV64,
3951 Init: buildop,
3952 Preprocess: preprocess,
3953 Assemble: assemble,
3954 Progedit: progedit,
3955 UnaryDst: unaryDst,
3956 DWARFRegisters: RISCV64DWARFRegisters,
3957 }
3958
View as plain text