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