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