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

View as plain text