github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/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/sparc64" 14 "cmd/internal/obj/s390x" 15 "cmd/internal/obj/x86" 16 "fmt" 17 "strings" 18 ) 19 20 // Pseudo-registers whose names are the constant name without the leading R. 21 const ( 22 RFP = -(iota + 1) 23 RSB 24 RSP 25 RPC 26 ) 27 28 // Arch wraps the link architecture object with more architecture-specific information. 29 type Arch struct { 30 *obj.LinkArch 31 // Map of instruction names to enumeration. 32 Instructions map[string]obj.As 33 // Map of register names to enumeration. 34 Register map[string]int16 35 // Table of register prefix names. These are things like R for R(0) and SPR for SPR(268). 36 RegisterPrefix map[string]bool 37 // RegisterNumber converts R(10) into arm.REG_R10. 38 RegisterNumber func(string, int16) (int16, bool) 39 // Instruction is a jump. 40 IsJump func(word string) bool 41 } 42 43 // nilRegisterNumber is the register number function for architectures 44 // that do not accept the R(N) notation. It always returns failure. 45 func nilRegisterNumber(name string, n int16) (int16, bool) { 46 return 0, false 47 } 48 49 // Set configures the architecture specified by GOARCH and returns its representation. 50 // It returns nil if GOARCH is not recognized. 51 func Set(GOARCH string) *Arch { 52 switch GOARCH { 53 case "386": 54 return archX86(&x86.Link386) 55 case "amd64": 56 return archX86(&x86.Linkamd64) 57 case "amd64p32": 58 return archX86(&x86.Linkamd64p32) 59 case "arm": 60 return archArm() 61 case "arm64": 62 return archArm64() 63 case "mips64": 64 a := archMips64() 65 a.LinkArch = &mips.Linkmips64 66 return a 67 case "mips64le": 68 a := archMips64() 69 a.LinkArch = &mips.Linkmips64le 70 return a 71 case "ppc64": 72 a := archPPC64() 73 a.LinkArch = &ppc64.Linkppc64 74 return a 75 case "ppc64le": 76 a := archPPC64() 77 a.LinkArch = &ppc64.Linkppc64le 78 return a 79 case "s390x": 80 a := archS390x() 81 a.LinkArch = &s390x.Links390x 82 return a 83 case "sparc64": 84 return archSparc64() 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]obj.As) 106 for i, s := range obj.Anames { 107 instructions[s] = obj.As(i) 108 } 109 for i, s := range x86.Anames { 110 if obj.As(i) >= obj.A_ARCHSPECIFIC { 111 instructions[s] = obj.As(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["PSLLDQ"] = x86.APSLLO 166 instructions["PSRLDQ"] = x86.APSRLO 167 instructions["PADDD"] = x86.APADDL 168 169 return &Arch{ 170 LinkArch: linkArch, 171 Instructions: instructions, 172 Register: register, 173 RegisterPrefix: nil, 174 RegisterNumber: nilRegisterNumber, 175 IsJump: jumpX86, 176 } 177 } 178 179 func archArm() *Arch { 180 register := make(map[string]int16) 181 // Create maps for easy lookup of instruction names etc. 182 // Note that there is no list of names as there is for x86. 183 for i := arm.REG_R0; i < arm.REG_SPSR; i++ { 184 register[obj.Rconv(i)] = int16(i) 185 } 186 // Avoid unintentionally clobbering g using R10. 187 delete(register, "R10") 188 register["g"] = arm.REG_R10 189 for i := 0; i < 16; i++ { 190 register[fmt.Sprintf("C%d", i)] = int16(i) 191 } 192 193 // Pseudo-registers. 194 register["SB"] = RSB 195 register["FP"] = RFP 196 register["PC"] = RPC 197 register["SP"] = RSP 198 registerPrefix := map[string]bool{ 199 "F": true, 200 "R": true, 201 } 202 203 instructions := make(map[string]obj.As) 204 for i, s := range obj.Anames { 205 instructions[s] = obj.As(i) 206 } 207 for i, s := range arm.Anames { 208 if obj.As(i) >= obj.A_ARCHSPECIFIC { 209 instructions[s] = obj.As(i) + obj.ABaseARM 210 } 211 } 212 // Annoying aliases. 213 instructions["B"] = obj.AJMP 214 instructions["BL"] = obj.ACALL 215 // MCR differs from MRC by the way fields of the word are encoded. 216 // (Details in arm.go). Here we add the instruction so parse will find 217 // it, but give it an opcode number known only to us. 218 instructions["MCR"] = aMCR 219 220 return &Arch{ 221 LinkArch: &arm.Linkarm, 222 Instructions: instructions, 223 Register: register, 224 RegisterPrefix: registerPrefix, 225 RegisterNumber: armRegisterNumber, 226 IsJump: jumpArm, 227 } 228 } 229 230 func archArm64() *Arch { 231 register := make(map[string]int16) 232 // Create maps for easy lookup of instruction names etc. 233 // Note that there is no list of names as there is for 386 and amd64. 234 register[arm64.Rconv(arm64.REGSP)] = int16(arm64.REGSP) 235 for i := arm64.REG_R0; i <= arm64.REG_R31; i++ { 236 register[arm64.Rconv(i)] = int16(i) 237 } 238 for i := arm64.REG_F0; i <= arm64.REG_F31; i++ { 239 register[arm64.Rconv(i)] = int16(i) 240 } 241 for i := arm64.REG_V0; i <= arm64.REG_V31; i++ { 242 register[arm64.Rconv(i)] = int16(i) 243 } 244 register["LR"] = arm64.REGLINK 245 register["DAIF"] = arm64.REG_DAIF 246 register["NZCV"] = arm64.REG_NZCV 247 register["FPSR"] = arm64.REG_FPSR 248 register["FPCR"] = arm64.REG_FPCR 249 register["SPSR_EL1"] = arm64.REG_SPSR_EL1 250 register["ELR_EL1"] = arm64.REG_ELR_EL1 251 register["SPSR_EL2"] = arm64.REG_SPSR_EL2 252 register["ELR_EL2"] = arm64.REG_ELR_EL2 253 register["CurrentEL"] = arm64.REG_CurrentEL 254 register["SP_EL0"] = arm64.REG_SP_EL0 255 register["SPSel"] = arm64.REG_SPSel 256 register["DAIFSet"] = arm64.REG_DAIFSet 257 register["DAIFClr"] = arm64.REG_DAIFClr 258 // Conditional operators, like EQ, NE, etc. 259 register["EQ"] = arm64.COND_EQ 260 register["NE"] = arm64.COND_NE 261 register["HS"] = arm64.COND_HS 262 register["CS"] = arm64.COND_HS 263 register["LO"] = arm64.COND_LO 264 register["CC"] = arm64.COND_LO 265 register["MI"] = arm64.COND_MI 266 register["PL"] = arm64.COND_PL 267 register["VS"] = arm64.COND_VS 268 register["VC"] = arm64.COND_VC 269 register["HI"] = arm64.COND_HI 270 register["LS"] = arm64.COND_LS 271 register["GE"] = arm64.COND_GE 272 register["LT"] = arm64.COND_LT 273 register["GT"] = arm64.COND_GT 274 register["LE"] = arm64.COND_LE 275 register["AL"] = arm64.COND_AL 276 register["NV"] = arm64.COND_NV 277 // Pseudo-registers. 278 register["SB"] = RSB 279 register["FP"] = RFP 280 register["PC"] = RPC 281 register["SP"] = RSP 282 // Avoid unintentionally clobbering g using R28. 283 delete(register, "R28") 284 register["g"] = arm64.REG_R28 285 registerPrefix := map[string]bool{ 286 "F": true, 287 "R": true, 288 "V": true, 289 } 290 291 instructions := make(map[string]obj.As) 292 for i, s := range obj.Anames { 293 instructions[s] = obj.As(i) 294 } 295 for i, s := range arm64.Anames { 296 if obj.As(i) >= obj.A_ARCHSPECIFIC { 297 instructions[s] = obj.As(i) + obj.ABaseARM64 298 } 299 } 300 // Annoying aliases. 301 instructions["B"] = arm64.AB 302 instructions["BL"] = arm64.ABL 303 304 return &Arch{ 305 LinkArch: &arm64.Linkarm64, 306 Instructions: instructions, 307 Register: register, 308 RegisterPrefix: registerPrefix, 309 RegisterNumber: arm64RegisterNumber, 310 IsJump: jumpArm64, 311 } 312 313 } 314 315 func archPPC64() *Arch { 316 register := make(map[string]int16) 317 // Create maps for easy lookup of instruction names etc. 318 // Note that there is no list of names as there is for x86. 319 for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ { 320 register[obj.Rconv(i)] = int16(i) 321 } 322 for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ { 323 register[obj.Rconv(i)] = int16(i) 324 } 325 for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ { 326 register[obj.Rconv(i)] = int16(i) 327 } 328 for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ { 329 register[obj.Rconv(i)] = int16(i) 330 } 331 register["CR"] = ppc64.REG_CR 332 register["XER"] = ppc64.REG_XER 333 register["LR"] = ppc64.REG_LR 334 register["CTR"] = ppc64.REG_CTR 335 register["FPSCR"] = ppc64.REG_FPSCR 336 register["MSR"] = ppc64.REG_MSR 337 // Pseudo-registers. 338 register["SB"] = RSB 339 register["FP"] = RFP 340 register["PC"] = RPC 341 // Avoid unintentionally clobbering g using R30. 342 delete(register, "R30") 343 register["g"] = ppc64.REG_R30 344 registerPrefix := map[string]bool{ 345 "CR": true, 346 "F": true, 347 "R": true, 348 "SPR": true, 349 } 350 351 instructions := make(map[string]obj.As) 352 for i, s := range obj.Anames { 353 instructions[s] = obj.As(i) 354 } 355 for i, s := range ppc64.Anames { 356 if obj.As(i) >= obj.A_ARCHSPECIFIC { 357 instructions[s] = obj.As(i) + obj.ABasePPC64 358 } 359 } 360 // Annoying aliases. 361 instructions["BR"] = ppc64.ABR 362 instructions["BL"] = ppc64.ABL 363 364 return &Arch{ 365 LinkArch: &ppc64.Linkppc64, 366 Instructions: instructions, 367 Register: register, 368 RegisterPrefix: registerPrefix, 369 RegisterNumber: ppc64RegisterNumber, 370 IsJump: jumpPPC64, 371 } 372 } 373 374 func archMips64() *Arch { 375 register := make(map[string]int16) 376 // Create maps for easy lookup of instruction names etc. 377 // Note that there is no list of names as there is for x86. 378 for i := mips.REG_R0; i <= mips.REG_R31; i++ { 379 register[obj.Rconv(i)] = int16(i) 380 } 381 for i := mips.REG_F0; i <= mips.REG_F31; i++ { 382 register[obj.Rconv(i)] = int16(i) 383 } 384 for i := mips.REG_M0; i <= mips.REG_M31; i++ { 385 register[obj.Rconv(i)] = int16(i) 386 } 387 for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ { 388 register[obj.Rconv(i)] = int16(i) 389 } 390 register["HI"] = mips.REG_HI 391 register["LO"] = mips.REG_LO 392 // Pseudo-registers. 393 register["SB"] = RSB 394 register["FP"] = RFP 395 register["PC"] = RPC 396 // Avoid unintentionally clobbering g using R30. 397 delete(register, "R30") 398 register["g"] = mips.REG_R30 399 // Avoid unintentionally clobbering RSB using R28. 400 delete(register, "R28") 401 register["RSB"] = mips.REG_R28 402 registerPrefix := map[string]bool{ 403 "F": true, 404 "FCR": true, 405 "M": true, 406 "R": true, 407 } 408 409 instructions := make(map[string]obj.As) 410 for i, s := range obj.Anames { 411 instructions[s] = obj.As(i) 412 } 413 for i, s := range mips.Anames { 414 if obj.As(i) >= obj.A_ARCHSPECIFIC { 415 instructions[s] = obj.As(i) + obj.ABaseMIPS64 416 } 417 } 418 // Annoying alias. 419 instructions["JAL"] = mips.AJAL 420 421 return &Arch{ 422 LinkArch: &mips.Linkmips64, 423 Instructions: instructions, 424 Register: register, 425 RegisterPrefix: registerPrefix, 426 RegisterNumber: mipsRegisterNumber, 427 IsJump: jumpMIPS64, 428 } 429 } 430 431 func archS390x() *Arch { 432 register := make(map[string]int16) 433 // Create maps for easy lookup of instruction names etc. 434 // Note that there is no list of names as there is for x86. 435 for i := s390x.REG_R0; i <= s390x.REG_R15; i++ { 436 register[obj.Rconv(i)] = int16(i) 437 } 438 for i := s390x.REG_F0; i <= s390x.REG_F15; i++ { 439 register[obj.Rconv(i)] = int16(i) 440 } 441 for i := s390x.REG_V0; i <= s390x.REG_V31; i++ { 442 register[obj.Rconv(i)] = int16(i) 443 } 444 for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ { 445 register[obj.Rconv(i)] = int16(i) 446 } 447 register["LR"] = s390x.REG_LR 448 // Pseudo-registers. 449 register["SB"] = RSB 450 register["FP"] = RFP 451 register["PC"] = RPC 452 // Avoid unintentionally clobbering g using R13. 453 delete(register, "R13") 454 register["g"] = s390x.REG_R13 455 registerPrefix := map[string]bool{ 456 "AR": true, 457 "F": true, 458 "R": true, 459 } 460 461 instructions := make(map[string]obj.As) 462 for i, s := range obj.Anames { 463 instructions[s] = obj.As(i) 464 } 465 for i, s := range s390x.Anames { 466 if obj.As(i) >= obj.A_ARCHSPECIFIC { 467 instructions[s] = obj.As(i) + obj.ABaseS390X 468 } 469 } 470 // Annoying aliases. 471 instructions["BR"] = s390x.ABR 472 instructions["BL"] = s390x.ABL 473 474 return &Arch{ 475 LinkArch: &s390x.Links390x, 476 Instructions: instructions, 477 Register: register, 478 RegisterPrefix: registerPrefix, 479 RegisterNumber: s390xRegisterNumber, 480 IsJump: jumpS390x, 481 } 482 } 483 484 func archSparc64() *Arch { 485 register := make(map[string]int16) 486 // Create maps for easy lookup of instruction names etc. 487 // Note that there is no list of names as there is for 386 and amd64. 488 for i := sparc64.REG_G0; i <= sparc64.REG_I7; i++ { 489 register[sparc64.Rconv(i)] = int16(i) 490 } 491 for i := sparc64.REG_F0; i <= sparc64.REG_F31; i++ { 492 register[sparc64.Rconv(i)] = int16(i) 493 } 494 for i := sparc64.REG_D0; i <= sparc64.REG_D62; i++ { 495 register[sparc64.Rconv(i)] = int16(i) 496 } 497 register["BSP"] = sparc64.REG_BSP 498 register["BFP"] = sparc64.REG_BFP 499 // Avoid accidental confusion between RSP and BSP, always use BSP. 500 delete(register, "RSP") 501 delete(register, "RFP") 502 delete(register, "G6") 503 register["ICC"] = sparc64.REG_ICC 504 register["XCC"] = sparc64.REG_XCC 505 register["FCC0"] = sparc64.REG_FCC0 506 register["FCC1"] = sparc64.REG_FCC1 507 register["FCC2"] = sparc64.REG_FCC2 508 register["FCC3"] = sparc64.REG_FCC3 509 register["CCR"] = sparc64.REG_CCR 510 register["TICK"] = sparc64.REG_TICK 511 register["RPC"] = sparc64.REG_RPC 512 // Pseudo-registers. 513 register["SB"] = RSB 514 register["FP"] = RFP 515 register["PC"] = RPC 516 register["SP"] = RSP 517 registerPrefix := map[string]bool{ 518 "D": true, 519 "F": true, 520 "R": true, 521 "O": true, 522 "I": true, 523 "L": true, 524 } 525 526 instructions := make(map[string]obj.As) 527 for i, s := range obj.Anames { 528 instructions[s] = obj.As(i) 529 } 530 for i, s := range sparc64.Anames { 531 if obj.As(i) >= obj.A_ARCHSPECIFIC { 532 instructions[s] = obj.As(i) + obj.ABaseSPARC64 533 } 534 } 535 // Annoying aliases. 536 instructions["BL"] = sparc64.ABL 537 538 return &Arch{ 539 LinkArch: &sparc64.Linksparc64, 540 Instructions: instructions, 541 Register: register, 542 RegisterPrefix: registerPrefix, 543 RegisterNumber: sparc64RegisterNumber, 544 IsJump: jumpSparc64, 545 } 546 }