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