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