mirror of
https://github.com/golang/go.git
synced 2025-05-29 03:11:26 +00:00
An editing error prevented the tables from being set up correctly. With that fixed, asm is now compatible with 8a. Change-Id: Ieb20e6dcaf4c05bd448ea748a010ee1f58ef4807 Reviewed-on: https://go-review.googlesource.com/3867 Reviewed-by: Russ Cox <rsc@golang.org>
293 lines
8.7 KiB
Go
293 lines
8.7 KiB
Go
// 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 int // TODO: why not in LinkArch?
|
|
D_CONST2 int // 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: i386.D_NONE,
|
|
Index: i386.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"] = i386.AJHI
|
|
instructions["JAE"] = i386.AJCC
|
|
instructions["JB"] = i386.AJCS
|
|
instructions["JBE"] = i386.AJLS
|
|
instructions["JC"] = i386.AJCS
|
|
instructions["JE"] = i386.AJEQ
|
|
instructions["JG"] = i386.AJGT
|
|
instructions["JHS"] = i386.AJCC
|
|
instructions["JL"] = i386.AJLT
|
|
instructions["JLO"] = i386.AJCS
|
|
instructions["JNA"] = i386.AJLS
|
|
instructions["JNAE"] = i386.AJCS
|
|
instructions["JNB"] = i386.AJCC
|
|
instructions["JNBE"] = i386.AJHI
|
|
instructions["JNC"] = i386.AJCC
|
|
instructions["JNG"] = i386.AJLE
|
|
instructions["JNGE"] = i386.AJLT
|
|
instructions["JNL"] = i386.AJGE
|
|
instructions["JNLE"] = i386.AJGT
|
|
instructions["JNO"] = i386.AJOC
|
|
instructions["JNP"] = i386.AJPC
|
|
instructions["JNS"] = i386.AJPL
|
|
instructions["JNZ"] = i386.AJNE
|
|
instructions["JO"] = i386.AJOS
|
|
instructions["JP"] = i386.AJPS
|
|
instructions["JPE"] = i386.AJPS
|
|
instructions["JPO"] = i386.AJPC
|
|
instructions["JS"] = i386.AJMI
|
|
instructions["JZ"] = i386.AJEQ
|
|
instructions["MASKMOVDQU"] = i386.AMASKMOVOU
|
|
instructions["MOVOA"] = i386.AMOVO
|
|
instructions["MOVNTDQ"] = i386.AMOVNTO
|
|
|
|
pseudos := make(map[string]int) // TEXT, DATA etc.
|
|
pseudos["DATA"] = i386.ADATA
|
|
pseudos["FUNCDATA"] = i386.AFUNCDATA
|
|
pseudos["GLOBL"] = i386.AGLOBL
|
|
pseudos["PCDATA"] = i386.APCDATA
|
|
pseudos["TEXT"] = i386.ATEXT
|
|
|
|
unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
|
|
// These instructions write to prog.To.
|
|
unaryDestination[i386.ABSWAPL] = true
|
|
unaryDestination[i386.ACMPXCHG8B] = true
|
|
unaryDestination[i386.ADECB] = true
|
|
unaryDestination[i386.ADECL] = true
|
|
unaryDestination[i386.ADECW] = true
|
|
unaryDestination[i386.AINCB] = true
|
|
unaryDestination[i386.AINCL] = true
|
|
unaryDestination[i386.AINCW] = true
|
|
unaryDestination[i386.ANEGB] = true
|
|
unaryDestination[i386.ANEGL] = true
|
|
unaryDestination[i386.ANEGW] = true
|
|
unaryDestination[i386.ANOTB] = true
|
|
unaryDestination[i386.ANOTL] = true
|
|
unaryDestination[i386.ANOTW] = true
|
|
unaryDestination[i386.APOPL] = true
|
|
unaryDestination[i386.APOPW] = true
|
|
unaryDestination[i386.ASETCC] = true
|
|
unaryDestination[i386.ASETCS] = true
|
|
unaryDestination[i386.ASETEQ] = true
|
|
unaryDestination[i386.ASETGE] = true
|
|
unaryDestination[i386.ASETGT] = true
|
|
unaryDestination[i386.ASETHI] = true
|
|
unaryDestination[i386.ASETLE] = true
|
|
unaryDestination[i386.ASETLS] = true
|
|
unaryDestination[i386.ASETLT] = true
|
|
unaryDestination[i386.ASETMI] = true
|
|
unaryDestination[i386.ASETNE] = true
|
|
unaryDestination[i386.ASETOC] = true
|
|
unaryDestination[i386.ASETOS] = true
|
|
unaryDestination[i386.ASETPC] = true
|
|
unaryDestination[i386.ASETPL] = true
|
|
unaryDestination[i386.ASETPS] = true
|
|
unaryDestination[i386.AFFREE] = true
|
|
unaryDestination[i386.AFLDENV] = true
|
|
unaryDestination[i386.AFSAVE] = true
|
|
unaryDestination[i386.AFSTCW] = true
|
|
unaryDestination[i386.AFSTENV] = true
|
|
unaryDestination[i386.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,
|
|
}
|
|
}
|