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 mips
31
32 import (
33 "cmd/internal/obj"
34 "cmd/internal/sys"
35 "encoding/binary"
36 "fmt"
37 "internal/abi"
38 "log"
39 "math"
40 )
41
42 func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
43 c := ctxt0{ctxt: ctxt}
44
45 p.From.Class = 0
46 p.To.Class = 0
47
48
49 switch p.As {
50 case AJMP,
51 AJAL,
52 ARET,
53 obj.ADUFFZERO,
54 obj.ADUFFCOPY:
55 if p.To.Sym != nil {
56 p.To.Type = obj.TYPE_BRANCH
57 }
58 }
59
60
61 switch p.As {
62 case AMOVF:
63 if p.From.Type == obj.TYPE_FCONST {
64 f32 := float32(p.From.Val.(float64))
65 if math.Float32bits(f32) == 0 {
66 p.As = AMOVW
67 p.From.Type = obj.TYPE_REG
68 p.From.Reg = REGZERO
69 break
70 }
71 p.From.Type = obj.TYPE_MEM
72 p.From.Sym = ctxt.Float32Sym(f32)
73 p.From.Name = obj.NAME_EXTERN
74 p.From.Offset = 0
75 }
76
77 case AMOVD:
78 if p.From.Type == obj.TYPE_FCONST {
79 f64 := p.From.Val.(float64)
80 if math.Float64bits(f64) == 0 && c.ctxt.Arch.Family == sys.MIPS64 {
81 p.As = AMOVV
82 p.From.Type = obj.TYPE_REG
83 p.From.Reg = REGZERO
84 break
85 }
86 p.From.Type = obj.TYPE_MEM
87 p.From.Sym = ctxt.Float64Sym(f64)
88 p.From.Name = obj.NAME_EXTERN
89 p.From.Offset = 0
90 }
91
92
93 case AMOVV:
94 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 {
95 p.From.Type = obj.TYPE_MEM
96 p.From.Sym = ctxt.Int64Sym(p.From.Offset)
97 p.From.Name = obj.NAME_EXTERN
98 p.From.Offset = 0
99 }
100 }
101
102
103 switch p.As {
104 case ASUB:
105 if p.From.Type == obj.TYPE_CONST {
106 p.From.Offset = -p.From.Offset
107 p.As = AADD
108 }
109
110 case ASUBU:
111 if p.From.Type == obj.TYPE_CONST {
112 p.From.Offset = -p.From.Offset
113 p.As = AADDU
114 }
115
116 case ASUBV:
117 if p.From.Type == obj.TYPE_CONST {
118 p.From.Offset = -p.From.Offset
119 p.As = AADDV
120 }
121
122 case ASUBVU:
123 if p.From.Type == obj.TYPE_CONST {
124 p.From.Offset = -p.From.Offset
125 p.As = AADDVU
126 }
127 }
128 }
129
130 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
131
132 c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym}
133
134
135 nosched := true
136
137 if c.cursym.Func().Text == nil || c.cursym.Func().Text.Link == nil {
138 return
139 }
140
141 p := c.cursym.Func().Text
142 textstksiz := p.To.Offset
143 if textstksiz == -ctxt.Arch.FixedFrameSize {
144
145 p.From.Sym.Set(obj.AttrNoFrame, true)
146 textstksiz = 0
147 }
148 if textstksiz < 0 {
149 c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz)
150 }
151 if p.From.Sym.NoFrame() {
152 if textstksiz != 0 {
153 c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
154 }
155 }
156
157 c.cursym.Func().Args = p.To.Val.(int32)
158 c.cursym.Func().Locals = int32(textstksiz)
159
160
165
166 for p := c.cursym.Func().Text; p != nil; p = p.Link {
167 switch p.As {
168
169 case obj.ATEXT:
170 p.Mark |= LABEL | LEAF | SYNC
171 if p.Link != nil {
172 p.Link.Mark |= LABEL
173 }
174
175
176 case AMOVW,
177 AMOVV:
178 if p.To.Type == obj.TYPE_REG && p.To.Reg >= REG_SPECIAL {
179 p.Mark |= LABEL | SYNC
180 break
181 }
182 if p.From.Type == obj.TYPE_REG && p.From.Reg >= REG_SPECIAL {
183 p.Mark |= LABEL | SYNC
184 }
185
186
187 case ASYSCALL,
188 AWORD,
189 ATLBWR,
190 ATLBWI,
191 ATLBP,
192 ATLBR:
193 p.Mark |= LABEL | SYNC
194
195 case ANOR:
196 if p.To.Type == obj.TYPE_REG {
197 if p.To.Reg == REGZERO {
198 p.Mark |= LABEL | SYNC
199 }
200 }
201
202 case ABGEZAL,
203 ABLTZAL,
204 AJAL,
205 obj.ADUFFZERO,
206 obj.ADUFFCOPY:
207 c.cursym.Func().Text.Mark &^= LEAF
208 fallthrough
209
210 case AJMP,
211 ABEQ,
212 ABGEZ,
213 ABGTZ,
214 ABLEZ,
215 ABLTZ,
216 ABNE,
217 ABFPT, ABFPF:
218 if p.As == ABFPT || p.As == ABFPF {
219
220
221
222
223
224
225
226
227 p.Mark |= SYNC
228 } else {
229 p.Mark |= BRANCH
230 }
231 q1 := p.To.Target()
232 if q1 != nil {
233 for q1.As == obj.ANOP {
234 q1 = q1.Link
235 p.To.SetTarget(q1)
236 }
237
238 if q1.Mark&LEAF == 0 {
239 q1.Mark |= LABEL
240 }
241 }
242
243
244
245 q1 = p.Link
246 if q1 != nil {
247 q1.Mark |= LABEL
248 }
249
250 case ARET:
251 if p.Link != nil {
252 p.Link.Mark |= LABEL
253 }
254 }
255 }
256
257 var mov, add obj.As
258 if c.ctxt.Arch.Family == sys.MIPS64 {
259 add = AADDV
260 mov = AMOVV
261 } else {
262 add = AADDU
263 mov = AMOVW
264 }
265
266 var q *obj.Prog
267 var q1 *obj.Prog
268 autosize := int32(0)
269 var p1 *obj.Prog
270 for p := c.cursym.Func().Text; p != nil; p = p.Link {
271 o := p.As
272 switch o {
273 case obj.ATEXT:
274 autosize = int32(textstksiz)
275
276 if p.Mark&LEAF != 0 && autosize == 0 {
277
278 p.From.Sym.Set(obj.AttrNoFrame, true)
279 }
280
281 if !p.From.Sym.NoFrame() {
282
283
284 autosize += int32(c.ctxt.Arch.FixedFrameSize)
285 }
286
287 if autosize&4 != 0 && c.ctxt.Arch.Family == sys.MIPS64 {
288 autosize += 4
289 }
290
291 if autosize == 0 && c.cursym.Func().Text.Mark&LEAF == 0 {
292 if c.cursym.Func().Text.From.Sym.NoSplit() {
293 if ctxt.Debugvlog {
294 ctxt.Logf("save suppressed in: %s\n", c.cursym.Name)
295 }
296
297 c.cursym.Func().Text.Mark |= LEAF
298 }
299 }
300
301 p.To.Offset = int64(autosize) - ctxt.Arch.FixedFrameSize
302
303 if c.cursym.Func().Text.Mark&LEAF != 0 {
304 c.cursym.Set(obj.AttrLeaf, true)
305 if p.From.Sym.NoFrame() {
306 break
307 }
308 }
309
310 if !p.From.Sym.NoSplit() {
311 p = c.stacksplit(p, autosize)
312 }
313
314 q = p
315
316 if autosize != 0 {
317
318
319
320
321
322
323
324 q = c.ctxt.StartUnsafePoint(q, c.newprog)
325
326 q = obj.Appendp(q, newprog)
327 q.As = mov
328 q.Pos = p.Pos
329 q.From.Type = obj.TYPE_REG
330 q.From.Reg = REGLINK
331 q.To.Type = obj.TYPE_MEM
332 q.To.Offset = int64(-autosize)
333 q.To.Reg = REGSP
334
335 q = obj.Appendp(q, newprog)
336 q.As = add
337 q.Pos = p.Pos
338 q.From.Type = obj.TYPE_CONST
339 q.From.Offset = int64(-autosize)
340 q.To.Type = obj.TYPE_REG
341 q.To.Reg = REGSP
342 q.Spadj = +autosize
343
344 q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
345
346
347
348
349
350
351 q = obj.Appendp(q, newprog)
352 q.As = mov
353 q.Pos = p.Pos
354 q.From.Type = obj.TYPE_REG
355 q.From.Reg = REGLINK
356 q.To.Type = obj.TYPE_MEM
357 q.To.Offset = 0
358 q.To.Reg = REGSP
359 }
360
361 case ARET:
362 if p.From.Type == obj.TYPE_CONST {
363 ctxt.Diag("using BECOME (%v) is not supported!", p)
364 break
365 }
366
367 retSym := p.To.Sym
368 p.To.Name = obj.NAME_NONE
369 p.To.Sym = nil
370
371 if c.cursym.Func().Text.Mark&LEAF != 0 {
372 if autosize == 0 {
373 p.As = AJMP
374 p.From = obj.Addr{}
375 if retSym != nil {
376 p.To.Type = obj.TYPE_BRANCH
377 p.To.Name = obj.NAME_EXTERN
378 p.To.Sym = retSym
379 } else {
380 p.To.Type = obj.TYPE_MEM
381 p.To.Reg = REGLINK
382 p.To.Offset = 0
383 }
384 p.Mark |= BRANCH
385 break
386 }
387
388 p.As = add
389 p.From.Type = obj.TYPE_CONST
390 p.From.Offset = int64(autosize)
391 p.To.Type = obj.TYPE_REG
392 p.To.Reg = REGSP
393 p.Spadj = -autosize
394
395 q = c.newprog()
396 q.As = AJMP
397 q.Pos = p.Pos
398 if retSym != nil {
399 q.To.Type = obj.TYPE_BRANCH
400 q.To.Name = obj.NAME_EXTERN
401 q.To.Sym = retSym
402 } else {
403 q.To.Type = obj.TYPE_MEM
404 q.To.Reg = REGLINK
405 q.To.Offset = 0
406 }
407 q.Mark |= BRANCH
408 q.Spadj = +autosize
409
410 q.Link = p.Link
411 p.Link = q
412 break
413 }
414
415 p.As = mov
416 p.From.Type = obj.TYPE_MEM
417 p.From.Offset = 0
418 p.From.Reg = REGSP
419 p.To.Type = obj.TYPE_REG
420 p.To.Reg = REGLINK
421
422 if autosize != 0 {
423 q = c.newprog()
424 q.As = add
425 q.Pos = p.Pos
426 q.From.Type = obj.TYPE_CONST
427 q.From.Offset = int64(autosize)
428 q.To.Type = obj.TYPE_REG
429 q.To.Reg = REGSP
430 q.Spadj = -autosize
431
432 q.Link = p.Link
433 p.Link = q
434 }
435
436 q1 = c.newprog()
437 q1.As = AJMP
438 q1.Pos = p.Pos
439 if retSym != nil {
440 q1.To.Type = obj.TYPE_BRANCH
441 q1.To.Name = obj.NAME_EXTERN
442 q1.To.Sym = retSym
443 } else {
444 q1.To.Type = obj.TYPE_MEM
445 q1.To.Offset = 0
446 q1.To.Reg = REGLINK
447 }
448 q1.Mark |= BRANCH
449 q1.Spadj = +autosize
450
451 q1.Link = q.Link
452 q.Link = q1
453
454 case AADD,
455 AADDU,
456 AADDV,
457 AADDVU:
458 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
459 p.Spadj = int32(-p.From.Offset)
460 }
461
462 case obj.AGETCALLERPC:
463 if cursym.Leaf() {
464
465 p.As = mov
466 p.From.Type = obj.TYPE_REG
467 p.From.Reg = REGLINK
468 } else {
469
470 p.As = mov
471 p.From.Type = obj.TYPE_MEM
472 p.From.Reg = REGSP
473 }
474 }
475
476 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
477 f := c.cursym.Func()
478 if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
479 c.cursym.Func().FuncFlag |= abi.FuncFlagSPWrite
480 if ctxt.Debugvlog || !ctxt.IsAsm {
481 ctxt.Logf("auto-SPWRITE: %s %v\n", c.cursym.Name, p)
482 if !ctxt.IsAsm {
483 ctxt.Diag("invalid auto-SPWRITE in non-assembly")
484 ctxt.DiagFlush()
485 log.Fatalf("bad SPWRITE")
486 }
487 }
488 }
489 }
490 }
491
492 if c.ctxt.Arch.Family == sys.MIPS {
493
494 for p = c.cursym.Func().Text; p != nil; p = p1 {
495 p1 = p.Link
496
497 if p.As != AMOVD {
498 continue
499 }
500 if p.From.Type != obj.TYPE_MEM && p.To.Type != obj.TYPE_MEM {
501 continue
502 }
503
504 p.As = AMOVF
505 q = c.newprog()
506 *q = *p
507 q.Link = p.Link
508 p.Link = q
509 p1 = q.Link
510
511 var addrOff int64
512 if c.ctxt.Arch.ByteOrder == binary.BigEndian {
513 addrOff = 4
514 }
515 if p.From.Type == obj.TYPE_MEM {
516 reg := REG_F0 + (p.To.Reg-REG_F0)&^1
517 p.To.Reg = reg
518 q.To.Reg = reg + 1
519 p.From.Offset += addrOff
520 q.From.Offset += 4 - addrOff
521 } else if p.To.Type == obj.TYPE_MEM {
522 reg := REG_F0 + (p.From.Reg-REG_F0)&^1
523 p.From.Reg = reg
524 q.From.Reg = reg + 1
525 p.To.Offset += addrOff
526 q.To.Offset += 4 - addrOff
527 }
528 }
529 }
530
531 if nosched {
532
533
534 for p = c.cursym.Func().Text; p != nil; p = p.Link {
535 if p.Mark&BRANCH != 0 {
536 c.addnop(p)
537 }
538 }
539 return
540 }
541
542
543 q = nil
544 q1 = c.cursym.Func().Text
545 o := 0
546 for p = c.cursym.Func().Text; p != nil; p = p1 {
547 p1 = p.Link
548 o++
549 if p.Mark&NOSCHED != 0 {
550 if q1 != p {
551 c.sched(q1, q)
552 }
553 for ; p != nil; p = p.Link {
554 if p.Mark&NOSCHED == 0 {
555 break
556 }
557 q = p
558 }
559 p1 = p
560 q1 = p
561 o = 0
562 continue
563 }
564 if p.Mark&(LABEL|SYNC) != 0 {
565 if q1 != p {
566 c.sched(q1, q)
567 }
568 q1 = p
569 o = 1
570 }
571 if p.Mark&(BRANCH|SYNC) != 0 {
572 c.sched(q1, p)
573 q1 = p1
574 o = 0
575 }
576 if o >= NSCHED {
577 c.sched(q1, p)
578 q1 = p1
579 o = 0
580 }
581 q = p
582 }
583 }
584
585 func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
586 var mov, add obj.As
587
588 if c.ctxt.Arch.Family == sys.MIPS64 {
589 add = AADDV
590 mov = AMOVV
591 } else {
592 add = AADDU
593 mov = AMOVW
594 }
595
596 if c.ctxt.Flag_maymorestack != "" {
597
598 frameSize := 2 * c.ctxt.Arch.PtrSize
599
600 p = c.ctxt.StartUnsafePoint(p, c.newprog)
601
602
603 p = obj.Appendp(p, c.newprog)
604 p.As = mov
605 p.From.Type = obj.TYPE_REG
606 p.From.Reg = REGLINK
607 p.To.Type = obj.TYPE_MEM
608 p.To.Offset = int64(-frameSize)
609 p.To.Reg = REGSP
610
611
612 p = obj.Appendp(p, c.newprog)
613 p.As = mov
614 p.From.Type = obj.TYPE_REG
615 p.From.Reg = REGCTXT
616 p.To.Type = obj.TYPE_MEM
617 p.To.Offset = -int64(c.ctxt.Arch.PtrSize)
618 p.To.Reg = REGSP
619
620
621 p = obj.Appendp(p, c.newprog)
622 p.As = add
623 p.From.Type = obj.TYPE_CONST
624 p.From.Offset = int64(-frameSize)
625 p.To.Type = obj.TYPE_REG
626 p.To.Reg = REGSP
627 p.Spadj = int32(frameSize)
628
629
630 p = obj.Appendp(p, c.newprog)
631 p.As = AJAL
632 p.To.Type = obj.TYPE_BRANCH
633
634 p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI())
635 p.Mark |= BRANCH
636
637
638
639
640 p = obj.Appendp(p, c.newprog)
641 p.As = mov
642 p.From.Type = obj.TYPE_MEM
643 p.From.Offset = 0
644 p.From.Reg = REGSP
645 p.To.Type = obj.TYPE_REG
646 p.To.Reg = REGLINK
647
648
649 p = obj.Appendp(p, c.newprog)
650 p.As = mov
651 p.From.Type = obj.TYPE_MEM
652 p.From.Offset = int64(c.ctxt.Arch.PtrSize)
653 p.From.Reg = REGSP
654 p.To.Type = obj.TYPE_REG
655 p.To.Reg = REGCTXT
656
657
658 p = obj.Appendp(p, c.newprog)
659 p.As = add
660 p.From.Type = obj.TYPE_CONST
661 p.From.Offset = int64(frameSize)
662 p.To.Type = obj.TYPE_REG
663 p.To.Reg = REGSP
664 p.Spadj = int32(-frameSize)
665
666 p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
667 }
668
669
670 startPred := p
671
672
673 p = obj.Appendp(p, c.newprog)
674
675 p.As = mov
676 p.From.Type = obj.TYPE_MEM
677 p.From.Reg = REGG
678 p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize)
679 if c.cursym.CFunc() {
680 p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize)
681 }
682 p.To.Type = obj.TYPE_REG
683 p.To.Reg = REG_R1
684
685
686
687
688
689 p = c.ctxt.StartUnsafePoint(p, c.newprog)
690
691 var q *obj.Prog
692 if framesize <= abi.StackSmall {
693
694
695 p = obj.Appendp(p, c.newprog)
696
697 p.As = ASGTU
698 p.From.Type = obj.TYPE_REG
699 p.From.Reg = REGSP
700 p.Reg = REG_R1
701 p.To.Type = obj.TYPE_REG
702 p.To.Reg = REG_R1
703 } else {
704
705 offset := int64(framesize) - abi.StackSmall
706 if framesize > abi.StackBig {
707
708
709
710
711
712
713
714
715
716
717 p = obj.Appendp(p, c.newprog)
718 p.As = ASGTU
719 p.From.Type = obj.TYPE_CONST
720 p.From.Offset = offset
721 p.Reg = REGSP
722 p.To.Type = obj.TYPE_REG
723 p.To.Reg = REG_R2
724
725 p = obj.Appendp(p, c.newprog)
726 q = p
727 p.As = ABNE
728 p.From.Type = obj.TYPE_REG
729 p.From.Reg = REG_R2
730 p.To.Type = obj.TYPE_BRANCH
731 p.Mark |= BRANCH
732 }
733
734
735
736
737 p = obj.Appendp(p, c.newprog)
738
739 p.As = add
740 p.From.Type = obj.TYPE_CONST
741 p.From.Offset = -offset
742 p.Reg = REGSP
743 p.To.Type = obj.TYPE_REG
744 p.To.Reg = REG_R2
745
746 p = obj.Appendp(p, c.newprog)
747 p.As = ASGTU
748 p.From.Type = obj.TYPE_REG
749 p.From.Reg = REG_R2
750 p.Reg = REG_R1
751 p.To.Type = obj.TYPE_REG
752 p.To.Reg = REG_R1
753 }
754
755
756 p = obj.Appendp(p, c.newprog)
757 q1 := p
758
759 p.As = ABNE
760 p.From.Type = obj.TYPE_REG
761 p.From.Reg = REG_R1
762 p.To.Type = obj.TYPE_BRANCH
763 p.Mark |= BRANCH
764
765
766 p = obj.Appendp(p, c.newprog)
767
768 p.As = mov
769 p.From.Type = obj.TYPE_REG
770 p.From.Reg = REGLINK
771 p.To.Type = obj.TYPE_REG
772 p.To.Reg = REG_R3
773 if q != nil {
774 q.To.SetTarget(p)
775 p.Mark |= LABEL
776 }
777
778 p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
779
780
781 p = obj.Appendp(p, c.newprog)
782
783 p.As = AJAL
784 p.To.Type = obj.TYPE_BRANCH
785 if c.cursym.CFunc() {
786 p.To.Sym = c.ctxt.Lookup("runtime.morestackc")
787 } else if !c.cursym.Func().Text.From.Sym.NeedCtxt() {
788 p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
789 } else {
790 p.To.Sym = c.ctxt.Lookup("runtime.morestack")
791 }
792 p.Mark |= BRANCH
793
794 p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
795
796
797 p = obj.Appendp(p, c.newprog)
798
799 p.As = AJMP
800 p.To.Type = obj.TYPE_BRANCH
801 p.To.SetTarget(startPred.Link)
802 startPred.Link.Mark |= LABEL
803 p.Mark |= BRANCH
804
805
806 p = obj.Appendp(p, c.newprog)
807
808 p.As = obj.ANOP
809 q1.To.SetTarget(p)
810
811 return p
812 }
813
814 func (c *ctxt0) addnop(p *obj.Prog) {
815 q := c.newprog()
816 q.As = ANOOP
817 q.Pos = p.Pos
818 q.Link = p.Link
819 p.Link = q
820 }
821
822 const (
823 E_HILO = 1 << 0
824 E_FCR = 1 << 1
825 E_MCR = 1 << 2
826 E_MEM = 1 << 3
827 E_MEMSP = 1 << 4
828 E_MEMSB = 1 << 5
829 ANYMEM = E_MEM | E_MEMSP | E_MEMSB
830
831 DELAY = BRANCH
832 )
833
834 type Dep struct {
835 ireg uint32
836 freg uint32
837 cc uint32
838 }
839
840 type Sch struct {
841 p obj.Prog
842 set Dep
843 used Dep
844 soffset int32
845 size uint8
846 nop uint8
847 comp bool
848 }
849
850 func (c *ctxt0) sched(p0, pe *obj.Prog) {
851 var sch [NSCHED]Sch
852
853
856 s := sch[:]
857 for p := p0; ; p = p.Link {
858 s[0].p = *p
859 c.markregused(&s[0])
860 if p == pe {
861 break
862 }
863 s = s[1:]
864 }
865 se := s
866
867 for i := cap(sch) - cap(se); i >= 0; i-- {
868 s = sch[i:]
869 if s[0].p.Mark&DELAY == 0 {
870 continue
871 }
872 if -cap(s) < -cap(se) {
873 if !conflict(&s[0], &s[1]) {
874 continue
875 }
876 }
877
878 var t []Sch
879 var j int
880 for j = cap(sch) - cap(s) - 1; j >= 0; j-- {
881 t = sch[j:]
882 if t[0].comp {
883 if s[0].p.Mark&BRANCH != 0 {
884 continue
885 }
886 }
887 if t[0].p.Mark&DELAY != 0 {
888 if -cap(s) >= -cap(se) || conflict(&t[0], &s[1]) {
889 continue
890 }
891 }
892 for u := t[1:]; -cap(u) <= -cap(s); u = u[1:] {
893 if c.depend(&u[0], &t[0]) {
894 continue
895 }
896 }
897 goto out2
898 }
899
900 if s[0].p.Mark&BRANCH != 0 {
901 s[0].nop = 1
902 }
903 continue
904
905 out2:
906
907 stmp := t[0]
908 copy(t[:i-j], t[1:i-j+1])
909 s[0] = stmp
910
911 if t[i-j-1].p.Mark&BRANCH != 0 {
912
913
914 t[i-j-1].p.Spadj += t[i-j].p.Spadj
915 t[i-j].p.Spadj = 0
916 }
917
918 i--
919 }
920
921
924 var p *obj.Prog
925 var q *obj.Prog
926 for s, p = sch[:], p0; -cap(s) <= -cap(se); s, p = s[1:], q {
927 q = p.Link
928 if q != s[0].p.Link {
929 *p = s[0].p
930 p.Link = q
931 }
932 for s[0].nop != 0 {
933 s[0].nop--
934 c.addnop(p)
935 }
936 }
937 }
938
939 func (c *ctxt0) markregused(s *Sch) {
940 p := &s.p
941 s.comp = c.compound(p)
942 s.nop = 0
943 if s.comp {
944 s.set.ireg |= 1 << (REGTMP - REG_R0)
945 s.used.ireg |= 1 << (REGTMP - REG_R0)
946 }
947
948 ar := 0
949 ad := 0
950 ld := 0
951 sz := 20
952
953
956 switch p.As {
957 case obj.ATEXT:
958 c.autosize = int32(p.To.Offset + 8)
959 ad = 1
960
961 case AJAL:
962 r := p.Reg
963 if r == 0 {
964 r = REGLINK
965 }
966 s.set.ireg |= 1 << uint(r-REG_R0)
967 ar = 1
968 ad = 1
969
970 case ABGEZAL,
971 ABLTZAL:
972 s.set.ireg |= 1 << (REGLINK - REG_R0)
973 fallthrough
974 case ABEQ,
975 ABGEZ,
976 ABGTZ,
977 ABLEZ,
978 ABLTZ,
979 ABNE:
980 ar = 1
981 ad = 1
982
983 case ABFPT,
984 ABFPF:
985 ad = 1
986 s.used.cc |= E_FCR
987
988 case ACMPEQD,
989 ACMPEQF,
990 ACMPGED,
991 ACMPGEF,
992 ACMPGTD,
993 ACMPGTF:
994 ar = 1
995 s.set.cc |= E_FCR
996 p.Mark |= FCMP
997
998 case AJMP:
999 ar = 1
1000 ad = 1
1001
1002 case AMOVB,
1003 AMOVBU:
1004 sz = 1
1005 ld = 1
1006
1007 case AMOVH,
1008 AMOVHU:
1009 sz = 2
1010 ld = 1
1011
1012 case AMOVF,
1013 AMOVW,
1014 AMOVWL,
1015 AMOVWR:
1016 sz = 4
1017 ld = 1
1018
1019 case AMOVD,
1020 AMOVV,
1021 AMOVVL,
1022 AMOVVR:
1023 sz = 8
1024 ld = 1
1025
1026 case ADIV,
1027 ADIVU,
1028 AMUL,
1029 AMULU,
1030 AREM,
1031 AREMU,
1032 ADIVV,
1033 ADIVVU,
1034 AMULV,
1035 AMULVU,
1036 AREMV,
1037 AREMVU:
1038 s.set.cc = E_HILO
1039 fallthrough
1040 case AADD,
1041 AADDU,
1042 AADDV,
1043 AADDVU,
1044 AAND,
1045 ANOR,
1046 AOR,
1047 ASGT,
1048 ASGTU,
1049 ASLL,
1050 ASRA,
1051 ASRL,
1052 ASLLV,
1053 ASRAV,
1054 ASRLV,
1055 ASUB,
1056 ASUBU,
1057 ASUBV,
1058 ASUBVU,
1059 AXOR,
1060
1061 AADDD,
1062 AADDF,
1063 AADDW,
1064 ASUBD,
1065 ASUBF,
1066 ASUBW,
1067 AMULF,
1068 AMULD,
1069 AMULW,
1070 ADIVF,
1071 ADIVD,
1072 ADIVW:
1073 if p.Reg == 0 {
1074 if p.To.Type == obj.TYPE_REG {
1075 p.Reg = p.To.Reg
1076 }
1077
1078
1079 }
1080 }
1081
1082
1085 cls := int(p.To.Class)
1086 if cls == 0 {
1087 cls = c.aclass(&p.To) + 1
1088 p.To.Class = int8(cls)
1089 }
1090 cls--
1091 switch cls {
1092 default:
1093 fmt.Printf("unknown class %d %v\n", cls, p)
1094
1095 case C_ZCON,
1096 C_SCON,
1097 C_ADD0CON,
1098 C_AND0CON,
1099 C_ADDCON,
1100 C_ANDCON,
1101 C_UCON,
1102 C_LCON,
1103 C_NONE,
1104 C_SBRA,
1105 C_LBRA,
1106 C_ADDR,
1107 C_TEXTSIZE:
1108 break
1109
1110 case C_HI,
1111 C_LO:
1112 s.set.cc |= E_HILO
1113
1114 case C_FCREG:
1115 s.set.cc |= E_FCR
1116
1117 case C_MREG:
1118 s.set.cc |= E_MCR
1119
1120 case C_ZOREG,
1121 C_SOREG,
1122 C_LOREG:
1123 cls = int(p.To.Reg)
1124 s.used.ireg |= 1 << uint(cls-REG_R0)
1125 if ad != 0 {
1126 break
1127 }
1128 s.size = uint8(sz)
1129 s.soffset = c.regoff(&p.To)
1130
1131 m := uint32(ANYMEM)
1132 if cls == REGSB {
1133 m = E_MEMSB
1134 }
1135 if cls == REGSP {
1136 m = E_MEMSP
1137 }
1138
1139 if ar != 0 {
1140 s.used.cc |= m
1141 } else {
1142 s.set.cc |= m
1143 }
1144
1145 case C_SACON,
1146 C_LACON:
1147 s.used.ireg |= 1 << (REGSP - REG_R0)
1148
1149 case C_SECON,
1150 C_LECON:
1151 s.used.ireg |= 1 << (REGSB - REG_R0)
1152
1153 case C_REG:
1154 if ar != 0 {
1155 s.used.ireg |= 1 << uint(p.To.Reg-REG_R0)
1156 } else {
1157 s.set.ireg |= 1 << uint(p.To.Reg-REG_R0)
1158 }
1159
1160 case C_FREG:
1161 if ar != 0 {
1162 s.used.freg |= 1 << uint(p.To.Reg-REG_F0)
1163 } else {
1164 s.set.freg |= 1 << uint(p.To.Reg-REG_F0)
1165 }
1166 if ld != 0 && p.From.Type == obj.TYPE_REG {
1167 p.Mark |= LOAD
1168 }
1169
1170 case C_SAUTO,
1171 C_LAUTO:
1172 s.used.ireg |= 1 << (REGSP - REG_R0)
1173 if ad != 0 {
1174 break
1175 }
1176 s.size = uint8(sz)
1177 s.soffset = c.regoff(&p.To)
1178
1179 if ar != 0 {
1180 s.used.cc |= E_MEMSP
1181 } else {
1182 s.set.cc |= E_MEMSP
1183 }
1184
1185 case C_SEXT,
1186 C_LEXT:
1187 s.used.ireg |= 1 << (REGSB - REG_R0)
1188 if ad != 0 {
1189 break
1190 }
1191 s.size = uint8(sz)
1192 s.soffset = c.regoff(&p.To)
1193
1194 if ar != 0 {
1195 s.used.cc |= E_MEMSB
1196 } else {
1197 s.set.cc |= E_MEMSB
1198 }
1199 }
1200
1201
1204 cls = int(p.From.Class)
1205 if cls == 0 {
1206 cls = c.aclass(&p.From) + 1
1207 p.From.Class = int8(cls)
1208 }
1209 cls--
1210 switch cls {
1211 default:
1212 fmt.Printf("unknown class %d %v\n", cls, p)
1213
1214 case C_ZCON,
1215 C_SCON,
1216 C_ADD0CON,
1217 C_AND0CON,
1218 C_ADDCON,
1219 C_ANDCON,
1220 C_UCON,
1221 C_LCON,
1222 C_NONE,
1223 C_SBRA,
1224 C_LBRA,
1225 C_ADDR,
1226 C_TEXTSIZE:
1227 break
1228
1229 case C_HI,
1230 C_LO:
1231 s.used.cc |= E_HILO
1232
1233 case C_FCREG:
1234 s.used.cc |= E_FCR
1235
1236 case C_MREG:
1237 s.used.cc |= E_MCR
1238
1239 case C_ZOREG,
1240 C_SOREG,
1241 C_LOREG:
1242 cls = int(p.From.Reg)
1243 s.used.ireg |= 1 << uint(cls-REG_R0)
1244 if ld != 0 {
1245 p.Mark |= LOAD
1246 }
1247 s.size = uint8(sz)
1248 s.soffset = c.regoff(&p.From)
1249
1250 m := uint32(ANYMEM)
1251 if cls == REGSB {
1252 m = E_MEMSB
1253 }
1254 if cls == REGSP {
1255 m = E_MEMSP
1256 }
1257
1258 s.used.cc |= m
1259
1260 case C_SACON,
1261 C_LACON:
1262 cls = int(p.From.Reg)
1263 if cls == 0 {
1264 cls = REGSP
1265 }
1266 s.used.ireg |= 1 << uint(cls-REG_R0)
1267
1268 case C_SECON,
1269 C_LECON:
1270 s.used.ireg |= 1 << (REGSB - REG_R0)
1271
1272 case C_REG:
1273 s.used.ireg |= 1 << uint(p.From.Reg-REG_R0)
1274
1275 case C_FREG:
1276 s.used.freg |= 1 << uint(p.From.Reg-REG_F0)
1277 if ld != 0 && p.To.Type == obj.TYPE_REG {
1278 p.Mark |= LOAD
1279 }
1280
1281 case C_SAUTO,
1282 C_LAUTO:
1283 s.used.ireg |= 1 << (REGSP - REG_R0)
1284 if ld != 0 {
1285 p.Mark |= LOAD
1286 }
1287 if ad != 0 {
1288 break
1289 }
1290 s.size = uint8(sz)
1291 s.soffset = c.regoff(&p.From)
1292
1293 s.used.cc |= E_MEMSP
1294
1295 case C_SEXT:
1296 case C_LEXT:
1297 s.used.ireg |= 1 << (REGSB - REG_R0)
1298 if ld != 0 {
1299 p.Mark |= LOAD
1300 }
1301 if ad != 0 {
1302 break
1303 }
1304 s.size = uint8(sz)
1305 s.soffset = c.regoff(&p.From)
1306
1307 s.used.cc |= E_MEMSB
1308 }
1309
1310 cls = int(p.Reg)
1311 if cls != 0 {
1312 if REG_F0 <= cls && cls <= REG_F31 {
1313 s.used.freg |= 1 << uint(cls-REG_F0)
1314 } else {
1315 s.used.ireg |= 1 << uint(cls-REG_R0)
1316 }
1317 }
1318 s.set.ireg &^= (1 << (REGZERO - REG_R0))
1319 }
1320
1321
1325 func (c *ctxt0) depend(sa, sb *Sch) bool {
1326 if sa.set.ireg&(sb.set.ireg|sb.used.ireg) != 0 {
1327 return true
1328 }
1329 if sb.set.ireg&sa.used.ireg != 0 {
1330 return true
1331 }
1332
1333 if sa.set.freg&(sb.set.freg|sb.used.freg) != 0 {
1334 return true
1335 }
1336 if sb.set.freg&sa.used.freg != 0 {
1337 return true
1338 }
1339
1340
1345 if sa.used.cc&sb.used.cc&E_MEM != 0 {
1346 if sa.p.Reg == sb.p.Reg {
1347 if c.regoff(&sa.p.From) == c.regoff(&sb.p.From) {
1348 return true
1349 }
1350 }
1351 }
1352
1353 x := (sa.set.cc & (sb.set.cc | sb.used.cc)) | (sb.set.cc & sa.used.cc)
1354 if x != 0 {
1355
1360 if x != E_MEMSP && x != E_MEMSB {
1361 return true
1362 }
1363 x = sa.set.cc | sb.set.cc | sa.used.cc | sb.used.cc
1364 if x&E_MEM != 0 {
1365 return true
1366 }
1367 if offoverlap(sa, sb) {
1368 return true
1369 }
1370 }
1371
1372 return false
1373 }
1374
1375 func offoverlap(sa, sb *Sch) bool {
1376 if sa.soffset < sb.soffset {
1377 if sa.soffset+int32(sa.size) > sb.soffset {
1378 return true
1379 }
1380 return false
1381 }
1382 if sb.soffset+int32(sb.size) > sa.soffset {
1383 return true
1384 }
1385 return false
1386 }
1387
1388
1393 func conflict(sa, sb *Sch) bool {
1394 if sa.set.ireg&sb.used.ireg != 0 {
1395 return true
1396 }
1397 if sa.set.freg&sb.used.freg != 0 {
1398 return true
1399 }
1400 if sa.set.cc&sb.used.cc != 0 {
1401 return true
1402 }
1403 return false
1404 }
1405
1406 func (c *ctxt0) compound(p *obj.Prog) bool {
1407 o := c.oplook(p)
1408 if o.size != 4 {
1409 return true
1410 }
1411 if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSB {
1412 return true
1413 }
1414 return false
1415 }
1416
1417 var Linkmips64 = obj.LinkArch{
1418 Arch: sys.ArchMIPS64,
1419 Init: buildop,
1420 Preprocess: preprocess,
1421 Assemble: span0,
1422 Progedit: progedit,
1423 DWARFRegisters: MIPSDWARFRegisters,
1424 }
1425
1426 var Linkmips64le = obj.LinkArch{
1427 Arch: sys.ArchMIPS64LE,
1428 Init: buildop,
1429 Preprocess: preprocess,
1430 Assemble: span0,
1431 Progedit: progedit,
1432 DWARFRegisters: MIPSDWARFRegisters,
1433 }
1434
1435 var Linkmips = obj.LinkArch{
1436 Arch: sys.ArchMIPS,
1437 Init: buildop,
1438 Preprocess: preprocess,
1439 Assemble: span0,
1440 Progedit: progedit,
1441 DWARFRegisters: MIPSDWARFRegisters,
1442 }
1443
1444 var Linkmipsle = obj.LinkArch{
1445 Arch: sys.ArchMIPSLE,
1446 Init: buildop,
1447 Preprocess: preprocess,
1448 Assemble: span0,
1449 Progedit: progedit,
1450 DWARFRegisters: MIPSDWARFRegisters,
1451 }
1452
View as plain text