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