1
2
3
4
5 package asm
6
7 import (
8 "fmt"
9 "internal/abi"
10 "strconv"
11 "strings"
12 "text/scanner"
13
14 "cmd/asm/internal/arch"
15 "cmd/asm/internal/flags"
16 "cmd/asm/internal/lex"
17 "cmd/internal/obj"
18 "cmd/internal/obj/ppc64"
19 "cmd/internal/obj/riscv"
20 "cmd/internal/obj/x86"
21 "cmd/internal/sys"
22 )
23
24
25
26 var testOut *strings.Builder
27
28
29
30 func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
31 if cond != "" {
32 switch p.arch.Family {
33 case sys.ARM:
34 if !arch.ARMConditionCodes(prog, cond) {
35 p.errorf("unrecognized condition code .%q", cond)
36 return
37 }
38
39 case sys.ARM64:
40 if !arch.ARM64Suffix(prog, cond) {
41 p.errorf("unrecognized suffix .%q", cond)
42 return
43 }
44
45 case sys.AMD64, sys.I386:
46 if err := x86.ParseSuffix(prog, cond); err != nil {
47 p.errorf("%v", err)
48 return
49 }
50 case sys.RISCV64:
51 if err := riscv.ParseSuffix(prog, cond); err != nil {
52 p.errorf("unrecognized suffix .%q", cond)
53 return
54 }
55 default:
56 p.errorf("unrecognized suffix .%q", cond)
57 return
58 }
59 }
60 if p.firstProg == nil {
61 p.firstProg = prog
62 } else {
63 p.lastProg.Link = prog
64 }
65 p.lastProg = prog
66 if doLabel {
67 p.pc++
68 for _, label := range p.pendingLabels {
69 if p.labels[label] != nil {
70 p.errorf("label %q multiply defined", label)
71 return
72 }
73 p.labels[label] = prog
74 }
75 p.pendingLabels = p.pendingLabels[0:0]
76 }
77 prog.Pc = p.pc
78 if *flags.Debug {
79 fmt.Println(p.lineNum, prog)
80 }
81 if testOut != nil {
82 fmt.Fprintln(testOut, prog)
83 }
84 }
85
86
87 func (p *Parser) validSymbol(pseudo string, addr *obj.Addr, offsetOk bool) bool {
88 if addr.Sym == nil || addr.Name != obj.NAME_EXTERN && addr.Name != obj.NAME_STATIC || addr.Scale != 0 || addr.Reg != 0 {
89 p.errorf("%s symbol %q must be a symbol(SB)", pseudo, symbolName(addr))
90 return false
91 }
92 if !offsetOk && addr.Offset != 0 {
93 p.errorf("%s symbol %q must not be offset from SB", pseudo, symbolName(addr))
94 return false
95 }
96 return true
97 }
98
99
100 func (p *Parser) evalInteger(pseudo string, operands []lex.Token) int64 {
101 addr := p.address(operands)
102 return p.getConstantPseudo(pseudo, &addr)
103 }
104
105
106 func (p *Parser) validImmediate(pseudo string, addr *obj.Addr) bool {
107 if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
108 p.errorf("%s: expected immediate constant; found %s", pseudo, obj.Dconv(&emptyProg, addr))
109 return false
110 }
111 return true
112 }
113
114
115
116 func (p *Parser) asmText(operands [][]lex.Token) {
117 if len(operands) != 2 && len(operands) != 3 {
118 p.errorf("expect two or three operands for TEXT")
119 return
120 }
121
122
123
124 p.patch()
125 p.labels = make(map[string]*obj.Prog)
126
127
128
129 nameAddr := p.address(operands[0])
130 if !p.validSymbol("TEXT", &nameAddr, false) {
131 return
132 }
133 name := symbolName(&nameAddr)
134 next := 1
135
136
137 var flag = int64(0)
138 if len(operands) == 3 {
139 flag = p.evalInteger("TEXT", operands[1])
140 next++
141 }
142
143
144
145
146
147 if nameAddr.Sym.ABI() == obj.ABIInternal && flag&obj.NOSPLIT == 0 {
148 p.errorf("TEXT %q: ABIInternal requires NOSPLIT", name)
149 }
150
151
152
153
154
155
156
157 op := operands[next]
158 if len(op) < 2 || op[0].ScanToken != '$' {
159 p.errorf("TEXT %s: frame size must be an immediate constant", name)
160 return
161 }
162 op = op[1:]
163 negative := false
164 if op[0].ScanToken == '-' {
165 negative = true
166 op = op[1:]
167 }
168 if len(op) == 0 || op[0].ScanToken != scanner.Int {
169 p.errorf("TEXT %s: frame size must be an immediate constant", name)
170 return
171 }
172 frameSize := p.positiveAtoi(op[0].String())
173 if negative {
174 frameSize = -frameSize
175 }
176 op = op[1:]
177 argSize := int64(abi.ArgsSizeUnknown)
178 if len(op) > 0 {
179
180 if len(op) != 2 || op[0].ScanToken != '-' || op[1].ScanToken != scanner.Int {
181 p.errorf("TEXT %s: argument size must be of form -integer", name)
182 return
183 }
184 argSize = p.positiveAtoi(op[1].String())
185 }
186 p.ctxt.InitTextSym(nameAddr.Sym, int(flag), p.pos())
187 prog := &obj.Prog{
188 Ctxt: p.ctxt,
189 As: obj.ATEXT,
190 Pos: p.pos(),
191 From: nameAddr,
192 To: obj.Addr{
193 Type: obj.TYPE_TEXTSIZE,
194 Offset: frameSize,
195
196 },
197 }
198 nameAddr.Sym.Func().Text = prog
199 prog.To.Val = int32(argSize)
200 p.append(prog, "", true)
201 }
202
203
204
205 func (p *Parser) asmData(operands [][]lex.Token) {
206 if len(operands) != 2 {
207 p.errorf("expect two operands for DATA")
208 return
209 }
210
211
212 op := operands[0]
213 n := len(op)
214 if n < 3 || op[n-2].ScanToken != '/' || op[n-1].ScanToken != scanner.Int {
215 p.errorf("expect /size for DATA argument")
216 return
217 }
218 szop := op[n-1].String()
219 sz, err := strconv.Atoi(szop)
220 if err != nil {
221 p.errorf("bad size for DATA argument: %q", szop)
222 }
223 op = op[:n-2]
224 nameAddr := p.address(op)
225 if !p.validSymbol("DATA", &nameAddr, true) {
226 return
227 }
228 name := symbolName(&nameAddr)
229
230
231 valueAddr := p.address(operands[1])
232 switch valueAddr.Type {
233 case obj.TYPE_CONST, obj.TYPE_FCONST, obj.TYPE_SCONST, obj.TYPE_ADDR:
234
235 default:
236 p.errorf("DATA value must be an immediate constant or address")
237 return
238 }
239
240
241 if lastAddr, ok := p.dataAddr[name]; ok && nameAddr.Offset < lastAddr {
242 p.errorf("overlapping DATA entry for %s", name)
243 return
244 }
245 p.dataAddr[name] = nameAddr.Offset + int64(sz)
246
247 switch valueAddr.Type {
248 case obj.TYPE_CONST:
249 switch sz {
250 case 1, 2, 4, 8:
251 nameAddr.Sym.WriteInt(p.ctxt, nameAddr.Offset, int(sz), valueAddr.Offset)
252 default:
253 p.errorf("bad int size for DATA argument: %d", sz)
254 }
255 case obj.TYPE_FCONST:
256 switch sz {
257 case 4:
258 nameAddr.Sym.WriteFloat32(p.ctxt, nameAddr.Offset, float32(valueAddr.Val.(float64)))
259 case 8:
260 nameAddr.Sym.WriteFloat64(p.ctxt, nameAddr.Offset, valueAddr.Val.(float64))
261 default:
262 p.errorf("bad float size for DATA argument: %d", sz)
263 }
264 case obj.TYPE_SCONST:
265 nameAddr.Sym.WriteString(p.ctxt, nameAddr.Offset, int(sz), valueAddr.Val.(string))
266 case obj.TYPE_ADDR:
267 if sz == p.arch.PtrSize {
268 nameAddr.Sym.WriteAddr(p.ctxt, nameAddr.Offset, int(sz), valueAddr.Sym, valueAddr.Offset)
269 } else {
270 p.errorf("bad addr size for DATA argument: %d", sz)
271 }
272 }
273 }
274
275
276
277
278 func (p *Parser) asmGlobl(operands [][]lex.Token) {
279 if len(operands) != 2 && len(operands) != 3 {
280 p.errorf("expect two or three operands for GLOBL")
281 return
282 }
283
284
285 nameAddr := p.address(operands[0])
286 if !p.validSymbol("GLOBL", &nameAddr, false) {
287 return
288 }
289 next := 1
290
291
292 var flag = int64(0)
293 if len(operands) == 3 {
294 flag = p.evalInteger("GLOBL", operands[1])
295 next++
296 }
297
298
299 addr := p.address(operands[next])
300 if !p.validImmediate("GLOBL", &addr) {
301 return
302 }
303
304
305 p.ctxt.GloblPos(nameAddr.Sym, addr.Offset, int(flag), p.pos())
306 }
307
308
309
310 func (p *Parser) asmPCData(operands [][]lex.Token) {
311 if len(operands) != 2 {
312 p.errorf("expect two operands for PCDATA")
313 return
314 }
315
316
317 key := p.address(operands[0])
318 if !p.validImmediate("PCDATA", &key) {
319 return
320 }
321
322
323 value := p.address(operands[1])
324 if !p.validImmediate("PCDATA", &value) {
325 return
326 }
327
328
329 prog := &obj.Prog{
330 Ctxt: p.ctxt,
331 As: obj.APCDATA,
332 Pos: p.pos(),
333 From: key,
334 To: value,
335 }
336 p.append(prog, "", true)
337 }
338
339
340
341 func (p *Parser) asmPCAlign(operands [][]lex.Token) {
342 if len(operands) != 1 {
343 p.errorf("expect one operand for PCALIGN")
344 return
345 }
346
347
348 key := p.address(operands[0])
349 if !p.validImmediate("PCALIGN", &key) {
350 return
351 }
352
353 prog := &obj.Prog{
354 Ctxt: p.ctxt,
355 As: obj.APCALIGN,
356 Pos: p.pos(),
357 From: key,
358 }
359 p.append(prog, "", true)
360 }
361
362
363
364 func (p *Parser) asmFuncData(operands [][]lex.Token) {
365 if len(operands) != 2 {
366 p.errorf("expect two operands for FUNCDATA")
367 return
368 }
369
370
371 valueAddr := p.address(operands[0])
372 if !p.validImmediate("FUNCDATA", &valueAddr) {
373 return
374 }
375
376
377 nameAddr := p.address(operands[1])
378 if !p.validSymbol("FUNCDATA", &nameAddr, true) {
379 return
380 }
381
382 prog := &obj.Prog{
383 Ctxt: p.ctxt,
384 As: obj.AFUNCDATA,
385 Pos: p.pos(),
386 From: valueAddr,
387 To: nameAddr,
388 }
389 p.append(prog, "", true)
390 }
391
392
393
394
395
396 func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
397 var target *obj.Addr
398 prog := &obj.Prog{
399 Ctxt: p.ctxt,
400 Pos: p.pos(),
401 As: op,
402 }
403 targetAddr := &prog.To
404 switch len(a) {
405 case 0:
406 if p.arch.Family == sys.Wasm {
407 target = &obj.Addr{Type: obj.TYPE_NONE}
408 break
409 }
410 p.errorf("wrong number of arguments to %s instruction", op)
411 return
412 case 1:
413 target = &a[0]
414 case 2:
415
416 if p.arch.Family == sys.ARM64 && arch.IsARM64ADR(op) {
417
418 target = &a[0]
419 prog.To = a[1]
420 targetAddr = &prog.From
421 } else {
422 target = &a[1]
423 prog.From = a[0]
424 }
425 case 3:
426 if p.arch.Family == sys.PPC64 {
427
428
429 target = &a[2]
430 prog.From = a[0]
431 if a[0].Type != obj.TYPE_CONST {
432
433
434
435
436
437 prog.From = obj.Addr{
438 Type: obj.TYPE_CONST,
439 Offset: p.getConstant(prog, op, &a[0]),
440 }
441
442 }
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457 prog.Reg = a[1].Reg
458 if a[1].Type != obj.TYPE_REG {
459
460 c := p.getConstant(prog, op, &a[1])
461 reg, success := ppc64.ConstantToCRbit(c)
462 if !success {
463 p.errorf("invalid CR bit register number %d", c)
464 }
465 prog.Reg = reg
466 }
467 break
468 }
469 if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 || p.arch.Family == sys.RISCV64 {
470
471
472 target = &a[2]
473 prog.From = a[0]
474 prog.Reg = p.getRegister(prog, op, &a[1])
475 break
476 }
477 if p.arch.Family == sys.Loong64 {
478
479
480 target = &a[2]
481 prog.From = a[0]
482 prog.Reg = p.getRegister(prog, op, &a[1])
483 break
484 }
485 if p.arch.Family == sys.S390X {
486
487 target = &a[2]
488 prog.From = a[0]
489 if a[1].Reg != 0 {
490
491 prog.Reg = p.getRegister(prog, op, &a[1])
492 } else {
493
494 prog.AddRestSource(a[1])
495 }
496 break
497 }
498 if p.arch.Family == sys.ARM64 {
499
500
501 if a[0].Type != obj.TYPE_CONST {
502 p.errorf("%s: expected immediate constant; found %s", op, obj.Dconv(prog, &a[0]))
503 return
504 }
505 prog.From = a[0]
506 prog.Reg = p.getRegister(prog, op, &a[1])
507 target = &a[2]
508 break
509 }
510 p.errorf("wrong number of arguments to %s instruction", op)
511 return
512 case 4:
513 if p.arch.Family == sys.S390X || p.arch.Family == sys.PPC64 {
514
515 prog.From = a[0]
516 prog.Reg = p.getRegister(prog, op, &a[1])
517 prog.AddRestSource(a[2])
518 target = &a[3]
519 break
520 }
521 p.errorf("wrong number of arguments to %s instruction", op)
522 return
523 default:
524 p.errorf("wrong number of arguments to %s instruction", op)
525 return
526 }
527 switch {
528 case target.Type == obj.TYPE_BRANCH:
529
530 *targetAddr = obj.Addr{
531 Type: obj.TYPE_BRANCH,
532 Offset: p.pc + 1 + target.Offset,
533 }
534 case target.Type == obj.TYPE_REG:
535
536 *targetAddr = *target
537 case target.Type == obj.TYPE_MEM && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
538
539 *targetAddr = *target
540 case target.Type == obj.TYPE_INDIR && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
541
542 *targetAddr = *target
543 targetAddr.Type = obj.TYPE_INDIR
544 case target.Type == obj.TYPE_MEM && target.Reg == 0 && target.Offset == 0:
545
546 if target.Sym == nil {
547
548 return
549 }
550 targetProg := p.labels[target.Sym.Name]
551 if targetProg == nil {
552 p.toPatch = append(p.toPatch, Patch{targetAddr, target.Sym.Name})
553 } else {
554 p.branch(targetAddr, targetProg)
555 }
556 case target.Type == obj.TYPE_MEM && target.Name == obj.NAME_NONE:
557
558 *targetAddr = *target
559
560 if p.arch.Family == sys.PPC64 && target.Offset == 0 {
561 targetAddr.Type = obj.TYPE_REG
562 }
563 case target.Type == obj.TYPE_CONST:
564
565 *targetAddr = a[0]
566 case target.Type == obj.TYPE_NONE:
567
568 default:
569 p.errorf("cannot assemble jump %+v", target)
570 return
571 }
572
573 p.append(prog, cond, true)
574 }
575
576 func (p *Parser) patch() {
577 for _, patch := range p.toPatch {
578 targetProg := p.labels[patch.label]
579 if targetProg == nil {
580 p.errorf("undefined label %s", patch.label)
581 return
582 }
583 p.branch(patch.addr, targetProg)
584 }
585 p.toPatch = p.toPatch[:0]
586 }
587
588 func (p *Parser) branch(addr *obj.Addr, target *obj.Prog) {
589 *addr = obj.Addr{
590 Type: obj.TYPE_BRANCH,
591 Index: 0,
592 }
593 addr.Val = target
594 }
595
596
597
598 func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
599
600 prog := &obj.Prog{
601 Ctxt: p.ctxt,
602 Pos: p.pos(),
603 As: op,
604 }
605 switch len(a) {
606 case 0:
607
608 case 1:
609 if p.arch.UnaryDst[op] || op == obj.ARET || op == obj.AGETCALLERPC {
610
611 prog.To = a[0]
612 } else {
613 prog.From = a[0]
614
615 }
616 if p.arch.Family == sys.PPC64 && arch.IsPPC64NEG(op) {
617
618 prog.To = a[0]
619 prog.From = a[0]
620 break
621 }
622 case 2:
623 if p.arch.Family == sys.ARM {
624 if arch.IsARMCMP(op) {
625 prog.From = a[0]
626 prog.Reg = p.getRegister(prog, op, &a[1])
627 break
628 }
629
630 if arch.IsARMFloatCmp(op) {
631 prog.From = a[0]
632 prog.Reg = p.getRegister(prog, op, &a[1])
633 break
634 }
635 } else if p.arch.Family == sys.ARM64 && arch.IsARM64CMP(op) {
636 prog.From = a[0]
637 prog.Reg = p.getRegister(prog, op, &a[1])
638 break
639 } else if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 {
640 if arch.IsMIPSCMP(op) || arch.IsMIPSMUL(op) {
641 prog.From = a[0]
642 prog.Reg = p.getRegister(prog, op, &a[1])
643 break
644 }
645 } else if p.arch.Family == sys.Loong64 {
646 if arch.IsLoong64RDTIME(op) {
647
648
649 prog.To = a[0]
650 if a[1].Type != obj.TYPE_REG {
651 p.errorf("invalid addressing modes for 2nd operand to %s instruction, must be register", op)
652 return
653 }
654 prog.RegTo2 = a[1].Reg
655 break
656 }
657
658 if arch.IsLoong64PRELD(op) {
659 prog.From = a[0]
660 prog.AddRestSource(a[1])
661 break
662 }
663 }
664 prog.From = a[0]
665 prog.To = a[1]
666 case 3:
667 switch p.arch.Family {
668 case sys.MIPS, sys.MIPS64:
669 prog.From = a[0]
670 prog.Reg = p.getRegister(prog, op, &a[1])
671 prog.To = a[2]
672 case sys.Loong64:
673 switch {
674
675 case arch.IsLoong64AMO(op):
676 prog.From = a[0]
677 prog.To = a[1]
678 prog.RegTo2 = a[2].Reg
679
680 case arch.IsLoong64PRELD(op):
681 prog.From = a[0]
682 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2]})
683
684 default:
685 prog.From = a[0]
686 prog.Reg = p.getRegister(prog, op, &a[1])
687 prog.To = a[2]
688 }
689 case sys.ARM:
690
691 if arch.IsARMSTREX(op) {
692
696 prog.From = a[1]
697 prog.Reg = p.getRegister(prog, op, &a[0])
698 prog.To = a[2]
699 break
700 }
701 if arch.IsARMBFX(op) {
702
703 prog.From = a[0]
704 prog.AddRestSource(a[1])
705 prog.To = a[2]
706 break
707 }
708
709 prog.From = a[0]
710 prog.Reg = p.getRegister(prog, op, &a[1])
711 prog.To = a[2]
712 case sys.AMD64:
713 prog.From = a[0]
714 prog.AddRestSource(a[1])
715 prog.To = a[2]
716 case sys.ARM64:
717 switch {
718 case arch.IsARM64STLXR(op):
719
720 prog.From = a[0]
721 prog.To = a[1]
722 if a[2].Type != obj.TYPE_REG {
723 p.errorf("invalid addressing modes for third operand to %s instruction, must be register", op)
724 return
725 }
726 prog.RegTo2 = a[2].Reg
727 case arch.IsARM64TBL(op):
728
729 prog.From = a[0]
730 prog.AddRestSource(a[1])
731 prog.To = a[2]
732 case arch.IsARM64CASP(op):
733 prog.From = a[0]
734 prog.To = a[1]
735
736
737 if (a[0].Type != obj.TYPE_REGREG) || (a[2].Type != obj.TYPE_REGREG) {
738 p.errorf("invalid addressing modes for 1st or 3rd operand to %s instruction, must be register pair", op)
739 return
740 }
741
742
743 prog.AddRestDest(a[2])
744 default:
745 prog.From = a[0]
746 prog.Reg = p.getRegister(prog, op, &a[1])
747 prog.To = a[2]
748 }
749 case sys.I386:
750 prog.From = a[0]
751 prog.AddRestSource(a[1])
752 prog.To = a[2]
753 case sys.PPC64:
754 if arch.IsPPC64CMP(op) {
755
756 prog.From = a[0]
757 prog.Reg = p.getRegister(prog, op, &a[2])
758 prog.To = a[1]
759 break
760 }
761
762 prog.From = a[0]
763 prog.To = a[2]
764
765
766
767 switch a[1].Type {
768 case obj.TYPE_REG:
769 prog.Reg = p.getRegister(prog, op, &a[1])
770 default:
771 prog.AddRestSource(a[1])
772 }
773 case sys.RISCV64:
774
775 if arch.IsRISCV64AMO(op) {
776 prog.From = a[0]
777 prog.To = a[1]
778 if a[2].Type != obj.TYPE_REG {
779 p.errorf("invalid addressing modes for third operand to %s instruction, must be register", op)
780 return
781 }
782 prog.RegTo2 = a[2].Reg
783 break
784 }
785 prog.From = a[0]
786 prog.Reg = p.getRegister(prog, op, &a[1])
787 prog.To = a[2]
788 case sys.S390X:
789 prog.From = a[0]
790 if a[1].Type == obj.TYPE_REG {
791 prog.Reg = p.getRegister(prog, op, &a[1])
792 } else {
793 prog.AddRestSource(a[1])
794 }
795 prog.To = a[2]
796 default:
797 p.errorf("TODO: implement three-operand instructions for this architecture")
798 return
799 }
800 case 4:
801 if p.arch.Family == sys.ARM {
802 if arch.IsARMBFX(op) {
803
804 prog.From = a[0]
805 prog.AddRestSource(a[1])
806 prog.Reg = p.getRegister(prog, op, &a[2])
807 prog.To = a[3]
808 break
809 }
810 if arch.IsARMMULA(op) {
811
812 p.getRegister(prog, op, &a[0])
813 r1 := p.getRegister(prog, op, &a[1])
814 r2 := p.getRegister(prog, op, &a[2])
815 p.getRegister(prog, op, &a[3])
816 prog.From = a[0]
817 prog.To = a[3]
818 prog.To.Type = obj.TYPE_REGREG2
819 prog.To.Offset = int64(r2)
820 prog.Reg = r1
821 break
822 }
823 }
824 if p.arch.Family == sys.AMD64 {
825 prog.From = a[0]
826 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2]})
827 prog.To = a[3]
828 break
829 }
830 if p.arch.Family == sys.ARM64 {
831 prog.From = a[0]
832 prog.Reg = p.getRegister(prog, op, &a[1])
833 prog.AddRestSource(a[2])
834 prog.To = a[3]
835 break
836 }
837 if p.arch.Family == sys.Loong64 {
838 prog.From = a[0]
839 prog.Reg = p.getRegister(prog, op, &a[1])
840 prog.AddRestSource(a[2])
841 prog.To = a[3]
842 break
843 }
844 if p.arch.Family == sys.PPC64 {
845 prog.From = a[0]
846 prog.To = a[3]
847
848
849 if a[1].Type == obj.TYPE_REG {
850 prog.Reg = p.getRegister(prog, op, &a[1])
851 prog.AddRestSource(a[2])
852 } else {
853
854 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2]})
855 }
856 break
857 }
858 if p.arch.Family == sys.RISCV64 {
859 prog.From = a[0]
860 prog.Reg = p.getRegister(prog, op, &a[1])
861 prog.AddRestSource(a[2])
862 prog.To = a[3]
863 break
864 }
865 if p.arch.Family == sys.S390X {
866 if a[1].Type != obj.TYPE_REG {
867 p.errorf("second operand must be a register in %s instruction", op)
868 return
869 }
870 prog.From = a[0]
871 prog.Reg = p.getRegister(prog, op, &a[1])
872 prog.AddRestSource(a[2])
873 prog.To = a[3]
874 break
875 }
876 p.errorf("can't handle %s instruction with 4 operands", op)
877 return
878 case 5:
879 if p.arch.Family == sys.PPC64 {
880 prog.From = a[0]
881
882 prog.Reg = p.getRegister(prog, op, &a[1])
883 prog.AddRestSourceArgs([]obj.Addr{a[2], a[3]})
884 prog.To = a[4]
885 break
886 }
887 if p.arch.Family == sys.AMD64 {
888 prog.From = a[0]
889 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2], a[3]})
890 prog.To = a[4]
891 break
892 }
893 if p.arch.Family == sys.S390X {
894 prog.From = a[0]
895 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2], a[3]})
896 prog.To = a[4]
897 break
898 }
899 p.errorf("can't handle %s instruction with 5 operands", op)
900 return
901 case 6:
902 if p.arch.Family == sys.ARM && arch.IsARMMRC(op) {
903
904 prog.To.Type = obj.TYPE_CONST
905 x0 := p.getConstant(prog, op, &a[0])
906 x1 := p.getConstant(prog, op, &a[1])
907 x2 := int64(p.getRegister(prog, op, &a[2]))
908 x3 := int64(p.getRegister(prog, op, &a[3]))
909 x4 := int64(p.getRegister(prog, op, &a[4]))
910 x5 := p.getConstant(prog, op, &a[5])
911
912 offset, MRC, ok := arch.ARMMRCOffset(op, cond, x0, x1, x2, x3, x4, x5)
913 if !ok {
914 p.errorf("unrecognized condition code .%q", cond)
915 }
916 prog.To.Offset = offset
917 cond = ""
918 prog.As = MRC
919 break
920 }
921 if p.arch.Family == sys.PPC64 {
922 prog.From = a[0]
923
924 prog.Reg = p.getRegister(prog, op, &a[1])
925 prog.AddRestSourceArgs([]obj.Addr{a[2], a[3], a[4]})
926 prog.To = a[5]
927 break
928 }
929 if p.arch.Family == sys.RISCV64 && arch.IsRISCV64VTypeI(op) {
930 prog.From = a[0]
931 vsew := p.getSpecial(prog, op, &a[1])
932 vlmul := p.getSpecial(prog, op, &a[2])
933 vtail := p.getSpecial(prog, op, &a[3])
934 vmask := p.getSpecial(prog, op, &a[4])
935 if err := arch.RISCV64ValidateVectorType(vsew, vlmul, vtail, vmask); err != nil {
936 p.errorf("invalid vtype: %v", err)
937 }
938 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2], a[3], a[4]})
939 prog.To = a[5]
940 break
941 }
942 fallthrough
943 default:
944 p.errorf("can't handle %s instruction with %d operands", op, len(a))
945 return
946 }
947
948 p.append(prog, cond, true)
949 }
950
951
952 func symbolName(addr *obj.Addr) string {
953 if addr.Sym != nil {
954 return addr.Sym.Name
955 }
956 return "<erroneous symbol>"
957 }
958
959 var emptyProg obj.Prog
960
961
962 func (p *Parser) getConstantPseudo(pseudo string, addr *obj.Addr) int64 {
963 if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
964 p.errorf("%s: expected integer constant; found %s", pseudo, obj.Dconv(&emptyProg, addr))
965 }
966 return addr.Offset
967 }
968
969
970 func (p *Parser) getConstant(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
971 if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
972 p.errorf("%s: expected integer constant; found %s", op, obj.Dconv(prog, addr))
973 }
974 return addr.Offset
975 }
976
977
978 func (p *Parser) getImmediate(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
979 if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
980 p.errorf("%s: expected immediate constant; found %s", op, obj.Dconv(prog, addr))
981 }
982 return addr.Offset
983 }
984
985
986 func (p *Parser) getRegister(prog *obj.Prog, op obj.As, addr *obj.Addr) int16 {
987 if addr.Type != obj.TYPE_REG || addr.Offset != 0 || addr.Name != 0 || addr.Index != 0 {
988 p.errorf("%s: expected register; found %s", op, obj.Dconv(prog, addr))
989 }
990 return addr.Reg
991 }
992
993
994 func (p *Parser) getSpecial(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
995 if addr.Type != obj.TYPE_SPECIAL || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
996 p.errorf("%s: expected special operand; found %s", op, obj.Dconv(prog, addr))
997 }
998 return addr.Offset
999 }
1000
View as plain text