Skip to content

Commit f4c9975

Browse files
Vladimir Stefanovicbradfitz
Vladimir Stefanovic
authored andcommitted
cmd/compile: add support for GOARCH=mips{,le}
Change-Id: Ib489dc847787aaab7ba1be96792f885469e346ae Reviewed-on: https://go-review.googlesource.com/31479 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 247fc4a commit f4c9975

File tree

4 files changed

+1191
-0
lines changed

4 files changed

+1191
-0
lines changed

Diff for: src/cmd/compile/internal/mips/galign.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package mips
6+
7+
import (
8+
"cmd/compile/internal/gc"
9+
"cmd/compile/internal/ssa"
10+
"cmd/internal/obj"
11+
"cmd/internal/obj/mips"
12+
)
13+
14+
func Init() {
15+
gc.Thearch.LinkArch = &mips.Linkmips
16+
if obj.GOARCH == "mipsle" {
17+
gc.Thearch.LinkArch = &mips.Linkmipsle
18+
}
19+
gc.Thearch.REGSP = mips.REGSP
20+
gc.Thearch.MAXWIDTH = (1 << 31) - 1
21+
gc.Thearch.Defframe = defframe
22+
gc.Thearch.Proginfo = proginfo
23+
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
24+
gc.Thearch.SSAGenValue = ssaGenValue
25+
gc.Thearch.SSAGenBlock = ssaGenBlock
26+
}

Diff for: src/cmd/compile/internal/mips/ggen.go

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package mips
6+
7+
import (
8+
"cmd/compile/internal/gc"
9+
"cmd/internal/obj"
10+
"cmd/internal/obj/mips"
11+
)
12+
13+
func defframe(ptxt *obj.Prog) {
14+
// fill in argument size, stack size
15+
ptxt.To.Type = obj.TYPE_TEXTSIZE
16+
17+
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
18+
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
19+
ptxt.To.Offset = int64(frame)
20+
21+
// insert code to zero ambiguously live variables
22+
// so that the garbage collector only sees initialized values
23+
// when it looks for pointers.
24+
p := ptxt
25+
26+
hi := int64(0)
27+
lo := hi
28+
29+
// iterate through declarations - they are sorted in decreasing xoffset order.
30+
for _, n := range gc.Curfn.Func.Dcl {
31+
if !n.Name.Needzero {
32+
continue
33+
}
34+
if n.Class != gc.PAUTO {
35+
gc.Fatalf("needzero class %d", n.Class)
36+
}
37+
if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
38+
gc.Fatalf("var %L has size %d offset %d", n, int(n.Type.Width), int(n.Xoffset))
39+
}
40+
41+
if lo != hi && n.Xoffset+n.Type.Width >= lo-int64(2*gc.Widthreg) {
42+
// merge with range we already have
43+
lo = n.Xoffset
44+
45+
continue
46+
}
47+
48+
// zero old range
49+
p = zerorange(p, int64(frame), lo, hi)
50+
51+
// set new range
52+
hi = n.Xoffset + n.Type.Width
53+
54+
lo = n.Xoffset
55+
}
56+
57+
// zero final range
58+
zerorange(p, int64(frame), lo, hi)
59+
}
60+
61+
// TODO(mips): implement DUFFZERO
62+
func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
63+
64+
cnt := hi - lo
65+
if cnt == 0 {
66+
return p
67+
}
68+
if cnt < int64(4*gc.Widthptr) {
69+
for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
70+
p = gc.Appendpp(p, mips.AMOVW, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGSP, gc.Ctxt.FixedFrameSize()+frame+lo+i)
71+
}
72+
} else {
73+
//fmt.Printf("zerorange frame:%v, lo: %v, hi:%v \n", frame ,lo, hi)
74+
// ADD $(FIXED_FRAME+frame+lo-4), SP, r1
75+
// ADD $cnt, r1, r2
76+
// loop:
77+
// MOVW R0, (Widthptr)r1
78+
// ADD $Widthptr, r1
79+
// BNE r1, r2, loop
80+
p = gc.Appendpp(p, mips.AADD, obj.TYPE_CONST, 0, gc.Ctxt.FixedFrameSize()+frame+lo-4, obj.TYPE_REG, mips.REGRT1, 0)
81+
p.Reg = mips.REGSP
82+
p = gc.Appendpp(p, mips.AADD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, mips.REGRT2, 0)
83+
p.Reg = mips.REGRT1
84+
p = gc.Appendpp(p, mips.AMOVW, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGRT1, int64(gc.Widthptr))
85+
p1 := p
86+
p = gc.Appendpp(p, mips.AADD, obj.TYPE_CONST, 0, int64(gc.Widthptr), obj.TYPE_REG, mips.REGRT1, 0)
87+
p = gc.Appendpp(p, mips.ABNE, obj.TYPE_REG, mips.REGRT1, 0, obj.TYPE_BRANCH, 0, 0)
88+
p.Reg = mips.REGRT2
89+
gc.Patch(p, p1)
90+
}
91+
92+
return p
93+
}
94+
95+
func ginsnop() {
96+
p := gc.Prog(mips.ANOR)
97+
p.From.Type = obj.TYPE_REG
98+
p.From.Reg = mips.REG_R0
99+
p.To.Type = obj.TYPE_REG
100+
p.To.Reg = mips.REG_R0
101+
}

Diff for: src/cmd/compile/internal/mips/prog.go

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package mips
6+
7+
import (
8+
"cmd/compile/internal/gc"
9+
"cmd/internal/obj"
10+
"cmd/internal/obj/mips"
11+
)
12+
13+
const (
14+
LeftRdwr uint32 = gc.LeftRead | gc.LeftWrite
15+
RightRdwr uint32 = gc.RightRead | gc.RightWrite
16+
)
17+
18+
// This table gives the basic information about instruction
19+
// generated by the compiler and processed in the optimizer.
20+
// See opt.h for bit definitions.
21+
//
22+
// Instructions not generated need not be listed.
23+
// As an exception to that rule, we typically write down all the
24+
// size variants of an operation even if we just use a subset.
25+
//
26+
// The table is formatted for 8-space tabs.
27+
var progtable = [mips.ALAST & obj.AMask]gc.ProgInfo{
28+
obj.ATYPE: {Flags: gc.Pseudo | gc.Skip},
29+
obj.ATEXT: {Flags: gc.Pseudo},
30+
obj.AFUNCDATA: {Flags: gc.Pseudo},
31+
obj.APCDATA: {Flags: gc.Pseudo},
32+
obj.AUNDEF: {Flags: gc.Break},
33+
obj.AUSEFIELD: {Flags: gc.OK},
34+
obj.AVARDEF: {Flags: gc.Pseudo | gc.RightWrite},
35+
obj.AVARKILL: {Flags: gc.Pseudo | gc.RightWrite},
36+
obj.AVARLIVE: {Flags: gc.Pseudo | gc.LeftRead},
37+
38+
// NOP is an internal no-op that also stands
39+
// for USED and SET annotations, not the MIPS opcode.
40+
obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
41+
42+
// Integer
43+
mips.AADD & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
44+
mips.AADDU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
45+
mips.ASUB & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
46+
mips.ASUBU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
47+
mips.AAND & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
48+
mips.AOR & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
49+
mips.AXOR & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
50+
mips.ANOR & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
51+
mips.AMUL & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
52+
mips.AMULU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
53+
mips.ADIV & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
54+
mips.ADIVU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
55+
mips.ASLL & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
56+
mips.ASRA & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
57+
mips.ASRL & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
58+
mips.ASGT & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
59+
mips.ASGTU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
60+
61+
mips.ACLZ & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
62+
mips.ACLO & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
63+
64+
// Floating point.
65+
mips.AADDF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
66+
mips.AADDD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
67+
mips.ASUBF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
68+
mips.ASUBD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
69+
mips.AMULF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
70+
mips.AMULD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
71+
mips.ADIVF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
72+
mips.ADIVD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
73+
mips.AABSF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
74+
mips.AABSD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
75+
mips.ANEGF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
76+
mips.ANEGD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
77+
mips.ACMPEQF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
78+
mips.ACMPEQD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
79+
mips.ACMPGTF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
80+
mips.ACMPGTD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
81+
mips.ACMPGEF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
82+
mips.ACMPGED & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
83+
mips.AMOVFD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
84+
mips.AMOVDF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
85+
mips.AMOVFW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
86+
mips.AMOVWF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
87+
mips.AMOVDW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
88+
mips.AMOVWD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
89+
mips.ATRUNCFW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
90+
mips.ATRUNCDW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
91+
92+
mips.ASQRTF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
93+
mips.ASQRTD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
94+
95+
// Moves
96+
mips.AMOVB & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
97+
mips.AMOVBU & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
98+
mips.AMOVH & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
99+
mips.AMOVHU & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
100+
mips.AMOVW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
101+
mips.AMOVF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
102+
mips.AMOVD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
103+
104+
// Conditional moves
105+
mips.ACMOVN & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
106+
mips.ACMOVZ & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
107+
mips.ACMOVT & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | RightRdwr},
108+
mips.ACMOVF & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | RightRdwr},
109+
110+
// Conditional trap
111+
mips.ATEQ & obj.AMask: {Flags: gc.SizeL | gc.RegRead | gc.RightRead},
112+
mips.ATNE & obj.AMask: {Flags: gc.SizeL | gc.RegRead | gc.RightRead},
113+
114+
// Atomic
115+
mips.ASYNC & obj.AMask: {Flags: gc.OK},
116+
mips.ALL & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite},
117+
mips.ASC & obj.AMask: {Flags: gc.SizeL | LeftRdwr | gc.RightRead},
118+
119+
// Jumps
120+
mips.AJMP & obj.AMask: {Flags: gc.Jump | gc.Break},
121+
mips.AJAL & obj.AMask: {Flags: gc.Call},
122+
mips.ABEQ & obj.AMask: {Flags: gc.Cjmp},
123+
mips.ABNE & obj.AMask: {Flags: gc.Cjmp},
124+
mips.ABGEZ & obj.AMask: {Flags: gc.Cjmp},
125+
mips.ABLTZ & obj.AMask: {Flags: gc.Cjmp},
126+
mips.ABGTZ & obj.AMask: {Flags: gc.Cjmp},
127+
mips.ABLEZ & obj.AMask: {Flags: gc.Cjmp},
128+
mips.ABFPF & obj.AMask: {Flags: gc.Cjmp},
129+
mips.ABFPT & obj.AMask: {Flags: gc.Cjmp},
130+
mips.ARET & obj.AMask: {Flags: gc.Break},
131+
obj.ADUFFZERO: {Flags: gc.Call},
132+
obj.ADUFFCOPY: {Flags: gc.Call},
133+
}
134+
135+
func proginfo(p *obj.Prog) gc.ProgInfo {
136+
info := progtable[p.As&obj.AMask]
137+
138+
if info.Flags == 0 {
139+
gc.Fatalf("proginfo: unknown instruction %v", p)
140+
}
141+
142+
if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
143+
info.Flags &^= gc.RegRead
144+
info.Flags |= gc.RightRead
145+
}
146+
147+
if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
148+
info.Flags &^= gc.LeftRead
149+
info.Flags |= gc.LeftAddr
150+
}
151+
152+
if p.As == mips.AMUL && p.To.Reg != 0 {
153+
info.Flags |= gc.RightWrite
154+
}
155+
156+
return info
157+
}

0 commit comments

Comments
 (0)