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