Commit 5d28bc58 authored by Vladimir Stefanovic's avatar Vladimir Stefanovic Committed by Brad Fitzpatrick

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: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
parent c41137d2
......@@ -415,7 +415,7 @@ func archMips64() *Arch {
}
for i, s := range mips.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseMIPS64
instructions[s] = obj.As(i) + obj.ABaseMIPS
}
}
// Annoying alias.
......
......@@ -311,7 +311,7 @@ const (
ABaseAMD64
ABasePPC64
ABaseARM64
ABaseMIPS64
ABaseMIPS
ABaseS390X
AllowedOpCodes = 1 << 10 // The number of opcodes available for any given architecture.
......@@ -532,7 +532,7 @@ const (
// R_ADDRARM64 relocates an adrp, add pair to compute the address of the
// referenced symbol.
R_ADDRARM64
// R_ADDRMIPS (only used on mips64) resolves to the low 16 bits of an external
// R_ADDRMIPS (only used on mips/mips64) resolves to the low 16 bits of an external
// address, by encoding it into the instruction.
R_ADDRMIPS
// R_ADDROFF resolves to a 32-bit offset from the beginning of the section
......@@ -660,7 +660,7 @@ const (
// TODO(mundaym): remove once variants can be serialized - see issue 14218.
R_PCRELDBL
// R_ADDRMIPSU (only used on mips64) resolves to the sign-adjusted "upper" 16
// R_ADDRMIPSU (only used on mips/mips64) resolves to the sign-adjusted "upper" 16
// bits (bit 16-31) of an external address, by encoding it into the instruction.
R_ADDRMIPSU
// R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS
......
......@@ -44,7 +44,7 @@ const (
)
const (
REG_R0 = obj.RBaseMIPS64 + iota
REG_R0 = obj.RBaseMIPS + iota
REG_R1
REG_R2
REG_R3
......@@ -217,6 +217,11 @@ const (
NSCHED = 20
)
const (
Mips32 = 32
Mips64 = 64
)
const (
C_NONE = iota
C_REG
......@@ -258,7 +263,7 @@ const (
)
const (
AABSD = obj.ABaseMIPS64 + obj.A_ARCHSPECIFIC + iota
AABSD = obj.ABaseMIPS + obj.A_ARCHSPECIFIC + iota
AABSF
AABSW
AADD
......@@ -278,6 +283,12 @@ const (
ABLTZAL
ABNE
ABREAK
ACLO
ACLZ
ACMOVF
ACMOVN
ACMOVT
ACMOVZ
ACMPEQD
ACMPEQF
ACMPGED
......@@ -290,6 +301,7 @@ const (
ADIVU
ADIVW
AGOK
ALL
ALUI
AMOVB
AMOVBU
......@@ -319,9 +331,12 @@ const (
AREM
AREMU
ARFE
ASC
ASGT
ASGTU
ASLL
ASQRTD
ASQRTF
ASRA
ASRL
ASUB
......@@ -329,11 +344,14 @@ const (
ASUBF
ASUBU
ASUBW
ASYNC
ASYSCALL
ATEQ
ATLBP
ATLBR
ATLBWI
ATLBWR
ATNE
AWORD
AXOR
......
......@@ -26,6 +26,12 @@ var Anames = []string{
"BLTZAL",
"BNE",
"BREAK",
"CLO",
"CLZ",
"CMOVF",
"CMOVN",
"CMOVT",
"CMOVZ",
"CMPEQD",
"CMPEQF",
"CMPGED",
......@@ -38,6 +44,7 @@ var Anames = []string{
"DIVU",
"DIVW",
"GOK",
"LL",
"LUI",
"MOVB",
"MOVBU",
......@@ -67,9 +74,12 @@ var Anames = []string{
"REM",
"REMU",
"RFE",
"SC",
"SGT",
"SGTU",
"SLL",
"SQRTD",
"SQRTF",
"SRA",
"SRL",
"SUB",
......@@ -77,11 +87,14 @@ var Anames = []string{
"SUBF",
"SUBU",
"SUBW",
"SYNC",
"SYSCALL",
"TEQ",
"TLBP",
"TLBR",
"TLBWI",
"TLBWR",
"TNE",
"WORD",
"XOR",
"MOVV",
......
This diff is collapsed.
......@@ -35,8 +35,8 @@ import (
)
func init() {
obj.RegisterRegister(obj.RBaseMIPS64, REG_LAST&^1023+1024, Rconv)
obj.RegisterOpcode(obj.ABaseMIPS64, Anames)
obj.RegisterRegister(obj.RBaseMIPS, REG_LAST+1, Rconv)
obj.RegisterOpcode(obj.ABaseMIPS, Anames)
}
func Rconv(r int) string {
......@@ -70,7 +70,7 @@ func Rconv(r int) string {
return "LO"
}
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS64)
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS)
}
func DRconv(a int) string {
......
......@@ -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
// MOV g_panic(g), R1
// BEQ R1, end
// MOVV panic_argp(R1), R2
// ADDV $(autosize+8), R29, R3
// MOV panic_argp(R1), R2
// ADD $(autosize+FIXED_FRAME), R29, R3
// BNE R2, R3, end
// ADDV $8, R29, R2
// MOVV R2, panic_argp(R1)
// 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,
}
......@@ -389,7 +389,7 @@ const (
RBaseARM = 3 * 1024
RBasePPC64 = 4 * 1024 // range [4k, 8k)
RBaseARM64 = 8 * 1024 // range [8k, 13k)
RBaseMIPS64 = 13 * 1024 // range [13k, 14k)
RBaseMIPS = 13 * 1024 // range [13k, 14k)
RBaseS390X = 14 * 1024 // range [14k, 15k)
)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment