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