Home | History | Annotate | Download | only in arch
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package arch
      6 
      7 import (
      8 	"cmd/internal/obj"
      9 	"cmd/internal/obj/arm"
     10 	"cmd/internal/obj/arm64"
     11 	"cmd/internal/obj/ppc64"
     12 	"cmd/internal/obj/x86"
     13 	"fmt"
     14 	"strings"
     15 )
     16 
     17 // Pseudo-registers whose names are the constant name without the leading R.
     18 const (
     19 	RFP = -(iota + 1)
     20 	RSB
     21 	RSP
     22 	RPC
     23 )
     24 
     25 // Arch wraps the link architecture object with more architecture-specific information.
     26 type Arch struct {
     27 	*obj.LinkArch
     28 	// Map of instruction names to enumeration.
     29 	Instructions map[string]int
     30 	// Map of register names to enumeration.
     31 	Register map[string]int16
     32 	// Table of register prefix names. These are things like R for R(0) and SPR for SPR(268).
     33 	RegisterPrefix map[string]bool
     34 	// RegisterNumber converts R(10) into arm.REG_R10.
     35 	RegisterNumber func(string, int16) (int16, bool)
     36 	// Instruction is a jump.
     37 	IsJump func(word string) bool
     38 }
     39 
     40 // nilRegisterNumber is the register number function for architectures
     41 // that do not accept the R(N) notation. It always returns failure.
     42 func nilRegisterNumber(name string, n int16) (int16, bool) {
     43 	return 0, false
     44 }
     45 
     46 var Pseudos = map[string]int{
     47 	"DATA":     obj.ADATA,
     48 	"FUNCDATA": obj.AFUNCDATA,
     49 	"GLOBL":    obj.AGLOBL,
     50 	"PCDATA":   obj.APCDATA,
     51 	"TEXT":     obj.ATEXT,
     52 }
     53 
     54 // Set configures the architecture specified by GOARCH and returns its representation.
     55 // It returns nil if GOARCH is not recognized.
     56 func Set(GOARCH string) *Arch {
     57 	switch GOARCH {
     58 	case "386":
     59 		return archX86(&x86.Link386)
     60 	case "amd64":
     61 		return archX86(&x86.Linkamd64)
     62 	case "amd64p32":
     63 		return archX86(&x86.Linkamd64p32)
     64 	case "arm":
     65 		return archArm()
     66 	case "arm64":
     67 		return archArm64()
     68 	case "ppc64":
     69 		a := archPPC64()
     70 		a.LinkArch = &ppc64.Linkppc64
     71 		return a
     72 	case "ppc64le":
     73 		a := archPPC64()
     74 		a.LinkArch = &ppc64.Linkppc64le
     75 		return a
     76 	}
     77 	return nil
     78 }
     79 
     80 func jumpX86(word string) bool {
     81 	return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP")
     82 }
     83 
     84 func archX86(linkArch *obj.LinkArch) *Arch {
     85 	register := make(map[string]int16)
     86 	// Create maps for easy lookup of instruction names etc.
     87 	for i, s := range x86.Register {
     88 		register[s] = int16(i + x86.REG_AL)
     89 	}
     90 	// Pseudo-registers.
     91 	register["SB"] = RSB
     92 	register["FP"] = RFP
     93 	register["PC"] = RPC
     94 	// Register prefix not used on this architecture.
     95 
     96 	instructions := make(map[string]int)
     97 	for i, s := range obj.Anames {
     98 		instructions[s] = i
     99 	}
    100 	for i, s := range x86.Anames {
    101 		if i >= obj.A_ARCHSPECIFIC {
    102 			instructions[s] = i + obj.ABaseAMD64
    103 		}
    104 	}
    105 	// Annoying aliases.
    106 	instructions["JA"] = x86.AJHI   /* alternate */
    107 	instructions["JAE"] = x86.AJCC  /* alternate */
    108 	instructions["JB"] = x86.AJCS   /* alternate */
    109 	instructions["JBE"] = x86.AJLS  /* alternate */
    110 	instructions["JC"] = x86.AJCS   /* alternate */
    111 	instructions["JCC"] = x86.AJCC  /* carry clear (CF = 0) */
    112 	instructions["JCS"] = x86.AJCS  /* carry set (CF = 1) */
    113 	instructions["JE"] = x86.AJEQ   /* alternate */
    114 	instructions["JEQ"] = x86.AJEQ  /* equal (ZF = 1) */
    115 	instructions["JG"] = x86.AJGT   /* alternate */
    116 	instructions["JGE"] = x86.AJGE  /* greater than or equal (signed) (SF = OF) */
    117 	instructions["JGT"] = x86.AJGT  /* greater than (signed) (ZF = 0 && SF = OF) */
    118 	instructions["JHI"] = x86.AJHI  /* higher (unsigned) (CF = 0 && ZF = 0) */
    119 	instructions["JHS"] = x86.AJCC  /* alternate */
    120 	instructions["JL"] = x86.AJLT   /* alternate */
    121 	instructions["JLE"] = x86.AJLE  /* less than or equal (signed) (ZF = 1 || SF != OF) */
    122 	instructions["JLO"] = x86.AJCS  /* alternate */
    123 	instructions["JLS"] = x86.AJLS  /* lower or same (unsigned) (CF = 1 || ZF = 1) */
    124 	instructions["JLT"] = x86.AJLT  /* less than (signed) (SF != OF) */
    125 	instructions["JMI"] = x86.AJMI  /* negative (minus) (SF = 1) */
    126 	instructions["JNA"] = x86.AJLS  /* alternate */
    127 	instructions["JNAE"] = x86.AJCS /* alternate */
    128 	instructions["JNB"] = x86.AJCC  /* alternate */
    129 	instructions["JNBE"] = x86.AJHI /* alternate */
    130 	instructions["JNC"] = x86.AJCC  /* alternate */
    131 	instructions["JNE"] = x86.AJNE  /* not equal (ZF = 0) */
    132 	instructions["JNG"] = x86.AJLE  /* alternate */
    133 	instructions["JNGE"] = x86.AJLT /* alternate */
    134 	instructions["JNL"] = x86.AJGE  /* alternate */
    135 	instructions["JNLE"] = x86.AJGT /* alternate */
    136 	instructions["JNO"] = x86.AJOC  /* alternate */
    137 	instructions["JNP"] = x86.AJPC  /* alternate */
    138 	instructions["JNS"] = x86.AJPL  /* alternate */
    139 	instructions["JNZ"] = x86.AJNE  /* alternate */
    140 	instructions["JO"] = x86.AJOS   /* alternate */
    141 	instructions["JOC"] = x86.AJOC  /* overflow clear (OF = 0) */
    142 	instructions["JOS"] = x86.AJOS  /* overflow set (OF = 1) */
    143 	instructions["JP"] = x86.AJPS   /* alternate */
    144 	instructions["JPC"] = x86.AJPC  /* parity clear (PF = 0) */
    145 	instructions["JPE"] = x86.AJPS  /* alternate */
    146 	instructions["JPL"] = x86.AJPL  /* non-negative (plus) (SF = 0) */
    147 	instructions["JPO"] = x86.AJPC  /* alternate */
    148 	instructions["JPS"] = x86.AJPS  /* parity set (PF = 1) */
    149 	instructions["JS"] = x86.AJMI   /* alternate */
    150 	instructions["JZ"] = x86.AJEQ   /* alternate */
    151 	instructions["MASKMOVDQU"] = x86.AMASKMOVOU
    152 	instructions["MOVD"] = x86.AMOVQ
    153 	instructions["MOVDQ2Q"] = x86.AMOVQ
    154 	instructions["MOVNTDQ"] = x86.AMOVNTO
    155 	instructions["MOVOA"] = x86.AMOVO
    156 	instructions["MOVOA"] = x86.AMOVO
    157 	instructions["PF2ID"] = x86.APF2IL
    158 	instructions["PI2FD"] = x86.API2FL
    159 	instructions["PSLLDQ"] = x86.APSLLO
    160 	instructions["PSRLDQ"] = x86.APSRLO
    161 
    162 	return &Arch{
    163 		LinkArch:       linkArch,
    164 		Instructions:   instructions,
    165 		Register:       register,
    166 		RegisterPrefix: nil,
    167 		RegisterNumber: nilRegisterNumber,
    168 		IsJump:         jumpX86,
    169 	}
    170 }
    171 
    172 func archArm() *Arch {
    173 	register := make(map[string]int16)
    174 	// Create maps for easy lookup of instruction names etc.
    175 	// Note that there is no list of names as there is for x86.
    176 	for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
    177 		register[obj.Rconv(i)] = int16(i)
    178 	}
    179 	// Avoid unintentionally clobbering g using R10.
    180 	delete(register, "R10")
    181 	register["g"] = arm.REG_R10
    182 	for i := 0; i < 16; i++ {
    183 		register[fmt.Sprintf("C%d", i)] = int16(i)
    184 	}
    185 
    186 	// Pseudo-registers.
    187 	register["SB"] = RSB
    188 	register["FP"] = RFP
    189 	register["PC"] = RPC
    190 	register["SP"] = RSP
    191 	registerPrefix := map[string]bool{
    192 		"F": true,
    193 		"R": true,
    194 	}
    195 
    196 	instructions := make(map[string]int)
    197 	for i, s := range obj.Anames {
    198 		instructions[s] = i
    199 	}
    200 	for i, s := range arm.Anames {
    201 		if i >= obj.A_ARCHSPECIFIC {
    202 			instructions[s] = i + obj.ABaseARM
    203 		}
    204 	}
    205 	// Annoying aliases.
    206 	instructions["B"] = obj.AJMP
    207 	instructions["BL"] = obj.ACALL
    208 	// MCR differs from MRC by the way fields of the word are encoded.
    209 	// (Details in arm.go). Here we add the instruction so parse will find
    210 	// it, but give it an opcode number known only to us.
    211 	instructions["MCR"] = aMCR
    212 
    213 	return &Arch{
    214 		LinkArch:       &arm.Linkarm,
    215 		Instructions:   instructions,
    216 		Register:       register,
    217 		RegisterPrefix: registerPrefix,
    218 		RegisterNumber: armRegisterNumber,
    219 		IsJump:         jumpArm,
    220 	}
    221 }
    222 
    223 func archArm64() *Arch {
    224 	register := make(map[string]int16)
    225 	// Create maps for easy lookup of instruction names etc.
    226 	// Note that there is no list of names as there is for 386 and amd64.
    227 	register[arm64.Rconv(arm64.REGSP)] = int16(arm64.REGSP)
    228 	for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
    229 		register[arm64.Rconv(i)] = int16(i)
    230 	}
    231 	for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
    232 		register[arm64.Rconv(i)] = int16(i)
    233 	}
    234 	for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
    235 		register[arm64.Rconv(i)] = int16(i)
    236 	}
    237 	register["LR"] = arm64.REGLINK
    238 	register["DAIF"] = arm64.REG_DAIF
    239 	register["NZCV"] = arm64.REG_NZCV
    240 	register["FPSR"] = arm64.REG_FPSR
    241 	register["FPCR"] = arm64.REG_FPCR
    242 	register["SPSR_EL1"] = arm64.REG_SPSR_EL1
    243 	register["ELR_EL1"] = arm64.REG_ELR_EL1
    244 	register["SPSR_EL2"] = arm64.REG_SPSR_EL2
    245 	register["ELR_EL2"] = arm64.REG_ELR_EL2
    246 	register["CurrentEL"] = arm64.REG_CurrentEL
    247 	register["SP_EL0"] = arm64.REG_SP_EL0
    248 	register["SPSel"] = arm64.REG_SPSel
    249 	register["DAIFSet"] = arm64.REG_DAIFSet
    250 	register["DAIFClr"] = arm64.REG_DAIFClr
    251 	// Conditional operators, like EQ, NE, etc.
    252 	register["EQ"] = arm64.COND_EQ
    253 	register["NE"] = arm64.COND_NE
    254 	register["HS"] = arm64.COND_HS
    255 	register["LO"] = arm64.COND_LO
    256 	register["MI"] = arm64.COND_MI
    257 	register["PL"] = arm64.COND_PL
    258 	register["VS"] = arm64.COND_VS
    259 	register["VC"] = arm64.COND_VC
    260 	register["HI"] = arm64.COND_HI
    261 	register["LS"] = arm64.COND_LS
    262 	register["GE"] = arm64.COND_GE
    263 	register["LT"] = arm64.COND_LT
    264 	register["GT"] = arm64.COND_GT
    265 	register["LE"] = arm64.COND_LE
    266 	register["AL"] = arm64.COND_AL
    267 	register["NV"] = arm64.COND_NV
    268 	// Pseudo-registers.
    269 	register["SB"] = RSB
    270 	register["FP"] = RFP
    271 	register["PC"] = RPC
    272 	register["SP"] = RSP
    273 	// Avoid unintentionally clobbering g using R28.
    274 	delete(register, "R28")
    275 	register["g"] = arm64.REG_R28
    276 	registerPrefix := map[string]bool{
    277 		"F": true,
    278 		"R": true,
    279 		"V": true,
    280 	}
    281 
    282 	instructions := make(map[string]int)
    283 	for i, s := range obj.Anames {
    284 		instructions[s] = i
    285 	}
    286 	for i, s := range arm64.Anames {
    287 		if i >= obj.A_ARCHSPECIFIC {
    288 			instructions[s] = i + obj.ABaseARM64
    289 		}
    290 	}
    291 	// Annoying aliases.
    292 	instructions["B"] = arm64.AB
    293 	instructions["BL"] = arm64.ABL
    294 
    295 	return &Arch{
    296 		LinkArch:       &arm64.Linkarm64,
    297 		Instructions:   instructions,
    298 		Register:       register,
    299 		RegisterPrefix: registerPrefix,
    300 		RegisterNumber: arm64RegisterNumber,
    301 		IsJump:         jumpArm64,
    302 	}
    303 
    304 }
    305 
    306 func archPPC64() *Arch {
    307 	register := make(map[string]int16)
    308 	// Create maps for easy lookup of instruction names etc.
    309 	// Note that there is no list of names as there is for x86.
    310 	for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
    311 		register[obj.Rconv(i)] = int16(i)
    312 	}
    313 	for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
    314 		register[obj.Rconv(i)] = int16(i)
    315 	}
    316 	for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
    317 		register[obj.Rconv(i)] = int16(i)
    318 	}
    319 	for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
    320 		register[obj.Rconv(i)] = int16(i)
    321 	}
    322 	register["CR"] = ppc64.REG_CR
    323 	register["XER"] = ppc64.REG_XER
    324 	register["LR"] = ppc64.REG_LR
    325 	register["CTR"] = ppc64.REG_CTR
    326 	register["FPSCR"] = ppc64.REG_FPSCR
    327 	register["MSR"] = ppc64.REG_MSR
    328 	// Pseudo-registers.
    329 	register["SB"] = RSB
    330 	register["FP"] = RFP
    331 	register["PC"] = RPC
    332 	// Avoid unintentionally clobbering g using R30.
    333 	delete(register, "R30")
    334 	register["g"] = ppc64.REG_R30
    335 	registerPrefix := map[string]bool{
    336 		"CR":  true,
    337 		"F":   true,
    338 		"R":   true,
    339 		"SPR": true,
    340 	}
    341 
    342 	instructions := make(map[string]int)
    343 	for i, s := range obj.Anames {
    344 		instructions[s] = i
    345 	}
    346 	for i, s := range ppc64.Anames {
    347 		if i >= obj.A_ARCHSPECIFIC {
    348 			instructions[s] = i + obj.ABasePPC64
    349 		}
    350 	}
    351 	// Annoying aliases.
    352 	instructions["BR"] = ppc64.ABR
    353 	instructions["BL"] = ppc64.ABL
    354 
    355 	return &Arch{
    356 		LinkArch:       &ppc64.Linkppc64,
    357 		Instructions:   instructions,
    358 		Register:       register,
    359 		RegisterPrefix: registerPrefix,
    360 		RegisterNumber: ppc64RegisterNumber,
    361 		IsJump:         jumpPPC64,
    362 	}
    363 }
    364