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 From: key,
357 }
358 p.append(prog, "", true)
359 }
360
361
362
363 func (p *Parser) asmFuncData(operands [][]lex.Token) {
364 if len(operands) != 2 {
365 p.errorf("expect two operands for FUNCDATA")
366 return
367 }
368
369
370 valueAddr := p.address(operands[0])
371 if !p.validImmediate("FUNCDATA", &valueAddr) {
372 return
373 }
374
375
376 nameAddr := p.address(operands[1])
377 if !p.validSymbol("FUNCDATA", &nameAddr, true) {
378 return
379 }
380
381 prog := &obj.Prog{
382 Ctxt: p.ctxt,
383 As: obj.AFUNCDATA,
384 Pos: p.pos(),
385 From: valueAddr,
386 To: nameAddr,
387 }
388 p.append(prog, "", true)
389 }
390
391
392
393
394
395 func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
396 var target *obj.Addr
397 prog := &obj.Prog{
398 Ctxt: p.ctxt,
399 Pos: p.pos(),
400 As: op,
401 }
402 targetAddr := &prog.To
403 switch len(a) {
404 case 0:
405 if p.arch.Family == sys.Wasm {
406 target = &obj.Addr{Type: obj.TYPE_NONE}
407 break
408 }
409 p.errorf("wrong number of arguments to %s instruction", op)
410 return
411 case 1:
412 target = &a[0]
413 case 2:
414
415 if p.arch.Family == sys.ARM64 && arch.IsARM64ADR(op) {
416
417 target = &a[0]
418 prog.To = a[1]
419 targetAddr = &prog.From
420 } else {
421 target = &a[1]
422 prog.From = a[0]
423 }
424 case 3:
425 if p.arch.Family == sys.PPC64 {
426
427
428 target = &a[2]
429 prog.From = a[0]
430 if a[0].Type != obj.TYPE_CONST {
431
432
433
434
435
436 prog.From = obj.Addr{
437 Type: obj.TYPE_CONST,
438 Offset: p.getConstant(prog, op, &a[0]),
439 }
440
441 }
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456 prog.Reg = a[1].Reg
457 if a[1].Type != obj.TYPE_REG {
458
459 c := p.getConstant(prog, op, &a[1])
460 reg, success := ppc64.ConstantToCRbit(c)
461 if !success {
462 p.errorf("invalid CR bit register number %d", c)
463 }
464 prog.Reg = reg
465 }
466 break
467 }
468 if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 || p.arch.Family == sys.RISCV64 {
469
470
471 target = &a[2]
472 prog.From = a[0]
473 prog.Reg = p.getRegister(prog, op, &a[1])
474 break
475 }
476 if p.arch.Family == sys.Loong64 {
477
478
479 target = &a[2]
480 prog.From = a[0]
481 prog.Reg = p.getRegister(prog, op, &a[1])
482 break
483 }
484 if p.arch.Family == sys.S390X {
485
486 target = &a[2]
487 prog.From = a[0]
488 if a[1].Reg != 0 {
489
490 prog.Reg = p.getRegister(prog, op, &a[1])
491 } else {
492
493 prog.AddRestSource(a[1])
494 }
495 break
496 }
497 if p.arch.Family == sys.ARM64 {
498
499
500 if a[0].Type != obj.TYPE_CONST {
501 p.errorf("%s: expected immediate constant; found %s", op, obj.Dconv(prog, &a[0]))
502 return
503 }
504 prog.From = a[0]
505 prog.Reg = p.getRegister(prog, op, &a[1])
506 target = &a[2]
507 break
508 }
509 p.errorf("wrong number of arguments to %s instruction", op)
510 return
511 case 4:
512 if p.arch.Family == sys.S390X || p.arch.Family == sys.PPC64 {
513
514 prog.From = a[0]
515 prog.Reg = p.getRegister(prog, op, &a[1])
516 prog.AddRestSource(a[2])
517 target = &a[3]
518 break
519 }
520 p.errorf("wrong number of arguments to %s instruction", op)
521 return
522 default:
523 p.errorf("wrong number of arguments to %s instruction", op)
524 return
525 }
526 switch {
527 case target.Type == obj.TYPE_BRANCH:
528
529 *targetAddr = obj.Addr{
530 Type: obj.TYPE_BRANCH,
531 Offset: p.pc + 1 + target.Offset,
532 }
533 case target.Type == obj.TYPE_REG:
534
535 *targetAddr = *target
536 case target.Type == obj.TYPE_MEM && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
537
538 *targetAddr = *target
539 case target.Type == obj.TYPE_INDIR && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
540
541 *targetAddr = *target
542 targetAddr.Type = obj.TYPE_INDIR
543 case target.Type == obj.TYPE_MEM && target.Reg == 0 && target.Offset == 0:
544
545 if target.Sym == nil {
546
547 return
548 }
549 targetProg := p.labels[target.Sym.Name]
550 if targetProg == nil {
551 p.toPatch = append(p.toPatch, Patch{targetAddr, target.Sym.Name})
552 } else {
553 p.branch(targetAddr, targetProg)
554 }
555 case target.Type == obj.TYPE_MEM && target.Name == obj.NAME_NONE:
556
557 *targetAddr = *target
558
559 if p.arch.Family == sys.PPC64 && target.Offset == 0 {
560 targetAddr.Type = obj.TYPE_REG
561 }
562 case target.Type == obj.TYPE_CONST:
563
564 *targetAddr = a[0]
565 case target.Type == obj.TYPE_NONE:
566
567 default:
568 p.errorf("cannot assemble jump %+v", target)
569 return
570 }
571
572 p.append(prog, cond, true)
573 }
574
575 func (p *Parser) patch() {
576 for _, patch := range p.toPatch {
577 targetProg := p.labels[patch.label]
578 if targetProg == nil {
579 p.errorf("undefined label %s", patch.label)
580 return
581 }
582 p.branch(patch.addr, targetProg)
583 }
584 p.toPatch = p.toPatch[:0]
585 }
586
587 func (p *Parser) branch(addr *obj.Addr, target *obj.Prog) {
588 *addr = obj.Addr{
589 Type: obj.TYPE_BRANCH,
590 Index: 0,
591 }
592 addr.Val = target
593 }
594
595
596
597 func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
598
599 prog := &obj.Prog{
600 Ctxt: p.ctxt,
601 Pos: p.pos(),
602 As: op,
603 }
604 switch len(a) {
605 case 0:
606
607 case 1:
608 if p.arch.UnaryDst[op] || op == obj.ARET || op == obj.AGETCALLERPC {
609
610 prog.To = a[0]
611 } else {
612 prog.From = a[0]
613
614 }
615 if p.arch.Family == sys.PPC64 && arch.IsPPC64NEG(op) {
616
617 prog.To = a[0]
618 prog.From = a[0]
619 break
620 }
621 case 2:
622 if p.arch.Family == sys.ARM {
623 if arch.IsARMCMP(op) {
624 prog.From = a[0]
625 prog.Reg = p.getRegister(prog, op, &a[1])
626 break
627 }
628
629 if arch.IsARMFloatCmp(op) {
630 prog.From = a[0]
631 prog.Reg = p.getRegister(prog, op, &a[1])
632 break
633 }
634 } else if p.arch.Family == sys.ARM64 && arch.IsARM64CMP(op) {
635 prog.From = a[0]
636 prog.Reg = p.getRegister(prog, op, &a[1])
637 break
638 } else if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 {
639 if arch.IsMIPSCMP(op) || arch.IsMIPSMUL(op) {
640 prog.From = a[0]
641 prog.Reg = p.getRegister(prog, op, &a[1])
642 break
643 }
644 } else if p.arch.Family == sys.Loong64 {
645 if arch.IsLoong64CMP(op) {
646 prog.From = a[0]
647 prog.Reg = p.getRegister(prog, op, &a[1])
648 break
649 }
650
651 if arch.IsLoong64RDTIME(op) {
652
653
654 prog.To = a[0]
655 if a[1].Type != obj.TYPE_REG {
656 p.errorf("invalid addressing modes for 2nd operand to %s instruction, must be register", op)
657 return
658 }
659 prog.RegTo2 = a[1].Reg
660 break
661 }
662 }
663 prog.From = a[0]
664 prog.To = a[1]
665 case 3:
666 switch p.arch.Family {
667 case sys.MIPS, sys.MIPS64:
668 prog.From = a[0]
669 prog.Reg = p.getRegister(prog, op, &a[1])
670 prog.To = a[2]
671 case sys.Loong64:
672 prog.From = a[0]
673 prog.Reg = p.getRegister(prog, op, &a[1])
674 prog.To = a[2]
675 case sys.ARM:
676
677 if arch.IsARMSTREX(op) {
678
682 prog.From = a[1]
683 prog.Reg = p.getRegister(prog, op, &a[0])
684 prog.To = a[2]
685 break
686 }
687 if arch.IsARMBFX(op) {
688
689 prog.From = a[0]
690 prog.AddRestSource(a[1])
691 prog.To = a[2]
692 break
693 }
694
695 prog.From = a[0]
696 prog.Reg = p.getRegister(prog, op, &a[1])
697 prog.To = a[2]
698 case sys.AMD64:
699 prog.From = a[0]
700 prog.AddRestSource(a[1])
701 prog.To = a[2]
702 case sys.ARM64:
703 switch {
704 case arch.IsARM64STLXR(op):
705
706 prog.From = a[0]
707 prog.To = a[1]
708 if a[2].Type != obj.TYPE_REG {
709 p.errorf("invalid addressing modes for third operand to %s instruction, must be register", op)
710 return
711 }
712 prog.RegTo2 = a[2].Reg
713 case arch.IsARM64TBL(op):
714
715 prog.From = a[0]
716 prog.AddRestSource(a[1])
717 prog.To = a[2]
718 case arch.IsARM64CASP(op):
719 prog.From = a[0]
720 prog.To = a[1]
721
722
723 if (a[0].Type != obj.TYPE_REGREG) || (a[2].Type != obj.TYPE_REGREG) {
724 p.errorf("invalid addressing modes for 1st or 3rd operand to %s instruction, must be register pair", op)
725 return
726 }
727
728
729 prog.AddRestDest(a[2])
730 default:
731 prog.From = a[0]
732 prog.Reg = p.getRegister(prog, op, &a[1])
733 prog.To = a[2]
734 }
735 case sys.I386:
736 prog.From = a[0]
737 prog.AddRestSource(a[1])
738 prog.To = a[2]
739 case sys.PPC64:
740 if arch.IsPPC64CMP(op) {
741
742 prog.From = a[0]
743 prog.Reg = p.getRegister(prog, op, &a[2])
744 prog.To = a[1]
745 break
746 }
747
748 prog.From = a[0]
749 prog.To = a[2]
750
751
752
753 switch a[1].Type {
754 case obj.TYPE_REG:
755 prog.Reg = p.getRegister(prog, op, &a[1])
756 default:
757 prog.AddRestSource(a[1])
758 }
759 case sys.RISCV64:
760
761 if arch.IsRISCV64AMO(op) {
762 prog.From = a[0]
763 prog.To = a[1]
764 if a[2].Type != obj.TYPE_REG {
765 p.errorf("invalid addressing modes for third operand to %s instruction, must be register", op)
766 return
767 }
768 prog.RegTo2 = a[2].Reg
769 break
770 }
771 prog.From = a[0]
772 prog.Reg = p.getRegister(prog, op, &a[1])
773 prog.To = a[2]
774 case sys.S390X:
775 prog.From = a[0]
776 if a[1].Type == obj.TYPE_REG {
777 prog.Reg = p.getRegister(prog, op, &a[1])
778 } else {
779 prog.AddRestSource(a[1])
780 }
781 prog.To = a[2]
782 default:
783 p.errorf("TODO: implement three-operand instructions for this architecture")
784 return
785 }
786 case 4:
787 if p.arch.Family == sys.ARM {
788 if arch.IsARMBFX(op) {
789
790 prog.From = a[0]
791 prog.AddRestSource(a[1])
792 prog.Reg = p.getRegister(prog, op, &a[2])
793 prog.To = a[3]
794 break
795 }
796 if arch.IsARMMULA(op) {
797
798 p.getRegister(prog, op, &a[0])
799 r1 := p.getRegister(prog, op, &a[1])
800 r2 := p.getRegister(prog, op, &a[2])
801 p.getRegister(prog, op, &a[3])
802 prog.From = a[0]
803 prog.To = a[3]
804 prog.To.Type = obj.TYPE_REGREG2
805 prog.To.Offset = int64(r2)
806 prog.Reg = r1
807 break
808 }
809 }
810 if p.arch.Family == sys.AMD64 {
811 prog.From = a[0]
812 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2]})
813 prog.To = a[3]
814 break
815 }
816 if p.arch.Family == sys.ARM64 {
817 prog.From = a[0]
818 prog.Reg = p.getRegister(prog, op, &a[1])
819 prog.AddRestSource(a[2])
820 prog.To = a[3]
821 break
822 }
823 if p.arch.Family == sys.PPC64 {
824 prog.From = a[0]
825 prog.To = a[3]
826
827
828 if a[1].Type == obj.TYPE_REG {
829 prog.Reg = p.getRegister(prog, op, &a[1])
830 prog.AddRestSource(a[2])
831 } else {
832
833 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2]})
834 }
835 break
836 }
837 if p.arch.Family == sys.RISCV64 {
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.S390X {
845 if a[1].Type != obj.TYPE_REG {
846 p.errorf("second operand must be a register in %s instruction", op)
847 return
848 }
849 prog.From = a[0]
850 prog.Reg = p.getRegister(prog, op, &a[1])
851 prog.AddRestSource(a[2])
852 prog.To = a[3]
853 break
854 }
855 p.errorf("can't handle %s instruction with 4 operands", op)
856 return
857 case 5:
858 if p.arch.Family == sys.PPC64 {
859 prog.From = a[0]
860
861 prog.Reg = p.getRegister(prog, op, &a[1])
862 prog.AddRestSourceArgs([]obj.Addr{a[2], a[3]})
863 prog.To = a[4]
864 break
865 }
866 if p.arch.Family == sys.AMD64 {
867 prog.From = a[0]
868 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2], a[3]})
869 prog.To = a[4]
870 break
871 }
872 if p.arch.Family == sys.S390X {
873 prog.From = a[0]
874 prog.AddRestSourceArgs([]obj.Addr{a[1], a[2], a[3]})
875 prog.To = a[4]
876 break
877 }
878 p.errorf("can't handle %s instruction with 5 operands", op)
879 return
880 case 6:
881 if p.arch.Family == sys.ARM && arch.IsARMMRC(op) {
882
883 prog.To.Type = obj.TYPE_CONST
884 x0 := p.getConstant(prog, op, &a[0])
885 x1 := p.getConstant(prog, op, &a[1])
886 x2 := int64(p.getRegister(prog, op, &a[2]))
887 x3 := int64(p.getRegister(prog, op, &a[3]))
888 x4 := int64(p.getRegister(prog, op, &a[4]))
889 x5 := p.getConstant(prog, op, &a[5])
890
891 offset, MRC, ok := arch.ARMMRCOffset(op, cond, x0, x1, x2, x3, x4, x5)
892 if !ok {
893 p.errorf("unrecognized condition code .%q", cond)
894 }
895 prog.To.Offset = offset
896 cond = ""
897 prog.As = MRC
898 break
899 }
900 if p.arch.Family == sys.PPC64 {
901 prog.From = a[0]
902
903 prog.Reg = p.getRegister(prog, op, &a[1])
904 prog.AddRestSourceArgs([]obj.Addr{a[2], a[3], a[4]})
905 prog.To = a[5]
906 break
907 }
908 fallthrough
909 default:
910 p.errorf("can't handle %s instruction with %d operands", op, len(a))
911 return
912 }
913
914 p.append(prog, cond, true)
915 }
916
917
918 func symbolName(addr *obj.Addr) string {
919 if addr.Sym != nil {
920 return addr.Sym.Name
921 }
922 return "<erroneous symbol>"
923 }
924
925 var emptyProg obj.Prog
926
927
928 func (p *Parser) getConstantPseudo(pseudo string, addr *obj.Addr) int64 {
929 if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
930 p.errorf("%s: expected integer constant; found %s", pseudo, obj.Dconv(&emptyProg, addr))
931 }
932 return addr.Offset
933 }
934
935
936 func (p *Parser) getConstant(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
937 if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
938 p.errorf("%s: expected integer constant; found %s", op, obj.Dconv(prog, addr))
939 }
940 return addr.Offset
941 }
942
943
944 func (p *Parser) getImmediate(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
945 if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
946 p.errorf("%s: expected immediate constant; found %s", op, obj.Dconv(prog, addr))
947 }
948 return addr.Offset
949 }
950
951
952 func (p *Parser) getRegister(prog *obj.Prog, op obj.As, addr *obj.Addr) int16 {
953 if addr.Type != obj.TYPE_REG || addr.Offset != 0 || addr.Name != 0 || addr.Index != 0 {
954 p.errorf("%s: expected register; found %s", op, obj.Dconv(prog, addr))
955 }
956 return addr.Reg
957 }
958
View as plain text