github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/backend/isa/arm64/reg.go (about)

     1  package arm64
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
     9  )
    10  
    11  // Arm64-specific registers.
    12  //
    13  // See https://developer.arm.com/documentation/dui0801/a/Overview-of-AArch64-state/Predeclared-core-register-names-in-AArch64-state
    14  
    15  const (
    16  	// General purpose registers. Note that we do not distinguish wn and xn registers
    17  	// because they are the same from the perspective of register allocator, and
    18  	// the size can be determined by the type of the instruction.
    19  
    20  	x0 = regalloc.RealRegInvalid + 1 + iota
    21  	x1
    22  	x2
    23  	x3
    24  	x4
    25  	x5
    26  	x6
    27  	x7
    28  	x8
    29  	x9
    30  	x10
    31  	x11
    32  	x12
    33  	x13
    34  	x14
    35  	x15
    36  	x16
    37  	x17
    38  	x18
    39  	x19
    40  	x20
    41  	x21
    42  	x22
    43  	x23
    44  	x24
    45  	x25
    46  	x26
    47  	x27
    48  	x28
    49  	x29
    50  	x30
    51  
    52  	// Vector registers. Note that we do not distinguish vn and dn, ... registers
    53  	// because they are the same from the perspective of register allocator, and
    54  	// the size can be determined by the type of the instruction.
    55  
    56  	v0
    57  	v1
    58  	v2
    59  	v3
    60  	v4
    61  	v5
    62  	v6
    63  	v7
    64  	v8
    65  	v9
    66  	v10
    67  	v11
    68  	v12
    69  	v13
    70  	v14
    71  	v15
    72  	v16
    73  	v17
    74  	v18
    75  	v19
    76  	v20
    77  	v21
    78  	v22
    79  	v23
    80  	v24
    81  	v25
    82  	v26
    83  	v27
    84  	v28
    85  	v29
    86  	v30
    87  	v31
    88  
    89  	// Special registers
    90  
    91  	xzr
    92  	sp
    93  	lr  = x30
    94  	fp  = x29
    95  	tmp = x27
    96  )
    97  
    98  var (
    99  	x0VReg  = regalloc.FromRealReg(x0, regalloc.RegTypeInt)
   100  	x1VReg  = regalloc.FromRealReg(x1, regalloc.RegTypeInt)
   101  	x2VReg  = regalloc.FromRealReg(x2, regalloc.RegTypeInt)
   102  	x3VReg  = regalloc.FromRealReg(x3, regalloc.RegTypeInt)
   103  	x4VReg  = regalloc.FromRealReg(x4, regalloc.RegTypeInt)
   104  	x5VReg  = regalloc.FromRealReg(x5, regalloc.RegTypeInt)
   105  	x6VReg  = regalloc.FromRealReg(x6, regalloc.RegTypeInt)
   106  	x7VReg  = regalloc.FromRealReg(x7, regalloc.RegTypeInt)
   107  	x8VReg  = regalloc.FromRealReg(x8, regalloc.RegTypeInt)
   108  	x9VReg  = regalloc.FromRealReg(x9, regalloc.RegTypeInt)
   109  	x10VReg = regalloc.FromRealReg(x10, regalloc.RegTypeInt)
   110  	x11VReg = regalloc.FromRealReg(x11, regalloc.RegTypeInt)
   111  	x12VReg = regalloc.FromRealReg(x12, regalloc.RegTypeInt)
   112  	x13VReg = regalloc.FromRealReg(x13, regalloc.RegTypeInt)
   113  	x14VReg = regalloc.FromRealReg(x14, regalloc.RegTypeInt)
   114  	x15VReg = regalloc.FromRealReg(x15, regalloc.RegTypeInt)
   115  	x16VReg = regalloc.FromRealReg(x16, regalloc.RegTypeInt)
   116  	x17VReg = regalloc.FromRealReg(x17, regalloc.RegTypeInt)
   117  	x18VReg = regalloc.FromRealReg(x18, regalloc.RegTypeInt)
   118  	x19VReg = regalloc.FromRealReg(x19, regalloc.RegTypeInt)
   119  	x20VReg = regalloc.FromRealReg(x20, regalloc.RegTypeInt)
   120  	x21VReg = regalloc.FromRealReg(x21, regalloc.RegTypeInt)
   121  	x22VReg = regalloc.FromRealReg(x22, regalloc.RegTypeInt)
   122  	x23VReg = regalloc.FromRealReg(x23, regalloc.RegTypeInt)
   123  	x24VReg = regalloc.FromRealReg(x24, regalloc.RegTypeInt)
   124  	x25VReg = regalloc.FromRealReg(x25, regalloc.RegTypeInt)
   125  	x26VReg = regalloc.FromRealReg(x26, regalloc.RegTypeInt)
   126  	x27VReg = regalloc.FromRealReg(x27, regalloc.RegTypeInt)
   127  	x28VReg = regalloc.FromRealReg(x28, regalloc.RegTypeInt)
   128  	x29VReg = regalloc.FromRealReg(x29, regalloc.RegTypeInt)
   129  	x30VReg = regalloc.FromRealReg(x30, regalloc.RegTypeInt)
   130  	v0VReg  = regalloc.FromRealReg(v0, regalloc.RegTypeFloat)
   131  	v1VReg  = regalloc.FromRealReg(v1, regalloc.RegTypeFloat)
   132  	v2VReg  = regalloc.FromRealReg(v2, regalloc.RegTypeFloat)
   133  	v3VReg  = regalloc.FromRealReg(v3, regalloc.RegTypeFloat)
   134  	v4VReg  = regalloc.FromRealReg(v4, regalloc.RegTypeFloat)
   135  	v5VReg  = regalloc.FromRealReg(v5, regalloc.RegTypeFloat)
   136  	v6VReg  = regalloc.FromRealReg(v6, regalloc.RegTypeFloat)
   137  	v7VReg  = regalloc.FromRealReg(v7, regalloc.RegTypeFloat)
   138  	v8VReg  = regalloc.FromRealReg(v8, regalloc.RegTypeFloat)
   139  	v9VReg  = regalloc.FromRealReg(v9, regalloc.RegTypeFloat)
   140  	v10VReg = regalloc.FromRealReg(v10, regalloc.RegTypeFloat)
   141  	v11VReg = regalloc.FromRealReg(v11, regalloc.RegTypeFloat)
   142  	v12VReg = regalloc.FromRealReg(v12, regalloc.RegTypeFloat)
   143  	v13VReg = regalloc.FromRealReg(v13, regalloc.RegTypeFloat)
   144  	v14VReg = regalloc.FromRealReg(v14, regalloc.RegTypeFloat)
   145  	v15VReg = regalloc.FromRealReg(v15, regalloc.RegTypeFloat)
   146  	v16VReg = regalloc.FromRealReg(v16, regalloc.RegTypeFloat)
   147  	v17VReg = regalloc.FromRealReg(v17, regalloc.RegTypeFloat)
   148  	v18VReg = regalloc.FromRealReg(v18, regalloc.RegTypeFloat)
   149  	v19VReg = regalloc.FromRealReg(v19, regalloc.RegTypeFloat)
   150  	v20VReg = regalloc.FromRealReg(v20, regalloc.RegTypeFloat)
   151  	v21VReg = regalloc.FromRealReg(v21, regalloc.RegTypeFloat)
   152  	v22VReg = regalloc.FromRealReg(v22, regalloc.RegTypeFloat)
   153  	v23VReg = regalloc.FromRealReg(v23, regalloc.RegTypeFloat)
   154  	v24VReg = regalloc.FromRealReg(v24, regalloc.RegTypeFloat)
   155  	v25VReg = regalloc.FromRealReg(v25, regalloc.RegTypeFloat)
   156  	v26VReg = regalloc.FromRealReg(v26, regalloc.RegTypeFloat)
   157  	v27VReg = regalloc.FromRealReg(v27, regalloc.RegTypeFloat)
   158  	// lr (link register) holds the return address at the function entry.
   159  	lrVReg = x30VReg
   160  	// tmpReg is used to perform spill/load on large stack offsets, and load large constants.
   161  	// Therefore, be cautious to use this register in the middle of the compilation, especially before the register allocation.
   162  	// This is the same as golang/go, but it's only described in the source code:
   163  	// https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go#L59
   164  	// https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go#L13-L15
   165  	tmpRegVReg = regalloc.FromRealReg(tmp, regalloc.RegTypeInt)
   166  	v28VReg    = regalloc.FromRealReg(v28, regalloc.RegTypeFloat)
   167  	v29VReg    = regalloc.FromRealReg(v29, regalloc.RegTypeFloat)
   168  	v30VReg    = regalloc.FromRealReg(v30, regalloc.RegTypeFloat)
   169  	v31VReg    = regalloc.FromRealReg(v31, regalloc.RegTypeFloat)
   170  	xzrVReg    = regalloc.FromRealReg(xzr, regalloc.RegTypeInt)
   171  	spVReg     = regalloc.FromRealReg(sp, regalloc.RegTypeInt)
   172  	fpVReg     = regalloc.FromRealReg(fp, regalloc.RegTypeInt)
   173  )
   174  
   175  var regNames = [...]string{
   176  	x0:  "x0",
   177  	x1:  "x1",
   178  	x2:  "x2",
   179  	x3:  "x3",
   180  	x4:  "x4",
   181  	x5:  "x5",
   182  	x6:  "x6",
   183  	x7:  "x7",
   184  	x8:  "x8",
   185  	x9:  "x9",
   186  	x10: "x10",
   187  	x11: "x11",
   188  	x12: "x12",
   189  	x13: "x13",
   190  	x14: "x14",
   191  	x15: "x15",
   192  	x16: "x16",
   193  	x17: "x17",
   194  	x18: "x18",
   195  	x19: "x19",
   196  	x20: "x20",
   197  	x21: "x21",
   198  	x22: "x22",
   199  	x23: "x23",
   200  	x24: "x24",
   201  	x25: "x25",
   202  	x26: "x26",
   203  	x27: "x27",
   204  	x28: "x28",
   205  	x29: "x29",
   206  	x30: "x30",
   207  	xzr: "xzr",
   208  	sp:  "sp",
   209  	v0:  "v0",
   210  	v1:  "v1",
   211  	v2:  "v2",
   212  	v3:  "v3",
   213  	v4:  "v4",
   214  	v5:  "v5",
   215  	v6:  "v6",
   216  	v7:  "v7",
   217  	v8:  "v8",
   218  	v9:  "v9",
   219  	v10: "v10",
   220  	v11: "v11",
   221  	v12: "v12",
   222  	v13: "v13",
   223  	v14: "v14",
   224  	v15: "v15",
   225  	v16: "v16",
   226  	v17: "v17",
   227  	v18: "v18",
   228  	v19: "v19",
   229  	v20: "v20",
   230  	v21: "v21",
   231  	v22: "v22",
   232  	v23: "v23",
   233  	v24: "v24",
   234  	v25: "v25",
   235  	v26: "v26",
   236  	v27: "v27",
   237  	v28: "v28",
   238  	v29: "v29",
   239  	v30: "v30",
   240  	v31: "v31",
   241  }
   242  
   243  func formatVRegSized(r regalloc.VReg, size byte) (ret string) {
   244  	if r.IsRealReg() {
   245  		ret = regNames[r.RealReg()]
   246  		switch ret[0] {
   247  		case 'x':
   248  			switch size {
   249  			case 32:
   250  				ret = strings.Replace(ret, "x", "w", 1)
   251  			case 64:
   252  			default:
   253  				panic("BUG: invalid register size: " + strconv.Itoa(int(size)))
   254  			}
   255  		case 'v':
   256  			switch size {
   257  			case 32:
   258  				ret = strings.Replace(ret, "v", "s", 1)
   259  			case 64:
   260  				ret = strings.Replace(ret, "v", "d", 1)
   261  			case 128:
   262  				ret = strings.Replace(ret, "v", "q", 1)
   263  			default:
   264  				panic("BUG: invalid register size")
   265  			}
   266  		}
   267  	} else {
   268  		switch r.RegType() {
   269  		case regalloc.RegTypeInt:
   270  			switch size {
   271  			case 32:
   272  				ret = fmt.Sprintf("w%d?", r.ID())
   273  			case 64:
   274  				ret = fmt.Sprintf("x%d?", r.ID())
   275  			default:
   276  				panic("BUG: invalid register size: " + strconv.Itoa(int(size)))
   277  			}
   278  		case regalloc.RegTypeFloat:
   279  			switch size {
   280  			case 32:
   281  				ret = fmt.Sprintf("s%d?", r.ID())
   282  			case 64:
   283  				ret = fmt.Sprintf("d%d?", r.ID())
   284  			case 128:
   285  				ret = fmt.Sprintf("q%d?", r.ID())
   286  			default:
   287  				panic("BUG: invalid register size")
   288  			}
   289  		default:
   290  			panic(fmt.Sprintf("BUG: invalid register type: %d for %s", r.RegType(), r))
   291  		}
   292  	}
   293  	return
   294  }
   295  
   296  func formatVRegWidthVec(r regalloc.VReg, width vecArrangement) (ret string) {
   297  	var id string
   298  	wspec := strings.ToLower(width.String())
   299  	if r.IsRealReg() {
   300  		id = regNames[r.RealReg()][1:]
   301  	} else {
   302  		id = fmt.Sprintf("%d?", r.ID())
   303  	}
   304  	ret = fmt.Sprintf("%s%s", wspec, id)
   305  	return
   306  }
   307  
   308  func formatVRegVec(r regalloc.VReg, arr vecArrangement, index vecIndex) (ret string) {
   309  	id := fmt.Sprintf("v%d?", r.ID())
   310  	if r.IsRealReg() {
   311  		id = regNames[r.RealReg()]
   312  	}
   313  	ret = fmt.Sprintf("%s.%s", id, strings.ToLower(arr.String()))
   314  	if index != vecIndexNone {
   315  		ret += fmt.Sprintf("[%d]", index)
   316  	}
   317  	return
   318  }
   319  
   320  func regTypeToRegisterSizeInBits(r regalloc.RegType) byte {
   321  	switch r {
   322  	case regalloc.RegTypeInt:
   323  		return 64
   324  	case regalloc.RegTypeFloat:
   325  		return 128
   326  	default:
   327  		panic("BUG: invalid register type")
   328  	}
   329  }
   330  
   331  var regNumberInEncoding = [...]uint32{
   332  	x0:  0,
   333  	x1:  1,
   334  	x2:  2,
   335  	x3:  3,
   336  	x4:  4,
   337  	x5:  5,
   338  	x6:  6,
   339  	x7:  7,
   340  	x8:  8,
   341  	x9:  9,
   342  	x10: 10,
   343  	x11: 11,
   344  	x12: 12,
   345  	x13: 13,
   346  	x14: 14,
   347  	x15: 15,
   348  	x16: 16,
   349  	x17: 17,
   350  	x18: 18,
   351  	x19: 19,
   352  	x20: 20,
   353  	x21: 21,
   354  	x22: 22,
   355  	x23: 23,
   356  	x24: 24,
   357  	x25: 25,
   358  	x26: 26,
   359  	x27: 27,
   360  	x28: 28,
   361  	x29: 29,
   362  	x30: 30,
   363  	xzr: 31,
   364  	sp:  31,
   365  	v0:  0,
   366  	v1:  1,
   367  	v2:  2,
   368  	v3:  3,
   369  	v4:  4,
   370  	v5:  5,
   371  	v6:  6,
   372  	v7:  7,
   373  	v8:  8,
   374  	v9:  9,
   375  	v10: 10,
   376  	v11: 11,
   377  	v12: 12,
   378  	v13: 13,
   379  	v14: 14,
   380  	v15: 15,
   381  	v16: 16,
   382  	v17: 17,
   383  	v18: 18,
   384  	v19: 19,
   385  	v20: 20,
   386  	v21: 21,
   387  	v22: 22,
   388  	v23: 23,
   389  	v24: 24,
   390  	v25: 25,
   391  	v26: 26,
   392  	v27: 27,
   393  	v28: 28,
   394  	v29: 29,
   395  	v30: 30,
   396  	v31: 31,
   397  }