github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/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   /* alternate */
   107  	instructions["JAE"] = x86.AJCC  /* alternate */
   108  	instructions["JB"] = x86.AJCS   /* alternate */
   109  	instructions["JBE"] = x86.AJLS  /* alternate */
   110  	instructions["JC"] = x86.AJCS   /* alternate */
   111  	instructions["JCC"] = x86.AJCC  /* carry clear (CF = 0) */
   112  	instructions["JCS"] = x86.AJCS  /* carry set (CF = 1) */
   113  	instructions["JE"] = x86.AJEQ   /* alternate */
   114  	instructions["JEQ"] = x86.AJEQ  /* equal (ZF = 1) */
   115  	instructions["JG"] = x86.AJGT   /* alternate */
   116  	instructions["JGE"] = x86.AJGE  /* greater than or equal (signed) (SF = OF) */
   117  	instructions["JGT"] = x86.AJGT  /* greater than (signed) (ZF = 0 && SF = OF) */
   118  	instructions["JHI"] = x86.AJHI  /* higher (unsigned) (CF = 0 && ZF = 0) */
   119  	instructions["JHS"] = x86.AJCC  /* alternate */
   120  	instructions["JL"] = x86.AJLT   /* alternate */
   121  	instructions["JLE"] = x86.AJLE  /* less than or equal (signed) (ZF = 1 || SF != OF) */
   122  	instructions["JLO"] = x86.AJCS  /* alternate */
   123  	instructions["JLS"] = x86.AJLS  /* lower or same (unsigned) (CF = 1 || ZF = 1) */
   124  	instructions["JLT"] = x86.AJLT  /* less than (signed) (SF != OF) */
   125  	instructions["JMI"] = x86.AJMI  /* negative (minus) (SF = 1) */
   126  	instructions["JNA"] = x86.AJLS  /* alternate */
   127  	instructions["JNAE"] = x86.AJCS /* alternate */
   128  	instructions["JNB"] = x86.AJCC  /* alternate */
   129  	instructions["JNBE"] = x86.AJHI /* alternate */
   130  	instructions["JNC"] = x86.AJCC  /* alternate */
   131  	instructions["JNE"] = x86.AJNE  /* not equal (ZF = 0) */
   132  	instructions["JNG"] = x86.AJLE  /* alternate */
   133  	instructions["JNGE"] = x86.AJLT /* alternate */
   134  	instructions["JNL"] = x86.AJGE  /* alternate */
   135  	instructions["JNLE"] = x86.AJGT /* alternate */
   136  	instructions["JNO"] = x86.AJOC  /* alternate */
   137  	instructions["JNP"] = x86.AJPC  /* alternate */
   138  	instructions["JNS"] = x86.AJPL  /* alternate */
   139  	instructions["JNZ"] = x86.AJNE  /* alternate */
   140  	instructions["JO"] = x86.AJOS   /* alternate */
   141  	instructions["JOC"] = x86.AJOC  /* overflow clear (OF = 0) */
   142  	instructions["JOS"] = x86.AJOS  /* overflow set (OF = 1) */
   143  	instructions["JP"] = x86.AJPS   /* alternate */
   144  	instructions["JPC"] = x86.AJPC  /* parity clear (PF = 0) */
   145  	instructions["JPE"] = x86.AJPS  /* alternate */
   146  	instructions["JPL"] = x86.AJPL  /* non-negative (plus) (SF = 0) */
   147  	instructions["JPO"] = x86.AJPC  /* alternate */
   148  	instructions["JPS"] = x86.AJPS  /* parity set (PF = 1) */
   149  	instructions["JS"] = x86.AJMI   /* alternate */
   150  	instructions["JZ"] = x86.AJEQ   /* alternate */
   151  	instructions["MASKMOVDQU"] = x86.AMASKMOVOU
   152  	instructions["MOVD"] = x86.AMOVQ
   153  	instructions["MOVDQ2Q"] = x86.AMOVQ
   154  	instructions["MOVNTDQ"] = x86.AMOVNTO
   155  	instructions["MOVOA"] = x86.AMOVO
   156  	instructions["MOVOA"] = x86.AMOVO
   157  	instructions["PF2ID"] = x86.APF2IL
   158  	instructions["PI2FD"] = x86.API2FL
   159  	instructions["PSLLDQ"] = x86.APSLLO
   160  	instructions["PSRLDQ"] = x86.APSRLO
   161  
   162  	return &Arch{
   163  		LinkArch:       linkArch,
   164  		Instructions:   instructions,
   165  		Register:       register,
   166  		RegisterPrefix: nil,
   167  		RegisterNumber: nilRegisterNumber,
   168  		IsJump:         jumpX86,
   169  	}
   170  }
   171  
   172  func archArm() *Arch {
   173  	register := make(map[string]int16)
   174  	// Create maps for easy lookup of instruction names etc.
   175  	// Note that there is no list of names as there is for x86.
   176  	for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
   177  		register[obj.Rconv(i)] = int16(i)
   178  	}
   179  	// Avoid unintentionally clobbering g using R10.
   180  	delete(register, "R10")
   181  	register["g"] = arm.REG_R10
   182  	for i := 0; i < 16; i++ {
   183  		register[fmt.Sprintf("C%d", i)] = int16(i)
   184  	}
   185  
   186  	// Pseudo-registers.
   187  	register["SB"] = RSB
   188  	register["FP"] = RFP
   189  	register["PC"] = RPC
   190  	register["SP"] = RSP
   191  	registerPrefix := map[string]bool{
   192  		"F": true,
   193  		"R": true,
   194  	}
   195  
   196  	instructions := make(map[string]int)
   197  	for i, s := range obj.Anames {
   198  		instructions[s] = i
   199  	}
   200  	for i, s := range arm.Anames {
   201  		if i >= obj.A_ARCHSPECIFIC {
   202  			instructions[s] = i + obj.ABaseARM
   203  		}
   204  	}
   205  	// Annoying aliases.
   206  	instructions["B"] = obj.AJMP
   207  	instructions["BL"] = obj.ACALL
   208  	// MCR differs from MRC by the way fields of the word are encoded.
   209  	// (Details in arm.go). Here we add the instruction so parse will find
   210  	// it, but give it an opcode number known only to us.
   211  	instructions["MCR"] = aMCR
   212  
   213  	return &Arch{
   214  		LinkArch:       &arm.Linkarm,
   215  		Instructions:   instructions,
   216  		Register:       register,
   217  		RegisterPrefix: registerPrefix,
   218  		RegisterNumber: armRegisterNumber,
   219  		IsJump:         jumpArm,
   220  	}
   221  }
   222  
   223  func archArm64() *Arch {
   224  	register := make(map[string]int16)
   225  	// Create maps for easy lookup of instruction names etc.
   226  	// Note that there is no list of names as there is for 386 and amd64.
   227  	register[arm64.Rconv(arm64.REGSP)] = int16(arm64.REGSP)
   228  	for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
   229  		register[arm64.Rconv(i)] = int16(i)
   230  	}
   231  	for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
   232  		register[arm64.Rconv(i)] = int16(i)
   233  	}
   234  	for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
   235  		register[arm64.Rconv(i)] = int16(i)
   236  	}
   237  	register["LR"] = arm64.REGLINK
   238  	register["DAIF"] = arm64.REG_DAIF
   239  	register["NZCV"] = arm64.REG_NZCV
   240  	register["FPSR"] = arm64.REG_FPSR
   241  	register["FPCR"] = arm64.REG_FPCR
   242  	register["SPSR_EL1"] = arm64.REG_SPSR_EL1
   243  	register["ELR_EL1"] = arm64.REG_ELR_EL1
   244  	register["SPSR_EL2"] = arm64.REG_SPSR_EL2
   245  	register["ELR_EL2"] = arm64.REG_ELR_EL2
   246  	register["CurrentEL"] = arm64.REG_CurrentEL
   247  	register["SP_EL0"] = arm64.REG_SP_EL0
   248  	register["SPSel"] = arm64.REG_SPSel
   249  	register["DAIFSet"] = arm64.REG_DAIFSet
   250  	register["DAIFClr"] = arm64.REG_DAIFClr
   251  	// Conditional operators, like EQ, NE, etc.
   252  	register["EQ"] = arm64.COND_EQ
   253  	register["NE"] = arm64.COND_NE
   254  	register["HS"] = arm64.COND_HS
   255  	register["CS"] = arm64.COND_HS
   256  	register["LO"] = arm64.COND_LO
   257  	register["CC"] = arm64.COND_LO
   258  	register["MI"] = arm64.COND_MI
   259  	register["PL"] = arm64.COND_PL
   260  	register["VS"] = arm64.COND_VS
   261  	register["VC"] = arm64.COND_VC
   262  	register["HI"] = arm64.COND_HI
   263  	register["LS"] = arm64.COND_LS
   264  	register["GE"] = arm64.COND_GE
   265  	register["LT"] = arm64.COND_LT
   266  	register["GT"] = arm64.COND_GT
   267  	register["LE"] = arm64.COND_LE
   268  	register["AL"] = arm64.COND_AL
   269  	register["NV"] = arm64.COND_NV
   270  	// Pseudo-registers.
   271  	register["SB"] = RSB
   272  	register["FP"] = RFP
   273  	register["PC"] = RPC
   274  	register["SP"] = RSP
   275  	// Avoid unintentionally clobbering g using R28.
   276  	delete(register, "R28")
   277  	register["g"] = arm64.REG_R28
   278  	registerPrefix := map[string]bool{
   279  		"F": true,
   280  		"R": true,
   281  		"V": true,
   282  	}
   283  
   284  	instructions := make(map[string]int)
   285  	for i, s := range obj.Anames {
   286  		instructions[s] = i
   287  	}
   288  	for i, s := range arm64.Anames {
   289  		if i >= obj.A_ARCHSPECIFIC {
   290  			instructions[s] = i + obj.ABaseARM64
   291  		}
   292  	}
   293  	// Annoying aliases.
   294  	instructions["B"] = arm64.AB
   295  	instructions["BL"] = arm64.ABL
   296  
   297  	return &Arch{
   298  		LinkArch:       &arm64.Linkarm64,
   299  		Instructions:   instructions,
   300  		Register:       register,
   301  		RegisterPrefix: registerPrefix,
   302  		RegisterNumber: arm64RegisterNumber,
   303  		IsJump:         jumpArm64,
   304  	}
   305  
   306  }
   307  
   308  func archPPC64() *Arch {
   309  	register := make(map[string]int16)
   310  	// Create maps for easy lookup of instruction names etc.
   311  	// Note that there is no list of names as there is for x86.
   312  	for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
   313  		register[obj.Rconv(i)] = int16(i)
   314  	}
   315  	for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
   316  		register[obj.Rconv(i)] = int16(i)
   317  	}
   318  	for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
   319  		register[obj.Rconv(i)] = int16(i)
   320  	}
   321  	for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
   322  		register[obj.Rconv(i)] = int16(i)
   323  	}
   324  	register["CR"] = ppc64.REG_CR
   325  	register["XER"] = ppc64.REG_XER
   326  	register["LR"] = ppc64.REG_LR
   327  	register["CTR"] = ppc64.REG_CTR
   328  	register["FPSCR"] = ppc64.REG_FPSCR
   329  	register["MSR"] = ppc64.REG_MSR
   330  	// Pseudo-registers.
   331  	register["SB"] = RSB
   332  	register["FP"] = RFP
   333  	register["PC"] = RPC
   334  	// Avoid unintentionally clobbering g using R30.
   335  	delete(register, "R30")
   336  	register["g"] = ppc64.REG_R30
   337  	registerPrefix := map[string]bool{
   338  		"CR":  true,
   339  		"F":   true,
   340  		"R":   true,
   341  		"SPR": true,
   342  	}
   343  
   344  	instructions := make(map[string]int)
   345  	for i, s := range obj.Anames {
   346  		instructions[s] = i
   347  	}
   348  	for i, s := range ppc64.Anames {
   349  		if i >= obj.A_ARCHSPECIFIC {
   350  			instructions[s] = i + obj.ABasePPC64
   351  		}
   352  	}
   353  	// Annoying aliases.
   354  	instructions["BR"] = ppc64.ABR
   355  	instructions["BL"] = ppc64.ABL
   356  
   357  	return &Arch{
   358  		LinkArch:       &ppc64.Linkppc64,
   359  		Instructions:   instructions,
   360  		Register:       register,
   361  		RegisterPrefix: registerPrefix,
   362  		RegisterNumber: ppc64RegisterNumber,
   363  		IsJump:         jumpPPC64,
   364  	}
   365  }