2015-01-22 10:46:50 -08:00
|
|
|
// 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"
|
2015-02-13 17:01:43 -08:00
|
|
|
"cmd/internal/obj/arm"
|
2015-01-22 10:46:50 -08:00
|
|
|
"cmd/internal/obj/i386" // == 386
|
2015-02-18 20:30:55 -08:00
|
|
|
"cmd/internal/obj/ppc64"
|
|
|
|
|
"cmd/internal/obj/x86" // == amd64
|
2015-02-13 17:01:43 -08:00
|
|
|
"fmt"
|
2015-01-22 10:46:50 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
// Map of instruction names to enumeration.
|
|
|
|
|
Instructions map[string]int
|
|
|
|
|
// Map of register names to enumeration.
|
2015-02-18 20:30:55 -08:00
|
|
|
Register map[string]int16
|
|
|
|
|
// Table of register prefix names. These are things like R for R(0) and SPR for SPR(268).
|
|
|
|
|
RegisterPrefix map[string]bool
|
|
|
|
|
// RegisterNumber converts R(10) into arm.REG_R10.
|
|
|
|
|
RegisterNumber func(string, int16) (int16, bool)
|
2015-01-22 10:46:50 -08:00
|
|
|
// Instructions that take one operand whose result is a destination.
|
|
|
|
|
UnaryDestination map[int]bool
|
2015-02-13 17:01:43 -08:00
|
|
|
// Instruction is a jump.
|
|
|
|
|
IsJump func(word string) bool
|
|
|
|
|
// Aconv pretty-prints an instruction opcode for this architecture.
|
|
|
|
|
Aconv func(int) string
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
|
2015-02-18 20:30:55 -08:00
|
|
|
// nilRegisterNumber is the register number function for architectures
|
|
|
|
|
// that do not accept the R(N) notation. It always returns failure.
|
|
|
|
|
func nilRegisterNumber(name string, n int16) (int16, bool) {
|
|
|
|
|
return 0, false
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 11:39:23 -08:00
|
|
|
var Pseudos = map[string]int{
|
|
|
|
|
"DATA": obj.ADATA,
|
|
|
|
|
"FUNCDATA": obj.AFUNCDATA,
|
|
|
|
|
"GLOBL": obj.AGLOBL,
|
|
|
|
|
"PCDATA": obj.APCDATA,
|
|
|
|
|
"TEXT": obj.ATEXT,
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-22 10:46:50 -08:00
|
|
|
// 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()
|
2015-02-13 17:01:43 -08:00
|
|
|
case "amd64p32":
|
|
|
|
|
a := archAmd64()
|
|
|
|
|
a.LinkArch = &x86.Linkamd64p32
|
|
|
|
|
return a
|
|
|
|
|
case "arm":
|
|
|
|
|
return archArm()
|
2015-02-18 20:30:55 -08:00
|
|
|
case "ppc64":
|
|
|
|
|
a := archPPC64()
|
|
|
|
|
a.LinkArch = &ppc64.Linkppc64
|
|
|
|
|
return a
|
2015-02-20 12:23:27 -05:00
|
|
|
case "ppc64le":
|
|
|
|
|
a := archPPC64()
|
|
|
|
|
a.LinkArch = &ppc64.Linkppc64le
|
|
|
|
|
return a
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 17:01:43 -08:00
|
|
|
func jump386(word string) bool {
|
|
|
|
|
return word[0] == 'J' || word == "CALL"
|
|
|
|
|
}
|
2015-01-22 10:46:50 -08:00
|
|
|
|
2015-02-13 17:01:43 -08:00
|
|
|
func arch386() *Arch {
|
2015-02-18 20:30:55 -08:00
|
|
|
register := make(map[string]int16)
|
2015-01-22 10:46:50 -08:00
|
|
|
// Create maps for easy lookup of instruction names etc.
|
|
|
|
|
// TODO: Should this be done in obj for us?
|
|
|
|
|
for i, s := range i386.Register {
|
2015-02-18 20:30:55 -08:00
|
|
|
register[s] = int16(i + i386.REG_AL)
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
// Pseudo-registers.
|
2015-02-18 20:30:55 -08:00
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
// Prefixes not used on this architecture.
|
2015-01-22 10:46:50 -08:00
|
|
|
|
|
|
|
|
instructions := make(map[string]int)
|
|
|
|
|
for i, s := range i386.Anames {
|
|
|
|
|
instructions[s] = i
|
|
|
|
|
}
|
|
|
|
|
// Annoying aliases.
|
2015-02-04 10:06:06 -08:00
|
|
|
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
|
2015-01-22 10:46:50 -08:00
|
|
|
|
|
|
|
|
unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
|
|
|
|
|
// These instructions write to prog.To.
|
2015-02-04 10:06:06 -08:00
|
|
|
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
|
2015-01-22 10:46:50 -08:00
|
|
|
|
|
|
|
|
return &Arch{
|
|
|
|
|
LinkArch: &i386.Link386,
|
|
|
|
|
Instructions: instructions,
|
2015-02-18 20:30:55 -08:00
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: nil,
|
|
|
|
|
RegisterNumber: nilRegisterNumber,
|
2015-01-22 10:46:50 -08:00
|
|
|
UnaryDestination: unaryDestination,
|
2015-02-13 17:01:43 -08:00
|
|
|
IsJump: jump386,
|
|
|
|
|
Aconv: i386.Aconv,
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func archAmd64() *Arch {
|
2015-02-18 20:30:55 -08:00
|
|
|
register := make(map[string]int16)
|
2015-01-22 10:46:50 -08:00
|
|
|
// Create maps for easy lookup of instruction names etc.
|
|
|
|
|
// TODO: Should this be done in obj for us?
|
|
|
|
|
for i, s := range x86.Register {
|
2015-02-18 20:30:55 -08:00
|
|
|
register[s] = int16(i + x86.REG_AL)
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
// Pseudo-registers.
|
2015-02-18 20:30:55 -08:00
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
// Register prefix not used on this architecture.
|
2015-01-22 10:46:50 -08:00
|
|
|
|
|
|
|
|
instructions := make(map[string]int)
|
|
|
|
|
for i, s := range x86.Anames {
|
|
|
|
|
instructions[s] = i
|
|
|
|
|
}
|
|
|
|
|
// Annoying aliases.
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JA"] = x86.AJHI
|
|
|
|
|
instructions["JAE"] = x86.AJCC
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["JB"] = x86.AJCS
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JBE"] = x86.AJLS
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["JC"] = x86.AJCS
|
|
|
|
|
instructions["JE"] = x86.AJEQ
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JG"] = x86.AJGT
|
|
|
|
|
instructions["JHS"] = x86.AJCC
|
|
|
|
|
instructions["JL"] = x86.AJLT
|
|
|
|
|
instructions["JLO"] = x86.AJCS
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["JNA"] = x86.AJLS
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JNAE"] = x86.AJCS
|
|
|
|
|
instructions["JNB"] = x86.AJCC
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["JNBE"] = x86.AJHI
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JNC"] = x86.AJCC
|
|
|
|
|
instructions["JNG"] = x86.AJLE
|
|
|
|
|
instructions["JNGE"] = x86.AJLT
|
|
|
|
|
instructions["JNL"] = x86.AJGE
|
|
|
|
|
instructions["JNLE"] = x86.AJGT
|
2015-02-24 12:30:39 -08:00
|
|
|
instructions["JNO"] = x86.AJOC
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JNP"] = x86.AJPC
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["JNS"] = x86.AJPL
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JNZ"] = x86.AJNE
|
2015-02-24 12:30:39 -08:00
|
|
|
instructions["JO"] = x86.AJOS
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["JP"] = x86.AJPS
|
|
|
|
|
instructions["JPE"] = x86.AJPS
|
|
|
|
|
instructions["JPO"] = x86.AJPC
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["JS"] = x86.AJMI
|
|
|
|
|
instructions["JZ"] = x86.AJEQ
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["MASKMOVDQU"] = x86.AMASKMOVOU
|
|
|
|
|
instructions["MOVD"] = x86.AMOVQ
|
|
|
|
|
instructions["MOVDQ2Q"] = x86.AMOVQ
|
2015-02-24 12:30:39 -08:00
|
|
|
instructions["MOVNTDQ"] = x86.AMOVNTO
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["MOVOA"] = x86.AMOVO
|
2015-02-24 12:30:39 -08:00
|
|
|
instructions["MOVOA"] = x86.AMOVO
|
|
|
|
|
instructions["PF2ID"] = x86.APF2IL
|
|
|
|
|
instructions["PI2FD"] = x86.API2FL
|
|
|
|
|
instructions["PSLLDQ"] = x86.APSLLO
|
|
|
|
|
instructions["PSRLDQ"] = x86.APSRLO
|
2015-01-22 10:46:50 -08:00
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
Instructions: instructions,
|
2015-02-18 20:30:55 -08:00
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: nil,
|
|
|
|
|
RegisterNumber: nilRegisterNumber,
|
2015-01-22 10:46:50 -08:00
|
|
|
UnaryDestination: unaryDestination,
|
2015-02-13 17:01:43 -08:00
|
|
|
IsJump: jump386,
|
|
|
|
|
Aconv: x86.Aconv,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func archArm() *Arch {
|
2015-02-18 20:30:55 -08:00
|
|
|
register := make(map[string]int16)
|
2015-02-13 17:01:43 -08:00
|
|
|
// Create maps for easy lookup of instruction names etc.
|
|
|
|
|
// TODO: Should this be done in obj for us?
|
|
|
|
|
// Note that there is no list of names as there is for 386 and amd64.
|
|
|
|
|
// TODO: Are there aliases we need to add?
|
|
|
|
|
for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-13 17:01:43 -08:00
|
|
|
}
|
|
|
|
|
// Avoid unintentionally clobbering g using R10.
|
2015-02-18 20:30:55 -08:00
|
|
|
delete(register, "R10")
|
|
|
|
|
register["g"] = arm.REG_R10
|
2015-02-13 17:01:43 -08:00
|
|
|
for i := 0; i < 16; i++ {
|
2015-02-18 20:30:55 -08:00
|
|
|
register[fmt.Sprintf("C%d", i)] = int16(i)
|
2015-02-13 17:01:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pseudo-registers.
|
2015-02-18 20:30:55 -08:00
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
register["SP"] = RSP
|
|
|
|
|
registerPrefix := map[string]bool{
|
|
|
|
|
"F": true,
|
|
|
|
|
"R": true,
|
|
|
|
|
}
|
2015-02-13 17:01:43 -08:00
|
|
|
|
|
|
|
|
instructions := make(map[string]int)
|
|
|
|
|
for i, s := range arm.Anames {
|
|
|
|
|
instructions[s] = i
|
|
|
|
|
}
|
|
|
|
|
// Annoying aliases.
|
|
|
|
|
instructions["B"] = obj.AJMP
|
|
|
|
|
instructions["BL"] = obj.ACALL
|
|
|
|
|
|
|
|
|
|
unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
|
|
|
|
|
// These instructions write to prog.To.
|
|
|
|
|
// TODO: These are silly. Fix once C assembler is gone.
|
|
|
|
|
unaryDestination[arm.ASWI] = true
|
|
|
|
|
unaryDestination[arm.AWORD] = true
|
|
|
|
|
|
|
|
|
|
return &Arch{
|
|
|
|
|
LinkArch: &arm.Linkarm,
|
|
|
|
|
Instructions: instructions,
|
2015-02-18 20:30:55 -08:00
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: registerPrefix,
|
|
|
|
|
RegisterNumber: armRegisterNumber,
|
2015-02-13 17:01:43 -08:00
|
|
|
UnaryDestination: unaryDestination,
|
|
|
|
|
IsJump: jumpArm,
|
|
|
|
|
Aconv: arm.Aconv,
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-02-18 20:30:55 -08:00
|
|
|
|
|
|
|
|
func archPPC64() *Arch {
|
|
|
|
|
register := make(map[string]int16)
|
|
|
|
|
// Create maps for easy lookup of instruction names etc.
|
|
|
|
|
// TODO: Should this be done in obj for us?
|
|
|
|
|
// Note that there is no list of names as there is for 386 and amd64.
|
|
|
|
|
for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
|
|
|
|
for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
|
|
|
|
for i := ppc64.REG_C0; i <= ppc64.REG_C7; i++ {
|
|
|
|
|
// TODO: Rconv prints these as C7 but the input syntax requires CR7.
|
|
|
|
|
register[fmt.Sprintf("CR%d", i-ppc64.REG_C0)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
|
|
|
|
register["CR"] = ppc64.REG_CR
|
|
|
|
|
register["XER"] = ppc64.REG_XER
|
|
|
|
|
register["LR"] = ppc64.REG_LR
|
|
|
|
|
register["CTR"] = ppc64.REG_CTR
|
|
|
|
|
register["FPSCR"] = ppc64.REG_FPSCR
|
|
|
|
|
register["MSR"] = ppc64.REG_MSR
|
|
|
|
|
// Pseudo-registers.
|
|
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
// Avoid unintentionally clobbering g using R30.
|
|
|
|
|
delete(register, "R30")
|
|
|
|
|
register["g"] = ppc64.REG_R30
|
|
|
|
|
registerPrefix := map[string]bool{
|
|
|
|
|
"CR": true,
|
|
|
|
|
"F": true,
|
|
|
|
|
"R": true,
|
|
|
|
|
"SPR": true,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
instructions := make(map[string]int)
|
|
|
|
|
for i, s := range ppc64.Anames {
|
|
|
|
|
instructions[s] = i
|
|
|
|
|
}
|
|
|
|
|
// Annoying aliases.
|
|
|
|
|
instructions["BR"] = ppc64.ABR
|
|
|
|
|
instructions["BL"] = ppc64.ABL
|
|
|
|
|
instructions["RETURN"] = ppc64.ARETURN
|
|
|
|
|
|
|
|
|
|
return &Arch{
|
|
|
|
|
LinkArch: &ppc64.Linkppc64,
|
|
|
|
|
Instructions: instructions,
|
|
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: registerPrefix,
|
|
|
|
|
RegisterNumber: ppc64RegisterNumber,
|
|
|
|
|
UnaryDestination: nil,
|
|
|
|
|
IsJump: jumpPPC64,
|
|
|
|
|
Aconv: ppc64.Aconv,
|
|
|
|
|
}
|
|
|
|
|
}
|