aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/asm
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2016-04-06 12:01:40 -0700
committerMatthew Dempsky <mdempsky@google.com>2016-04-07 01:23:25 +0000
commitc6e11fe03765e3fe1fc68bd794625ca0ecd833be (patch)
treec5b131e7c2406496f836a0055e28e9a9ff09eedb /src/cmd/asm
parent31cf1c17792d4da9dae2504c703633a0db8072c7 (diff)
downloadgo-c6e11fe03765e3fe1fc68bd794625ca0ecd833be.tar.xz
cmd: add new common architecture representation
Information about CPU architectures (e.g., name, family, byte ordering, pointer and register size) is currently redundantly scattered around the source tree. Instead consolidate the basic information into a single new package cmd/internal/sys. Also, introduce new sys.I386, sys.AMD64, etc. names for the constants '8', '6', etc. and replace most uses of the latter. The notable exceptions are a couple of error messages that still refer to the old char-based toolchain names and function reltype in cmd/link. Passes toolstash/buildall. Change-Id: I8a6f0cbd49577ec1672a98addebc45f767e36461 Reviewed-on: https://go-review.googlesource.com/21623 Reviewed-by: Michael Hudson-Doyle <michael.hudson@canonical.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/cmd/asm')
-rw-r--r--src/cmd/asm/internal/asm/asm.go49
-rw-r--r--src/cmd/asm/internal/asm/parse.go16
2 files changed, 33 insertions, 32 deletions
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index 950fd735c9..d674914c67 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -13,6 +13,7 @@ import (
"cmd/asm/internal/flags"
"cmd/asm/internal/lex"
"cmd/internal/obj"
+ "cmd/internal/sys"
)
// TODO: configure the architecture
@@ -23,14 +24,14 @@ var testOut *bytes.Buffer // Gathers output when testing.
// If doLabel is set, it also defines the labels collect for this Prog.
func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
if cond != "" {
- switch p.arch.Thechar {
- case '5':
+ switch p.arch.Family {
+ case sys.ARM:
if !arch.ARMConditionCodes(prog, cond) {
p.errorf("unrecognized condition code .%q", cond)
return
}
- case '7':
+ case sys.ARM64:
if !arch.ARM64Suffix(prog, cond) {
p.errorf("unrecognized suffix .%q", cond)
return
@@ -361,7 +362,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
target = &a[1]
prog.From = a[0]
case 3:
- if p.arch.Thechar == '9' {
+ if p.arch.Family == sys.PPC64 {
// Special 3-operand jumps.
// First two must be constants; a[1] is a register number.
target = &a[2]
@@ -378,7 +379,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
prog.Reg = reg
break
}
- if p.arch.Thechar == '0' {
+ if p.arch.Family == sys.MIPS64 {
// 3-operand jumps.
// First two must be registers
target = &a[2]
@@ -386,7 +387,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
- if p.arch.Thechar == 'z' {
+ if p.arch.Family == sys.S390X {
// 3-operand jumps.
target = &a[2]
prog.From = a[0]
@@ -438,7 +439,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
// JMP 4(R0)
prog.To = *target
// On the ppc64, 9a encodes BR (CTR) as BR CTR. We do the same.
- if p.arch.Thechar == '9' && target.Offset == 0 {
+ if p.arch.Family == sys.PPC64 && target.Offset == 0 {
prog.To.Type = obj.TYPE_REG
}
case target.Type == obj.TYPE_CONST:
@@ -492,14 +493,14 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.From = a[0]
// prog.To is no address.
}
- if p.arch.Thechar == '9' && arch.IsPPC64NEG(op) {
+ if p.arch.Family == sys.PPC64 && arch.IsPPC64NEG(op) {
// NEG: From and To are both a[0].
prog.To = a[0]
prog.From = a[0]
break
}
case 2:
- if p.arch.Thechar == '5' {
+ if p.arch.Family == sys.ARM {
if arch.IsARMCMP(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
@@ -532,11 +533,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
- } else if p.arch.Thechar == '7' && arch.IsARM64CMP(op) {
+ } else if p.arch.Family == sys.ARM64 && arch.IsARM64CMP(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
break
- } else if p.arch.Thechar == '0' {
+ } else if p.arch.Family == sys.MIPS64 {
if arch.IsMIPS64CMP(op) || arch.IsMIPS64MUL(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
@@ -546,12 +547,12 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.From = a[0]
prog.To = a[1]
case 3:
- switch p.arch.Thechar {
- case '0':
+ switch p.arch.Family {
+ case sys.MIPS64:
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
- case '5':
+ case sys.ARM:
// Special cases.
if arch.IsARMSTREX(op) {
/*
@@ -567,7 +568,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
- case '7':
+ case sys.ARM64:
// ARM64 instructions with one input and two outputs.
if arch.IsARM64STLXR(op) {
prog.From = a[0]
@@ -582,11 +583,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
- case '6', '8':
+ case sys.AMD64, sys.I386:
prog.From = a[0]
prog.From3 = newAddr(a[1])
prog.To = a[2]
- case '9':
+ case sys.PPC64:
if arch.IsPPC64CMP(op) {
// CMPW etc.; third argument is a CR register that goes into prog.Reg.
prog.From = a[0]
@@ -612,7 +613,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
p.errorf("invalid addressing modes for %s instruction", obj.Aconv(op))
return
}
- case 'z':
+ case sys.S390X:
if arch.IsS390xWithLength(op) || arch.IsS390xWithIndex(op) {
prog.From = a[1]
prog.From3 = newAddr(a[0])
@@ -626,7 +627,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
return
}
case 4:
- if p.arch.Thechar == '5' && arch.IsARMMULA(op) {
+ if p.arch.Family == sys.ARM && arch.IsARMMULA(op) {
// All must be registers.
p.getRegister(prog, op, &a[0])
r1 := p.getRegister(prog, op, &a[1])
@@ -639,14 +640,14 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.Reg = r1
break
}
- if p.arch.Thechar == '7' {
+ if p.arch.Family == sys.ARM64 {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.From3 = newAddr(a[2])
prog.To = a[3]
break
}
- if p.arch.Thechar == '9' && arch.IsPPC64RLD(op) {
+ if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) {
// 2nd operand must always be a register.
// TODO: Do we need to guard this with the instruction type?
// That is, are there 4-operand instructions without this property?
@@ -656,7 +657,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.To = a[3]
break
}
- if p.arch.Thechar == 'z' {
+ if p.arch.Family == sys.S390X {
prog.From = a[1]
prog.Reg = p.getRegister(prog, op, &a[2])
prog.From3 = newAddr(a[0])
@@ -666,7 +667,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
p.errorf("can't handle %s instruction with 4 operands", obj.Aconv(op))
return
case 5:
- if p.arch.Thechar == '9' && arch.IsPPC64RLD(op) {
+ if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) {
// Always reg, reg, con, con, reg. (con, con is a 'mask').
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
@@ -688,7 +689,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
p.errorf("can't handle %s instruction with 5 operands", obj.Aconv(op))
return
case 6:
- if p.arch.Thechar == '5' && arch.IsARMMRC(op) {
+ if p.arch.Family == sys.ARM && arch.IsARMMRC(op) {
// Strange special case: MCR, MRC.
prog.To.Type = obj.TYPE_CONST
x0 := p.getConstant(prog, op, &a[0])
diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go
index ee37439962..40206e6dc1 100644
--- a/src/cmd/asm/internal/asm/parse.go
+++ b/src/cmd/asm/internal/asm/parse.go
@@ -19,6 +19,7 @@ import (
"cmd/asm/internal/flags"
"cmd/asm/internal/lex"
"cmd/internal/obj"
+ "cmd/internal/sys"
)
type Parser struct {
@@ -130,7 +131,7 @@ func (p *Parser) line() bool {
for {
tok = p.lex.Next()
if len(operands) == 0 && len(items) == 0 {
- if (p.arch.Thechar == '5' || p.arch.Thechar == '7') && tok == '.' {
+ if p.arch.InFamily(sys.ARM, sys.ARM64) && tok == '.' {
// ARM conditionals.
tok = p.lex.Next()
str := p.lex.Text()
@@ -420,7 +421,7 @@ func (p *Parser) atStartOfRegister(name string) bool {
// We have consumed the register or R prefix.
func (p *Parser) atRegisterShift() bool {
// ARM only.
- if p.arch.Thechar != '5' {
+ if p.arch.Family != sys.ARM {
return false
}
// R1<<...
@@ -476,15 +477,14 @@ func (p *Parser) register(name string, prefix rune) (r1, r2 int16, scale int8, o
if c == ':' || c == ',' || c == '+' {
// 2nd register; syntax (R1+R2) etc. No two architectures agree.
// Check the architectures match the syntax.
- char := p.arch.Thechar
switch p.next().ScanToken {
case ',':
- if char != '5' && char != '7' {
+ if !p.arch.InFamily(sys.ARM, sys.ARM64) {
p.errorf("(register,register) not supported on this architecture")
return
}
case '+':
- if char != '9' {
+ if p.arch.Family != sys.PPC64 {
p.errorf("(register+register) not supported on this architecture")
return
}
@@ -649,7 +649,7 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
a.Reg = r1
if r2 != 0 {
// TODO: Consistency in the encoding would be nice here.
- if p.arch.Thechar == '5' || p.arch.Thechar == '7' {
+ if p.arch.InFamily(sys.ARM, sys.ARM64) {
// Special form
// ARM: destination register pair (R1, R2).
// ARM64: register pair (R1, R2) for LDP/STP.
@@ -662,7 +662,7 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
// Nothing may follow
return
}
- if p.arch.Thechar == '9' {
+ if p.arch.Family == sys.PPC64 {
// Special form for PPC64: (R1+R2); alias for (R1)(R2*1).
if prefix != 0 || scale != 0 {
p.errorf("illegal address mode for register+register")
@@ -752,7 +752,7 @@ ListLoop:
// register number is ARM-specific. It returns the number of the specified register.
func (p *Parser) registerNumber(name string) uint16 {
- if p.arch.Thechar == '5' && name == "g" {
+ if p.arch.Family == sys.ARM && name == "g" {
return 10
}
if name[0] != 'R' {