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