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