Source file src/pkg/cmd/internal/obj/arm64/obj7.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package arm64
32
33 import (
34 "cmd/internal/obj"
35 "cmd/internal/objabi"
36 "cmd/internal/sys"
37 "math"
38 )
39
40 var complements = []obj.As{
41 AADD: ASUB,
42 AADDW: ASUBW,
43 ASUB: AADD,
44 ASUBW: AADDW,
45 ACMP: ACMN,
46 ACMPW: ACMNW,
47 ACMN: ACMP,
48 ACMNW: ACMPW,
49 }
50
51 func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
52
53 p = obj.Appendp(p, c.newprog)
54
55 p.As = AMOVD
56 p.From.Type = obj.TYPE_MEM
57 p.From.Reg = REGG
58 p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize)
59 if c.cursym.CFunc() {
60 p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize)
61 }
62 p.To.Type = obj.TYPE_REG
63 p.To.Reg = REG_R1
64
65 q := (*obj.Prog)(nil)
66 if framesize <= objabi.StackSmall {
67
68
69
70 p = obj.Appendp(p, c.newprog)
71
72 p.As = AMOVD
73 p.From.Type = obj.TYPE_REG
74 p.From.Reg = REGSP
75 p.To.Type = obj.TYPE_REG
76 p.To.Reg = REG_R2
77
78 p = obj.Appendp(p, c.newprog)
79 p.As = ACMP
80 p.From.Type = obj.TYPE_REG
81 p.From.Reg = REG_R1
82 p.Reg = REG_R2
83 } else if framesize <= objabi.StackBig {
84
85
86
87 p = obj.Appendp(p, c.newprog)
88
89 p.As = ASUB
90 p.From.Type = obj.TYPE_CONST
91 p.From.Offset = int64(framesize) - objabi.StackSmall
92 p.Reg = REGSP
93 p.To.Type = obj.TYPE_REG
94 p.To.Reg = REG_R2
95
96 p = obj.Appendp(p, c.newprog)
97 p.As = ACMP
98 p.From.Type = obj.TYPE_REG
99 p.From.Reg = REG_R1
100 p.Reg = REG_R2
101 } else {
102
103
104
105
106
107
108
109
110
111
112
113 p = obj.Appendp(p, c.newprog)
114
115 p.As = ACMP
116 p.From.Type = obj.TYPE_CONST
117 p.From.Offset = objabi.StackPreempt
118 p.Reg = REG_R1
119
120 p = obj.Appendp(p, c.newprog)
121 q = p
122 p.As = ABEQ
123 p.To.Type = obj.TYPE_BRANCH
124
125 p = obj.Appendp(p, c.newprog)
126 p.As = AADD
127 p.From.Type = obj.TYPE_CONST
128 p.From.Offset = int64(objabi.StackGuard)
129 p.Reg = REGSP
130 p.To.Type = obj.TYPE_REG
131 p.To.Reg = REG_R2
132
133 p = obj.Appendp(p, c.newprog)
134 p.As = ASUB
135 p.From.Type = obj.TYPE_REG
136 p.From.Reg = REG_R1
137 p.To.Type = obj.TYPE_REG
138 p.To.Reg = REG_R2
139
140 p = obj.Appendp(p, c.newprog)
141 p.As = AMOVD
142 p.From.Type = obj.TYPE_CONST
143 p.From.Offset = int64(framesize) + (int64(objabi.StackGuard) - objabi.StackSmall)
144 p.To.Type = obj.TYPE_REG
145 p.To.Reg = REG_R3
146
147 p = obj.Appendp(p, c.newprog)
148 p.As = ACMP
149 p.From.Type = obj.TYPE_REG
150 p.From.Reg = REG_R3
151 p.Reg = REG_R2
152 }
153
154
155 bls := obj.Appendp(p, c.newprog)
156 bls.As = ABLS
157 bls.To.Type = obj.TYPE_BRANCH
158
159 var last *obj.Prog
160 for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
161 }
162
163
164
165
166 spfix := obj.Appendp(last, c.newprog)
167 spfix.As = obj.ANOP
168 spfix.Spadj = -framesize
169
170 pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
171
172
173 movlr := obj.Appendp(pcdata, c.newprog)
174 movlr.As = AMOVD
175 movlr.From.Type = obj.TYPE_REG
176 movlr.From.Reg = REGLINK
177 movlr.To.Type = obj.TYPE_REG
178 movlr.To.Reg = REG_R3
179 if q != nil {
180 q.Pcond = movlr
181 }
182 bls.Pcond = movlr
183
184 debug := movlr
185 if false {
186 debug = obj.Appendp(debug, c.newprog)
187 debug.As = AMOVD
188 debug.From.Type = obj.TYPE_CONST
189 debug.From.Offset = int64(framesize)
190 debug.To.Type = obj.TYPE_REG
191 debug.To.Reg = REGTMP
192 }
193
194
195 call := obj.Appendp(debug, c.newprog)
196 call.As = ABL
197 call.To.Type = obj.TYPE_BRANCH
198 morestack := "runtime.morestack"
199 switch {
200 case c.cursym.CFunc():
201 morestack = "runtime.morestackc"
202 case !c.cursym.Func.Text.From.Sym.NeedCtxt():
203 morestack = "runtime.morestack_noctxt"
204 }
205 call.To.Sym = c.ctxt.Lookup(morestack)
206
207
208 jmp := obj.Appendp(call, c.newprog)
209 jmp.As = AB
210 jmp.To.Type = obj.TYPE_BRANCH
211 jmp.Pcond = c.cursym.Func.Text.Link
212 jmp.Spadj = +framesize
213
214
215
216
217
218 return bls
219 }
220
221 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
222 c := ctxt7{ctxt: ctxt, newprog: newprog}
223
224 p.From.Class = 0
225 p.To.Class = 0
226
227
228
229
230
231 if p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 {
232 p.From.Type = obj.TYPE_REG
233 p.From.Reg = REGZERO
234 }
235 if p.To.Type == obj.TYPE_CONST && p.To.Offset == 0 {
236 p.To.Type = obj.TYPE_REG
237 p.To.Reg = REGZERO
238 }
239
240
241 switch p.As {
242 case AB,
243 ABL,
244 obj.ARET,
245 obj.ADUFFZERO,
246 obj.ADUFFCOPY:
247 if p.To.Sym != nil {
248 p.To.Type = obj.TYPE_BRANCH
249 }
250 break
251 }
252
253
254 switch p.As {
255 case AFMOVS:
256 if p.From.Type == obj.TYPE_FCONST {
257 f64 := p.From.Val.(float64)
258 f32 := float32(f64)
259 if c.chipfloat7(f64) > 0 {
260 break
261 }
262 if math.Float32bits(f32) == 0 {
263 p.From.Type = obj.TYPE_REG
264 p.From.Reg = REGZERO
265 break
266 }
267 p.From.Type = obj.TYPE_MEM
268 p.From.Sym = c.ctxt.Float32Sym(f32)
269 p.From.Name = obj.NAME_EXTERN
270 p.From.Offset = 0
271 }
272
273 case AFMOVD:
274 if p.From.Type == obj.TYPE_FCONST {
275 f64 := p.From.Val.(float64)
276 if c.chipfloat7(f64) > 0 {
277 break
278 }
279 if math.Float64bits(f64) == 0 {
280 p.From.Type = obj.TYPE_REG
281 p.From.Reg = REGZERO
282 break
283 }
284 p.From.Type = obj.TYPE_MEM
285 p.From.Sym = c.ctxt.Float64Sym(f64)
286 p.From.Name = obj.NAME_EXTERN
287 p.From.Offset = 0
288 }
289
290 break
291 }
292
293
294
295 switch p.As {
296 case AADD, ASUB, ACMP, ACMN:
297 if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
298 p.From.Offset = -p.From.Offset
299 p.As = complements[p.As]
300 }
301 case AADDW, ASUBW, ACMPW, ACMNW:
302 if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
303 p.From.Offset = -p.From.Offset
304 p.As = complements[p.As]
305 }
306 }
307
308
309
310
311
312
313
314 if isANDWop(p.As) && p.From.Type == obj.TYPE_CONST {
315 v := p.From.Offset & 0xffffffff
316 p.From.Offset = v | v<<32
317 }
318
319 if c.ctxt.Flag_dynlink {
320 c.rewriteToUseGot(p)
321 }
322 }
323
324
325 func (c *ctxt7) rewriteToUseGot(p *obj.Prog) {
326 if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
327
328
329
330
331
332 var sym *obj.LSym
333 if p.As == obj.ADUFFZERO {
334 sym = c.ctxt.Lookup("runtime.duffzero")
335 } else {
336 sym = c.ctxt.Lookup("runtime.duffcopy")
337 }
338 offset := p.To.Offset
339 p.As = AMOVD
340 p.From.Type = obj.TYPE_MEM
341 p.From.Name = obj.NAME_GOTREF
342 p.From.Sym = sym
343 p.To.Type = obj.TYPE_REG
344 p.To.Reg = REGTMP
345 p.To.Name = obj.NAME_NONE
346 p.To.Offset = 0
347 p.To.Sym = nil
348 p1 := obj.Appendp(p, c.newprog)
349 p1.As = AADD
350 p1.From.Type = obj.TYPE_CONST
351 p1.From.Offset = offset
352 p1.To.Type = obj.TYPE_REG
353 p1.To.Reg = REGTMP
354 p2 := obj.Appendp(p1, c.newprog)
355 p2.As = obj.ACALL
356 p2.To.Type = obj.TYPE_REG
357 p2.To.Reg = REGTMP
358 }
359
360
361
362
363 if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
364
365
366 if p.As != AMOVD {
367 c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
368 }
369 if p.To.Type != obj.TYPE_REG {
370 c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
371 }
372 p.From.Type = obj.TYPE_MEM
373 p.From.Name = obj.NAME_GOTREF
374 if p.From.Offset != 0 {
375 q := obj.Appendp(p, c.newprog)
376 q.As = AADD
377 q.From.Type = obj.TYPE_CONST
378 q.From.Offset = p.From.Offset
379 q.To = p.To
380 p.From.Offset = 0
381 }
382 }
383 if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
384 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
385 }
386 var source *obj.Addr
387
388
389
390 if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
391 if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
392 c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
393 }
394 source = &p.From
395 } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
396 source = &p.To
397 } else {
398 return
399 }
400 if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
401 return
402 }
403 if source.Sym.Type == objabi.STLSBSS {
404 return
405 }
406 if source.Type != obj.TYPE_MEM {
407 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
408 }
409 p1 := obj.Appendp(p, c.newprog)
410 p2 := obj.Appendp(p1, c.newprog)
411 p1.As = AMOVD
412 p1.From.Type = obj.TYPE_MEM
413 p1.From.Sym = source.Sym
414 p1.From.Name = obj.NAME_GOTREF
415 p1.To.Type = obj.TYPE_REG
416 p1.To.Reg = REGTMP
417
418 p2.As = p.As
419 p2.From = p.From
420 p2.To = p.To
421 if p.From.Name == obj.NAME_EXTERN {
422 p2.From.Reg = REGTMP
423 p2.From.Name = obj.NAME_NONE
424 p2.From.Sym = nil
425 } else if p.To.Name == obj.NAME_EXTERN {
426 p2.To.Reg = REGTMP
427 p2.To.Name = obj.NAME_NONE
428 p2.To.Sym = nil
429 } else {
430 return
431 }
432 obj.Nopout(p)
433 }
434
435 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
436 if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
437 return
438 }
439
440 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym}
441
442 p := c.cursym.Func.Text
443 textstksiz := p.To.Offset
444 if textstksiz == -8 {
445
446 p.From.Sym.Set(obj.AttrNoFrame, true)
447 textstksiz = 0
448 }
449 if textstksiz < 0 {
450 c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz)
451 }
452 if p.From.Sym.NoFrame() {
453 if textstksiz != 0 {
454 c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
455 }
456 }
457
458 c.cursym.Func.Args = p.To.Val.(int32)
459 c.cursym.Func.Locals = int32(textstksiz)
460
461
466 q := (*obj.Prog)(nil)
467 var q1 *obj.Prog
468 for p := c.cursym.Func.Text; p != nil; p = p.Link {
469 switch p.As {
470 case obj.ATEXT:
471 p.Mark |= LEAF
472
473 case obj.ARET:
474 break
475
476 case obj.ANOP:
477 if p.Link != nil {
478 q1 = p.Link
479 q.Link = q1
480 q1.Mark |= p.Mark
481 }
482 continue
483
484 case ABL,
485 obj.ADUFFZERO,
486 obj.ADUFFCOPY:
487 c.cursym.Func.Text.Mark &^= LEAF
488 fallthrough
489
490 case ACBNZ,
491 ACBZ,
492 ACBNZW,
493 ACBZW,
494 ATBZ,
495 ATBNZ,
496 AB,
497 ABEQ,
498 ABNE,
499 ABCS,
500 ABHS,
501 ABCC,
502 ABLO,
503 ABMI,
504 ABPL,
505 ABVS,
506 ABVC,
507 ABHI,
508 ABLS,
509 ABGE,
510 ABLT,
511 ABGT,
512 ABLE,
513 AADR,
514 AADRP:
515 q1 = p.Pcond
516
517 if q1 != nil {
518 for q1.As == obj.ANOP {
519 q1 = q1.Link
520 p.Pcond = q1
521 }
522 }
523
524 break
525 }
526
527 q = p
528 }
529
530 var retjmp *obj.LSym
531 for p := c.cursym.Func.Text; p != nil; p = p.Link {
532 o := p.As
533 switch o {
534 case obj.ATEXT:
535 c.cursym.Func.Text = p
536 c.autosize = int32(textstksiz)
537
538 if p.Mark&LEAF != 0 && c.autosize == 0 {
539
540 p.From.Sym.Set(obj.AttrNoFrame, true)
541 }
542
543 if !p.From.Sym.NoFrame() {
544
545
546 c.autosize += 8
547 }
548
549 if c.autosize != 0 {
550 extrasize := int32(0)
551 if c.autosize%16 == 8 {
552
553 extrasize = 8
554 } else if c.autosize&(16-1) == 0 {
555
556 extrasize = 16
557 } else {
558 c.ctxt.Diag("%v: unaligned frame size %d - must be 16 aligned", p, c.autosize-8)
559 }
560 c.autosize += extrasize
561 c.cursym.Func.Locals += extrasize
562
563
564
565 p.To.Offset = int64(c.autosize) | int64(extrasize)<<32
566 } else {
567
568 p.To.Offset = 0
569 }
570
571 if c.autosize == 0 && c.cursym.Func.Text.Mark&LEAF == 0 {
572 if c.ctxt.Debugvlog {
573 c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func.Text.From.Sym.Name)
574 }
575 c.cursym.Func.Text.Mark |= LEAF
576 }
577
578 if cursym.Func.Text.Mark&LEAF != 0 {
579 cursym.Set(obj.AttrLeaf, true)
580 if p.From.Sym.NoFrame() {
581 break
582 }
583 }
584
585 if !p.From.Sym.NoSplit() {
586 p = c.stacksplit(p, c.autosize)
587 }
588
589 aoffset := c.autosize
590 if aoffset > 0xF0 {
591 aoffset = 0xF0
592 }
593
594
595
596 q = p
597 if c.autosize > aoffset {
598
599
600
601
602 q = obj.Appendp(q, c.newprog)
603 q.Pos = p.Pos
604 q.As = ASUB
605 q.From.Type = obj.TYPE_CONST
606 q.From.Offset = int64(c.autosize)
607 q.Reg = REGSP
608 q.To.Type = obj.TYPE_REG
609 q.To.Reg = REGTMP
610
611 q = obj.Appendp(q, c.newprog)
612 q.Pos = p.Pos
613 q.As = AMOVD
614 q.From.Type = obj.TYPE_REG
615 q.From.Reg = REGLINK
616 q.To.Type = obj.TYPE_MEM
617 q.To.Reg = REGTMP
618
619 q1 = obj.Appendp(q, c.newprog)
620 q1.Pos = p.Pos
621 q1.As = AMOVD
622 q1.From.Type = obj.TYPE_REG
623 q1.From.Reg = REGTMP
624 q1.To.Type = obj.TYPE_REG
625 q1.To.Reg = REGSP
626 q1.Spadj = c.autosize
627 } else {
628
629 q1 = obj.Appendp(q, c.newprog)
630 q1.As = AMOVD
631 q1.Pos = p.Pos
632 q1.From.Type = obj.TYPE_REG
633 q1.From.Reg = REGLINK
634 q1.To.Type = obj.TYPE_MEM
635 q1.Scond = C_XPRE
636 q1.To.Offset = int64(-aoffset)
637 q1.To.Reg = REGSP
638 q1.Spadj = aoffset
639 }
640
641 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
642 q1 = obj.Appendp(q1, c.newprog)
643 q1.Pos = p.Pos
644 q1.As = AMOVD
645 q1.From.Type = obj.TYPE_REG
646 q1.From.Reg = REGFP
647 q1.To.Type = obj.TYPE_MEM
648 q1.To.Reg = REGSP
649 q1.To.Offset = -8
650
651 q1 = obj.Appendp(q1, c.newprog)
652 q1.Pos = p.Pos
653 q1.As = ASUB
654 q1.From.Type = obj.TYPE_CONST
655 q1.From.Offset = 8
656 q1.Reg = REGSP
657 q1.To.Type = obj.TYPE_REG
658 q1.To.Reg = REGFP
659 }
660
661 if c.cursym.Func.Text.From.Sym.Wrapper() {
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680 q = q1
681
682
683 q = obj.Appendp(q, c.newprog)
684 q.As = AMOVD
685 q.From.Type = obj.TYPE_MEM
686 q.From.Reg = REGG
687 q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize)
688 q.To.Type = obj.TYPE_REG
689 q.To.Reg = REG_R1
690
691
692 cbnz := obj.Appendp(q, c.newprog)
693 cbnz.As = ACBNZ
694 cbnz.From.Type = obj.TYPE_REG
695 cbnz.From.Reg = REG_R1
696 cbnz.To.Type = obj.TYPE_BRANCH
697
698
699 end := obj.Appendp(cbnz, c.newprog)
700 end.As = obj.ANOP
701
702
703 var last *obj.Prog
704 for last = end; last.Link != nil; last = last.Link {
705 }
706
707
708 mov := obj.Appendp(last, c.newprog)
709 mov.As = AMOVD
710 mov.From.Type = obj.TYPE_MEM
711 mov.From.Reg = REG_R1
712 mov.From.Offset = 0
713 mov.To.Type = obj.TYPE_REG
714 mov.To.Reg = REG_R2
715
716
717 cbnz.Pcond = mov
718
719
720 q = obj.Appendp(mov, c.newprog)
721 q.As = AADD
722 q.From.Type = obj.TYPE_CONST
723 q.From.Offset = int64(c.autosize) + 8
724 q.Reg = REGSP
725 q.To.Type = obj.TYPE_REG
726 q.To.Reg = REG_R3
727
728
729 q = obj.Appendp(q, c.newprog)
730 q.As = ACMP
731 q.From.Type = obj.TYPE_REG
732 q.From.Reg = REG_R2
733 q.Reg = REG_R3
734
735
736 q = obj.Appendp(q, c.newprog)
737 q.As = ABNE
738 q.To.Type = obj.TYPE_BRANCH
739 q.Pcond = end
740
741
742 q = obj.Appendp(q, c.newprog)
743 q.As = AADD
744 q.From.Type = obj.TYPE_CONST
745 q.From.Offset = 8
746 q.Reg = REGSP
747 q.To.Type = obj.TYPE_REG
748 q.To.Reg = REG_R4
749
750
751 q = obj.Appendp(q, c.newprog)
752 q.As = AMOVD
753 q.From.Type = obj.TYPE_REG
754 q.From.Reg = REG_R4
755 q.To.Type = obj.TYPE_MEM
756 q.To.Reg = REG_R1
757 q.To.Offset = 0
758
759
760 q = obj.Appendp(q, c.newprog)
761 q.As = AB
762 q.To.Type = obj.TYPE_BRANCH
763 q.Pcond = end
764 }
765
766 case obj.ARET:
767 nocache(p)
768 if p.From.Type == obj.TYPE_CONST {
769 c.ctxt.Diag("using BECOME (%v) is not supported!", p)
770 break
771 }
772
773 retjmp = p.To.Sym
774 p.To = obj.Addr{}
775 if c.cursym.Func.Text.Mark&LEAF != 0 {
776 if c.autosize != 0 {
777 p.As = AADD
778 p.From.Type = obj.TYPE_CONST
779 p.From.Offset = int64(c.autosize)
780 p.To.Type = obj.TYPE_REG
781 p.To.Reg = REGSP
782 p.Spadj = -c.autosize
783
784 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
785 p = obj.Appendp(p, c.newprog)
786 p.As = ASUB
787 p.From.Type = obj.TYPE_CONST
788 p.From.Offset = 8
789 p.Reg = REGSP
790 p.To.Type = obj.TYPE_REG
791 p.To.Reg = REGFP
792 }
793 }
794 } else {
795
796
797 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
798 p.As = AMOVD
799 p.From.Type = obj.TYPE_MEM
800 p.From.Reg = REGSP
801 p.From.Offset = -8
802 p.To.Type = obj.TYPE_REG
803 p.To.Reg = REGFP
804 p = obj.Appendp(p, c.newprog)
805 }
806
807 aoffset := c.autosize
808
809 if aoffset > 0xF0 {
810 aoffset = 0xF0
811 }
812 p.As = AMOVD
813 p.From.Type = obj.TYPE_MEM
814 p.Scond = C_XPOST
815 p.From.Offset = int64(aoffset)
816 p.From.Reg = REGSP
817 p.To.Type = obj.TYPE_REG
818 p.To.Reg = REGLINK
819 p.Spadj = -aoffset
820 if c.autosize > aoffset {
821 q = newprog()
822 q.As = AADD
823 q.From.Type = obj.TYPE_CONST
824 q.From.Offset = int64(c.autosize) - int64(aoffset)
825 q.To.Type = obj.TYPE_REG
826 q.To.Reg = REGSP
827 q.Link = p.Link
828 q.Spadj = int32(-q.From.Offset)
829 q.Pos = p.Pos
830 p.Link = q
831 p = q
832 }
833 }
834
835 if p.As != obj.ARET {
836 q = newprog()
837 q.Pos = p.Pos
838 q.Link = p.Link
839 p.Link = q
840 p = q
841 }
842
843 if retjmp != nil {
844 p.As = AB
845 p.To.Type = obj.TYPE_BRANCH
846 p.To.Sym = retjmp
847 p.Spadj = +c.autosize
848 break
849 }
850
851 p.As = obj.ARET
852 p.To.Type = obj.TYPE_MEM
853 p.To.Offset = 0
854 p.To.Reg = REGLINK
855 p.Spadj = +c.autosize
856
857 case AADD, ASUB:
858 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
859 if p.As == AADD {
860 p.Spadj = int32(-p.From.Offset)
861 } else {
862 p.Spadj = int32(+p.From.Offset)
863 }
864 }
865
866 case obj.AGETCALLERPC:
867 if cursym.Leaf() {
868
869 p.As = AMOVD
870 p.From.Type = obj.TYPE_REG
871 p.From.Reg = REGLINK
872 } else {
873
874 p.As = AMOVD
875 p.From.Type = obj.TYPE_MEM
876 p.From.Reg = REGSP
877 }
878
879 case obj.ADUFFCOPY:
880 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
881
882
883
884
885
886
887
888 q1 := p
889
890 q4 := obj.Appendp(p, c.newprog)
891 q4.Pos = p.Pos
892 q4.As = obj.ADUFFCOPY
893 q4.To = p.To
894
895 q1.As = AADR
896 q1.From.Type = obj.TYPE_BRANCH
897 q1.To.Type = obj.TYPE_REG
898 q1.To.Reg = REG_R27
899
900 q2 := obj.Appendp(q1, c.newprog)
901 q2.Pos = p.Pos
902 q2.As = ASTP
903 q2.From.Type = obj.TYPE_REGREG
904 q2.From.Reg = REGFP
905 q2.From.Offset = int64(REG_R27)
906 q2.To.Type = obj.TYPE_MEM
907 q2.To.Reg = REGSP
908 q2.To.Offset = -24
909
910
911 q3 := obj.Appendp(q2, c.newprog)
912 q3.Pos = p.Pos
913 q3.As = ASUB
914 q3.From.Type = obj.TYPE_CONST
915 q3.From.Offset = 24
916 q3.Reg = REGSP
917 q3.To.Type = obj.TYPE_REG
918 q3.To.Reg = REGFP
919
920 q5 := obj.Appendp(q4, c.newprog)
921 q5.Pos = p.Pos
922 q5.As = ASUB
923 q5.From.Type = obj.TYPE_CONST
924 q5.From.Offset = 8
925 q5.Reg = REGSP
926 q5.To.Type = obj.TYPE_REG
927 q5.To.Reg = REGFP
928 q1.Pcond = q5
929 p = q5
930 }
931
932 case obj.ADUFFZERO:
933 if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
934
935
936
937
938
939
940
941 q1 := p
942
943 q4 := obj.Appendp(p, c.newprog)
944 q4.Pos = p.Pos
945 q4.As = obj.ADUFFZERO
946 q4.To = p.To
947
948 q1.As = AADR
949 q1.From.Type = obj.TYPE_BRANCH
950 q1.To.Type = obj.TYPE_REG
951 q1.To.Reg = REG_R27
952
953 q2 := obj.Appendp(q1, c.newprog)
954 q2.Pos = p.Pos
955 q2.As = ASTP
956 q2.From.Type = obj.TYPE_REGREG
957 q2.From.Reg = REGFP
958 q2.From.Offset = int64(REG_R27)
959 q2.To.Type = obj.TYPE_MEM
960 q2.To.Reg = REGSP
961 q2.To.Offset = -24
962
963
964 q3 := obj.Appendp(q2, c.newprog)
965 q3.Pos = p.Pos
966 q3.As = ASUB
967 q3.From.Type = obj.TYPE_CONST
968 q3.From.Offset = 24
969 q3.Reg = REGSP
970 q3.To.Type = obj.TYPE_REG
971 q3.To.Reg = REGFP
972
973 q5 := obj.Appendp(q4, c.newprog)
974 q5.Pos = p.Pos
975 q5.As = ASUB
976 q5.From.Type = obj.TYPE_CONST
977 q5.From.Offset = 8
978 q5.Reg = REGSP
979 q5.To.Type = obj.TYPE_REG
980 q5.To.Reg = REGFP
981 q1.Pcond = q5
982 p = q5
983 }
984 }
985 }
986 }
987
988 func nocache(p *obj.Prog) {
989 p.Optab = 0
990 p.From.Class = 0
991 p.To.Class = 0
992 }
993
994 var unaryDst = map[obj.As]bool{
995 AWORD: true,
996 ADWORD: true,
997 ABL: true,
998 AB: true,
999 ACLREX: true,
1000 }
1001
1002 var Linkarm64 = obj.LinkArch{
1003 Arch: sys.ArchARM64,
1004 Init: buildop,
1005 Preprocess: preprocess,
1006 Assemble: span7,
1007 Progedit: progedit,
1008 UnaryDst: unaryDst,
1009 DWARFRegisters: ARM64DWARFRegisters,
1010 }
1011
View as plain text