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