github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/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/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[obj.Rconv(arm64.REGSP)] = int16(arm64.REGSP) 240 for i := arm64.REG_R0; i <= arm64.REG_R31; i++ { 241 register[obj.Rconv(i)] = int16(i) 242 } 243 for i := arm64.REG_F0; i <= arm64.REG_F31; i++ { 244 register[obj.Rconv(i)] = int16(i) 245 } 246 for i := arm64.REG_V0; i <= arm64.REG_V31; i++ { 247 register[obj.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 register["PLDL1KEEP"] = arm64.REG_PLDL1KEEP 264 register["PLDL1STRM"] = arm64.REG_PLDL1STRM 265 register["PLDL2KEEP"] = arm64.REG_PLDL2KEEP 266 register["PLDL2STRM"] = arm64.REG_PLDL2STRM 267 register["PLDL3KEEP"] = arm64.REG_PLDL3KEEP 268 register["PLDL3STRM"] = arm64.REG_PLDL3STRM 269 register["PLIL1KEEP"] = arm64.REG_PLIL1KEEP 270 register["PLIL1STRM"] = arm64.REG_PLIL1STRM 271 register["PLIL2KEEP"] = arm64.REG_PLIL2KEEP 272 register["PLIL2STRM"] = arm64.REG_PLIL2STRM 273 register["PLIL3KEEP"] = arm64.REG_PLIL3KEEP 274 register["PLIL3STRM"] = arm64.REG_PLIL3STRM 275 register["PSTL1KEEP"] = arm64.REG_PSTL1KEEP 276 register["PSTL1STRM"] = arm64.REG_PSTL1STRM 277 register["PSTL2KEEP"] = arm64.REG_PSTL2KEEP 278 register["PSTL2STRM"] = arm64.REG_PSTL2STRM 279 register["PSTL3KEEP"] = arm64.REG_PSTL3KEEP 280 register["PSTL3STRM"] = arm64.REG_PSTL3STRM 281 282 // Conditional operators, like EQ, NE, etc. 283 register["EQ"] = arm64.COND_EQ 284 register["NE"] = arm64.COND_NE 285 register["HS"] = arm64.COND_HS 286 register["CS"] = arm64.COND_HS 287 register["LO"] = arm64.COND_LO 288 register["CC"] = arm64.COND_LO 289 register["MI"] = arm64.COND_MI 290 register["PL"] = arm64.COND_PL 291 register["VS"] = arm64.COND_VS 292 register["VC"] = arm64.COND_VC 293 register["HI"] = arm64.COND_HI 294 register["LS"] = arm64.COND_LS 295 register["GE"] = arm64.COND_GE 296 register["LT"] = arm64.COND_LT 297 register["GT"] = arm64.COND_GT 298 register["LE"] = arm64.COND_LE 299 register["AL"] = arm64.COND_AL 300 register["NV"] = arm64.COND_NV 301 // Pseudo-registers. 302 register["SB"] = RSB 303 register["FP"] = RFP 304 register["PC"] = RPC 305 register["SP"] = RSP 306 // Avoid unintentionally clobbering g using R28. 307 delete(register, "R28") 308 register["g"] = arm64.REG_R28 309 registerPrefix := map[string]bool{ 310 "F": true, 311 "R": true, 312 "V": true, 313 } 314 315 instructions := make(map[string]obj.As) 316 for i, s := range obj.Anames { 317 instructions[s] = obj.As(i) 318 } 319 for i, s := range arm64.Anames { 320 if obj.As(i) >= obj.A_ARCHSPECIFIC { 321 instructions[s] = obj.As(i) + obj.ABaseARM64 322 } 323 } 324 // Annoying aliases. 325 instructions["B"] = arm64.AB 326 instructions["BL"] = arm64.ABL 327 328 return &Arch{ 329 LinkArch: &arm64.Linkarm64, 330 Instructions: instructions, 331 Register: register, 332 RegisterPrefix: registerPrefix, 333 RegisterNumber: arm64RegisterNumber, 334 IsJump: jumpArm64, 335 } 336 337 } 338 339 func archPPC64() *Arch { 340 register := make(map[string]int16) 341 // Create maps for easy lookup of instruction names etc. 342 // Note that there is no list of names as there is for x86. 343 for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ { 344 register[obj.Rconv(i)] = int16(i) 345 } 346 for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ { 347 register[obj.Rconv(i)] = int16(i) 348 } 349 for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ { 350 register[obj.Rconv(i)] = int16(i) 351 } 352 for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ { 353 register[obj.Rconv(i)] = int16(i) 354 } 355 for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ { 356 register[obj.Rconv(i)] = int16(i) 357 } 358 for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ { 359 register[obj.Rconv(i)] = int16(i) 360 } 361 register["CR"] = ppc64.REG_CR 362 register["XER"] = ppc64.REG_XER 363 register["LR"] = ppc64.REG_LR 364 register["CTR"] = ppc64.REG_CTR 365 register["FPSCR"] = ppc64.REG_FPSCR 366 register["MSR"] = ppc64.REG_MSR 367 // Pseudo-registers. 368 register["SB"] = RSB 369 register["FP"] = RFP 370 register["PC"] = RPC 371 // Avoid unintentionally clobbering g using R30. 372 delete(register, "R30") 373 register["g"] = ppc64.REG_R30 374 registerPrefix := map[string]bool{ 375 "CR": true, 376 "F": true, 377 "R": true, 378 "SPR": true, 379 } 380 381 instructions := make(map[string]obj.As) 382 for i, s := range obj.Anames { 383 instructions[s] = obj.As(i) 384 } 385 for i, s := range ppc64.Anames { 386 if obj.As(i) >= obj.A_ARCHSPECIFIC { 387 instructions[s] = obj.As(i) + obj.ABasePPC64 388 } 389 } 390 // Annoying aliases. 391 instructions["BR"] = ppc64.ABR 392 instructions["BL"] = ppc64.ABL 393 394 return &Arch{ 395 LinkArch: &ppc64.Linkppc64, 396 Instructions: instructions, 397 Register: register, 398 RegisterPrefix: registerPrefix, 399 RegisterNumber: ppc64RegisterNumber, 400 IsJump: jumpPPC64, 401 } 402 } 403 404 func archMips() *Arch { 405 register := make(map[string]int16) 406 // Create maps for easy lookup of instruction names etc. 407 // Note that there is no list of names as there is for x86. 408 for i := mips.REG_R0; i <= mips.REG_R31; i++ { 409 register[obj.Rconv(i)] = int16(i) 410 } 411 412 for i := mips.REG_F0; i <= mips.REG_F31; i++ { 413 register[obj.Rconv(i)] = int16(i) 414 } 415 for i := mips.REG_M0; i <= mips.REG_M31; i++ { 416 register[obj.Rconv(i)] = int16(i) 417 } 418 for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ { 419 register[obj.Rconv(i)] = int16(i) 420 } 421 register["HI"] = mips.REG_HI 422 register["LO"] = mips.REG_LO 423 // Pseudo-registers. 424 register["SB"] = RSB 425 register["FP"] = RFP 426 register["PC"] = RPC 427 // Avoid unintentionally clobbering g using R30. 428 delete(register, "R30") 429 register["g"] = mips.REG_R30 430 431 registerPrefix := map[string]bool{ 432 "F": true, 433 "FCR": true, 434 "M": true, 435 "R": true, 436 } 437 438 instructions := make(map[string]obj.As) 439 for i, s := range obj.Anames { 440 instructions[s] = obj.As(i) 441 } 442 for i, s := range mips.Anames { 443 if obj.As(i) >= obj.A_ARCHSPECIFIC { 444 instructions[s] = obj.As(i) + obj.ABaseMIPS 445 } 446 } 447 // Annoying alias. 448 instructions["JAL"] = mips.AJAL 449 450 return &Arch{ 451 LinkArch: &mips.Linkmipsle, 452 Instructions: instructions, 453 Register: register, 454 RegisterPrefix: registerPrefix, 455 RegisterNumber: mipsRegisterNumber, 456 IsJump: jumpMIPS, 457 } 458 } 459 460 func archMips64() *Arch { 461 register := make(map[string]int16) 462 // Create maps for easy lookup of instruction names etc. 463 // Note that there is no list of names as there is for x86. 464 for i := mips.REG_R0; i <= mips.REG_R31; i++ { 465 register[obj.Rconv(i)] = int16(i) 466 } 467 for i := mips.REG_F0; i <= mips.REG_F31; i++ { 468 register[obj.Rconv(i)] = int16(i) 469 } 470 for i := mips.REG_M0; i <= mips.REG_M31; i++ { 471 register[obj.Rconv(i)] = int16(i) 472 } 473 for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ { 474 register[obj.Rconv(i)] = int16(i) 475 } 476 register["HI"] = mips.REG_HI 477 register["LO"] = mips.REG_LO 478 // Pseudo-registers. 479 register["SB"] = RSB 480 register["FP"] = RFP 481 register["PC"] = RPC 482 // Avoid unintentionally clobbering g using R30. 483 delete(register, "R30") 484 register["g"] = mips.REG_R30 485 // Avoid unintentionally clobbering RSB using R28. 486 delete(register, "R28") 487 register["RSB"] = mips.REG_R28 488 registerPrefix := map[string]bool{ 489 "F": true, 490 "FCR": true, 491 "M": true, 492 "R": true, 493 } 494 495 instructions := make(map[string]obj.As) 496 for i, s := range obj.Anames { 497 instructions[s] = obj.As(i) 498 } 499 for i, s := range mips.Anames { 500 if obj.As(i) >= obj.A_ARCHSPECIFIC { 501 instructions[s] = obj.As(i) + obj.ABaseMIPS 502 } 503 } 504 // Annoying alias. 505 instructions["JAL"] = mips.AJAL 506 507 return &Arch{ 508 LinkArch: &mips.Linkmips64, 509 Instructions: instructions, 510 Register: register, 511 RegisterPrefix: registerPrefix, 512 RegisterNumber: mipsRegisterNumber, 513 IsJump: jumpMIPS, 514 } 515 } 516 517 func archS390x() *Arch { 518 register := make(map[string]int16) 519 // Create maps for easy lookup of instruction names etc. 520 // Note that there is no list of names as there is for x86. 521 for i := s390x.REG_R0; i <= s390x.REG_R15; i++ { 522 register[obj.Rconv(i)] = int16(i) 523 } 524 for i := s390x.REG_F0; i <= s390x.REG_F15; i++ { 525 register[obj.Rconv(i)] = int16(i) 526 } 527 for i := s390x.REG_V0; i <= s390x.REG_V31; i++ { 528 register[obj.Rconv(i)] = int16(i) 529 } 530 for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ { 531 register[obj.Rconv(i)] = int16(i) 532 } 533 register["LR"] = s390x.REG_LR 534 // Pseudo-registers. 535 register["SB"] = RSB 536 register["FP"] = RFP 537 register["PC"] = RPC 538 // Avoid unintentionally clobbering g using R13. 539 delete(register, "R13") 540 register["g"] = s390x.REG_R13 541 registerPrefix := map[string]bool{ 542 "AR": true, 543 "F": true, 544 "R": true, 545 } 546 547 instructions := make(map[string]obj.As) 548 for i, s := range obj.Anames { 549 instructions[s] = obj.As(i) 550 } 551 for i, s := range s390x.Anames { 552 if obj.As(i) >= obj.A_ARCHSPECIFIC { 553 instructions[s] = obj.As(i) + obj.ABaseS390X 554 } 555 } 556 // Annoying aliases. 557 instructions["BR"] = s390x.ABR 558 instructions["BL"] = s390x.ABL 559 560 return &Arch{ 561 LinkArch: &s390x.Links390x, 562 Instructions: instructions, 563 Register: register, 564 RegisterPrefix: registerPrefix, 565 RegisterNumber: s390xRegisterNumber, 566 IsJump: jumpS390x, 567 } 568 }