1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package arm
32
33 import (
34 "cmd/internal/obj"
35 "cmd/internal/objabi"
36 "cmd/internal/sys"
37 "internal/buildcfg"
38 "log"
39 )
40
41 var progedit_tlsfallback *obj.LSym
42
43 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
44 p.From.Class = 0
45 p.To.Class = 0
46
47 c := ctxt5{ctxt: ctxt, newprog: newprog}
48
49
50 switch p.As {
51 case AB, ABL, obj.ADUFFZERO, obj.ADUFFCOPY:
52 if p.To.Type == obj.TYPE_MEM && (p.To.Name == obj.NAME_EXTERN || p.To.Name == obj.NAME_STATIC) && p.To.Sym != nil {
53 p.To.Type = obj.TYPE_BRANCH
54 }
55 }
56
57
58 switch p.As {
59
60 case AMRC:
61 if p.To.Offset&0xffff0fff == 0xee1d0f70 {
62
63
64 if p.To.Offset&0xf000 != 0 {
65 ctxt.Diag("%v: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p.Line())
66 }
67
68 if buildcfg.GOARM < 7 {
69
70 if progedit_tlsfallback == nil {
71 progedit_tlsfallback = ctxt.Lookup("runtime.read_tls_fallback")
72 }
73
74
75 p.As = AMOVW
76
77 p.From.Type = obj.TYPE_REG
78 p.From.Reg = REGLINK
79 p.To.Type = obj.TYPE_REG
80 p.To.Reg = REGTMP
81
82
83 p = obj.Appendp(p, newprog)
84
85 p.As = ABL
86 p.To.Type = obj.TYPE_BRANCH
87 p.To.Sym = progedit_tlsfallback
88 p.To.Offset = 0
89
90
91 p = obj.Appendp(p, newprog)
92
93 p.As = AMOVW
94 p.From.Type = obj.TYPE_REG
95 p.From.Reg = REGTMP
96 p.To.Type = obj.TYPE_REG
97 p.To.Reg = REGLINK
98 break
99 }
100 }
101
102
103 p.As = AWORD
104 }
105
106
107 switch p.As {
108 case AMOVF:
109 if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
110 f32 := float32(p.From.Val.(float64))
111 p.From.Type = obj.TYPE_MEM
112 p.From.Sym = ctxt.Float32Sym(f32)
113 p.From.Name = obj.NAME_EXTERN
114 p.From.Offset = 0
115 }
116
117 case AMOVD:
118 if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
119 p.From.Type = obj.TYPE_MEM
120 p.From.Sym = ctxt.Float64Sym(p.From.Val.(float64))
121 p.From.Name = obj.NAME_EXTERN
122 p.From.Offset = 0
123 }
124 }
125
126 if ctxt.Flag_dynlink {
127 c.rewriteToUseGot(p)
128 }
129 }
130
131
132 func (c *ctxt5) rewriteToUseGot(p *obj.Prog) {
133 if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
134
135
136
137
138
139 var sym *obj.LSym
140 if p.As == obj.ADUFFZERO {
141 sym = c.ctxt.Lookup("runtime.duffzero")
142 } else {
143 sym = c.ctxt.Lookup("runtime.duffcopy")
144 }
145 offset := p.To.Offset
146 p.As = AMOVW
147 p.From.Type = obj.TYPE_MEM
148 p.From.Name = obj.NAME_GOTREF
149 p.From.Sym = sym
150 p.To.Type = obj.TYPE_REG
151 p.To.Reg = REG_R9
152 p.To.Name = obj.NAME_NONE
153 p.To.Offset = 0
154 p.To.Sym = nil
155 p1 := obj.Appendp(p, c.newprog)
156 p1.As = AADD
157 p1.From.Type = obj.TYPE_CONST
158 p1.From.Offset = offset
159 p1.To.Type = obj.TYPE_REG
160 p1.To.Reg = REG_R9
161 p2 := obj.Appendp(p1, c.newprog)
162 p2.As = obj.ACALL
163 p2.To.Type = obj.TYPE_MEM
164 p2.To.Reg = REG_R9
165 return
166 }
167
168
169
170
171 if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
172
173
174 if p.As != AMOVW {
175 c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
176 }
177 if p.To.Type != obj.TYPE_REG {
178 c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
179 }
180 p.From.Type = obj.TYPE_MEM
181 p.From.Name = obj.NAME_GOTREF
182 if p.From.Offset != 0 {
183 q := obj.Appendp(p, c.newprog)
184 q.As = AADD
185 q.From.Type = obj.TYPE_CONST
186 q.From.Offset = p.From.Offset
187 q.To = p.To
188 p.From.Offset = 0
189 }
190 }
191 if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
192 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
193 }
194 var source *obj.Addr
195
196
197
198 if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
199 if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
200 c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
201 }
202 source = &p.From
203 } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
204 source = &p.To
205 } else {
206 return
207 }
208 if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
209 return
210 }
211 if source.Sym.Type == objabi.STLSBSS {
212 return
213 }
214 if source.Type != obj.TYPE_MEM {
215 c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
216 }
217 p1 := obj.Appendp(p, c.newprog)
218 p2 := obj.Appendp(p1, c.newprog)
219
220 p1.As = AMOVW
221 p1.From.Type = obj.TYPE_MEM
222 p1.From.Sym = source.Sym
223 p1.From.Name = obj.NAME_GOTREF
224 p1.To.Type = obj.TYPE_REG
225 p1.To.Reg = REG_R9
226
227 p2.As = p.As
228 p2.From = p.From
229 p2.To = p.To
230 if p.From.Name == obj.NAME_EXTERN {
231 p2.From.Reg = REG_R9
232 p2.From.Name = obj.NAME_NONE
233 p2.From.Sym = nil
234 } else if p.To.Name == obj.NAME_EXTERN {
235 p2.To.Reg = REG_R9
236 p2.To.Name = obj.NAME_NONE
237 p2.To.Sym = nil
238 } else {
239 return
240 }
241 obj.Nopout(p)
242 }
243
244
245 const (
246 FOLL = 1 << 0
247 LABEL = 1 << 1
248 LEAF = 1 << 2
249 )
250
251 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
252 autosize := int32(0)
253
254 if cursym.Func().Text == nil || cursym.Func().Text.Link == nil {
255 return
256 }
257
258 c := ctxt5{ctxt: ctxt, cursym: cursym, newprog: newprog}
259
260 p := c.cursym.Func().Text
261 autoffset := int32(p.To.Offset)
262 if autoffset == -4 {
263
264 p.From.Sym.Set(obj.AttrNoFrame, true)
265 autoffset = 0
266 }
267 if autoffset < 0 || autoffset%4 != 0 {
268 c.ctxt.Diag("frame size %d not 0 or a positive multiple of 4", autoffset)
269 }
270 if p.From.Sym.NoFrame() {
271 if autoffset != 0 {
272 c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", autoffset)
273 }
274 }
275
276 cursym.Func().Locals = autoffset
277 cursym.Func().Args = p.To.Val.(int32)
278
279
282 for p := cursym.Func().Text; p != nil; p = p.Link {
283 switch p.As {
284 case obj.ATEXT:
285 p.Mark |= LEAF
286
287 case ADIV, ADIVU, AMOD, AMODU:
288 cursym.Func().Text.Mark &^= LEAF
289
290 case ABL,
291 ABX,
292 obj.ADUFFZERO,
293 obj.ADUFFCOPY:
294 cursym.Func().Text.Mark &^= LEAF
295 }
296 }
297
298 var q2 *obj.Prog
299 for p := cursym.Func().Text; p != nil; p = p.Link {
300 o := p.As
301 switch o {
302 case obj.ATEXT:
303 autosize = autoffset
304
305 if p.Mark&LEAF != 0 && autosize == 0 {
306
307 p.From.Sym.Set(obj.AttrNoFrame, true)
308 }
309
310 if !p.From.Sym.NoFrame() {
311
312
313 autosize += 4
314 }
315
316 if autosize == 0 && cursym.Func().Text.Mark&LEAF == 0 {
317
318
319 if ctxt.Debugvlog {
320 ctxt.Logf("save suppressed in: %s\n", cursym.Name)
321 }
322
323 cursym.Func().Text.Mark |= LEAF
324 }
325
326
327 p.To.Offset = int64(autosize) - 4
328
329 if cursym.Func().Text.Mark&LEAF != 0 {
330 cursym.Set(obj.AttrLeaf, true)
331 if p.From.Sym.NoFrame() {
332 break
333 }
334 }
335
336 if !p.From.Sym.NoSplit() {
337 p = c.stacksplit(p, autosize)
338 }
339
340
341 p = obj.Appendp(p, c.newprog)
342
343 p.As = AMOVW
344 p.Scond |= C_WBIT
345 p.From.Type = obj.TYPE_REG
346 p.From.Reg = REGLINK
347 p.To.Type = obj.TYPE_MEM
348 p.To.Offset = int64(-autosize)
349 p.To.Reg = REGSP
350 p.Spadj = autosize
351
352 if cursym.Func().Text.From.Sym.Wrapper() {
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 p = obj.Appendp(p, newprog)
374 p.As = AMOVW
375 p.From.Type = obj.TYPE_MEM
376 p.From.Reg = REGG
377 p.From.Offset = 4 * int64(ctxt.Arch.PtrSize)
378 p.To.Type = obj.TYPE_REG
379 p.To.Reg = REG_R1
380
381 p = obj.Appendp(p, newprog)
382 p.As = ACMP
383 p.From.Type = obj.TYPE_CONST
384 p.From.Offset = 0
385 p.Reg = REG_R1
386
387
388 bne := obj.Appendp(p, newprog)
389 bne.As = ABNE
390 bne.To.Type = obj.TYPE_BRANCH
391
392
393 end := obj.Appendp(bne, newprog)
394 end.As = obj.ANOP
395
396
397 var last *obj.Prog
398 for last = end; last.Link != nil; last = last.Link {
399 }
400
401
402 mov := obj.Appendp(last, newprog)
403 mov.As = AMOVW
404 mov.From.Type = obj.TYPE_MEM
405 mov.From.Reg = REG_R1
406 mov.From.Offset = 0
407 mov.To.Type = obj.TYPE_REG
408 mov.To.Reg = REG_R2
409
410
411 bne.To.SetTarget(mov)
412
413
414 p = obj.Appendp(mov, newprog)
415 p.As = AADD
416 p.From.Type = obj.TYPE_CONST
417 p.From.Offset = int64(autosize) + 4
418 p.Reg = REG_R13
419 p.To.Type = obj.TYPE_REG
420 p.To.Reg = REG_R3
421
422
423 p = obj.Appendp(p, newprog)
424 p.As = ACMP
425 p.From.Type = obj.TYPE_REG
426 p.From.Reg = REG_R2
427 p.Reg = REG_R3
428
429
430 p = obj.Appendp(p, newprog)
431 p.As = ABNE
432 p.To.Type = obj.TYPE_BRANCH
433 p.To.SetTarget(end)
434
435
436 p = obj.Appendp(p, newprog)
437 p.As = AADD
438 p.From.Type = obj.TYPE_CONST
439 p.From.Offset = 4
440 p.Reg = REG_R13
441 p.To.Type = obj.TYPE_REG
442 p.To.Reg = REG_R4
443
444
445 p = obj.Appendp(p, newprog)
446 p.As = AMOVW
447 p.From.Type = obj.TYPE_REG
448 p.From.Reg = REG_R4
449 p.To.Type = obj.TYPE_MEM
450 p.To.Reg = REG_R1
451 p.To.Offset = 0
452
453
454 p = obj.Appendp(p, newprog)
455 p.As = AB
456 p.To.Type = obj.TYPE_BRANCH
457 p.To.SetTarget(end)
458
459
460 p = end
461 }
462
463 case obj.ARET:
464 nocache(p)
465 if cursym.Func().Text.Mark&LEAF != 0 {
466 if autosize == 0 {
467 p.As = AB
468 p.From = obj.Addr{}
469 if p.To.Sym != nil {
470 p.To.Type = obj.TYPE_BRANCH
471 } else {
472 p.To.Type = obj.TYPE_MEM
473 p.To.Offset = 0
474 p.To.Reg = REGLINK
475 }
476
477 break
478 }
479 }
480
481 p.As = AMOVW
482 p.Scond |= C_PBIT
483 p.From.Type = obj.TYPE_MEM
484 p.From.Offset = int64(autosize)
485 p.From.Reg = REGSP
486 p.To.Type = obj.TYPE_REG
487 p.To.Reg = REGPC
488
489
490
491
492
493 if p.To.Sym != nil {
494 p.To.Reg = REGLINK
495 q2 = obj.Appendp(p, newprog)
496 q2.As = AB
497 q2.To.Type = obj.TYPE_BRANCH
498 q2.To.Sym = p.To.Sym
499 p.To.Sym = nil
500 p.To.Name = obj.NAME_NONE
501 p = q2
502 }
503
504 case AADD:
505 if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
506 p.Spadj = int32(-p.From.Offset)
507 }
508
509 case ASUB:
510 if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
511 p.Spadj = int32(p.From.Offset)
512 }
513
514 case ADIV, ADIVU, AMOD, AMODU:
515 if cursym.Func().Text.From.Sym.NoSplit() {
516 ctxt.Diag("cannot divide in NOSPLIT function")
517 }
518 const debugdivmod = false
519 if debugdivmod {
520 break
521 }
522 if p.From.Type != obj.TYPE_REG {
523 break
524 }
525 if p.To.Type != obj.TYPE_REG {
526 break
527 }
528
529
530 q1 := *p
531 if q1.Reg == REGTMP || q1.Reg == 0 && q1.To.Reg == REGTMP {
532 ctxt.Diag("div already using REGTMP: %v", p)
533 }
534
535
536 p.As = AMOVW
537 p.Pos = q1.Pos
538 p.From.Type = obj.TYPE_MEM
539 p.From.Reg = REGG
540 p.From.Offset = 6 * 4
541 p.Reg = 0
542 p.To.Type = obj.TYPE_REG
543 p.To.Reg = REGTMP
544
545
546 p = obj.Appendp(p, newprog)
547 p.As = AMOVW
548 p.Pos = q1.Pos
549 p.From.Type = obj.TYPE_REG
550 p.From.Reg = q1.From.Reg
551 p.To.Type = obj.TYPE_MEM
552 p.To.Reg = REGTMP
553 p.To.Offset = 8 * 4
554
555
556 p = obj.Appendp(p, newprog)
557 p.As = AMOVW
558 p.Pos = q1.Pos
559 p.From.Type = obj.TYPE_REG
560 p.From.Reg = q1.Reg
561 if q1.Reg == 0 {
562 p.From.Reg = q1.To.Reg
563 }
564 p.To.Type = obj.TYPE_REG
565 p.To.Reg = REG_R8
566 p.To.Offset = 0
567
568
569 p = obj.Appendp(p, newprog)
570 p.As = ABL
571 p.Pos = q1.Pos
572 p.To.Type = obj.TYPE_BRANCH
573 switch o {
574 case ADIV:
575 p.To.Sym = symdiv
576 case ADIVU:
577 p.To.Sym = symdivu
578 case AMOD:
579 p.To.Sym = symmod
580 case AMODU:
581 p.To.Sym = symmodu
582 }
583
584
585 p = obj.Appendp(p, newprog)
586 p.As = AMOVW
587 p.Pos = q1.Pos
588 p.From.Type = obj.TYPE_REG
589 p.From.Reg = REGTMP
590 p.From.Offset = 0
591 p.To.Type = obj.TYPE_REG
592 p.To.Reg = q1.To.Reg
593
594 case AMOVW:
595 if (p.Scond&C_WBIT != 0) && p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP {
596 p.Spadj = int32(-p.To.Offset)
597 }
598 if (p.Scond&C_PBIT != 0) && p.From.Type == obj.TYPE_MEM && p.From.Reg == REGSP && p.To.Reg != REGPC {
599 p.Spadj = int32(-p.From.Offset)
600 }
601 if p.From.Type == obj.TYPE_ADDR && p.From.Reg == REGSP && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
602 p.Spadj = int32(-p.From.Offset)
603 }
604
605 case obj.AGETCALLERPC:
606 if cursym.Leaf() {
607
608 p.As = AMOVW
609 p.From.Type = obj.TYPE_REG
610 p.From.Reg = REGLINK
611 } else {
612
613 p.As = AMOVW
614 p.From.Type = obj.TYPE_MEM
615 p.From.Reg = REGSP
616 }
617 }
618
619 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
620 f := c.cursym.Func()
621 if f.FuncFlag&objabi.FuncFlag_SPWRITE == 0 {
622 c.cursym.Func().FuncFlag |= objabi.FuncFlag_SPWRITE
623 if ctxt.Debugvlog || !ctxt.IsAsm {
624 ctxt.Logf("auto-SPWRITE: %s %v\n", c.cursym.Name, p)
625 if !ctxt.IsAsm {
626 ctxt.Diag("invalid auto-SPWRITE in non-assembly")
627 ctxt.DiagFlush()
628 log.Fatalf("bad SPWRITE")
629 }
630 }
631 }
632 }
633 }
634 }
635
636 func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
637 if c.ctxt.Flag_maymorestack != "" {
638
639 const frameSize = 8
640
641 p = obj.Appendp(p, c.newprog)
642 p.As = AMOVW
643 p.Scond |= C_WBIT
644 p.From.Type = obj.TYPE_REG
645 p.From.Reg = REGLINK
646 p.To.Type = obj.TYPE_MEM
647 p.To.Offset = -frameSize
648 p.To.Reg = REGSP
649 p.Spadj = frameSize
650
651
652 p = obj.Appendp(p, c.newprog)
653 p.As = AMOVW
654 p.From.Type = obj.TYPE_REG
655 p.From.Reg = REGCTXT
656 p.To.Type = obj.TYPE_MEM
657 p.To.Offset = 4
658 p.To.Reg = REGSP
659
660
661 p = obj.Appendp(p, c.newprog)
662 p.As = obj.ACALL
663 p.To.Type = obj.TYPE_BRANCH
664
665 p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI())
666
667
668
669
670 p = obj.Appendp(p, c.newprog)
671 p.As = AMOVW
672 p.From.Type = obj.TYPE_MEM
673 p.From.Offset = 4
674 p.From.Reg = REGSP
675 p.To.Type = obj.TYPE_REG
676 p.To.Reg = REGCTXT
677
678
679 p.As = AMOVW
680 p.Scond |= C_PBIT
681 p.From.Type = obj.TYPE_MEM
682 p.From.Offset = frameSize
683 p.From.Reg = REGSP
684 p.To.Type = obj.TYPE_REG
685 p.To.Reg = REGLINK
686 p.Spadj = -frameSize
687 }
688
689
690 startPred := p
691
692
693 p = obj.Appendp(p, c.newprog)
694
695 p.As = AMOVW
696 p.From.Type = obj.TYPE_MEM
697 p.From.Reg = REGG
698 p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize)
699 if c.cursym.CFunc() {
700 p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize)
701 }
702 p.To.Type = obj.TYPE_REG
703 p.To.Reg = REG_R1
704
705
706
707
708
709 p = c.ctxt.StartUnsafePoint(p, c.newprog)
710
711 if framesize <= objabi.StackSmall {
712
713
714 p = obj.Appendp(p, c.newprog)
715
716 p.As = ACMP
717 p.From.Type = obj.TYPE_REG
718 p.From.Reg = REG_R1
719 p.Reg = REGSP
720 } else if framesize <= objabi.StackBig {
721
722
723
724 p = obj.Appendp(p, c.newprog)
725
726 p.As = AMOVW
727 p.From.Type = obj.TYPE_ADDR
728 p.From.Reg = REGSP
729 p.From.Offset = -(int64(framesize) - objabi.StackSmall)
730 p.To.Type = obj.TYPE_REG
731 p.To.Reg = REG_R2
732
733 p = obj.Appendp(p, c.newprog)
734 p.As = ACMP
735 p.From.Type = obj.TYPE_REG
736 p.From.Reg = REG_R1
737 p.Reg = REG_R2
738 } else {
739
740
741
742
743
744
745
746
747
748
749
750
751
752 p = obj.Appendp(p, c.newprog)
753 p.As = ASUB
754 p.Scond = C_SBIT
755 p.From.Type = obj.TYPE_CONST
756 p.From.Offset = int64(framesize) - objabi.StackSmall
757 p.Reg = REGSP
758 p.To.Type = obj.TYPE_REG
759 p.To.Reg = REG_R2
760
761 p = obj.Appendp(p, c.newprog)
762 p.As = ACMP
763 p.Scond = C_SCOND_HS
764 p.From.Type = obj.TYPE_REG
765 p.From.Reg = REG_R1
766 p.Reg = REG_R2
767 }
768
769
770 bls := obj.Appendp(p, c.newprog)
771 bls.As = ABLS
772 bls.To.Type = obj.TYPE_BRANCH
773
774 end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1)
775
776 var last *obj.Prog
777 for last = c.cursym.Func().Text; last.Link != nil; last = last.Link {
778 }
779
780
781
782
783 spfix := obj.Appendp(last, c.newprog)
784 spfix.As = obj.ANOP
785 spfix.Spadj = -framesize
786
787 pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
788 pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
789
790
791 movw := obj.Appendp(pcdata, c.newprog)
792 movw.As = AMOVW
793 movw.From.Type = obj.TYPE_REG
794 movw.From.Reg = REGLINK
795 movw.To.Type = obj.TYPE_REG
796 movw.To.Reg = REG_R3
797
798 bls.To.SetTarget(movw)
799
800
801 call := obj.Appendp(movw, c.newprog)
802 call.As = obj.ACALL
803 call.To.Type = obj.TYPE_BRANCH
804 morestack := "runtime.morestack"
805 switch {
806 case c.cursym.CFunc():
807 morestack = "runtime.morestackc"
808 case !c.cursym.Func().Text.From.Sym.NeedCtxt():
809 morestack = "runtime.morestack_noctxt"
810 }
811 call.To.Sym = c.ctxt.Lookup(morestack)
812
813 pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
814
815
816 b := obj.Appendp(pcdata, c.newprog)
817 b.As = obj.AJMP
818 b.To.Type = obj.TYPE_BRANCH
819 b.To.SetTarget(startPred.Link)
820 b.Spadj = +framesize
821
822 return end
823 }
824
825 var unaryDst = map[obj.As]bool{
826 ASWI: true,
827 AWORD: true,
828 }
829
830 var Linkarm = obj.LinkArch{
831 Arch: sys.ArchARM,
832 Init: buildop,
833 Preprocess: preprocess,
834 Assemble: span5,
835 Progedit: progedit,
836 UnaryDst: unaryDst,
837 DWARFRegisters: ARMDWARFRegisters,
838 }
839
View as plain text