// 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/arm" "cmd/internal/obj/i386" // == 386 "cmd/internal/obj/ppc64" "cmd/internal/obj/x86" // == amd64 "fmt" ) // 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. 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) // Instruction is a jump. IsJump func(word string) bool // Aconv pretty-prints an instruction opcode for this architecture. Aconv func(int) string } // 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 } var Pseudos = map[string]int{ "DATA": obj.ADATA, "FUNCDATA": obj.AFUNCDATA, "GLOBL": obj.AGLOBL, "PCDATA": obj.APCDATA, "TEXT": obj.ATEXT, } // Set configures the architecture specified by GOARCH and returns its representation. // It returns nil if GOARCH is not recognized. func Set(GOARCH string) *Arch { switch GOARCH { case "386": return arch386() case "amd64": return archAmd64() case "amd64p32": a := archAmd64() a.LinkArch = &x86.Linkamd64p32 return a case "arm": return archArm() case "ppc64": a := archPPC64() a.LinkArch = &ppc64.Linkppc64 return a case "ppc64le": a := archPPC64() a.LinkArch = &ppc64.Linkppc64le return a } return nil } func jump386(word string) bool { return word[0] == 'J' || word == "CALL" } func arch386() *Arch { register := make(map[string]int16) // Create maps for easy lookup of instruction names etc. // TODO: Should this be done in obj for us? for i, s := range i386.Register { register[s] = int16(i + i386.REG_AL) } // Pseudo-registers. register["SB"] = RSB register["FP"] = RFP register["PC"] = RPC // Prefixes not used on this architecture. 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 return &Arch{ LinkArch: &i386.Link386, Instructions: instructions, Register: register, RegisterPrefix: nil, RegisterNumber: nilRegisterNumber, IsJump: jump386, Aconv: i386.Aconv, } } func archAmd64() *Arch { register := make(map[string]int16) // Create maps for easy lookup of instruction names etc. // TODO: Should this be done in obj for us? for i, s := range x86.Register { register[s] = int16(i + x86.REG_AL) } // Pseudo-registers. register["SB"] = RSB register["FP"] = RFP register["PC"] = RPC // Register prefix not used on this architecture. instructions := make(map[string]int) for i, s := range x86.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["MOVD"] = x86.AMOVQ instructions["MOVDQ2Q"] = x86.AMOVQ instructions["MOVNTDQ"] = x86.AMOVNTO instructions["MOVOA"] = x86.AMOVO instructions["MOVOA"] = x86.AMOVO instructions["PF2ID"] = x86.APF2IL instructions["PI2FD"] = x86.API2FL instructions["PSLLDQ"] = x86.APSLLO instructions["PSRLDQ"] = x86.APSRLO return &Arch{ LinkArch: &x86.Linkamd64, Instructions: instructions, Register: register, RegisterPrefix: nil, RegisterNumber: nilRegisterNumber, IsJump: jump386, Aconv: x86.Aconv, } } func archArm() *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. // TODO: Are there aliases we need to add? for i := arm.REG_R0; i < arm.REG_SPSR; i++ { register[obj.Rconv(i)] = int16(i) } // Avoid unintentionally clobbering g using R10. delete(register, "R10") register["g"] = arm.REG_R10 for i := 0; i < 16; i++ { register[fmt.Sprintf("C%d", i)] = int16(i) } // Pseudo-registers. register["SB"] = RSB register["FP"] = RFP register["PC"] = RPC register["SP"] = RSP registerPrefix := map[string]bool{ "F": true, "R": true, } instructions := make(map[string]int) for i, s := range arm.Anames { instructions[s] = i } // Annoying aliases. instructions["B"] = obj.AJMP instructions["BL"] = obj.ACALL return &Arch{ LinkArch: &arm.Linkarm, Instructions: instructions, Register: register, RegisterPrefix: registerPrefix, RegisterNumber: armRegisterNumber, IsJump: jumpArm, Aconv: arm.Aconv, } } 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++ { register[obj.Rconv(i)] = int16(i) } for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ { register[obj.Rconv(i)] = int16(i) } for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ { register[obj.Rconv(i)] = int16(i) } for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ { register[obj.Rconv(i)] = int16(i) } 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, IsJump: jumpPPC64, Aconv: ppc64.Aconv, } }