github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/asm/arm64/impl_1_test.go (about)

     1  package arm64
     2  
     3  import (
     4  	"encoding/hex"
     5  	"testing"
     6  
     7  	"github.com/wasilibs/wazerox/internal/asm"
     8  	"github.com/wasilibs/wazerox/internal/testing/require"
     9  )
    10  
    11  func TestNodePool_allocNode(t *testing.T) {
    12  	np := nodePool{index: nodePageSize}
    13  
    14  	for i := 0; i < nodePageSize; i++ {
    15  		n := np.allocNode()
    16  		require.Equal(t, &np.pages[0][i], n)
    17  		require.Equal(t, i+1, np.index)
    18  		require.Equal(t, 1, len(np.pages))
    19  	}
    20  	require.Equal(t, nodePageSize, np.index)
    21  
    22  	// Reached the next page.
    23  	secondPageBegin := np.allocNode()
    24  	require.Equal(t, 1, np.index)
    25  	require.Equal(t, 2, len(np.pages))
    26  	require.Equal(t, &np.pages[1][0], secondPageBegin)
    27  }
    28  
    29  func TestAssemblerImpl_Reset(t *testing.T) {
    30  	// Existing values.
    31  	code := asm.CodeSegment{}
    32  	defer func() { require.NoError(t, code.Unmap()) }()
    33  
    34  	buf := code.NextCodeSection()
    35  	buf.AppendBytes([]byte{0, 0, 0, 0, 0})
    36  
    37  	staticConsts := asm.NewStaticConstPool()
    38  	staticConsts.AddConst(asm.NewStaticConst(nil), 1234)
    39  	adrInstructionNodes := make([]*nodeImpl, 5)
    40  	relativeJumpNodes := make([]*nodeImpl, 10)
    41  	ba := asm.BaseAssemblerImpl{
    42  		SetBranchTargetOnNextNodes: make([]asm.Node, 5),
    43  		JumpTableEntries:           make([]asm.JumpTableEntry, 10),
    44  	}
    45  
    46  	// Create assembler and reset.
    47  	a := &AssemblerImpl{
    48  		nodePool: nodePool{
    49  			pages: []*nodePage{new(nodePage), new(nodePage)},
    50  			index: 12,
    51  		},
    52  		pool:                staticConsts,
    53  		temporaryRegister:   RegV2,
    54  		relativeJumpNodes:   relativeJumpNodes,
    55  		adrInstructionNodes: adrInstructionNodes,
    56  		BaseAssemblerImpl:   ba,
    57  	}
    58  	a.Reset()
    59  	buf.Reset()
    60  
    61  	// Check each field.
    62  	require.Equal(t, 65536, buf.Cap())
    63  	require.Equal(t, 0, buf.Len())
    64  
    65  	require.Zero(t, len(a.nodePool.pages))
    66  	require.Equal(t, nodePageSize, a.nodePool.index)
    67  
    68  	require.NotEqual(t, staticConsts, a.pool)
    69  
    70  	require.Equal(t, RegV2, a.temporaryRegister)
    71  
    72  	require.Equal(t, 0, len(a.adrInstructionNodes))
    73  	require.Equal(t, cap(adrInstructionNodes), cap(a.adrInstructionNodes))
    74  
    75  	require.Equal(t, 0, len(a.relativeJumpNodes))
    76  	require.Equal(t, cap(relativeJumpNodes), cap(a.relativeJumpNodes))
    77  
    78  	require.Equal(t, 0, len(a.SetBranchTargetOnNextNodes))
    79  	require.Equal(t, cap(ba.SetBranchTargetOnNextNodes), cap(a.SetBranchTargetOnNextNodes))
    80  
    81  	require.Equal(t, 0, len(a.JumpTableEntries))
    82  	require.Equal(t, cap(ba.JumpTableEntries), cap(a.JumpTableEntries))
    83  }
    84  
    85  func TestNodeImpl_AssignJumpTarget(t *testing.T) {
    86  	n := &nodeImpl{}
    87  	target := &nodeImpl{}
    88  	n.AssignJumpTarget(target)
    89  	require.Equal(t, n.jumpTarget, target)
    90  }
    91  
    92  func TestNodeImpl_AssignDestinationConstant(t *testing.T) {
    93  	n := &nodeImpl{}
    94  	n.AssignDestinationConstant(12345)
    95  	require.Equal(t, int64(12345), n.dstConst)
    96  }
    97  
    98  func TestNodeImpl_AssignSourceConstant(t *testing.T) {
    99  	n := &nodeImpl{}
   100  	n.AssignSourceConstant(12345)
   101  	require.Equal(t, int64(12345), n.srcConst)
   102  }
   103  
   104  func TestNodeImpl_String(t *testing.T) {
   105  	tests := []struct {
   106  		in  *nodeImpl
   107  		exp string
   108  	}{
   109  		{
   110  			in:  &nodeImpl{instruction: NOP, types: operandTypesNoneToNone},
   111  			exp: "NOP",
   112  		},
   113  		{
   114  			in:  &nodeImpl{instruction: BCONDEQ, types: operandTypesNoneToRegister, dstReg: RegR1},
   115  			exp: "BCONDEQ R1",
   116  		},
   117  		{
   118  			in:  &nodeImpl{instruction: BCONDNE, types: operandTypesNoneToBranch, jumpTarget: &nodeImpl{instruction: NOP}},
   119  			exp: "BCONDNE {NOP}",
   120  		},
   121  		{
   122  			in:  &nodeImpl{instruction: ADD, types: operandTypesRegisterToRegister, srcReg: RegV0, dstReg: RegV10},
   123  			exp: "ADD V0, V10",
   124  		},
   125  		{
   126  			in: &nodeImpl{
   127  				instruction: ADD, types: operandTypesLeftShiftedRegisterToRegister,
   128  				srcReg: RegR0, srcReg2: RegR11, srcConst: 4, dstReg: RegR10,
   129  			},
   130  			exp: "ADD (R0, R11 << 4), R10",
   131  		},
   132  		{
   133  			in:  &nodeImpl{instruction: ADD, types: operandTypesTwoRegistersToRegister, srcReg: RegR0, srcReg2: RegR8, dstReg: RegR10},
   134  			exp: "ADD (R0, R8), R10",
   135  		},
   136  		{
   137  			in: &nodeImpl{
   138  				instruction: MSUB, types: operandTypesThreeRegistersToRegister,
   139  				srcReg: RegR0, srcReg2: RegR8, dstReg: RegR10, dstReg2: RegR1,
   140  			},
   141  			exp: "MSUB (R0, R8, R10), R1)",
   142  		},
   143  		{
   144  			in:  &nodeImpl{instruction: CMPW, types: operandTypesTwoRegistersToNone, srcReg: RegR0, srcReg2: RegR8},
   145  			exp: "CMPW (R0, R8)",
   146  		},
   147  		{
   148  			in:  &nodeImpl{instruction: CMP, types: operandTypesRegisterAndConstToNone, srcReg: RegR0, srcConst: 0x123},
   149  			exp: "CMP (R0, 0x123)",
   150  		},
   151  		{
   152  			in:  &nodeImpl{instruction: MOVD, types: operandTypesRegisterToMemory, srcReg: RegR0, dstReg: RegR8, dstConst: 0x123},
   153  			exp: "MOVD R0, [R8 + 0x123]",
   154  		},
   155  		{
   156  			in:  &nodeImpl{instruction: MOVD, types: operandTypesRegisterToMemory, srcReg: RegR0, dstReg: RegR8, dstReg2: RegR6},
   157  			exp: "MOVD R0, [R8 + R6]",
   158  		},
   159  		{
   160  			in:  &nodeImpl{instruction: MOVD, types: operandTypesMemoryToRegister, srcReg: RegR0, srcConst: 0x123, dstReg: RegR8},
   161  			exp: "MOVD [R0 + 0x123], R8",
   162  		},
   163  		{
   164  			in:  &nodeImpl{instruction: MOVD, types: operandTypesMemoryToRegister, srcReg: RegR0, srcReg2: RegR6, dstReg: RegR8},
   165  			exp: "MOVD [R0 + R6], R8",
   166  		},
   167  		{
   168  			in:  &nodeImpl{instruction: MOVD, types: operandTypesConstToRegister, srcConst: 0x123, dstReg: RegR8},
   169  			exp: "MOVD 0x123, R8",
   170  		},
   171  		{
   172  			in: &nodeImpl{
   173  				instruction: VMOV, types: operandTypesMemoryToVectorRegister,
   174  				srcReg: RegR1, dstReg: RegV29, vectorArrangement: VectorArrangement2S,
   175  			},
   176  			exp: "VMOV [R1], V29.2S",
   177  		},
   178  		{
   179  			in: &nodeImpl{
   180  				instruction: VMOV, types: operandTypesVectorRegisterToMemory,
   181  				dstReg: RegR1, dstReg2: RegR6,
   182  				srcReg: RegV29, vectorArrangement: VectorArrangementQ,
   183  			},
   184  			exp: "VMOV V29.Q, [R1 + R6]",
   185  		},
   186  		{
   187  			in: &nodeImpl{
   188  				instruction: VMOV, types: operandTypesVectorRegisterToMemory,
   189  				dstReg: RegR1, dstConst: 0x10,
   190  				srcReg: RegV29, vectorArrangement: VectorArrangementQ,
   191  			},
   192  			exp: "VMOV V29.Q, [R1 + 0x10]",
   193  		},
   194  		{
   195  			in: &nodeImpl{
   196  				instruction: VMOV, types: operandTypesRegisterToVectorRegister,
   197  				srcReg: RegR1, dstReg: RegV29, vectorArrangement: VectorArrangement2D, dstVectorIndex: 1,
   198  			},
   199  			exp: "VMOV R1, V29.2D[1]",
   200  		},
   201  		{
   202  			in: &nodeImpl{
   203  				instruction: VCNT, types: operandTypesVectorRegisterToVectorRegister,
   204  				srcReg: RegV3, dstReg: RegV29, vectorArrangement: VectorArrangement2D, srcVectorIndex: 1,
   205  			},
   206  			exp: "VCNT V3.2D, V29.2D",
   207  		},
   208  		{
   209  			in: &nodeImpl{
   210  				instruction: VCNT, types: operandTypesVectorRegisterToVectorRegister,
   211  				srcReg: RegV3, dstReg: RegV29, vectorArrangement: VectorArrangement2D, srcVectorIndex: 1,
   212  			},
   213  			exp: "VCNT V3.2D, V29.2D",
   214  		},
   215  		{
   216  			in: &nodeImpl{
   217  				instruction: UMOV, types: operandTypesVectorRegisterToRegister,
   218  				srcReg: RegV31, dstReg: RegR8, vectorArrangement: VectorArrangementS, srcVectorIndex: 1,
   219  			},
   220  			exp: "UMOV V31.S[1], R8",
   221  		},
   222  		{
   223  			in: &nodeImpl{
   224  				instruction: UMOV, types: operandTypesTwoVectorRegistersToVectorRegister,
   225  				srcReg: RegV31, srcReg2: RegV1, dstReg: RegV8, vectorArrangement: VectorArrangementS, srcVectorIndex: 1,
   226  			},
   227  			exp: "UMOV (V31.S, V1.S), V8.S",
   228  		},
   229  		{
   230  			in: &nodeImpl{
   231  				instruction: VORR, types: operandTypesStaticConstToVectorRegister,
   232  				staticConst: &asm.StaticConst{Raw: []byte{1, 2, 3, 4}},
   233  				dstReg:      RegV8, vectorArrangement: VectorArrangement16B, srcVectorIndex: 1,
   234  			},
   235  			exp: "VORR $0x01020304 V8.16B",
   236  		},
   237  	}
   238  
   239  	for _, tt := range tests {
   240  		tc := tt
   241  		t.Run(tc.exp, func(t *testing.T) {
   242  			require.Equal(t, tc.exp, tc.in.String())
   243  		})
   244  	}
   245  }
   246  
   247  func TestAssemblerImpl_addNode(t *testing.T) {
   248  	a := NewAssembler(RegR10)
   249  
   250  	root := &nodeImpl{}
   251  	a.addNode(root)
   252  	require.Equal(t, a.root, root)
   253  	require.Equal(t, a.current, root)
   254  	require.Nil(t, root.next)
   255  
   256  	next := &nodeImpl{}
   257  	a.addNode(next)
   258  	require.Equal(t, a.root, root)
   259  	require.Equal(t, a.current, next)
   260  	require.Equal(t, next, root.next)
   261  	require.Nil(t, next.next)
   262  }
   263  
   264  func TestAssemblerImpl_newNode(t *testing.T) {
   265  	a := NewAssembler(RegR10)
   266  	actual := a.newNode(MOVD, operandTypesMemoryToRegister)
   267  	require.Equal(t, MOVD, actual.instruction)
   268  	require.Equal(t, operandTypesMemoryToRegister, actual.types)
   269  	require.Equal(t, actual, a.root)
   270  	require.Equal(t, actual, a.current)
   271  }
   272  
   273  func TestAssemblerImpl_CompileStandAlone(t *testing.T) {
   274  	a := NewAssembler(RegR10)
   275  	a.CompileStandAlone(RET)
   276  	actualNode := a.current
   277  	require.Equal(t, RET, actualNode.instruction)
   278  	require.Equal(t, operandTypesNoneToNone, actualNode.types)
   279  }
   280  
   281  func TestAssemblerImpl_CompileConstToRegister(t *testing.T) {
   282  	a := NewAssembler(RegR10)
   283  	a.CompileConstToRegister(MOVD, 1000, RegR10)
   284  	actualNode := a.current
   285  	require.Equal(t, MOVD, actualNode.instruction)
   286  	require.Equal(t, int64(1000), actualNode.srcConst)
   287  	require.Equal(t, RegR10, actualNode.dstReg)
   288  	require.Equal(t, operandTypesConstToRegister, actualNode.types)
   289  }
   290  
   291  func TestAssemblerImpl_CompileRegisterToRegister(t *testing.T) {
   292  	a := NewAssembler(RegR10)
   293  	a.CompileRegisterToRegister(MOVD, RegR15, RegR27)
   294  	actualNode := a.current
   295  	require.Equal(t, MOVD, actualNode.instruction)
   296  	require.Equal(t, RegR15, actualNode.srcReg)
   297  	require.Equal(t, RegR27, actualNode.dstReg)
   298  	require.Equal(t, operandTypesRegisterToRegister, actualNode.types)
   299  }
   300  
   301  func TestAssemblerImpl_CompileMemoryToRegister(t *testing.T) {
   302  	a := NewAssembler(RegR10)
   303  	a.CompileMemoryToRegister(MOVD, RegR15, 100, RegR27)
   304  	actualNode := a.current
   305  	require.Equal(t, MOVD, actualNode.instruction)
   306  	require.Equal(t, RegR15, actualNode.srcReg)
   307  	require.Equal(t, int64(100), actualNode.srcConst)
   308  	require.Equal(t, RegR27, actualNode.dstReg)
   309  	require.Equal(t, operandTypesMemoryToRegister, actualNode.types)
   310  }
   311  
   312  func TestAssemblerImpl_CompileRegisterToMemory(t *testing.T) {
   313  	a := NewAssembler(RegR10)
   314  	a.CompileRegisterToMemory(MOVD, RegR15, RegR27, 100)
   315  	actualNode := a.current
   316  	require.Equal(t, MOVD, actualNode.instruction)
   317  	require.Equal(t, RegR15, actualNode.srcReg)
   318  	require.Equal(t, RegR27, actualNode.dstReg)
   319  	require.Equal(t, int64(100), actualNode.dstConst)
   320  	require.Equal(t, operandTypesRegisterToMemory, actualNode.types)
   321  }
   322  
   323  func TestAssemblerImpl_CompileJump(t *testing.T) {
   324  	a := NewAssembler(RegR10)
   325  	a.CompileJump(B)
   326  	actualNode := a.current
   327  	require.Equal(t, B, actualNode.instruction)
   328  	require.Equal(t, operandTypesNoneToBranch, actualNode.types)
   329  }
   330  
   331  func TestAssemblerImpl_CompileJumpToRegister(t *testing.T) {
   332  	a := NewAssembler(RegR10)
   333  	a.CompileJumpToRegister(BCONDNE, RegR27)
   334  	actualNode := a.current
   335  	require.Equal(t, BCONDNE, actualNode.instruction)
   336  	require.Equal(t, RegR27, actualNode.dstReg)
   337  	require.Equal(t, operandTypesNoneToRegister, actualNode.types)
   338  }
   339  
   340  func TestAssemblerImpl_CompileReadInstructionAddress(t *testing.T) {
   341  	a := NewAssembler(RegR10)
   342  	a.CompileReadInstructionAddress(RegR10, RET)
   343  	actualNode := a.current
   344  	require.Equal(t, ADR, actualNode.instruction)
   345  	require.Equal(t, RegR10, actualNode.dstReg)
   346  	require.Equal(t, operandTypesMemoryToRegister, actualNode.types)
   347  	require.Equal(t, RET, actualNode.readInstructionAddressBeforeTargetInstruction)
   348  }
   349  
   350  func Test_CompileMemoryWithRegisterOffsetToRegister(t *testing.T) {
   351  	a := NewAssembler(RegR10)
   352  	a.CompileMemoryWithRegisterOffsetToRegister(MOVD, RegR27, RegR10, RegR0)
   353  	actualNode := a.current
   354  	require.Equal(t, MOVD, actualNode.instruction)
   355  	require.Equal(t, RegR27, actualNode.srcReg)
   356  	require.Equal(t, RegR10, actualNode.srcReg2)
   357  	require.Equal(t, RegR0, actualNode.dstReg)
   358  	require.Equal(t, operandTypesMemoryToRegister, actualNode.types)
   359  }
   360  
   361  func Test_CompileMemoryWithRegisterOffsetToVectorRegister(t *testing.T) {
   362  	a := NewAssembler(RegR10)
   363  	a.CompileMemoryWithRegisterOffsetToVectorRegister(MOVD, RegR27, RegR10, RegV31, VectorArrangementS)
   364  	actualNode := a.current
   365  	require.Equal(t, MOVD, actualNode.instruction)
   366  	require.Equal(t, RegR27, actualNode.srcReg)
   367  	require.Equal(t, RegR10, actualNode.srcReg2)
   368  	require.Equal(t, RegV31, actualNode.dstReg)
   369  	require.Equal(t, VectorArrangementS, actualNode.vectorArrangement)
   370  	require.Equal(t, operandTypesMemoryToVectorRegister, actualNode.types)
   371  }
   372  
   373  func Test_CompileRegisterToMemoryWithRegisterOffset(t *testing.T) {
   374  	a := NewAssembler(RegR10)
   375  	a.CompileRegisterToMemoryWithRegisterOffset(MOVD, RegR27, RegR10, RegR0)
   376  	actualNode := a.current
   377  	require.Equal(t, MOVD, actualNode.instruction)
   378  	require.Equal(t, RegR27, actualNode.srcReg)
   379  	require.Equal(t, RegR10, actualNode.dstReg)
   380  	require.Equal(t, RegR0, actualNode.dstReg2)
   381  	require.Equal(t, operandTypesRegisterToMemory, actualNode.types)
   382  }
   383  
   384  func Test_CompileVectorRegisterToMemoryWithRegisterOffset(t *testing.T) {
   385  	a := NewAssembler(RegR10)
   386  	a.CompileVectorRegisterToMemoryWithRegisterOffset(MOVD, RegV31, RegR10, RegR0, VectorArrangement2D)
   387  	actualNode := a.current
   388  	require.Equal(t, MOVD, actualNode.instruction)
   389  	require.Equal(t, RegV31, actualNode.srcReg)
   390  	require.Equal(t, RegR10, actualNode.dstReg)
   391  	require.Equal(t, RegR0, actualNode.dstReg2)
   392  	require.Equal(t, VectorArrangement2D, actualNode.vectorArrangement)
   393  	require.Equal(t, operandTypesVectorRegisterToMemory, actualNode.types)
   394  }
   395  
   396  func Test_CompileTwoRegistersToRegister(t *testing.T) {
   397  	a := NewAssembler(RegR10)
   398  	a.CompileTwoRegistersToRegister(MOVD, RegR27, RegR10, RegR0)
   399  	actualNode := a.current
   400  	require.Equal(t, MOVD, actualNode.instruction)
   401  	require.Equal(t, RegR27, actualNode.srcReg)
   402  	require.Equal(t, RegR10, actualNode.srcReg2)
   403  	require.Equal(t, RegR0, actualNode.dstReg)
   404  	require.Equal(t, operandTypesTwoRegistersToRegister, actualNode.types)
   405  }
   406  
   407  func Test_CompileThreeRegistersToRegister(t *testing.T) {
   408  	a := NewAssembler(RegR10)
   409  	a.CompileThreeRegistersToRegister(MOVD, RegR27, RegR10, RegR0, RegR28)
   410  	actualNode := a.current
   411  	require.Equal(t, MOVD, actualNode.instruction)
   412  	require.Equal(t, RegR27, actualNode.srcReg)
   413  	require.Equal(t, RegR10, actualNode.srcReg2)
   414  	require.Equal(t, RegR0, actualNode.dstReg)
   415  	require.Equal(t, RegR28, actualNode.dstReg2)
   416  	require.Equal(t, operandTypesThreeRegistersToRegister, actualNode.types)
   417  }
   418  
   419  func Test_CompileTwoRegistersToNone(t *testing.T) {
   420  	a := NewAssembler(RegR10)
   421  	a.CompileTwoRegistersToNone(CMP, RegR27, RegR10)
   422  	actualNode := a.current
   423  	require.Equal(t, CMP, actualNode.instruction)
   424  	require.Equal(t, RegR27, actualNode.srcReg)
   425  	require.Equal(t, RegR10, actualNode.srcReg2)
   426  	require.Equal(t, operandTypesTwoRegistersToNone, actualNode.types)
   427  }
   428  
   429  func Test_CompileRegisterAndConstToNone(t *testing.T) {
   430  	a := NewAssembler(RegR10)
   431  	a.CompileRegisterAndConstToNone(CMP, RegR27, 10)
   432  	actualNode := a.current
   433  	require.Equal(t, CMP, actualNode.instruction)
   434  	require.Equal(t, RegR27, actualNode.srcReg)
   435  	require.Equal(t, int64(10), actualNode.srcConst)
   436  	require.Equal(t, operandTypesRegisterAndConstToNone, actualNode.types)
   437  }
   438  
   439  func Test_CompileRegisterAndConstToRegister(t *testing.T) {
   440  	a := NewAssembler(RegR10)
   441  	a.CompileRegisterAndConstToRegister(CMP, RegR27, 10, RegSP)
   442  	actualNode := a.current
   443  	require.Equal(t, CMP, actualNode.instruction)
   444  	require.Equal(t, RegR27, actualNode.srcReg)
   445  	require.Equal(t, int64(10), actualNode.srcConst)
   446  	require.Equal(t, RegSP, actualNode.dstReg)
   447  	require.Equal(t, operandTypesRegisterAndConstToRegister, actualNode.types)
   448  }
   449  
   450  func Test_CompileLeftShiftedRegisterToRegister(t *testing.T) {
   451  	a := NewAssembler(RegR10)
   452  	a.CompileLeftShiftedRegisterToRegister(ADD, RegR27, 10, RegR28, RegR5)
   453  	actualNode := a.current
   454  	require.Equal(t, ADD, actualNode.instruction)
   455  	require.Equal(t, RegR28, actualNode.srcReg)
   456  	require.Equal(t, RegR27, actualNode.srcReg2)
   457  	require.Equal(t, int64(10), actualNode.srcConst)
   458  	require.Equal(t, RegR5, actualNode.dstReg)
   459  	require.Equal(t, operandTypesLeftShiftedRegisterToRegister, actualNode.types)
   460  }
   461  
   462  func Test_CompileConditionalRegisterSet(t *testing.T) {
   463  	a := NewAssembler(RegR10)
   464  	a.CompileConditionalRegisterSet(CondNE, RegR10)
   465  	actualNode := a.current
   466  	require.Equal(t, CSET, actualNode.instruction)
   467  	require.Equal(t, RegCondNE, actualNode.srcReg)
   468  	require.Equal(t, RegR10, actualNode.dstReg)
   469  	require.Equal(t, operandTypesRegisterToRegister, actualNode.types)
   470  }
   471  
   472  func Test_CompileMemoryToVectorRegister(t *testing.T) {
   473  	a := NewAssembler(RegR10)
   474  	a.CompileMemoryToVectorRegister(VMOV, RegR10, 10, RegV3, VectorArrangement1D)
   475  	actualNode := a.current
   476  	require.Equal(t, VMOV, actualNode.instruction)
   477  	require.Equal(t, RegR10, actualNode.srcReg)
   478  	require.Equal(t, int64(10), actualNode.srcConst)
   479  	require.Equal(t, RegV3, actualNode.dstReg)
   480  	require.Equal(t, operandTypesMemoryToVectorRegister, actualNode.types)
   481  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   482  }
   483  
   484  func Test_CompileVectorRegisterToMemory(t *testing.T) {
   485  	a := NewAssembler(RegR10)
   486  	a.CompileVectorRegisterToMemory(VMOV, RegV3, RegR10, 12, VectorArrangement1D)
   487  	actualNode := a.current
   488  	require.Equal(t, VMOV, actualNode.instruction)
   489  	require.Equal(t, RegV3, actualNode.srcReg)
   490  	require.Equal(t, RegR10, actualNode.dstReg)
   491  	require.Equal(t, int64(12), actualNode.dstConst)
   492  	require.Equal(t, operandTypesVectorRegisterToMemory, actualNode.types)
   493  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   494  }
   495  
   496  func Test_CompileRegisterToVectorRegister(t *testing.T) {
   497  	a := NewAssembler(RegR10)
   498  	a.CompileRegisterToVectorRegister(VMOV, RegV3, RegR10, VectorArrangement1D, 10)
   499  	actualNode := a.current
   500  	require.Equal(t, VMOV, actualNode.instruction)
   501  	require.Equal(t, RegV3, actualNode.srcReg)
   502  	require.Equal(t, RegR10, actualNode.dstReg)
   503  	require.Equal(t, operandTypesRegisterToVectorRegister, actualNode.types)
   504  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   505  	require.Equal(t, VectorIndex(10), actualNode.dstVectorIndex)
   506  }
   507  
   508  func Test_CompileVectorRegisterToRegister(t *testing.T) {
   509  	a := NewAssembler(RegR10)
   510  	a.CompileVectorRegisterToRegister(VMOV, RegR10, RegV3, VectorArrangement1D, 10)
   511  	actualNode := a.current
   512  	require.Equal(t, VMOV, actualNode.instruction)
   513  	require.Equal(t, RegR10, actualNode.srcReg)
   514  	require.Equal(t, RegV3, actualNode.dstReg)
   515  	require.Equal(t, operandTypesVectorRegisterToRegister, actualNode.types)
   516  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   517  	require.Equal(t, VectorIndex(10), actualNode.srcVectorIndex)
   518  }
   519  
   520  func Test_CompileVectorRegisterToVectorRegister(t *testing.T) {
   521  	a := NewAssembler(RegR10)
   522  	a.CompileVectorRegisterToVectorRegister(VMOV, RegV3, RegV10, VectorArrangement1D, 1, 2)
   523  	actualNode := a.current
   524  	require.Equal(t, VMOV, actualNode.instruction)
   525  	require.Equal(t, RegV3, actualNode.srcReg)
   526  	require.Equal(t, RegV10, actualNode.dstReg)
   527  	require.Equal(t, operandTypesVectorRegisterToVectorRegister, actualNode.types)
   528  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   529  	require.Equal(t, VectorIndex(1), actualNode.srcVectorIndex)
   530  	require.Equal(t, VectorIndex(2), actualNode.dstVectorIndex)
   531  }
   532  
   533  func Test_CompileVectorRegisterToVectorRegisterWithConst(t *testing.T) {
   534  	a := NewAssembler(RegR10)
   535  	a.CompileVectorRegisterToVectorRegisterWithConst(VMOV, RegV3, RegV10, VectorArrangement1D, 1234)
   536  	actualNode := a.current
   537  	require.Equal(t, VMOV, actualNode.instruction)
   538  	require.Equal(t, RegV3, actualNode.srcReg)
   539  	require.Equal(t, RegV10, actualNode.dstReg)
   540  	require.Equal(t, operandTypesVectorRegisterToVectorRegister, actualNode.types)
   541  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   542  	require.Equal(t, int64(1234), actualNode.srcConst)
   543  }
   544  
   545  func Test_CompileTwoVectorRegistersToVectorRegister(t *testing.T) {
   546  	a := NewAssembler(RegR10)
   547  	a.CompileTwoVectorRegistersToVectorRegister(VMOV, RegV3, RegV15, RegV10, VectorArrangement1D)
   548  	actualNode := a.current
   549  	require.Equal(t, VMOV, actualNode.instruction)
   550  	require.Equal(t, RegV3, actualNode.srcReg)
   551  	require.Equal(t, RegV15, actualNode.srcReg2)
   552  	require.Equal(t, RegV10, actualNode.dstReg)
   553  	require.Equal(t, operandTypesTwoVectorRegistersToVectorRegister, actualNode.types)
   554  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   555  }
   556  
   557  func Test_CompileTwoVectorRegistersToVectorRegisterWithConst(t *testing.T) {
   558  	a := NewAssembler(RegR10)
   559  	a.CompileTwoVectorRegistersToVectorRegisterWithConst(VMOV, RegV3, RegV15, RegV10, VectorArrangement1D, 1234)
   560  	actualNode := a.current
   561  	require.Equal(t, VMOV, actualNode.instruction)
   562  	require.Equal(t, RegV3, actualNode.srcReg)
   563  	require.Equal(t, RegV15, actualNode.srcReg2)
   564  	require.Equal(t, int64(1234), actualNode.srcConst)
   565  	require.Equal(t, RegV10, actualNode.dstReg)
   566  	require.Equal(t, operandTypesTwoVectorRegistersToVectorRegister, actualNode.types)
   567  	require.Equal(t, VectorArrangement1D, actualNode.vectorArrangement)
   568  }
   569  
   570  func Test_CompileStaticConstToVectorRegister(t *testing.T) {
   571  	s := asm.NewStaticConst([]byte{1, 2, 3, 4})
   572  	a := NewAssembler(RegR10)
   573  	a.CompileStaticConstToVectorRegister(VMOV, s, RegV3, VectorArrangement2D)
   574  	actualNode := a.current
   575  	require.Equal(t, VMOV, actualNode.instruction)
   576  	require.Equal(t, s, actualNode.staticConst)
   577  	require.Equal(t, RegV3, actualNode.dstReg)
   578  	require.Equal(t, operandTypesStaticConstToVectorRegister, actualNode.types)
   579  	require.Equal(t, VectorArrangement2D, actualNode.vectorArrangement)
   580  }
   581  
   582  func Test_CompileStaticConstToRegister(t *testing.T) {
   583  	s := asm.NewStaticConst([]byte{1, 2, 3, 4})
   584  	a := NewAssembler(RegR10)
   585  	a.CompileStaticConstToRegister(ADR, s, RegR27)
   586  	actualNode := a.current
   587  	require.Equal(t, ADR, actualNode.instruction)
   588  	require.Equal(t, s, actualNode.staticConst)
   589  	require.Equal(t, RegR27, actualNode.dstReg)
   590  	require.Equal(t, operandTypesMemoryToRegister, actualNode.types)
   591  }
   592  
   593  func Test_checkRegisterToRegisterType(t *testing.T) {
   594  	tests := []struct {
   595  		expErr        string
   596  		src           asm.Register
   597  		dst           asm.Register
   598  		requireSrcInt bool
   599  		requireDstInt bool
   600  	}{
   601  		{src: RegR10, dst: RegR30, requireSrcInt: true, requireDstInt: true, expErr: ""},
   602  		{src: RegR10, dst: RegR30, requireSrcInt: false, requireDstInt: true, expErr: "src requires float register but got R10"},
   603  		{src: RegR10, dst: RegR30, requireSrcInt: false, requireDstInt: false, expErr: "src requires float register but got R10"},
   604  		{src: RegR10, dst: RegR30, requireSrcInt: true, requireDstInt: false, expErr: "dst requires float register but got R30"},
   605  
   606  		{src: RegR10, dst: RegV30, requireSrcInt: true, requireDstInt: false, expErr: ""},
   607  		{src: RegR10, dst: RegV30, requireSrcInt: false, requireDstInt: true, expErr: "src requires float register but got R10"},
   608  		{src: RegR10, dst: RegV30, requireSrcInt: false, requireDstInt: false, expErr: "src requires float register but got R10"},
   609  		{src: RegR10, dst: RegV30, requireSrcInt: true, requireDstInt: true, expErr: "dst requires int register but got V30"},
   610  
   611  		{src: RegV10, dst: RegR30, requireSrcInt: false, requireDstInt: true, expErr: ""},
   612  		{src: RegV10, dst: RegR30, requireSrcInt: true, requireDstInt: true, expErr: "src requires int register but got V10"},
   613  		{src: RegV10, dst: RegR30, requireSrcInt: true, requireDstInt: false, expErr: "src requires int register but got V10"},
   614  		{src: RegV10, dst: RegR30, requireSrcInt: false, requireDstInt: false, expErr: "dst requires float register but got R30"},
   615  
   616  		{src: RegV10, dst: RegV30, requireSrcInt: false, requireDstInt: false, expErr: ""},
   617  		{src: RegV10, dst: RegV30, requireSrcInt: true, requireDstInt: false, expErr: "src requires int register but got V10"},
   618  		{src: RegV10, dst: RegV30, requireSrcInt: true, requireDstInt: true, expErr: "src requires int register but got V10"},
   619  		{src: RegV10, dst: RegV30, requireSrcInt: false, requireDstInt: true, expErr: "dst requires int register but got V30"},
   620  	}
   621  
   622  	for _, tt := range tests {
   623  		tc := tt
   624  		actual := checkRegisterToRegisterType(tc.src, tc.dst, tc.requireSrcInt, tc.requireDstInt)
   625  		if tc.expErr != "" {
   626  			require.EqualError(t, actual, tc.expErr)
   627  		} else {
   628  			require.NoError(t, actual)
   629  		}
   630  	}
   631  }
   632  
   633  func TestAssemblerImpl_encodeNoneToNone(t *testing.T) {
   634  	t.Run("error", func(t *testing.T) {
   635  		code := asm.CodeSegment{}
   636  		defer func() { require.NoError(t, code.Unmap()) }()
   637  
   638  		a := NewAssembler(asm.NilRegister)
   639  		buf := code.NextCodeSection()
   640  		err := a.encodeNoneToNone(buf, &nodeImpl{instruction: ADD})
   641  		require.EqualError(t, err, "ADD is unsupported for NoneToNone type")
   642  	})
   643  	t.Run("NOP", func(t *testing.T) {
   644  		code := asm.CodeSegment{}
   645  		defer func() { require.NoError(t, code.Unmap()) }()
   646  
   647  		a := NewAssembler(asm.NilRegister)
   648  		buf := code.NextCodeSection()
   649  		err := a.encodeNoneToNone(buf, &nodeImpl{instruction: NOP})
   650  		require.NoError(t, err)
   651  
   652  		// NOP must be ignored.
   653  		actual := buf.Bytes()
   654  		require.Zero(t, len(actual))
   655  	})
   656  	t.Run("UDF", func(t *testing.T) {
   657  		code := asm.CodeSegment{}
   658  		defer func() { require.NoError(t, code.Unmap()) }()
   659  
   660  		a := NewAssembler(asm.NilRegister)
   661  		buf := code.NextCodeSection()
   662  		err := a.encodeNoneToNone(buf, &nodeImpl{instruction: UDF})
   663  		require.NoError(t, err)
   664  
   665  		actual := buf.Bytes()
   666  		require.Equal(t, []byte{0x0, 0x0, 0x0, 0x0}, actual, hex.EncodeToString(actual))
   667  	})
   668  }
   669  
   670  func Test_validateMemoryOffset(t *testing.T) {
   671  	tests := []struct {
   672  		expErr string
   673  		offset int64
   674  	}{
   675  		{offset: 0},
   676  		{offset: -256},
   677  		{offset: 255},
   678  		{offset: 123 * 8},
   679  		{offset: 123 * 4},
   680  		{offset: -257, expErr: "negative memory offset must be larget than or equal -256 but got -257"},
   681  		{offset: 257, expErr: "large memory offset (>255) must be a multiple of 4 but got 257"},
   682  	}
   683  
   684  	for _, tt := range tests {
   685  		tc := tt
   686  		actual := validateMemoryOffset(tc.offset)
   687  		if tc.expErr == "" {
   688  			require.NoError(t, actual)
   689  		} else {
   690  			require.EqualError(t, actual, tc.expErr)
   691  		}
   692  	}
   693  }
   694  
   695  func TestAssemblerImpl_EncodeVectorRegisterToMemory(t *testing.T) {
   696  	tests := []struct {
   697  		name string
   698  		n    *nodeImpl
   699  		exp  []byte
   700  	}{
   701  		// Register offset cases.
   702  		{
   703  			name: "str b11, [x12, x6]",
   704  			n: &nodeImpl{
   705  				instruction:       VMOV,
   706  				srcReg:            RegV11,
   707  				dstReg:            RegR12,
   708  				dstReg2:           RegR6,
   709  				vectorArrangement: VectorArrangementB,
   710  			},
   711  			exp: []byte{0x8b, 0x69, 0x26, 0x3c},
   712  		},
   713  		{
   714  			name: "str h11, [x12, x6]",
   715  			n: &nodeImpl{
   716  				instruction:       VMOV,
   717  				srcReg:            RegV11,
   718  				dstReg:            RegR0,
   719  				dstReg2:           RegR6,
   720  				vectorArrangement: VectorArrangementH,
   721  			},
   722  			exp: []byte{0xb, 0x68, 0x26, 0x7c},
   723  		},
   724  		{
   725  			name: "str s11, [x29, x6]",
   726  			n: &nodeImpl{
   727  				instruction:       VMOV,
   728  				srcReg:            RegV11,
   729  				dstReg:            RegR29,
   730  				dstReg2:           RegR6,
   731  				vectorArrangement: VectorArrangementS,
   732  			},
   733  			exp: []byte{0xab, 0x6b, 0x26, 0xbc},
   734  		},
   735  		{
   736  			name: "str d0, [x0, x0]",
   737  			n: &nodeImpl{
   738  				instruction:       VMOV,
   739  				srcReg:            RegV0,
   740  				dstReg:            RegR0,
   741  				dstReg2:           RegR0,
   742  				vectorArrangement: VectorArrangementD,
   743  			},
   744  			exp: []byte{0x0, 0x68, 0x20, 0xfc},
   745  		},
   746  		{
   747  			name: "str q30, [x30, x29]",
   748  			n: &nodeImpl{
   749  				instruction:       VMOV,
   750  				srcReg:            RegV30,
   751  				dstReg:            RegR30,
   752  				dstReg2:           RegR29,
   753  				vectorArrangement: VectorArrangementQ,
   754  			},
   755  			exp: []byte{0xde, 0x6b, 0xbd, 0x3c},
   756  		},
   757  		// Constant offset cases.
   758  		{
   759  			name: "str b11, [x12, #0x7b]",
   760  			n: &nodeImpl{
   761  				instruction:       VMOV,
   762  				srcReg:            RegV11,
   763  				dstReg:            RegR12,
   764  				dstConst:          0x7b,
   765  				vectorArrangement: VectorArrangementB,
   766  			},
   767  			exp: []byte{0x8b, 0xed, 0x1, 0x3d},
   768  		},
   769  		{
   770  			name: "ldr w10, #0xc ; str h11, [x12, x10]",
   771  			n: &nodeImpl{
   772  				instruction:       VMOV,
   773  				srcReg:            RegV11,
   774  				dstReg:            RegR12,
   775  				dstConst:          1 << 30,
   776  				vectorArrangement: VectorArrangementH,
   777  			},
   778  			exp: []byte{0x6a, 0x0, 0x0, 0x18, 0x8b, 0x69, 0x2a, 0x7c, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x40},
   779  		},
   780  		{
   781  			name: "ldr w10, #0xc ; str s11, [x12, x10]",
   782  			n: &nodeImpl{
   783  				instruction:       VMOV,
   784  				srcReg:            RegV11,
   785  				dstReg:            RegR12,
   786  				dstConst:          (1 << 28) + 4,
   787  				vectorArrangement: VectorArrangementS,
   788  			},
   789  			exp: []byte{0x6a, 0x0, 0x0, 0x18, 0x8b, 0x69, 0x2a, 0xbc, 0x0, 0x0, 0x0, 0x14, 0x4, 0x0, 0x0, 0x10},
   790  		},
   791  		{
   792  			name: "str d11, [x12, #0x3d8]",
   793  			n: &nodeImpl{
   794  				instruction:       VMOV,
   795  				srcReg:            RegV11,
   796  				dstReg:            RegR12,
   797  				dstConst:          0x3d8,
   798  				vectorArrangement: VectorArrangementD,
   799  			},
   800  			exp: []byte{0x8b, 0xed, 0x1, 0xfd},
   801  		},
   802  		{
   803  			name: "stur q1, [x30, #1]",
   804  			n: &nodeImpl{
   805  				instruction:       VMOV,
   806  				srcReg:            RegV1,
   807  				dstReg:            RegR30,
   808  				dstConst:          1,
   809  				vectorArrangement: VectorArrangementQ,
   810  			},
   811  			exp: []byte{0xc1, 0x13, 0x80, 0x3c},
   812  		},
   813  		{
   814  			name: "str q1, [x30, #0x100]",
   815  			n: &nodeImpl{
   816  				instruction:       VMOV,
   817  				srcReg:            RegV1,
   818  				dstReg:            RegR30,
   819  				dstConst:          0x100,
   820  				vectorArrangement: VectorArrangementQ,
   821  			},
   822  			exp: []byte{0xc1, 0x43, 0x80, 0x3d},
   823  		},
   824  		{
   825  			name: "stur q1, [x30, #0xfc]",
   826  			n: &nodeImpl{
   827  				instruction: VMOV,
   828  				srcReg:      RegV1,
   829  				dstReg:      RegR30,
   830  				// This offset is not a multiple of 16 bytes, but fits in 9-bit signed integer,
   831  				// therefore it can be encoded as one instruction of "unscaled immediate".
   832  				dstConst:          0xfc,
   833  				vectorArrangement: VectorArrangementQ,
   834  			},
   835  			exp: []byte{0xc1, 0xc3, 0x8f, 0x3c},
   836  		},
   837  		{
   838  			name: `ldr w10, #0xc; str q11, [x12, x10]`,
   839  			n: &nodeImpl{
   840  				instruction: VMOV,
   841  				srcReg:      RegV11,
   842  				dstReg:      RegR12,
   843  				// This case offset is not a multiple of 16 bytes and doesn't fit in 9-bit signed integer,
   844  				// therefore, we encode the offset in a temporary register, then store it with the register offset variant.
   845  				dstConst:          0x108,
   846  				vectorArrangement: VectorArrangementQ,
   847  			},
   848  			exp: []byte{0x6a, 0x0, 0x0, 0x18, 0x8b, 0x69, 0xaa, 0x3c, 0x0, 0x0, 0x0, 0x14, 0x8, 0x1, 0x0, 0x0},
   849  		},
   850  	}
   851  
   852  	for _, tt := range tests {
   853  		tc := tt
   854  		t.Run(tc.name, func(t *testing.T) {
   855  			code := asm.CodeSegment{}
   856  			defer func() { require.NoError(t, code.Unmap()) }()
   857  
   858  			a := NewAssembler(RegR10)
   859  			buf := code.NextCodeSection()
   860  			err := a.encodeVectorRegisterToMemory(buf, tc.n)
   861  			require.NoError(t, err)
   862  
   863  			a.maybeFlushConstPool(buf, true)
   864  
   865  			err = a.Assemble(buf)
   866  			require.NoError(t, err)
   867  
   868  			actual := buf.Bytes()
   869  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
   870  		})
   871  	}
   872  }
   873  
   874  func TestAssemblerImpl_EncodeMemoryToVectorRegister(t *testing.T) {
   875  	tests := []struct {
   876  		name string
   877  		n    *nodeImpl
   878  		exp  []byte
   879  	}{
   880  		// ldr Register offset cases.
   881  		{
   882  			name: "ldr b11, [x12, x8]",
   883  			n: &nodeImpl{
   884  				instruction:       VMOV,
   885  				srcReg:            RegR12,
   886  				srcReg2:           RegR8,
   887  				dstReg:            RegV11,
   888  				vectorArrangement: VectorArrangementB,
   889  			},
   890  			exp: []byte{0x8b, 0x69, 0x68, 0x3c},
   891  		},
   892  		{
   893  			name: "ldr h11, [x30, x0]",
   894  			n: &nodeImpl{
   895  				instruction:       VMOV,
   896  				srcReg:            RegR30,
   897  				srcReg2:           RegR0,
   898  				dstReg:            RegV11,
   899  				vectorArrangement: VectorArrangementH,
   900  			},
   901  			exp: []byte{0xcb, 0x6b, 0x60, 0x7c},
   902  		},
   903  		{
   904  			name: "ldr s11, [x0, x30]",
   905  			n: &nodeImpl{
   906  				instruction:       VMOV,
   907  				srcReg:            RegR0,
   908  				srcReg2:           RegR30,
   909  				dstReg:            RegV11,
   910  				vectorArrangement: VectorArrangementS,
   911  			},
   912  			exp: []byte{0xb, 0x68, 0x7e, 0xbc},
   913  		},
   914  		{
   915  			name: "ldr d11, [x15, x15]",
   916  			n: &nodeImpl{
   917  				instruction:       VMOV,
   918  				srcReg:            RegR15,
   919  				srcReg2:           RegR15,
   920  				dstReg:            RegV11,
   921  				vectorArrangement: VectorArrangementD,
   922  			},
   923  			exp: []byte{0xeb, 0x69, 0x6f, 0xfc},
   924  		},
   925  		{
   926  			name: "ldr q30, [x0, x0]",
   927  			n: &nodeImpl{
   928  				instruction:       VMOV,
   929  				srcReg:            RegR0,
   930  				srcReg2:           RegR0,
   931  				dstReg:            RegV30,
   932  				vectorArrangement: VectorArrangementQ,
   933  			},
   934  			exp: []byte{0x1e, 0x68, 0xe0, 0x3c},
   935  		},
   936  		// ldr Constant offset cases.
   937  		{
   938  			name: "ldr b11, [x12, #0x7b]",
   939  			n: &nodeImpl{
   940  				instruction:       VMOV,
   941  				srcReg:            RegR12,
   942  				srcConst:          0x7b,
   943  				dstReg:            RegV11,
   944  				vectorArrangement: VectorArrangementB,
   945  			},
   946  			exp: []byte{0x8b, 0xed, 0x41, 0x3d},
   947  		},
   948  		{
   949  			name: "str h11, [x12, w30, uxtw]",
   950  			n: &nodeImpl{
   951  				instruction:       VMOV,
   952  				dstReg:            RegV11,
   953  				srcReg:            RegR12,
   954  				vectorArrangement: VectorArrangementH,
   955  			},
   956  			exp: []byte{0x8b, 0x1, 0x40, 0x7d},
   957  		},
   958  		{
   959  			name: "ldr w10, #0xc ; ldr s11, [x12, x10]",
   960  			n: &nodeImpl{
   961  				instruction:       VMOV,
   962  				dstReg:            RegV11,
   963  				srcReg:            RegR12,
   964  				srcConst:          1 << 28,
   965  				vectorArrangement: VectorArrangementS,
   966  			},
   967  			exp: []byte{0x6a, 0x0, 0x0, 0x18, 0x8b, 0x69, 0x6a, 0xbc, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x10},
   968  		},
   969  		{
   970  			name: "ldr w10, #0xc ; ldr d11, [x12, x10]",
   971  			n: &nodeImpl{
   972  				instruction:       VMOV,
   973  				dstReg:            RegV11,
   974  				srcReg:            RegR12,
   975  				srcConst:          1<<29 + 4,
   976  				vectorArrangement: VectorArrangementD,
   977  			},
   978  			exp: []byte{0x6a, 0x0, 0x0, 0x18, 0x8b, 0x69, 0x6a, 0xfc, 0x0, 0x0, 0x0, 0x14, 0x4, 0x0, 0x0, 0x20},
   979  		},
   980  		{
   981  			name: "ldr w10, #0xc ; ldr q1, [x30, x10]",
   982  			n: &nodeImpl{
   983  				instruction:       VMOV,
   984  				dstReg:            RegV1,
   985  				srcReg:            RegR30,
   986  				srcConst:          1<<17 + 4,
   987  				vectorArrangement: VectorArrangementQ,
   988  			},
   989  			exp: []byte{0x6a, 0x0, 0x0, 0x18, 0xc1, 0x6b, 0xea, 0x3c, 0x0, 0x0, 0x0, 0x14, 0x4, 0x0, 0x2, 0x0},
   990  		},
   991  		{
   992  			name: "ld1r {v11.8b}, [x12]",
   993  			n: &nodeImpl{
   994  				instruction:       LD1R,
   995  				srcReg:            RegR12,
   996  				dstReg:            RegV11,
   997  				vectorArrangement: VectorArrangement8B,
   998  			},
   999  			exp: []byte{0x8b, 0xc1, 0x40, 0xd},
  1000  		},
  1001  		{
  1002  			name: "ld1r {v11.16b}, [x12]",
  1003  			n: &nodeImpl{
  1004  				instruction:       LD1R,
  1005  				srcReg:            RegR12,
  1006  				dstReg:            RegV11,
  1007  				vectorArrangement: VectorArrangement16B,
  1008  			},
  1009  			exp: []byte{0x8b, 0xc1, 0x40, 0x4d},
  1010  		},
  1011  		{
  1012  			name: "ld1r {v11.4h}, [x12]",
  1013  			n: &nodeImpl{
  1014  				instruction:       LD1R,
  1015  				srcReg:            RegR12,
  1016  				dstReg:            RegV11,
  1017  				vectorArrangement: VectorArrangement4H,
  1018  			},
  1019  			exp: []byte{0x8b, 0xc5, 0x40, 0xd},
  1020  		},
  1021  		{
  1022  			name: "ld1r {v9.8h}, [x0]",
  1023  			n: &nodeImpl{
  1024  				instruction:       LD1R,
  1025  				srcReg:            RegR0,
  1026  				dstReg:            RegV0,
  1027  				vectorArrangement: VectorArrangement8H,
  1028  			},
  1029  			exp: []byte{0x0, 0xc4, 0x40, 0x4d},
  1030  		},
  1031  		{
  1032  			name: "ld1r {v11.2s}, [x12]",
  1033  			n: &nodeImpl{
  1034  				instruction:       LD1R,
  1035  				srcReg:            RegR12,
  1036  				dstReg:            RegV11,
  1037  				vectorArrangement: VectorArrangement2S,
  1038  			},
  1039  			exp: []byte{0x8b, 0xc9, 0x40, 0xd},
  1040  		},
  1041  		{
  1042  			name: "ld1r {v0.4s}, [x0]",
  1043  			n: &nodeImpl{
  1044  				instruction:       LD1R,
  1045  				srcReg:            RegR0,
  1046  				dstReg:            RegV0,
  1047  				vectorArrangement: VectorArrangement4S,
  1048  			},
  1049  			exp: []byte{0x0, 0xc8, 0x40, 0x4d},
  1050  		},
  1051  		{
  1052  			name: "ld1r {v11.1d}, [x12]",
  1053  			n: &nodeImpl{
  1054  				instruction:       LD1R,
  1055  				srcReg:            RegR12,
  1056  				dstReg:            RegV11,
  1057  				vectorArrangement: VectorArrangement1D,
  1058  			},
  1059  			exp: []byte{0x8b, 0xcd, 0x40, 0xd},
  1060  		},
  1061  		{
  1062  			name: "ld1r {v0.2d}, [x0]",
  1063  			n: &nodeImpl{
  1064  				instruction:       LD1R,
  1065  				srcReg:            RegR0,
  1066  				dstReg:            RegV0,
  1067  				vectorArrangement: VectorArrangement2D,
  1068  			},
  1069  			exp: []byte{0x0, 0xcc, 0x40, 0x4d},
  1070  		},
  1071  	}
  1072  
  1073  	for _, tt := range tests {
  1074  		tc := tt
  1075  		t.Run(tc.name, func(t *testing.T) {
  1076  			code := asm.CodeSegment{}
  1077  			defer func() { require.NoError(t, code.Unmap()) }()
  1078  
  1079  			a := NewAssembler(RegR10)
  1080  			buf := code.NextCodeSection()
  1081  			err := a.encodeMemoryToVectorRegister(buf, tc.n)
  1082  			require.NoError(t, err)
  1083  
  1084  			a.maybeFlushConstPool(buf, true)
  1085  
  1086  			err = a.Assemble(buf)
  1087  			require.NoError(t, err)
  1088  
  1089  			actual := buf.Bytes()
  1090  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  1091  		})
  1092  	}
  1093  }
  1094  
  1095  func TestAssemblerImpl_EncodeVectorRegisterToVectorRegister(t *testing.T) {
  1096  	tests := []struct {
  1097  		name     string
  1098  		exp      []byte
  1099  		c        asm.ConstantValue
  1100  		inst     asm.Instruction
  1101  		x1       asm.Register
  1102  		x2       asm.Register
  1103  		arr      VectorArrangement
  1104  		srcIndex VectorIndex
  1105  		dstIndex VectorIndex
  1106  	}{
  1107  		{
  1108  			inst: XTN,
  1109  			name: "xtn v10.2s, v2.2d",
  1110  			x1:   RegV2,
  1111  			x2:   RegV10,
  1112  			arr:  VectorArrangement2D,
  1113  			exp:  []byte{0x4a, 0x28, 0xa1, 0xe},
  1114  		},
  1115  		{
  1116  			inst: XTN,
  1117  			name: "xtn v10.4h, v2.4s",
  1118  			x1:   RegV2,
  1119  			x2:   RegV10,
  1120  			arr:  VectorArrangement4S,
  1121  			exp:  []byte{0x4a, 0x28, 0x61, 0xe},
  1122  		},
  1123  		{
  1124  			inst: XTN,
  1125  			name: "xtn v10.8b, v2.8h",
  1126  			x1:   RegV2,
  1127  			x2:   RegV10,
  1128  			arr:  VectorArrangement8H,
  1129  			exp:  []byte{0x4a, 0x28, 0x21, 0xe},
  1130  		},
  1131  		{
  1132  			inst: REV64,
  1133  			name: "rev64 v10.16b, v2.16b",
  1134  			x1:   RegV2,
  1135  			x2:   RegV10,
  1136  			arr:  VectorArrangement16B,
  1137  			exp:  []byte{0x4a, 0x8, 0x20, 0x4e},
  1138  		},
  1139  		{
  1140  			inst: REV64,
  1141  			name: "rev64 v10.4s, v2.4s",
  1142  			x1:   RegV2,
  1143  			x2:   RegV10,
  1144  			arr:  VectorArrangement4S,
  1145  			exp:  []byte{0x4a, 0x8, 0xa0, 0x4e},
  1146  		},
  1147  		{
  1148  			inst: VCNT,
  1149  			name: "cnt v10.16b, v2.16b",
  1150  			x1:   RegV2,
  1151  			x2:   RegV10,
  1152  			arr:  VectorArrangement16B,
  1153  			exp:  []byte{0x4a, 0x58, 0x20, 0x4e},
  1154  		},
  1155  		{
  1156  			inst: VCNT,
  1157  			name: "cnt v10.8b, v2.8b",
  1158  			x1:   RegV2,
  1159  			x2:   RegV10,
  1160  			arr:  VectorArrangement8B,
  1161  			exp:  []byte{0x4a, 0x58, 0x20, 0xe},
  1162  		},
  1163  		{
  1164  			inst: VNEG,
  1165  			name: "neg v10.16b, v2.16b",
  1166  			x1:   RegV2,
  1167  			x2:   RegV10,
  1168  			arr:  VectorArrangement16B,
  1169  			exp:  []byte{0x4a, 0xb8, 0x20, 0x6e},
  1170  		},
  1171  		{
  1172  			inst: VNEG,
  1173  			name: "neg v10.8h, v2.18h",
  1174  			x1:   RegV2,
  1175  			x2:   RegV10,
  1176  			arr:  VectorArrangement8H,
  1177  			exp:  []byte{0x4a, 0xb8, 0x60, 0x6e},
  1178  		},
  1179  		{
  1180  			inst: VNEG,
  1181  			name: "neg v10.4s, v2.4s",
  1182  			x1:   RegV2,
  1183  			x2:   RegV10,
  1184  			arr:  VectorArrangement4S,
  1185  			exp:  []byte{0x4a, 0xb8, 0xa0, 0x6e},
  1186  		},
  1187  		{
  1188  			inst: VNEG,
  1189  			name: "neg v10.2d, v2.2d",
  1190  			x1:   RegV2,
  1191  			x2:   RegV10,
  1192  			arr:  VectorArrangement2D,
  1193  			exp:  []byte{0x4a, 0xb8, 0xe0, 0x6e},
  1194  		},
  1195  		{
  1196  			inst: VABS,
  1197  			name: "abs v10.16b, v2.16b",
  1198  			x1:   RegV2,
  1199  			x2:   RegV10,
  1200  			arr:  VectorArrangement16B,
  1201  			exp:  []byte{0x4a, 0xb8, 0x20, 0x4e},
  1202  		},
  1203  		{
  1204  			inst: VABS,
  1205  			name: "abs v10.8h, v2.18h",
  1206  			x1:   RegV2,
  1207  			x2:   RegV10,
  1208  			arr:  VectorArrangement8H,
  1209  			exp:  []byte{0x4a, 0xb8, 0x60, 0x4e},
  1210  		},
  1211  		{
  1212  			inst: VABS,
  1213  			name: "abs v10.4s, v2.4s",
  1214  			x1:   RegV2,
  1215  			x2:   RegV10,
  1216  			arr:  VectorArrangement4S,
  1217  			exp:  []byte{0x4a, 0xb8, 0xa0, 0x4e},
  1218  		},
  1219  		{
  1220  			inst: VABS,
  1221  			name: "abs v10.2d, v2.2d",
  1222  			x1:   RegV2,
  1223  			x2:   RegV10,
  1224  			arr:  VectorArrangement2D,
  1225  			exp:  []byte{0x4a, 0xb8, 0xe0, 0x4e},
  1226  		},
  1227  		{
  1228  			inst: ZIP1,
  1229  			name: "zip1 v10.16b, v10.16b, v2.16b",
  1230  			x1:   RegV2,
  1231  			x2:   RegV10,
  1232  			arr:  VectorArrangement16B,
  1233  			exp:  []byte{0x4a, 0x39, 0x2, 0x4e},
  1234  		},
  1235  		{
  1236  			inst: ADDV,
  1237  			name: "addv b10, v2.16b",
  1238  			x1:   RegV2,
  1239  			x2:   RegV10,
  1240  			arr:  VectorArrangement16B,
  1241  			exp:  []byte{0x4a, 0xb8, 0x31, 0x4e},
  1242  		},
  1243  		{
  1244  			inst: VORR,
  1245  			name: "orr v10.16b, v10.16b, v2.16b",
  1246  			x1:   RegV2,
  1247  			x2:   RegV10,
  1248  			arr:  VectorArrangement16B,
  1249  			exp:  []byte{0x4a, 0x1d, 0xa2, 0x4e},
  1250  		},
  1251  		{
  1252  			inst: VORR,
  1253  			name: "orr v10.8b, v10.8b, v2.8b",
  1254  			x1:   RegV2,
  1255  			x2:   RegV10,
  1256  			arr:  VectorArrangement8B,
  1257  			exp:  []byte{0x4a, 0x1d, 0xa2, 0xe},
  1258  		},
  1259  		{
  1260  			name: "fadd v10.2d, v10.2d, v2.2d",
  1261  			x1:   RegV2,
  1262  			x2:   RegV10,
  1263  			inst: VFADDD,
  1264  			arr:  VectorArrangement2D,
  1265  			exp:  []byte{0x4a, 0xd5, 0x62, 0x4e},
  1266  		},
  1267  		{
  1268  			name: "fadd v10.4s, v10.4s, v2.4s",
  1269  			x1:   RegV2,
  1270  			x2:   RegV10,
  1271  			inst: VFADDS,
  1272  			arr:  VectorArrangement4S,
  1273  			exp:  []byte{0x4a, 0xd5, 0x22, 0x4e},
  1274  		},
  1275  		{
  1276  			name: "fsub v10.2d, v10.2d, v2.2d",
  1277  			x1:   RegV2,
  1278  			x2:   RegV10,
  1279  			inst: VFSUBD,
  1280  			arr:  VectorArrangement2D,
  1281  			exp:  []byte{0x4a, 0xd5, 0xe2, 0x4e},
  1282  		},
  1283  		{
  1284  			name: "fsub v10.4s, v10.4s, v2.4s",
  1285  			x1:   RegV2,
  1286  			x2:   RegV10,
  1287  			inst: VFSUBS,
  1288  			arr:  VectorArrangement4S,
  1289  			exp:  []byte{0x4a, 0xd5, 0xa2, 0x4e},
  1290  		},
  1291  		{
  1292  			name: "ushll v10.8h, v2.8b, #0",
  1293  			x1:   RegV2,
  1294  			x2:   RegV10,
  1295  			inst: USHLL,
  1296  			exp:  []byte{0x4a, 0xa4, 0x8, 0x2f},
  1297  			arr:  VectorArrangement8B,
  1298  		},
  1299  		{
  1300  			name: "ushll v10.8h, v2.8b, #7",
  1301  			x1:   RegV2,
  1302  			x2:   RegV10,
  1303  			inst: USHLL,
  1304  			exp:  []byte{0x4a, 0xa4, 0xf, 0x2f},
  1305  			arr:  VectorArrangement8B,
  1306  			c:    7,
  1307  		},
  1308  		{
  1309  			name: "10.8h, v2.8b, #0",
  1310  			x1:   RegV2,
  1311  			x2:   RegV10,
  1312  			inst: SSHR,
  1313  			exp:  []byte{0x4a, 0x4, 0x8, 0x4f},
  1314  			arr:  VectorArrangement16B,
  1315  			c:    8,
  1316  		},
  1317  		{
  1318  			name: "sshr v10.16b, v2.16b, #3",
  1319  			x1:   RegV2,
  1320  			x2:   RegV10,
  1321  			inst: SSHR,
  1322  			exp:  []byte{0x4a, 0x4, 0xd, 0x4f},
  1323  			arr:  VectorArrangement16B,
  1324  			c:    3,
  1325  		},
  1326  		{
  1327  			name: "sshr v10.16b, v2.16b, #1",
  1328  			x1:   RegV2,
  1329  			x2:   RegV10,
  1330  			inst: SSHR,
  1331  			exp:  []byte{0x4a, 0x4, 0xf, 0x4f},
  1332  			arr:  VectorArrangement16B,
  1333  			c:    1,
  1334  		},
  1335  		{
  1336  			name: "sshr v10.8b, v2.8b, #3",
  1337  			x1:   RegV2,
  1338  			x2:   RegV10,
  1339  			inst: SSHR,
  1340  			exp:  []byte{0x4a, 0x4, 0xd, 0xf},
  1341  			arr:  VectorArrangement8B,
  1342  			c:    3,
  1343  		},
  1344  		{
  1345  			name: "sshr v10.8h, v2.8h, #0x10",
  1346  			x1:   RegV2,
  1347  			x2:   RegV10,
  1348  			inst: SSHR,
  1349  			exp:  []byte{0x4a, 0x4, 0x10, 0x4f},
  1350  			arr:  VectorArrangement8H,
  1351  			c:    16,
  1352  		},
  1353  		{
  1354  			name: "sshr v10.8h, v2.8h, #0xf",
  1355  			x1:   RegV2,
  1356  			x2:   RegV10,
  1357  			inst: SSHR,
  1358  			exp:  []byte{0x4a, 0x4, 0x11, 0x4f},
  1359  			arr:  VectorArrangement8H,
  1360  			c:    15,
  1361  		},
  1362  		{
  1363  			name: "sshr v10.8h, v2.8h, #3",
  1364  			x1:   RegV2,
  1365  			x2:   RegV10,
  1366  			inst: SSHR,
  1367  			exp:  []byte{0x4a, 0x4, 0x1d, 0x4f},
  1368  			arr:  VectorArrangement8H,
  1369  			c:    3,
  1370  		},
  1371  		{
  1372  			name: "sshr v10.4h, v2.4h, #0xf",
  1373  			x1:   RegV2,
  1374  			x2:   RegV10,
  1375  			inst: SSHR,
  1376  			exp:  []byte{0x4a, 0x4, 0x11, 0xf},
  1377  			arr:  VectorArrangement4H,
  1378  			c:    15,
  1379  		},
  1380  		{
  1381  			name: "sshr v10.2s, v2.2s, #0x20",
  1382  			x1:   RegV2,
  1383  			x2:   RegV10,
  1384  			inst: SSHR,
  1385  			exp:  []byte{0x4a, 0x4, 0x20, 0xf},
  1386  			arr:  VectorArrangement2S,
  1387  			c:    32,
  1388  		},
  1389  		{
  1390  			name: "sshr v10.2s, v2.2s, #0x1f",
  1391  			x1:   RegV2,
  1392  			x2:   RegV10,
  1393  			inst: SSHR,
  1394  			exp:  []byte{0x4a, 0x4, 0x21, 0xf},
  1395  			arr:  VectorArrangement2S,
  1396  			c:    31,
  1397  		},
  1398  		{
  1399  			name: "sshr v10.2s, v2.2s, #7",
  1400  			x1:   RegV2,
  1401  			x2:   RegV10,
  1402  			inst: SSHR,
  1403  			exp:  []byte{0x4a, 0x4, 0x39, 0xf},
  1404  			arr:  VectorArrangement2S,
  1405  			c:    7,
  1406  		},
  1407  		{
  1408  			name: "sshr v10.4s, v2.4s, #7",
  1409  			x1:   RegV2,
  1410  			x2:   RegV10,
  1411  			inst: SSHR,
  1412  			exp:  []byte{0x4a, 0x4, 0x39, 0x4f},
  1413  			arr:  VectorArrangement4S,
  1414  			c:    7,
  1415  		},
  1416  		{
  1417  			name: "sshr v10.2d, v2.2d, #0x3f",
  1418  			x1:   RegV2,
  1419  			x2:   RegV10,
  1420  			inst: SSHR,
  1421  			exp:  []byte{0x4a, 0x4, 0x41, 0x4f},
  1422  			arr:  VectorArrangement2D,
  1423  			c:    63,
  1424  		},
  1425  		{
  1426  			name: "sshr v10.2d, v2.2d, #0x21",
  1427  			x1:   RegV2,
  1428  			x2:   RegV10,
  1429  			inst: SSHR,
  1430  			exp:  []byte{0x4a, 0x4, 0x5f, 0x4f},
  1431  			arr:  VectorArrangement2D,
  1432  			c:    33,
  1433  		},
  1434  		{
  1435  			name: "sshr v10.2d, v2.2d, #1",
  1436  			x1:   RegV2,
  1437  			x2:   RegV10,
  1438  			inst: SSHR,
  1439  			exp:  []byte{0x4a, 0x4, 0x7f, 0x4f},
  1440  			arr:  VectorArrangement2D,
  1441  			c:    1,
  1442  		},
  1443  		{
  1444  			name: "sshll v10.8h, v2.8b, #7",
  1445  			x1:   RegV2,
  1446  			x2:   RegV10,
  1447  			inst: SSHLL, exp: []byte{0x4a, 0xa4, 0xf, 0xf},
  1448  			arr: VectorArrangement8B,
  1449  			c:   7,
  1450  		},
  1451  		{
  1452  			name: "sshll v10.4s, v2.4h, #0",
  1453  			x1:   RegV2,
  1454  			x2:   RegV10,
  1455  			inst: SSHLL,
  1456  			exp:  []byte{0x4a, 0xa4, 0x10, 0xf},
  1457  			arr:  VectorArrangement4H,
  1458  		},
  1459  		{
  1460  			name: "sshll v10.4s, v2.4h, #0xf",
  1461  			x1:   RegV2,
  1462  			x2:   RegV10,
  1463  			inst: SSHLL,
  1464  			exp:  []byte{0x4a, 0xa4, 0x1f, 0xf},
  1465  			arr:  VectorArrangement4H,
  1466  			c:    15,
  1467  		},
  1468  		{
  1469  			name: "sshll v10.2d, v2.2s, #0",
  1470  			x1:   RegV2,
  1471  			x2:   RegV10,
  1472  			inst: SSHLL,
  1473  			exp:  []byte{0x4a, 0xa4, 0x20, 0xf},
  1474  			arr:  VectorArrangement2S,
  1475  		},
  1476  		{
  1477  			name: "sshll v10.2d, v2.2s, #0x1f",
  1478  			x1:   RegV2,
  1479  			x2:   RegV10,
  1480  			inst: SSHLL,
  1481  			exp:  []byte{0x4a, 0xa4, 0x3f, 0xf},
  1482  			arr:  VectorArrangement2S,
  1483  			c:    31,
  1484  		},
  1485  		{
  1486  			x1:       RegV2,
  1487  			x2:       RegV10,
  1488  			name:     "ins v10.s[2], v2.s[1]",
  1489  			inst:     INSELEM,
  1490  			exp:      []byte{0x4a, 0x24, 0x14, 0x6e},
  1491  			arr:      VectorArrangementS,
  1492  			srcIndex: 1,
  1493  			dstIndex: 2,
  1494  		},
  1495  		{
  1496  			x1:       RegV2,
  1497  			x2:       RegV10,
  1498  			name:     "ins v10.s[0], v2.s[3]",
  1499  			inst:     INSELEM,
  1500  			exp:      []byte{0x4a, 0x64, 0x4, 0x6e},
  1501  			arr:      VectorArrangementS,
  1502  			srcIndex: 3,
  1503  			dstIndex: 0,
  1504  		},
  1505  		{
  1506  			x1:       RegV2,
  1507  			x2:       RegV10,
  1508  			name:     "ins v10.b[0], v2.b[0xf]",
  1509  			inst:     INSELEM,
  1510  			exp:      []byte{0x4a, 0x7c, 0x1, 0x6e},
  1511  			arr:      VectorArrangementB,
  1512  			srcIndex: 15,
  1513  			dstIndex: 0,
  1514  		},
  1515  		{
  1516  			x1:       RegV2,
  1517  			x2:       RegV10,
  1518  			name:     "ins v10.d[1], v2.d[0]",
  1519  			inst:     INSELEM,
  1520  			exp:      []byte{0x4a, 0x4, 0x18, 0x6e},
  1521  			arr:      VectorArrangementD,
  1522  			srcIndex: 0,
  1523  			dstIndex: 1,
  1524  		},
  1525  		{
  1526  			x1:       RegV2,
  1527  			x2:       RegV10,
  1528  			name:     "dup v10.2d, v2.d[0]",
  1529  			inst:     DUPELEM,
  1530  			exp:      []byte{0x4a, 0x4, 0x8, 0x4e},
  1531  			arr:      VectorArrangementD,
  1532  			srcIndex: 0,
  1533  		},
  1534  		{
  1535  			x1:       RegV2,
  1536  			x2:       RegV10,
  1537  			name:     "dup v10.2d, v2.d[1]",
  1538  			inst:     DUPELEM,
  1539  			exp:      []byte{0x4a, 0x4, 0x18, 0x4e},
  1540  			arr:      VectorArrangementD,
  1541  			srcIndex: 1,
  1542  		},
  1543  		{
  1544  			x1:       RegV2,
  1545  			x2:       RegV10,
  1546  			name:     "dup v10.4s, v2.s[3]",
  1547  			inst:     DUPELEM,
  1548  			exp:      []byte{0x4a, 0x4, 0x1c, 0x4e},
  1549  			arr:      VectorArrangementS,
  1550  			srcIndex: 3,
  1551  		},
  1552  		{
  1553  			x1:       RegV2,
  1554  			x2:       RegV10,
  1555  			name:     "dup v10.8h, v2.h[7]",
  1556  			inst:     DUPELEM,
  1557  			exp:      []byte{0x4a, 0x4, 0x1e, 0x4e},
  1558  			arr:      VectorArrangementH,
  1559  			srcIndex: 7,
  1560  		},
  1561  		{
  1562  			x1:       RegV2,
  1563  			x2:       RegV10,
  1564  			name:     "dup v10.16b, v2.b[0xf]",
  1565  			inst:     DUPELEM,
  1566  			exp:      []byte{0x4a, 0x4, 0x1f, 0x4e},
  1567  			arr:      VectorArrangementB,
  1568  			srcIndex: 15,
  1569  		},
  1570  		{
  1571  			x1:   RegV2,
  1572  			x2:   RegV10,
  1573  			name: "umaxp v10.16b, v10.16b, v2.16b",
  1574  			inst: UMAXP,
  1575  			exp:  []byte{0x4a, 0xa5, 0x22, 0x6e},
  1576  			arr:  VectorArrangement16B,
  1577  		},
  1578  		{
  1579  			x1:   RegV2,
  1580  			x2:   RegV10,
  1581  			name: "umaxp v10.8h, v10.8h, v2.8h",
  1582  			inst: UMAXP,
  1583  			exp:  []byte{0x4a, 0xa5, 0x62, 0x6e},
  1584  			arr:  VectorArrangement8H,
  1585  		},
  1586  		{
  1587  			x1:   RegV2,
  1588  			x2:   RegV10,
  1589  			name: "umaxp v10.4s, v10.4s, v2.4s",
  1590  			inst: UMAXP,
  1591  			exp:  []byte{0x4a, 0xa5, 0xa2, 0x6e},
  1592  			arr:  VectorArrangement4S,
  1593  		},
  1594  		{
  1595  			x1:   RegV11,
  1596  			x2:   RegV11,
  1597  			name: "addp d11, v11.2d",
  1598  			inst: ADDP,
  1599  			arr:  VectorArrangement2D,
  1600  			exp:  []byte{0x6b, 0xb9, 0xf1, 0x5e},
  1601  		},
  1602  		{
  1603  			x1:   RegV2,
  1604  			x2:   RegV10,
  1605  			name: "addp v10.16b, v10.16b, v2.16b",
  1606  			inst: VADDP,
  1607  			exp:  []byte{0x4a, 0xbd, 0x22, 0x4e},
  1608  			arr:  VectorArrangement16B,
  1609  		},
  1610  		{
  1611  			x1:   RegV2,
  1612  			x2:   RegV10,
  1613  			name: "addp v10.8h, v10.8h, v2.8h",
  1614  			inst: VADDP,
  1615  			exp:  []byte{0x4a, 0xbd, 0x62, 0x4e},
  1616  			arr:  VectorArrangement8H,
  1617  		},
  1618  		{
  1619  			x1:   RegV2,
  1620  			x2:   RegV10,
  1621  			name: "addp v10.4s, v10.4s, v2.4s",
  1622  			inst: VADDP,
  1623  			exp:  []byte{0x4a, 0xbd, 0xa2, 0x4e},
  1624  			arr:  VectorArrangement4S,
  1625  		},
  1626  		{
  1627  			x1:   RegV2,
  1628  			x2:   RegV10,
  1629  			name: "uminv b10, v2.16b",
  1630  			inst: UMINV,
  1631  			exp:  []byte{0x4a, 0xa8, 0x31, 0x6e},
  1632  			arr:  VectorArrangement16B,
  1633  		},
  1634  		{
  1635  			x1:   RegV2,
  1636  			x2:   RegV10,
  1637  			name: "uminv h10, v2.8h",
  1638  			inst: UMINV,
  1639  			exp:  []byte{0x4a, 0xa8, 0x71, 0x6e},
  1640  			arr:  VectorArrangement8H,
  1641  		},
  1642  		{
  1643  			x1:   RegV2,
  1644  			x2:   RegV10,
  1645  			name: "uminv s10, v2.4s",
  1646  			inst: UMINV,
  1647  			exp:  []byte{0x4a, 0xa8, 0xb1, 0x6e},
  1648  			arr:  VectorArrangement4S,
  1649  		},
  1650  		{
  1651  			x1:   RegV2,
  1652  			x2:   RegV10,
  1653  			name: "cmeq v10.2d, v10.2d, v2.2d",
  1654  			arr:  VectorArrangement2D,
  1655  			inst: CMEQ,
  1656  			exp:  []byte{0x4a, 0x8d, 0xe2, 0x6e},
  1657  		},
  1658  		{
  1659  			x1:   RegRZR,
  1660  			x2:   RegV12,
  1661  			name: "cmeq v12.2d, v12.2d, #0",
  1662  			inst: CMEQZERO,
  1663  			arr:  VectorArrangement2D,
  1664  			exp:  []byte{0x8c, 0x99, 0xe0, 0x4e},
  1665  		},
  1666  		{
  1667  			name: "tbl v1.8b, {v0.16b}, v1.8b",
  1668  			x1:   RegV0,
  1669  			x2:   RegV1,
  1670  			inst: TBL1,
  1671  			arr:  VectorArrangement8B,
  1672  			exp:  []byte{0x1, 0x0, 0x1, 0xe},
  1673  		},
  1674  		{
  1675  			name: "tbl v1.16b, {v0.16b}, v1.16b",
  1676  			x1:   RegV0,
  1677  			x2:   RegV1,
  1678  			inst: TBL1,
  1679  			arr:  VectorArrangement16B,
  1680  			exp:  []byte{0x1, 0x0, 0x1, 0x4e},
  1681  		},
  1682  		{
  1683  			name: "tbl v30.8b, {v0.16b, v1.16b}, v30.8b",
  1684  			x1:   RegV0,
  1685  			x2:   RegV30,
  1686  			inst: TBL2,
  1687  			arr:  VectorArrangement8B,
  1688  			exp:  []byte{0x1e, 0x20, 0x1e, 0xe},
  1689  		},
  1690  		{
  1691  			name: "tbl v1.16b, {v31.16b, v0.16b}, v1.16b",
  1692  			x1:   RegV31,
  1693  			x2:   RegV1,
  1694  			inst: TBL2,
  1695  			arr:  VectorArrangement16B,
  1696  			exp:  []byte{0xe1, 0x23, 0x1, 0x4e},
  1697  		},
  1698  		{
  1699  			x1:   RegV2,
  1700  			x2:   RegV10,
  1701  			name: "add v10.4s, v10.4s, v2.4s",
  1702  			inst: VADD,
  1703  			exp:  []byte{0x4a, 0x85, 0xa2, 0x4e},
  1704  			arr:  VectorArrangement4S,
  1705  		},
  1706  		{
  1707  			x1:   RegV2,
  1708  			x2:   RegV10,
  1709  			name: "add v10.2d, v10.2d, v2.2d",
  1710  			inst: VADD,
  1711  			exp:  []byte{0x4a, 0x85, 0xe2, 0x4e},
  1712  			arr:  VectorArrangement2D,
  1713  		},
  1714  		{
  1715  			x1:   RegV2,
  1716  			x2:   RegV10,
  1717  			name: "sub v10.8h, v10.8h, v2.8h",
  1718  			inst: VSUB,
  1719  			exp:  []byte{0x4a, 0x85, 0x62, 0x6e},
  1720  			arr:  VectorArrangement8H,
  1721  		},
  1722  		{
  1723  			x1:   RegV29,
  1724  			x2:   RegV30,
  1725  			name: "sub v30.16b, v30.16b, v29.16b",
  1726  			inst: VSUB,
  1727  			exp:  []byte{0xde, 0x87, 0x3d, 0x6e},
  1728  			arr:  VectorArrangement16B,
  1729  		},
  1730  		{
  1731  			name: "bic v10.16b, v10.16b, v2.16b",
  1732  			x1:   RegV2,
  1733  			x2:   RegV10,
  1734  			inst: BIC,
  1735  			arr:  VectorArrangement16B,
  1736  			exp:  []byte{0x4a, 0x1d, 0x62, 0x4e},
  1737  		},
  1738  		{
  1739  			name: "eor v10.16b, v10.16b, v2.16b",
  1740  			x1:   RegV2,
  1741  			x2:   RegV10,
  1742  			inst: EOR,
  1743  			arr:  VectorArrangement16B,
  1744  			exp:  []byte{0x4a, 0x1d, 0x22, 0x6e},
  1745  		},
  1746  		{
  1747  			name: "bsl v10.16b, v10.16b, v2.16b",
  1748  			x1:   RegV2,
  1749  			x2:   RegV10,
  1750  			inst: BSL,
  1751  			arr:  VectorArrangement16B,
  1752  			exp:  []byte{0x4a, 0x1d, 0x62, 0x6e},
  1753  		},
  1754  		{
  1755  			name: "bsl v10.16b, v10.16b, v2.16b",
  1756  			x1:   RegV2,
  1757  			x2:   RegV10,
  1758  			inst: BSL,
  1759  			arr:  VectorArrangement16B,
  1760  			exp:  []byte{0x4a, 0x1d, 0x62, 0x6e},
  1761  		},
  1762  		{
  1763  			name: "and v10.16b, v10.16b, v2.16b",
  1764  			x1:   RegV2,
  1765  			x2:   RegV10,
  1766  			inst: VAND,
  1767  			arr:  VectorArrangement16B,
  1768  			exp:  []byte{0x4a, 0x1d, 0x22, 0x4e},
  1769  		},
  1770  		{
  1771  			// mvn is an alias of NOT: https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/MVN--Bitwise-NOT--vector---an-alias-of-NOT-?lang=en
  1772  			name: "mvn v10.16b, v2.16b",
  1773  			x1:   RegV2,
  1774  			x2:   RegV10,
  1775  			inst: NOT,
  1776  			arr:  VectorArrangement16B,
  1777  			exp:  []byte{0x4a, 0x58, 0x20, 0x6e},
  1778  		},
  1779  		{
  1780  			name: "fneg v10.2d, v2.2d",
  1781  			x1:   RegV2,
  1782  			x2:   RegV10,
  1783  			inst: VFNEG,
  1784  			arr:  VectorArrangement2D,
  1785  			exp:  []byte{0x4a, 0xf8, 0xe0, 0x6e},
  1786  		},
  1787  		{
  1788  			name: "fneg v10.4s, v2.4s",
  1789  			x1:   RegV2,
  1790  			x2:   RegV10,
  1791  			inst: VFNEG,
  1792  			arr:  VectorArrangement4S,
  1793  			exp:  []byte{0x4a, 0xf8, 0xa0, 0x6e},
  1794  		},
  1795  		{
  1796  			x1:   RegV2,
  1797  			x2:   RegV10,
  1798  			name: "sshl v10.2d, v10.2d, v2.2d",
  1799  			inst: SSHL,
  1800  			exp:  []byte{0x4a, 0x45, 0xe2, 0x4e},
  1801  			arr:  VectorArrangement2D,
  1802  		},
  1803  		{
  1804  			x1:   RegV25,
  1805  			x2:   RegV30,
  1806  			name: "sshl v30.4s, v30.4s, v25.4s",
  1807  			inst: SSHL,
  1808  			exp:  []byte{0xde, 0x47, 0xb9, 0x4e},
  1809  			arr:  VectorArrangement4S,
  1810  		},
  1811  		{
  1812  			x1:   RegV2,
  1813  			x2:   RegV10,
  1814  			name: "ushl v10.8h, v10.8h, v2.8h",
  1815  			inst: USHL,
  1816  			exp:  []byte{0x4a, 0x45, 0x62, 0x6e},
  1817  			arr:  VectorArrangement8H,
  1818  		},
  1819  		{
  1820  			x1:   RegV25,
  1821  			x2:   RegV30,
  1822  			name: "ushl v30.16b, v30.16b, v25.16b",
  1823  			inst: USHL,
  1824  			exp:  []byte{0xde, 0x47, 0x39, 0x6e},
  1825  			arr:  VectorArrangement16B,
  1826  		},
  1827  		{
  1828  			x1:   RegV25,
  1829  			x2:   RegV30,
  1830  			name: "fabs v30.4s, v25.4s",
  1831  			inst: VFABS,
  1832  			exp:  []byte{0x3e, 0xfb, 0xa0, 0x4e},
  1833  			arr:  VectorArrangement4S,
  1834  		},
  1835  		{
  1836  			x1:   RegV25,
  1837  			x2:   RegV30,
  1838  			name: "fabs v30.2s, v25.2s",
  1839  			inst: VFABS,
  1840  			exp:  []byte{0x3e, 0xfb, 0xa0, 0xe},
  1841  			arr:  VectorArrangement2S,
  1842  		},
  1843  		{
  1844  			x1:   RegV25,
  1845  			x2:   RegV30,
  1846  			name: "fabs v30.2d, v25.2d",
  1847  			inst: VFABS,
  1848  			exp:  []byte{0x3e, 0xfb, 0xe0, 0x4e},
  1849  			arr:  VectorArrangement2D,
  1850  		},
  1851  		{
  1852  			x1:   RegV25,
  1853  			x2:   RegV30,
  1854  			name: "fsqrt v30.4s, v25.4s",
  1855  			inst: VFSQRT,
  1856  			exp:  []byte{0x3e, 0xfb, 0xa1, 0x6e},
  1857  			arr:  VectorArrangement4S,
  1858  		},
  1859  		{
  1860  			x1:   RegV25,
  1861  			x2:   RegV30,
  1862  			name: "fsqrt v30.2s, v25.2s",
  1863  			inst: VFSQRT,
  1864  			exp:  []byte{0x3e, 0xfb, 0xa1, 0x2e},
  1865  			arr:  VectorArrangement2S,
  1866  		},
  1867  		{
  1868  			x1:   RegV25,
  1869  			x2:   RegV30,
  1870  			name: "fsqrt v30.2d, v25.2d",
  1871  			inst: VFSQRT,
  1872  			exp:  []byte{0x3e, 0xfb, 0xe1, 0x6e},
  1873  			arr:  VectorArrangement2D,
  1874  		},
  1875  		{
  1876  			x1:   RegV25,
  1877  			x2:   RegV30,
  1878  			name: "frintm v30.4s, v25.4s",
  1879  			inst: VFRINTM,
  1880  			exp:  []byte{0x3e, 0x9b, 0x21, 0x4e},
  1881  			arr:  VectorArrangement4S,
  1882  		},
  1883  		{
  1884  			x1:   RegV25,
  1885  			x2:   RegV30,
  1886  			name: "frintm v30.2s, v25.2s",
  1887  			inst: VFRINTM,
  1888  			exp:  []byte{0x3e, 0x9b, 0x21, 0xe},
  1889  			arr:  VectorArrangement2S,
  1890  		},
  1891  		{
  1892  			x1:   RegV25,
  1893  			x2:   RegV30,
  1894  			name: "frintm v30.2d, v25.2d",
  1895  			inst: VFRINTM,
  1896  			exp:  []byte{0x3e, 0x9b, 0x61, 0x4e},
  1897  			arr:  VectorArrangement2D,
  1898  		},
  1899  		{
  1900  			x1:   RegV25,
  1901  			x2:   RegV30,
  1902  			name: "frintn v30.4s, v25.4s",
  1903  			inst: VFRINTN,
  1904  			exp:  []byte{0x3e, 0x8b, 0x21, 0x4e},
  1905  			arr:  VectorArrangement4S,
  1906  		},
  1907  		{
  1908  			x1:   RegV25,
  1909  			x2:   RegV30,
  1910  			name: "frintn v30.2s, v25.2s",
  1911  			inst: VFRINTN,
  1912  			exp:  []byte{0x3e, 0x8b, 0x21, 0xe},
  1913  			arr:  VectorArrangement2S,
  1914  		},
  1915  		{
  1916  			x1:   RegV25,
  1917  			x2:   RegV30,
  1918  			name: "frintn v30.2d, v25.2d",
  1919  			inst: VFRINTN,
  1920  			exp:  []byte{0x3e, 0x8b, 0x61, 0x4e},
  1921  			arr:  VectorArrangement2D,
  1922  		},
  1923  		{
  1924  			x1:   RegV25,
  1925  			x2:   RegV30,
  1926  			name: "frintp v30.4s, v25.4s",
  1927  			inst: VFRINTP,
  1928  			exp:  []byte{0x3e, 0x8b, 0xa1, 0x4e},
  1929  			arr:  VectorArrangement4S,
  1930  		},
  1931  		{
  1932  			x1:   RegV25,
  1933  			x2:   RegV30,
  1934  			name: "frintp v30.2s, v25.2s",
  1935  			inst: VFRINTP,
  1936  			exp:  []byte{0x3e, 0x8b, 0xa1, 0xe},
  1937  			arr:  VectorArrangement2S,
  1938  		},
  1939  		{
  1940  			x1:   RegV25,
  1941  			x2:   RegV30,
  1942  			name: "frintp v30.2d, v25.2d",
  1943  			inst: VFRINTP,
  1944  			exp:  []byte{0x3e, 0x8b, 0xe1, 0x4e},
  1945  			arr:  VectorArrangement2D,
  1946  		},
  1947  		{
  1948  			x1:   RegV25,
  1949  			x2:   RegV30,
  1950  			name: "frintp v30.4s, v25.4s",
  1951  			inst: VFRINTN,
  1952  			exp:  []byte{0x3e, 0x8b, 0x21, 0x4e},
  1953  			arr:  VectorArrangement4S,
  1954  		},
  1955  		{
  1956  			x1:   RegV25,
  1957  			x2:   RegV30,
  1958  			name: "frintp v30.2s, v25.2s",
  1959  			inst: VFRINTN,
  1960  			exp:  []byte{0x3e, 0x8b, 0x21, 0xe},
  1961  			arr:  VectorArrangement2S,
  1962  		},
  1963  		{
  1964  			x1:   RegV25,
  1965  			x2:   RegV30,
  1966  			name: "frintp v30.2d, v25.2d",
  1967  			inst: VFRINTN,
  1968  			exp:  []byte{0x3e, 0x8b, 0x61, 0x4e},
  1969  			arr:  VectorArrangement2D,
  1970  		},
  1971  		{
  1972  			x1:   RegV25,
  1973  			x2:   RegV30,
  1974  			name: "shll v30.8h, v25.8b, #8",
  1975  			inst: SHLL,
  1976  			exp:  []byte{0x3e, 0x3b, 0x21, 0x2e},
  1977  			arr:  VectorArrangement8B,
  1978  		},
  1979  		{
  1980  			x1:   RegV25,
  1981  			x2:   RegV30,
  1982  			name: "shll v30.4s, v25.4h, #16",
  1983  			inst: SHLL,
  1984  			exp:  []byte{0x3e, 0x3b, 0x61, 0x2e},
  1985  			arr:  VectorArrangement4H,
  1986  		},
  1987  		{
  1988  			x1:   RegV25,
  1989  			x2:   RegV30,
  1990  			name: "shll v30.2d, v25.2s, #32",
  1991  			inst: SHLL,
  1992  			exp:  []byte{0x3e, 0x3b, 0xa1, 0x2e},
  1993  			arr:  VectorArrangement2S,
  1994  		},
  1995  		{
  1996  			x1:   RegV25,
  1997  			x2:   RegV30,
  1998  			name: "uaddlv h30, v25.16b",
  1999  			inst: UADDLV,
  2000  			exp:  []byte{0x3e, 0x3b, 0x30, 0x6e},
  2001  			arr:  VectorArrangement16B,
  2002  		},
  2003  		{
  2004  			x1:   RegV25,
  2005  			x2:   RegV30,
  2006  			name: "uaddlv s30, v25.8h",
  2007  			inst: UADDLV,
  2008  			exp:  []byte{0x3e, 0x3b, 0x70, 0x6e},
  2009  			arr:  VectorArrangement8H,
  2010  		},
  2011  		{
  2012  			x1:   RegV25,
  2013  			x2:   RegV30,
  2014  			name: "uaddlv d30, v25.4s",
  2015  			inst: UADDLV,
  2016  			exp:  []byte{0x3e, 0x3b, 0xb0, 0x6e},
  2017  			arr:  VectorArrangement4S,
  2018  		},
  2019  		{
  2020  			x1:   RegV25,
  2021  			x2:   RegV30,
  2022  			name: "saddlp v30.2d, v25.4s",
  2023  			inst: SADDLP,
  2024  			exp:  []byte{0x3e, 0x2b, 0xa0, 0x4e},
  2025  			arr:  VectorArrangement4S,
  2026  		},
  2027  		{
  2028  			x1:   RegV25,
  2029  			x2:   RegV30,
  2030  			name: "saddlp v30.4s, v25.8h",
  2031  			inst: SADDLP,
  2032  			exp:  []byte{0x3e, 0x2b, 0x60, 0x4e},
  2033  			arr:  VectorArrangement8H,
  2034  		},
  2035  		{
  2036  			x1:   RegV25,
  2037  			x2:   RegV30,
  2038  			name: "uaddlp v30.2d, v25.4s",
  2039  			inst: UADDLP,
  2040  			exp:  []byte{0x3e, 0x2b, 0xa0, 0x6e},
  2041  			arr:  VectorArrangement4S,
  2042  		},
  2043  		{
  2044  			x1:   RegV25,
  2045  			x2:   RegV30,
  2046  			name: "uaddlp v30.4s, v25.8h",
  2047  			inst: UADDLP,
  2048  			exp:  []byte{0x3e, 0x2b, 0x60, 0x6e},
  2049  			arr:  VectorArrangement8H,
  2050  		},
  2051  		{
  2052  			name: "sshll2 v10.8h, v2.16b, #7",
  2053  			x1:   RegV2,
  2054  			x2:   RegV10,
  2055  			inst: SSHLL2,
  2056  			exp:  []byte{0x4a, 0xa4, 0xf, 0x4f},
  2057  			arr:  VectorArrangement16B,
  2058  			c:    7,
  2059  		},
  2060  		{
  2061  			name: "sshll2 v10.4s, v2.8h, #0",
  2062  			x1:   RegV2,
  2063  			x2:   RegV10,
  2064  			inst: SSHLL2,
  2065  			exp:  []byte{0x4a, 0xa4, 0x10, 0x4f},
  2066  			arr:  VectorArrangement8H,
  2067  		},
  2068  		{
  2069  			name: "sshll2 v10.2d, v2.4s, #0x15",
  2070  			x1:   RegV2,
  2071  			x2:   RegV10,
  2072  			inst: SSHLL2,
  2073  			exp:  []byte{0x4a, 0xa4, 0x35, 0x4f},
  2074  			arr:  VectorArrangement4S,
  2075  			c:    21,
  2076  		},
  2077  		{
  2078  			name: "ushll2 v10.8h, v2.16b, #7",
  2079  			x1:   RegV2,
  2080  			x2:   RegV10,
  2081  			inst: USHLL2,
  2082  			exp:  []byte{0x4a, 0xa4, 0xf, 0x6f},
  2083  			arr:  VectorArrangement16B,
  2084  			c:    7,
  2085  		},
  2086  		{
  2087  			name: "ushll2 v10.4s, v2.8h, #0",
  2088  			x1:   RegV2,
  2089  			x2:   RegV10,
  2090  			inst: USHLL2,
  2091  			exp:  []byte{0x4a, 0xa4, 0x10, 0x6f},
  2092  			arr:  VectorArrangement8H,
  2093  		},
  2094  		{
  2095  			name: "ushll2 v10.2d, v2.4s, #0x15",
  2096  			x1:   RegV2,
  2097  			x2:   RegV10,
  2098  			inst: USHLL2,
  2099  			exp:  []byte{0x4a, 0xa4, 0x35, 0x6f},
  2100  			arr:  VectorArrangement4S,
  2101  			c:    21,
  2102  		},
  2103  		{
  2104  			x1:   RegV25,
  2105  			x2:   RegV30,
  2106  			name: "fcvtzs v30.4s, v25.4s",
  2107  			inst: VFCVTZS,
  2108  			exp:  []byte{0x3e, 0xbb, 0xa1, 0x4e},
  2109  			arr:  VectorArrangement4S,
  2110  		},
  2111  		{
  2112  			x1:   RegV25,
  2113  			x2:   RegV30,
  2114  			name: "fcvtzs v30.2s, v25.2s",
  2115  			inst: VFCVTZS,
  2116  			exp:  []byte{0x3e, 0xbb, 0xa1, 0xe},
  2117  			arr:  VectorArrangement2S,
  2118  		},
  2119  		{
  2120  			x1:   RegV25,
  2121  			x2:   RegV30,
  2122  			name: "fcvtzs v30.2d, v25.2d",
  2123  			inst: VFCVTZS,
  2124  			exp:  []byte{0x3e, 0xbb, 0xe1, 0x4e},
  2125  			arr:  VectorArrangement2D,
  2126  		},
  2127  		{
  2128  			x1:   RegV25,
  2129  			x2:   RegV30,
  2130  			name: "fcvtzu v30.4s, v25.4s",
  2131  			inst: VFCVTZU,
  2132  			exp:  []byte{0x3e, 0xbb, 0xa1, 0x6e},
  2133  			arr:  VectorArrangement4S,
  2134  		},
  2135  		{
  2136  			x1:   RegV25,
  2137  			x2:   RegV30,
  2138  			name: "fcvtzu v30.2s, v25.2s",
  2139  			inst: VFCVTZU,
  2140  			exp:  []byte{0x3e, 0xbb, 0xa1, 0x2e},
  2141  			arr:  VectorArrangement2S,
  2142  		},
  2143  		{
  2144  			x1:   RegV25,
  2145  			x2:   RegV30,
  2146  			name: "fcvtzu v30.2d, v25.2d",
  2147  			inst: VFCVTZU,
  2148  			exp:  []byte{0x3e, 0xbb, 0xe1, 0x6e},
  2149  			arr:  VectorArrangement2D,
  2150  		},
  2151  		{
  2152  			x1:   RegV25,
  2153  			x2:   RegV30,
  2154  			name: "sqxtn v30.2s, v25.2d",
  2155  			inst: SQXTN,
  2156  			exp:  []byte{0x3e, 0x4b, 0xa1, 0xe},
  2157  			arr:  VectorArrangement2S,
  2158  		},
  2159  		{
  2160  			x1:   RegV25,
  2161  			x2:   RegV30,
  2162  			name: "sqxtn v30.4h, v25.4s",
  2163  			inst: SQXTN,
  2164  			exp:  []byte{0x3e, 0x4b, 0x61, 0xe},
  2165  			arr:  VectorArrangement4H,
  2166  		},
  2167  		{
  2168  			x1:   RegV25,
  2169  			x2:   RegV30,
  2170  			name: "uqxtn v30.2s, v25.2d",
  2171  			inst: UQXTN,
  2172  			exp:  []byte{0x3e, 0x4b, 0xa1, 0x2e},
  2173  			arr:  VectorArrangement2S,
  2174  		},
  2175  		{
  2176  			x1:   RegV25,
  2177  			x2:   RegV30,
  2178  			name: "uqxtn v30.4h, v25.4s",
  2179  			inst: UQXTN,
  2180  			exp:  []byte{0x3e, 0x4b, 0x61, 0x2e},
  2181  			arr:  VectorArrangement4H,
  2182  		},
  2183  		{
  2184  			x1:   RegV25,
  2185  			x2:   RegV30,
  2186  			name: "sqxtn2 v30.16b, v25.8h",
  2187  			inst: SQXTN2,
  2188  			exp:  []byte{0x3e, 0x4b, 0x21, 0x4e},
  2189  			arr:  VectorArrangement16B,
  2190  		},
  2191  		{
  2192  			x1:   RegV25,
  2193  			x2:   RegV30,
  2194  			name: "sqxtn2 v30.8h, v25.4s",
  2195  			inst: SQXTN2,
  2196  			exp:  []byte{0x3e, 0x4b, 0x61, 0x4e},
  2197  			arr:  VectorArrangement8H,
  2198  		},
  2199  		{
  2200  			x1:   RegV25,
  2201  			x2:   RegV30,
  2202  			name: "sqxtn2 v30.4s, v25.2d",
  2203  			inst: SQXTN2,
  2204  			exp:  []byte{0x3e, 0x4b, 0xa1, 0x4e},
  2205  			arr:  VectorArrangement4S,
  2206  		},
  2207  		{
  2208  			x1:   RegV25,
  2209  			x2:   RegV30,
  2210  			name: "sqxtun v30.8b, v25.8h",
  2211  			inst: SQXTUN,
  2212  			exp:  []byte{0x3e, 0x2b, 0x21, 0x2e},
  2213  			arr:  VectorArrangement8B,
  2214  		},
  2215  		{
  2216  			x1:   RegV25,
  2217  			x2:   RegV30,
  2218  			name: "sqxtun v30.4h, v25.4s",
  2219  			inst: SQXTUN,
  2220  			exp:  []byte{0x3e, 0x2b, 0x61, 0x2e},
  2221  			arr:  VectorArrangement4H,
  2222  		},
  2223  		{
  2224  			x1:   RegV25,
  2225  			x2:   RegV30,
  2226  			name: "sqxtun v30.2s, v25.2d",
  2227  			inst: SQXTUN,
  2228  			exp:  []byte{0x3e, 0x2b, 0xa1, 0x2e},
  2229  			arr:  VectorArrangement2S,
  2230  		},
  2231  		{
  2232  			x1:   RegV25,
  2233  			x2:   RegV30,
  2234  			name: "sqxtun2 v30.16b, v25.8h",
  2235  			inst: SQXTUN2,
  2236  			exp:  []byte{0x3e, 0x2b, 0x21, 0x6e},
  2237  			arr:  VectorArrangement16B,
  2238  		},
  2239  		{
  2240  			x1:   RegV25,
  2241  			x2:   RegV30,
  2242  			name: "sqxtun2 v30.8h, v25.4s",
  2243  			inst: SQXTUN2,
  2244  			exp:  []byte{0x3e, 0x2b, 0x61, 0x6e},
  2245  			arr:  VectorArrangement8H,
  2246  		},
  2247  		{
  2248  			x1:   RegV25,
  2249  			x2:   RegV30,
  2250  			name: "sqxtun2 v30.4s, v25.2d",
  2251  			inst: SQXTUN2,
  2252  			exp:  []byte{0x3e, 0x2b, 0xa1, 0x6e},
  2253  			arr:  VectorArrangement4S,
  2254  		},
  2255  		{
  2256  			x1:   RegV25,
  2257  			x2:   RegV30,
  2258  			name: "scvtf v30.2d, v25.2d",
  2259  			inst: VSCVTF,
  2260  			exp:  []byte{0x3e, 0xdb, 0x61, 0x4e},
  2261  			arr:  VectorArrangement2D,
  2262  		},
  2263  		{
  2264  			x1:   RegV25,
  2265  			x2:   RegV30,
  2266  			name: "scvtf v30.4s, v25.4s",
  2267  			inst: VSCVTF,
  2268  			exp:  []byte{0x3e, 0xdb, 0x21, 0x4e},
  2269  			arr:  VectorArrangement4S,
  2270  		},
  2271  		{
  2272  			x1:   RegV25,
  2273  			x2:   RegV30,
  2274  			name: "ucvtf v30.2d, v25.2d",
  2275  			inst: VUCVTF,
  2276  			exp:  []byte{0x3e, 0xdb, 0x61, 0x6e},
  2277  			arr:  VectorArrangement2D,
  2278  		},
  2279  		{
  2280  			x1:   RegV25,
  2281  			x2:   RegV30,
  2282  			name: "ucvtf v30.4s, v25.4s",
  2283  			inst: VUCVTF,
  2284  			exp:  []byte{0x3e, 0xdb, 0x21, 0x6e},
  2285  			arr:  VectorArrangement4S,
  2286  		},
  2287  		{
  2288  			x1:   RegV25,
  2289  			x2:   RegV30,
  2290  			name: "fcvtl v30.2d, v25.2s",
  2291  			inst: FCVTL,
  2292  			exp:  []byte{0x3e, 0x7b, 0x61, 0xe},
  2293  			arr:  VectorArrangement2S,
  2294  		},
  2295  		{
  2296  			x1:   RegV25,
  2297  			x2:   RegV30,
  2298  			name: "fcvtl v30.4s, v25.4h",
  2299  			inst: FCVTL,
  2300  			exp:  []byte{0x3e, 0x7b, 0x21, 0xe},
  2301  			arr:  VectorArrangement4H,
  2302  		},
  2303  		{
  2304  			x1:   RegV25,
  2305  			x2:   RegV30,
  2306  			name: "fcvtn v30.2s, v25.2d",
  2307  			inst: FCVTN,
  2308  			exp:  []byte{0x3e, 0x6b, 0x61, 0xe},
  2309  			arr:  VectorArrangement2S,
  2310  		},
  2311  		{
  2312  			x1:   RegV25,
  2313  			x2:   RegV30,
  2314  			name: "fcvtn v30.4h, v25.4s",
  2315  			inst: FCVTN,
  2316  			exp:  []byte{0x3e, 0x6b, 0x21, 0xe},
  2317  			arr:  VectorArrangement4H,
  2318  		},
  2319  	}
  2320  
  2321  	for _, tt := range tests {
  2322  		tc := tt
  2323  		t.Run(tc.name, func(t *testing.T) {
  2324  			code := asm.CodeSegment{}
  2325  			defer func() { require.NoError(t, code.Unmap()) }()
  2326  
  2327  			a := NewAssembler(asm.NilRegister)
  2328  			buf := code.NextCodeSection()
  2329  			err := a.encodeVectorRegisterToVectorRegister(buf, &nodeImpl{
  2330  				instruction:       tc.inst,
  2331  				srcReg:            tc.x1,
  2332  				srcConst:          tc.c,
  2333  				dstReg:            tc.x2,
  2334  				vectorArrangement: tc.arr,
  2335  				srcVectorIndex:    tc.srcIndex,
  2336  				dstVectorIndex:    tc.dstIndex,
  2337  			})
  2338  			require.NoError(t, err)
  2339  			actual := buf.Bytes()
  2340  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  2341  		})
  2342  	}
  2343  }
  2344  
  2345  func TestAssemblerImpl_EncodeVectorRegisterToRegister(t *testing.T) {
  2346  	tests := []struct {
  2347  		name string
  2348  		n    *nodeImpl
  2349  		exp  []byte
  2350  	}{
  2351  		{
  2352  			name: "umov w10, v0.b[0xf]",
  2353  			n: &nodeImpl{
  2354  				instruction:       UMOV,
  2355  				srcReg:            RegV0,
  2356  				dstReg:            RegR10,
  2357  				vectorArrangement: VectorArrangementB,
  2358  				srcVectorIndex:    15,
  2359  			},
  2360  			exp: []byte{0xa, 0x3c, 0x1f, 0xe},
  2361  		},
  2362  		{
  2363  			name: "mov w10, v0.s[3]",
  2364  			n: &nodeImpl{
  2365  				instruction:       UMOV,
  2366  				srcReg:            RegV0,
  2367  				dstReg:            RegR10,
  2368  				vectorArrangement: VectorArrangementS,
  2369  				srcVectorIndex:    3,
  2370  			},
  2371  			exp: []byte{0xa, 0x3c, 0x1c, 0xe},
  2372  		},
  2373  		{
  2374  			name: "mov x5, v30.d[1]",
  2375  			n: &nodeImpl{
  2376  				instruction:       UMOV,
  2377  				srcReg:            RegV30,
  2378  				dstReg:            RegR5,
  2379  				vectorArrangement: VectorArrangementD,
  2380  				srcVectorIndex:    1,
  2381  			},
  2382  			exp: []byte{0xc5, 0x3f, 0x18, 0x4e},
  2383  		},
  2384  		{
  2385  			name: "smov w10, v0.b[0xf]",
  2386  			n: &nodeImpl{
  2387  				instruction:       SMOV32,
  2388  				srcReg:            RegV0,
  2389  				dstReg:            RegR10,
  2390  				vectorArrangement: VectorArrangementB,
  2391  				srcVectorIndex:    15,
  2392  			},
  2393  			exp: []byte{0xa, 0x2c, 0x1f, 0xe},
  2394  		},
  2395  		{
  2396  			name: "smov w10, v0.b[0]",
  2397  			n: &nodeImpl{
  2398  				instruction:       SMOV32,
  2399  				srcReg:            RegV0,
  2400  				dstReg:            RegR10,
  2401  				vectorArrangement: VectorArrangementB,
  2402  				srcVectorIndex:    0,
  2403  			},
  2404  			exp: []byte{0xa, 0x2c, 0x1, 0xe},
  2405  		},
  2406  		{
  2407  			name: "smov w1, v30.h[7]",
  2408  			n: &nodeImpl{
  2409  				instruction:       SMOV32,
  2410  				srcReg:            RegV30,
  2411  				dstReg:            RegR1,
  2412  				vectorArrangement: VectorArrangementH,
  2413  				srcVectorIndex:    7,
  2414  			},
  2415  			exp: []byte{0xc1, 0x2f, 0x1e, 0xe},
  2416  		},
  2417  		{
  2418  			name: "smov w1, v30.h[0]",
  2419  			n: &nodeImpl{
  2420  				instruction:       SMOV32,
  2421  				srcReg:            RegV30,
  2422  				dstReg:            RegR1,
  2423  				vectorArrangement: VectorArrangementH,
  2424  				srcVectorIndex:    0,
  2425  			},
  2426  			exp: []byte{0xc1, 0x2f, 0x2, 0xe},
  2427  		},
  2428  	}
  2429  
  2430  	for _, tt := range tests {
  2431  		tc := tt
  2432  		t.Run(tc.name, func(t *testing.T) {
  2433  			code := asm.CodeSegment{}
  2434  			defer func() { require.NoError(t, code.Unmap()) }()
  2435  
  2436  			a := NewAssembler(asm.NilRegister)
  2437  			buf := code.NextCodeSection()
  2438  			err := a.encodeVectorRegisterToRegister(buf, tc.n)
  2439  			require.NoError(t, err)
  2440  
  2441  			actual := buf.Bytes()
  2442  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  2443  		})
  2444  	}
  2445  }
  2446  
  2447  func TestAssemblerImpl_EncodeLeftShiftedRegisterToRegister(t *testing.T) {
  2448  	t.Run("error", func(t *testing.T) {
  2449  		tests := []struct {
  2450  			n      *nodeImpl
  2451  			expErr string
  2452  		}{
  2453  			{
  2454  				n: &nodeImpl{
  2455  					instruction: SUB, types: operandTypesLeftShiftedRegisterToRegister,
  2456  					srcReg: RegR0, srcReg2: RegR0, dstReg: RegR0,
  2457  				},
  2458  				expErr: "SUB is unsupported for LeftShiftedRegisterToRegister type",
  2459  			},
  2460  			{
  2461  				n: &nodeImpl{
  2462  					instruction: ADD,
  2463  					srcConst:    -1, srcReg: RegR0, srcReg2: RegR0, dstReg: RegR0,
  2464  				},
  2465  				expErr: "shift amount must fit in unsigned 6-bit integer (0-64) but got -1",
  2466  			},
  2467  			{
  2468  				n: &nodeImpl{
  2469  					instruction: ADD,
  2470  					srcConst:    -1, srcReg: RegV0, srcReg2: RegR0, dstReg: RegR0,
  2471  				},
  2472  				expErr: "V0 is not integer",
  2473  			},
  2474  			{
  2475  				n: &nodeImpl{
  2476  					instruction: ADD,
  2477  					srcConst:    -1, srcReg: RegR0, srcReg2: RegV0, dstReg: RegR0,
  2478  				},
  2479  				expErr: "V0 is not integer",
  2480  			},
  2481  			{
  2482  				n: &nodeImpl{
  2483  					instruction: ADD,
  2484  					srcConst:    -1, srcReg: RegR0, srcReg2: RegR0, dstReg: RegV0,
  2485  				},
  2486  				expErr: "V0 is not integer",
  2487  			},
  2488  		}
  2489  
  2490  		code := asm.CodeSegment{}
  2491  		defer func() { require.NoError(t, code.Unmap()) }()
  2492  
  2493  		for _, tt := range tests {
  2494  			tc := tt
  2495  			a := NewAssembler(asm.NilRegister)
  2496  			buf := code.NextCodeSection()
  2497  			err := a.encodeLeftShiftedRegisterToRegister(buf, tc.n)
  2498  			require.EqualError(t, err, tc.expErr)
  2499  		}
  2500  	})
  2501  
  2502  	tests := []struct {
  2503  		name string
  2504  		n    *nodeImpl
  2505  		exp  []byte
  2506  	}{
  2507  		{
  2508  			name: "ADD",
  2509  			n: &nodeImpl{
  2510  				instruction:       ADD,
  2511  				srcReg:            RegR0,
  2512  				srcReg2:           RegR29,
  2513  				srcConst:          1,
  2514  				dstReg:            RegR21,
  2515  				vectorArrangement: VectorArrangementH,
  2516  				srcVectorIndex:    0,
  2517  			},
  2518  			exp: []byte{0x15, 0x4, 0x1d, 0x8b},
  2519  		},
  2520  		{
  2521  			name: "ADD",
  2522  			n: &nodeImpl{
  2523  				instruction:       ADD,
  2524  				srcReg:            RegR0,
  2525  				srcReg2:           RegR29,
  2526  				srcConst:          2,
  2527  				dstReg:            RegR21,
  2528  				vectorArrangement: VectorArrangementH,
  2529  				srcVectorIndex:    0,
  2530  			},
  2531  			exp: []byte{0x15, 0x8, 0x1d, 0x8b},
  2532  		},
  2533  		{
  2534  			name: "ADD",
  2535  			n: &nodeImpl{
  2536  				instruction:       ADD,
  2537  				srcReg:            RegR0,
  2538  				srcReg2:           RegR29,
  2539  				srcConst:          8,
  2540  				dstReg:            RegR21,
  2541  				vectorArrangement: VectorArrangementH,
  2542  				srcVectorIndex:    0,
  2543  			},
  2544  			exp: []byte{0x15, 0x20, 0x1d, 0x8b},
  2545  		},
  2546  		{
  2547  			name: "ADD",
  2548  			n: &nodeImpl{
  2549  				instruction:       ADD,
  2550  				srcReg:            RegR29,
  2551  				srcReg2:           RegR0,
  2552  				srcConst:          16,
  2553  				dstReg:            RegR21,
  2554  				vectorArrangement: VectorArrangementH,
  2555  				srcVectorIndex:    0,
  2556  			},
  2557  			exp: []byte{0xb5, 0x43, 0x0, 0x8b},
  2558  		},
  2559  		{
  2560  			name: "ADD",
  2561  			n: &nodeImpl{
  2562  				instruction:       ADD,
  2563  				srcReg:            RegR29,
  2564  				srcReg2:           RegR0,
  2565  				srcConst:          64,
  2566  				dstReg:            RegR21,
  2567  				vectorArrangement: VectorArrangementH,
  2568  				srcVectorIndex:    0,
  2569  			},
  2570  			exp: []byte{0xb5, 0x3, 0x0, 0x8b},
  2571  		},
  2572  		{
  2573  			name: "ADD",
  2574  			n: &nodeImpl{
  2575  				instruction:       ADD,
  2576  				srcReg:            RegRZR,
  2577  				srcReg2:           RegR0,
  2578  				srcConst:          64,
  2579  				dstReg:            RegR21,
  2580  				vectorArrangement: VectorArrangementH,
  2581  				srcVectorIndex:    0,
  2582  			},
  2583  			exp: []byte{0xf5, 0x3, 0x0, 0x8b},
  2584  		},
  2585  		{
  2586  			name: "ADD",
  2587  			n: &nodeImpl{
  2588  				instruction:       ADD,
  2589  				srcReg:            RegRZR,
  2590  				srcReg2:           RegRZR,
  2591  				srcConst:          64,
  2592  				dstReg:            RegR21,
  2593  				vectorArrangement: VectorArrangementH,
  2594  				srcVectorIndex:    0,
  2595  			},
  2596  			exp: []byte{0xf5, 0x3, 0x1f, 0x8b},
  2597  		},
  2598  		{
  2599  			name: "ADD",
  2600  			n: &nodeImpl{
  2601  				instruction:       ADD,
  2602  				srcReg:            RegRZR,
  2603  				srcReg2:           RegRZR,
  2604  				srcConst:          64,
  2605  				dstReg:            RegRZR,
  2606  				vectorArrangement: VectorArrangementH,
  2607  				srcVectorIndex:    0,
  2608  			},
  2609  			exp: []byte{0xff, 0x3, 0x1f, 0x8b},
  2610  		},
  2611  	}
  2612  
  2613  	for _, tt := range tests {
  2614  		tc := tt
  2615  		t.Run(tc.name, func(t *testing.T) {
  2616  			code := asm.CodeSegment{}
  2617  			defer func() { require.NoError(t, code.Unmap()) }()
  2618  
  2619  			a := NewAssembler(asm.NilRegister)
  2620  			buf := code.NextCodeSection()
  2621  			err := a.encodeLeftShiftedRegisterToRegister(buf, tc.n)
  2622  			require.NoError(t, err)
  2623  
  2624  			actual := buf.Bytes()
  2625  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  2626  		})
  2627  	}
  2628  }
  2629  
  2630  func TestAssemblerImpl_encodeTwoRegistersToNone(t *testing.T) {
  2631  	t.Run("error", func(t *testing.T) {
  2632  		tests := []struct {
  2633  			n      *nodeImpl
  2634  			expErr string
  2635  		}{
  2636  			{
  2637  				n: &nodeImpl{
  2638  					instruction: SUB, types: operandTypesTwoRegistersToNone,
  2639  					srcReg: RegR0, srcReg2: RegR0, dstReg: RegR0,
  2640  				},
  2641  				expErr: "SUB is unsupported for TwoRegistersToNone type",
  2642  			},
  2643  			{
  2644  				n: &nodeImpl{
  2645  					instruction: CMP,
  2646  					srcReg:      RegR0, srcReg2: RegV0,
  2647  				},
  2648  				expErr: "V0 is not integer",
  2649  			},
  2650  			{
  2651  				n: &nodeImpl{
  2652  					instruction: FCMPS,
  2653  					srcReg:      RegR0, srcReg2: RegV0,
  2654  				},
  2655  				expErr: "R0 is not vector",
  2656  			},
  2657  		}
  2658  
  2659  		code := asm.CodeSegment{}
  2660  		defer func() { require.NoError(t, code.Unmap()) }()
  2661  
  2662  		for _, tt := range tests {
  2663  			tc := tt
  2664  			a := NewAssembler(asm.NilRegister)
  2665  			buf := code.NextCodeSection()
  2666  			err := a.encodeTwoRegistersToNone(buf, tc.n)
  2667  			require.EqualError(t, err, tc.expErr)
  2668  		}
  2669  	})
  2670  
  2671  	tests := []struct {
  2672  		name string
  2673  		n    *nodeImpl
  2674  		exp  []byte
  2675  	}{
  2676  		{
  2677  			name: "CMP",
  2678  			n: &nodeImpl{
  2679  				instruction:       CMP,
  2680  				srcReg:            RegRZR,
  2681  				srcReg2:           RegRZR,
  2682  				vectorArrangement: VectorArrangementH,
  2683  				srcVectorIndex:    0,
  2684  			},
  2685  			exp: []byte{0xff, 0x3, 0x1f, 0xeb},
  2686  		},
  2687  		{
  2688  			name: "CMP",
  2689  			n: &nodeImpl{
  2690  				instruction:       CMP,
  2691  				srcReg:            RegRZR,
  2692  				srcReg2:           RegR30,
  2693  				vectorArrangement: VectorArrangementH,
  2694  				srcVectorIndex:    0,
  2695  			},
  2696  			exp: []byte{0xdf, 0x3, 0x1f, 0xeb},
  2697  		},
  2698  		{
  2699  			name: "CMP",
  2700  			n: &nodeImpl{
  2701  				instruction:       CMP,
  2702  				srcReg:            RegR30,
  2703  				srcReg2:           RegRZR,
  2704  				vectorArrangement: VectorArrangementH,
  2705  				srcVectorIndex:    0,
  2706  			},
  2707  			exp: []byte{0xff, 0x3, 0x1e, 0xeb},
  2708  		},
  2709  		{
  2710  			name: "CMP",
  2711  			n: &nodeImpl{
  2712  				instruction:       CMP,
  2713  				srcReg:            RegR30,
  2714  				srcReg2:           RegR30,
  2715  				vectorArrangement: VectorArrangementH,
  2716  				srcVectorIndex:    0,
  2717  			},
  2718  			exp: []byte{0xdf, 0x3, 0x1e, 0xeb},
  2719  		},
  2720  		{
  2721  			name: "CMPW",
  2722  			n: &nodeImpl{
  2723  				instruction:       CMPW,
  2724  				srcReg:            RegRZR,
  2725  				srcReg2:           RegRZR,
  2726  				vectorArrangement: VectorArrangementH,
  2727  				srcVectorIndex:    0,
  2728  			},
  2729  			exp: []byte{0xff, 0x3, 0x1f, 0x6b},
  2730  		},
  2731  		{
  2732  			name: "CMPW",
  2733  			n: &nodeImpl{
  2734  				instruction:       CMPW,
  2735  				srcReg:            RegRZR,
  2736  				srcReg2:           RegR30,
  2737  				vectorArrangement: VectorArrangementH,
  2738  				srcVectorIndex:    0,
  2739  			},
  2740  			exp: []byte{0xdf, 0x3, 0x1f, 0x6b},
  2741  		},
  2742  		{
  2743  			name: "CMPW",
  2744  			n: &nodeImpl{
  2745  				instruction:       CMPW,
  2746  				srcReg:            RegR30,
  2747  				srcReg2:           RegRZR,
  2748  				vectorArrangement: VectorArrangementH,
  2749  				srcVectorIndex:    0,
  2750  			},
  2751  			exp: []byte{0xff, 0x3, 0x1e, 0x6b},
  2752  		},
  2753  		{
  2754  			name: "CMPW",
  2755  			n: &nodeImpl{
  2756  				instruction:       CMPW,
  2757  				srcReg:            RegR30,
  2758  				srcReg2:           RegR30,
  2759  				vectorArrangement: VectorArrangementH,
  2760  				srcVectorIndex:    0,
  2761  			},
  2762  			exp: []byte{0xdf, 0x3, 0x1e, 0x6b},
  2763  		},
  2764  		{
  2765  			name: "FCMPD",
  2766  			n: &nodeImpl{
  2767  				instruction:       FCMPD,
  2768  				srcReg:            RegV0,
  2769  				srcReg2:           RegV0,
  2770  				vectorArrangement: VectorArrangementH,
  2771  				srcVectorIndex:    0,
  2772  			},
  2773  			exp: []byte{0x0, 0x20, 0x60, 0x1e},
  2774  		},
  2775  		{
  2776  			name: "FCMPD",
  2777  			n: &nodeImpl{
  2778  				instruction:       FCMPD,
  2779  				srcReg:            RegV0,
  2780  				srcReg2:           RegV31,
  2781  				vectorArrangement: VectorArrangementH,
  2782  				srcVectorIndex:    0,
  2783  			},
  2784  			exp: []byte{0xe0, 0x23, 0x60, 0x1e},
  2785  		},
  2786  		{
  2787  			name: "FCMPD",
  2788  			n: &nodeImpl{
  2789  				instruction:       FCMPD,
  2790  				srcReg:            RegV31,
  2791  				srcReg2:           RegV0,
  2792  				vectorArrangement: VectorArrangementH,
  2793  				srcVectorIndex:    0,
  2794  			},
  2795  			exp: []byte{0x0, 0x20, 0x7f, 0x1e},
  2796  		},
  2797  		{
  2798  			name: "FCMPD",
  2799  			n: &nodeImpl{
  2800  				instruction:       FCMPD,
  2801  				srcReg:            RegV31,
  2802  				srcReg2:           RegV31,
  2803  				vectorArrangement: VectorArrangementH,
  2804  				srcVectorIndex:    0,
  2805  			},
  2806  			exp: []byte{0xe0, 0x23, 0x7f, 0x1e},
  2807  		},
  2808  		{
  2809  			name: "FCMPS",
  2810  			n: &nodeImpl{
  2811  				instruction:       FCMPS,
  2812  				srcReg:            RegV0,
  2813  				srcReg2:           RegV0,
  2814  				vectorArrangement: VectorArrangementH,
  2815  				srcVectorIndex:    0,
  2816  			},
  2817  			exp: []byte{0x0, 0x20, 0x20, 0x1e},
  2818  		},
  2819  		{
  2820  			name: "FCMPS",
  2821  			n: &nodeImpl{
  2822  				instruction:       FCMPS,
  2823  				srcReg:            RegV0,
  2824  				srcReg2:           RegV31,
  2825  				vectorArrangement: VectorArrangementH,
  2826  				srcVectorIndex:    0,
  2827  			},
  2828  			exp: []byte{0xe0, 0x23, 0x20, 0x1e},
  2829  		},
  2830  		{
  2831  			name: "FCMPS",
  2832  			n: &nodeImpl{
  2833  				instruction:       FCMPS,
  2834  				srcReg:            RegV31,
  2835  				srcReg2:           RegV0,
  2836  				vectorArrangement: VectorArrangementH,
  2837  				srcVectorIndex:    0,
  2838  			},
  2839  			exp: []byte{0x0, 0x20, 0x3f, 0x1e},
  2840  		},
  2841  		{
  2842  			name: "FCMPS",
  2843  			n: &nodeImpl{
  2844  				instruction:       FCMPS,
  2845  				srcReg:            RegV31,
  2846  				srcReg2:           RegV31,
  2847  				vectorArrangement: VectorArrangementH,
  2848  				srcVectorIndex:    0,
  2849  			},
  2850  			exp: []byte{0xe0, 0x23, 0x3f, 0x1e},
  2851  		},
  2852  	}
  2853  
  2854  	for _, tt := range tests {
  2855  		tc := tt
  2856  		t.Run(tc.name, func(t *testing.T) {
  2857  			code := asm.CodeSegment{}
  2858  			defer func() { require.NoError(t, code.Unmap()) }()
  2859  
  2860  			a := NewAssembler(asm.NilRegister)
  2861  			buf := code.NextCodeSection()
  2862  			err := a.encodeTwoRegistersToNone(buf, tc.n)
  2863  			require.NoError(t, err)
  2864  
  2865  			actual := buf.Bytes()
  2866  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  2867  		})
  2868  	}
  2869  }
  2870  
  2871  func TestAssemblerImpl_EncodeThreeRegistersToRegister(t *testing.T) {
  2872  	const src1, src2, src3, dst = RegR1, RegR10, RegR30, RegR11
  2873  
  2874  	tests := []struct {
  2875  		name string
  2876  		exp  []byte
  2877  		inst asm.Instruction
  2878  	}{
  2879  		{
  2880  			name: "MSUB/src1=R1,src2=R10,src3=R30,dst=R11",
  2881  			inst: MSUB,
  2882  			exp:  []byte{0xcb, 0xab, 0x1, 0x9b},
  2883  		},
  2884  		{
  2885  			name: "MSUBW/src1=R1,src2=R10,src3=R30,dst=R11",
  2886  			inst: MSUBW,
  2887  			exp:  []byte{0xcb, 0xab, 0x1, 0x1b},
  2888  		},
  2889  	}
  2890  
  2891  	for _, tc := range tests {
  2892  		t.Run(tc.name, func(t *testing.T) {
  2893  			code := asm.CodeSegment{}
  2894  			defer func() { require.NoError(t, code.Unmap()) }()
  2895  
  2896  			a := NewAssembler(asm.NilRegister)
  2897  			buf := code.NextCodeSection()
  2898  			err := a.encodeThreeRegistersToRegister(buf, &nodeImpl{
  2899  				instruction: tc.inst, srcReg: src1, srcReg2: src2, dstReg: src3, dstReg2: dst,
  2900  			})
  2901  			require.NoError(t, err)
  2902  
  2903  			actual := buf.Bytes()
  2904  			require.Equal(t, tc.exp, actual[:4])
  2905  		})
  2906  	}
  2907  }
  2908  
  2909  func TestAssemblerImpl_encodeTwoVectorRegistersToVectorRegister(t *testing.T) {
  2910  	tests := []struct {
  2911  		name string
  2912  		n    *nodeImpl
  2913  		exp  []byte
  2914  	}{
  2915  		{
  2916  			name: "orr v30.16b, v10.16b, v1.16b",
  2917  			n: &nodeImpl{
  2918  				instruction:       VORR,
  2919  				dstReg:            RegV30,
  2920  				srcReg:            RegV1,
  2921  				srcReg2:           RegV10,
  2922  				vectorArrangement: VectorArrangement16B,
  2923  			},
  2924  			exp: []byte{0x5e, 0x1d, 0xa1, 0x4e},
  2925  		},
  2926  		{
  2927  			name: "orr v30.8b, v10.8b, v1.8b",
  2928  			n: &nodeImpl{
  2929  				instruction:       VORR,
  2930  				dstReg:            RegV30,
  2931  				srcReg:            RegV1,
  2932  				srcReg2:           RegV10,
  2933  				vectorArrangement: VectorArrangement8B,
  2934  			},
  2935  			exp: []byte{0x5e, 0x1d, 0xa1, 0xe},
  2936  		},
  2937  		{
  2938  			name: "bsl v0.8b, v15.8b, v1.8b",
  2939  			n: &nodeImpl{
  2940  				instruction:       BSL,
  2941  				dstReg:            RegV0,
  2942  				srcReg:            RegV1,
  2943  				srcReg2:           RegV15,
  2944  				vectorArrangement: VectorArrangement8B,
  2945  			},
  2946  			exp: []byte{0xe0, 0x1d, 0x61, 0x2e},
  2947  		},
  2948  		{
  2949  			name: "zip1 v0.4s, v15.4s, v1.4s",
  2950  			n: &nodeImpl{
  2951  				instruction:       ZIP1,
  2952  				dstReg:            RegV0,
  2953  				srcReg:            RegV1,
  2954  				srcReg2:           RegV15,
  2955  				vectorArrangement: VectorArrangement4S,
  2956  			},
  2957  			exp: []byte{0xe0, 0x39, 0x81, 0x4e},
  2958  		},
  2959  		{
  2960  			name: "zip1 v0.2d, v15.2d, v1.2d",
  2961  			n: &nodeImpl{
  2962  				instruction:       ZIP1,
  2963  				dstReg:            RegV0,
  2964  				srcReg:            RegV1,
  2965  				srcReg2:           RegV15,
  2966  				vectorArrangement: VectorArrangement2D,
  2967  			},
  2968  			exp: []byte{0xe0, 0x39, 0xc1, 0x4e},
  2969  		},
  2970  		{
  2971  			name: "ext v0.16b, v15.16b, v1.16b, #0xf",
  2972  			n: &nodeImpl{
  2973  				instruction:       EXT,
  2974  				dstReg:            RegV0,
  2975  				srcReg:            RegV1,
  2976  				srcReg2:           RegV15,
  2977  				srcConst:          0xf,
  2978  				vectorArrangement: VectorArrangement16B,
  2979  			},
  2980  			exp: []byte{0xe0, 0x79, 0x1, 0x6e},
  2981  		},
  2982  		{
  2983  			name: "ext v0.16b, v15.16b, v1.16b, #8",
  2984  			n: &nodeImpl{
  2985  				instruction:       EXT,
  2986  				dstReg:            RegV0,
  2987  				srcReg:            RegV1,
  2988  				srcReg2:           RegV15,
  2989  				srcConst:          8,
  2990  				vectorArrangement: VectorArrangement16B,
  2991  			},
  2992  			exp: []byte{0xe0, 0x41, 0x1, 0x6e},
  2993  		},
  2994  		{
  2995  			name: "ext v0.16b, v15.16b, v1.16b, #0",
  2996  			n: &nodeImpl{
  2997  				instruction:       EXT,
  2998  				dstReg:            RegV0,
  2999  				srcReg:            RegV1,
  3000  				srcReg2:           RegV15,
  3001  				srcConst:          0,
  3002  				vectorArrangement: VectorArrangement16B,
  3003  			},
  3004  			exp: []byte{0xe0, 0x1, 0x1, 0x6e},
  3005  		},
  3006  		{
  3007  			name: "ext v0.8b, v15.8b, v1.8b, #7",
  3008  			n: &nodeImpl{
  3009  				instruction:       EXT,
  3010  				dstReg:            RegV0,
  3011  				srcReg:            RegV1,
  3012  				srcReg2:           RegV15,
  3013  				srcConst:          7,
  3014  				vectorArrangement: VectorArrangement8B,
  3015  			},
  3016  			exp: []byte{0xe0, 0x39, 0x1, 0x2e},
  3017  		},
  3018  		{
  3019  			name: "cmeq v0.8b, v15.8b, v1.8b",
  3020  			n: &nodeImpl{
  3021  				instruction:       CMEQ,
  3022  				dstReg:            RegV0,
  3023  				srcReg:            RegV1,
  3024  				srcReg2:           RegV15,
  3025  				vectorArrangement: VectorArrangement8B,
  3026  			},
  3027  			exp: []byte{0xe0, 0x8d, 0x21, 0x2e},
  3028  		},
  3029  		{
  3030  			name: "cmgt v0.16b, v15.16b, v1.16b",
  3031  			n: &nodeImpl{
  3032  				instruction:       CMGT,
  3033  				dstReg:            RegV0,
  3034  				srcReg:            RegV1,
  3035  				srcReg2:           RegV15,
  3036  				vectorArrangement: VectorArrangement16B,
  3037  			},
  3038  			exp: []byte{0xe0, 0x35, 0x21, 0x4e},
  3039  		},
  3040  		{
  3041  			name: "cmhi v0.8h, v15.8h, v1.8h",
  3042  			n: &nodeImpl{
  3043  				instruction:       CMHI,
  3044  				dstReg:            RegV0,
  3045  				srcReg:            RegV1,
  3046  				srcReg2:           RegV15,
  3047  				vectorArrangement: VectorArrangement8H,
  3048  			},
  3049  			exp: []byte{0xe0, 0x35, 0x61, 0x6e},
  3050  		},
  3051  		{
  3052  			name: "cmhi v0.4h, v15.4h, v1.4h",
  3053  			n: &nodeImpl{
  3054  				instruction:       CMHI,
  3055  				dstReg:            RegV0,
  3056  				srcReg:            RegV1,
  3057  				srcReg2:           RegV15,
  3058  				vectorArrangement: VectorArrangement4H,
  3059  			},
  3060  			exp: []byte{0xe0, 0x35, 0x61, 0x2e},
  3061  		},
  3062  		{
  3063  			name: "cmge v0.4s, v15.4s, v1.4s",
  3064  			n: &nodeImpl{
  3065  				instruction:       CMGE,
  3066  				dstReg:            RegV0,
  3067  				srcReg:            RegV1,
  3068  				srcReg2:           RegV15,
  3069  				vectorArrangement: VectorArrangement4S,
  3070  			},
  3071  			exp: []byte{0xe0, 0x3d, 0xa1, 0x4e},
  3072  		},
  3073  		{
  3074  			name: "cmge v0.2s, v15.2s, v1.2s",
  3075  			n: &nodeImpl{
  3076  				instruction:       CMGE,
  3077  				dstReg:            RegV0,
  3078  				srcReg:            RegV1,
  3079  				srcReg2:           RegV15,
  3080  				vectorArrangement: VectorArrangement2S,
  3081  			},
  3082  			exp: []byte{0xe0, 0x3d, 0xa1, 0xe},
  3083  		},
  3084  		{
  3085  			name: "cmhs v30.2d, v4.2d, v11.2d",
  3086  			n: &nodeImpl{
  3087  				instruction:       CMHS,
  3088  				dstReg:            RegV30,
  3089  				srcReg:            RegV11,
  3090  				srcReg2:           RegV4,
  3091  				vectorArrangement: VectorArrangement2D,
  3092  			},
  3093  			exp: []byte{0x9e, 0x3c, 0xeb, 0x6e},
  3094  		},
  3095  		{
  3096  			name: "fcmeq v30.2d, v4.2d, v11.2d",
  3097  			n: &nodeImpl{
  3098  				instruction:       FCMEQ,
  3099  				dstReg:            RegV30,
  3100  				srcReg:            RegV11,
  3101  				srcReg2:           RegV4,
  3102  				vectorArrangement: VectorArrangement2D,
  3103  			},
  3104  			exp: []byte{0x9e, 0xe4, 0x6b, 0x4e},
  3105  		},
  3106  		{
  3107  			name: "fcmeq v30.4s, v4.4s, v11.4s",
  3108  			n: &nodeImpl{
  3109  				instruction:       FCMEQ,
  3110  				dstReg:            RegV30,
  3111  				srcReg:            RegV11,
  3112  				srcReg2:           RegV4,
  3113  				vectorArrangement: VectorArrangement4S,
  3114  			},
  3115  			exp: []byte{0x9e, 0xe4, 0x2b, 0x4e},
  3116  		},
  3117  		{
  3118  			name: "fcmeq v30.2s, v4.2s, v11.2s",
  3119  			n: &nodeImpl{
  3120  				instruction:       FCMEQ,
  3121  				dstReg:            RegV30,
  3122  				srcReg:            RegV11,
  3123  				srcReg2:           RegV4,
  3124  				vectorArrangement: VectorArrangement2S,
  3125  			},
  3126  			exp: []byte{0x9e, 0xe4, 0x2b, 0xe},
  3127  		},
  3128  		{
  3129  			name: "fcmgt v30.2d, v4.2d, v11.2d",
  3130  			n: &nodeImpl{
  3131  				instruction:       FCMGT,
  3132  				dstReg:            RegV30,
  3133  				srcReg:            RegV11,
  3134  				srcReg2:           RegV4,
  3135  				vectorArrangement: VectorArrangement2D,
  3136  			},
  3137  			exp: []byte{0x9e, 0xe4, 0xeb, 0x6e},
  3138  		},
  3139  		{
  3140  			name: "fcmgt v30.4s, v4.4s, v11.4s",
  3141  			n: &nodeImpl{
  3142  				instruction:       FCMGT,
  3143  				dstReg:            RegV30,
  3144  				srcReg:            RegV11,
  3145  				srcReg2:           RegV4,
  3146  				vectorArrangement: VectorArrangement4S,
  3147  			},
  3148  			exp: []byte{0x9e, 0xe4, 0xab, 0x6e},
  3149  		},
  3150  		{
  3151  			name: "fcmgt v30.2s, v4.2s, v11.2s",
  3152  			n: &nodeImpl{
  3153  				instruction:       FCMGT,
  3154  				dstReg:            RegV30,
  3155  				srcReg:            RegV11,
  3156  				srcReg2:           RegV4,
  3157  				vectorArrangement: VectorArrangement2S,
  3158  			},
  3159  			exp: []byte{0x9e, 0xe4, 0xab, 0x2e},
  3160  		},
  3161  		{
  3162  			name: "fcmge v30.2d, v4.2d, v11.2d",
  3163  			n: &nodeImpl{
  3164  				instruction:       FCMGE,
  3165  				dstReg:            RegV30,
  3166  				srcReg:            RegV11,
  3167  				srcReg2:           RegV4,
  3168  				vectorArrangement: VectorArrangement2D,
  3169  			},
  3170  			exp: []byte{0x9e, 0xe4, 0x6b, 0x6e},
  3171  		},
  3172  		{
  3173  			name: "fcmge v30.4s, v4.4s, v11.4s",
  3174  			n: &nodeImpl{
  3175  				instruction:       FCMGE,
  3176  				dstReg:            RegV30,
  3177  				srcReg:            RegV11,
  3178  				srcReg2:           RegV4,
  3179  				vectorArrangement: VectorArrangement4S,
  3180  			},
  3181  			exp: []byte{0x9e, 0xe4, 0x2b, 0x6e},
  3182  		},
  3183  		{
  3184  			name: "fcmge v30.2s, v4.2s, v11.2s",
  3185  			n: &nodeImpl{
  3186  				instruction:       FCMGE,
  3187  				dstReg:            RegV30,
  3188  				srcReg:            RegV11,
  3189  				srcReg2:           RegV4,
  3190  				vectorArrangement: VectorArrangement2S,
  3191  			},
  3192  			exp: []byte{0x9e, 0xe4, 0x2b, 0x2e},
  3193  		},
  3194  		{
  3195  			name: "fdiv v30.4s, v4.4s, v11.4s",
  3196  			n: &nodeImpl{
  3197  				instruction:       VFDIV,
  3198  				dstReg:            RegV30,
  3199  				srcReg:            RegV11,
  3200  				srcReg2:           RegV4,
  3201  				vectorArrangement: VectorArrangement4S,
  3202  			},
  3203  			exp: []byte{0x9e, 0xfc, 0x2b, 0x6e},
  3204  		},
  3205  		{
  3206  			name: "fdiv v30.2s, v4.2s, v11.2s",
  3207  			n: &nodeImpl{
  3208  				instruction:       VFDIV,
  3209  				dstReg:            RegV30,
  3210  				srcReg:            RegV11,
  3211  				srcReg2:           RegV4,
  3212  				vectorArrangement: VectorArrangement2S,
  3213  			},
  3214  			exp: []byte{0x9e, 0xfc, 0x2b, 0x2e},
  3215  		},
  3216  		{
  3217  			name: "fdiv v30.2d, v4.2d, v11.2d",
  3218  			n: &nodeImpl{
  3219  				instruction:       VFDIV,
  3220  				dstReg:            RegV30,
  3221  				srcReg:            RegV11,
  3222  				srcReg2:           RegV4,
  3223  				vectorArrangement: VectorArrangement2D,
  3224  			},
  3225  			exp: []byte{0x9e, 0xfc, 0x6b, 0x6e},
  3226  		},
  3227  		{
  3228  			name: "fmul v30.4s, v4.4s, v11.4s",
  3229  			n: &nodeImpl{
  3230  				instruction:       VFMUL,
  3231  				dstReg:            RegV30,
  3232  				srcReg:            RegV11,
  3233  				srcReg2:           RegV4,
  3234  				vectorArrangement: VectorArrangement4S,
  3235  			},
  3236  			exp: []byte{0x9e, 0xdc, 0x2b, 0x6e},
  3237  		},
  3238  		{
  3239  			name: "fmul v30.2s, v4.2s, v11.2s",
  3240  			n: &nodeImpl{
  3241  				instruction:       VFMUL,
  3242  				dstReg:            RegV30,
  3243  				srcReg:            RegV11,
  3244  				srcReg2:           RegV4,
  3245  				vectorArrangement: VectorArrangement2S,
  3246  			},
  3247  			exp: []byte{0x9e, 0xdc, 0x2b, 0x2e},
  3248  		},
  3249  		{
  3250  			name: "fmul v30.2d, v4.2d, v11.2d",
  3251  			n: &nodeImpl{
  3252  				instruction:       VFMUL,
  3253  				dstReg:            RegV30,
  3254  				srcReg:            RegV11,
  3255  				srcReg2:           RegV4,
  3256  				vectorArrangement: VectorArrangement2D,
  3257  			},
  3258  			exp: []byte{0x9e, 0xdc, 0x6b, 0x6e},
  3259  		},
  3260  		{
  3261  			name: "fmin v30.4s, v4.4s, v11.4s",
  3262  			n: &nodeImpl{
  3263  				instruction:       VFMIN,
  3264  				dstReg:            RegV30,
  3265  				srcReg:            RegV11,
  3266  				srcReg2:           RegV4,
  3267  				vectorArrangement: VectorArrangement4S,
  3268  			},
  3269  			exp: []byte{0x9e, 0xf4, 0xab, 0x4e},
  3270  		},
  3271  		{
  3272  			name: "fmin v30.2s, v4.2s, v11.2s",
  3273  			n: &nodeImpl{
  3274  				instruction:       VFMIN,
  3275  				dstReg:            RegV30,
  3276  				srcReg:            RegV11,
  3277  				srcReg2:           RegV4,
  3278  				vectorArrangement: VectorArrangement2S,
  3279  			},
  3280  			exp: []byte{0x9e, 0xf4, 0xab, 0xe},
  3281  		},
  3282  		{
  3283  			name: "fmin v30.2d, v4.2d, v11.2d",
  3284  			n: &nodeImpl{
  3285  				instruction:       VFMIN,
  3286  				dstReg:            RegV30,
  3287  				srcReg:            RegV11,
  3288  				srcReg2:           RegV4,
  3289  				vectorArrangement: VectorArrangement2D,
  3290  			},
  3291  			exp: []byte{0x9e, 0xf4, 0xeb, 0x4e},
  3292  		},
  3293  		{
  3294  			name: "fmax v30.4s, v4.4s, v11.4s",
  3295  			n: &nodeImpl{
  3296  				instruction:       VFMAX,
  3297  				dstReg:            RegV30,
  3298  				srcReg:            RegV11,
  3299  				srcReg2:           RegV4,
  3300  				vectorArrangement: VectorArrangement4S,
  3301  			},
  3302  			exp: []byte{0x9e, 0xf4, 0x2b, 0x4e},
  3303  		},
  3304  		{
  3305  			name: "fmax v30.2s, v4.2s, v11.2s",
  3306  			n: &nodeImpl{
  3307  				instruction:       VFMAX,
  3308  				dstReg:            RegV30,
  3309  				srcReg:            RegV11,
  3310  				srcReg2:           RegV4,
  3311  				vectorArrangement: VectorArrangement2S,
  3312  			},
  3313  			exp: []byte{0x9e, 0xf4, 0x2b, 0xe},
  3314  		},
  3315  		{
  3316  			name: "fmax v30.2d, v4.2d, v11.2d",
  3317  			n: &nodeImpl{
  3318  				instruction:       VFMAX,
  3319  				dstReg:            RegV30,
  3320  				srcReg:            RegV11,
  3321  				srcReg2:           RegV4,
  3322  				vectorArrangement: VectorArrangement2D,
  3323  			},
  3324  			exp: []byte{0x9e, 0xf4, 0x6b, 0x4e},
  3325  		},
  3326  		{
  3327  			name: "mul v30.4s, v4.4s, v11.4s",
  3328  			n: &nodeImpl{
  3329  				instruction:       VMUL,
  3330  				dstReg:            RegV30,
  3331  				srcReg:            RegV11,
  3332  				srcReg2:           RegV4,
  3333  				vectorArrangement: VectorArrangement4S,
  3334  			},
  3335  			exp: []byte{0x9e, 0x9c, 0xab, 0x4e},
  3336  		},
  3337  		{
  3338  			name: "mul v30.16b, v4.16b, v11.16b",
  3339  			n: &nodeImpl{
  3340  				instruction:       VMUL,
  3341  				dstReg:            RegV30,
  3342  				srcReg:            RegV11,
  3343  				srcReg2:           RegV4,
  3344  				vectorArrangement: VectorArrangement16B,
  3345  			},
  3346  			exp: []byte{0x9e, 0x9c, 0x2b, 0x4e},
  3347  		},
  3348  		{
  3349  			name: "sqadd v30.2d, v4.2d, v11.2d",
  3350  			n: &nodeImpl{
  3351  				instruction:       VSQADD,
  3352  				dstReg:            RegV30,
  3353  				srcReg:            RegV11,
  3354  				srcReg2:           RegV4,
  3355  				vectorArrangement: VectorArrangement2D,
  3356  			},
  3357  			exp: []byte{0x9e, 0xc, 0xeb, 0x4e},
  3358  		},
  3359  		{
  3360  			name: "sqadd v30.8h, v4.8h, v11.8h",
  3361  			n: &nodeImpl{
  3362  				instruction:       VSQADD,
  3363  				dstReg:            RegV30,
  3364  				srcReg:            RegV11,
  3365  				srcReg2:           RegV4,
  3366  				vectorArrangement: VectorArrangement8H,
  3367  			},
  3368  			exp: []byte{0x9e, 0xc, 0x6b, 0x4e},
  3369  		},
  3370  		{
  3371  			name: "uqadd v30.4s, v4.4s, v11.4s",
  3372  			n: &nodeImpl{
  3373  				instruction:       VUQADD,
  3374  				dstReg:            RegV30,
  3375  				srcReg:            RegV11,
  3376  				srcReg2:           RegV4,
  3377  				vectorArrangement: VectorArrangement4S,
  3378  			},
  3379  			exp: []byte{0x9e, 0xc, 0xab, 0x6e},
  3380  		},
  3381  		{
  3382  			name: "uqadd v30.8h, v4.8h, v11.8h",
  3383  			n: &nodeImpl{
  3384  				instruction:       VUQADD,
  3385  				dstReg:            RegV30,
  3386  				srcReg:            RegV11,
  3387  				srcReg2:           RegV4,
  3388  				vectorArrangement: VectorArrangement8H,
  3389  			},
  3390  			exp: []byte{0x9e, 0xc, 0x6b, 0x6e},
  3391  		},
  3392  		{
  3393  			name: "smax v30.4s, v4.4s, v11.4s",
  3394  			n: &nodeImpl{
  3395  				instruction:       SMAX,
  3396  				dstReg:            RegV30,
  3397  				srcReg:            RegV11,
  3398  				srcReg2:           RegV4,
  3399  				vectorArrangement: VectorArrangement4S,
  3400  			},
  3401  			exp: []byte{0x9e, 0x64, 0xab, 0x4e},
  3402  		},
  3403  		{
  3404  			name: "smax v30.8h, v4.8h, v11.8h",
  3405  			n: &nodeImpl{
  3406  				instruction:       SMAX,
  3407  				dstReg:            RegV30,
  3408  				srcReg:            RegV11,
  3409  				srcReg2:           RegV4,
  3410  				vectorArrangement: VectorArrangement8H,
  3411  			},
  3412  			exp: []byte{0x9e, 0x64, 0x6b, 0x4e},
  3413  		},
  3414  		{
  3415  			name: "smin v30.16b, v4.16b, v11.16b",
  3416  			n: &nodeImpl{
  3417  				instruction:       SMIN,
  3418  				dstReg:            RegV30,
  3419  				srcReg:            RegV11,
  3420  				srcReg2:           RegV4,
  3421  				vectorArrangement: VectorArrangement16B,
  3422  			},
  3423  			exp: []byte{0x9e, 0x6c, 0x2b, 0x4e},
  3424  		},
  3425  		{
  3426  			name: "smin v30.4s, v4.4s, v11.4s",
  3427  			n: &nodeImpl{
  3428  				instruction:       SMIN,
  3429  				dstReg:            RegV30,
  3430  				srcReg:            RegV11,
  3431  				srcReg2:           RegV4,
  3432  				vectorArrangement: VectorArrangement4S,
  3433  			},
  3434  			exp: []byte{0x9e, 0x6c, 0xab, 0x4e},
  3435  		},
  3436  		{
  3437  			name: "umin v30.16b, v4.16b, v11.16b",
  3438  			n: &nodeImpl{
  3439  				instruction:       UMIN,
  3440  				dstReg:            RegV30,
  3441  				srcReg:            RegV11,
  3442  				srcReg2:           RegV4,
  3443  				vectorArrangement: VectorArrangement16B,
  3444  			},
  3445  			exp: []byte{0x9e, 0x6c, 0x2b, 0x6e},
  3446  		},
  3447  		{
  3448  			name: "umin v30.4s, v4.4s, v11.4s",
  3449  			n: &nodeImpl{
  3450  				instruction:       UMIN,
  3451  				dstReg:            RegV30,
  3452  				srcReg:            RegV11,
  3453  				srcReg2:           RegV4,
  3454  				vectorArrangement: VectorArrangement4S,
  3455  			},
  3456  			exp: []byte{0x9e, 0x6c, 0xab, 0x6e},
  3457  		},
  3458  		{
  3459  			name: "umax v30.4s, v4.4s, v11.4s",
  3460  			n: &nodeImpl{
  3461  				instruction:       UMAX,
  3462  				dstReg:            RegV30,
  3463  				srcReg:            RegV11,
  3464  				srcReg2:           RegV4,
  3465  				vectorArrangement: VectorArrangement4S,
  3466  			},
  3467  			exp: []byte{0x9e, 0x64, 0xab, 0x6e},
  3468  		},
  3469  		{
  3470  			name: "umax v30.8h, v4.8h, v11.8h",
  3471  			n: &nodeImpl{
  3472  				instruction:       UMAX,
  3473  				dstReg:            RegV30,
  3474  				srcReg:            RegV11,
  3475  				srcReg2:           RegV4,
  3476  				vectorArrangement: VectorArrangement8H,
  3477  			},
  3478  			exp: []byte{0x9e, 0x64, 0x6b, 0x6e},
  3479  		},
  3480  		{
  3481  			name: "umax v30.8h, v4.8h, v11.8h",
  3482  			n: &nodeImpl{
  3483  				instruction:       URHADD,
  3484  				dstReg:            RegV30,
  3485  				srcReg:            RegV11,
  3486  				srcReg2:           RegV4,
  3487  				vectorArrangement: VectorArrangement8H,
  3488  			},
  3489  			exp: []byte{0x9e, 0x14, 0x6b, 0x6e},
  3490  		},
  3491  		{
  3492  			name: "umax v30.16b, v4.16b, v11.16b",
  3493  			n: &nodeImpl{
  3494  				instruction:       URHADD,
  3495  				dstReg:            RegV30,
  3496  				srcReg:            RegV11,
  3497  				srcReg2:           RegV4,
  3498  				vectorArrangement: VectorArrangement16B,
  3499  			},
  3500  			exp: []byte{0x9e, 0x14, 0x2b, 0x6e},
  3501  		},
  3502  		{
  3503  			name: "sqsub v30.16b, v4.16b, v11.16b",
  3504  			n: &nodeImpl{
  3505  				instruction:       VSQSUB,
  3506  				dstReg:            RegV30,
  3507  				srcReg:            RegV11,
  3508  				srcReg2:           RegV4,
  3509  				vectorArrangement: VectorArrangement16B,
  3510  			},
  3511  			exp: []byte{0x9e, 0x2c, 0x2b, 0x4e},
  3512  		},
  3513  		{
  3514  			name: "sqsub v308hb, v4.8h, v11.8h",
  3515  			n: &nodeImpl{
  3516  				instruction:       VSQSUB,
  3517  				dstReg:            RegV30,
  3518  				srcReg:            RegV11,
  3519  				srcReg2:           RegV4,
  3520  				vectorArrangement: VectorArrangement8H,
  3521  			},
  3522  			exp: []byte{0x9e, 0x2c, 0x6b, 0x4e},
  3523  		},
  3524  		{
  3525  			name: "uqsub v30.16b, v4.16b, v11.16b",
  3526  			n: &nodeImpl{
  3527  				instruction:       VUQSUB,
  3528  				dstReg:            RegV30,
  3529  				srcReg:            RegV11,
  3530  				srcReg2:           RegV4,
  3531  				vectorArrangement: VectorArrangement16B,
  3532  			},
  3533  			exp: []byte{0x9e, 0x2c, 0x2b, 0x6e},
  3534  		},
  3535  		{
  3536  			name: "uqsub v308hb, v4.8h, v11.8h",
  3537  			n: &nodeImpl{
  3538  				instruction:       VUQSUB,
  3539  				dstReg:            RegV30,
  3540  				srcReg:            RegV11,
  3541  				srcReg2:           RegV4,
  3542  				vectorArrangement: VectorArrangement8H,
  3543  			},
  3544  			exp: []byte{0x9e, 0x2c, 0x6b, 0x6e},
  3545  		},
  3546  		{
  3547  			name: "umlal v0.2d, v6.2s, v2.2s",
  3548  			n: &nodeImpl{
  3549  				instruction:       VUMLAL,
  3550  				dstReg:            RegV0,
  3551  				srcReg:            RegV2,
  3552  				srcReg2:           RegV6,
  3553  				vectorArrangement: VectorArrangement2S,
  3554  			},
  3555  			exp: []byte{0xc0, 0x80, 0xa2, 0x2e},
  3556  		},
  3557  		{
  3558  			name: "umlal v0.4s, v6.4h, v2.4h",
  3559  			n: &nodeImpl{
  3560  				instruction:       VUMLAL,
  3561  				dstReg:            RegV0,
  3562  				srcReg:            RegV2,
  3563  				srcReg2:           RegV6,
  3564  				vectorArrangement: VectorArrangement4H,
  3565  			},
  3566  			exp: []byte{0xc0, 0x80, 0x62, 0x2e},
  3567  		},
  3568  		{
  3569  			name: "umlal v0.8h, v6.8b, v2.8b",
  3570  			n: &nodeImpl{
  3571  				instruction:       VUMLAL,
  3572  				dstReg:            RegV0,
  3573  				srcReg:            RegV2,
  3574  				srcReg2:           RegV6,
  3575  				vectorArrangement: VectorArrangement8B,
  3576  			},
  3577  			exp: []byte{0xc0, 0x80, 0x22, 0x2e},
  3578  		},
  3579  		{
  3580  			name: "bit v30.16b, v4.16b, v11.16b",
  3581  			n: &nodeImpl{
  3582  				instruction:       VBIT,
  3583  				dstReg:            RegV30,
  3584  				srcReg:            RegV11,
  3585  				srcReg2:           RegV4,
  3586  				vectorArrangement: VectorArrangement16B,
  3587  			},
  3588  			exp: []byte{0x9e, 0x1c, 0xab, 0x6e},
  3589  		},
  3590  		{
  3591  			name: "bit v30.8b, v4.8b, v11.8b",
  3592  			n: &nodeImpl{
  3593  				instruction:       VBIT,
  3594  				dstReg:            RegV30,
  3595  				srcReg:            RegV11,
  3596  				srcReg2:           RegV4,
  3597  				vectorArrangement: VectorArrangement8B,
  3598  			},
  3599  			exp: []byte{0x9e, 0x1c, 0xab, 0x2e},
  3600  		},
  3601  		{
  3602  			name: "sqrdmulh v30.8h, v4.8h, v11.8h",
  3603  			n: &nodeImpl{
  3604  				instruction:       SQRDMULH,
  3605  				dstReg:            RegV30,
  3606  				srcReg:            RegV11,
  3607  				srcReg2:           RegV4,
  3608  				vectorArrangement: VectorArrangement8H,
  3609  			},
  3610  			exp: []byte{0x9e, 0xb4, 0x6b, 0x6e},
  3611  		},
  3612  		{
  3613  			name: "sqrdmulh v30.4s, v4.4s, v11.4s",
  3614  			n: &nodeImpl{
  3615  				instruction:       SQRDMULH,
  3616  				dstReg:            RegV30,
  3617  				srcReg:            RegV11,
  3618  				srcReg2:           RegV4,
  3619  				vectorArrangement: VectorArrangement4S,
  3620  			},
  3621  			exp: []byte{0x9e, 0xb4, 0xab, 0x6e},
  3622  		},
  3623  		{
  3624  			name: "smull v30.8h, v4.8b, v11.8b",
  3625  			n: &nodeImpl{
  3626  				instruction:       SMULL,
  3627  				dstReg:            RegV30,
  3628  				srcReg:            RegV11,
  3629  				srcReg2:           RegV4,
  3630  				vectorArrangement: VectorArrangement8B,
  3631  			},
  3632  			exp: []byte{0x9e, 0xc0, 0x2b, 0xe},
  3633  		},
  3634  		{
  3635  			name: "smull v30.4s, v4.4h, v11.4h",
  3636  			n: &nodeImpl{
  3637  				instruction:       SMULL,
  3638  				dstReg:            RegV30,
  3639  				srcReg:            RegV11,
  3640  				srcReg2:           RegV4,
  3641  				vectorArrangement: VectorArrangement4H,
  3642  			},
  3643  			exp: []byte{0x9e, 0xc0, 0x6b, 0xe},
  3644  		},
  3645  		{
  3646  			name: "smull v30.2d, v4.2s, v11.2s",
  3647  			n: &nodeImpl{
  3648  				instruction:       SMULL,
  3649  				dstReg:            RegV30,
  3650  				srcReg:            RegV11,
  3651  				srcReg2:           RegV4,
  3652  				vectorArrangement: VectorArrangement2S,
  3653  			},
  3654  			exp: []byte{0x9e, 0xc0, 0xab, 0xe},
  3655  		},
  3656  		{
  3657  			name: "smull2 v30.8h, v4.16b, v11.16b",
  3658  			n: &nodeImpl{
  3659  				instruction:       SMULL2,
  3660  				dstReg:            RegV30,
  3661  				srcReg:            RegV11,
  3662  				srcReg2:           RegV4,
  3663  				vectorArrangement: VectorArrangement16B,
  3664  			},
  3665  			exp: []byte{0x9e, 0xc0, 0x2b, 0x4e},
  3666  		},
  3667  		{
  3668  			name: "smull2 v30.4s, v4.8h, v11.8h",
  3669  			n: &nodeImpl{
  3670  				instruction:       SMULL2,
  3671  				dstReg:            RegV30,
  3672  				srcReg:            RegV11,
  3673  				srcReg2:           RegV4,
  3674  				vectorArrangement: VectorArrangement8H,
  3675  			},
  3676  			exp: []byte{0x9e, 0xc0, 0x6b, 0x4e},
  3677  		},
  3678  		{
  3679  			name: "smull2 v30.2d, v4.4s, v11.4s",
  3680  			n: &nodeImpl{
  3681  				instruction:       SMULL2,
  3682  				dstReg:            RegV30,
  3683  				srcReg:            RegV11,
  3684  				srcReg2:           RegV4,
  3685  				vectorArrangement: VectorArrangement4S,
  3686  			},
  3687  			exp: []byte{0x9e, 0xc0, 0xab, 0x4e},
  3688  		},
  3689  
  3690  		//////////////////////
  3691  
  3692  		{
  3693  			name: "umull v30.8h, v4.8b, v11.8b",
  3694  			n: &nodeImpl{
  3695  				instruction:       UMULL,
  3696  				dstReg:            RegV30,
  3697  				srcReg:            RegV11,
  3698  				srcReg2:           RegV4,
  3699  				vectorArrangement: VectorArrangement8B,
  3700  			},
  3701  			exp: []byte{0x9e, 0xc0, 0x2b, 0x2e},
  3702  		},
  3703  		{
  3704  			name: "umull v30.4s, v4.4h, v11.4h",
  3705  			n: &nodeImpl{
  3706  				instruction:       UMULL,
  3707  				dstReg:            RegV30,
  3708  				srcReg:            RegV11,
  3709  				srcReg2:           RegV4,
  3710  				vectorArrangement: VectorArrangement4H,
  3711  			},
  3712  			exp: []byte{0x9e, 0xc0, 0x6b, 0x2e},
  3713  		},
  3714  		{
  3715  			name: "umull v30.2d, v4.2s, v11.2s",
  3716  			n: &nodeImpl{
  3717  				instruction:       UMULL,
  3718  				dstReg:            RegV30,
  3719  				srcReg:            RegV11,
  3720  				srcReg2:           RegV4,
  3721  				vectorArrangement: VectorArrangement2S,
  3722  			},
  3723  			exp: []byte{0x9e, 0xc0, 0xab, 0x2e},
  3724  		},
  3725  		{
  3726  			name: "umull2 v30.8h, v4.16b, v11.16b",
  3727  			n: &nodeImpl{
  3728  				instruction:       UMULL2,
  3729  				dstReg:            RegV30,
  3730  				srcReg:            RegV11,
  3731  				srcReg2:           RegV4,
  3732  				vectorArrangement: VectorArrangement16B,
  3733  			},
  3734  			exp: []byte{0x9e, 0xc0, 0x2b, 0x6e},
  3735  		},
  3736  		{
  3737  			name: "umull2 v30.4s, v4.8h, v11.8h",
  3738  			n: &nodeImpl{
  3739  				instruction:       UMULL2,
  3740  				dstReg:            RegV30,
  3741  				srcReg:            RegV11,
  3742  				srcReg2:           RegV4,
  3743  				vectorArrangement: VectorArrangement8H,
  3744  			},
  3745  			exp: []byte{0x9e, 0xc0, 0x6b, 0x6e},
  3746  		},
  3747  		{
  3748  			name: "umull2 v30.2d, v4.4s, v11.4s",
  3749  			n: &nodeImpl{
  3750  				instruction:       UMULL2,
  3751  				dstReg:            RegV30,
  3752  				srcReg:            RegV11,
  3753  				srcReg2:           RegV4,
  3754  				vectorArrangement: VectorArrangement4S,
  3755  			},
  3756  			exp: []byte{0x9e, 0xc0, 0xab, 0x6e},
  3757  		},
  3758  	}
  3759  
  3760  	for _, tt := range tests {
  3761  		tc := tt
  3762  		t.Run(tc.name, func(t *testing.T) {
  3763  			code := asm.CodeSegment{}
  3764  			defer func() { require.NoError(t, code.Unmap()) }()
  3765  
  3766  			a := NewAssembler(asm.NilRegister)
  3767  			buf := code.NextCodeSection()
  3768  			err := a.encodeTwoVectorRegistersToVectorRegister(buf, tc.n)
  3769  			require.NoError(t, err)
  3770  
  3771  			actual := buf.Bytes()
  3772  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  3773  		})
  3774  	}
  3775  }
  3776  
  3777  func TestAssemblerImpl_EncodeRegisterToVectorRegister(t *testing.T) {
  3778  	tests := []struct {
  3779  		name string
  3780  		n    *nodeImpl
  3781  		exp  []byte
  3782  	}{
  3783  		{
  3784  			name: "ins v10.d[0], x10",
  3785  			n: &nodeImpl{
  3786  				instruction:       INSGEN,
  3787  				dstReg:            RegV10,
  3788  				srcReg:            RegR10,
  3789  				vectorArrangement: VectorArrangementD,
  3790  			},
  3791  			exp: []byte{0x4a, 0x1d, 0x8, 0x4e},
  3792  		},
  3793  		{
  3794  			name: "ins v10.d[1], x10",
  3795  			n: &nodeImpl{
  3796  				instruction:       INSGEN,
  3797  				dstReg:            RegV10,
  3798  				srcReg:            RegR10,
  3799  				vectorArrangement: VectorArrangementD,
  3800  				dstVectorIndex:    1,
  3801  			},
  3802  			exp: []byte{0x4a, 0x1d, 0x18, 0x4e},
  3803  		},
  3804  		{
  3805  			name: "dup v10.2d, x10",
  3806  			n: &nodeImpl{
  3807  				instruction:       DUPGEN,
  3808  				srcReg:            RegR10,
  3809  				dstReg:            RegV10,
  3810  				vectorArrangement: VectorArrangement2D,
  3811  			},
  3812  			exp: []byte{0x4a, 0xd, 0x8, 0x4e},
  3813  		},
  3814  		{
  3815  			name: "dup v1.4s, w30",
  3816  			n: &nodeImpl{
  3817  				instruction:       DUPGEN,
  3818  				srcReg:            RegR30,
  3819  				dstReg:            RegV1,
  3820  				vectorArrangement: VectorArrangement4S,
  3821  			},
  3822  			exp: []byte{0xc1, 0xf, 0x4, 0x4e},
  3823  		},
  3824  		{
  3825  			name: "dup v30.8h, w1",
  3826  			n: &nodeImpl{
  3827  				instruction:       DUPGEN,
  3828  				srcReg:            RegR1,
  3829  				dstReg:            RegV30,
  3830  				vectorArrangement: VectorArrangement8H,
  3831  			},
  3832  			exp: []byte{0x3e, 0xc, 0x2, 0x4e},
  3833  		},
  3834  		{
  3835  			name: "dup v30.16b, w1",
  3836  			n: &nodeImpl{
  3837  				instruction:       DUPGEN,
  3838  				srcReg:            RegR1,
  3839  				dstReg:            RegV30,
  3840  				vectorArrangement: VectorArrangement16B,
  3841  			},
  3842  			exp: []byte{0x3e, 0xc, 0x1, 0x4e},
  3843  		},
  3844  	}
  3845  
  3846  	for _, tt := range tests {
  3847  		tc := tt
  3848  		t.Run(tc.name, func(t *testing.T) {
  3849  			code := asm.CodeSegment{}
  3850  			defer func() { require.NoError(t, code.Unmap()) }()
  3851  
  3852  			a := NewAssembler(asm.NilRegister)
  3853  			buf := code.NextCodeSection()
  3854  			err := a.encodeRegisterToVectorRegister(buf, tc.n)
  3855  			require.NoError(t, err)
  3856  
  3857  			actual := buf.Bytes()
  3858  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  3859  		})
  3860  	}
  3861  }
  3862  
  3863  func TestAssemblerImpl_maybeFlushConstPool(t *testing.T) {
  3864  	tests := []struct {
  3865  		name string
  3866  		c    []byte
  3867  		exp  []byte
  3868  	}{
  3869  		{
  3870  			name: "1 byte consts",
  3871  			c:    []byte{1},
  3872  			exp: []byte{
  3873  				// 0x0:
  3874  				// b #0x8
  3875  				0x2, 0x0, 0x0, 0x14,
  3876  				// 0x4:
  3877  				0x1,
  3878  				0x0, 0x0, 0x0, // padding to be 4-byte aligned.
  3879  				// 0x8: <- branch dst.
  3880  			},
  3881  		},
  3882  		{
  3883  			name: "2 byte consts",
  3884  			c:    []byte{0xff, 0xfe},
  3885  			exp: []byte{
  3886  				// 0x0:
  3887  				// b #0x8
  3888  				0x2, 0x0, 0x0, 0x14,
  3889  				// 0x4:
  3890  				0xff, 0xfe,
  3891  				0x0, 0x0, // padding to be 4-byte aligned.
  3892  				// 0x8: <- branch dst.
  3893  			},
  3894  		},
  3895  		{
  3896  			name: "3 byte consts",
  3897  			c:    []byte{0xff, 0xfe, 0xa},
  3898  			exp: []byte{
  3899  				// 0x0:
  3900  				// b #0x8
  3901  				0x2, 0x0, 0x0, 0x14,
  3902  				// 0x4:
  3903  				0xff, 0xfe, 0xa,
  3904  				0x0, // padding to be 4-byte aligned.
  3905  				// 0x8: <- branch dst.
  3906  			},
  3907  		},
  3908  		{
  3909  			name: "4 byte consts",
  3910  			c:    []byte{1, 2, 3, 4},
  3911  			exp: []byte{
  3912  				// 0x0:
  3913  				// b #0x8
  3914  				0x2, 0x0, 0x0, 0x14,
  3915  				// 0x4:
  3916  				0x1, 0x2, 0x3, 0x4,
  3917  				// 0x8: <- branch dst.
  3918  			},
  3919  		},
  3920  		{
  3921  			name: "12 byte consts",
  3922  			c:    []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
  3923  			exp: []byte{
  3924  				// 0x0:
  3925  				// b #0x10
  3926  				0x4, 0x0, 0x0, 0x14,
  3927  				// 0x4:
  3928  				1, 2, 3, 4,
  3929  				5, 6, 7, 8,
  3930  				9, 10, 11, 12,
  3931  				// 0x10: <- branch dst.
  3932  			},
  3933  		},
  3934  		{
  3935  			name: "16 byte consts",
  3936  			c:    []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
  3937  			exp: []byte{
  3938  				// 0x0:
  3939  				// b #0x14
  3940  				0x5, 0x0, 0x0, 0x14,
  3941  				// 0x04:
  3942  				0x1, 0x2, 0x3, 0x4,
  3943  				0x5, 0x6, 0x7, 0x8,
  3944  				0x9, 0xa, 0xb, 0xc,
  3945  				0xd, 0xe, 0xf, 0x10,
  3946  				// 0x14: <- branch dst.
  3947  			},
  3948  		},
  3949  	}
  3950  
  3951  	for _, tc := range tests {
  3952  		tc := tc
  3953  		t.Run(tc.name, func(t *testing.T) {
  3954  			code := asm.CodeSegment{}
  3955  			defer func() { require.NoError(t, code.Unmap()) }()
  3956  
  3957  			a := NewAssembler(asm.NilRegister)
  3958  			sc := asm.NewStaticConst(tc.c)
  3959  			a.pool.AddConst(sc, 0)
  3960  
  3961  			var called bool
  3962  			sc.AddOffsetFinalizedCallback(func(uint64) {
  3963  				called = true
  3964  			})
  3965  
  3966  			a.MaxDisplacementForConstantPool = 0
  3967  			buf := code.NextCodeSection()
  3968  			a.maybeFlushConstPool(buf, false)
  3969  			require.True(t, called)
  3970  
  3971  			actual := buf.Bytes()
  3972  			require.Equal(t, tc.exp, actual)
  3973  		})
  3974  	}
  3975  }
  3976  
  3977  func TestAssemblerImpl_EncodeStaticConstToVectorRegister(t *testing.T) {
  3978  	tests := []struct {
  3979  		name string
  3980  		n    *nodeImpl
  3981  		exp  []byte
  3982  	}{
  3983  		{
  3984  			name: "ldr q8, #8",
  3985  			n: &nodeImpl{
  3986  				instruction:       VMOV,
  3987  				dstReg:            RegV8,
  3988  				vectorArrangement: VectorArrangementQ,
  3989  				staticConst:       asm.NewStaticConst([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}),
  3990  			},
  3991  			exp: []byte{
  3992  				// 0x0: ldr q8, #8
  3993  				0x48, 0x0, 0x0, 0x9c,
  3994  				// Emitted after the end of function.
  3995  				// 0x4: br #4  (See AssemblerImpl.maybeFlushConstPool)
  3996  				0x0, 0x0, 0x0, 0x14,
  3997  				// 0x8: consts.
  3998  				0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
  3999  				0x10,
  4000  			},
  4001  		},
  4002  		{
  4003  			name: "ldr d30, #8",
  4004  			n: &nodeImpl{
  4005  				instruction:       VMOV,
  4006  				dstReg:            RegV30,
  4007  				vectorArrangement: VectorArrangementD,
  4008  				staticConst:       asm.NewStaticConst([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
  4009  			},
  4010  			exp: []byte{
  4011  				// 0x0: ldr d30, #8
  4012  				0x5e, 0x0, 0x0, 0x5c,
  4013  				// Emitted after the end of function.
  4014  				// 0x4: br #4  (See AssemblerImpl.maybeFlushConstPool)
  4015  				0x0, 0x0, 0x0, 0x14,
  4016  				// 0x8: consts.
  4017  				0x1, 0x2, 0x3, 0x4,
  4018  				0x5, 0x6, 0x7, 0x8,
  4019  			},
  4020  		},
  4021  		{
  4022  			name: "ldr s8, #8",
  4023  			n: &nodeImpl{
  4024  				instruction:       VMOV,
  4025  				dstReg:            RegV8,
  4026  				vectorArrangement: VectorArrangementS,
  4027  				staticConst:       asm.NewStaticConst([]byte{1, 2, 3, 4}),
  4028  			},
  4029  			exp: []byte{
  4030  				// 0x0: ldr s8, #8
  4031  				0x48, 0x0, 0x0, 0x1c,
  4032  				// Emitted after the end of function.
  4033  				// 0x4: br #4  (See AssemblerImpl.maybeFlushConstPool)
  4034  				0x0, 0x0, 0x0, 0x14,
  4035  				// 0x8: consts.
  4036  				0x1, 0x2, 0x3, 0x4,
  4037  			},
  4038  		},
  4039  	}
  4040  
  4041  	for _, tc := range tests {
  4042  		tc := tc
  4043  		t.Run(tc.name, func(t *testing.T) {
  4044  			code := asm.CodeSegment{}
  4045  			defer func() { require.NoError(t, code.Unmap()) }()
  4046  
  4047  			a := NewAssembler(asm.NilRegister)
  4048  			buf := code.NextCodeSection()
  4049  			err := a.encodeStaticConstToVectorRegister(buf, tc.n)
  4050  			require.NoError(t, err)
  4051  			a.maybeFlushConstPool(buf, true)
  4052  
  4053  			err = a.Assemble(buf)
  4054  			require.NoError(t, err)
  4055  
  4056  			actual := buf.Bytes()
  4057  			require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
  4058  		})
  4059  	}
  4060  }
  4061  
  4062  func TestAssemblerImpl_encodeADR_staticConst(t *testing.T) {
  4063  	const beforeADRByteNum uint64 = 2
  4064  
  4065  	tests := []struct {
  4066  		name                   string
  4067  		expADRInstructionBytes []byte
  4068  		offsetOfConstInBinary  uint64
  4069  		reg                    asm.Register
  4070  	}{
  4071  		{
  4072  			// #8 = offsetOfConstInBinary - beforeADRByteNum.
  4073  			name:                   "adr x12, #8",
  4074  			reg:                    RegR12,
  4075  			offsetOfConstInBinary:  10,
  4076  			expADRInstructionBytes: []byte{0x4c, 0x0, 0x0, 0x10},
  4077  		},
  4078  		{
  4079  			// #0x7fffd = offsetOfConstInBinary - beforeADRByteNum.
  4080  			name:                   "adr x12, #0x7fffd",
  4081  			reg:                    RegR12,
  4082  			offsetOfConstInBinary:  0x7ffff,
  4083  			expADRInstructionBytes: []byte{0xec, 0xff, 0x3f, 0x30},
  4084  		},
  4085  	}
  4086  
  4087  	for _, tc := range tests {
  4088  		tc := tc
  4089  		t.Run(tc.name, func(t *testing.T) {
  4090  			code := asm.CodeSegment{}
  4091  			defer func() { require.NoError(t, code.Unmap()) }()
  4092  
  4093  			sc := asm.NewStaticConst([]byte{1, 2, 3, 4}) // Arbitrary data is fine.
  4094  
  4095  			a := NewAssembler(asm.NilRegister)
  4096  
  4097  			buf := code.NextCodeSection()
  4098  			buf.AppendBytes(make([]byte, beforeADRByteNum))
  4099  
  4100  			err := a.encodeADR(buf, &nodeImpl{instruction: ADR, dstReg: tc.reg, staticConst: sc})
  4101  			require.NoError(t, err)
  4102  			require.Equal(t, 1, len(a.pool.Consts))
  4103  			require.Equal(t, sc, a.pool.Consts[0])
  4104  			require.Equal(t, beforeADRByteNum, a.pool.FirstUseOffsetInBinary)
  4105  
  4106  			// Finalize the ADR instruction bytes.
  4107  			sc.SetOffsetInBinary(tc.offsetOfConstInBinary)
  4108  
  4109  			actual := buf.Bytes()[beforeADRByteNum : beforeADRByteNum+4]
  4110  			require.Equal(t, tc.expADRInstructionBytes, actual, hex.EncodeToString(actual))
  4111  		})
  4112  	}
  4113  }