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