1
0
mirror of https://github.com/golang/go synced 2024-11-20 10:24:40 -07:00

[dev.cc] cmd/asm: add arch package

This package builds the representation of the machine architecture
for the new assembler.

Almost nothing in it is likely to last but this will get things running.

Change-Id: I8edd891f927a81f76d2dbdcd7484b9c87ac0fb2e
Reviewed-on: https://go-review.googlesource.com/3194
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Rob Pike 2015-01-22 10:46:50 -08:00
parent 67e7ded029
commit 6017f68029

View File

@ -0,0 +1,292 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package arch
import (
"cmd/internal/obj"
"cmd/internal/obj/i386" // == 386
"cmd/internal/obj/x86" // == amd64
)
// Pseudo-registers whose names are the constant name without the leading R.
const (
RFP = -(iota + 1)
RSB
RSP
RPC
)
// Arch wraps the link architecture object with more architecture-specific information.
type Arch struct {
*obj.LinkArch
D_INDIR int16 // TODO: why not in LinkArch?
D_CONST2 int16 // TODO: why not in LinkArch?
// Register number of hardware stack pointer.
SP int
// Encoding of non-address.
NoAddr obj.Addr
// Map of instruction names to enumeration.
Instructions map[string]int
// Map of register names to enumeration.
Registers map[string]int
// Map of pseudo-instructions (TEXT, DATA etc.) to enumeration.
Pseudos map[string]int
// Instructions that take one operand whose result is a destination.
UnaryDestination map[int]bool
}
// Set configures the architecture specified by GOARCH and returns its representation.
// It returns nil if GOARCH is not recognized.
func Set(GOARCH string) *Arch {
// TODO: Is this how to set this up?
switch GOARCH {
case "386":
return arch386()
case "amd64":
return archAmd64()
}
return nil
}
func arch386() *Arch {
noAddr := obj.Addr{
Type: x86.D_NONE,
Index: x86.D_NONE,
}
registers := make(map[string]int)
// Create maps for easy lookup of instruction names etc.
// TODO: Should this be done in obj for us?
for i, s := range i386.Register {
registers[s] = i
}
// Pseudo-registers.
registers["SB"] = RSB
registers["FP"] = RFP
registers["SP"] = RSP
registers["PC"] = RPC
instructions := make(map[string]int)
for i, s := range i386.Anames {
instructions[s] = i
}
// Annoying aliases.
instructions["JA"] = x86.AJHI
instructions["JAE"] = x86.AJCC
instructions["JB"] = x86.AJCS
instructions["JBE"] = x86.AJLS
instructions["JC"] = x86.AJCS
instructions["JE"] = x86.AJEQ
instructions["JG"] = x86.AJGT
instructions["JHS"] = x86.AJCC
instructions["JL"] = x86.AJLT
instructions["JLO"] = x86.AJCS
instructions["JNA"] = x86.AJLS
instructions["JNAE"] = x86.AJCS
instructions["JNB"] = x86.AJCC
instructions["JNBE"] = x86.AJHI
instructions["JNC"] = x86.AJCC
instructions["JNG"] = x86.AJLE
instructions["JNGE"] = x86.AJLT
instructions["JNL"] = x86.AJGE
instructions["JNLE"] = x86.AJGT
instructions["JNO"] = x86.AJOC
instructions["JNP"] = x86.AJPC
instructions["JNS"] = x86.AJPL
instructions["JNZ"] = x86.AJNE
instructions["JO"] = x86.AJOS
instructions["JP"] = x86.AJPS
instructions["JPE"] = x86.AJPS
instructions["JPO"] = x86.AJPC
instructions["JS"] = x86.AJMI
instructions["JZ"] = x86.AJEQ
instructions["MASKMOVDQU"] = x86.AMASKMOVOU
instructions["MOVOA"] = x86.AMOVO
instructions["MOVNTDQ"] = x86.AMOVNTO
pseudos := make(map[string]int) // TEXT, DATA etc.
pseudos["DATA"] = x86.ADATA
pseudos["FUNCDATA"] = x86.AFUNCDATA
pseudos["GLOBL"] = x86.AGLOBL
pseudos["PCDATA"] = x86.APCDATA
pseudos["TEXT"] = x86.ATEXT
unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
// These instructions write to prog.To.
unaryDestination[x86.ABSWAPL] = true
unaryDestination[x86.ACMPXCHG8B] = true
unaryDestination[x86.ADECB] = true
unaryDestination[x86.ADECL] = true
unaryDestination[x86.ADECW] = true
unaryDestination[x86.AINCB] = true
unaryDestination[x86.AINCL] = true
unaryDestination[x86.AINCW] = true
unaryDestination[x86.ANEGB] = true
unaryDestination[x86.ANEGL] = true
unaryDestination[x86.ANEGW] = true
unaryDestination[x86.ANOTB] = true
unaryDestination[x86.ANOTL] = true
unaryDestination[x86.ANOTW] = true
unaryDestination[x86.APOPL] = true
unaryDestination[x86.APOPW] = true
unaryDestination[x86.ASETCC] = true
unaryDestination[x86.ASETCS] = true
unaryDestination[x86.ASETEQ] = true
unaryDestination[x86.ASETGE] = true
unaryDestination[x86.ASETGT] = true
unaryDestination[x86.ASETHI] = true
unaryDestination[x86.ASETLE] = true
unaryDestination[x86.ASETLS] = true
unaryDestination[x86.ASETLT] = true
unaryDestination[x86.ASETMI] = true
unaryDestination[x86.ASETNE] = true
unaryDestination[x86.ASETOC] = true
unaryDestination[x86.ASETOS] = true
unaryDestination[x86.ASETPC] = true
unaryDestination[x86.ASETPL] = true
unaryDestination[x86.ASETPS] = true
unaryDestination[x86.AFFREE] = true
unaryDestination[x86.AFLDENV] = true
unaryDestination[x86.AFSAVE] = true
unaryDestination[x86.AFSTCW] = true
unaryDestination[x86.AFSTENV] = true
unaryDestination[x86.AFSTSW] = true
return &Arch{
LinkArch: &i386.Link386,
D_INDIR: i386.D_INDIR,
D_CONST2: i386.D_CONST2,
SP: i386.D_SP,
NoAddr: noAddr,
Instructions: instructions,
Registers: registers,
Pseudos: pseudos,
UnaryDestination: unaryDestination,
}
}
func archAmd64() *Arch {
noAddr := obj.Addr{
Type: x86.D_NONE,
Index: x86.D_NONE,
}
registers := make(map[string]int)
// Create maps for easy lookup of instruction names etc.
// TODO: Should this be done in obj for us?
for i, s := range x86.Register {
registers[s] = i
}
// Pseudo-registers.
registers["SB"] = RSB
registers["FP"] = RFP
registers["SP"] = RSP
registers["PC"] = RPC
instructions := make(map[string]int)
for i, s := range x86.Anames {
instructions[s] = i
}
// Annoying aliases.
instructions["JB"] = x86.AJCS
instructions["JC"] = x86.AJCS
instructions["JNAE"] = x86.AJCS
instructions["JLO"] = x86.AJCS
instructions["JAE"] = x86.AJCC
instructions["JNB"] = x86.AJCC
instructions["JNC"] = x86.AJCC
instructions["JHS"] = x86.AJCC
instructions["JE"] = x86.AJEQ
instructions["JZ"] = x86.AJEQ
instructions["JNZ"] = x86.AJNE
instructions["JBE"] = x86.AJLS
instructions["JNA"] = x86.AJLS
instructions["JA"] = x86.AJHI
instructions["JNBE"] = x86.AJHI
instructions["JS"] = x86.AJMI
instructions["JNS"] = x86.AJPL
instructions["JP"] = x86.AJPS
instructions["JPE"] = x86.AJPS
instructions["JNP"] = x86.AJPC
instructions["JPO"] = x86.AJPC
instructions["JL"] = x86.AJLT
instructions["JNGE"] = x86.AJLT
instructions["JNL"] = x86.AJGE
instructions["JNG"] = x86.AJLE
instructions["JG"] = x86.AJGT
instructions["JNLE"] = x86.AJGT
instructions["MASKMOVDQU"] = x86.AMASKMOVOU
instructions["MOVD"] = x86.AMOVQ
instructions["MOVDQ2Q"] = x86.AMOVQ
pseudos := make(map[string]int) // TEXT, DATA etc.
pseudos["DATA"] = x86.ADATA
pseudos["FUNCDATA"] = x86.AFUNCDATA
pseudos["GLOBL"] = x86.AGLOBL
pseudos["PCDATA"] = x86.APCDATA
pseudos["TEXT"] = x86.ATEXT
unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
// These instructions write to prog.To.
unaryDestination[x86.ABSWAPL] = true
unaryDestination[x86.ABSWAPQ] = true
unaryDestination[x86.ACMPXCHG8B] = true
unaryDestination[x86.ADECB] = true
unaryDestination[x86.ADECL] = true
unaryDestination[x86.ADECQ] = true
unaryDestination[x86.ADECW] = true
unaryDestination[x86.AINCB] = true
unaryDestination[x86.AINCL] = true
unaryDestination[x86.AINCQ] = true
unaryDestination[x86.AINCW] = true
unaryDestination[x86.ANEGB] = true
unaryDestination[x86.ANEGL] = true
unaryDestination[x86.ANEGQ] = true
unaryDestination[x86.ANEGW] = true
unaryDestination[x86.ANOTB] = true
unaryDestination[x86.ANOTL] = true
unaryDestination[x86.ANOTQ] = true
unaryDestination[x86.ANOTW] = true
unaryDestination[x86.APOPL] = true
unaryDestination[x86.APOPQ] = true
unaryDestination[x86.APOPW] = true
unaryDestination[x86.ASETCC] = true
unaryDestination[x86.ASETCS] = true
unaryDestination[x86.ASETEQ] = true
unaryDestination[x86.ASETGE] = true
unaryDestination[x86.ASETGT] = true
unaryDestination[x86.ASETHI] = true
unaryDestination[x86.ASETLE] = true
unaryDestination[x86.ASETLS] = true
unaryDestination[x86.ASETLT] = true
unaryDestination[x86.ASETMI] = true
unaryDestination[x86.ASETNE] = true
unaryDestination[x86.ASETOC] = true
unaryDestination[x86.ASETOS] = true
unaryDestination[x86.ASETPC] = true
unaryDestination[x86.ASETPL] = true
unaryDestination[x86.ASETPS] = true
unaryDestination[x86.AFFREE] = true
unaryDestination[x86.AFLDENV] = true
unaryDestination[x86.AFSAVE] = true
unaryDestination[x86.AFSTCW] = true
unaryDestination[x86.AFSTENV] = true
unaryDestination[x86.AFSTSW] = true
unaryDestination[x86.AFXSAVE] = true
unaryDestination[x86.AFXSAVE64] = true
unaryDestination[x86.ASTMXCSR] = true
return &Arch{
LinkArch: &x86.Linkamd64,
D_INDIR: x86.D_INDIR,
D_CONST2: x86.D_NONE,
SP: x86.D_SP,
NoAddr: noAddr,
Instructions: instructions,
Registers: registers,
Pseudos: pseudos,
UnaryDestination: unaryDestination,
}
}