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