cmd/internal/obj/mips: add support for GOARCH=mips{,le}

Implements subset of MIPS32(r1) instruction set.

Change-Id: Iba017350f6c2763de05d4d1bc2f123e8eb76d0ff
Reviewed-on: https://go-review.googlesource.com/31475
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Vladimir Stefanovic 2016-10-18 23:50:37 +02:00 committed by Brad Fitzpatrick
parent c41137d242
commit 5d28bc58b6
8 changed files with 553 additions and 321 deletions

View file

@ -37,6 +37,18 @@ import (
)
func progedit(ctxt *obj.Link, p *obj.Prog) {
// Maintain information about code generation mode.
if ctxt.Mode == 0 {
switch ctxt.Arch.Family {
default:
ctxt.Diag("unsupported arch family")
case sys.MIPS:
ctxt.Mode = Mips32
case sys.MIPS64:
ctxt.Mode = Mips64
}
}
p.From.Class = 0
p.To.Class = 0
@ -59,7 +71,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
f32 := float32(p.From.Val.(float64))
i32 := math.Float32bits(f32)
if i32 == 0 {
p.As = AMOVV
p.As = AMOVW
p.From.Type = obj.TYPE_REG
p.From.Reg = REGZERO
break
@ -76,7 +88,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
case AMOVD:
if p.From.Type == obj.TYPE_FCONST {
i64 := math.Float64bits(p.From.Val.(float64))
if i64 == 0 {
if i64 == 0 && ctxt.Mode&Mips64 != 0 {
p.As = AMOVV
p.From.Type = obj.TYPE_REG
p.From.Reg = REGZERO
@ -271,6 +283,15 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
}
}
var mov, add obj.As
if ctxt.Mode&Mips64 != 0 {
add = AADDV
mov = AMOVV
} else {
add = AADDU
mov = AMOVW
}
autosize := int32(0)
var p1 *obj.Prog
var p2 *obj.Prog
@ -278,13 +299,14 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
o := p.As
switch o {
case obj.ATEXT:
autosize = int32(textstksiz + 8)
if (p.Mark&LEAF != 0) && autosize <= 8 {
autosize = int32(textstksiz + ctxt.FixedFrameSize())
if (p.Mark&LEAF != 0) && autosize <= int32(ctxt.FixedFrameSize()) {
autosize = 0
} else if autosize&4 != 0 {
} else if autosize&4 != 0 && ctxt.Mode&Mips64 != 0 {
autosize += 4
}
p.To.Offset = int64(autosize) - 8
p.To.Offset = int64(autosize) - ctxt.FixedFrameSize()
if p.From3.Offset&obj.NOSPLIT == 0 {
p = stacksplit(ctxt, p, autosize) // emit split check
@ -299,7 +321,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
// during the execution of the function prologue, the traceback
// code will not see a half-updated stack frame.
q = obj.Appendp(ctxt, q)
q.As = AMOVV
q.As = mov
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_REG
q.From.Reg = REGLINK
@ -308,7 +330,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
q.To.Reg = REGSP
q = obj.Appendp(ctxt, q)
q.As = AADDV
q.As = add
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(-autosize)
@ -333,13 +355,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVV g_panic(g), R1
// BEQ R1, end
// MOVV panic_argp(R1), R2
// ADDV $(autosize+8), R29, R3
// BNE R2, R3, end
// ADDV $8, R29, R2
// MOVV R2, panic_argp(R1)
// MOV g_panic(g), R1
// BEQ R1, end
// MOV panic_argp(R1), R2
// ADD $(autosize+FIXED_FRAME), R29, R3
// BNE R2, R3, end
// ADD $FIXED_FRAME, R29, R2
// MOV R2, panic_argp(R1)
// end:
// NOP
//
@ -348,7 +370,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
q = obj.Appendp(ctxt, q)
q.As = AMOVV
q.As = mov
q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG
q.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // G.panic
@ -364,7 +386,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p1 = q
q = obj.Appendp(ctxt, q)
q.As = AMOVV
q.As = mov
q.From.Type = obj.TYPE_MEM
q.From.Reg = REG_R1
q.From.Offset = 0 // Panic.argp
@ -372,9 +394,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
q.To.Reg = REG_R2
q = obj.Appendp(ctxt, q)
q.As = AADDV
q.As = add
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize) + 8
q.From.Offset = int64(autosize) + ctxt.FixedFrameSize()
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R3
@ -389,15 +411,15 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p2 = q
q = obj.Appendp(ctxt, q)
q.As = AADDV
q.As = add
q.From.Type = obj.TYPE_CONST
q.From.Offset = 8
q.From.Offset = ctxt.FixedFrameSize()
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R2
q = obj.Appendp(ctxt, q)
q.As = AMOVV
q.As = mov
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R2
q.To.Type = obj.TYPE_MEM
@ -438,7 +460,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
break
}
p.As = AADDV
p.As = add
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autosize)
p.To.Type = obj.TYPE_REG
@ -459,7 +481,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
break
}
p.As = AMOVV
p.As = mov
p.From.Type = obj.TYPE_MEM
p.From.Offset = 0
p.From.Reg = REGSP
@ -471,7 +493,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
if autosize != 0 {
q = ctxt.NewProg()
q.As = AADDV
q.As = add
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize)
@ -501,7 +523,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
q1.Link = q.Link
q.Link = q1
case AADDV,
case AADD,
AADDU,
AADDV,
AADDVU:
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
p.Spadj = int32(-p.From.Offset)
@ -564,10 +588,27 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
}
func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
// MOVV g_stackguard(g), R1
// Leaf function with no frame is effectively NOSPLIT.
if framesize == 0 {
return p
}
var mov, add, sub obj.As
if ctxt.Mode&Mips64 != 0 {
add = AADDV
mov = AMOVV
sub = ASUBVU
} else {
add = AADDU
mov = AMOVW
sub = ASUBU
}
// MOV g_stackguard(g), R1
p = obj.Appendp(ctxt, p)
p.As = AMOVV
p.As = mov
p.From.Type = obj.TYPE_MEM
p.From.Reg = REGG
p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
@ -591,11 +632,11 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
p.To.Reg = REG_R1
} else if framesize <= obj.StackBig {
// large stack: SP-framesize < stackguard-StackSmall
// ADDV $-framesize, SP, R2
// ADD $-framesize, SP, R2
// SGTU R2, stackguard, R1
p = obj.Appendp(ctxt, p)
p.As = AADDV
p.As = add
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(-framesize)
p.Reg = REGSP
@ -619,15 +660,15 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
// Preemption sets stackguard to StackPreempt, a very large value.
// That breaks the math above, so we have to check for that explicitly.
// // stackguard is R1
// MOVV $StackPreempt, R2
// MOV $StackPreempt, R2
// BEQ R1, R2, label-of-call-to-morestack
// ADDV $StackGuard, SP, R2
// SUBVU R1, R2
// MOVV $(framesize+(StackGuard-StackSmall)), R1
// ADD $StackGuard, SP, R2
// SUB R1, R2
// MOV $(framesize+(StackGuard-StackSmall)), R1
// SGTU R2, R1, R1
p = obj.Appendp(ctxt, p)
p.As = AMOVV
p.As = mov
p.From.Type = obj.TYPE_CONST
p.From.Offset = obj.StackPreempt
p.To.Type = obj.TYPE_REG
@ -643,7 +684,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
p.Mark |= BRANCH
p = obj.Appendp(ctxt, p)
p.As = AADDV
p.As = add
p.From.Type = obj.TYPE_CONST
p.From.Offset = obj.StackGuard
p.Reg = REGSP
@ -651,14 +692,14 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
p.As = ASUBVU
p.As = sub
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_R1
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
p.As = AMOVV
p.As = mov
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
p.To.Type = obj.TYPE_REG
@ -683,10 +724,10 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
p.To.Type = obj.TYPE_BRANCH
p.Mark |= BRANCH
// MOVV LINK, R3
// MOV LINK, R3
p = obj.Appendp(ctxt, p)
p.As = AMOVV
p.As = mov
p.From.Type = obj.TYPE_REG
p.From.Reg = REGLINK
p.To.Type = obj.TYPE_REG
@ -1494,3 +1535,19 @@ var Linkmips64le = obj.LinkArch{
Follow: follow,
Progedit: progedit,
}
var Linkmips = obj.LinkArch{
Arch: sys.ArchMIPS,
Preprocess: preprocess,
Assemble: span0,
Follow: follow,
Progedit: progedit,
}
var Linkmipsle = obj.LinkArch{
Arch: sys.ArchMIPSLE,
Preprocess: preprocess,
Assemble: span0,
Follow: follow,
Progedit: progedit,
}