github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/asm/arm64/impl_1_test.go (about) 1 package arm64 2 3 import ( 4 "encoding/hex" 5 "testing" 6 7 "github.com/bananabytelabs/wazero/internal/asm" 8 "github.com/bananabytelabs/wazero/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 }