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