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