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 func regAddr(a obj.Addr, min, max uint32) uint32 {
1077 if a.Type != obj.TYPE_REG {
1078 panic(fmt.Sprintf("ill typed: %+v", a))
1079 }
1080 return regVal(uint32(a.Reg), min, max)
1081 }
1082
1083
1084 func regIAddr(a obj.Addr) uint32 {
1085 return regAddr(a, REG_X0, REG_X31)
1086 }
1087
1088
1089 func regFAddr(a obj.Addr) uint32 {
1090 return regAddr(a, REG_F0, REG_F31)
1091 }
1092
1093
1094
1095 func immEven(x int64) error {
1096 if x&1 != 0 {
1097 return fmt.Errorf("immediate %#x is not a multiple of two", x)
1098 }
1099 return nil
1100 }
1101
1102 func immFits(x int64, nbits uint, signed bool) error {
1103 label := "unsigned"
1104 min, max := int64(0), int64(1)<<nbits-1
1105 if signed {
1106 label = "signed"
1107 sbits := nbits - 1
1108 min, max = int64(-1)<<sbits, int64(1)<<sbits-1
1109 }
1110 if x < min || x > max {
1111 if nbits <= 16 {
1112 return fmt.Errorf("%s immediate %d must be in range [%d, %d] (%d bits)", label, x, min, max, nbits)
1113 }
1114 return fmt.Errorf("%s immediate %#x must be in range [%#x, %#x] (%d bits)", label, x, min, max, nbits)
1115 }
1116 return nil
1117 }
1118
1119
1120
1121 func immIFits(x int64, nbits uint) error {
1122 return immFits(x, nbits, true)
1123 }
1124
1125
1126 func immI(as obj.As, imm int64, nbits uint) uint32 {
1127 if err := immIFits(imm, nbits); err != nil {
1128 panic(fmt.Sprintf("%v: %v", as, err))
1129 }
1130 return uint32(imm) & ((1 << nbits) - 1)
1131 }
1132
1133 func wantImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
1134 if err := immIFits(imm, nbits); err != nil {
1135 ctxt.Diag("%v: %v", ins, err)
1136 }
1137 }
1138
1139
1140
1141 func immUFits(x int64, nbits uint) error {
1142 return immFits(x, nbits, false)
1143 }
1144
1145
1146 func immU(as obj.As, imm int64, nbits uint) uint32 {
1147 if err := immUFits(imm, nbits); err != nil {
1148 panic(fmt.Sprintf("%v: %v", as, err))
1149 }
1150 return uint32(imm) & ((1 << nbits) - 1)
1151 }
1152
1153 func wantImmU(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
1154 if err := immUFits(imm, nbits); err != nil {
1155 ctxt.Diag("%v: %v", ins, err)
1156 }
1157 }
1158
1159 func wantReg(ctxt *obj.Link, ins *instruction, pos string, descr string, r, min, max uint32) {
1160 if r < min || r > max {
1161 var suffix string
1162 if r != obj.REG_NONE {
1163 suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r)))
1164 }
1165 ctxt.Diag("%v: expected %s register in %s position%s", ins, descr, pos, suffix)
1166 }
1167 }
1168
1169 func wantNoneReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1170 if r != obj.REG_NONE {
1171 ctxt.Diag("%v: expected no register in %s but got register %s", ins, pos, RegName(int(r)))
1172 }
1173 }
1174
1175
1176 func wantIntReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1177 wantReg(ctxt, ins, pos, "integer", r, REG_X0, REG_X31)
1178 }
1179
1180
1181 func wantFloatReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1182 wantReg(ctxt, ins, pos, "float", r, REG_F0, REG_F31)
1183 }
1184
1185
1186 func wantVectorReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
1187 wantReg(ctxt, ins, pos, "vector", r, REG_V0, REG_V31)
1188 }
1189
1190
1191 func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) {
1192 if err := immEven(offset); err != nil {
1193 ctxt.Diag("%v: %v", ins, err)
1194 }
1195 }
1196
1197 func validateRII(ctxt *obj.Link, ins *instruction) {
1198 wantIntReg(ctxt, ins, "rd", ins.rd)
1199 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1200 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1201 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1202 }
1203
1204 func validateRIII(ctxt *obj.Link, ins *instruction) {
1205 wantIntReg(ctxt, ins, "rd", ins.rd)
1206 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1207 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1208 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1209 }
1210
1211 func validateRFFF(ctxt *obj.Link, ins *instruction) {
1212 wantFloatReg(ctxt, ins, "rd", ins.rd)
1213 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1214 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1215 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1216 }
1217
1218 func validateRFFFF(ctxt *obj.Link, ins *instruction) {
1219 wantFloatReg(ctxt, ins, "rd", ins.rd)
1220 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1221 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1222 wantFloatReg(ctxt, ins, "rs3", ins.rs3)
1223 }
1224
1225 func validateRFFI(ctxt *obj.Link, ins *instruction) {
1226 wantIntReg(ctxt, ins, "rd", ins.rd)
1227 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1228 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1229 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1230 }
1231
1232 func validateRFI(ctxt *obj.Link, ins *instruction) {
1233 wantIntReg(ctxt, ins, "rd", ins.rd)
1234 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1235 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1236 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1237 }
1238
1239 func validateRFV(ctxt *obj.Link, ins *instruction) {
1240 wantVectorReg(ctxt, ins, "vd", ins.rd)
1241 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1242 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1243 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1244 }
1245
1246 func validateRFF(ctxt *obj.Link, ins *instruction) {
1247 wantFloatReg(ctxt, ins, "rd", ins.rd)
1248 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1249 wantFloatReg(ctxt, ins, "rs2", ins.rs2)
1250 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1251 }
1252
1253 func validateRIF(ctxt *obj.Link, ins *instruction) {
1254 wantFloatReg(ctxt, ins, "rd", ins.rd)
1255 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1256 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1257 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1258 }
1259
1260 func validateRIV(ctxt *obj.Link, ins *instruction) {
1261 wantVectorReg(ctxt, ins, "vd", ins.rd)
1262 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1263 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1264 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1265 }
1266
1267 func validateRVF(ctxt *obj.Link, ins *instruction) {
1268 wantFloatReg(ctxt, ins, "rd", ins.rd)
1269 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1270 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1271 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1272 }
1273
1274 func validateRVFV(ctxt *obj.Link, ins *instruction) {
1275 wantVectorReg(ctxt, ins, "vd", ins.rd)
1276 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1277 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1278 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1279 }
1280
1281 func validateRVI(ctxt *obj.Link, ins *instruction) {
1282 wantIntReg(ctxt, ins, "rd", ins.rd)
1283 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1284 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1285 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1286 }
1287
1288 func validateRVIV(ctxt *obj.Link, ins *instruction) {
1289 wantVectorReg(ctxt, ins, "vd", ins.rd)
1290 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1291 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1292 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1293 }
1294
1295 func validateRVV(ctxt *obj.Link, ins *instruction) {
1296 wantVectorReg(ctxt, ins, "vd", ins.rd)
1297 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1298 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1299 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1300 }
1301
1302 func validateRVVi(ctxt *obj.Link, ins *instruction) {
1303 wantImmI(ctxt, ins, ins.imm, 5)
1304 wantVectorReg(ctxt, ins, "vd", ins.rd)
1305 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1306 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1307 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1308 }
1309
1310 func validateRVVu(ctxt *obj.Link, ins *instruction) {
1311 wantImmU(ctxt, ins, ins.imm, 5)
1312 wantVectorReg(ctxt, ins, "vd", ins.rd)
1313 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1314 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1315 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1316 }
1317
1318 func validateRVVV(ctxt *obj.Link, ins *instruction) {
1319 wantVectorReg(ctxt, ins, "vd", ins.rd)
1320 wantVectorReg(ctxt, ins, "vs1", ins.rs1)
1321 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1322 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1323 }
1324
1325 func validateIII(ctxt *obj.Link, ins *instruction) {
1326 wantImmI(ctxt, ins, ins.imm, 12)
1327 wantIntReg(ctxt, ins, "rd", ins.rd)
1328 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1329 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1330 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1331 }
1332
1333 func validateIF(ctxt *obj.Link, ins *instruction) {
1334 wantImmI(ctxt, ins, ins.imm, 12)
1335 wantFloatReg(ctxt, ins, "rd", ins.rd)
1336 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1337 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1338 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1339 }
1340
1341 func validateIV(ctxt *obj.Link, ins *instruction) {
1342 wantVectorReg(ctxt, ins, "vd", ins.rd)
1343 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1344 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1345 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1346 }
1347
1348 func validateIIIV(ctxt *obj.Link, ins *instruction) {
1349 wantVectorReg(ctxt, ins, "vd", ins.rd)
1350 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1351 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1352 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1353 }
1354
1355 func validateIVIV(ctxt *obj.Link, ins *instruction) {
1356 wantVectorReg(ctxt, ins, "vd", ins.rd)
1357 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1358 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1359 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1360 }
1361
1362 func validateSI(ctxt *obj.Link, ins *instruction) {
1363 wantImmI(ctxt, ins, ins.imm, 12)
1364 wantIntReg(ctxt, ins, "rd", ins.rd)
1365 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1366 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1367 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1368 }
1369
1370 func validateSF(ctxt *obj.Link, ins *instruction) {
1371 wantImmI(ctxt, ins, ins.imm, 12)
1372 wantIntReg(ctxt, ins, "rd", ins.rd)
1373 wantFloatReg(ctxt, ins, "rs1", ins.rs1)
1374 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1375 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1376 }
1377
1378 func validateSV(ctxt *obj.Link, ins *instruction) {
1379 wantIntReg(ctxt, ins, "rd", ins.rd)
1380 wantVectorReg(ctxt, ins, "vs1", ins.rs1)
1381 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1382 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1383 }
1384
1385 func validateSVII(ctxt *obj.Link, ins *instruction) {
1386 wantVectorReg(ctxt, ins, "vd", 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 validateSVIV(ctxt *obj.Link, ins *instruction) {
1393 wantVectorReg(ctxt, ins, "vd", ins.rd)
1394 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1395 wantVectorReg(ctxt, ins, "vs2", ins.rs2)
1396 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1397 }
1398
1399 func validateB(ctxt *obj.Link, ins *instruction) {
1400
1401
1402 wantEvenOffset(ctxt, ins, ins.imm)
1403 wantImmI(ctxt, ins, ins.imm, 13)
1404 wantNoneReg(ctxt, ins, "rd", ins.rd)
1405 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1406 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1407 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1408 }
1409
1410 func validateU(ctxt *obj.Link, ins *instruction) {
1411 wantImmI(ctxt, ins, ins.imm, 20)
1412 wantIntReg(ctxt, ins, "rd", ins.rd)
1413 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1414 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1415 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1416 }
1417
1418 func validateJ(ctxt *obj.Link, ins *instruction) {
1419
1420
1421 wantEvenOffset(ctxt, ins, ins.imm)
1422 wantImmI(ctxt, ins, ins.imm, 21)
1423 wantIntReg(ctxt, ins, "rd", ins.rd)
1424 wantNoneReg(ctxt, ins, "rs1", ins.rs1)
1425 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1426 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1427 }
1428
1429 func validateVsetvli(ctxt *obj.Link, ins *instruction) {
1430 wantImmU(ctxt, ins, ins.imm, 11)
1431 wantIntReg(ctxt, ins, "rd", ins.rd)
1432 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1433 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1434 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1435 }
1436
1437 func validateVsetivli(ctxt *obj.Link, ins *instruction) {
1438 wantImmU(ctxt, ins, ins.imm, 10)
1439 wantIntReg(ctxt, ins, "rd", ins.rd)
1440 wantImmU(ctxt, ins, int64(ins.rs1), 5)
1441 wantNoneReg(ctxt, ins, "rs2", ins.rs2)
1442 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1443 }
1444
1445 func validateVsetvl(ctxt *obj.Link, ins *instruction) {
1446 wantIntReg(ctxt, ins, "rd", ins.rd)
1447 wantIntReg(ctxt, ins, "rs1", ins.rs1)
1448 wantIntReg(ctxt, ins, "rs2", ins.rs2)
1449 wantNoneReg(ctxt, ins, "rs3", ins.rs3)
1450 }
1451
1452 func validateRaw(ctxt *obj.Link, ins *instruction) {
1453
1454
1455 if ins.imm < 0 || 1<<32 <= ins.imm {
1456 ctxt.Diag("%v: immediate %d in raw position cannot be larger than 32 bits", ins.as, ins.imm)
1457 }
1458 }
1459
1460
1461
1462 func extractBitAndShift(imm uint32, bit, pos int) uint32 {
1463 return ((imm >> bit) & 1) << pos
1464 }
1465
1466
1467 func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
1468 enc := encode(as)
1469 if enc == nil {
1470 panic("encodeR: could not encode instruction")
1471 }
1472 if enc.rs1 != 0 && rs1 != 0 {
1473 panic("encodeR: instruction uses rs1, but rs1 is nonzero")
1474 }
1475 if enc.rs2 != 0 && rs2 != 0 {
1476 panic("encodeR: instruction uses rs2, but rs2 is nonzero")
1477 }
1478 funct3 |= enc.funct3
1479 funct7 |= enc.funct7
1480 rs1 |= enc.rs1
1481 rs2 |= enc.rs2
1482 return funct7<<25 | rs2<<20 | rs1<<15 | funct3<<12 | rd<<7 | enc.opcode
1483 }
1484
1485
1486 func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
1487 enc := encode(as)
1488 if enc == nil {
1489 panic("encodeR4: could not encode instruction")
1490 }
1491 if enc.rs2 != 0 {
1492 panic("encodeR4: instruction uses rs2")
1493 }
1494 funct2 |= enc.funct7
1495 if funct2&^3 != 0 {
1496 panic("encodeR4: funct2 requires more than 2 bits")
1497 }
1498 return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
1499 }
1500
1501 func encodeRII(ins *instruction) uint32 {
1502 return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7)
1503 }
1504
1505 func encodeRIII(ins *instruction) uint32 {
1506 return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1507 }
1508
1509 func encodeRFFF(ins *instruction) uint32 {
1510 return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
1511 }
1512
1513 func encodeRFFFF(ins *instruction) uint32 {
1514 return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7)
1515 }
1516
1517 func encodeRFFI(ins *instruction) uint32 {
1518 return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1519 }
1520
1521 func encodeRFI(ins *instruction) uint32 {
1522 return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
1523 }
1524
1525 func encodeRFF(ins *instruction) uint32 {
1526 return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
1527 }
1528
1529 func encodeRFV(ins *instruction) uint32 {
1530 return encodeR(ins.as, regF(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
1531 }
1532
1533 func encodeRIF(ins *instruction) uint32 {
1534 return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
1535 }
1536
1537 func encodeRIV(ins *instruction) uint32 {
1538 return encodeR(ins.as, regI(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
1539 }
1540
1541 func encodeRVF(ins *instruction) uint32 {
1542 return encodeR(ins.as, 0, regV(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
1543 }
1544
1545 func encodeRVFV(ins *instruction) uint32 {
1546 return encodeR(ins.as, regF(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1547 }
1548
1549 func encodeRVI(ins *instruction) uint32 {
1550 return encodeR(ins.as, 0, regV(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
1551 }
1552
1553 func encodeRVIV(ins *instruction) uint32 {
1554 return encodeR(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1555 }
1556
1557 func encodeRVV(ins *instruction) uint32 {
1558 return encodeR(ins.as, 0, regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1559 }
1560
1561 func encodeRVVi(ins *instruction) uint32 {
1562 return encodeR(ins.as, immI(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1563 }
1564
1565 func encodeRVVu(ins *instruction) uint32 {
1566 return encodeR(ins.as, immU(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1567 }
1568
1569 func encodeRVVV(ins *instruction) uint32 {
1570 return encodeR(ins.as, regV(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
1571 }
1572
1573
1574 func encodeI(as obj.As, rs1, rd, imm, funct7 uint32) uint32 {
1575 enc := encode(as)
1576 if enc == nil {
1577 panic("encodeI: could not encode instruction")
1578 }
1579 imm |= uint32(enc.csr)
1580 return funct7<<25 | imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
1581 }
1582
1583 func encodeIII(ins *instruction) uint32 {
1584 return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm), 0)
1585 }
1586
1587 func encodeIF(ins *instruction) uint32 {
1588 return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm), 0)
1589 }
1590
1591 func encodeIV(ins *instruction) uint32 {
1592 return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), uint32(ins.imm), ins.funct7)
1593 }
1594
1595 func encodeIIIV(ins *instruction) uint32 {
1596 return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regI(ins.rs2), ins.funct7)
1597 }
1598
1599 func encodeIVIV(ins *instruction) uint32 {
1600 return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regV(ins.rs2), ins.funct7)
1601 }
1602
1603
1604 func encodeS(as obj.As, rs1, rs2, imm, funct7 uint32) uint32 {
1605 enc := encode(as)
1606 if enc == nil {
1607 panic("encodeS: could not encode instruction")
1608 }
1609 if enc.rs2 != 0 && rs2 != 0 {
1610 panic("encodeS: instruction uses rs2, but rs2 was nonzero")
1611 }
1612 rs2 |= enc.rs2
1613 imm |= uint32(enc.csr) &^ 0x1f
1614 return funct7<<25 | (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
1615 }
1616
1617 func encodeSI(ins *instruction) uint32 {
1618 return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm), 0)
1619 }
1620
1621 func encodeSF(ins *instruction) uint32 {
1622 return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm), 0)
1623 }
1624
1625 func encodeSV(ins *instruction) uint32 {
1626 return encodeS(ins.as, regI(ins.rd), 0, regV(ins.rs1), ins.funct7)
1627 }
1628
1629 func encodeSVII(ins *instruction) uint32 {
1630 return encodeS(ins.as, regI(ins.rs1), regI(ins.rs2), regV(ins.rd), ins.funct7)
1631 }
1632
1633 func encodeSVIV(ins *instruction) uint32 {
1634 return encodeS(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct7)
1635 }
1636
1637
1638 func encodeBImmediate(imm uint32) uint32 {
1639 return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
1640 }
1641
1642
1643 func encodeB(ins *instruction) uint32 {
1644 imm := immI(ins.as, ins.imm, 13)
1645 rs2 := regI(ins.rs1)
1646 rs1 := regI(ins.rs2)
1647 enc := encode(ins.as)
1648 if enc == nil {
1649 panic("encodeB: could not encode instruction")
1650 }
1651 return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
1652 }
1653
1654
1655 func encodeU(ins *instruction) uint32 {
1656
1657
1658
1659
1660 imm := immI(ins.as, ins.imm, 20)
1661 rd := regI(ins.rd)
1662 enc := encode(ins.as)
1663 if enc == nil {
1664 panic("encodeU: could not encode instruction")
1665 }
1666 return imm<<12 | rd<<7 | enc.opcode
1667 }
1668
1669
1670 func encodeJImmediate(imm uint32) uint32 {
1671 return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12
1672 }
1673
1674
1675 func encodeJ(ins *instruction) uint32 {
1676 imm := immI(ins.as, ins.imm, 21)
1677 rd := regI(ins.rd)
1678 enc := encode(ins.as)
1679 if enc == nil {
1680 panic("encodeJ: could not encode instruction")
1681 }
1682 return encodeJImmediate(imm) | rd<<7 | enc.opcode
1683 }
1684
1685
1686 func encodeCBImmediate(imm uint32) uint32 {
1687
1688 bits := extractBitAndShift(imm, 8, 7)
1689 bits |= extractBitAndShift(imm, 4, 6)
1690 bits |= extractBitAndShift(imm, 3, 5)
1691 bits |= extractBitAndShift(imm, 7, 4)
1692 bits |= extractBitAndShift(imm, 6, 3)
1693 bits |= extractBitAndShift(imm, 2, 2)
1694 bits |= extractBitAndShift(imm, 1, 1)
1695 bits |= extractBitAndShift(imm, 5, 0)
1696 return (bits>>5)<<10 | (bits&0x1f)<<2
1697 }
1698
1699
1700 func encodeCJImmediate(imm uint32) uint32 {
1701
1702 bits := extractBitAndShift(imm, 11, 10)
1703 bits |= extractBitAndShift(imm, 4, 9)
1704 bits |= extractBitAndShift(imm, 9, 8)
1705 bits |= extractBitAndShift(imm, 8, 7)
1706 bits |= extractBitAndShift(imm, 10, 6)
1707 bits |= extractBitAndShift(imm, 6, 5)
1708 bits |= extractBitAndShift(imm, 7, 4)
1709 bits |= extractBitAndShift(imm, 3, 3)
1710 bits |= extractBitAndShift(imm, 2, 2)
1711 bits |= extractBitAndShift(imm, 1, 1)
1712 bits |= extractBitAndShift(imm, 5, 0)
1713 return bits << 2
1714 }
1715
1716 func encodeVset(as obj.As, rs1, rs2, rd uint32) uint32 {
1717 enc := encode(as)
1718 if enc == nil {
1719 panic("encodeVset: could not encode instruction")
1720 }
1721 return enc.funct7<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
1722 }
1723
1724 func encodeVsetvli(ins *instruction) uint32 {
1725 vtype := immU(ins.as, ins.imm, 11)
1726 return encodeVset(ins.as, regI(ins.rs1), vtype, regI(ins.rd))
1727 }
1728
1729 func encodeVsetivli(ins *instruction) uint32 {
1730 vtype := immU(ins.as, ins.imm, 10)
1731 avl := immU(ins.as, int64(ins.rs1), 5)
1732 return encodeVset(ins.as, avl, vtype, regI(ins.rd))
1733 }
1734
1735 func encodeVsetvl(ins *instruction) uint32 {
1736 return encodeVset(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd))
1737 }
1738
1739 func encodeRawIns(ins *instruction) uint32 {
1740
1741
1742 if ins.imm < 0 || 1<<32 <= ins.imm {
1743 panic(fmt.Sprintf("immediate %d cannot fit in 32 bits", ins.imm))
1744 }
1745 return uint32(ins.imm)
1746 }
1747
1748 func EncodeBImmediate(imm int64) (int64, error) {
1749 if err := immIFits(imm, 13); err != nil {
1750 return 0, err
1751 }
1752 if err := immEven(imm); err != nil {
1753 return 0, err
1754 }
1755 return int64(encodeBImmediate(uint32(imm))), nil
1756 }
1757
1758 func EncodeCBImmediate(imm int64) (int64, error) {
1759 if err := immIFits(imm, 9); err != nil {
1760 return 0, err
1761 }
1762 if err := immEven(imm); err != nil {
1763 return 0, err
1764 }
1765 return int64(encodeCBImmediate(uint32(imm))), nil
1766 }
1767
1768 func EncodeCJImmediate(imm int64) (int64, error) {
1769 if err := immIFits(imm, 12); err != nil {
1770 return 0, err
1771 }
1772 if err := immEven(imm); err != nil {
1773 return 0, err
1774 }
1775 return int64(encodeCJImmediate(uint32(imm))), nil
1776 }
1777
1778 func EncodeIImmediate(imm int64) (int64, error) {
1779 if err := immIFits(imm, 12); err != nil {
1780 return 0, err
1781 }
1782 return imm << 20, nil
1783 }
1784
1785 func EncodeJImmediate(imm int64) (int64, error) {
1786 if err := immIFits(imm, 21); err != nil {
1787 return 0, err
1788 }
1789 if err := immEven(imm); err != nil {
1790 return 0, err
1791 }
1792 return int64(encodeJImmediate(uint32(imm))), nil
1793 }
1794
1795 func EncodeSImmediate(imm int64) (int64, error) {
1796 if err := immIFits(imm, 12); err != nil {
1797 return 0, err
1798 }
1799 return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
1800 }
1801
1802 func EncodeUImmediate(imm int64) (int64, error) {
1803 if err := immIFits(imm, 20); err != nil {
1804 return 0, err
1805 }
1806 return imm << 12, nil
1807 }
1808
1809 func EncodeVectorType(vsew, vlmul, vtail, vmask int64) (int64, error) {
1810 vsewSO := SpecialOperand(vsew)
1811 if vsewSO < SPOP_E8 || vsewSO > SPOP_E64 {
1812 return -1, fmt.Errorf("invalid vector selected element width %q", vsewSO)
1813 }
1814 vlmulSO := SpecialOperand(vlmul)
1815 if vlmulSO < SPOP_M1 || vlmulSO > SPOP_MF8 {
1816 return -1, fmt.Errorf("invalid vector register group multiplier %q", vlmulSO)
1817 }
1818 vtailSO := SpecialOperand(vtail)
1819 if vtailSO != SPOP_TA && vtailSO != SPOP_TU {
1820 return -1, fmt.Errorf("invalid vector tail policy %q", vtailSO)
1821 }
1822 vmaskSO := SpecialOperand(vmask)
1823 if vmaskSO != SPOP_MA && vmaskSO != SPOP_MU {
1824 return -1, fmt.Errorf("invalid vector mask policy %q", vmaskSO)
1825 }
1826 vtype := vmaskSO.encode()<<7 | vtailSO.encode()<<6 | vsewSO.encode()<<3 | vlmulSO.encode()
1827 return int64(vtype), nil
1828 }
1829
1830 type encoding struct {
1831 encode func(*instruction) uint32
1832 validate func(*obj.Link, *instruction)
1833 length int
1834 }
1835
1836 var (
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848 rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
1849 rIIEncoding = encoding{encode: encodeRII, validate: validateRII, length: 4}
1850 rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
1851 rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
1852 rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
1853 rFIEncoding = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
1854 rFVEncoding = encoding{encode: encodeRFV, validate: validateRFV, length: 4}
1855 rIFEncoding = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
1856 rIVEncoding = encoding{encode: encodeRIV, validate: validateRIV, length: 4}
1857 rFFEncoding = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
1858 rVFEncoding = encoding{encode: encodeRVF, validate: validateRVF, length: 4}
1859 rVFVEncoding = encoding{encode: encodeRVFV, validate: validateRVFV, length: 4}
1860 rVIEncoding = encoding{encode: encodeRVI, validate: validateRVI, length: 4}
1861 rVIVEncoding = encoding{encode: encodeRVIV, validate: validateRVIV, length: 4}
1862 rVVEncoding = encoding{encode: encodeRVV, validate: validateRVV, length: 4}
1863 rVViEncoding = encoding{encode: encodeRVVi, validate: validateRVVi, length: 4}
1864 rVVuEncoding = encoding{encode: encodeRVVu, validate: validateRVVu, length: 4}
1865 rVVVEncoding = encoding{encode: encodeRVVV, validate: validateRVVV, length: 4}
1866
1867 iIIEncoding = encoding{encode: encodeIII, validate: validateIII, length: 4}
1868 iFEncoding = encoding{encode: encodeIF, validate: validateIF, length: 4}
1869 iVEncoding = encoding{encode: encodeIV, validate: validateIV, length: 4}
1870 iIIVEncoding = encoding{encode: encodeIIIV, validate: validateIIIV, length: 4}
1871 iVIVEncoding = encoding{encode: encodeIVIV, validate: validateIVIV, length: 4}
1872
1873 sIEncoding = encoding{encode: encodeSI, validate: validateSI, length: 4}
1874 sFEncoding = encoding{encode: encodeSF, validate: validateSF, length: 4}
1875 sVEncoding = encoding{encode: encodeSV, validate: validateSV, length: 4}
1876 sVIIEncoding = encoding{encode: encodeSVII, validate: validateSVII, length: 4}
1877 sVIVEncoding = encoding{encode: encodeSVIV, validate: validateSVIV, length: 4}
1878
1879 bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
1880 uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
1881 jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
1882
1883
1884 vsetvliEncoding = encoding{encode: encodeVsetvli, validate: validateVsetvli, length: 4}
1885 vsetivliEncoding = encoding{encode: encodeVsetivli, validate: validateVsetivli, length: 4}
1886 vsetvlEncoding = encoding{encode: encodeVsetvl, validate: validateVsetvl, length: 4}
1887
1888
1889 rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
1890
1891
1892 pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
1893
1894
1895
1896 badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
1897 )
1898
1899
1900 type instructionData struct {
1901 enc encoding
1902 immForm obj.As
1903 ternary bool
1904 }
1905
1906
1907
1908
1909 var instructions = [ALAST & obj.AMask]instructionData{
1910
1911
1912
1913
1914
1915 AADDI & obj.AMask: {enc: iIIEncoding, ternary: true},
1916 ASLTI & obj.AMask: {enc: iIIEncoding, ternary: true},
1917 ASLTIU & obj.AMask: {enc: iIIEncoding, ternary: true},
1918 AANDI & obj.AMask: {enc: iIIEncoding, ternary: true},
1919 AORI & obj.AMask: {enc: iIIEncoding, ternary: true},
1920 AXORI & obj.AMask: {enc: iIIEncoding, ternary: true},
1921 ASLLI & obj.AMask: {enc: iIIEncoding, ternary: true},
1922 ASRLI & obj.AMask: {enc: iIIEncoding, ternary: true},
1923 ASRAI & obj.AMask: {enc: iIIEncoding, ternary: true},
1924 ALUI & obj.AMask: {enc: uEncoding},
1925 AAUIPC & obj.AMask: {enc: uEncoding},
1926 AADD & obj.AMask: {enc: rIIIEncoding, immForm: AADDI, ternary: true},
1927 ASLT & obj.AMask: {enc: rIIIEncoding, immForm: ASLTI, ternary: true},
1928 ASLTU & obj.AMask: {enc: rIIIEncoding, immForm: ASLTIU, ternary: true},
1929 AAND & obj.AMask: {enc: rIIIEncoding, immForm: AANDI, ternary: true},
1930 AOR & obj.AMask: {enc: rIIIEncoding, immForm: AORI, ternary: true},
1931 AXOR & obj.AMask: {enc: rIIIEncoding, immForm: AXORI, ternary: true},
1932 ASLL & obj.AMask: {enc: rIIIEncoding, immForm: ASLLI, ternary: true},
1933 ASRL & obj.AMask: {enc: rIIIEncoding, immForm: ASRLI, ternary: true},
1934 ASUB & obj.AMask: {enc: rIIIEncoding, ternary: true},
1935 ASRA & obj.AMask: {enc: rIIIEncoding, immForm: ASRAI, ternary: true},
1936
1937
1938 AJAL & obj.AMask: {enc: jEncoding},
1939 AJALR & obj.AMask: {enc: iIIEncoding},
1940 ABEQ & obj.AMask: {enc: bEncoding},
1941 ABNE & obj.AMask: {enc: bEncoding},
1942 ABLT & obj.AMask: {enc: bEncoding},
1943 ABLTU & obj.AMask: {enc: bEncoding},
1944 ABGE & obj.AMask: {enc: bEncoding},
1945 ABGEU & obj.AMask: {enc: bEncoding},
1946
1947
1948 ALW & obj.AMask: {enc: iIIEncoding},
1949 ALWU & obj.AMask: {enc: iIIEncoding},
1950 ALH & obj.AMask: {enc: iIIEncoding},
1951 ALHU & obj.AMask: {enc: iIIEncoding},
1952 ALB & obj.AMask: {enc: iIIEncoding},
1953 ALBU & obj.AMask: {enc: iIIEncoding},
1954 ASW & obj.AMask: {enc: sIEncoding},
1955 ASH & obj.AMask: {enc: sIEncoding},
1956 ASB & obj.AMask: {enc: sIEncoding},
1957
1958
1959 AFENCE & obj.AMask: {enc: iIIEncoding},
1960
1961
1962 AADDIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1963 ASLLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1964 ASRLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1965 ASRAIW & obj.AMask: {enc: iIIEncoding, ternary: true},
1966 AADDW & obj.AMask: {enc: rIIIEncoding, immForm: AADDIW, ternary: true},
1967 ASLLW & obj.AMask: {enc: rIIIEncoding, immForm: ASLLIW, ternary: true},
1968 ASRLW & obj.AMask: {enc: rIIIEncoding, immForm: ASRLIW, ternary: true},
1969 ASUBW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1970 ASRAW & obj.AMask: {enc: rIIIEncoding, immForm: ASRAIW, ternary: true},
1971
1972
1973 ALD & obj.AMask: {enc: iIIEncoding},
1974 ASD & obj.AMask: {enc: sIEncoding},
1975
1976
1977 ACSRRS & obj.AMask: {enc: iIIEncoding},
1978
1979
1980 AMUL & obj.AMask: {enc: rIIIEncoding, ternary: true},
1981 AMULH & obj.AMask: {enc: rIIIEncoding, ternary: true},
1982 AMULHU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1983 AMULHSU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1984 AMULW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1985 ADIV & obj.AMask: {enc: rIIIEncoding, ternary: true},
1986 ADIVU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1987 AREM & obj.AMask: {enc: rIIIEncoding, ternary: true},
1988 AREMU & obj.AMask: {enc: rIIIEncoding, ternary: true},
1989 ADIVW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1990 ADIVUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1991 AREMW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1992 AREMUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
1993
1994
1995 ALRW & obj.AMask: {enc: rIIIEncoding},
1996 ALRD & obj.AMask: {enc: rIIIEncoding},
1997 ASCW & obj.AMask: {enc: rIIIEncoding},
1998 ASCD & obj.AMask: {enc: rIIIEncoding},
1999
2000
2001 AAMOSWAPW & obj.AMask: {enc: rIIIEncoding},
2002 AAMOSWAPD & obj.AMask: {enc: rIIIEncoding},
2003 AAMOADDW & obj.AMask: {enc: rIIIEncoding},
2004 AAMOADDD & obj.AMask: {enc: rIIIEncoding},
2005 AAMOANDW & obj.AMask: {enc: rIIIEncoding},
2006 AAMOANDD & obj.AMask: {enc: rIIIEncoding},
2007 AAMOORW & obj.AMask: {enc: rIIIEncoding},
2008 AAMOORD & obj.AMask: {enc: rIIIEncoding},
2009 AAMOXORW & obj.AMask: {enc: rIIIEncoding},
2010 AAMOXORD & obj.AMask: {enc: rIIIEncoding},
2011 AAMOMAXW & obj.AMask: {enc: rIIIEncoding},
2012 AAMOMAXD & obj.AMask: {enc: rIIIEncoding},
2013 AAMOMAXUW & obj.AMask: {enc: rIIIEncoding},
2014 AAMOMAXUD & obj.AMask: {enc: rIIIEncoding},
2015 AAMOMINW & obj.AMask: {enc: rIIIEncoding},
2016 AAMOMIND & obj.AMask: {enc: rIIIEncoding},
2017 AAMOMINUW & obj.AMask: {enc: rIIIEncoding},
2018 AAMOMINUD & obj.AMask: {enc: rIIIEncoding},
2019
2020
2021 AFLW & obj.AMask: {enc: iFEncoding},
2022 AFSW & obj.AMask: {enc: sFEncoding},
2023
2024
2025 AFADDS & obj.AMask: {enc: rFFFEncoding},
2026 AFSUBS & obj.AMask: {enc: rFFFEncoding},
2027 AFMULS & obj.AMask: {enc: rFFFEncoding},
2028 AFDIVS & obj.AMask: {enc: rFFFEncoding},
2029 AFMINS & obj.AMask: {enc: rFFFEncoding},
2030 AFMAXS & obj.AMask: {enc: rFFFEncoding},
2031 AFSQRTS & obj.AMask: {enc: rFFFEncoding},
2032 AFMADDS & obj.AMask: {enc: rFFFFEncoding},
2033 AFMSUBS & obj.AMask: {enc: rFFFFEncoding},
2034 AFNMSUBS & obj.AMask: {enc: rFFFFEncoding},
2035 AFNMADDS & obj.AMask: {enc: rFFFFEncoding},
2036
2037
2038 AFCVTWS & obj.AMask: {enc: rFIEncoding},
2039 AFCVTLS & obj.AMask: {enc: rFIEncoding},
2040 AFCVTSW & obj.AMask: {enc: rIFEncoding},
2041 AFCVTSL & obj.AMask: {enc: rIFEncoding},
2042 AFCVTWUS & obj.AMask: {enc: rFIEncoding},
2043 AFCVTLUS & obj.AMask: {enc: rFIEncoding},
2044 AFCVTSWU & obj.AMask: {enc: rIFEncoding},
2045 AFCVTSLU & obj.AMask: {enc: rIFEncoding},
2046 AFSGNJS & obj.AMask: {enc: rFFFEncoding},
2047 AFSGNJNS & obj.AMask: {enc: rFFFEncoding},
2048 AFSGNJXS & obj.AMask: {enc: rFFFEncoding},
2049 AFMVXW & obj.AMask: {enc: rFIEncoding},
2050 AFMVWX & obj.AMask: {enc: rIFEncoding},
2051
2052
2053 AFEQS & obj.AMask: {enc: rFFIEncoding},
2054 AFLTS & obj.AMask: {enc: rFFIEncoding},
2055 AFLES & obj.AMask: {enc: rFFIEncoding},
2056
2057
2058 AFCLASSS & obj.AMask: {enc: rFIEncoding},
2059
2060
2061 AFLD & obj.AMask: {enc: iFEncoding},
2062 AFSD & obj.AMask: {enc: sFEncoding},
2063
2064
2065 AFADDD & obj.AMask: {enc: rFFFEncoding},
2066 AFSUBD & obj.AMask: {enc: rFFFEncoding},
2067 AFMULD & obj.AMask: {enc: rFFFEncoding},
2068 AFDIVD & obj.AMask: {enc: rFFFEncoding},
2069 AFMIND & obj.AMask: {enc: rFFFEncoding},
2070 AFMAXD & obj.AMask: {enc: rFFFEncoding},
2071 AFSQRTD & obj.AMask: {enc: rFFFEncoding},
2072 AFMADDD & obj.AMask: {enc: rFFFFEncoding},
2073 AFMSUBD & obj.AMask: {enc: rFFFFEncoding},
2074 AFNMSUBD & obj.AMask: {enc: rFFFFEncoding},
2075 AFNMADDD & obj.AMask: {enc: rFFFFEncoding},
2076
2077
2078 AFCVTWD & obj.AMask: {enc: rFIEncoding},
2079 AFCVTLD & obj.AMask: {enc: rFIEncoding},
2080 AFCVTDW & obj.AMask: {enc: rIFEncoding},
2081 AFCVTDL & obj.AMask: {enc: rIFEncoding},
2082 AFCVTWUD & obj.AMask: {enc: rFIEncoding},
2083 AFCVTLUD & obj.AMask: {enc: rFIEncoding},
2084 AFCVTDWU & obj.AMask: {enc: rIFEncoding},
2085 AFCVTDLU & obj.AMask: {enc: rIFEncoding},
2086 AFCVTSD & obj.AMask: {enc: rFFEncoding},
2087 AFCVTDS & obj.AMask: {enc: rFFEncoding},
2088 AFSGNJD & obj.AMask: {enc: rFFFEncoding},
2089 AFSGNJND & obj.AMask: {enc: rFFFEncoding},
2090 AFSGNJXD & obj.AMask: {enc: rFFFEncoding},
2091 AFMVXD & obj.AMask: {enc: rFIEncoding},
2092 AFMVDX & obj.AMask: {enc: rIFEncoding},
2093
2094
2095 AFEQD & obj.AMask: {enc: rFFIEncoding},
2096 AFLTD & obj.AMask: {enc: rFFIEncoding},
2097 AFLED & obj.AMask: {enc: rFFIEncoding},
2098
2099
2100 AFCLASSD & obj.AMask: {enc: rFIEncoding},
2101
2102
2103
2104
2105
2106
2107 AADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2108 ASH1ADD & obj.AMask: {enc: rIIIEncoding, ternary: true},
2109 ASH1ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2110 ASH2ADD & obj.AMask: {enc: rIIIEncoding, ternary: true},
2111 ASH2ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2112 ASH3ADD & obj.AMask: {enc: rIIIEncoding, ternary: true},
2113 ASH3ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2114 ASLLIUW & obj.AMask: {enc: iIIEncoding, ternary: true},
2115
2116
2117 AANDN & obj.AMask: {enc: rIIIEncoding, ternary: true},
2118 ACLZ & obj.AMask: {enc: rIIEncoding},
2119 ACLZW & obj.AMask: {enc: rIIEncoding},
2120 ACPOP & obj.AMask: {enc: rIIEncoding},
2121 ACPOPW & obj.AMask: {enc: rIIEncoding},
2122 ACTZ & obj.AMask: {enc: rIIEncoding},
2123 ACTZW & obj.AMask: {enc: rIIEncoding},
2124 AMAX & obj.AMask: {enc: rIIIEncoding, ternary: true},
2125 AMAXU & obj.AMask: {enc: rIIIEncoding, ternary: true},
2126 AMIN & obj.AMask: {enc: rIIIEncoding, ternary: true},
2127 AMINU & obj.AMask: {enc: rIIIEncoding, ternary: true},
2128 AORN & obj.AMask: {enc: rIIIEncoding, ternary: true},
2129 ASEXTB & obj.AMask: {enc: rIIEncoding},
2130 ASEXTH & obj.AMask: {enc: rIIEncoding},
2131 AXNOR & obj.AMask: {enc: rIIIEncoding, ternary: true},
2132 AZEXTH & obj.AMask: {enc: rIIEncoding},
2133
2134
2135 AROL & obj.AMask: {enc: rIIIEncoding, ternary: true},
2136 AROLW & obj.AMask: {enc: rIIIEncoding, ternary: true},
2137 AROR & obj.AMask: {enc: rIIIEncoding, immForm: ARORI, ternary: true},
2138 ARORI & obj.AMask: {enc: iIIEncoding, ternary: true},
2139 ARORIW & obj.AMask: {enc: iIIEncoding, ternary: true},
2140 ARORW & obj.AMask: {enc: rIIIEncoding, immForm: ARORIW, ternary: true},
2141 AORCB & obj.AMask: {enc: rIIEncoding},
2142 AREV8 & obj.AMask: {enc: rIIEncoding},
2143
2144
2145 ABCLR & obj.AMask: {enc: rIIIEncoding, immForm: ABCLRI, ternary: true},
2146 ABCLRI & obj.AMask: {enc: iIIEncoding, ternary: true},
2147 ABEXT & obj.AMask: {enc: rIIIEncoding, immForm: ABEXTI, ternary: true},
2148 ABEXTI & obj.AMask: {enc: iIIEncoding, ternary: true},
2149 ABINV & obj.AMask: {enc: rIIIEncoding, immForm: ABINVI, ternary: true},
2150 ABINVI & obj.AMask: {enc: iIIEncoding, ternary: true},
2151 ABSET & obj.AMask: {enc: rIIIEncoding, immForm: ABSETI, ternary: true},
2152 ABSETI & obj.AMask: {enc: iIIEncoding, ternary: true},
2153
2154
2155
2156
2157
2158
2159 AVSETVLI & obj.AMask: {enc: vsetvliEncoding, immForm: AVSETIVLI},
2160 AVSETIVLI & obj.AMask: {enc: vsetivliEncoding},
2161 AVSETVL & obj.AMask: {enc: vsetvlEncoding},
2162
2163
2164 AVLE8V & obj.AMask: {enc: iVEncoding},
2165 AVLE16V & obj.AMask: {enc: iVEncoding},
2166 AVLE32V & obj.AMask: {enc: iVEncoding},
2167 AVLE64V & obj.AMask: {enc: iVEncoding},
2168 AVSE8V & obj.AMask: {enc: sVEncoding},
2169 AVSE16V & obj.AMask: {enc: sVEncoding},
2170 AVSE32V & obj.AMask: {enc: sVEncoding},
2171 AVSE64V & obj.AMask: {enc: sVEncoding},
2172 AVLMV & obj.AMask: {enc: iVEncoding},
2173 AVSMV & obj.AMask: {enc: sVEncoding},
2174
2175
2176 AVLSE8V & obj.AMask: {enc: iIIVEncoding},
2177 AVLSE16V & obj.AMask: {enc: iIIVEncoding},
2178 AVLSE32V & obj.AMask: {enc: iIIVEncoding},
2179 AVLSE64V & obj.AMask: {enc: iIIVEncoding},
2180 AVSSE8V & obj.AMask: {enc: sVIIEncoding},
2181 AVSSE16V & obj.AMask: {enc: sVIIEncoding},
2182 AVSSE32V & obj.AMask: {enc: sVIIEncoding},
2183 AVSSE64V & obj.AMask: {enc: sVIIEncoding},
2184
2185
2186 AVLUXEI8V & obj.AMask: {enc: iVIVEncoding},
2187 AVLUXEI16V & obj.AMask: {enc: iVIVEncoding},
2188 AVLUXEI32V & obj.AMask: {enc: iVIVEncoding},
2189 AVLUXEI64V & obj.AMask: {enc: iVIVEncoding},
2190 AVLOXEI8V & obj.AMask: {enc: iVIVEncoding},
2191 AVLOXEI16V & obj.AMask: {enc: iVIVEncoding},
2192 AVLOXEI32V & obj.AMask: {enc: iVIVEncoding},
2193 AVLOXEI64V & obj.AMask: {enc: iVIVEncoding},
2194 AVSUXEI8V & obj.AMask: {enc: sVIVEncoding},
2195 AVSUXEI16V & obj.AMask: {enc: sVIVEncoding},
2196 AVSUXEI32V & obj.AMask: {enc: sVIVEncoding},
2197 AVSUXEI64V & obj.AMask: {enc: sVIVEncoding},
2198 AVSOXEI8V & obj.AMask: {enc: sVIVEncoding},
2199 AVSOXEI16V & obj.AMask: {enc: sVIVEncoding},
2200 AVSOXEI32V & obj.AMask: {enc: sVIVEncoding},
2201 AVSOXEI64V & obj.AMask: {enc: sVIVEncoding},
2202
2203
2204 AVL1RE8V & obj.AMask: {enc: iVEncoding},
2205 AVL1RE16V & obj.AMask: {enc: iVEncoding},
2206 AVL1RE32V & obj.AMask: {enc: iVEncoding},
2207 AVL1RE64V & obj.AMask: {enc: iVEncoding},
2208 AVL2RE8V & obj.AMask: {enc: iVEncoding},
2209 AVL2RE16V & obj.AMask: {enc: iVEncoding},
2210 AVL2RE32V & obj.AMask: {enc: iVEncoding},
2211 AVL2RE64V & obj.AMask: {enc: iVEncoding},
2212 AVL4RE8V & obj.AMask: {enc: iVEncoding},
2213 AVL4RE16V & obj.AMask: {enc: iVEncoding},
2214 AVL4RE32V & obj.AMask: {enc: iVEncoding},
2215 AVL4RE64V & obj.AMask: {enc: iVEncoding},
2216 AVL8RE8V & obj.AMask: {enc: iVEncoding},
2217 AVL8RE16V & obj.AMask: {enc: iVEncoding},
2218 AVL8RE32V & obj.AMask: {enc: iVEncoding},
2219 AVL8RE64V & obj.AMask: {enc: iVEncoding},
2220 AVS1RV & obj.AMask: {enc: sVEncoding},
2221 AVS2RV & obj.AMask: {enc: sVEncoding},
2222 AVS4RV & obj.AMask: {enc: sVEncoding},
2223 AVS8RV & obj.AMask: {enc: sVEncoding},
2224
2225
2226 AVADDVV & obj.AMask: {enc: rVVVEncoding},
2227 AVADDVX & obj.AMask: {enc: rVIVEncoding},
2228 AVADDVI & obj.AMask: {enc: rVViEncoding},
2229 AVSUBVV & obj.AMask: {enc: rVVVEncoding},
2230 AVSUBVX & obj.AMask: {enc: rVIVEncoding},
2231 AVRSUBVX & obj.AMask: {enc: rVIVEncoding},
2232 AVRSUBVI & obj.AMask: {enc: rVViEncoding},
2233
2234
2235 AVWADDUVV & obj.AMask: {enc: rVVVEncoding},
2236 AVWADDUVX & obj.AMask: {enc: rVIVEncoding},
2237 AVWSUBUVV & obj.AMask: {enc: rVVVEncoding},
2238 AVWSUBUVX & obj.AMask: {enc: rVIVEncoding},
2239 AVWADDVV & obj.AMask: {enc: rVVVEncoding},
2240 AVWADDVX & obj.AMask: {enc: rVIVEncoding},
2241 AVWSUBVV & obj.AMask: {enc: rVVVEncoding},
2242 AVWSUBVX & obj.AMask: {enc: rVIVEncoding},
2243 AVWADDUWV & obj.AMask: {enc: rVVVEncoding},
2244 AVWADDUWX & obj.AMask: {enc: rVIVEncoding},
2245 AVWSUBUWV & obj.AMask: {enc: rVVVEncoding},
2246 AVWSUBUWX & obj.AMask: {enc: rVIVEncoding},
2247 AVWADDWV & obj.AMask: {enc: rVVVEncoding},
2248 AVWADDWX & obj.AMask: {enc: rVIVEncoding},
2249 AVWSUBWV & obj.AMask: {enc: rVVVEncoding},
2250 AVWSUBWX & obj.AMask: {enc: rVIVEncoding},
2251
2252
2253 AVZEXTVF2 & obj.AMask: {enc: rVVEncoding},
2254 AVSEXTVF2 & obj.AMask: {enc: rVVEncoding},
2255 AVZEXTVF4 & obj.AMask: {enc: rVVEncoding},
2256 AVSEXTVF4 & obj.AMask: {enc: rVVEncoding},
2257 AVZEXTVF8 & obj.AMask: {enc: rVVEncoding},
2258 AVSEXTVF8 & obj.AMask: {enc: rVVEncoding},
2259
2260
2261 AVADCVVM & obj.AMask: {enc: rVVVEncoding},
2262 AVADCVXM & obj.AMask: {enc: rVIVEncoding},
2263 AVADCVIM & obj.AMask: {enc: rVViEncoding},
2264 AVMADCVVM & obj.AMask: {enc: rVVVEncoding},
2265 AVMADCVXM & obj.AMask: {enc: rVIVEncoding},
2266 AVMADCVIM & obj.AMask: {enc: rVViEncoding},
2267 AVMADCVV & obj.AMask: {enc: rVVVEncoding},
2268 AVMADCVX & obj.AMask: {enc: rVIVEncoding},
2269 AVMADCVI & obj.AMask: {enc: rVViEncoding},
2270 AVSBCVVM & obj.AMask: {enc: rVVVEncoding},
2271 AVSBCVXM & obj.AMask: {enc: rVIVEncoding},
2272 AVMSBCVVM & obj.AMask: {enc: rVVVEncoding},
2273 AVMSBCVXM & obj.AMask: {enc: rVIVEncoding},
2274 AVMSBCVV & obj.AMask: {enc: rVVVEncoding},
2275 AVMSBCVX & obj.AMask: {enc: rVIVEncoding},
2276
2277
2278 AVANDVV & obj.AMask: {enc: rVVVEncoding},
2279 AVANDVX & obj.AMask: {enc: rVIVEncoding},
2280 AVANDVI & obj.AMask: {enc: rVViEncoding},
2281 AVORVV & obj.AMask: {enc: rVVVEncoding},
2282 AVORVX & obj.AMask: {enc: rVIVEncoding},
2283 AVORVI & obj.AMask: {enc: rVViEncoding},
2284 AVXORVV & obj.AMask: {enc: rVVVEncoding},
2285 AVXORVX & obj.AMask: {enc: rVIVEncoding},
2286 AVXORVI & obj.AMask: {enc: rVViEncoding},
2287
2288
2289 AVSLLVV & obj.AMask: {enc: rVVVEncoding},
2290 AVSLLVX & obj.AMask: {enc: rVIVEncoding},
2291 AVSLLVI & obj.AMask: {enc: rVVuEncoding},
2292 AVSRLVV & obj.AMask: {enc: rVVVEncoding},
2293 AVSRLVX & obj.AMask: {enc: rVIVEncoding},
2294 AVSRLVI & obj.AMask: {enc: rVVuEncoding},
2295 AVSRAVV & obj.AMask: {enc: rVVVEncoding},
2296 AVSRAVX & obj.AMask: {enc: rVIVEncoding},
2297 AVSRAVI & obj.AMask: {enc: rVVuEncoding},
2298
2299
2300 AVNSRLWV & obj.AMask: {enc: rVVVEncoding},
2301 AVNSRLWX & obj.AMask: {enc: rVIVEncoding},
2302 AVNSRLWI & obj.AMask: {enc: rVVuEncoding},
2303 AVNSRAWV & obj.AMask: {enc: rVVVEncoding},
2304 AVNSRAWX & obj.AMask: {enc: rVIVEncoding},
2305 AVNSRAWI & obj.AMask: {enc: rVVuEncoding},
2306
2307
2308 AVMSEQVV & obj.AMask: {enc: rVVVEncoding},
2309 AVMSEQVX & obj.AMask: {enc: rVIVEncoding},
2310 AVMSEQVI & obj.AMask: {enc: rVViEncoding},
2311 AVMSNEVV & obj.AMask: {enc: rVVVEncoding},
2312 AVMSNEVX & obj.AMask: {enc: rVIVEncoding},
2313 AVMSNEVI & obj.AMask: {enc: rVViEncoding},
2314 AVMSLTUVV & obj.AMask: {enc: rVVVEncoding},
2315 AVMSLTUVX & obj.AMask: {enc: rVIVEncoding},
2316 AVMSLTVV & obj.AMask: {enc: rVVVEncoding},
2317 AVMSLTVX & obj.AMask: {enc: rVIVEncoding},
2318 AVMSLEUVV & obj.AMask: {enc: rVVVEncoding},
2319 AVMSLEUVX & obj.AMask: {enc: rVIVEncoding},
2320 AVMSLEUVI & obj.AMask: {enc: rVViEncoding},
2321 AVMSLEVV & obj.AMask: {enc: rVVVEncoding},
2322 AVMSLEVX & obj.AMask: {enc: rVIVEncoding},
2323 AVMSLEVI & obj.AMask: {enc: rVViEncoding},
2324 AVMSGTUVX & obj.AMask: {enc: rVIVEncoding},
2325 AVMSGTUVI & obj.AMask: {enc: rVViEncoding},
2326 AVMSGTVX & obj.AMask: {enc: rVIVEncoding},
2327 AVMSGTVI & obj.AMask: {enc: rVViEncoding},
2328
2329
2330 AVMINUVV & obj.AMask: {enc: rVVVEncoding},
2331 AVMINUVX & obj.AMask: {enc: rVIVEncoding},
2332 AVMINVV & obj.AMask: {enc: rVVVEncoding},
2333 AVMINVX & obj.AMask: {enc: rVIVEncoding},
2334 AVMAXUVV & obj.AMask: {enc: rVVVEncoding},
2335 AVMAXUVX & obj.AMask: {enc: rVIVEncoding},
2336 AVMAXVV & obj.AMask: {enc: rVVVEncoding},
2337 AVMAXVX & obj.AMask: {enc: rVIVEncoding},
2338
2339
2340 AVMULVV & obj.AMask: {enc: rVVVEncoding},
2341 AVMULVX & obj.AMask: {enc: rVIVEncoding},
2342 AVMULHVV & obj.AMask: {enc: rVVVEncoding},
2343 AVMULHVX & obj.AMask: {enc: rVIVEncoding},
2344 AVMULHUVV & obj.AMask: {enc: rVVVEncoding},
2345 AVMULHUVX & obj.AMask: {enc: rVIVEncoding},
2346 AVMULHSUVV & obj.AMask: {enc: rVVVEncoding},
2347 AVMULHSUVX & obj.AMask: {enc: rVIVEncoding},
2348
2349
2350 AVDIVUVV & obj.AMask: {enc: rVVVEncoding},
2351 AVDIVUVX & obj.AMask: {enc: rVIVEncoding},
2352 AVDIVVV & obj.AMask: {enc: rVVVEncoding},
2353 AVDIVVX & obj.AMask: {enc: rVIVEncoding},
2354 AVREMUVV & obj.AMask: {enc: rVVVEncoding},
2355 AVREMUVX & obj.AMask: {enc: rVIVEncoding},
2356 AVREMVV & obj.AMask: {enc: rVVVEncoding},
2357 AVREMVX & obj.AMask: {enc: rVIVEncoding},
2358
2359
2360 AVWMULVV & obj.AMask: {enc: rVVVEncoding},
2361 AVWMULVX & obj.AMask: {enc: rVIVEncoding},
2362 AVWMULUVV & obj.AMask: {enc: rVVVEncoding},
2363 AVWMULUVX & obj.AMask: {enc: rVIVEncoding},
2364 AVWMULSUVV & obj.AMask: {enc: rVVVEncoding},
2365 AVWMULSUVX & obj.AMask: {enc: rVIVEncoding},
2366
2367
2368 AVMACCVV & obj.AMask: {enc: rVVVEncoding},
2369 AVMACCVX & obj.AMask: {enc: rVIVEncoding},
2370 AVNMSACVV & obj.AMask: {enc: rVVVEncoding},
2371 AVNMSACVX & obj.AMask: {enc: rVIVEncoding},
2372 AVMADDVV & obj.AMask: {enc: rVVVEncoding},
2373 AVMADDVX & obj.AMask: {enc: rVIVEncoding},
2374 AVNMSUBVV & obj.AMask: {enc: rVVVEncoding},
2375 AVNMSUBVX & obj.AMask: {enc: rVIVEncoding},
2376
2377
2378 AVWMACCUVV & obj.AMask: {enc: rVVVEncoding},
2379 AVWMACCUVX & obj.AMask: {enc: rVIVEncoding},
2380 AVWMACCVV & obj.AMask: {enc: rVVVEncoding},
2381 AVWMACCVX & obj.AMask: {enc: rVIVEncoding},
2382 AVWMACCSUVV & obj.AMask: {enc: rVVVEncoding},
2383 AVWMACCSUVX & obj.AMask: {enc: rVIVEncoding},
2384 AVWMACCUSVX & obj.AMask: {enc: rVIVEncoding},
2385
2386
2387 AVMERGEVVM & obj.AMask: {enc: rVVVEncoding},
2388 AVMERGEVXM & obj.AMask: {enc: rVIVEncoding},
2389 AVMERGEVIM & obj.AMask: {enc: rVViEncoding},
2390
2391
2392 AVMVVV & obj.AMask: {enc: rVVVEncoding},
2393 AVMVVX & obj.AMask: {enc: rVIVEncoding},
2394 AVMVVI & obj.AMask: {enc: rVViEncoding},
2395
2396
2397 AVSADDUVV & obj.AMask: {enc: rVVVEncoding},
2398 AVSADDUVX & obj.AMask: {enc: rVIVEncoding},
2399 AVSADDUVI & obj.AMask: {enc: rVViEncoding},
2400 AVSADDVV & obj.AMask: {enc: rVVVEncoding},
2401 AVSADDVX & obj.AMask: {enc: rVIVEncoding},
2402 AVSADDVI & obj.AMask: {enc: rVViEncoding},
2403 AVSSUBUVV & obj.AMask: {enc: rVVVEncoding},
2404 AVSSUBUVX & obj.AMask: {enc: rVIVEncoding},
2405 AVSSUBVV & obj.AMask: {enc: rVVVEncoding},
2406 AVSSUBVX & obj.AMask: {enc: rVIVEncoding},
2407
2408
2409 AVAADDUVV & obj.AMask: {enc: rVVVEncoding},
2410 AVAADDUVX & obj.AMask: {enc: rVIVEncoding},
2411 AVAADDVV & obj.AMask: {enc: rVVVEncoding},
2412 AVAADDVX & obj.AMask: {enc: rVIVEncoding},
2413 AVASUBUVV & obj.AMask: {enc: rVVVEncoding},
2414 AVASUBUVX & obj.AMask: {enc: rVIVEncoding},
2415 AVASUBVV & obj.AMask: {enc: rVVVEncoding},
2416 AVASUBVX & obj.AMask: {enc: rVIVEncoding},
2417
2418
2419 AVSMULVV & obj.AMask: {enc: rVVVEncoding},
2420 AVSMULVX & obj.AMask: {enc: rVIVEncoding},
2421
2422
2423 AVSSRLVV & obj.AMask: {enc: rVVVEncoding},
2424 AVSSRLVX & obj.AMask: {enc: rVIVEncoding},
2425 AVSSRLVI & obj.AMask: {enc: rVVuEncoding},
2426 AVSSRAVV & obj.AMask: {enc: rVVVEncoding},
2427 AVSSRAVX & obj.AMask: {enc: rVIVEncoding},
2428 AVSSRAVI & obj.AMask: {enc: rVVuEncoding},
2429
2430
2431 AVNCLIPUWV & obj.AMask: {enc: rVVVEncoding},
2432 AVNCLIPUWX & obj.AMask: {enc: rVIVEncoding},
2433 AVNCLIPUWI & obj.AMask: {enc: rVVuEncoding},
2434 AVNCLIPWV & obj.AMask: {enc: rVVVEncoding},
2435 AVNCLIPWX & obj.AMask: {enc: rVIVEncoding},
2436 AVNCLIPWI & obj.AMask: {enc: rVVuEncoding},
2437
2438
2439 AVFADDVV & obj.AMask: {enc: rVVVEncoding},
2440 AVFADDVF & obj.AMask: {enc: rVFVEncoding},
2441 AVFSUBVV & obj.AMask: {enc: rVVVEncoding},
2442 AVFSUBVF & obj.AMask: {enc: rVFVEncoding},
2443 AVFRSUBVF & obj.AMask: {enc: rVFVEncoding},
2444
2445
2446 AVFWADDVV & obj.AMask: {enc: rVVVEncoding},
2447 AVFWADDVF & obj.AMask: {enc: rVFVEncoding},
2448 AVFWSUBVV & obj.AMask: {enc: rVVVEncoding},
2449 AVFWSUBVF & obj.AMask: {enc: rVFVEncoding},
2450 AVFWADDWV & obj.AMask: {enc: rVVVEncoding},
2451 AVFWADDWF & obj.AMask: {enc: rVFVEncoding},
2452 AVFWSUBWV & obj.AMask: {enc: rVVVEncoding},
2453 AVFWSUBWF & obj.AMask: {enc: rVFVEncoding},
2454
2455
2456 AVFMULVV & obj.AMask: {enc: rVVVEncoding},
2457 AVFMULVF & obj.AMask: {enc: rVFVEncoding},
2458 AVFDIVVV & obj.AMask: {enc: rVVVEncoding},
2459 AVFDIVVF & obj.AMask: {enc: rVFVEncoding},
2460 AVFRDIVVF & obj.AMask: {enc: rVFVEncoding},
2461
2462
2463 AVFWMULVV & obj.AMask: {enc: rVVVEncoding},
2464 AVFWMULVF & obj.AMask: {enc: rVFVEncoding},
2465
2466
2467 AVFMACCVV & obj.AMask: {enc: rVVVEncoding},
2468 AVFMACCVF & obj.AMask: {enc: rVFVEncoding},
2469 AVFNMACCVV & obj.AMask: {enc: rVVVEncoding},
2470 AVFNMACCVF & obj.AMask: {enc: rVFVEncoding},
2471 AVFMSACVV & obj.AMask: {enc: rVVVEncoding},
2472 AVFMSACVF & obj.AMask: {enc: rVFVEncoding},
2473 AVFNMSACVV & obj.AMask: {enc: rVVVEncoding},
2474 AVFNMSACVF & obj.AMask: {enc: rVFVEncoding},
2475 AVFMADDVV & obj.AMask: {enc: rVVVEncoding},
2476 AVFMADDVF & obj.AMask: {enc: rVFVEncoding},
2477 AVFNMADDVV & obj.AMask: {enc: rVVVEncoding},
2478 AVFNMADDVF & obj.AMask: {enc: rVFVEncoding},
2479 AVFMSUBVV & obj.AMask: {enc: rVVVEncoding},
2480 AVFMSUBVF & obj.AMask: {enc: rVFVEncoding},
2481 AVFNMSUBVV & obj.AMask: {enc: rVVVEncoding},
2482 AVFNMSUBVF & obj.AMask: {enc: rVFVEncoding},
2483
2484
2485 AVFWMACCVV & obj.AMask: {enc: rVVVEncoding},
2486 AVFWMACCVF & obj.AMask: {enc: rVFVEncoding},
2487 AVFWNMACCVV & obj.AMask: {enc: rVVVEncoding},
2488 AVFWNMACCVF & obj.AMask: {enc: rVFVEncoding},
2489 AVFWMSACVV & obj.AMask: {enc: rVVVEncoding},
2490 AVFWMSACVF & obj.AMask: {enc: rVFVEncoding},
2491 AVFWNMSACVV & obj.AMask: {enc: rVVVEncoding},
2492 AVFWNMSACVF & obj.AMask: {enc: rVFVEncoding},
2493
2494
2495 AVFSQRTV & obj.AMask: {enc: rVVEncoding},
2496
2497
2498 AVFRSQRT7V & obj.AMask: {enc: rVVEncoding},
2499
2500
2501 AVFREC7V & obj.AMask: {enc: rVVEncoding},
2502
2503
2504 AVFMINVV & obj.AMask: {enc: rVVVEncoding},
2505 AVFMINVF & obj.AMask: {enc: rVFVEncoding},
2506 AVFMAXVV & obj.AMask: {enc: rVVVEncoding},
2507 AVFMAXVF & obj.AMask: {enc: rVFVEncoding},
2508
2509
2510 AVFSGNJVV & obj.AMask: {enc: rVVVEncoding},
2511 AVFSGNJVF & obj.AMask: {enc: rVFVEncoding},
2512 AVFSGNJNVV & obj.AMask: {enc: rVVVEncoding},
2513 AVFSGNJNVF & obj.AMask: {enc: rVFVEncoding},
2514 AVFSGNJXVV & obj.AMask: {enc: rVVVEncoding},
2515 AVFSGNJXVF & obj.AMask: {enc: rVFVEncoding},
2516
2517
2518 AVMFEQVV & obj.AMask: {enc: rVVVEncoding},
2519 AVMFEQVF & obj.AMask: {enc: rVFVEncoding},
2520 AVMFNEVV & obj.AMask: {enc: rVVVEncoding},
2521 AVMFNEVF & obj.AMask: {enc: rVFVEncoding},
2522 AVMFLTVV & obj.AMask: {enc: rVVVEncoding},
2523 AVMFLTVF & obj.AMask: {enc: rVFVEncoding},
2524 AVMFLEVV & obj.AMask: {enc: rVVVEncoding},
2525 AVMFLEVF & obj.AMask: {enc: rVFVEncoding},
2526 AVMFGTVF & obj.AMask: {enc: rVFVEncoding},
2527 AVMFGEVF & obj.AMask: {enc: rVFVEncoding},
2528
2529
2530 AVFCLASSV & obj.AMask: {enc: rVVEncoding},
2531
2532
2533 AVFMERGEVFM & obj.AMask: {enc: rVFVEncoding},
2534
2535
2536 AVFMVVF & obj.AMask: {enc: rVFVEncoding},
2537
2538
2539 AVFCVTXUFV & obj.AMask: {enc: rVVEncoding},
2540 AVFCVTXFV & obj.AMask: {enc: rVVEncoding},
2541 AVFCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
2542 AVFCVTRTZXFV & obj.AMask: {enc: rVVEncoding},
2543 AVFCVTFXUV & obj.AMask: {enc: rVVEncoding},
2544 AVFCVTFXV & obj.AMask: {enc: rVVEncoding},
2545
2546
2547 AVFWCVTXUFV & obj.AMask: {enc: rVVEncoding},
2548 AVFWCVTXFV & obj.AMask: {enc: rVVEncoding},
2549 AVFWCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
2550 AVFWCVTRTZXFV & obj.AMask: {enc: rVVEncoding},
2551 AVFWCVTFXUV & obj.AMask: {enc: rVVEncoding},
2552 AVFWCVTFXV & obj.AMask: {enc: rVVEncoding},
2553 AVFWCVTFFV & obj.AMask: {enc: rVVEncoding},
2554
2555
2556 AVFNCVTXUFW & obj.AMask: {enc: rVVEncoding},
2557 AVFNCVTXFW & obj.AMask: {enc: rVVEncoding},
2558 AVFNCVTRTZXUFW & obj.AMask: {enc: rVVEncoding},
2559 AVFNCVTRTZXFW & obj.AMask: {enc: rVVEncoding},
2560 AVFNCVTFXUW & obj.AMask: {enc: rVVEncoding},
2561 AVFNCVTFXW & obj.AMask: {enc: rVVEncoding},
2562 AVFNCVTFFW & obj.AMask: {enc: rVVEncoding},
2563 AVFNCVTRODFFW & obj.AMask: {enc: rVVEncoding},
2564
2565
2566 AVREDSUMVS & obj.AMask: {enc: rVVVEncoding},
2567 AVREDMAXUVS & obj.AMask: {enc: rVVVEncoding},
2568 AVREDMAXVS & obj.AMask: {enc: rVVVEncoding},
2569 AVREDMINUVS & obj.AMask: {enc: rVVVEncoding},
2570 AVREDMINVS & obj.AMask: {enc: rVVVEncoding},
2571 AVREDANDVS & obj.AMask: {enc: rVVVEncoding},
2572 AVREDORVS & obj.AMask: {enc: rVVVEncoding},
2573 AVREDXORVS & obj.AMask: {enc: rVVVEncoding},
2574
2575
2576 AVWREDSUMUVS & obj.AMask: {enc: rVVVEncoding},
2577 AVWREDSUMVS & obj.AMask: {enc: rVVVEncoding},
2578
2579
2580 AVFREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
2581 AVFREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
2582 AVFREDMAXVS & obj.AMask: {enc: rVVVEncoding},
2583 AVFREDMINVS & obj.AMask: {enc: rVVVEncoding},
2584
2585
2586 AVFWREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
2587 AVFWREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
2588
2589
2590 AVMANDMM & obj.AMask: {enc: rVVVEncoding},
2591 AVMNANDMM & obj.AMask: {enc: rVVVEncoding},
2592 AVMANDNMM & obj.AMask: {enc: rVVVEncoding},
2593 AVMXORMM & obj.AMask: {enc: rVVVEncoding},
2594 AVMORMM & obj.AMask: {enc: rVVVEncoding},
2595 AVMNORMM & obj.AMask: {enc: rVVVEncoding},
2596 AVMORNMM & obj.AMask: {enc: rVVVEncoding},
2597 AVMXNORMM & obj.AMask: {enc: rVVVEncoding},
2598 AVCPOPM & obj.AMask: {enc: rVIEncoding},
2599 AVFIRSTM & obj.AMask: {enc: rVIEncoding},
2600 AVMSBFM & obj.AMask: {enc: rVVEncoding},
2601 AVMSIFM & obj.AMask: {enc: rVVEncoding},
2602 AVMSOFM & obj.AMask: {enc: rVVEncoding},
2603 AVIOTAM & obj.AMask: {enc: rVVEncoding},
2604 AVIDV & obj.AMask: {enc: rVVEncoding},
2605
2606
2607 AVMVXS & obj.AMask: {enc: rVIEncoding},
2608 AVMVSX & obj.AMask: {enc: rIVEncoding},
2609
2610
2611 AVFMVFS & obj.AMask: {enc: rVFEncoding},
2612 AVFMVSF & obj.AMask: {enc: rFVEncoding},
2613
2614
2615 AVSLIDEUPVX & obj.AMask: {enc: rVIVEncoding},
2616 AVSLIDEUPVI & obj.AMask: {enc: rVVuEncoding},
2617 AVSLIDEDOWNVX & obj.AMask: {enc: rVIVEncoding},
2618 AVSLIDEDOWNVI & obj.AMask: {enc: rVVuEncoding},
2619 AVSLIDE1UPVX & obj.AMask: {enc: rVIVEncoding},
2620 AVFSLIDE1UPVF & obj.AMask: {enc: rVFVEncoding},
2621 AVSLIDE1DOWNVX & obj.AMask: {enc: rVIVEncoding},
2622 AVFSLIDE1DOWNVF & obj.AMask: {enc: rVFVEncoding},
2623
2624
2625 AVRGATHERVV & obj.AMask: {enc: rVVVEncoding},
2626 AVRGATHEREI16VV & obj.AMask: {enc: rVVVEncoding},
2627 AVRGATHERVX & obj.AMask: {enc: rVIVEncoding},
2628 AVRGATHERVI & obj.AMask: {enc: rVVuEncoding},
2629
2630
2631 AVCOMPRESSVM & obj.AMask: {enc: rVVVEncoding},
2632
2633
2634 AVMV1RV & obj.AMask: {enc: rVVEncoding},
2635 AVMV2RV & obj.AMask: {enc: rVVEncoding},
2636 AVMV4RV & obj.AMask: {enc: rVVEncoding},
2637 AVMV8RV & obj.AMask: {enc: rVVEncoding},
2638
2639
2640
2641
2642
2643
2644 AECALL & obj.AMask: {enc: iIIEncoding},
2645 AEBREAK & obj.AMask: {enc: iIIEncoding},
2646
2647
2648 AWORD & obj.AMask: {enc: rawEncoding},
2649
2650
2651 obj.AFUNCDATA: {enc: pseudoOpEncoding},
2652 obj.APCDATA: {enc: pseudoOpEncoding},
2653 obj.ATEXT: {enc: pseudoOpEncoding},
2654 obj.ANOP: {enc: pseudoOpEncoding},
2655 obj.ADUFFZERO: {enc: pseudoOpEncoding},
2656 obj.ADUFFCOPY: {enc: pseudoOpEncoding},
2657 obj.APCALIGN: {enc: pseudoOpEncoding},
2658 }
2659
2660
2661 func instructionDataForAs(as obj.As) (*instructionData, error) {
2662 if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
2663 return nil, fmt.Errorf("%v is not a RISC-V instruction", as)
2664 }
2665 asi := as & obj.AMask
2666 if int(asi) >= len(instructions) {
2667 return nil, fmt.Errorf("bad RISC-V instruction %v", as)
2668 }
2669 return &instructions[asi], nil
2670 }
2671
2672
2673 func encodingForAs(as obj.As) (*encoding, error) {
2674 insData, err := instructionDataForAs(as)
2675 if err != nil {
2676 return &badEncoding, err
2677 }
2678 if insData.enc.validate == nil {
2679 return &badEncoding, fmt.Errorf("no encoding for instruction %s", as)
2680 }
2681 return &insData.enc, nil
2682 }
2683
2684
2685
2686 func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) {
2687
2688 lsh = bits.TrailingZeros64(uint64(v))
2689 c := v >> lsh
2690 if int64(int32(c)) == c {
2691 return c, lsh, 0, true
2692 }
2693
2694
2695 rsh = bits.LeadingZeros64(uint64(v))
2696 ones := bits.OnesCount64((uint64(v) >> lsh) >> 11)
2697 c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
2698 if rsh+ones+lsh+11 == 64 {
2699 if lsh > 0 || c != -1 {
2700 lsh += rsh
2701 }
2702 return c, lsh, rsh, true
2703 }
2704
2705 return 0, 0, 0, false
2706 }
2707
2708
2709
2710 func isShiftConst(v int64) bool {
2711 _, lsh, rsh, ok := splitShiftConst(v)
2712 return ok && (lsh > 0 || rsh > 0)
2713 }
2714
2715 type instruction struct {
2716 p *obj.Prog
2717 as obj.As
2718 rd uint32
2719 rs1 uint32
2720 rs2 uint32
2721 rs3 uint32
2722 imm int64
2723 funct3 uint32
2724 funct7 uint32
2725 }
2726
2727 func (ins *instruction) String() string {
2728 if ins.p == nil {
2729 return ins.as.String()
2730 }
2731 var suffix string
2732 if ins.p.As != ins.as {
2733 suffix = fmt.Sprintf(" (%v)", ins.as)
2734 }
2735 return fmt.Sprintf("%v%v", ins.p, suffix)
2736 }
2737
2738 func (ins *instruction) encode() (uint32, error) {
2739 enc, err := encodingForAs(ins.as)
2740 if err != nil {
2741 return 0, err
2742 }
2743 if enc.length <= 0 {
2744 return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
2745 }
2746 return enc.encode(ins), nil
2747 }
2748
2749 func (ins *instruction) length() int {
2750 enc, err := encodingForAs(ins.as)
2751 if err != nil {
2752 return 0
2753 }
2754 return enc.length
2755 }
2756
2757 func (ins *instruction) validate(ctxt *obj.Link) {
2758 enc, err := encodingForAs(ins.as)
2759 if err != nil {
2760 ctxt.Diag(err.Error())
2761 return
2762 }
2763 enc.validate(ctxt, ins)
2764 }
2765
2766 func (ins *instruction) usesRegTmp() bool {
2767 return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
2768 }
2769
2770
2771 func instructionForProg(p *obj.Prog) *instruction {
2772 ins := &instruction{
2773 as: p.As,
2774 rd: uint32(p.To.Reg),
2775 rs1: uint32(p.Reg),
2776 rs2: uint32(p.From.Reg),
2777 imm: p.From.Offset,
2778 }
2779 if len(p.RestArgs) == 1 {
2780 ins.rs3 = uint32(p.RestArgs[0].Reg)
2781 }
2782 return ins
2783 }
2784
2785
2786
2787
2788 func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
2789
2790 ins := instructionForProg(p)
2791 ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
2792
2793 low, high, err := Split32BitImmediate(ins.imm)
2794 if err != nil {
2795 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err)
2796 return nil
2797 }
2798 if high == 0 {
2799 return []*instruction{ins}
2800 }
2801
2802
2803
2804 if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
2805 imm0 := ins.imm / 2
2806 imm1 := ins.imm - imm0
2807
2808
2809
2810 ins.imm = imm0
2811 insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
2812 return []*instruction{ins, insADDI}
2813 }
2814
2815
2816
2817
2818 insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
2819 insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
2820 switch ins.as {
2821 case AADDI:
2822 ins.as = AADD
2823 case AANDI:
2824 ins.as = AAND
2825 case AORI:
2826 ins.as = AOR
2827 case AXORI:
2828 ins.as = AXOR
2829 default:
2830 p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
2831 return nil
2832 }
2833 ins.rs2 = REG_TMP
2834 if low == 0 {
2835 return []*instruction{insLUI, ins}
2836 }
2837 return []*instruction{insLUI, insADDIW, ins}
2838 }
2839
2840
2841
2842
2843 func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
2844 if p.From.Type != obj.TYPE_MEM {
2845 p.Ctxt.Diag("%v requires memory for source", p)
2846 return nil
2847 }
2848
2849 switch as {
2850 case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
2851 default:
2852 p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
2853 return nil
2854 }
2855
2856
2857 ins := instructionForProg(p)
2858 ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
2859 ins.imm = p.From.Offset
2860
2861 low, high, err := Split32BitImmediate(ins.imm)
2862 if err != nil {
2863 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
2864 return nil
2865 }
2866 if high == 0 {
2867 return []*instruction{ins}
2868 }
2869
2870
2871
2872
2873 insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
2874 insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
2875 ins.rs1, ins.imm = REG_TMP, low
2876
2877 return []*instruction{insLUI, insADD, ins}
2878 }
2879
2880
2881
2882
2883 func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
2884 if p.To.Type != obj.TYPE_MEM {
2885 p.Ctxt.Diag("%v requires memory for destination", p)
2886 return nil
2887 }
2888
2889 switch as {
2890 case ASW, ASH, ASB, ASD, AFSW, AFSD:
2891 default:
2892 p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
2893 return nil
2894 }
2895
2896
2897 ins := instructionForProg(p)
2898 ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
2899 ins.imm = p.To.Offset
2900
2901 low, high, err := Split32BitImmediate(ins.imm)
2902 if err != nil {
2903 p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
2904 return nil
2905 }
2906 if high == 0 {
2907 return []*instruction{ins}
2908 }
2909
2910
2911
2912
2913 insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
2914 insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
2915 ins.rd, ins.imm = REG_TMP, low
2916
2917 return []*instruction{insLUI, insADD, ins}
2918 }
2919
2920 func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
2921 insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
2922
2923 var inss []*instruction
2924 if p.Ctxt.Flag_shared {
2925
2926
2927 insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
2928 insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
2929 inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
2930 } else {
2931
2932
2933
2934
2935
2936 insLUI := &instruction{as: ALUI, rd: REG_TMP}
2937 insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
2938 inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
2939 }
2940 return inss
2941 }
2942
2943 func instructionsForTLSLoad(p *obj.Prog) []*instruction {
2944 if p.From.Sym.Type != objabi.STLSBSS {
2945 p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
2946 return nil
2947 }
2948
2949 ins := instructionForProg(p)
2950 ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
2951
2952 return instructionsForTLS(p, ins)
2953 }
2954
2955 func instructionsForTLSStore(p *obj.Prog) []*instruction {
2956 if p.To.Sym.Type != objabi.STLSBSS {
2957 p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
2958 return nil
2959 }
2960
2961 ins := instructionForProg(p)
2962 ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
2963
2964 return instructionsForTLS(p, ins)
2965 }
2966
2967
2968
2969 func instructionsForMOV(p *obj.Prog) []*instruction {
2970 ins := instructionForProg(p)
2971 inss := []*instruction{ins}
2972
2973 if p.Reg != 0 {
2974 p.Ctxt.Diag("%v: illegal MOV instruction", p)
2975 return nil
2976 }
2977
2978 switch {
2979 case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
2980
2981 if p.As != AMOV {
2982 p.Ctxt.Diag("%v: unsupported constant load", p)
2983 return nil
2984 }
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007 var insSLLI, insSRLI *instruction
3008 if err := immIFits(ins.imm, 32); err != nil {
3009 if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok {
3010 ins.imm = c
3011 if lsh > 0 {
3012 insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)}
3013 }
3014 if rsh > 0 {
3015 insSRLI = &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: int64(rsh)}
3016 }
3017 }
3018 }
3019
3020 low, high, err := Split32BitImmediate(ins.imm)
3021 if err != nil {
3022 p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
3023 return nil
3024 }
3025
3026
3027 ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
3028
3029
3030 if high != 0 {
3031
3032
3033 insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
3034 inss = []*instruction{insLUI}
3035 if low != 0 {
3036 ins.as, ins.rs1 = AADDIW, ins.rd
3037 inss = append(inss, ins)
3038 }
3039 }
3040 if insSLLI != nil {
3041 inss = append(inss, insSLLI)
3042 }
3043 if insSRLI != nil {
3044 inss = append(inss, insSRLI)
3045 }
3046
3047 case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
3048 p.Ctxt.Diag("%v: constant load must target register", p)
3049 return nil
3050
3051 case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
3052
3053 switch p.As {
3054 case AMOV:
3055 ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
3056 case AMOVW:
3057 ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
3058 case AMOVBU:
3059 ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
3060 case AMOVF:
3061 ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
3062 case AMOVD:
3063 ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
3064 case AMOVB, AMOVH:
3065 if buildcfg.GORISCV64 >= 22 {
3066
3067 ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE
3068 if p.As == AMOVH {
3069 ins.as = ASEXTH
3070 }
3071 } else {
3072
3073 ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
3074 if p.As == AMOVB {
3075 ins.imm = 56
3076 } else if p.As == AMOVH {
3077 ins.imm = 48
3078 }
3079 ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
3080 inss = append(inss, ins2)
3081 }
3082 case AMOVHU, AMOVWU:
3083 if buildcfg.GORISCV64 >= 22 {
3084
3085 ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0
3086 if p.As == AMOVWU {
3087 ins.as, ins.rs2 = AADDUW, REG_ZERO
3088 }
3089 } else {
3090
3091 ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
3092 if p.As == AMOVHU {
3093 ins.imm = 48
3094 } else if p.As == AMOVWU {
3095 ins.imm = 32
3096 }
3097 ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
3098 inss = append(inss, ins2)
3099 }
3100 }
3101
3102 case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
3103
3104 switch p.From.Name {
3105 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
3106
3107 inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
3108
3109 case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF:
3110 if p.From.Sym.Type == objabi.STLSBSS {
3111 return instructionsForTLSLoad(p)
3112 }
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122 addrReg := ins.rd
3123 if addrReg < REG_X0 || addrReg > REG_X31 {
3124 addrReg = REG_TMP
3125 }
3126 insAUIPC := &instruction{as: AAUIPC, rd: addrReg}
3127 ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), addrReg, obj.REG_NONE, 0
3128 inss = []*instruction{insAUIPC, ins}
3129
3130 default:
3131 p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
3132 return nil
3133 }
3134
3135 case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
3136
3137 switch p.As {
3138 case AMOVBU, AMOVHU, AMOVWU:
3139 p.Ctxt.Diag("%v: unsupported unsigned store", p)
3140 return nil
3141 }
3142 switch p.To.Name {
3143 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
3144
3145 inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
3146
3147 case obj.NAME_EXTERN, obj.NAME_STATIC:
3148 if p.To.Sym.Type == objabi.STLSBSS {
3149 return instructionsForTLSStore(p)
3150 }
3151
3152
3153
3154
3155
3156
3157 insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
3158 ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
3159 inss = []*instruction{insAUIPC, ins}
3160
3161 default:
3162 p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
3163 return nil
3164 }
3165
3166 case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
3167
3168 if p.As != AMOV {
3169 p.Ctxt.Diag("%v: unsupported address load", p)
3170 return nil
3171 }
3172 switch p.From.Name {
3173 case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
3174 inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
3175
3176 case obj.NAME_EXTERN, obj.NAME_STATIC:
3177
3178
3179
3180
3181
3182 insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
3183 ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
3184 inss = []*instruction{insAUIPC, ins}
3185
3186 default:
3187 p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
3188 return nil
3189 }
3190
3191 case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
3192 p.Ctxt.Diag("%v: address load must target register", p)
3193 return nil
3194
3195 default:
3196 p.Ctxt.Diag("%v: unsupported MOV", p)
3197 return nil
3198 }
3199
3200 return inss
3201 }
3202
3203
3204 func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
3205 if buildcfg.GORISCV64 >= 22 {
3206
3207 return []*instruction{ins}
3208 }
3209
3210 switch ins.as {
3211 case AROL, AROLW, AROR, ARORW:
3212
3213
3214 sllOp, srlOp := ASLL, ASRL
3215 if ins.as == AROLW || ins.as == ARORW {
3216 sllOp, srlOp = ASLLW, ASRLW
3217 }
3218 shift1, shift2 := sllOp, srlOp
3219 if ins.as == AROR || ins.as == ARORW {
3220 shift1, shift2 = shift2, shift1
3221 }
3222 return []*instruction{
3223 &instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP},
3224 &instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP},
3225 &instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
3226 &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
3227 }
3228
3229 case ARORI, ARORIW:
3230
3231 sllOp, srlOp := ASLLI, ASRLI
3232 sllImm := int64(int8(-ins.imm) & 63)
3233 if ins.as == ARORIW {
3234 sllOp, srlOp = ASLLIW, ASRLIW
3235 sllImm = int64(int8(-ins.imm) & 31)
3236 }
3237 return []*instruction{
3238 &instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm},
3239 &instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm},
3240 &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
3241 }
3242
3243 default:
3244 p.Ctxt.Diag("%v: unknown rotation", p)
3245 return nil
3246 }
3247 }
3248
3249
3250 func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction {
3251 if buildcfg.GORISCV64 >= 22 {
3252
3253 return []*instruction{ins}
3254 }
3255
3256
3257 if ins.rs1 == ins.rs2 {
3258 ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0
3259 return []*instruction{ins}
3260 }
3261
3262
3263
3264 if ins.rs1 == ins.rd {
3265 ins.rs1, ins.rs2 = ins.rs2, ins.rs1
3266 }
3267 sltReg1, sltReg2 := ins.rs2, ins.rs1
3268
3269
3270
3271 switch ins.as {
3272 case AMIN:
3273 ins.as = ASLT
3274 case AMAX:
3275 ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1
3276 case AMINU:
3277 ins.as = ASLTU
3278 case AMAXU:
3279 ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1
3280 }
3281 return []*instruction{
3282 &instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP},
3283 &instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP},
3284 &instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
3285 &instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
3286 &instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd},
3287 }
3288 }
3289
3290
3291 func instructionsForProg(p *obj.Prog) []*instruction {
3292 ins := instructionForProg(p)
3293 inss := []*instruction{ins}
3294
3295 if ins.as == AVSETVLI || ins.as == AVSETIVLI {
3296 if len(p.RestArgs) != 4 {
3297 p.Ctxt.Diag("incorrect number of arguments for instruction")
3298 return nil
3299 }
3300 } else if len(p.RestArgs) > 1 {
3301 p.Ctxt.Diag("too many source registers")
3302 return nil
3303 }
3304
3305 switch ins.as {
3306 case AJAL, AJALR:
3307 ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
3308 ins.imm = p.To.Offset
3309
3310 case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
3311 switch ins.as {
3312 case ABEQZ:
3313 ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
3314 case ABGEZ:
3315 ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
3316 case ABGT:
3317 ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
3318 case ABGTU:
3319 ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
3320 case ABGTZ:
3321 ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
3322 case ABLE:
3323 ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
3324 case ABLEU:
3325 ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
3326 case ABLEZ:
3327 ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
3328 case ABLTZ:
3329 ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
3330 case ABNEZ:
3331 ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
3332 }
3333 ins.imm = p.To.Offset
3334
3335 case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
3336 inss = instructionsForMOV(p)
3337
3338 case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
3339 inss = instructionsForLoad(p, ins.as, p.From.Reg)
3340
3341 case ASW, ASH, ASB, ASD, AFSW, AFSD:
3342 inss = instructionsForStore(p, ins.as, p.To.Reg)
3343
3344 case ALRW, ALRD:
3345
3346 ins.funct7 = 2
3347 ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
3348
3349 case AADDI, AANDI, AORI, AXORI:
3350 inss = instructionsForOpImmediate(p, ins.as, p.Reg)
3351
3352 case ASCW, ASCD:
3353
3354 ins.funct7 = 1
3355 ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
3356
3357 case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
3358 AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
3359
3360 ins.funct7 = 3
3361 ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
3362
3363 case AECALL, AEBREAK:
3364 insEnc := encode(p.As)
3365 if p.To.Type == obj.TYPE_NONE {
3366 ins.rd = REG_ZERO
3367 }
3368 ins.rs1 = REG_ZERO
3369 ins.imm = insEnc.csr
3370
3371 case ARDCYCLE, ARDTIME, ARDINSTRET:
3372 ins.as = ACSRRS
3373 if p.To.Type == obj.TYPE_NONE {
3374 ins.rd = REG_ZERO
3375 }
3376 ins.rs1 = REG_ZERO
3377 switch p.As {
3378 case ARDCYCLE:
3379 ins.imm = -1024
3380 case ARDTIME:
3381 ins.imm = -1023
3382 case ARDINSTRET:
3383 ins.imm = -1022
3384 }
3385
3386 case AFENCE:
3387 ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
3388 ins.imm = 0x0ff
3389
3390 case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
3391
3392 if p.Scond&rmSuffixBit == 0 {
3393 ins.funct3 = uint32(RM_RTZ)
3394 } else {
3395 ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
3396 }
3397
3398 case AFNES, AFNED:
3399
3400 if p.To.Type != obj.TYPE_REG {
3401 p.Ctxt.Diag("%v needs an integer register output", p)
3402 return nil
3403 }
3404 if ins.as == AFNES {
3405 ins.as = AFEQS
3406 } else {
3407 ins.as = AFEQD
3408 }
3409 ins2 := &instruction{
3410 as: AXORI,
3411 rd: ins.rd,
3412 rs1: ins.rd,
3413 imm: 1,
3414 }
3415 inss = append(inss, ins2)
3416
3417 case AFSQRTS, AFSQRTD:
3418
3419
3420 ins.rs1 = uint32(p.From.Reg)
3421 ins.rs2 = REG_F0
3422
3423 case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
3424 AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
3425
3426
3427 ins.rs1, ins.rs2 = ins.rs2, ins.rs1
3428
3429 case ANEG, ANEGW:
3430
3431 ins.as = ASUB
3432 if p.As == ANEGW {
3433 ins.as = ASUBW
3434 }
3435 ins.rs1 = REG_ZERO
3436 if ins.rd == obj.REG_NONE {
3437 ins.rd = ins.rs2
3438 }
3439
3440 case ANOT:
3441
3442 ins.as = AXORI
3443 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
3444 if ins.rd == obj.REG_NONE {
3445 ins.rd = ins.rs1
3446 }
3447 ins.imm = -1
3448
3449 case ASEQZ:
3450
3451 ins.as = ASLTIU
3452 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
3453 ins.imm = 1
3454
3455 case ASNEZ:
3456
3457 ins.as = ASLTU
3458 ins.rs1 = REG_ZERO
3459
3460 case AFABSS:
3461
3462 ins.as = AFSGNJXS
3463 ins.rs1 = uint32(p.From.Reg)
3464
3465 case AFABSD:
3466
3467 ins.as = AFSGNJXD
3468 ins.rs1 = uint32(p.From.Reg)
3469
3470 case AFNEGS:
3471
3472 ins.as = AFSGNJNS
3473 ins.rs1 = uint32(p.From.Reg)
3474
3475 case AFNEGD:
3476
3477 ins.as = AFSGNJND
3478 ins.rs1 = uint32(p.From.Reg)
3479
3480 case AROL, AROLW, AROR, ARORW:
3481 inss = instructionsForRotate(p, ins)
3482
3483 case ARORI:
3484 if ins.imm < 0 || ins.imm > 63 {
3485 p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
3486 }
3487 inss = instructionsForRotate(p, ins)
3488
3489 case ARORIW:
3490 if ins.imm < 0 || ins.imm > 31 {
3491 p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
3492 }
3493 inss = instructionsForRotate(p, ins)
3494
3495 case ASLLI, ASRLI, ASRAI:
3496 if ins.imm < 0 || ins.imm > 63 {
3497 p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
3498 }
3499
3500 case ASLLIW, ASRLIW, ASRAIW:
3501 if ins.imm < 0 || ins.imm > 31 {
3502 p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
3503 }
3504
3505 case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
3506 ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
3507
3508 case AORCB, AREV8:
3509 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3510
3511 case AANDN, AORN:
3512 if buildcfg.GORISCV64 >= 22 {
3513
3514 break
3515 }
3516
3517
3518 bitwiseOp, notReg := AAND, ins.rd
3519 if ins.as == AORN {
3520 bitwiseOp = AOR
3521 }
3522 if ins.rs1 == notReg {
3523 notReg = REG_TMP
3524 }
3525 inss = []*instruction{
3526 &instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1},
3527 &instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd},
3528 }
3529
3530 case AXNOR:
3531 if buildcfg.GORISCV64 >= 22 {
3532
3533 break
3534 }
3535
3536 ins.as = AXOR
3537 inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
3538
3539 case AMIN, AMAX, AMINU, AMAXU:
3540 inss = instructionsForMinMax(p, ins)
3541
3542 case AVSETVLI, AVSETIVLI:
3543 ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
3544 vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
3545 if err != nil {
3546 p.Ctxt.Diag("%v: %v", p, err)
3547 }
3548 ins.imm = int64(vtype)
3549 if ins.as == AVSETIVLI {
3550 if p.From.Type != obj.TYPE_CONST {
3551 p.Ctxt.Diag("%v: expected immediate value", p)
3552 }
3553 ins.rs1 = uint32(p.From.Offset)
3554 }
3555
3556 case AVLE8V, AVLE16V, AVLE32V, AVLE64V, AVSE8V, AVSE16V, AVSE32V, AVSE64V, AVLMV, AVSMV:
3557
3558 switch {
3559 case ins.rs1 == obj.REG_NONE:
3560 ins.funct7 |= 1
3561 case ins.rs1 != REG_V0:
3562 p.Ctxt.Diag("%v: invalid vector mask register", p)
3563 }
3564 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3565
3566 case AVLSE8V, AVLSE16V, AVLSE32V, AVLSE64V,
3567 AVLUXEI8V, AVLUXEI16V, AVLUXEI32V, AVLUXEI64V, AVLOXEI8V, AVLOXEI16V, AVLOXEI32V, AVLOXEI64V:
3568
3569 switch {
3570 case ins.rs3 == obj.REG_NONE:
3571 ins.funct7 |= 1
3572 case ins.rs3 != REG_V0:
3573 p.Ctxt.Diag("%v: invalid vector mask register", p)
3574 }
3575 ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rs1, obj.REG_NONE
3576
3577 case AVSSE8V, AVSSE16V, AVSSE32V, AVSSE64V,
3578 AVSUXEI8V, AVSUXEI16V, AVSUXEI32V, AVSUXEI64V, AVSOXEI8V, AVSOXEI16V, AVSOXEI32V, AVSOXEI64V:
3579
3580 switch {
3581 case ins.rs3 == obj.REG_NONE:
3582 ins.funct7 |= 1
3583 case ins.rs3 != REG_V0:
3584 p.Ctxt.Diag("%v: invalid vector mask register", p)
3585 }
3586 ins.rd, ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rd, ins.rs1, obj.REG_NONE
3587
3588 case AVL1RV, AVL1RE8V, AVL1RE16V, AVL1RE32V, AVL1RE64V, AVL2RV, AVL2RE8V, AVL2RE16V, AVL2RE32V, AVL2RE64V,
3589 AVL4RV, AVL4RE8V, AVL4RE16V, AVL4RE32V, AVL4RE64V, AVL8RV, AVL8RE8V, AVL8RE16V, AVL8RE32V, AVL8RE64V:
3590 switch ins.as {
3591 case AVL1RV:
3592 ins.as = AVL1RE8V
3593 case AVL2RV:
3594 ins.as = AVL2RE8V
3595 case AVL4RV:
3596 ins.as = AVL4RE8V
3597 case AVL8RV:
3598 ins.as = AVL8RE8V
3599 }
3600 if ins.rs1 != obj.REG_NONE {
3601 p.Ctxt.Diag("%v: too many operands for instruction", p)
3602 }
3603 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3604
3605 case AVS1RV, AVS2RV, AVS4RV, AVS8RV:
3606 if ins.rs1 != obj.REG_NONE {
3607 p.Ctxt.Diag("%v: too many operands for instruction", p)
3608 }
3609 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
3610
3611 case AVADDVV, AVADDVX, AVSUBVV, AVSUBVX, AVRSUBVX, AVWADDUVV, AVWADDUVX, AVWSUBUVV, AVWSUBUVX,
3612 AVWADDVV, AVWADDVX, AVWSUBVV, AVWSUBVX, AVWADDUWV, AVWADDUWX, AVWSUBUWV, AVWSUBUWX,
3613 AVWADDWV, AVWADDWX, AVWSUBWV, AVWSUBWX, AVANDVV, AVANDVX, AVORVV, AVORVX, AVXORVV, AVXORVX,
3614 AVSLLVV, AVSLLVX, AVSRLVV, AVSRLVX, AVSRAVV, AVSRAVX,
3615 AVMSEQVV, AVMSEQVX, AVMSNEVV, AVMSNEVX, AVMSLTUVV, AVMSLTUVX, AVMSLTVV, AVMSLTVX,
3616 AVMSLEUVV, AVMSLEUVX, AVMSLEVV, AVMSLEVX, AVMSGTUVX, AVMSGTVX,
3617 AVMINUVV, AVMINUVX, AVMINVV, AVMINVX, AVMAXUVV, AVMAXUVX, AVMAXVV, AVMAXVX,
3618 AVMULVV, AVMULVX, AVMULHVV, AVMULHVX, AVMULHUVV, AVMULHUVX, AVMULHSUVV, AVMULHSUVX,
3619 AVDIVUVV, AVDIVUVX, AVDIVVV, AVDIVVX, AVREMUVV, AVREMUVX, AVREMVV, AVREMVX,
3620 AVWMULVV, AVWMULVX, AVWMULUVV, AVWMULUVX, AVWMULSUVV, AVWMULSUVX, AVNSRLWV, AVNSRLWX, AVNSRAWV, AVNSRAWX,
3621 AVSADDUVV, AVSADDUVX, AVSADDUVI, AVSADDVV, AVSADDVX, AVSADDVI, AVSSUBUVV, AVSSUBUVX, AVSSUBVV, AVSSUBVX,
3622 AVAADDUVV, AVAADDUVX, AVAADDVV, AVAADDVX, AVASUBUVV, AVASUBUVX, AVASUBVV, AVASUBVX,
3623 AVSMULVV, AVSMULVX, AVSSRLVV, AVSSRLVX, AVSSRLVI, AVSSRAVV, AVSSRAVX, AVSSRAVI,
3624 AVNCLIPUWV, AVNCLIPUWX, AVNCLIPUWI, AVNCLIPWV, AVNCLIPWX, AVNCLIPWI,
3625 AVFADDVV, AVFADDVF, AVFSUBVV, AVFSUBVF, AVFRSUBVF,
3626 AVFWADDVV, AVFWADDVF, AVFWSUBVV, AVFWSUBVF, AVFWADDWV, AVFWADDWF, AVFWSUBWV, AVFWSUBWF,
3627 AVFMULVV, AVFMULVF, AVFDIVVV, AVFDIVVF, AVFRDIVVF, AVFWMULVV, AVFWMULVF,
3628 AVFMINVV, AVFMINVF, AVFMAXVV, AVFMAXVF,
3629 AVFSGNJVV, AVFSGNJVF, AVFSGNJNVV, AVFSGNJNVF, AVFSGNJXVV, AVFSGNJXVF,
3630 AVMFEQVV, AVMFEQVF, AVMFNEVV, AVMFNEVF, AVMFLTVV, AVMFLTVF, AVMFLEVV, AVMFLEVF, AVMFGTVF, AVMFGEVF,
3631 AVREDSUMVS, AVREDMAXUVS, AVREDMAXVS, AVREDMINUVS, AVREDMINVS, AVREDANDVS, AVREDORVS, AVREDXORVS,
3632 AVWREDSUMUVS, AVWREDSUMVS, AVFREDOSUMVS, AVFREDUSUMVS, AVFREDMAXVS, AVFREDMINVS, AVFWREDOSUMVS, AVFWREDUSUMVS,
3633 AVSLIDEUPVX, AVSLIDEDOWNVX, AVSLIDE1UPVX, AVFSLIDE1UPVF, AVSLIDE1DOWNVX, AVFSLIDE1DOWNVF,
3634 AVRGATHERVV, AVRGATHEREI16VV, AVRGATHERVX:
3635
3636 switch {
3637 case ins.rs3 == obj.REG_NONE:
3638 ins.funct7 |= 1
3639 case ins.rs3 != REG_V0:
3640 p.Ctxt.Diag("%v: invalid vector mask register", p)
3641 }
3642 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
3643
3644 case AVFMACCVV, AVFMACCVF, AVFNMACCVV, AVFNMACCVF, AVFMSACVV, AVFMSACVF, AVFNMSACVV, AVFNMSACVF,
3645 AVFMADDVV, AVFMADDVF, AVFNMADDVV, AVFNMADDVF, AVFMSUBVV, AVFMSUBVF, AVFNMSUBVV, AVFNMSUBVF,
3646 AVFWMACCVV, AVFWMACCVF, AVFWNMACCVV, AVFWNMACCVF, AVFWMSACVV, AVFWMSACVF, AVFWNMSACVV, AVFWNMSACVF,
3647 AVMACCVV, AVMACCVX, AVNMSACVV, AVNMSACVX, AVMADDVV, AVMADDVX, AVNMSUBVV, AVNMSUBVX,
3648 AVWMACCUVV, AVWMACCUVX, AVWMACCVV, AVWMACCVX, AVWMACCSUVV, AVWMACCSUVX, AVWMACCUSVX:
3649 switch {
3650 case ins.rs3 == obj.REG_NONE:
3651 ins.funct7 |= 1
3652 case ins.rs3 != REG_V0:
3653 p.Ctxt.Diag("%v: invalid vector mask register", p)
3654 }
3655 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
3656
3657 case AVADDVI, AVRSUBVI, AVANDVI, AVORVI, AVXORVI, AVMSEQVI, AVMSNEVI, AVMSLEUVI, AVMSLEVI, AVMSGTUVI, AVMSGTVI,
3658 AVSLLVI, AVSRLVI, AVSRAVI, AVNSRLWI, AVNSRAWI, AVRGATHERVI, AVSLIDEUPVI, AVSLIDEDOWNVI:
3659
3660 switch {
3661 case ins.rs3 == obj.REG_NONE:
3662 ins.funct7 |= 1
3663 case ins.rs3 != REG_V0:
3664 p.Ctxt.Diag("%v: invalid vector mask register", p)
3665 }
3666 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE
3667
3668 case AVZEXTVF2, AVSEXTVF2, AVZEXTVF4, AVSEXTVF4, AVZEXTVF8, AVSEXTVF8, AVFSQRTV, AVFRSQRT7V, AVFREC7V, AVFCLASSV,
3669 AVFCVTXUFV, AVFCVTXFV, AVFCVTRTZXUFV, AVFCVTRTZXFV, AVFCVTFXUV, AVFCVTFXV,
3670 AVFWCVTXUFV, AVFWCVTXFV, AVFWCVTRTZXUFV, AVFWCVTRTZXFV, AVFWCVTFXUV, AVFWCVTFXV, AVFWCVTFFV,
3671 AVFNCVTXUFW, AVFNCVTXFW, AVFNCVTRTZXUFW, AVFNCVTRTZXFW, AVFNCVTFXUW, AVFNCVTFXW, AVFNCVTFFW, AVFNCVTRODFFW:
3672
3673 switch {
3674 case ins.rs1 == obj.REG_NONE:
3675 ins.funct7 |= 1
3676 case ins.rs1 != REG_V0:
3677 p.Ctxt.Diag("%v: invalid vector mask register", p)
3678 }
3679 ins.rs1 = obj.REG_NONE
3680
3681 case AVMVVV, AVMVVX:
3682 if ins.rs1 != obj.REG_NONE {
3683 p.Ctxt.Diag("%v: too many operands for instruction", p)
3684 }
3685 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
3686
3687 case AVMVVI:
3688 if ins.rs1 != obj.REG_NONE {
3689 p.Ctxt.Diag("%v: too many operands for instruction", p)
3690 }
3691 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), obj.REG_NONE, REG_V0
3692
3693 case AVFMVVF:
3694 ins.funct7 |= 1
3695 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
3696
3697 case AVADCVIM, AVADCVVM, AVADCVXM, AVSBCVVM, AVSBCVXM:
3698 if ins.rd == REG_V0 {
3699 p.Ctxt.Diag("%v: invalid destination register V0", p)
3700 }
3701 fallthrough
3702
3703 case AVMADCVVM, AVMADCVXM, AVMSBCVVM, AVMSBCVXM, AVMADCVIM, AVMERGEVVM, AVMERGEVXM, AVMERGEVIM, AVFMERGEVFM:
3704 if ins.rs3 != REG_V0 {
3705 p.Ctxt.Diag("%v: invalid vector mask register", p)
3706 }
3707 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
3708
3709 case AVMADCVV, AVMADCVX, AVMSBCVV, AVMSBCVX, AVMADCVI:
3710 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
3711
3712 case AVNEGV, AVWCVTXXV, AVWCVTUXXV, AVNCVTXXW:
3713
3714 switch {
3715 case ins.rs1 == obj.REG_NONE:
3716 ins.funct7 |= 1
3717 case ins.rs1 != REG_V0:
3718 p.Ctxt.Diag("%v: invalid vector mask register", p)
3719 }
3720 switch ins.as {
3721 case AVNEGV:
3722 ins.as = AVRSUBVX
3723 case AVWCVTXXV:
3724 ins.as = AVWADDVX
3725 case AVWCVTUXXV:
3726 ins.as = AVWADDUVX
3727 case AVNCVTXXW:
3728 ins.as = AVNSRLWX
3729 }
3730 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), REG_X0, uint32(p.From.Reg)
3731
3732 case AVNOTV:
3733
3734 switch {
3735 case ins.rs1 == obj.REG_NONE:
3736 ins.funct7 |= 1
3737 case ins.rs1 != REG_V0:
3738 p.Ctxt.Diag("%v: invalid vector mask register", p)
3739 }
3740 ins.as = AVXORVI
3741 ins.rd, ins.rs1, ins.rs2, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.From.Reg), -1
3742
3743 case AVMSGTVV, AVMSGTUVV, AVMSGEVV, AVMSGEUVV, AVMFGTVV, AVMFGEVV:
3744
3745 switch {
3746 case ins.rs3 == obj.REG_NONE:
3747 ins.funct7 |= 1
3748 case ins.rs3 != REG_V0:
3749 p.Ctxt.Diag("%v: invalid vector mask register", p)
3750 }
3751 switch ins.as {
3752 case AVMSGTVV:
3753 ins.as = AVMSLTVV
3754 case AVMSGTUVV:
3755 ins.as = AVMSLTUVV
3756 case AVMSGEVV:
3757 ins.as = AVMSLEVV
3758 case AVMSGEUVV:
3759 ins.as = AVMSLEUVV
3760 case AVMFGTVV:
3761 ins.as = AVMFLTVV
3762 case AVMFGEVV:
3763 ins.as = AVMFLEVV
3764 }
3765 ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
3766
3767 case AVMSLTVI, AVMSLTUVI, AVMSGEVI, AVMSGEUVI:
3768
3769 switch {
3770 case ins.rs3 == obj.REG_NONE:
3771 ins.funct7 |= 1
3772 case ins.rs3 != REG_V0:
3773 p.Ctxt.Diag("%v: invalid vector mask register", p)
3774 }
3775 switch ins.as {
3776 case AVMSLTVI:
3777 ins.as = AVMSLEVI
3778 case AVMSLTUVI:
3779 ins.as = AVMSLEUVI
3780 case AVMSGEVI:
3781 ins.as = AVMSGTVI
3782 case AVMSGEUVI:
3783 ins.as = AVMSGTUVI
3784 }
3785 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
3786
3787 case AVFABSV, AVFNEGV:
3788
3789 switch {
3790 case ins.rs1 == obj.REG_NONE:
3791 ins.funct7 |= 1
3792 case ins.rs1 != REG_V0:
3793 p.Ctxt.Diag("%v: invalid vector mask register", p)
3794 }
3795 switch ins.as {
3796 case AVFABSV:
3797 ins.as = AVFSGNJXVV
3798 case AVFNEGV:
3799 ins.as = AVFSGNJNVV
3800 }
3801 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
3802
3803 case AVMANDMM, AVMNANDMM, AVMANDNMM, AVMXORMM, AVMORMM, AVMNORMM, AVMORNMM, AVMXNORMM, AVMMVM, AVMNOTM, AVCOMPRESSVM:
3804 ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
3805 switch ins.as {
3806 case AVMMVM:
3807 ins.as, ins.rs2 = AVMANDMM, ins.rs1
3808 case AVMNOTM:
3809 ins.as, ins.rs2 = AVMNANDMM, ins.rs1
3810 }
3811
3812 case AVMCLRM, AVMSETM:
3813 ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
3814 switch ins.as {
3815 case AVMCLRM:
3816 ins.as = AVMXORMM
3817 case AVMSETM:
3818 ins.as = AVMXNORMM
3819 }
3820
3821 case AVCPOPM, AVFIRSTM, AVMSBFM, AVMSIFM, AVMSOFM, AVIOTAM:
3822
3823 switch {
3824 case ins.rs1 == obj.REG_NONE:
3825 ins.funct7 |= 1
3826 case ins.rs1 != REG_V0:
3827 p.Ctxt.Diag("%v: invalid vector mask register", p)
3828 }
3829 ins.rs1 = obj.REG_NONE
3830
3831 case AVIDV:
3832
3833 switch {
3834 case ins.rd == obj.REG_NONE:
3835 ins.funct7 |= 1
3836 case ins.rd != obj.REG_NONE && ins.rs2 != REG_V0:
3837 p.Ctxt.Diag("%v: invalid vector mask register", p)
3838 }
3839 if ins.rd == obj.REG_NONE {
3840 ins.rd = uint32(p.From.Reg)
3841 }
3842 ins.rs1, ins.rs2 = obj.REG_NONE, REG_V0
3843 }
3844
3845 for _, ins := range inss {
3846 ins.p = p
3847 }
3848
3849 return inss
3850 }
3851
3852
3853
3854 func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
3855 if ctxt.Retpoline {
3856 ctxt.Diag("-spectre=ret not supported on riscv")
3857 ctxt.Retpoline = false
3858 }
3859
3860
3861
3862 if ctxt.Errors > 0 {
3863 return
3864 }
3865
3866 for p := cursym.Func().Text; p != nil; p = p.Link {
3867 switch p.As {
3868 case AJAL:
3869 if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
3870 cursym.AddRel(ctxt, obj.Reloc{
3871 Type: objabi.R_RISCV_JAL,
3872 Off: int32(p.Pc),
3873 Siz: 4,
3874 Sym: p.To.Sym,
3875 Add: p.To.Offset,
3876 })
3877 }
3878 case AJALR:
3879 if p.To.Sym != nil {
3880 ctxt.Diag("%v: unexpected AJALR with to symbol", p)
3881 }
3882
3883 case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
3884 var addr *obj.Addr
3885 var rt objabi.RelocType
3886 if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
3887 rt = objabi.R_RISCV_CALL
3888 addr = &p.From
3889 } else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
3890 rt = objabi.R_RISCV_PCREL_ITYPE
3891 addr = &p.From
3892 } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
3893 rt = objabi.R_RISCV_PCREL_STYPE
3894 addr = &p.To
3895 } else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC {
3896 rt = objabi.R_RISCV_GOT_PCREL_ITYPE
3897 addr = &p.From
3898 } else {
3899 break
3900 }
3901 if p.As == AAUIPC {
3902 if p.Link == nil {
3903 ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
3904 break
3905 }
3906 addr = &p.RestArgs[0].Addr
3907 }
3908 if addr.Sym == nil {
3909 ctxt.Diag("PC-relative relocation missing symbol")
3910 break
3911 }
3912 if addr.Sym.Type == objabi.STLSBSS {
3913 if ctxt.Flag_shared {
3914 rt = objabi.R_RISCV_TLS_IE
3915 } else {
3916 rt = objabi.R_RISCV_TLS_LE
3917 }
3918 }
3919
3920 cursym.AddRel(ctxt, obj.Reloc{
3921 Type: rt,
3922 Off: int32(p.Pc),
3923 Siz: 8,
3924 Sym: addr.Sym,
3925 Add: addr.Offset,
3926 })
3927
3928 case obj.APCALIGN:
3929 alignedValue := p.From.Offset
3930 v := pcAlignPadLength(p.Pc, alignedValue)
3931 offset := p.Pc
3932 for ; v >= 4; v -= 4 {
3933
3934 cursym.WriteBytes(ctxt, offset, []byte{0x13, 0, 0, 0})
3935 offset += 4
3936 }
3937 continue
3938 }
3939
3940 offset := p.Pc
3941 for _, ins := range instructionsForProg(p) {
3942 if ic, err := ins.encode(); err == nil {
3943 cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
3944 offset += int64(ins.length())
3945 }
3946 if ins.usesRegTmp() {
3947 p.Mark |= USES_REG_TMP
3948 }
3949 }
3950 }
3951
3952 obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
3953 }
3954
3955 func isUnsafePoint(p *obj.Prog) bool {
3956 return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
3957 }
3958
3959 func ParseSuffix(prog *obj.Prog, cond string) (err error) {
3960 switch prog.As {
3961 case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
3962 prog.Scond, err = rmSuffixEncode(strings.TrimPrefix(cond, "."))
3963 }
3964 return
3965 }
3966
3967 var LinkRISCV64 = obj.LinkArch{
3968 Arch: sys.ArchRISCV64,
3969 Init: buildop,
3970 Preprocess: preprocess,
3971 Assemble: assemble,
3972 Progedit: progedit,
3973 UnaryDst: unaryDst,
3974 DWARFRegisters: RISCV64DWARFRegisters,
3975 }
3976
View as plain text