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  }