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