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