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/mips"
     12 	"cmd/internal/obj/ppc64"
     13 	"cmd/internal/obj/s390x"
     14 	"cmd/internal/obj/x86"
     15 	"fmt"
     16 	"strings"
     17 )
     18 
     19 // Pseudo-registers whose names are the constant name without the leading R.
     20 const (
     21 	RFP = -(iota + 1)
     22 	RSB
     23 	RSP
     24 	RPC
     25 )
     26 
     27 // Arch wraps the link architecture object with more architecture-specific information.
     28 type Arch struct {
     29 	*obj.LinkArch
     30 	// Map of instruction names to enumeration.
     31 	Instructions map[string]obj.As
     32 	// Map of register names to enumeration.
     33 	Register map[string]int16
     34 	// Table of register prefix names. These are things like R for R(0) and SPR for SPR(268).
     35 	RegisterPrefix map[string]bool
     36 	// RegisterNumber converts R(10) into arm.REG_R10.
     37 	RegisterNumber func(string, int16) (int16, bool)
     38 	// Instruction is a jump.
     39 	IsJump func(word string) bool
     40 }
     41 
     42 // nilRegisterNumber is the register number function for architectures
     43 // that do not accept the R(N) notation. It always returns failure.
     44 func nilRegisterNumber(name string, n int16) (int16, bool) {
     45 	return 0, false
     46 }
     47 
     48 // Set configures the architecture specified by GOARCH and returns its representation.
     49 // It returns nil if GOARCH is not recognized.
     50 func Set(GOARCH string) *Arch {
     51 	switch GOARCH {
     52 	case "386":
     53 		return archX86(&x86.Link386)
     54 	case "amd64":
     55 		return archX86(&x86.Linkamd64)
     56 	case "amd64p32":
     57 		return archX86(&x86.Linkamd64p32)
     58 	case "arm":
     59 		return archArm()
     60 	case "arm64":
     61 		return archArm64()
     62 	case "mips":
     63 		a := archMips()
     64 		a.LinkArch = &mips.Linkmips
     65 		return a
     66 	case "mipsle":
     67 		a := archMips()
     68 		a.LinkArch = &mips.Linkmipsle
     69 		return a
     70 	case "mips64":
     71 		a := archMips64()
     72 		a.LinkArch = &mips.Linkmips64
     73 		return a
     74 	case "mips64le":
     75 		a := archMips64()
     76 		a.LinkArch = &mips.Linkmips64le
     77 		return a
     78 	case "ppc64":
     79 		a := archPPC64()
     80 		a.LinkArch = &ppc64.Linkppc64
     81 		return a
     82 	case "ppc64le":
     83 		a := archPPC64()
     84 		a.LinkArch = &ppc64.Linkppc64le
     85 		return a
     86 	case "s390x":
     87 		a := archS390x()
     88 		a.LinkArch = &s390x.Links390x
     89 		return a
     90 	}
     91 	return nil
     92 }
     93 
     94 func jumpX86(word string) bool {
     95 	return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN"
     96 }
     97 
     98 func archX86(linkArch *obj.LinkArch) *Arch {
     99 	register := make(map[string]int16)
    100 	// Create maps for easy lookup of instruction names etc.
    101 	for i, s := range x86.Register {
    102 		register[s] = int16(i + x86.REG_AL)
    103 	}
    104 	// Pseudo-registers.
    105 	register["SB"] = RSB
    106 	register["FP"] = RFP
    107 	register["PC"] = RPC
    108 	// Register prefix not used on this architecture.
    109 
    110 	instructions := make(map[string]obj.As)
    111 	for i, s := range obj.Anames {
    112 		instructions[s] = obj.As(i)
    113 	}
    114 	for i, s := range x86.Anames {
    115 		if obj.As(i) >= obj.A_ARCHSPECIFIC {
    116 			instructions[s] = obj.As(i) + obj.ABaseAMD64
    117 		}
    118 	}
    119 	// Annoying aliases.
    120 	instructions["JA"] = x86.AJHI   /* alternate */
    121 	instructions["JAE"] = x86.AJCC  /* alternate */
    122 	instructions["JB"] = x86.AJCS   /* alternate */
    123 	instructions["JBE"] = x86.AJLS  /* alternate */
    124 	instructions["JC"] = x86.AJCS   /* alternate */
    125 	instructions["JCC"] = x86.AJCC  /* carry clear (CF = 0) */
    126 	instructions["JCS"] = x86.AJCS  /* carry set (CF = 1) */
    127 	instructions["JE"] = x86.AJEQ   /* alternate */
    128 	instructions["JEQ"] = x86.AJEQ  /* equal (ZF = 1) */
    129 	instructions["JG"] = x86.AJGT   /* alternate */
    130 	instructions["JGE"] = x86.AJGE  /* greater than or equal (signed) (SF = OF) */
    131 	instructions["JGT"] = x86.AJGT  /* greater than (signed) (ZF = 0 && SF = OF) */
    132 	instructions["JHI"] = x86.AJHI  /* higher (unsigned) (CF = 0 && ZF = 0) */
    133 	instructions["JHS"] = x86.AJCC  /* alternate */
    134 	instructions["JL"] = x86.AJLT   /* alternate */
    135 	instructions["JLE"] = x86.AJLE  /* less than or equal (signed) (ZF = 1 || SF != OF) */
    136 	instructions["JLO"] = x86.AJCS  /* alternate */
    137 	instructions["JLS"] = x86.AJLS  /* lower or same (unsigned) (CF = 1 || ZF = 1) */
    138 	instructions["JLT"] = x86.AJLT  /* less than (signed) (SF != OF) */
    139 	instructions["JMI"] = x86.AJMI  /* negative (minus) (SF = 1) */
    140 	instructions["JNA"] = x86.AJLS  /* alternate */
    141 	instructions["JNAE"] = x86.AJCS /* alternate */
    142 	instructions["JNB"] = x86.AJCC  /* alternate */
    143 	instructions["JNBE"] = x86.AJHI /* alternate */
    144 	instructions["JNC"] = x86.AJCC  /* alternate */
    145 	instructions["JNE"] = x86.AJNE  /* not equal (ZF = 0) */
    146 	instructions["JNG"] = x86.AJLE  /* alternate */
    147 	instructions["JNGE"] = x86.AJLT /* alternate */
    148 	instructions["JNL"] = x86.AJGE  /* alternate */
    149 	instructions["JNLE"] = x86.AJGT /* alternate */
    150 	instructions["JNO"] = x86.AJOC  /* alternate */
    151 	instructions["JNP"] = x86.AJPC  /* alternate */
    152 	instructions["JNS"] = x86.AJPL  /* alternate */
    153 	instructions["JNZ"] = x86.AJNE  /* alternate */
    154 	instructions["JO"] = x86.AJOS   /* alternate */
    155 	instructions["JOC"] = x86.AJOC  /* overflow clear (OF = 0) */
    156 	instructions["JOS"] = x86.AJOS  /* overflow set (OF = 1) */
    157 	instructions["JP"] = x86.AJPS   /* alternate */
    158 	instructions["JPC"] = x86.AJPC  /* parity clear (PF = 0) */
    159 	instructions["JPE"] = x86.AJPS  /* alternate */
    160 	instructions["JPL"] = x86.AJPL  /* non-negative (plus) (SF = 0) */
    161 	instructions["JPO"] = x86.AJPC  /* alternate */
    162 	instructions["JPS"] = x86.AJPS  /* parity set (PF = 1) */
    163 	instructions["JS"] = x86.AJMI   /* alternate */
    164 	instructions["JZ"] = x86.AJEQ   /* alternate */
    165 	instructions["MASKMOVDQU"] = x86.AMASKMOVOU
    166 	instructions["MOVD"] = x86.AMOVQ
    167 	instructions["MOVDQ2Q"] = x86.AMOVQ
    168 	instructions["MOVNTDQ"] = x86.AMOVNTO
    169 	instructions["MOVOA"] = x86.AMOVO
    170 	instructions["PSLLDQ"] = x86.APSLLO
    171 	instructions["PSRLDQ"] = x86.APSRLO
    172 	instructions["PADDD"] = x86.APADDL
    173 
    174 	return &Arch{
    175 		LinkArch:       linkArch,
    176 		Instructions:   instructions,
    177 		Register:       register,
    178 		RegisterPrefix: nil,
    179 		RegisterNumber: nilRegisterNumber,
    180 		IsJump:         jumpX86,
    181 	}
    182 }
    183 
    184 func archArm() *Arch {
    185 	register := make(map[string]int16)
    186 	// Create maps for easy lookup of instruction names etc.
    187 	// Note that there is no list of names as there is for x86.
    188 	for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
    189 		register[obj.Rconv(i)] = int16(i)
    190 	}
    191 	// Avoid unintentionally clobbering g using R10.
    192 	delete(register, "R10")
    193 	register["g"] = arm.REG_R10
    194 	for i := 0; i < 16; i++ {
    195 		register[fmt.Sprintf("C%d", i)] = int16(i)
    196 	}
    197 
    198 	// Pseudo-registers.
    199 	register["SB"] = RSB
    200 	register["FP"] = RFP
    201 	register["PC"] = RPC
    202 	register["SP"] = RSP
    203 	registerPrefix := map[string]bool{
    204 		"F": true,
    205 		"R": true,
    206 	}
    207 
    208 	instructions := make(map[string]obj.As)
    209 	for i, s := range obj.Anames {
    210 		instructions[s] = obj.As(i)
    211 	}
    212 	for i, s := range arm.Anames {
    213 		if obj.As(i) >= obj.A_ARCHSPECIFIC {
    214 			instructions[s] = obj.As(i) + obj.ABaseARM
    215 		}
    216 	}
    217 	// Annoying aliases.
    218 	instructions["B"] = obj.AJMP
    219 	instructions["BL"] = obj.ACALL
    220 	// MCR differs from MRC by the way fields of the word are encoded.
    221 	// (Details in arm.go). Here we add the instruction so parse will find
    222 	// it, but give it an opcode number known only to us.
    223 	instructions["MCR"] = aMCR
    224 
    225 	return &Arch{
    226 		LinkArch:       &arm.Linkarm,
    227 		Instructions:   instructions,
    228 		Register:       register,
    229 		RegisterPrefix: registerPrefix,
    230 		RegisterNumber: armRegisterNumber,
    231 		IsJump:         jumpArm,
    232 	}
    233 }
    234 
    235 func archArm64() *Arch {
    236 	register := make(map[string]int16)
    237 	// Create maps for easy lookup of instruction names etc.
    238 	// Note that there is no list of names as there is for 386 and amd64.
    239 	register[arm64.Rconv(arm64.REGSP)] = int16(arm64.REGSP)
    240 	for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
    241 		register[arm64.Rconv(i)] = int16(i)
    242 	}
    243 	for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
    244 		register[arm64.Rconv(i)] = int16(i)
    245 	}
    246 	for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
    247 		register[arm64.Rconv(i)] = int16(i)
    248 	}
    249 	register["LR"] = arm64.REGLINK
    250 	register["DAIF"] = arm64.REG_DAIF
    251 	register["NZCV"] = arm64.REG_NZCV
    252 	register["FPSR"] = arm64.REG_FPSR
    253 	register["FPCR"] = arm64.REG_FPCR
    254 	register["SPSR_EL1"] = arm64.REG_SPSR_EL1
    255 	register["ELR_EL1"] = arm64.REG_ELR_EL1
    256 	register["SPSR_EL2"] = arm64.REG_SPSR_EL2
    257 	register["ELR_EL2"] = arm64.REG_ELR_EL2
    258 	register["CurrentEL"] = arm64.REG_CurrentEL
    259 	register["SP_EL0"] = arm64.REG_SP_EL0
    260 	register["SPSel"] = arm64.REG_SPSel
    261 	register["DAIFSet"] = arm64.REG_DAIFSet
    262 	register["DAIFClr"] = arm64.REG_DAIFClr
    263 	// Conditional operators, like EQ, NE, etc.
    264 	register["EQ"] = arm64.COND_EQ
    265 	register["NE"] = arm64.COND_NE
    266 	register["HS"] = arm64.COND_HS
    267 	register["CS"] = arm64.COND_HS
    268 	register["LO"] = arm64.COND_LO
    269 	register["CC"] = arm64.COND_LO
    270 	register["MI"] = arm64.COND_MI
    271 	register["PL"] = arm64.COND_PL
    272 	register["VS"] = arm64.COND_VS
    273 	register["VC"] = arm64.COND_VC
    274 	register["HI"] = arm64.COND_HI
    275 	register["LS"] = arm64.COND_LS
    276 	register["GE"] = arm64.COND_GE
    277 	register["LT"] = arm64.COND_LT
    278 	register["GT"] = arm64.COND_GT
    279 	register["LE"] = arm64.COND_LE
    280 	register["AL"] = arm64.COND_AL
    281 	register["NV"] = arm64.COND_NV
    282 	// Pseudo-registers.
    283 	register["SB"] = RSB
    284 	register["FP"] = RFP
    285 	register["PC"] = RPC
    286 	register["SP"] = RSP
    287 	// Avoid unintentionally clobbering g using R28.
    288 	delete(register, "R28")
    289 	register["g"] = arm64.REG_R28
    290 	registerPrefix := map[string]bool{
    291 		"F": true,
    292 		"R": true,
    293 		"V": true,
    294 	}
    295 
    296 	instructions := make(map[string]obj.As)
    297 	for i, s := range obj.Anames {
    298 		instructions[s] = obj.As(i)
    299 	}
    300 	for i, s := range arm64.Anames {
    301 		if obj.As(i) >= obj.A_ARCHSPECIFIC {
    302 			instructions[s] = obj.As(i) + obj.ABaseARM64
    303 		}
    304 	}
    305 	// Annoying aliases.
    306 	instructions["B"] = arm64.AB
    307 	instructions["BL"] = arm64.ABL
    308 
    309 	return &Arch{
    310 		LinkArch:       &arm64.Linkarm64,
    311 		Instructions:   instructions,
    312 		Register:       register,
    313 		RegisterPrefix: registerPrefix,
    314 		RegisterNumber: arm64RegisterNumber,
    315 		IsJump:         jumpArm64,
    316 	}
    317 
    318 }
    319 
    320 func archPPC64() *Arch {
    321 	register := make(map[string]int16)
    322 	// Create maps for easy lookup of instruction names etc.
    323 	// Note that there is no list of names as there is for x86.
    324 	for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
    325 		register[obj.Rconv(i)] = int16(i)
    326 	}
    327 	for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
    328 		register[obj.Rconv(i)] = int16(i)
    329 	}
    330 	for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ {
    331 		register[obj.Rconv(i)] = int16(i)
    332 	}
    333 	for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ {
    334 		register[obj.Rconv(i)] = int16(i)
    335 	}
    336 	for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
    337 		register[obj.Rconv(i)] = int16(i)
    338 	}
    339 	for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
    340 		register[obj.Rconv(i)] = int16(i)
    341 	}
    342 	register["CR"] = ppc64.REG_CR
    343 	register["XER"] = ppc64.REG_XER
    344 	register["LR"] = ppc64.REG_LR
    345 	register["CTR"] = ppc64.REG_CTR
    346 	register["FPSCR"] = ppc64.REG_FPSCR
    347 	register["MSR"] = ppc64.REG_MSR
    348 	// Pseudo-registers.
    349 	register["SB"] = RSB
    350 	register["FP"] = RFP
    351 	register["PC"] = RPC
    352 	// Avoid unintentionally clobbering g using R30.
    353 	delete(register, "R30")
    354 	register["g"] = ppc64.REG_R30
    355 	registerPrefix := map[string]bool{
    356 		"CR":  true,
    357 		"F":   true,
    358 		"R":   true,
    359 		"SPR": true,
    360 	}
    361 
    362 	instructions := make(map[string]obj.As)
    363 	for i, s := range obj.Anames {
    364 		instructions[s] = obj.As(i)
    365 	}
    366 	for i, s := range ppc64.Anames {
    367 		if obj.As(i) >= obj.A_ARCHSPECIFIC {
    368 			instructions[s] = obj.As(i) + obj.ABasePPC64
    369 		}
    370 	}
    371 	// Annoying aliases.
    372 	instructions["BR"] = ppc64.ABR
    373 	instructions["BL"] = ppc64.ABL
    374 
    375 	return &Arch{
    376 		LinkArch:       &ppc64.Linkppc64,
    377 		Instructions:   instructions,
    378 		Register:       register,
    379 		RegisterPrefix: registerPrefix,
    380 		RegisterNumber: ppc64RegisterNumber,
    381 		IsJump:         jumpPPC64,
    382 	}
    383 }
    384 
    385 func archMips() *Arch {
    386 	register := make(map[string]int16)
    387 	// Create maps for easy lookup of instruction names etc.
    388 	// Note that there is no list of names as there is for x86.
    389 	for i := mips.REG_R0; i <= mips.REG_R31; i++ {
    390 		register[obj.Rconv(i)] = int16(i)
    391 	}
    392 
    393 	for i := mips.REG_F0; i <= mips.REG_F31; i++ {
    394 		register[obj.Rconv(i)] = int16(i)
    395 	}
    396 	for i := mips.REG_M0; i <= mips.REG_M31; i++ {
    397 		register[obj.Rconv(i)] = int16(i)
    398 	}
    399 	for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
    400 		register[obj.Rconv(i)] = int16(i)
    401 	}
    402 	register["HI"] = mips.REG_HI
    403 	register["LO"] = mips.REG_LO
    404 	// Pseudo-registers.
    405 	register["SB"] = RSB
    406 	register["FP"] = RFP
    407 	register["PC"] = RPC
    408 	// Avoid unintentionally clobbering g using R30.
    409 	delete(register, "R30")
    410 	register["g"] = mips.REG_R30
    411 
    412 	registerPrefix := map[string]bool{
    413 		"F":   true,
    414 		"FCR": true,
    415 		"M":   true,
    416 		"R":   true,
    417 	}
    418 
    419 	instructions := make(map[string]obj.As)
    420 	for i, s := range obj.Anames {
    421 		instructions[s] = obj.As(i)
    422 	}
    423 	for i, s := range mips.Anames {
    424 		if obj.As(i) >= obj.A_ARCHSPECIFIC {
    425 			instructions[s] = obj.As(i) + obj.ABaseMIPS
    426 		}
    427 	}
    428 	// Annoying alias.
    429 	instructions["JAL"] = mips.AJAL
    430 
    431 	return &Arch{
    432 		LinkArch:       &mips.Linkmipsle,
    433 		Instructions:   instructions,
    434 		Register:       register,
    435 		RegisterPrefix: registerPrefix,
    436 		RegisterNumber: mipsRegisterNumber,
    437 		IsJump:         jumpMIPS,
    438 	}
    439 }
    440 
    441 func archMips64() *Arch {
    442 	register := make(map[string]int16)
    443 	// Create maps for easy lookup of instruction names etc.
    444 	// Note that there is no list of names as there is for x86.
    445 	for i := mips.REG_R0; i <= mips.REG_R31; i++ {
    446 		register[obj.Rconv(i)] = int16(i)
    447 	}
    448 	for i := mips.REG_F0; i <= mips.REG_F31; i++ {
    449 		register[obj.Rconv(i)] = int16(i)
    450 	}
    451 	for i := mips.REG_M0; i <= mips.REG_M31; i++ {
    452 		register[obj.Rconv(i)] = int16(i)
    453 	}
    454 	for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
    455 		register[obj.Rconv(i)] = int16(i)
    456 	}
    457 	register["HI"] = mips.REG_HI
    458 	register["LO"] = mips.REG_LO
    459 	// Pseudo-registers.
    460 	register["SB"] = RSB
    461 	register["FP"] = RFP
    462 	register["PC"] = RPC
    463 	// Avoid unintentionally clobbering g using R30.
    464 	delete(register, "R30")
    465 	register["g"] = mips.REG_R30
    466 	// Avoid unintentionally clobbering RSB using R28.
    467 	delete(register, "R28")
    468 	register["RSB"] = mips.REG_R28
    469 	registerPrefix := map[string]bool{
    470 		"F":   true,
    471 		"FCR": true,
    472 		"M":   true,
    473 		"R":   true,
    474 	}
    475 
    476 	instructions := make(map[string]obj.As)
    477 	for i, s := range obj.Anames {
    478 		instructions[s] = obj.As(i)
    479 	}
    480 	for i, s := range mips.Anames {
    481 		if obj.As(i) >= obj.A_ARCHSPECIFIC {
    482 			instructions[s] = obj.As(i) + obj.ABaseMIPS
    483 		}
    484 	}
    485 	// Annoying alias.
    486 	instructions["JAL"] = mips.AJAL
    487 
    488 	return &Arch{
    489 		LinkArch:       &mips.Linkmips64,
    490 		Instructions:   instructions,
    491 		Register:       register,
    492 		RegisterPrefix: registerPrefix,
    493 		RegisterNumber: mipsRegisterNumber,
    494 		IsJump:         jumpMIPS,
    495 	}
    496 }
    497 
    498 func archS390x() *Arch {
    499 	register := make(map[string]int16)
    500 	// Create maps for easy lookup of instruction names etc.
    501 	// Note that there is no list of names as there is for x86.
    502 	for i := s390x.REG_R0; i <= s390x.REG_R15; i++ {
    503 		register[obj.Rconv(i)] = int16(i)
    504 	}
    505 	for i := s390x.REG_F0; i <= s390x.REG_F15; i++ {
    506 		register[obj.Rconv(i)] = int16(i)
    507 	}
    508 	for i := s390x.REG_V0; i <= s390x.REG_V31; i++ {
    509 		register[obj.Rconv(i)] = int16(i)
    510 	}
    511 	for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ {
    512 		register[obj.Rconv(i)] = int16(i)
    513 	}
    514 	register["LR"] = s390x.REG_LR
    515 	// Pseudo-registers.
    516 	register["SB"] = RSB
    517 	register["FP"] = RFP
    518 	register["PC"] = RPC
    519 	// Avoid unintentionally clobbering g using R13.
    520 	delete(register, "R13")
    521 	register["g"] = s390x.REG_R13
    522 	registerPrefix := map[string]bool{
    523 		"AR": true,
    524 		"F":  true,
    525 		"R":  true,
    526 	}
    527 
    528 	instructions := make(map[string]obj.As)
    529 	for i, s := range obj.Anames {
    530 		instructions[s] = obj.As(i)
    531 	}
    532 	for i, s := range s390x.Anames {
    533 		if obj.As(i) >= obj.A_ARCHSPECIFIC {
    534 			instructions[s] = obj.As(i) + obj.ABaseS390X
    535 		}
    536 	}
    537 	// Annoying aliases.
    538 	instructions["BR"] = s390x.ABR
    539 	instructions["BL"] = s390x.ABL
    540 
    541 	return &Arch{
    542 		LinkArch:       &s390x.Links390x,
    543 		Instructions:   instructions,
    544 		Register:       register,
    545 		RegisterPrefix: registerPrefix,
    546 		RegisterNumber: s390xRegisterNumber,
    547 		IsJump:         jumpS390x,
    548 	}
    549 }
    550