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 package ppc64
31
32 import (
33 "cmd/internal/obj"
34 "cmd/internal/objabi"
35 "cmd/internal/src"
36 "cmd/internal/sys"
37 "log"
38 )
39
40 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
41 p.From.Class = 0
42 p.To.Class = 0
43
44 c := ctxt9{ctxt: ctxt, newprog: newprog}
45
46
47 switch p.As {
48 case ABR,
49 ABL,
50 obj.ARET,
51 obj.ADUFFZERO,
52 obj.ADUFFCOPY:
53 if p.To.Sym != nil {
54 p.To.Type = obj.TYPE_BRANCH
55 }
56 }
57
58
59 switch p.As {
60 case AFMOVS:
61 if p.From.Type == obj.TYPE_FCONST {
62 f32 := float32(p.From.Val.(float64))
63 p.From.Type = obj.TYPE_MEM
64 p.From.Sym = ctxt.Float32Sym(f32)
65 p.From.Name = obj.NAME_EXTERN
66 p.From.Offset = 0
67 }
68
69 case AFMOVD:
70 if p.From.Type == obj.TYPE_FCONST {
71 f64 := p.From.Val.(float64)
72
73 if f64 != 0 {
74 p.From.Type = obj.TYPE_MEM
75 p.From.Sym = ctxt.Float64Sym(f64)
76 p.From.Name = obj.NAME_EXTERN
77 p.From.Offset = 0
78 }
79 }
80
81
82 case AMOVD:
83 if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset {
84 p.From.Type = obj.TYPE_MEM
85 p.From.Sym = ctxt.Int64Sym(p.From.Offset)
86 p.From.Name = obj.NAME_EXTERN
87 p.From.Offset = 0
88 }
89 }
90
91
92 switch p.As {
93 case ASUBC:
94 if p.From.Type == obj.TYPE_CONST {
95 p.From.Offset = -p.From.Offset
96 p.As = AADDC
97 }
98
99 case ASUBCCC:
100 if p.From.Type == obj.TYPE_CONST {
101 p.From.Offset = -p.From.Offset
102 p.As = AADDCCC
103 }
104
105 case ASUB:
106 if p.From.Type == obj.TYPE_CONST {
107 p.From.Offset = -p.From.Offset
108 p.As = AADD
109 }
110 }
111 if c.ctxt.Headtype == objabi.Haix {
112 c.rewriteToUseTOC(p)
113 } else if c.ctxt.Flag_dynlink {
114 c.rewriteToUseGot(p)
115 }
116 }
117
118
119
120 func (c *ctxt9) rewriteToUseTOC(p *obj.Prog) {
121 if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
122 return
123 }
124
125 if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
126
127
128 if !c.ctxt.Flag_dynlink {
129 return
130 }
131
132
133
134
135
136
137 var sym *obj.LSym
138 if p.As == obj.ADUFFZERO {
139 sym = c.ctxt.Lookup("runtime.duffzero")
140 } else {
141 sym = c.ctxt.Lookup("runtime.duffcopy")
142 }
143
144 symtoc := c.ctxt.LookupInit("TOC."+sym.Name, func(s *obj.LSym) {
145 s.Type = objabi.SDATA
146 s.Set(obj.AttrDuplicateOK, true)
147 s.Set(obj.AttrStatic, true)
148 c.ctxt.Data = append(c.ctxt.Data, s)
149 s.WriteAddr(c.ctxt, 0, 8, sym, 0)
150 })
151
152 offset := p.To.Offset
153 p.As = AMOVD
154 p.From.Type = obj.TYPE_MEM
155 p.From.Name = obj.NAME_TOCREF
156 p.From.Sym = symtoc
157 p.To.Type = obj.TYPE_REG
158 p.To.Reg = REG_R12
159 p.To.Name = obj.NAME_NONE
160 p.To.Offset = 0
161 p.To.Sym = nil
162 p1 := obj.Appendp(p, c.newprog)
163 p1.As = AADD
164 p1.From.Type = obj.TYPE_CONST
165 p1.From.Offset = offset
166 p1.To.Type = obj.TYPE_REG
167 p1.To.Reg = REG_R12
168 p2 := obj.Appendp(p1, c.newprog)
169 p2.As = AMOVD
170 p2.From.Type = obj.TYPE_REG
171 p2.From.Reg = REG_R12
172 p2.To.Type = obj.TYPE_REG
173 p2.To.Reg = REG_LR
174 p3 := obj.Appendp(p2, c.newprog)
175 p3.As = obj.ACALL
176 p3.To.Type = obj.TYPE_REG
177 p3.To.Reg = REG_LR
178 }
179
180 var source *obj.Addr
181 if p.From.Name == obj.NAME_EXTERN || p.From.Name == obj.NAME_STATIC {
182 if p.From.Type == obj.TYPE_ADDR {
183 if p.As == ADWORD {
184
185 return
186 }
187 if p.As != AMOVD {
188 c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v", p)
189 return
190 }
191 if p.To.Type != obj.TYPE_REG {
192 c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v", p)
193 return
194 }
195 } else if p.From.Type != obj.TYPE_MEM {
196 c.ctxt.Diag("do not know how to handle %v without TYPE_MEM", p)
197 return
198 }
199 source = &p.From
200
201 } else if p.To.Name == obj.NAME_EXTERN || p.To.Name == obj.NAME_STATIC {
202 if p.To.Type != obj.TYPE_MEM {
203 c.ctxt.Diag("do not know how to handle %v without TYPE_MEM", p)
204 return
205 }
206 if source != nil {
207 c.ctxt.Diag("cannot handle symbols on both sides in %v", p)
208 return
209 }
210 source = &p.To
211 } else {
212 return
213
214 }
215
216 if source.Sym == nil {
217 c.ctxt.Diag("do not know how to handle nil symbol in %v", p)
218 return
219 }
220
221 if source.Sym.Type == objabi.STLSBSS {
222 return
223 }
224
225
226 symtoc := c.ctxt.LookupInit("TOC."+source.Sym.Name, func(s *obj.LSym) {
227 s.Type = objabi.SDATA
228 s.Set(obj.AttrDuplicateOK, true)
229 s.Set(obj.AttrStatic, true)
230 c.ctxt.Data = append(c.ctxt.Data, s)
231 s.WriteAddr(c.ctxt, 0, 8, source.Sym, 0)
232 })
233
234 if source.Type == obj.TYPE_ADDR {
235
236
237 p.From.Type = obj.TYPE_MEM
238 p.From.Sym = symtoc
239 p.From.Name = obj.NAME_TOCREF
240
241 if p.From.Offset != 0 {
242 q := obj.Appendp(p, c.newprog)
243 q.As = AADD
244 q.From.Type = obj.TYPE_CONST
245 q.From.Offset = p.From.Offset
246 p.From.Offset = 0
247 q.To = p.To
248 }
249 return
250
251 }
252
253
254
255
256
257 q := obj.Appendp(p, c.newprog)
258 q.As = AMOVD
259 q.From.Type = obj.TYPE_MEM
260 q.From.Sym = symtoc
261 q.From.Name = obj.NAME_TOCREF
262 q.To.Type = obj.TYPE_REG
263 q.To.Reg = REGTMP
264
265 q = obj.Appendp(q, c.newprog)
266 q.As = p.As
267 q.From = p.From
268 q.To = p.To
269 if p.From.Name != obj.NAME_NONE {
270 q.From.Type = obj.TYPE_MEM
271 q.From.Reg = REGTMP
272 q.From.Name = obj.NAME_NONE
273 q.From.Sym = nil
274 } else if p.To.Name != obj.NAME_NONE {
275 q.To.Type = obj.TYPE_MEM
276 q.To.Reg = REGTMP
277 q.To.Name = obj.NAME_NONE
278 q.To.Sym = nil
279 } else {
280 c.ctxt.Diag("unreachable case in rewriteToUseTOC with %v", p)
281 }
282
283 obj.Nopout(p)
284 }
285
286
287 func (c *ctxt9) rewriteToUseGot(p *obj.Prog) {
288 if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
289
290
291
292
293
294
295 var sym *obj.LSym
296 if p.As == obj.ADUFFZERO {
297 sym = c.ctxt.LookupABI("runtime.duffzero", obj.ABIInternal)
298 } else {
299 sym = c.ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal)
300 }
301 offset := p.To.Offset
302 p.As = AMOVD
303 p.From.Type = obj.TYPE_MEM
304 p.From.Name = obj.NAME_GOTREF
305 p.From.Sym = sym
306 p.To.Type = obj.TYPE_REG
307 p.To.Reg = REG_R12
308 p.To.Name = obj.NAME_NONE
309 p.To.Offset = 0
310 p.To.Sym = nil
311 p1 := obj.Appendp(p, c.newprog)
312 p1.As = AADD
313 p1.From.Type = obj.TYPE_CONST
314 p1.From.Offset = offset
315 p1.To.Type = obj.TYPE_REG
316 p1.To.Reg = REG_R12
317 p2 := obj.Appendp(p1, c.newprog)
318 p2.As = AMOVD
319 p2.From.Type = obj.TYPE_REG
320 p2.From.Reg = REG_R12
321 p2.To.Type = obj.TYPE_REG
322 p2.To.Reg = REG_LR
323 p3 := obj.Appendp(p2, c.newprog)
324 p3.As = obj.ACALL
325 p3.To.Type = obj.TYPE_REG
326 p3.To.Reg = REG_LR
327 }
328
329
330
331
332 if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
333
334
335 if p.As != AMOVD {
336 c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
337 }
338 if p.To.Type != obj.TYPE_REG {
339 c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
340 }
341 p.From.Type = obj.TYPE_MEM
342 p.From.Name = obj.NAME_GOTREF
343 if p.From.Offset != 0 {
344 q := obj.Appendp(p, c.newprog)
345 q.As = AADD
346 q.From.Type = obj.TYPE_CONST
347 q.From.Offset = p.From.Offset
348 q.To = p.To
349 p.From.Offset = 0
350 }
351 }
352 if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
353 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
354 }
355 var source *obj.Addr
356
357
358
359 if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
360 if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
361 c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
362 }
363 source = &p.From
364 } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
365 source = &p.To
366 } else {
367 return
368 }
369 if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
370 return
371 }
372 if source.Sym.Type == objabi.STLSBSS {
373 return
374 }
375 if source.Type != obj.TYPE_MEM {
376 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
377 }
378 p1 := obj.Appendp(p, c.newprog)
379 p2 := obj.Appendp(p1, c.newprog)
380
381 p1.As = AMOVD
382 p1.From.Type = obj.TYPE_MEM
383 p1.From.Sym = source.Sym
384 p1.From.Name = obj.NAME_GOTREF
385 p1.To.Type = obj.TYPE_REG
386 p1.To.Reg = REGTMP
387
388 p2.As = p.As
389 p2.From = p.From
390 p2.To = p.To
391 if p.From.Name == obj.NAME_EXTERN {
392 p2.From.Reg = REGTMP
393 p2.From.Name = obj.NAME_NONE
394 p2.From.Sym = nil
395 } else if p.To.Name == obj.NAME_EXTERN {
396 p2.To.Reg = REGTMP
397 p2.To.Name = obj.NAME_NONE
398 p2.To.Sym = nil
399 } else {
400 return
401 }
402 obj.Nopout(p)
403 }
404
405 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
406
407 if cursym.Func().Text == nil || cursym.Func().Text.Link == nil {
408 return
409 }
410
411 c := ctxt9{ctxt: ctxt, cursym: cursym, newprog: newprog}
412
413 p := c.cursym.Func().Text
414 textstksiz := p.To.Offset
415 if textstksiz == -8 {
416
417 p.From.Sym.Set(obj.AttrNoFrame, true)
418 textstksiz = 0
419 }
420 if textstksiz%8 != 0 {
421 c.ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
422 }
423 if p.From.Sym.NoFrame() {
424 if textstksiz != 0 {
425 c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
426 }
427 }
428
429 c.cursym.Func().Args = p.To.Val.(int32)
430 c.cursym.Func().Locals = int32(textstksiz)
431
432
437
438 var q *obj.Prog
439 var q1 *obj.Prog
440 for p := c.cursym.Func().Text; p != nil; p = p.Link {
441 switch p.As {
442
443 case obj.ATEXT:
444 q = p
445
446 p.Mark |= LABEL | LEAF | SYNC
447 if p.Link != nil {
448 p.Link.Mark |= LABEL
449 }
450
451 case ANOR:
452 q = p
453 if p.To.Type == obj.TYPE_REG {
454 if p.To.Reg == REGZERO {
455 p.Mark |= LABEL | SYNC
456 }
457 }
458
459 case ALWAR,
460 ALBAR,
461 ASTBCCC,
462 ASTWCCC,
463 AECIWX,
464 AECOWX,
465 AEIEIO,
466 AICBI,
467 AISYNC,
468 ATLBIE,
469 ATLBIEL,
470 ASLBIA,
471 ASLBIE,
472 ASLBMFEE,
473 ASLBMFEV,
474 ASLBMTE,
475 ADCBF,
476 ADCBI,
477 ADCBST,
478 ADCBT,
479 ADCBTST,
480 ADCBZ,
481 ASYNC,
482 ATLBSYNC,
483 APTESYNC,
484 ALWSYNC,
485 ATW,
486 AWORD,
487 ARFI,
488 ARFCI,
489 ARFID,
490 AHRFID:
491 q = p
492 p.Mark |= LABEL | SYNC
493 continue
494
495 case AMOVW, AMOVWZ, AMOVD:
496 q = p
497 if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL {
498 p.Mark |= LABEL | SYNC
499 }
500 continue
501
502 case AFABS,
503 AFABSCC,
504 AFADD,
505 AFADDCC,
506 AFCTIW,
507 AFCTIWCC,
508 AFCTIWZ,
509 AFCTIWZCC,
510 AFDIV,
511 AFDIVCC,
512 AFMADD,
513 AFMADDCC,
514 AFMOVD,
515 AFMOVDU,
516
517 AFMOVS,
518 AFMOVSU,
519
520
521 AFMSUB,
522 AFMSUBCC,
523 AFMUL,
524 AFMULCC,
525 AFNABS,
526 AFNABSCC,
527 AFNEG,
528 AFNEGCC,
529 AFNMADD,
530 AFNMADDCC,
531 AFNMSUB,
532 AFNMSUBCC,
533 AFRSP,
534 AFRSPCC,
535 AFSUB,
536 AFSUBCC:
537 q = p
538
539 p.Mark |= FLOAT
540 continue
541
542 case ABL,
543 ABCL,
544 obj.ADUFFZERO,
545 obj.ADUFFCOPY:
546 c.cursym.Func().Text.Mark &^= LEAF
547 fallthrough
548
549 case ABC,
550 ABEQ,
551 ABGE,
552 ABGT,
553 ABLE,
554 ABLT,
555 ABNE,
556 ABR,
557 ABVC,
558 ABVS:
559 p.Mark |= BRANCH
560 q = p
561 q1 = p.To.Target()
562 if q1 != nil {
563
564
565 if q1.Mark&LEAF == 0 {
566 q1.Mark |= LABEL
567 }
568 } else {
569 p.Mark |= LABEL
570 }
571 q1 = p.Link
572 if q1 != nil {
573 q1.Mark |= LABEL
574 }
575 continue
576
577 case AFCMPO, AFCMPU:
578 q = p
579 p.Mark |= FCMP | FLOAT
580 continue
581
582 case obj.ARET:
583 q = p
584 if p.Link != nil {
585 p.Link.Mark |= LABEL
586 }
587 continue
588
589 case obj.ANOP:
590
591
592 continue
593
594 default:
595 q = p
596 continue
597 }
598 }
599
600 autosize := int32(0)
601 var p1 *obj.Prog
602 var p2 *obj.Prog
603 for p := c.cursym.Func().Text; p != nil; p = p.Link {
604 o := p.As
605 switch o {
606 case obj.ATEXT:
607 autosize = int32(textstksiz)
608
609 if p.Mark&LEAF != 0 && autosize == 0 {
610
611 p.From.Sym.Set(obj.AttrNoFrame, true)
612 }
613
614 if !p.From.Sym.NoFrame() {
615
616
617 autosize += int32(c.ctxt.FixedFrameSize())
618 }
619
620 if p.Mark&LEAF != 0 && autosize < objabi.StackSmall {
621
622
623 p.From.Sym.Set(obj.AttrNoSplit, true)
624 }
625
626 p.To.Offset = int64(autosize)
627
628 q = p
629
630 if c.ctxt.Flag_shared && c.cursym.Name != "runtime.duffzero" && c.cursym.Name != "runtime.duffcopy" {
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652 q = obj.Appendp(q, c.newprog)
653 q.As = AWORD
654 q.Pos = p.Pos
655 q.From.Type = obj.TYPE_CONST
656 q.From.Offset = 0x3c4c0000
657 q = obj.Appendp(q, c.newprog)
658 q.As = AWORD
659 q.Pos = p.Pos
660 q.From.Type = obj.TYPE_CONST
661 q.From.Offset = 0x38420000
662 rel := obj.Addrel(c.cursym)
663 rel.Off = 0
664 rel.Siz = 8
665 rel.Sym = c.ctxt.Lookup(".TOC.")
666 rel.Type = objabi.R_ADDRPOWER_PCREL
667 }
668
669 if !c.cursym.Func().Text.From.Sym.NoSplit() {
670 q = c.stacksplit(q, autosize)
671 }
672
673
674
675
676 if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
677 var prologueEnd *obj.Prog
678
679
680
681 if autosize >= -BIG && autosize <= BIG {
682
683 q = obj.Appendp(q, c.newprog)
684 q.As = AMOVD
685 q.Pos = p.Pos
686 q.From.Type = obj.TYPE_REG
687 q.From.Reg = REG_LR
688 q.To.Type = obj.TYPE_REG
689 q.To.Reg = REGTMP
690 prologueEnd = q
691
692 q = obj.Appendp(q, c.newprog)
693 q.As = AMOVDU
694 q.Pos = p.Pos
695 q.From.Type = obj.TYPE_REG
696 q.From.Reg = REGTMP
697 q.To.Type = obj.TYPE_MEM
698 q.To.Offset = int64(-autosize)
699 q.To.Reg = REGSP
700 q.Spadj = autosize
701 } else {
702
703
704
705
706
707
708 q = obj.Appendp(q, c.newprog)
709 q.As = AMOVD
710 q.Pos = p.Pos
711 q.From.Type = obj.TYPE_REG
712 q.From.Reg = REG_LR
713 q.To.Type = obj.TYPE_REG
714 q.To.Reg = REG_R29
715
716 q = c.ctxt.StartUnsafePoint(q, c.newprog)
717
718 q = obj.Appendp(q, c.newprog)
719 q.As = AMOVD
720 q.Pos = p.Pos
721 q.From.Type = obj.TYPE_REG
722 q.From.Reg = REG_R29
723 q.To.Type = obj.TYPE_MEM
724 q.To.Offset = int64(-autosize)
725 q.To.Reg = REGSP
726
727 prologueEnd = q
728
729 q = obj.Appendp(q, c.newprog)
730 q.As = AADD
731 q.Pos = p.Pos
732 q.From.Type = obj.TYPE_CONST
733 q.From.Offset = int64(-autosize)
734 q.To.Type = obj.TYPE_REG
735 q.To.Reg = REGSP
736 q.Spadj = +autosize
737
738 q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
739 }
740 prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
741 } else if c.cursym.Func().Text.Mark&LEAF == 0 {
742
743
744
745 c.cursym.Func().Text.Mark |= LEAF
746 }
747
748 if c.cursym.Func().Text.Mark&LEAF != 0 {
749 c.cursym.Set(obj.AttrLeaf, true)
750 break
751 }
752
753 if c.ctxt.Flag_shared {
754 q = obj.Appendp(q, c.newprog)
755 q.As = AMOVD
756 q.Pos = p.Pos
757 q.From.Type = obj.TYPE_REG
758 q.From.Reg = REG_R2
759 q.To.Type = obj.TYPE_MEM
760 q.To.Reg = REGSP
761 q.To.Offset = 24
762 }
763
764 if c.cursym.Func().Text.From.Sym.Wrapper() {
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782 q = obj.Appendp(q, c.newprog)
783
784 q.As = AMOVD
785 q.From.Type = obj.TYPE_MEM
786 q.From.Reg = REGG
787 q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize)
788 q.To.Type = obj.TYPE_REG
789 q.To.Reg = REG_R22
790
791 q = obj.Appendp(q, c.newprog)
792 q.As = ACMP
793 q.From.Type = obj.TYPE_REG
794 q.From.Reg = REG_R0
795 q.To.Type = obj.TYPE_REG
796 q.To.Reg = REG_R22
797
798 q = obj.Appendp(q, c.newprog)
799 q.As = ABEQ
800 q.To.Type = obj.TYPE_BRANCH
801 p1 = q
802
803 q = obj.Appendp(q, c.newprog)
804 q.As = AMOVD
805 q.From.Type = obj.TYPE_MEM
806 q.From.Reg = REG_R22
807 q.From.Offset = 0
808 q.To.Type = obj.TYPE_REG
809 q.To.Reg = REG_R23
810
811 q = obj.Appendp(q, c.newprog)
812 q.As = AADD
813 q.From.Type = obj.TYPE_CONST
814 q.From.Offset = int64(autosize) + c.ctxt.FixedFrameSize()
815 q.Reg = REGSP
816 q.To.Type = obj.TYPE_REG
817 q.To.Reg = REG_R24
818
819 q = obj.Appendp(q, c.newprog)
820 q.As = ACMP
821 q.From.Type = obj.TYPE_REG
822 q.From.Reg = REG_R23
823 q.To.Type = obj.TYPE_REG
824 q.To.Reg = REG_R24
825
826 q = obj.Appendp(q, c.newprog)
827 q.As = ABNE
828 q.To.Type = obj.TYPE_BRANCH
829 p2 = q
830
831 q = obj.Appendp(q, c.newprog)
832 q.As = AADD
833 q.From.Type = obj.TYPE_CONST
834 q.From.Offset = c.ctxt.FixedFrameSize()
835 q.Reg = REGSP
836 q.To.Type = obj.TYPE_REG
837 q.To.Reg = REG_R25
838
839 q = obj.Appendp(q, c.newprog)
840 q.As = AMOVD
841 q.From.Type = obj.TYPE_REG
842 q.From.Reg = REG_R25
843 q.To.Type = obj.TYPE_MEM
844 q.To.Reg = REG_R22
845 q.To.Offset = 0
846
847 q = obj.Appendp(q, c.newprog)
848
849 q.As = obj.ANOP
850 p1.To.SetTarget(q)
851 p2.To.SetTarget(q)
852 }
853
854 case obj.ARET:
855 if p.From.Type == obj.TYPE_CONST {
856 c.ctxt.Diag("using BECOME (%v) is not supported!", p)
857 break
858 }
859
860 retTarget := p.To.Sym
861
862 if c.cursym.Func().Text.Mark&LEAF != 0 {
863 if autosize == 0 || c.cursym.Name == "runtime.racecallbackthunk" {
864 p.As = ABR
865 p.From = obj.Addr{}
866 if retTarget == nil {
867 p.To.Type = obj.TYPE_REG
868 p.To.Reg = REG_LR
869 } else {
870 p.To.Type = obj.TYPE_BRANCH
871 p.To.Sym = retTarget
872 }
873 p.Mark |= BRANCH
874 break
875 }
876
877 p.As = AADD
878 p.From.Type = obj.TYPE_CONST
879 p.From.Offset = int64(autosize)
880 p.To.Type = obj.TYPE_REG
881 p.To.Reg = REGSP
882 p.Spadj = -autosize
883
884 q = c.newprog()
885 q.As = ABR
886 q.Pos = p.Pos
887 if retTarget == nil {
888 q.To.Type = obj.TYPE_REG
889 q.To.Reg = REG_LR
890 } else {
891 q.To.Type = obj.TYPE_BRANCH
892 q.To.Sym = retTarget
893 }
894 q.Mark |= BRANCH
895 q.Spadj = +autosize
896
897 q.Link = p.Link
898 p.Link = q
899 break
900 }
901
902 p.As = AMOVD
903 p.From.Type = obj.TYPE_MEM
904 p.From.Offset = 0
905 p.From.Reg = REGSP
906 p.To.Type = obj.TYPE_REG
907 p.To.Reg = REGTMP
908
909 q = c.newprog()
910 q.As = AMOVD
911 q.Pos = p.Pos
912 q.From.Type = obj.TYPE_REG
913 q.From.Reg = REGTMP
914 q.To.Type = obj.TYPE_REG
915 q.To.Reg = REG_LR
916
917 q.Link = p.Link
918 p.Link = q
919 p = q
920
921 if false {
922
923 q = c.newprog()
924
925 q.As = AMOVD
926 q.Pos = p.Pos
927 q.From.Type = obj.TYPE_MEM
928 q.From.Offset = 0
929 q.From.Reg = REGTMP
930 q.To.Type = obj.TYPE_REG
931 q.To.Reg = REGTMP
932
933 q.Link = p.Link
934 p.Link = q
935 p = q
936 }
937 prev := p
938 if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
939 q = c.newprog()
940 q.As = AADD
941 q.Pos = p.Pos
942 q.From.Type = obj.TYPE_CONST
943 q.From.Offset = int64(autosize)
944 q.To.Type = obj.TYPE_REG
945 q.To.Reg = REGSP
946 q.Spadj = -autosize
947
948 q.Link = p.Link
949 prev.Link = q
950 prev = q
951 }
952
953 q1 = c.newprog()
954 q1.As = ABR
955 q1.Pos = p.Pos
956 if retTarget == nil {
957 q1.To.Type = obj.TYPE_REG
958 q1.To.Reg = REG_LR
959 } else {
960 q1.To.Type = obj.TYPE_BRANCH
961 q1.To.Sym = retTarget
962 }
963 q1.Mark |= BRANCH
964 q1.Spadj = +autosize
965
966 q1.Link = q.Link
967 prev.Link = q1
968 case AADD:
969 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
970 p.Spadj = int32(-p.From.Offset)
971 }
972 case AMOVDU:
973 if p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP {
974 p.Spadj = int32(-p.To.Offset)
975 }
976 if p.From.Type == obj.TYPE_MEM && p.From.Reg == REGSP {
977 p.Spadj = int32(-p.From.Offset)
978 }
979 case obj.AGETCALLERPC:
980 if cursym.Leaf() {
981
982 p.As = AMOVD
983 p.From.Type = obj.TYPE_REG
984 p.From.Reg = REG_LR
985 } else {
986
987 p.As = AMOVD
988 p.From.Type = obj.TYPE_MEM
989 p.From.Reg = REGSP
990 }
991 }
992
993 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 && p.As != ACMPU {
994 f := c.cursym.Func()
995 if f.FuncFlag&objabi.FuncFlag_SPWRITE == 0 {
996 c.cursym.Func().FuncFlag |= objabi.FuncFlag_SPWRITE
997 if ctxt.Debugvlog || !ctxt.IsAsm {
998 ctxt.Logf("auto-SPWRITE: %s %v\n", c.cursym.Name, p)
999 if !ctxt.IsAsm {
1000 ctxt.Diag("invalid auto-SPWRITE in non-assembly")
1001 ctxt.DiagFlush()
1002 log.Fatalf("bad SPWRITE")
1003 }
1004 }
1005 }
1006 }
1007 }
1008 }
1009
1010
1055 func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
1056 if c.ctxt.Flag_maymorestack != "" {
1057 if c.ctxt.Flag_shared || c.ctxt.Flag_dynlink {
1058
1059
1060 c.ctxt.Diag("maymorestack with -shared or -dynlink is not supported")
1061 }
1062
1063
1064
1065 p = c.cursym.Func().SpillRegisterArgs(p, c.newprog)
1066
1067
1068 frameSize := 8 + c.ctxt.FixedFrameSize()
1069
1070
1071 p = obj.Appendp(p, c.newprog)
1072 p.As = AMOVD
1073 p.From.Type = obj.TYPE_REG
1074 p.From.Reg = REG_LR
1075 p.To.Type = obj.TYPE_REG
1076 p.To.Reg = REGTMP
1077
1078 p = obj.Appendp(p, c.newprog)
1079 p.As = AMOVDU
1080 p.From.Type = obj.TYPE_REG
1081 p.From.Reg = REGTMP
1082 p.To.Type = obj.TYPE_MEM
1083 p.To.Offset = -frameSize
1084 p.To.Reg = REGSP
1085 p.Spadj = int32(frameSize)
1086
1087
1088 p = obj.Appendp(p, c.newprog)
1089 p.As = AMOVD
1090 p.From.Type = obj.TYPE_REG
1091 p.From.Reg = REGCTXT
1092 p.To.Type = obj.TYPE_MEM
1093 p.To.Offset = 8
1094 p.To.Reg = REGSP
1095
1096
1097 p = obj.Appendp(p, c.newprog)
1098 p.As = ABL
1099 p.To.Type = obj.TYPE_BRANCH
1100
1101 p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI())
1102
1103
1104
1105
1106 p = obj.Appendp(p, c.newprog)
1107 p.As = AMOVD
1108 p.From.Type = obj.TYPE_MEM
1109 p.From.Offset = 8
1110 p.From.Reg = REGSP
1111 p.To.Type = obj.TYPE_REG
1112 p.To.Reg = REGCTXT
1113
1114
1115 p = obj.Appendp(p, c.newprog)
1116 p.As = AMOVD
1117 p.From.Type = obj.TYPE_MEM
1118 p.From.Offset = 0
1119 p.From.Reg = REGSP
1120 p.To.Type = obj.TYPE_REG
1121 p.To.Reg = REGTMP
1122
1123
1124 p = obj.Appendp(p, c.newprog)
1125 p.As = AMOVD
1126 p.From.Type = obj.TYPE_REG
1127 p.From.Reg = REGTMP
1128 p.To.Type = obj.TYPE_REG
1129 p.To.Reg = REG_LR
1130
1131
1132 p = obj.Appendp(p, c.newprog)
1133 p.As = AADD
1134 p.From.Type = obj.TYPE_CONST
1135 p.From.Offset = frameSize
1136 p.To.Type = obj.TYPE_REG
1137 p.To.Reg = REGSP
1138 p.Spadj = -int32(frameSize)
1139
1140
1141 p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog)
1142 }
1143
1144
1145 startPred := p
1146
1147
1148 p = obj.Appendp(p, c.newprog)
1149
1150 p.As = AMOVD
1151 p.From.Type = obj.TYPE_MEM
1152 p.From.Reg = REGG
1153 p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize)
1154 if c.cursym.CFunc() {
1155 p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize)
1156 }
1157 p.To.Type = obj.TYPE_REG
1158 p.To.Reg = REG_R22
1159
1160
1161
1162
1163
1164 p = c.ctxt.StartUnsafePoint(p, c.newprog)
1165
1166 var q *obj.Prog
1167 if framesize <= objabi.StackSmall {
1168
1169
1170 p = obj.Appendp(p, c.newprog)
1171
1172 p.As = ACMPU
1173 p.From.Type = obj.TYPE_REG
1174 p.From.Reg = REG_R22
1175 p.To.Type = obj.TYPE_REG
1176 p.To.Reg = REGSP
1177 } else {
1178
1179 offset := int64(framesize) - objabi.StackSmall
1180 if framesize > objabi.StackBig {
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 if offset <= 0xffff {
1191 p = obj.Appendp(p, c.newprog)
1192 p.As = ACMPU
1193 p.From.Type = obj.TYPE_REG
1194 p.From.Reg = REGSP
1195 p.To.Type = obj.TYPE_CONST
1196 p.To.Offset = offset
1197 } else {
1198
1199 p = obj.Appendp(p, c.newprog)
1200 p.As = AMOVD
1201 p.From.Type = obj.TYPE_CONST
1202 p.From.Offset = offset
1203 p.To.Type = obj.TYPE_REG
1204 p.To.Reg = REG_R23
1205
1206 p = obj.Appendp(p, c.newprog)
1207 p.As = ACMPU
1208 p.From.Type = obj.TYPE_REG
1209 p.From.Reg = REGSP
1210 p.To.Type = obj.TYPE_REG
1211 p.To.Reg = REG_R23
1212 }
1213
1214 p = obj.Appendp(p, c.newprog)
1215 q = p
1216 p.As = ABLT
1217 p.To.Type = obj.TYPE_BRANCH
1218 }
1219
1220
1221
1222
1223 p = obj.Appendp(p, c.newprog)
1224
1225 p.As = AADD
1226 p.From.Type = obj.TYPE_CONST
1227 p.From.Offset = -offset
1228 p.Reg = REGSP
1229 p.To.Type = obj.TYPE_REG
1230 p.To.Reg = REG_R23
1231
1232 p = obj.Appendp(p, c.newprog)
1233 p.As = ACMPU
1234 p.From.Type = obj.TYPE_REG
1235 p.From.Reg = REG_R22
1236 p.To.Type = obj.TYPE_REG
1237 p.To.Reg = REG_R23
1238 }
1239
1240
1241 p = obj.Appendp(p, c.newprog)
1242 q1 := p
1243
1244 p.As = ABLT
1245 p.To.Type = obj.TYPE_BRANCH
1246
1247 p = obj.Appendp(p, c.newprog)
1248 p.As = obj.ANOP
1249
1250 if q != nil {
1251 q.To.SetTarget(p)
1252 }
1253
1254
1255
1256
1257 spill := c.cursym.Func().SpillRegisterArgs(p, c.newprog)
1258
1259
1260 p = obj.Appendp(spill, c.newprog)
1261 p.As = AMOVD
1262 p.From.Type = obj.TYPE_REG
1263 p.From.Reg = REG_LR
1264 p.To.Type = obj.TYPE_REG
1265 p.To.Reg = REG_R5
1266
1267 p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
1268
1269 var morestacksym *obj.LSym
1270 if c.cursym.CFunc() {
1271 morestacksym = c.ctxt.Lookup("runtime.morestackc")
1272 } else if !c.cursym.Func().Text.From.Sym.NeedCtxt() {
1273 morestacksym = c.ctxt.Lookup("runtime.morestack_noctxt")
1274 } else {
1275 morestacksym = c.ctxt.Lookup("runtime.morestack")
1276 }
1277
1278 if c.ctxt.Flag_shared {
1279
1280
1281
1282
1283
1284
1285
1286 p = obj.Appendp(p, c.newprog)
1287 p.As = AMOVD
1288 p.From.Type = obj.TYPE_REG
1289 p.From.Reg = REG_R2
1290 p.To.Type = obj.TYPE_MEM
1291 p.To.Reg = REGSP
1292 p.To.Offset = 8
1293 }
1294
1295 if c.ctxt.Flag_dynlink {
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311 p = obj.Appendp(p, c.newprog)
1312 p.As = AMOVD
1313 p.From.Type = obj.TYPE_MEM
1314 p.From.Sym = morestacksym
1315 p.From.Name = obj.NAME_GOTREF
1316 p.To.Type = obj.TYPE_REG
1317 p.To.Reg = REG_R12
1318
1319
1320 p = obj.Appendp(p, c.newprog)
1321 p.As = AMOVD
1322 p.From.Type = obj.TYPE_REG
1323 p.From.Reg = REG_R12
1324 p.To.Type = obj.TYPE_REG
1325 p.To.Reg = REG_LR
1326
1327
1328 p = obj.Appendp(p, c.newprog)
1329 p.As = obj.ACALL
1330 p.To.Type = obj.TYPE_REG
1331 p.To.Reg = REG_LR
1332 } else {
1333
1334 p = obj.Appendp(p, c.newprog)
1335
1336 p.As = ABL
1337 p.To.Type = obj.TYPE_BRANCH
1338 p.To.Sym = morestacksym
1339 }
1340
1341 if c.ctxt.Flag_shared {
1342
1343 p = obj.Appendp(p, c.newprog)
1344 p.As = AMOVD
1345 p.From.Type = obj.TYPE_MEM
1346 p.From.Reg = REGSP
1347 p.From.Offset = 8
1348 p.To.Type = obj.TYPE_REG
1349 p.To.Reg = REG_R2
1350 }
1351
1352 unspill := c.cursym.Func().UnspillRegisterArgs(p, c.newprog)
1353 p = c.ctxt.EndUnsafePoint(unspill, c.newprog, -1)
1354
1355
1356 p = obj.Appendp(p, c.newprog)
1357 p.As = ABR
1358 p.To.Type = obj.TYPE_BRANCH
1359 p.To.SetTarget(startPred.Link)
1360
1361
1362 p = obj.Appendp(p, c.newprog)
1363
1364 p.As = obj.ANOP
1365 q1.To.SetTarget(p)
1366
1367 return p
1368 }
1369
1370 var Linkppc64 = obj.LinkArch{
1371 Arch: sys.ArchPPC64,
1372 Init: buildop,
1373 Preprocess: preprocess,
1374 Assemble: span9,
1375 Progedit: progedit,
1376 DWARFRegisters: PPC64DWARFRegisters,
1377 }
1378
1379 var Linkppc64le = obj.LinkArch{
1380 Arch: sys.ArchPPC64LE,
1381 Init: buildop,
1382 Preprocess: preprocess,
1383 Assemble: span9,
1384 Progedit: progedit,
1385 DWARFRegisters: PPC64DWARFRegisters,
1386 }
1387
View as plain text