Source file src/cmd/asm/internal/arch/arch.go

     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 defines architecture-specific information and support functions.
     6  package arch
     7  
     8  import (
     9  	"cmd/internal/obj"
    10  	"cmd/internal/obj/arm"
    11  	"cmd/internal/obj/arm64"
    12  	"cmd/internal/obj/mips"
    13  	"cmd/internal/obj/ppc64"
    14  	"cmd/internal/obj/riscv"
    15  	"cmd/internal/obj/s390x"
    16  	"cmd/internal/obj/wasm"
    17  	"cmd/internal/obj/x86"
    18  	"fmt"
    19  	"strings"
    20  )
    21  
    22  // Pseudo-registers whose names are the constant name without the leading R.
    23  const (
    24  	RFP = -(iota + 1)
    25  	RSB
    26  	RSP
    27  	RPC
    28  )
    29  
    30  // Arch wraps the link architecture object with more architecture-specific information.
    31  type Arch struct {
    32  	*obj.LinkArch
    33  	// Map of instruction names to enumeration.
    34  	Instructions map[string]obj.As
    35  	// Map of register names to enumeration.
    36  	Register map[string]int16
    37  	// Table of register prefix names. These are things like R for R(0) and SPR for SPR(268).
    38  	RegisterPrefix map[string]bool
    39  	// RegisterNumber converts R(10) into arm.REG_R10.
    40  	RegisterNumber func(string, int16) (int16, bool)
    41  	// Instruction is a jump.
    42  	IsJump func(word string) bool
    43  }
    44  
    45  // nilRegisterNumber is the register number function for architectures
    46  // that do not accept the R(N) notation. It always returns failure.
    47  func nilRegisterNumber(name string, n int16) (int16, bool) {
    48  	return 0, false
    49  }
    50  
    51  // Set configures the architecture specified by GOARCH and returns its representation.
    52  // It returns nil if GOARCH is not recognized.
    53  func Set(GOARCH string, shared bool) *Arch {
    54  	switch GOARCH {
    55  	case "386":
    56  		return archX86(&x86.Link386)
    57  	case "amd64":
    58  		return archX86(&x86.Linkamd64)
    59  	case "arm":
    60  		return archArm()
    61  	case "arm64":
    62  		return archArm64()
    63  	case "mips":
    64  		return archMips(&mips.Linkmips)
    65  	case "mipsle":
    66  		return archMips(&mips.Linkmipsle)
    67  	case "mips64":
    68  		return archMips64(&mips.Linkmips64)
    69  	case "mips64le":
    70  		return archMips64(&mips.Linkmips64le)
    71  	case "ppc64":
    72  		return archPPC64(&ppc64.Linkppc64)
    73  	case "ppc64le":
    74  		return archPPC64(&ppc64.Linkppc64le)
    75  	case "riscv64":
    76  		return archRISCV64(shared)
    77  	case "s390x":
    78  		return archS390x()
    79  	case "wasm":
    80  		return archWasm()
    81  	}
    82  	return nil
    83  }
    84  
    85  func jumpX86(word string) bool {
    86  	return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN"
    87  }
    88  
    89  func jumpRISCV(word string) bool {
    90  	switch word {
    91  	case "BEQ", "BEQZ", "BGE", "BGEU", "BGEZ", "BGT", "BGTU", "BGTZ", "BLE", "BLEU", "BLEZ",
    92  		"BLT", "BLTU", "BLTZ", "BNE", "BNEZ", "CALL", "JAL", "JALR", "JMP":
    93  		return true
    94  	}
    95  	return false
    96  }
    97  
    98  func jumpWasm(word string) bool {
    99  	return word == "JMP" || word == "CALL" || word == "Call" || word == "Br" || word == "BrIf"
   100  }
   101  
   102  func archX86(linkArch *obj.LinkArch) *Arch {
   103  	register := make(map[string]int16)
   104  	// Create maps for easy lookup of instruction names etc.
   105  	for i, s := range x86.Register {
   106  		register[s] = int16(i + x86.REG_AL)
   107  	}
   108  	// Pseudo-registers.
   109  	register["SB"] = RSB
   110  	register["FP"] = RFP
   111  	register["PC"] = RPC
   112  	if linkArch == &x86.Linkamd64 {
   113  		// Alias g to R14
   114  		register["g"] = x86.REGG
   115  	}
   116  	// Register prefix not used on this architecture.
   117  
   118  	instructions := make(map[string]obj.As)
   119  	for i, s := range obj.Anames {
   120  		instructions[s] = obj.As(i)
   121  	}
   122  	for i, s := range x86.Anames {
   123  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   124  			instructions[s] = obj.As(i) + obj.ABaseAMD64
   125  		}
   126  	}
   127  	// Annoying aliases.
   128  	instructions["JA"] = x86.AJHI   /* alternate */
   129  	instructions["JAE"] = x86.AJCC  /* alternate */
   130  	instructions["JB"] = x86.AJCS   /* alternate */
   131  	instructions["JBE"] = x86.AJLS  /* alternate */
   132  	instructions["JC"] = x86.AJCS   /* alternate */
   133  	instructions["JCC"] = x86.AJCC  /* carry clear (CF = 0) */
   134  	instructions["JCS"] = x86.AJCS  /* carry set (CF = 1) */
   135  	instructions["JE"] = x86.AJEQ   /* alternate */
   136  	instructions["JEQ"] = x86.AJEQ  /* equal (ZF = 1) */
   137  	instructions["JG"] = x86.AJGT   /* alternate */
   138  	instructions["JGE"] = x86.AJGE  /* greater than or equal (signed) (SF = OF) */
   139  	instructions["JGT"] = x86.AJGT  /* greater than (signed) (ZF = 0 && SF = OF) */
   140  	instructions["JHI"] = x86.AJHI  /* higher (unsigned) (CF = 0 && ZF = 0) */
   141  	instructions["JHS"] = x86.AJCC  /* alternate */
   142  	instructions["JL"] = x86.AJLT   /* alternate */
   143  	instructions["JLE"] = x86.AJLE  /* less than or equal (signed) (ZF = 1 || SF != OF) */
   144  	instructions["JLO"] = x86.AJCS  /* alternate */
   145  	instructions["JLS"] = x86.AJLS  /* lower or same (unsigned) (CF = 1 || ZF = 1) */
   146  	instructions["JLT"] = x86.AJLT  /* less than (signed) (SF != OF) */
   147  	instructions["JMI"] = x86.AJMI  /* negative (minus) (SF = 1) */
   148  	instructions["JNA"] = x86.AJLS  /* alternate */
   149  	instructions["JNAE"] = x86.AJCS /* alternate */
   150  	instructions["JNB"] = x86.AJCC  /* alternate */
   151  	instructions["JNBE"] = x86.AJHI /* alternate */
   152  	instructions["JNC"] = x86.AJCC  /* alternate */
   153  	instructions["JNE"] = x86.AJNE  /* not equal (ZF = 0) */
   154  	instructions["JNG"] = x86.AJLE  /* alternate */
   155  	instructions["JNGE"] = x86.AJLT /* alternate */
   156  	instructions["JNL"] = x86.AJGE  /* alternate */
   157  	instructions["JNLE"] = x86.AJGT /* alternate */
   158  	instructions["JNO"] = x86.AJOC  /* alternate */
   159  	instructions["JNP"] = x86.AJPC  /* alternate */
   160  	instructions["JNS"] = x86.AJPL  /* alternate */
   161  	instructions["JNZ"] = x86.AJNE  /* alternate */
   162  	instructions["JO"] = x86.AJOS   /* alternate */
   163  	instructions["JOC"] = x86.AJOC  /* overflow clear (OF = 0) */
   164  	instructions["JOS"] = x86.AJOS  /* overflow set (OF = 1) */
   165  	instructions["JP"] = x86.AJPS   /* alternate */
   166  	instructions["JPC"] = x86.AJPC  /* parity clear (PF = 0) */
   167  	instructions["JPE"] = x86.AJPS  /* alternate */
   168  	instructions["JPL"] = x86.AJPL  /* non-negative (plus) (SF = 0) */
   169  	instructions["JPO"] = x86.AJPC  /* alternate */
   170  	instructions["JPS"] = x86.AJPS  /* parity set (PF = 1) */
   171  	instructions["JS"] = x86.AJMI   /* alternate */
   172  	instructions["JZ"] = x86.AJEQ   /* alternate */
   173  	instructions["MASKMOVDQU"] = x86.AMASKMOVOU
   174  	instructions["MOVD"] = x86.AMOVQ
   175  	instructions["MOVDQ2Q"] = x86.AMOVQ
   176  	instructions["MOVNTDQ"] = x86.AMOVNTO
   177  	instructions["MOVOA"] = x86.AMOVO
   178  	instructions["PSLLDQ"] = x86.APSLLO
   179  	instructions["PSRLDQ"] = x86.APSRLO
   180  	instructions["PADDD"] = x86.APADDL
   181  	// Spellings originally used in CL 97235.
   182  	instructions["MOVBELL"] = x86.AMOVBEL
   183  	instructions["MOVBEQQ"] = x86.AMOVBEQ
   184  	instructions["MOVBEWW"] = x86.AMOVBEW
   185  
   186  	return &Arch{
   187  		LinkArch:       linkArch,
   188  		Instructions:   instructions,
   189  		Register:       register,
   190  		RegisterPrefix: nil,
   191  		RegisterNumber: nilRegisterNumber,
   192  		IsJump:         jumpX86,
   193  	}
   194  }
   195  
   196  func archArm() *Arch {
   197  	register := make(map[string]int16)
   198  	// Create maps for easy lookup of instruction names etc.
   199  	// Note that there is no list of names as there is for x86.
   200  	for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
   201  		register[obj.Rconv(i)] = int16(i)
   202  	}
   203  	// Avoid unintentionally clobbering g using R10.
   204  	delete(register, "R10")
   205  	register["g"] = arm.REG_R10
   206  	for i := 0; i < 16; i++ {
   207  		register[fmt.Sprintf("C%d", i)] = int16(i)
   208  	}
   209  
   210  	// Pseudo-registers.
   211  	register["SB"] = RSB
   212  	register["FP"] = RFP
   213  	register["PC"] = RPC
   214  	register["SP"] = RSP
   215  	registerPrefix := map[string]bool{
   216  		"F": true,
   217  		"R": true,
   218  	}
   219  
   220  	// special operands for DMB/DSB instructions
   221  	register["MB_SY"] = arm.REG_MB_SY
   222  	register["MB_ST"] = arm.REG_MB_ST
   223  	register["MB_ISH"] = arm.REG_MB_ISH
   224  	register["MB_ISHST"] = arm.REG_MB_ISHST
   225  	register["MB_NSH"] = arm.REG_MB_NSH
   226  	register["MB_NSHST"] = arm.REG_MB_NSHST
   227  	register["MB_OSH"] = arm.REG_MB_OSH
   228  	register["MB_OSHST"] = arm.REG_MB_OSHST
   229  
   230  	instructions := make(map[string]obj.As)
   231  	for i, s := range obj.Anames {
   232  		instructions[s] = obj.As(i)
   233  	}
   234  	for i, s := range arm.Anames {
   235  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   236  			instructions[s] = obj.As(i) + obj.ABaseARM
   237  		}
   238  	}
   239  	// Annoying aliases.
   240  	instructions["B"] = obj.AJMP
   241  	instructions["BL"] = obj.ACALL
   242  	// MCR differs from MRC by the way fields of the word are encoded.
   243  	// (Details in arm.go). Here we add the instruction so parse will find
   244  	// it, but give it an opcode number known only to us.
   245  	instructions["MCR"] = aMCR
   246  
   247  	return &Arch{
   248  		LinkArch:       &arm.Linkarm,
   249  		Instructions:   instructions,
   250  		Register:       register,
   251  		RegisterPrefix: registerPrefix,
   252  		RegisterNumber: armRegisterNumber,
   253  		IsJump:         jumpArm,
   254  	}
   255  }
   256  
   257  func archArm64() *Arch {
   258  	register := make(map[string]int16)
   259  	// Create maps for easy lookup of instruction names etc.
   260  	// Note that there is no list of names as there is for 386 and amd64.
   261  	register[obj.Rconv(arm64.REGSP)] = int16(arm64.REGSP)
   262  	for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
   263  		register[obj.Rconv(i)] = int16(i)
   264  	}
   265  	// Rename R18 to R18_PLATFORM to avoid accidental use.
   266  	register["R18_PLATFORM"] = register["R18"]
   267  	delete(register, "R18")
   268  	for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
   269  		register[obj.Rconv(i)] = int16(i)
   270  	}
   271  	for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
   272  		register[obj.Rconv(i)] = int16(i)
   273  	}
   274  
   275  	// System registers.
   276  	for i := 0; i < len(arm64.SystemReg); i++ {
   277  		register[arm64.SystemReg[i].Name] = arm64.SystemReg[i].Reg
   278  	}
   279  
   280  	register["LR"] = arm64.REGLINK
   281  	register["DAIFSet"] = arm64.REG_DAIFSet
   282  	register["DAIFClr"] = arm64.REG_DAIFClr
   283  	register["PLDL1KEEP"] = arm64.REG_PLDL1KEEP
   284  	register["PLDL1STRM"] = arm64.REG_PLDL1STRM
   285  	register["PLDL2KEEP"] = arm64.REG_PLDL2KEEP
   286  	register["PLDL2STRM"] = arm64.REG_PLDL2STRM
   287  	register["PLDL3KEEP"] = arm64.REG_PLDL3KEEP
   288  	register["PLDL3STRM"] = arm64.REG_PLDL3STRM
   289  	register["PLIL1KEEP"] = arm64.REG_PLIL1KEEP
   290  	register["PLIL1STRM"] = arm64.REG_PLIL1STRM
   291  	register["PLIL2KEEP"] = arm64.REG_PLIL2KEEP
   292  	register["PLIL2STRM"] = arm64.REG_PLIL2STRM
   293  	register["PLIL3KEEP"] = arm64.REG_PLIL3KEEP
   294  	register["PLIL3STRM"] = arm64.REG_PLIL3STRM
   295  	register["PSTL1KEEP"] = arm64.REG_PSTL1KEEP
   296  	register["PSTL1STRM"] = arm64.REG_PSTL1STRM
   297  	register["PSTL2KEEP"] = arm64.REG_PSTL2KEEP
   298  	register["PSTL2STRM"] = arm64.REG_PSTL2STRM
   299  	register["PSTL3KEEP"] = arm64.REG_PSTL3KEEP
   300  	register["PSTL3STRM"] = arm64.REG_PSTL3STRM
   301  
   302  	// Conditional operators, like EQ, NE, etc.
   303  	register["EQ"] = arm64.COND_EQ
   304  	register["NE"] = arm64.COND_NE
   305  	register["HS"] = arm64.COND_HS
   306  	register["CS"] = arm64.COND_HS
   307  	register["LO"] = arm64.COND_LO
   308  	register["CC"] = arm64.COND_LO
   309  	register["MI"] = arm64.COND_MI
   310  	register["PL"] = arm64.COND_PL
   311  	register["VS"] = arm64.COND_VS
   312  	register["VC"] = arm64.COND_VC
   313  	register["HI"] = arm64.COND_HI
   314  	register["LS"] = arm64.COND_LS
   315  	register["GE"] = arm64.COND_GE
   316  	register["LT"] = arm64.COND_LT
   317  	register["GT"] = arm64.COND_GT
   318  	register["LE"] = arm64.COND_LE
   319  	register["AL"] = arm64.COND_AL
   320  	register["NV"] = arm64.COND_NV
   321  	// Pseudo-registers.
   322  	register["SB"] = RSB
   323  	register["FP"] = RFP
   324  	register["PC"] = RPC
   325  	register["SP"] = RSP
   326  	// Avoid unintentionally clobbering g using R28.
   327  	delete(register, "R28")
   328  	register["g"] = arm64.REG_R28
   329  	registerPrefix := map[string]bool{
   330  		"F": true,
   331  		"R": true,
   332  		"V": true,
   333  	}
   334  
   335  	instructions := make(map[string]obj.As)
   336  	for i, s := range obj.Anames {
   337  		instructions[s] = obj.As(i)
   338  	}
   339  	for i, s := range arm64.Anames {
   340  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   341  			instructions[s] = obj.As(i) + obj.ABaseARM64
   342  		}
   343  	}
   344  	// Annoying aliases.
   345  	instructions["B"] = arm64.AB
   346  	instructions["BL"] = arm64.ABL
   347  
   348  	return &Arch{
   349  		LinkArch:       &arm64.Linkarm64,
   350  		Instructions:   instructions,
   351  		Register:       register,
   352  		RegisterPrefix: registerPrefix,
   353  		RegisterNumber: arm64RegisterNumber,
   354  		IsJump:         jumpArm64,
   355  	}
   356  
   357  }
   358  
   359  func archPPC64(linkArch *obj.LinkArch) *Arch {
   360  	register := make(map[string]int16)
   361  	// Create maps for easy lookup of instruction names etc.
   362  	// Note that there is no list of names as there is for x86.
   363  	for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
   364  		register[obj.Rconv(i)] = int16(i)
   365  	}
   366  	for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
   367  		register[obj.Rconv(i)] = int16(i)
   368  	}
   369  	for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ {
   370  		register[obj.Rconv(i)] = int16(i)
   371  	}
   372  	for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ {
   373  		register[obj.Rconv(i)] = int16(i)
   374  	}
   375  	for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
   376  		register[obj.Rconv(i)] = int16(i)
   377  	}
   378  	for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
   379  		register[obj.Rconv(i)] = int16(i)
   380  	}
   381  	for i := ppc64.REG_CR0LT; i <= ppc64.REG_CR7SO; i++ {
   382  		register[obj.Rconv(i)] = int16(i)
   383  	}
   384  	register["CR"] = ppc64.REG_CR
   385  	register["XER"] = ppc64.REG_XER
   386  	register["LR"] = ppc64.REG_LR
   387  	register["CTR"] = ppc64.REG_CTR
   388  	register["FPSCR"] = ppc64.REG_FPSCR
   389  	register["MSR"] = ppc64.REG_MSR
   390  	// Pseudo-registers.
   391  	register["SB"] = RSB
   392  	register["FP"] = RFP
   393  	register["PC"] = RPC
   394  	// Avoid unintentionally clobbering g using R30.
   395  	delete(register, "R30")
   396  	register["g"] = ppc64.REG_R30
   397  	registerPrefix := map[string]bool{
   398  		"CR":  true,
   399  		"F":   true,
   400  		"R":   true,
   401  		"SPR": true,
   402  	}
   403  
   404  	instructions := make(map[string]obj.As)
   405  	for i, s := range obj.Anames {
   406  		instructions[s] = obj.As(i)
   407  	}
   408  	for i, s := range ppc64.Anames {
   409  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   410  			instructions[s] = obj.As(i) + obj.ABasePPC64
   411  		}
   412  	}
   413  	// Annoying aliases.
   414  	instructions["BR"] = ppc64.ABR
   415  	instructions["BL"] = ppc64.ABL
   416  
   417  	return &Arch{
   418  		LinkArch:       linkArch,
   419  		Instructions:   instructions,
   420  		Register:       register,
   421  		RegisterPrefix: registerPrefix,
   422  		RegisterNumber: ppc64RegisterNumber,
   423  		IsJump:         jumpPPC64,
   424  	}
   425  }
   426  
   427  func archMips(linkArch *obj.LinkArch) *Arch {
   428  	register := make(map[string]int16)
   429  	// Create maps for easy lookup of instruction names etc.
   430  	// Note that there is no list of names as there is for x86.
   431  	for i := mips.REG_R0; i <= mips.REG_R31; i++ {
   432  		register[obj.Rconv(i)] = int16(i)
   433  	}
   434  
   435  	for i := mips.REG_F0; i <= mips.REG_F31; i++ {
   436  		register[obj.Rconv(i)] = int16(i)
   437  	}
   438  	for i := mips.REG_M0; i <= mips.REG_M31; i++ {
   439  		register[obj.Rconv(i)] = int16(i)
   440  	}
   441  	for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
   442  		register[obj.Rconv(i)] = int16(i)
   443  	}
   444  	register["HI"] = mips.REG_HI
   445  	register["LO"] = mips.REG_LO
   446  	// Pseudo-registers.
   447  	register["SB"] = RSB
   448  	register["FP"] = RFP
   449  	register["PC"] = RPC
   450  	// Avoid unintentionally clobbering g using R30.
   451  	delete(register, "R30")
   452  	register["g"] = mips.REG_R30
   453  
   454  	registerPrefix := map[string]bool{
   455  		"F":   true,
   456  		"FCR": true,
   457  		"M":   true,
   458  		"R":   true,
   459  	}
   460  
   461  	instructions := make(map[string]obj.As)
   462  	for i, s := range obj.Anames {
   463  		instructions[s] = obj.As(i)
   464  	}
   465  	for i, s := range mips.Anames {
   466  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   467  			instructions[s] = obj.As(i) + obj.ABaseMIPS
   468  		}
   469  	}
   470  	// Annoying alias.
   471  	instructions["JAL"] = mips.AJAL
   472  
   473  	return &Arch{
   474  		LinkArch:       linkArch,
   475  		Instructions:   instructions,
   476  		Register:       register,
   477  		RegisterPrefix: registerPrefix,
   478  		RegisterNumber: mipsRegisterNumber,
   479  		IsJump:         jumpMIPS,
   480  	}
   481  }
   482  
   483  func archMips64(linkArch *obj.LinkArch) *Arch {
   484  	register := make(map[string]int16)
   485  	// Create maps for easy lookup of instruction names etc.
   486  	// Note that there is no list of names as there is for x86.
   487  	for i := mips.REG_R0; i <= mips.REG_R31; i++ {
   488  		register[obj.Rconv(i)] = int16(i)
   489  	}
   490  	for i := mips.REG_F0; i <= mips.REG_F31; i++ {
   491  		register[obj.Rconv(i)] = int16(i)
   492  	}
   493  	for i := mips.REG_M0; i <= mips.REG_M31; i++ {
   494  		register[obj.Rconv(i)] = int16(i)
   495  	}
   496  	for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
   497  		register[obj.Rconv(i)] = int16(i)
   498  	}
   499  	for i := mips.REG_W0; i <= mips.REG_W31; i++ {
   500  		register[obj.Rconv(i)] = int16(i)
   501  	}
   502  	register["HI"] = mips.REG_HI
   503  	register["LO"] = mips.REG_LO
   504  	// Pseudo-registers.
   505  	register["SB"] = RSB
   506  	register["FP"] = RFP
   507  	register["PC"] = RPC
   508  	// Avoid unintentionally clobbering g using R30.
   509  	delete(register, "R30")
   510  	register["g"] = mips.REG_R30
   511  	// Avoid unintentionally clobbering RSB using R28.
   512  	delete(register, "R28")
   513  	register["RSB"] = mips.REG_R28
   514  	registerPrefix := map[string]bool{
   515  		"F":   true,
   516  		"FCR": true,
   517  		"M":   true,
   518  		"R":   true,
   519  		"W":   true,
   520  	}
   521  
   522  	instructions := make(map[string]obj.As)
   523  	for i, s := range obj.Anames {
   524  		instructions[s] = obj.As(i)
   525  	}
   526  	for i, s := range mips.Anames {
   527  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   528  			instructions[s] = obj.As(i) + obj.ABaseMIPS
   529  		}
   530  	}
   531  	// Annoying alias.
   532  	instructions["JAL"] = mips.AJAL
   533  
   534  	return &Arch{
   535  		LinkArch:       linkArch,
   536  		Instructions:   instructions,
   537  		Register:       register,
   538  		RegisterPrefix: registerPrefix,
   539  		RegisterNumber: mipsRegisterNumber,
   540  		IsJump:         jumpMIPS,
   541  	}
   542  }
   543  
   544  func archRISCV64(shared bool) *Arch {
   545  	register := make(map[string]int16)
   546  
   547  	// Standard register names.
   548  	for i := riscv.REG_X0; i <= riscv.REG_X31; i++ {
   549  		// Disallow X3 in shared mode, as this will likely be used as the
   550  		// GP register, which could result in problems in non-Go code,
   551  		// including signal handlers.
   552  		if shared && i == riscv.REG_GP {
   553  			continue
   554  		}
   555  		if i == riscv.REG_TP || i == riscv.REG_G {
   556  			continue
   557  		}
   558  		name := fmt.Sprintf("X%d", i-riscv.REG_X0)
   559  		register[name] = int16(i)
   560  	}
   561  	for i := riscv.REG_F0; i <= riscv.REG_F31; i++ {
   562  		name := fmt.Sprintf("F%d", i-riscv.REG_F0)
   563  		register[name] = int16(i)
   564  	}
   565  
   566  	// General registers with ABI names.
   567  	register["ZERO"] = riscv.REG_ZERO
   568  	register["RA"] = riscv.REG_RA
   569  	register["SP"] = riscv.REG_SP
   570  	register["GP"] = riscv.REG_GP
   571  	register["TP"] = riscv.REG_TP
   572  	register["T0"] = riscv.REG_T0
   573  	register["T1"] = riscv.REG_T1
   574  	register["T2"] = riscv.REG_T2
   575  	register["S0"] = riscv.REG_S0
   576  	register["S1"] = riscv.REG_S1
   577  	register["A0"] = riscv.REG_A0
   578  	register["A1"] = riscv.REG_A1
   579  	register["A2"] = riscv.REG_A2
   580  	register["A3"] = riscv.REG_A3
   581  	register["A4"] = riscv.REG_A4
   582  	register["A5"] = riscv.REG_A5
   583  	register["A6"] = riscv.REG_A6
   584  	register["A7"] = riscv.REG_A7
   585  	register["S2"] = riscv.REG_S2
   586  	register["S3"] = riscv.REG_S3
   587  	register["S4"] = riscv.REG_S4
   588  	register["S5"] = riscv.REG_S5
   589  	register["S6"] = riscv.REG_S6
   590  	register["S7"] = riscv.REG_S7
   591  	register["S8"] = riscv.REG_S8
   592  	register["S9"] = riscv.REG_S9
   593  	register["S10"] = riscv.REG_S10
   594  	// Skip S11 as it is the g register.
   595  	register["T3"] = riscv.REG_T3
   596  	register["T4"] = riscv.REG_T4
   597  	register["T5"] = riscv.REG_T5
   598  	register["T6"] = riscv.REG_T6
   599  
   600  	// Go runtime register names.
   601  	register["g"] = riscv.REG_G
   602  	register["CTXT"] = riscv.REG_CTXT
   603  	register["TMP"] = riscv.REG_TMP
   604  
   605  	// ABI names for floating point register.
   606  	register["FT0"] = riscv.REG_FT0
   607  	register["FT1"] = riscv.REG_FT1
   608  	register["FT2"] = riscv.REG_FT2
   609  	register["FT3"] = riscv.REG_FT3
   610  	register["FT4"] = riscv.REG_FT4
   611  	register["FT5"] = riscv.REG_FT5
   612  	register["FT6"] = riscv.REG_FT6
   613  	register["FT7"] = riscv.REG_FT7
   614  	register["FS0"] = riscv.REG_FS0
   615  	register["FS1"] = riscv.REG_FS1
   616  	register["FA0"] = riscv.REG_FA0
   617  	register["FA1"] = riscv.REG_FA1
   618  	register["FA2"] = riscv.REG_FA2
   619  	register["FA3"] = riscv.REG_FA3
   620  	register["FA4"] = riscv.REG_FA4
   621  	register["FA5"] = riscv.REG_FA5
   622  	register["FA6"] = riscv.REG_FA6
   623  	register["FA7"] = riscv.REG_FA7
   624  	register["FS2"] = riscv.REG_FS2
   625  	register["FS3"] = riscv.REG_FS3
   626  	register["FS4"] = riscv.REG_FS4
   627  	register["FS5"] = riscv.REG_FS5
   628  	register["FS6"] = riscv.REG_FS6
   629  	register["FS7"] = riscv.REG_FS7
   630  	register["FS8"] = riscv.REG_FS8
   631  	register["FS9"] = riscv.REG_FS9
   632  	register["FS10"] = riscv.REG_FS10
   633  	register["FS11"] = riscv.REG_FS11
   634  	register["FT8"] = riscv.REG_FT8
   635  	register["FT9"] = riscv.REG_FT9
   636  	register["FT10"] = riscv.REG_FT10
   637  	register["FT11"] = riscv.REG_FT11
   638  
   639  	// Pseudo-registers.
   640  	register["SB"] = RSB
   641  	register["FP"] = RFP
   642  	register["PC"] = RPC
   643  
   644  	instructions := make(map[string]obj.As)
   645  	for i, s := range obj.Anames {
   646  		instructions[s] = obj.As(i)
   647  	}
   648  	for i, s := range riscv.Anames {
   649  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   650  			instructions[s] = obj.As(i) + obj.ABaseRISCV
   651  		}
   652  	}
   653  
   654  	return &Arch{
   655  		LinkArch:       &riscv.LinkRISCV64,
   656  		Instructions:   instructions,
   657  		Register:       register,
   658  		RegisterPrefix: nil,
   659  		RegisterNumber: nilRegisterNumber,
   660  		IsJump:         jumpRISCV,
   661  	}
   662  }
   663  
   664  func archS390x() *Arch {
   665  	register := make(map[string]int16)
   666  	// Create maps for easy lookup of instruction names etc.
   667  	// Note that there is no list of names as there is for x86.
   668  	for i := s390x.REG_R0; i <= s390x.REG_R15; i++ {
   669  		register[obj.Rconv(i)] = int16(i)
   670  	}
   671  	for i := s390x.REG_F0; i <= s390x.REG_F15; i++ {
   672  		register[obj.Rconv(i)] = int16(i)
   673  	}
   674  	for i := s390x.REG_V0; i <= s390x.REG_V31; i++ {
   675  		register[obj.Rconv(i)] = int16(i)
   676  	}
   677  	for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ {
   678  		register[obj.Rconv(i)] = int16(i)
   679  	}
   680  	register["LR"] = s390x.REG_LR
   681  	// Pseudo-registers.
   682  	register["SB"] = RSB
   683  	register["FP"] = RFP
   684  	register["PC"] = RPC
   685  	// Avoid unintentionally clobbering g using R13.
   686  	delete(register, "R13")
   687  	register["g"] = s390x.REG_R13
   688  	registerPrefix := map[string]bool{
   689  		"AR": true,
   690  		"F":  true,
   691  		"R":  true,
   692  	}
   693  
   694  	instructions := make(map[string]obj.As)
   695  	for i, s := range obj.Anames {
   696  		instructions[s] = obj.As(i)
   697  	}
   698  	for i, s := range s390x.Anames {
   699  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   700  			instructions[s] = obj.As(i) + obj.ABaseS390X
   701  		}
   702  	}
   703  	// Annoying aliases.
   704  	instructions["BR"] = s390x.ABR
   705  	instructions["BL"] = s390x.ABL
   706  
   707  	return &Arch{
   708  		LinkArch:       &s390x.Links390x,
   709  		Instructions:   instructions,
   710  		Register:       register,
   711  		RegisterPrefix: registerPrefix,
   712  		RegisterNumber: s390xRegisterNumber,
   713  		IsJump:         jumpS390x,
   714  	}
   715  }
   716  
   717  func archWasm() *Arch {
   718  	instructions := make(map[string]obj.As)
   719  	for i, s := range obj.Anames {
   720  		instructions[s] = obj.As(i)
   721  	}
   722  	for i, s := range wasm.Anames {
   723  		if obj.As(i) >= obj.A_ARCHSPECIFIC {
   724  			instructions[s] = obj.As(i) + obj.ABaseWasm
   725  		}
   726  	}
   727  
   728  	return &Arch{
   729  		LinkArch:       &wasm.Linkwasm,
   730  		Instructions:   instructions,
   731  		Register:       wasm.Register,
   732  		RegisterPrefix: nil,
   733  		RegisterNumber: nilRegisterNumber,
   734  		IsJump:         jumpWasm,
   735  	}
   736  }
   737  

View as plain text