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.Lookup("runtime.duffzero")
298 } else {
299 sym = c.ctxt.Lookup("runtime.duffcopy")
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
691 prologueEnd = q
692
693 q = obj.Appendp(q, c.newprog)
694 q.As = AMOVDU
695 q.Pos = p.Pos
696 q.From.Type = obj.TYPE_REG
697 q.From.Reg = REGTMP
698 q.To.Type = obj.TYPE_MEM
699 q.To.Offset = int64(-autosize)
700 q.To.Reg = REGSP
701 q.Spadj = autosize
702 } else {
703
704
705
706
707
708
709 q = obj.Appendp(q, c.newprog)
710 q.As = AMOVD
711 q.Pos = p.Pos
712 q.From.Type = obj.TYPE_REG
713 q.From.Reg = REG_LR
714 q.To.Type = obj.TYPE_REG
715 q.To.Reg = REG_R29
716
717 q = c.ctxt.StartUnsafePoint(q, c.newprog)
718
719 q = obj.Appendp(q, c.newprog)
720 q.As = AMOVD
721 q.Pos = p.Pos
722 q.From.Type = obj.TYPE_REG
723 q.From.Reg = REG_R29
724 q.To.Type = obj.TYPE_MEM
725 q.To.Offset = int64(-autosize)
726 q.To.Reg = REGSP
727
728 prologueEnd = q
729
730 q = obj.Appendp(q, c.newprog)
731 q.As = AADD
732 q.Pos = p.Pos
733 q.From.Type = obj.TYPE_CONST
734 q.From.Offset = int64(-autosize)
735 q.To.Type = obj.TYPE_REG
736 q.To.Reg = REGSP
737 q.Spadj = +autosize
738
739 q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
740 }
741 prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
742 } else if c.cursym.Func().Text.Mark&LEAF == 0 {
743
744
745
746 c.cursym.Func().Text.Mark |= LEAF
747 }
748
749 if c.cursym.Func().Text.Mark&LEAF != 0 {
750 c.cursym.Set(obj.AttrLeaf, true)
751 break
752 }
753
754 if c.ctxt.Flag_shared {
755 q = obj.Appendp(q, c.newprog)
756 q.As = AMOVD
757 q.Pos = p.Pos
758 q.From.Type = obj.TYPE_REG
759 q.From.Reg = REG_R2
760 q.To.Type = obj.TYPE_MEM
761 q.To.Reg = REGSP
762 q.To.Offset = 24
763 }
764
765 if c.cursym.Func().Text.From.Sym.Wrapper() {
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783 q = obj.Appendp(q, c.newprog)
784
785 q.As = AMOVD
786 q.From.Type = obj.TYPE_MEM
787 q.From.Reg = REGG
788 q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize)
789 q.To.Type = obj.TYPE_REG
790 q.To.Reg = REG_R3
791
792 q = obj.Appendp(q, c.newprog)
793 q.As = ACMP
794 q.From.Type = obj.TYPE_REG
795 q.From.Reg = REG_R0
796 q.To.Type = obj.TYPE_REG
797 q.To.Reg = REG_R3
798
799 q = obj.Appendp(q, c.newprog)
800 q.As = ABEQ
801 q.To.Type = obj.TYPE_BRANCH
802 p1 = q
803
804 q = obj.Appendp(q, c.newprog)
805 q.As = AMOVD
806 q.From.Type = obj.TYPE_MEM
807 q.From.Reg = REG_R3
808 q.From.Offset = 0
809 q.To.Type = obj.TYPE_REG
810 q.To.Reg = REG_R4
811
812 q = obj.Appendp(q, c.newprog)
813 q.As = AADD
814 q.From.Type = obj.TYPE_CONST
815 q.From.Offset = int64(autosize) + c.ctxt.FixedFrameSize()
816 q.Reg = REGSP
817 q.To.Type = obj.TYPE_REG
818 q.To.Reg = REG_R5
819
820 q = obj.Appendp(q, c.newprog)
821 q.As = ACMP
822 q.From.Type = obj.TYPE_REG
823 q.From.Reg = REG_R4
824 q.To.Type = obj.TYPE_REG
825 q.To.Reg = REG_R5
826
827 q = obj.Appendp(q, c.newprog)
828 q.As = ABNE
829 q.To.Type = obj.TYPE_BRANCH
830 p2 = q
831
832 q = obj.Appendp(q, c.newprog)
833 q.As = AADD
834 q.From.Type = obj.TYPE_CONST
835 q.From.Offset = c.ctxt.FixedFrameSize()
836 q.Reg = REGSP
837 q.To.Type = obj.TYPE_REG
838 q.To.Reg = REG_R6
839
840 q = obj.Appendp(q, c.newprog)
841 q.As = AMOVD
842 q.From.Type = obj.TYPE_REG
843 q.From.Reg = REG_R6
844 q.To.Type = obj.TYPE_MEM
845 q.To.Reg = REG_R3
846 q.To.Offset = 0
847
848 q = obj.Appendp(q, c.newprog)
849
850 q.As = obj.ANOP
851 p1.To.SetTarget(q)
852 p2.To.SetTarget(q)
853 }
854
855 case obj.ARET:
856 if p.From.Type == obj.TYPE_CONST {
857 c.ctxt.Diag("using BECOME (%v) is not supported!", p)
858 break
859 }
860
861 retTarget := p.To.Sym
862
863 if c.cursym.Func().Text.Mark&LEAF != 0 {
864 if autosize == 0 || c.cursym.Name == "runtime.racecallbackthunk" {
865 p.As = ABR
866 p.From = obj.Addr{}
867 if retTarget == nil {
868 p.To.Type = obj.TYPE_REG
869 p.To.Reg = REG_LR
870 } else {
871 p.To.Type = obj.TYPE_BRANCH
872 p.To.Sym = retTarget
873 }
874 p.Mark |= BRANCH
875 break
876 }
877
878 p.As = AADD
879 p.From.Type = obj.TYPE_CONST
880 p.From.Offset = int64(autosize)
881 p.To.Type = obj.TYPE_REG
882 p.To.Reg = REGSP
883 p.Spadj = -autosize
884
885 q = c.newprog()
886 q.As = ABR
887 q.Pos = p.Pos
888 q.To.Type = obj.TYPE_REG
889 q.To.Reg = REG_LR
890 q.Mark |= BRANCH
891 q.Spadj = +autosize
892
893 q.Link = p.Link
894 p.Link = q
895 break
896 }
897
898 p.As = AMOVD
899 p.From.Type = obj.TYPE_MEM
900 p.From.Offset = 0
901 p.From.Reg = REGSP
902 p.To.Type = obj.TYPE_REG
903 p.To.Reg = REGTMP
904
905 q = c.newprog()
906 q.As = AMOVD
907 q.Pos = p.Pos
908 q.From.Type = obj.TYPE_REG
909 q.From.Reg = REGTMP
910 q.To.Type = obj.TYPE_REG
911 q.To.Reg = REG_LR
912
913 q.Link = p.Link
914 p.Link = q
915 p = q
916
917 if false {
918
919 q = c.newprog()
920
921 q.As = AMOVD
922 q.Pos = p.Pos
923 q.From.Type = obj.TYPE_MEM
924 q.From.Offset = 0
925 q.From.Reg = REGTMP
926 q.To.Type = obj.TYPE_REG
927 q.To.Reg = REGTMP
928
929 q.Link = p.Link
930 p.Link = q
931 p = q
932 }
933 prev := p
934 if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
935 q = c.newprog()
936 q.As = AADD
937 q.Pos = p.Pos
938 q.From.Type = obj.TYPE_CONST
939 q.From.Offset = int64(autosize)
940 q.To.Type = obj.TYPE_REG
941 q.To.Reg = REGSP
942 q.Spadj = -autosize
943
944 q.Link = p.Link
945 prev.Link = q
946 prev = q
947 }
948
949 q1 = c.newprog()
950 q1.As = ABR
951 q1.Pos = p.Pos
952 if retTarget == nil {
953 q1.To.Type = obj.TYPE_REG
954 q1.To.Reg = REG_LR
955 } else {
956 q1.To.Type = obj.TYPE_BRANCH
957 q1.To.Sym = retTarget
958 }
959 q1.Mark |= BRANCH
960 q1.Spadj = +autosize
961
962 q1.Link = q.Link
963 prev.Link = q1
964 case AADD:
965 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
966 p.Spadj = int32(-p.From.Offset)
967 }
968 case AMOVDU:
969 if p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP {
970 p.Spadj = int32(-p.To.Offset)
971 }
972 if p.From.Type == obj.TYPE_MEM && p.From.Reg == REGSP {
973 p.Spadj = int32(-p.From.Offset)
974 }
975 case obj.AGETCALLERPC:
976 if cursym.Leaf() {
977
978 p.As = AMOVD
979 p.From.Type = obj.TYPE_REG
980 p.From.Reg = REG_LR
981 } else {
982
983 p.As = AMOVD
984 p.From.Type = obj.TYPE_MEM
985 p.From.Reg = REGSP
986 }
987 }
988
989 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 && p.As != ACMPU {
990 f := c.cursym.Func()
991 if f.FuncFlag&objabi.FuncFlag_SPWRITE == 0 {
992 c.cursym.Func().FuncFlag |= objabi.FuncFlag_SPWRITE
993 if ctxt.Debugvlog || !ctxt.IsAsm {
994 ctxt.Logf("auto-SPWRITE: %s %v\n", c.cursym.Name, p)
995 if !ctxt.IsAsm {
996 ctxt.Diag("invalid auto-SPWRITE in non-assembly")
997 ctxt.DiagFlush()
998 log.Fatalf("bad SPWRITE")
999 }
1000 }
1001 }
1002 }
1003 }
1004 }
1005
1006
1051 func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
1052 p0 := p
1053
1054
1055 p = obj.Appendp(p, c.newprog)
1056
1057 p.As = AMOVD
1058 p.From.Type = obj.TYPE_MEM
1059 p.From.Reg = REGG
1060 p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize)
1061 if c.cursym.CFunc() {
1062 p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize)
1063 }
1064 p.To.Type = obj.TYPE_REG
1065 p.To.Reg = REG_R3
1066
1067
1068
1069
1070
1071 p = c.ctxt.StartUnsafePoint(p, c.newprog)
1072
1073 var q *obj.Prog
1074 if framesize <= objabi.StackSmall {
1075
1076
1077 p = obj.Appendp(p, c.newprog)
1078
1079 p.As = ACMPU
1080 p.From.Type = obj.TYPE_REG
1081 p.From.Reg = REG_R3
1082 p.To.Type = obj.TYPE_REG
1083 p.To.Reg = REGSP
1084 } else {
1085
1086 offset := int64(framesize) - objabi.StackSmall
1087 if framesize > objabi.StackBig {
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097 if offset <= 0xffff {
1098 p = obj.Appendp(p, c.newprog)
1099 p.As = ACMPU
1100 p.From.Type = obj.TYPE_REG
1101 p.From.Reg = REGSP
1102 p.To.Type = obj.TYPE_CONST
1103 p.To.Offset = offset
1104 } else {
1105
1106 p = obj.Appendp(p, c.newprog)
1107 p.As = AMOVD
1108 p.From.Type = obj.TYPE_CONST
1109 p.From.Offset = offset
1110 p.To.Type = obj.TYPE_REG
1111 p.To.Reg = REG_R4
1112
1113 p = obj.Appendp(p, c.newprog)
1114 p.As = ACMPU
1115 p.From.Type = obj.TYPE_REG
1116 p.From.Reg = REGSP
1117 p.To.Type = obj.TYPE_REG
1118 p.To.Reg = REG_R4
1119 }
1120
1121 p = obj.Appendp(p, c.newprog)
1122 q = p
1123 p.As = ABLT
1124 p.To.Type = obj.TYPE_BRANCH
1125 }
1126
1127
1128
1129
1130 p = obj.Appendp(p, c.newprog)
1131
1132 p.As = AADD
1133 p.From.Type = obj.TYPE_CONST
1134 p.From.Offset = -offset
1135 p.Reg = REGSP
1136 p.To.Type = obj.TYPE_REG
1137 p.To.Reg = REG_R4
1138
1139 p = obj.Appendp(p, c.newprog)
1140 p.As = ACMPU
1141 p.From.Type = obj.TYPE_REG
1142 p.From.Reg = REG_R3
1143 p.To.Type = obj.TYPE_REG
1144 p.To.Reg = REG_R4
1145 }
1146
1147
1148 p = obj.Appendp(p, c.newprog)
1149 q1 := p
1150
1151 p.As = ABLT
1152 p.To.Type = obj.TYPE_BRANCH
1153
1154
1155 p = obj.Appendp(p, c.newprog)
1156
1157 p.As = AMOVD
1158 p.From.Type = obj.TYPE_REG
1159 p.From.Reg = REG_LR
1160 p.To.Type = obj.TYPE_REG
1161 p.To.Reg = REG_R5
1162 if q != nil {
1163 q.To.SetTarget(p)
1164 }
1165
1166 p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
1167
1168 var morestacksym *obj.LSym
1169 if c.cursym.CFunc() {
1170 morestacksym = c.ctxt.Lookup("runtime.morestackc")
1171 } else if !c.cursym.Func().Text.From.Sym.NeedCtxt() {
1172 morestacksym = c.ctxt.Lookup("runtime.morestack_noctxt")
1173 } else {
1174 morestacksym = c.ctxt.Lookup("runtime.morestack")
1175 }
1176
1177 if c.ctxt.Flag_shared {
1178
1179
1180
1181
1182
1183
1184
1185
1186 p = obj.Appendp(p, c.newprog)
1187 p.As = AMOVD
1188 p.From.Type = obj.TYPE_REG
1189 p.From.Reg = REG_R2
1190 p.To.Type = obj.TYPE_MEM
1191 p.To.Reg = REGSP
1192 p.To.Offset = 8
1193 }
1194
1195 if c.ctxt.Flag_dynlink {
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211 p = obj.Appendp(p, c.newprog)
1212 p.As = AMOVD
1213 p.From.Type = obj.TYPE_MEM
1214 p.From.Sym = morestacksym
1215 p.From.Name = obj.NAME_GOTREF
1216 p.To.Type = obj.TYPE_REG
1217 p.To.Reg = REG_R12
1218
1219
1220 p = obj.Appendp(p, c.newprog)
1221 p.As = AMOVD
1222 p.From.Type = obj.TYPE_REG
1223 p.From.Reg = REG_R12
1224 p.To.Type = obj.TYPE_REG
1225 p.To.Reg = REG_LR
1226
1227
1228 p = obj.Appendp(p, c.newprog)
1229 p.As = obj.ACALL
1230 p.To.Type = obj.TYPE_REG
1231 p.To.Reg = REG_LR
1232 } else {
1233
1234 p = obj.Appendp(p, c.newprog)
1235
1236 p.As = ABL
1237 p.To.Type = obj.TYPE_BRANCH
1238 p.To.Sym = morestacksym
1239 }
1240
1241 if c.ctxt.Flag_shared {
1242
1243 p = obj.Appendp(p, c.newprog)
1244 p.As = AMOVD
1245 p.From.Type = obj.TYPE_MEM
1246 p.From.Reg = REGSP
1247 p.From.Offset = 8
1248 p.To.Type = obj.TYPE_REG
1249 p.To.Reg = REG_R2
1250 }
1251
1252 p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
1253
1254
1255 p = obj.Appendp(p, c.newprog)
1256 p.As = ABR
1257 p.To.Type = obj.TYPE_BRANCH
1258 p.To.SetTarget(p0.Link)
1259
1260
1261 p = obj.Appendp(p, c.newprog)
1262
1263 p.As = obj.ANOP
1264 q1.To.SetTarget(p)
1265
1266 return p
1267 }
1268
1269 var Linkppc64 = obj.LinkArch{
1270 Arch: sys.ArchPPC64,
1271 Init: buildop,
1272 Preprocess: preprocess,
1273 Assemble: span9,
1274 Progedit: progedit,
1275 DWARFRegisters: PPC64DWARFRegisters,
1276 }
1277
1278 var Linkppc64le = obj.LinkArch{
1279 Arch: sys.ArchPPC64LE,
1280 Init: buildop,
1281 Preprocess: preprocess,
1282 Assemble: span9,
1283 Progedit: progedit,
1284 DWARFRegisters: PPC64DWARFRegisters,
1285 }
1286
View as plain text