Repository: tetratelabs/wazero
Pull request #641 (2022-06-20 01:46:19)

arm64: implement SIMD Integer arithmetics
This implements SIMD integer arithmetic instructions for arm64 backend.
Notably, now the engine passes  `simd_**_arith`, `simd_**_arith2`, and
`simd_**_sat_arith` spectests.


part of #484 


Patch:
diff --git a/internal/asm/amd64/impl.go b/internal/asm/amd64/impl.go
index bff8f6dd..42b82268 100644
--- a/internal/asm/amd64/impl.go
+++ b/internal/asm/amd64/impl.go
@@ -798,7 +798,7 @@ func (a *AssemblerImpl) EncodeNoneToRegister(n *NodeImpl) (err error) {
 	modRM := 0b11_000_000 | // Specifying that opeand is register.
 		regBits
 	if n.Instruction == JMP {
-		// JMP's Opcode is defined as "FF /4" meaning that we have to have "4"
+		// JMP's opcode is defined as "FF /4" meaning that we have to have "4"
 		// in 4-6th bits in the ModRM byte. https://www.felixcloutier.com/x86/jmp
 		modRM |= 0b00_100_000
 	} else if n.Instruction == NEGQ {
diff --git a/internal/asm/arm64/assembler.go b/internal/asm/arm64/assembler.go
index f6dd8d7b..5c1beba6 100644
--- a/internal/asm/arm64/assembler.go
+++ b/internal/asm/arm64/assembler.go
@@ -48,21 +48,6 @@ type Assembler interface {
 		srcReg, dstReg asm.Register,
 	)
 
-	// CompileSIMDByteToSIMDByte adds an instruction where source and destination operand is the SIMD register
-	// specified as `srcReg.B8` and `dstReg.B8` where `.B8` part of register is called "arrangement".
-	// See https://stackoverflow.com/questions/57294672/what-is-arrangement-specifier-16b-8b-in-arm-assembly-language-instructions
-	//
-	// TODO: implement this in CompileVectorRegisterToVectorRegister.
-	CompileSIMDByteToSIMDByte(instruction asm.Instruction, srcReg, dstReg asm.Register)
-
-	// CompileTwoSIMDBytesToSIMDByteRegister adds an instruction where source operand is two SIMD registers specified as `srcReg1.B8`,
-	// and `srcReg2.B8` and the destination is the one SIMD register `dstReg.B8`.
-	CompileTwoSIMDBytesToSIMDByteRegister(instruction asm.Instruction, srcReg1, srcReg2, dstReg asm.Register)
-
-	// CompileSIMDByteToRegister adds an instruction where source operand is the SIMD register specified as `srcReg.B8`,
-	// and the destination is the register `dstReg`.
-	CompileSIMDByteToRegister(instruction asm.Instruction, srcReg, dstReg asm.Register)
-
 	// CompileConditionalRegisterSet adds an instruction to set 1 on dstReg if the condition satisfies,
 	// otherwise set 0.
 	CompileConditionalRegisterSet(cond asm.ConditionalRegisterState, dstReg asm.Register)
diff --git a/internal/asm/arm64/consts.go b/internal/asm/arm64/consts.go
index f95de788..d3b234d1 100644
--- a/internal/asm/arm64/consts.go
+++ b/internal/asm/arm64/consts.go
@@ -535,7 +535,7 @@ const (
 	FCVTSD
 	// FCVTZSD is the FCVTZS instruction, for double precision. https://developer.arm.com/documentation/dui0802/a/A64-Floating-point-Instructions/FCVTZS--scalar--integer-
 	FCVTZSD
-	// FCVTZSD is the FCVTZS instruction, for double precision in 64-bit mode. https://developer.arm.com/documentation/dui0802/a/A64-Floating-point-Instructions/FCVTZS--scalar--integer-
+	// FCVTZSDW is the FCVTZS instruction, for double precision in 64-bit mode. https://developer.arm.com/documentation/dui0802/a/A64-Floating-point-Instructions/FCVTZS--scalar--integer-
 	FCVTZSDW
 	// FCVTZSS is the FCVTZS instruction, for single precision. https://developer.arm.com/documentation/dui0802/a/A64-Floating-point-Instructions/FCVTZS--scalar--integer-
 	FCVTZSS
@@ -702,8 +702,8 @@ const (
 	INSGEN
 	// INSELEM is the INS(element) instruction https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/INS--element---Insert-vector-element-from-another-vector-element-?lang=en
 	INSELEM
-	// VUADDLV is the UADDLV(vector) instruction. https://developer.arm.com/documentation/dui0802/a/A64-Advanced-SIMD-Vector-Instructions/UADDLV--vector-
-	VUADDLV
+	// UADDLV is the UADDLV(vector) instruction. https://developer.arm.com/documentation/dui0802/a/A64-Advanced-SIMD-Vector-Instructions/UADDLV--vector-
+	UADDLV
 	// VADD is the ADD(vector) instruction. https://developer.arm.com/documentation/dui0802/a/A64-Advanced-SIMD-Vector-Instructions/ADD--vector-
 	VADD
 	// VFADDS is the FADD(vector) instruction, for single precision. https://developer.arm.com/documentation/dui0802/a/A64-Advanced-SIMD-Vector-Instructions/FADD--vector-
@@ -816,6 +816,46 @@ const (
 	// VFRINTN is the FRINTN(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FRINTN--vector---Floating-point-Round-to-Integral--to-nearest-with-ties-to-even--vector--?lang=en
 	// Note: prefixed by V to distinguish from the non-vector variant.
 	VFRINTN
+	// VMUL is the MUL(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/MUL--vector---Multiply--vector--?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VMUL
+	// VNEG is the NEG(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/NEG--vector---Negate--vector--?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VNEG
+	// VABS is the ABS(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ABS--Absolute-value--vector--?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VABS
+	// VSQADD is the SQADD(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SQADD--Signed-saturating-Add-?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VSQADD
+	// VUQADD is the UQADD(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UQADD--Unsigned-saturating-Add-?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VUQADD
+	// VSQSUB is the SQSUB(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SQSUB--Signed-saturating-Subtract-?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VSQSUB
+	// VUQSUB is the UQSUB(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UQSUB--Unsigned-saturating-Subtract-?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VUQSUB
+	// SMIN is the SMIN instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SMIN--Signed-Minimum--vector--?lang=en
+	SMIN
+	// SMAX is the SMAX instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SMAX--Signed-Maximum--vector--?lang=en
+	SMAX
+	// UMIN is the UMIN instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMIN--Unsigned-Minimum--vector--?lang=en
+	UMIN
+	// UMAX is the UMAX instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMAX--Unsigned-Maximum--vector--?lang=en
+	UMAX
+	// URHADD is the URHADD instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/URHADD--Unsigned-Rounding-Halving-Add-?lang=en
+	URHADD
+	// REV64 is the REV64 instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/REV64--Reverse-elements-in-64-bit-doublewords--vector--?lang=en
+	REV64
+	// XTN is the XTN instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/XTN--XTN2--Extract-Narrow-?lang=en
+	XTN
+	// VUMLAL is the UMLAL(vector) instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMLAL--UMLAL2--vector---Unsigned-Multiply-Add-Long--vector--?lang=en
+	// Note: prefixed by V to distinguish from the non-vector variant.
+	VUMLAL
+	// SHLL is the SHLL instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SHLL--SHLL2--Shift-Left-Long--by-element-size--?lang=en
+	SHLL
 
 	// instructionEnd is always placed at the bottom of this iota definition to be used in the test.
 	instructionEnd
@@ -1146,8 +1186,8 @@ func InstructionName(i asm.Instruction) string {
 		return "VBIT"
 	case VCNT:
 		return "VCNT"
-	case VUADDLV:
-		return "VUADDLV"
+	case UADDLV:
+		return "UADDLV"
 	case VMOV:
 		return "VMOV"
 	case INSELEM:
@@ -1254,6 +1294,38 @@ func InstructionName(i asm.Instruction) string {
 		return "VFRINTZ"
 	case VFRINTN:
 		return "VFRINTN"
+	case VMUL:
+		return "VMUL"
+	case VNEG:
+		return "VNEG"
+	case VABS:
+		return "VABS"
+	case VSQADD:
+		return "VSQADD"
+	case VUQADD:
+		return "VUQADD"
+	case SMIN:
+		return "SMIN"
+	case SMAX:
+		return "SMAX"
+	case UMIN:
+		return "UMIN"
+	case UMAX:
+		return "UMAX"
+	case URHADD:
+		return "URHADD"
+	case VSQSUB:
+		return "VSQSUB"
+	case VUQSUB:
+		return "VUQSUB"
+	case REV64:
+		return "REV64"
+	case XTN:
+		return "XTN"
+	case VUMLAL:
+		return "VUMLAL"
+	case SHLL:
+		return "SHLL"
 	}
 	panic(fmt.Errorf("unknown instruction %d", i))
 }
diff --git a/internal/asm/arm64/impl.go b/internal/asm/arm64/impl.go
index bac696b4..bf74ecf7 100644
--- a/internal/asm/arm64/impl.go
+++ b/internal/asm/arm64/impl.go
@@ -102,12 +102,6 @@ func (n *NodeImpl) String() (ret string) {
 		}
 	case OperandTypesConstToRegister:
 		ret = fmt.Sprintf("%s 0x%x, %s", instName, n.SrcConst, RegisterName(n.DstReg))
-	case OperandTypesSIMDByteToSIMDByte:
-		ret = fmt.Sprintf("%s %s.B8, %s.B8", instName, RegisterName(n.SrcReg), RegisterName(n.DstReg))
-	case OperandTypesSIMDByteToRegister:
-		ret = fmt.Sprintf("%s %s.B8, %s", instName, RegisterName(n.SrcReg), RegisterName(n.DstReg))
-	case OperandTypesTwoSIMDBytesToSIMDByteRegister:
-		ret = fmt.Sprintf("%s (%s.B8, %s.B8), %s.B8", instName, RegisterName(n.SrcReg), RegisterName(n.SrcReg2), RegisterName(n.DstReg))
 	case OperandTypesRegisterToVectorRegister:
 		ret = fmt.Sprintf("%s %s, %s.%s[%d]", instName, RegisterName(n.SrcReg), RegisterName(n.DstReg), n.VectorArrangement, n.DstVectorIndex)
 	case OperandTypesVectorRegisterToRegister:
@@ -196,9 +190,6 @@ var (
 	OperandTypesRegisterToMemory                   = OperandTypes{OperandTypeRegister, OperandTypeMemory}
 	OperandTypesMemoryToRegister                   = OperandTypes{OperandTypeMemory, OperandTypeRegister}
 	OperandTypesConstToRegister                    = OperandTypes{OperandTypeConst, OperandTypeRegister}
-	OperandTypesSIMDByteToSIMDByte                 = OperandTypes{OperandTypeSIMDByte, OperandTypeSIMDByte}
-	OperandTypesSIMDByteToRegister                 = OperandTypes{OperandTypeSIMDByte, OperandTypeRegister}
-	OperandTypesTwoSIMDBytesToSIMDByteRegister     = OperandTypes{OperandTypeTwoSIMDBytes, OperandTypeSIMDByte}
 	OperandTypesRegisterToVectorRegister           = OperandTypes{OperandTypeRegister, OperandTypeVectorRegister}
 	OperandTypesVectorRegisterToRegister           = OperandTypes{OperandTypeVectorRegister, OperandTypeRegister}
 	OperandTypesMemoryToVectorRegister             = OperandTypes{OperandTypeMemory, OperandTypeVectorRegister}
@@ -420,12 +411,6 @@ func (a *AssemblerImpl) EncodeNode(n *NodeImpl) (err error) {
 		err = a.EncodeMemoryToRegister(n)
 	case OperandTypesConstToRegister:
 		err = a.EncodeConstToRegister(n)
-	case OperandTypesSIMDByteToSIMDByte:
-		err = a.EncodeSIMDByteToSIMDByte(n)
-	case OperandTypesSIMDByteToRegister:
-		err = a.EncodeSIMDByteToRegister(n)
-	case OperandTypesTwoSIMDBytesToSIMDByteRegister:
-		err = a.EncodeTwoSIMDBytesToSIMDByteRegister(n)
 	case OperandTypesRegisterToVectorRegister:
 		err = a.EncodeRegisterToVectorRegister(n)
 	case OperandTypesVectorRegisterToRegister:
@@ -599,31 +584,6 @@ func (a *AssemblerImpl) CompileLeftShiftedRegisterToRegister(
 	n.DstReg = dstReg
 }
 
-// CompileSIMDByteToSIMDByte implements Assembler.CompileSIMDByteToSIMDByte
-func (a *AssemblerImpl) CompileSIMDByteToSIMDByte(instruction asm.Instruction, srcReg, dstReg asm.Register) {
-	n := a.newNode(instruction, OperandTypesSIMDByteToSIMDByte)
-	n.SrcReg = srcReg
-	n.DstReg = dstReg
-}
-
-// CompileTwoSIMDBytesToSIMDByteRegister implements Assembler.CompileTwoSIMDBytesToSIMDByteRegister
-func (a *AssemblerImpl) CompileTwoSIMDBytesToSIMDByteRegister(
-	instruction asm.Instruction,
-	srcReg1, srcReg2, dstReg asm.Register,
-) {
-	n := a.newNode(instruction, OperandTypesTwoSIMDBytesToSIMDByteRegister)
-	n.SrcReg = srcReg1
-	n.SrcReg2 = srcReg2
-	n.DstReg = dstReg
-}
-
-// CompileSIMDByteToRegister implements Assembler.CompileSIMDByteToRegister
-func (a *AssemblerImpl) CompileSIMDByteToRegister(instruction asm.Instruction, srcReg, dstReg asm.Register) {
-	n := a.newNode(instruction, OperandTypesSIMDByteToRegister)
-	n.SrcReg = srcReg
-	n.DstReg = dstReg
-}
-
 // CompileConditionalRegisterSet implements Assembler.CompileConditionalRegisterSet
 func (a *AssemblerImpl) CompileConditionalRegisterSet(cond asm.ConditionalRegisterState, dstReg asm.Register) {
 	n := a.newNode(CSET, OperandTypesRegisterToRegister)
@@ -1858,7 +1818,7 @@ func (a *AssemblerImpl) EncodeRegisterToMemory(n *NodeImpl) (err error) {
 		return err
 	}
 
-	const opcode = 0x00 // Opcode for store instructions.
+	const opcode = 0x00 // opcode for store instructions.
 	if n.DstReg2 != asm.NilRegister {
 		offsetRegBits, err := intRegisterBits(n.DstReg2)
 		if err != nil {
@@ -1947,9 +1907,9 @@ func (a *AssemblerImpl) EncodeMemoryToRegister(n *NodeImpl) (err error) {
 		return err
 	}
 
-	var opcode byte = 0b01 // Opcode for load instructions.
+	var opcode byte = 0b01 // opcode for load instructions.
 	if n.Instruction == MOVW || n.Instruction == MOVH || n.Instruction == MOVB {
-		// Sign-extend load (without "U" suffix except 64-bit MOVD) needs different opcode.
+		// Sign-extend load (without "u" suffix except 64-bit MOVD) needs different opcode.
 		opcode = 0b10
 	}
 	if n.SrcReg2 != asm.NilRegister {
@@ -2584,92 +2544,6 @@ func setBitPos(x uint64) (ret uint32) {
 	return
 }
 
-// Exported for inter-op testing with golang-asm.
-// TODO: unexport after golang-asm complete removal.
-func (a *AssemblerImpl) EncodeSIMDByteToSIMDByte(n *NodeImpl) (err error) {
-	if n.Instruction != VCNT {
-		return errorEncodingUnsupported(n)
-	}
-
-	srcRegBits, err := vectorRegisterBits(n.SrcReg)
-	if err != nil {
-		return err
-	}
-
-	dstRegBits, err := vectorRegisterBits(n.DstReg)
-	if err != nil {
-		return err
-	}
-
-	// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/CNT--Population-Count-per-byte-
-	a.Buf.Write([]byte{
-		(srcRegBits << 5) | dstRegBits,
-		0b010110_00 | srcRegBits>>3,
-		0b00_100000,
-		0b1110,
-	})
-	return
-}
-
-// Exported for inter-op testing with golang-asm.
-// TODO: unexport after golang-asm complete removal.
-func (a *AssemblerImpl) EncodeSIMDByteToRegister(n *NodeImpl) (err error) {
-	if n.Instruction != VUADDLV {
-		return errorEncodingUnsupported(n)
-	}
-
-	srcRegBits, err := vectorRegisterBits(n.SrcReg)
-	if err != nil {
-		return err
-	}
-
-	dstRegBits, err := vectorRegisterBits(n.DstReg)
-	if err != nil {
-		return err
-	}
-
-	// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/UADDLV--Unsigned-sum-Long-across-Vector-
-	a.Buf.Write([]byte{
-		(srcRegBits << 5) | dstRegBits,
-		0b001110_00 | srcRegBits>>3,
-		0b00_110000,
-		0b101110,
-	})
-	return
-}
-
-// Exported for inter-op testing with golang-asm.
-// TODO: unexport after golang-asm complete removal.
-func (a *AssemblerImpl) EncodeTwoSIMDBytesToSIMDByteRegister(n *NodeImpl) (err error) {
-	if n.Instruction != VBIT {
-		return errorEncodingUnsupported(n)
-	}
-
-	src1RegBits, err := vectorRegisterBits(n.SrcReg)
-	if err != nil {
-		return err
-	}
-
-	src2RegBits, err := vectorRegisterBits(n.SrcReg2)
-	if err != nil {
-		return err
-	}
-
-	dstRegBits, err := vectorRegisterBits(n.DstReg)
-	if err != nil {
-		return err
-	}
-
-	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/BIT--Bitwise-Insert-if-True-?lang=en
-	a.Buf.Write([]byte{
-		(src2RegBits << 5) | dstRegBits,
-		0b000111_00 | src2RegBits>>3,
-		0b101_00000 | src1RegBits,
-		0b00101110,
-	})
-	return
-}
-
 func checkArrangementIndexPair(arr VectorArrangement, index VectorIndex) (err error) {
 	if arr == VectorArrangementNone {
 		return nil
@@ -2896,7 +2770,7 @@ func (a *AssemblerImpl) EncodeStaticConstToVectorRegister(n *NodeImpl) (err erro
 	return
 }
 
-// advancedSIMDAcrossLanes holds information to encode instructions as "Advanced SIMD two-register miscellaneous" in
+// advancedSIMDTwoRegisterMisc holds information to encode instructions as "Advanced SIMD two-register miscellaneous" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDTwoRegisterMisc = map[asm.Instruction]struct {
 	U, opcode byte
@@ -2953,99 +2827,134 @@ var advancedSIMDTwoRegisterMisc = map[asm.Instruction]struct {
 		VectorArrangement4S: {size: 0b10, q: 0b1},
 		VectorArrangement2S: {size: 0b10, q: 0b0},
 	}},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/CNT--Population-Count-per-byte-?lang=en
+	VCNT: {U: 0b0, opcode: 0b00101, qAndSize: map[VectorArrangement]qAndSize{
+		VectorArrangement8B:  {size: 0b00, q: 0b0},
+		VectorArrangement16B: {size: 0b00, q: 0b1},
+	}},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/NEG--vector---Negate--vector--?lang=en
+	VNEG: {U: 0b1, opcode: 0b01011, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ABS--Absolute-value--vector--?lang=en
+	VABS: {U: 0b0, opcode: 0b01011, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/REV64--Reverse-elements-in-64-bit-doublewords--vector--?lang=en
+	REV64: {U: 0b0, opcode: 0b00000, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/XTN--XTN2--Extract-Narrow-?lang=en
+	XTN: {U: 0b0, opcode: 0b10010, qAndSize: map[VectorArrangement]qAndSize{
+		VectorArrangement2D: {q: 0, size: 0b10},
+		VectorArrangement4S: {q: 0, size: 0b01},
+		VectorArrangement8H: {q: 0, size: 0b00},
+	}},
+	SHLL: {U: 0b1, opcode: 0b10011, qAndSize: map[VectorArrangement]qAndSize{
+		VectorArrangement8B: {q: 0b00, size: 0b00},
+		VectorArrangement4H: {q: 0b00, size: 0b01},
+		VectorArrangement2S: {q: 0b00, size: 0b10},
+	}},
 }
 
-// advancedSIMDAcrossLanes holds information to encode instructions as "Advanced SIMD three same" in
+// advancedSIMDThreeDifferent holds information to encode instructions as "Advanced SIMD three different" in
+// https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
+var advancedSIMDThreeDifferent = map[asm.Instruction]struct {
+	u, opcode byte
+	qAndSize  map[VectorArrangement]qAndSize
+}{
+	VUMLAL: {u: 0b1, opcode: 0b1000, qAndSize: map[VectorArrangement]qAndSize{
+		VectorArrangement2S: {q: 0b0, size: 0b10},
+		VectorArrangement4H: {q: 0b0, size: 0b01},
+		VectorArrangement8B: {q: 0b0, size: 0b00},
+	}},
+}
+
+// advancedSIMDThreeSame holds information to encode instructions as "Advanced SIMD three same" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDThreeSame = map[asm.Instruction]struct {
-	U, Opcode byte
+	u, opcode byte
 	qAndSize  map[VectorArrangement]qAndSize
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/AND--vector---Bitwise-AND--vector--?lang=en
-	VAND: {U: 0b0, Opcode: 0b00011,
+	VAND: {u: 0b0, opcode: 0b00011,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement16B: {size: 0b00, q: 0b1},
 			VectorArrangement8B:  {size: 0b00, q: 0b0},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/BSL--Bitwise-Select-?lang=en
-	BSL: {U: 0b1, Opcode: 0b00011,
+	BSL: {u: 0b1, opcode: 0b00011,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement16B: {size: 0b01, q: 0b1},
 			VectorArrangement8B:  {size: 0b01, q: 0b0},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/EOR--vector---Bitwise-Exclusive-OR--vector--?lang=en
-	EOR: {U: 0b1, Opcode: 0b00011,
+	EOR: {u: 0b1, opcode: 0b00011,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement16B: {size: 0b00, q: 0b1},
 			VectorArrangement8B:  {size: 0b00, q: 0b0},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ORR--vector--register---Bitwise-inclusive-OR--vector--register--?lang=en
-	VORR: {U: 0b0, Opcode: 0b00011,
+	VORR: {u: 0b0, opcode: 0b00011,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement16B: {size: 0b10, q: 0b1},
 			VectorArrangement8B:  {size: 0b10, q: 0b0},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/BIC--vector--register---Bitwise-bit-Clear--vector--register--?lang=en
-	BIC: {U: 0b0, Opcode: 0b00011,
+	BIC: {u: 0b0, opcode: 0b00011,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement16B: {size: 0b01, q: 0b1},
 			VectorArrangement8B:  {size: 0b01, q: 0b0},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FADD--vector---Floating-point-Add--vector--?lang=en
-	VFADDS: {U: 0b0, Opcode: 0b11010,
+	VFADDS: {u: 0b0, opcode: 0b11010,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b00, q: 0b1},
 			VectorArrangement2S: {size: 0b00, q: 0b0},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FADD--vector---Floating-point-Add--vector--?lang=en
-	VFADDD: {U: 0b0, Opcode: 0b11010,
+	VFADDD: {u: 0b0, opcode: 0b11010,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement2D: {size: 0b01, q: 0b1},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FSUB--vector---Floating-point-Subtract--vector--?lang=en
-	VFSUBS: {U: 0b0, Opcode: 0b11010,
+	VFSUBS: {u: 0b0, opcode: 0b11010,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b10, q: 0b1},
 			VectorArrangement2S: {size: 0b10, q: 0b0},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FSUB--vector---Floating-point-Subtract--vector--?lang=en
-	VFSUBD: {U: 0b0, Opcode: 0b11010,
+	VFSUBD: {u: 0b0, opcode: 0b11010,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement2D: {size: 0b11, q: 0b1},
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMAXP--Unsigned-Maximum-Pairwise-?lang=en
-	UMAXP: {U: 0b1, Opcode: 0b10100, qAndSize: defaultQAndSize},
+	UMAXP: {u: 0b1, opcode: 0b10100, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/CMEQ--register---Compare-bitwise-Equal--vector--?lang=en
-	CMEQ: {U: 0b1, Opcode: 0b10001, qAndSize: defaultQAndSize},
+	CMEQ: {u: 0b1, opcode: 0b10001, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/dui0801/g/A64-SIMD-Vector-Instructions/ADDP--vector-
-	VADDP: {U: 0b0, Opcode: 0b10111, qAndSize: defaultQAndSize},
+	VADDP: {u: 0b0, opcode: 0b10111, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ADD--vector---Add--vector--?lang=en
-	VADD: {U: 0, Opcode: 0b10000, qAndSize: defaultQAndSize},
+	VADD: {u: 0, opcode: 0b10000, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SUB--vector---Subtract--vector--?lang=en
-	VSUB: {U: 1, Opcode: 0b10000, qAndSize: defaultQAndSize},
+	VSUB: {u: 1, opcode: 0b10000, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SSHL--Signed-Shift-Left--register--?lang=en
-	SSHL: {U: 0, Opcode: 0b01000, qAndSize: defaultQAndSize},
+	SSHL: {u: 0, opcode: 0b01000, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SSHL--Signed-Shift-Left--register--?lang=en
-	USHL: {U: 0b1, Opcode: 0b01000, qAndSize: defaultQAndSize},
+	USHL: {u: 0b1, opcode: 0b01000, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/CMGT--register---Compare-signed-Greater-than--vector--?lang=en
-	CMGT: {U: 0b0, Opcode: 0b00110, qAndSize: defaultQAndSize},
+	CMGT: {u: 0b0, opcode: 0b00110, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/CMHI--register---Compare-unsigned-Higher--vector--?lang=en
-	CMHI: {U: 0b1, Opcode: 0b00110, qAndSize: defaultQAndSize},
+	CMHI: {u: 0b1, opcode: 0b00110, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/CMGE--register---Compare-signed-Greater-than-or-Equal--vector--?lang=en
-	CMGE: {U: 0b0, Opcode: 0b00111, qAndSize: defaultQAndSize},
+	CMGE: {u: 0b0, opcode: 0b00111, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/CMHS--register---Compare-unsigned-Higher-or-Same--vector--?lang=en
-	CMHS: {U: 0b1, Opcode: 0b00111, qAndSize: defaultQAndSize},
+	CMHS: {u: 0b1, opcode: 0b00111, qAndSize: defaultQAndSize},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FCMEQ--register---Floating-point-Compare-Equal--vector--?lang=en
-	FCMEQ: {U: 0b0, Opcode: 0b11100,
+	FCMEQ: {u: 0b0, opcode: 0b11100,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b00, q: 0b1},
 			VectorArrangement2S: {size: 0b00, q: 0b0},
@@ -3053,7 +2962,7 @@ var advancedSIMDThreeSame = map[asm.Instruction]struct {
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FCMGT--register---Floating-point-Compare-Greater-than--vector--?lang=en
-	FCMGT: {U: 0b1, Opcode: 0b11100,
+	FCMGT: {u: 0b1, opcode: 0b11100,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b10, q: 0b1},
 			VectorArrangement2S: {size: 0b10, q: 0b0},
@@ -3061,7 +2970,7 @@ var advancedSIMDThreeSame = map[asm.Instruction]struct {
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FCMGE--register---Floating-point-Compare-Greater-than-or-Equal--vector--?lang=en
-	FCMGE: {U: 0b1, Opcode: 0b11100,
+	FCMGE: {u: 0b1, opcode: 0b11100,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b00, q: 0b1},
 			VectorArrangement2S: {size: 0b00, q: 0b0},
@@ -3069,7 +2978,7 @@ var advancedSIMDThreeSame = map[asm.Instruction]struct {
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FMIN--vector---Floating-point-minimum--vector--?lang=en
-	VFMIN: {U: 0b0, Opcode: 0b11110,
+	VFMIN: {u: 0b0, opcode: 0b11110,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b10, q: 0b1},
 			VectorArrangement2S: {size: 0b10, q: 0b0},
@@ -3077,7 +2986,7 @@ var advancedSIMDThreeSame = map[asm.Instruction]struct {
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FMAX--vector---Floating-point-Maximum--vector--?lang=en
-	VFMAX: {U: 0b0, Opcode: 0b11110,
+	VFMAX: {u: 0b0, opcode: 0b11110,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b00, q: 0b1},
 			VectorArrangement2S: {size: 0b00, q: 0b0},
@@ -3085,7 +2994,7 @@ var advancedSIMDThreeSame = map[asm.Instruction]struct {
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FMUL--vector---Floating-point-Multiply--vector--?lang=en
-	VFMUL: {U: 0b1, Opcode: 0b11011,
+	VFMUL: {u: 0b1, opcode: 0b11011,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b00, q: 0b1},
 			VectorArrangement2S: {size: 0b00, q: 0b0},
@@ -3093,13 +3002,38 @@ var advancedSIMDThreeSame = map[asm.Instruction]struct {
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FDIV--vector---Floating-point-Divide--vector--?lang=en
-	VFDIV: {U: 0b1, Opcode: 0b11111,
+	VFDIV: {u: 0b1, opcode: 0b11111,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement4S: {size: 0b00, q: 0b1},
 			VectorArrangement2S: {size: 0b00, q: 0b0},
 			VectorArrangement2D: {size: 0b01, q: 0b1},
 		},
 	},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/MUL--vector---Multiply--vector--?lang=en
+	VMUL: {u: 0b0, opcode: 0b10011, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SQADD--Signed-saturating-Add-?lang=en
+	VSQADD: {u: 0b0, opcode: 0b00001, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UQADD--Unsigned-saturating-Add-?lang=en
+	VUQADD: {u: 0b1, opcode: 0b00001, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SMIN--Signed-Minimum--vector--?lang=en
+	SMIN: {u: 0b0, opcode: 0b01101, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SMAX--Signed-Maximum--vector--?lang=en
+	SMAX: {u: 0b0, opcode: 0b01100, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMIN--Unsigned-Minimum--vector--?lang=en
+	UMIN: {u: 0b1, opcode: 0b01101, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMAX--Unsigned-Maximum--vector--?lang=en
+	UMAX: {u: 0b1, opcode: 0b01100, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/URHADD--Unsigned-Rounding-Halving-Add-?lang=en
+	URHADD: {u: 0b1, opcode: 0b00010, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/SQSUB--Signed-saturating-Subtract-?lang=en
+	VSQSUB: {u: 0b0, opcode: 0b00101, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UQSUB--Unsigned-saturating-Subtract-?lang=en
+	VUQSUB: {u: 0b1, opcode: 0b00101, qAndSize: defaultQAndSize},
+	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/BIT--Bitwise-Insert-if-True-?lang=en
+	VBIT: {u: 0b1, opcode: 0b00011, qAndSize: map[VectorArrangement]qAndSize{
+		VectorArrangement8B:  {q: 0b0, size: 0b10},
+		VectorArrangement16B: {q: 0b1, size: 0b10},
+	}},
 }
 
 // aAndSize is a pair of "Q" and "size" that appear in https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
@@ -3120,11 +3054,11 @@ var defaultQAndSize = map[VectorArrangement]qAndSize{
 // advancedSIMDAcrossLanes holds information to encode instructions as "Advanced SIMD across lanes" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDAcrossLanes = map[asm.Instruction]struct {
-	U, Opcode byte
+	u, opcode byte
 	qAndSize  map[VectorArrangement]qAndSize
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ADDV--Add-across-Vector-?lang=en
-	ADDV: {U: 0b0, Opcode: 0b11011,
+	ADDV: {u: 0b0, opcode: 0b11011,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement16B: {size: 0b00, q: 0b1},
 			VectorArrangement8B:  {size: 0b00, q: 0b0},
@@ -3134,7 +3068,7 @@ var advancedSIMDAcrossLanes = map[asm.Instruction]struct {
 		},
 	},
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMINV--Unsigned-Minimum-across-Vector-?lang=en
-	UMINV: {U: 0b1, Opcode: 0b11010,
+	UMINV: {u: 0b1, opcode: 0b11010,
 		qAndSize: map[VectorArrangement]qAndSize{
 			VectorArrangement16B: {size: 0b00, q: 0b1},
 			VectorArrangement8B:  {size: 0b00, q: 0b0},
@@ -3143,16 +3077,23 @@ var advancedSIMDAcrossLanes = map[asm.Instruction]struct {
 			VectorArrangement4S:  {size: 0b10, q: 0b1},
 		},
 	},
+	UADDLV: {u: 0b1, opcode: 0b00011, qAndSize: map[VectorArrangement]qAndSize{
+		VectorArrangement16B: {size: 0b00, q: 0b1},
+		VectorArrangement8B:  {size: 0b00, q: 0b0},
+		VectorArrangement8H:  {size: 0b01, q: 0b1},
+		VectorArrangement4H:  {size: 0b01, q: 0b0},
+		VectorArrangement4S:  {size: 0b10, q: 0b1},
+	}},
 }
 
 // advancedSIMDScalarPairwise holds information to encode instructions as "Advanced SIMD scalar pairwise" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDScalarPairwise = map[asm.Instruction]struct {
-	U, Opcode byte
+	u, opcode byte
 	size      map[VectorArrangement]byte
 }{
 	// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ADDP--scalar---Add-Pair-of-elements--scalar--?lang=en
-	ADDP: {U: 0b0, Opcode: 0b11011, size: map[VectorArrangement]byte{VectorArrangement2D: 0b11}},
+	ADDP: {u: 0b0, opcode: 0b11011, size: map[VectorArrangement]byte{VectorArrangement2D: 0b11}},
 }
 
 // advancedSIMDCopy holds information to encode instructions as "Advanced SIMD copy" in
@@ -3363,7 +3304,7 @@ var advancedSIMDShiftByImmediate = map[asm.Instruction]struct {
 	}},
 }
 
-// advancedSIMDShiftByImmediate holds information to encode instructions as "Advanced SIMD permute" in
+// advancedSIMDPermute holds information to encode instructions as "Advanced SIMD permute" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 var advancedSIMDPermute = map[asm.Instruction]struct {
 	opcode byte
@@ -3412,6 +3353,17 @@ func (a *AssemblerImpl) encodeAdvancedSIMDThreeSame(src1, src2, dst, opcode, siz
 	})
 }
 
+// encodeAdvancedSIMDThreeDifferent encodes instruction as  "Advanced SIMD three different" in
+// https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
+func (a *AssemblerImpl) encodeAdvancedSIMDThreeDifferent(src1, src2, dst, opcode, size, q, u byte) {
+	a.Buf.Write([]byte{
+		(src2 << 5) | dst,
+		opcode<<4 | src2>>3,
+		size<<6 | 0b1<<5 | src1,
+		q<<6 | u<<5 | 0b1110,
+	})
+}
+
 // encodeAdvancedSIMDPermute encodes instruction as  "Advanced SIMD permute" in
 // https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en
 func (a *AssemblerImpl) encodeAdvancedSIMDPermute(src1, src2, dst, opcode, size, q byte) {
@@ -3455,9 +3407,9 @@ func (a *AssemblerImpl) EncodeVectorRegisterToVectorRegister(n *NodeImpl) (err e
 		}
 		a.Buf.Write([]byte{
 			(srcVectorRegBits << 5) | dstVectorRegBits,
-			scalarPairwise.Opcode<<4 | 1<<3 | srcVectorRegBits>>3,
-			size<<6 | 0b11<<4 | scalarPairwise.Opcode>>4,
-			0b1<<6 | scalarPairwise.U<<5 | 0b11110,
+			scalarPairwise.opcode<<4 | 1<<3 | srcVectorRegBits>>3,
+			size<<6 | 0b11<<4 | scalarPairwise.opcode>>4,
+			0b1<<6 | scalarPairwise.u<<5 | 0b11110,
 		})
 		return
 	}
@@ -3483,7 +3435,16 @@ func (a *AssemblerImpl) EncodeVectorRegisterToVectorRegister(n *NodeImpl) (err e
 		if !ok {
 			return fmt.Errorf("unsupported vector arrangement %s for %s", n.VectorArrangement, InstructionName(n.Instruction))
 		}
-		a.encodeAdvancedSIMDThreeSame(srcVectorRegBits, dstVectorRegBits, dstVectorRegBits, threeSame.Opcode, qs.size, qs.q, threeSame.U)
+		a.encodeAdvancedSIMDThreeSame(srcVectorRegBits, dstVectorRegBits, dstVectorRegBits, threeSame.opcode, qs.size, qs.q, threeSame.u)
+		return nil
+	}
+
+	if threeDifferent, ok := advancedSIMDThreeDifferent[n.Instruction]; ok {
+		qs, ok := threeDifferent.qAndSize[n.VectorArrangement]
+		if !ok {
+			return fmt.Errorf("unsupported vector arrangement %s for %s", n.VectorArrangement, InstructionName(n.Instruction))
+		}
+		a.encodeAdvancedSIMDThreeDifferent(srcVectorRegBits, dstVectorRegBits, dstVectorRegBits, threeDifferent.opcode, qs.size, qs.q, threeDifferent.u)
 		return nil
 	}
 
@@ -3496,9 +3457,9 @@ func (a *AssemblerImpl) EncodeVectorRegisterToVectorRegister(n *NodeImpl) (err e
 		}
 		a.Buf.Write([]byte{
 			(srcVectorRegBits << 5) | dstVectorRegBits,
-			acrossLanes.Opcode<<4 | 0b1<<3 | srcVectorRegBits>>3,
-			qs.size<<6 | 0b11000<<1 | acrossLanes.Opcode>>4,
-			qs.q<<6 | acrossLanes.U<<5 | 0b01110,
+			acrossLanes.opcode<<4 | 0b1<<3 | srcVectorRegBits>>3,
+			qs.size<<6 | 0b11000<<1 | acrossLanes.opcode>>4,
+			qs.q<<6 | acrossLanes.u<<5 | 0b01110,
 		})
 		return nil
 	}
@@ -3575,7 +3536,16 @@ func (a *AssemblerImpl) encodeTwoVectorRegistersToVectorRegister(n *NodeImpl) (e
 		if !ok {
 			return fmt.Errorf("unsupported vector arrangement %s for %s", n.VectorArrangement, InstructionName(n.Instruction))
 		}
-		a.encodeAdvancedSIMDThreeSame(srcRegBits, srcRegBits2, dstRegBits, threeSame.Opcode, qs.size, qs.q, threeSame.U)
+		a.encodeAdvancedSIMDThreeSame(srcRegBits, srcRegBits2, dstRegBits, threeSame.opcode, qs.size, qs.q, threeSame.u)
+		return nil
+	}
+
+	if threeDifferent, ok := advancedSIMDThreeDifferent[n.Instruction]; ok {
+		qs, ok := threeDifferent.qAndSize[n.VectorArrangement]
+		if !ok {
+			return fmt.Errorf("unsupported vector arrangement %s for %s", n.VectorArrangement, InstructionName(n.Instruction))
+		}
+		a.encodeAdvancedSIMDThreeDifferent(srcRegBits, srcRegBits2, dstRegBits, threeDifferent.opcode, qs.size, qs.q, threeDifferent.u)
 		return nil
 	}
 
diff --git a/internal/engine/compiler/impl_arm64.go b/internal/engine/compiler/impl_arm64.go
index 614fd826..071a22c2 100644
--- a/internal/engine/compiler/impl_arm64.go
+++ b/internal/engine/compiler/impl_arm64.go
@@ -1651,7 +1651,7 @@ func (c *arm64Compiler) compilePopcnt(o *wazeroir.OperationPopcnt) error {
 	//    MOVD    $10, R0 ;; Load 10.
 	//    FMOVD   R0, F0
 	//    VCNT    V0.B8, V0.B8
-	//    VUADDLV V0.B8, V0
+	//    UADDLV  V0.B8, V0
 	//
 	var movInst asm.Instruction
 	if o.Type == wazeroir.UnsignedInt32 {
@@ -1660,8 +1660,10 @@ func (c *arm64Compiler) compilePopcnt(o *wazeroir.OperationPopcnt) error {
 		movInst = arm64.FMOVD
 	}
 	c.assembler.CompileRegisterToRegister(movInst, reg, freg)
-	c.assembler.CompileSIMDByteToSIMDByte(arm64.VCNT, freg, freg)
-	c.assembler.CompileSIMDByteToRegister(arm64.VUADDLV, freg, freg)
+	c.assembler.CompileVectorRegisterToVectorRegister(arm64.VCNT, freg, freg,
+		arm64.VectorArrangement16B, arm64.VectorIndexNone, arm64.VectorIndexNone)
+	c.assembler.CompileVectorRegisterToVectorRegister(arm64.UADDLV, freg, freg, arm64.VectorArrangement8B,
+		arm64.VectorIndexNone, arm64.VectorIndexNone)
 
 	c.assembler.CompileRegisterToRegister(movInst, freg, reg)
 
@@ -2189,7 +2191,8 @@ func (c *arm64Compiler) compileCopysign(o *wazeroir.OperationCopysign) error {
 	// * https://github.com/golang/go/blob/739328c694d5e608faa66d17192f0a59f6e01d04/src/cmd/compile/internal/arm64/ssa.go#L972
 	//
 	// "vbit vreg.8b, x2vreg.8b, x1vreg.8b" == "inserting 64th bit of x2 into x1".
-	c.assembler.CompileTwoSIMDBytesToSIMDByteRegister(arm64.VBIT, freg, x2.register, x1.register)
+	c.assembler.CompileTwoVectorRegistersToVectorRegister(arm64.VBIT,
+		freg, x2.register, x1.register, arm64.VectorArrangement16B)
 
 	c.markRegisterUnused(x2.register)
 	c.pushRuntimeValueLocationOnRegister(x1.register, x1.valueType)
diff --git a/internal/engine/compiler/impl_vec_arm64.go b/internal/engine/compiler/impl_vec_arm64.go
index 94d655f9..d609c129 100644
--- a/internal/engine/compiler/impl_vec_arm64.go
+++ b/internal/engine/compiler/impl_vec_arm64.go
@@ -1013,30 +1013,88 @@ func (c *arm64Compiler) compileV128Cmp(o *wazeroir.OperationV128Cmp) error {
 
 // compileV128AddSat implements compiler.compileV128AddSat for arm64.
 func (c *arm64Compiler) compileV128AddSat(o *wazeroir.OperationV128AddSat) error {
-	return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
+	var inst asm.Instruction
+	if o.Signed {
+		inst = arm64.VSQADD
+	} else {
+		inst = arm64.VUQADD
+	}
+	return c.compileV128x2BinOp(inst, defaultArrangementForShape(o.Shape))
 }
 
 // compileV128SubSat implements compiler.compileV128SubSat for arm64.
 func (c *arm64Compiler) compileV128SubSat(o *wazeroir.OperationV128SubSat) error {
-	return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
+	var inst asm.Instruction
+	if o.Signed {
+		inst = arm64.VSQSUB
+	} else {
+		inst = arm64.VUQSUB
+	}
+	return c.compileV128x2BinOp(inst, defaultArrangementForShape(o.Shape))
 }
 
 // compileV128Mul implements compiler.compileV128Mul for arm64.
-func (c *arm64Compiler) compileV128Mul(o *wazeroir.OperationV128Mul) error {
-	var arr arm64.VectorArrangement
-	var inst asm.Instruction
+func (c *arm64Compiler) compileV128Mul(o *wazeroir.OperationV128Mul) (err error) {
 	switch o.Shape {
-	case wazeroir.ShapeF32x4:
-		arr = arm64.VectorArrangement4S
-		inst = arm64.VFMUL
-	case wazeroir.ShapeF64x2:
-		arr = arm64.VectorArrangement2D
-		inst = arm64.VFMUL
-	default:
-		// TODO: support for integer mul.
-		return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
+	case wazeroir.ShapeI8x16, wazeroir.ShapeI16x8, wazeroir.ShapeI32x4:
+		err = c.compileV128x2BinOp(arm64.VMUL, defaultArrangementForShape(o.Shape))
+	case wazeroir.ShapeF32x4, wazeroir.ShapeF64x2:
+		err = c.compileV128x2BinOp(arm64.VFMUL, defaultArrangementForShape(o.Shape))
+	case wazeroir.ShapeI64x2:
+		x2 := c.locationStack.popV128()
+		if err = c.compileEnsureOnGeneralPurposeRegister(x2); err != nil {
+			return
+		}
+
+		x1 := c.locationStack.popV128()
+		if err = c.compileEnsureOnGeneralPurposeRegister(x1); err != nil {
+			return
+		}
+
+		src1, src2 := x1.register, x2.register
+
+		tmp1, err := c.allocateRegister(registerTypeVector)
+		if err != nil {
+			return err
+		}
+		c.markRegisterUsed(tmp1)
+
+		tmp2, err := c.allocateRegister(registerTypeVector)
+		if err != nil {
+			return err
+		}
+
+		c.markRegisterUsed(tmp2)
+
+		tmp3, err := c.allocateRegister(registerTypeVector)
+		if err != nil {
+			return err
+		}
+
+		// Following the algorithm in https://chromium-review.googlesource.com/c/v8/v8/+/1781696
+		c.assembler.CompileVectorRegisterToVectorRegister(arm64.REV64, src2, tmp2,
+			arm64.VectorArrangement4S, arm64.VectorIndexNone, arm64.VectorIndexNone)
+		c.assembler.CompileTwoVectorRegistersToVectorRegister(arm64.VMUL, src1, tmp2, tmp2, arm64.VectorArrangement4S)
+
+		c.assembler.CompileVectorRegisterToVectorRegister(arm64.XTN, src1, tmp1,
+			arm64.VectorArrangement2D, arm64.VectorIndexNone, arm64.VectorIndexNone)
+
+		c.assembler.CompileVectorRegisterToVectorRegister(arm64.VADDP, tmp2, tmp2, arm64.VectorArrangement4S,
+			arm64.VectorIndexNone, arm64.VectorIndexNone,
+		)
+
+		c.assembler.CompileVectorRegisterToVectorRegister(arm64.XTN, src2, tmp3,
+			arm64.VectorArrangement2D, arm64.VectorIndexNone, arm64.VectorIndexNone)
+
+		c.assembler.CompileVectorRegisterToVectorRegister(arm64.SHLL, tmp2, src1,
+			arm64.VectorArrangement2S, arm64.VectorIndexNone, arm64.VectorIndexNone)
+
+		c.assembler.CompileTwoVectorRegistersToVectorRegister(arm64.VUMLAL, tmp3, tmp1, src1, arm64.VectorArrangement2S)
+
+		c.markRegisterUnused(src2, tmp1, tmp2)
+		c.pushVectorRuntimeValueLocationOnRegister(src1)
 	}
-	return c.compileV128x2BinOp(inst, arr)
+	return
 }
 
 // compileV128Div implements compiler.compileV128Div for arm64.
@@ -1056,20 +1114,13 @@ func (c *arm64Compiler) compileV128Div(o *wazeroir.OperationV128Div) error {
 
 // compileV128Neg implements compiler.compileV128Neg for arm64.
 func (c *arm64Compiler) compileV128Neg(o *wazeroir.OperationV128Neg) error {
-	var arr arm64.VectorArrangement
 	var inst asm.Instruction
-	switch o.Shape {
-	case wazeroir.ShapeF32x4:
-		arr = arm64.VectorArrangement4S
+	if o.Shape <= wazeroir.ShapeI64x2 { // Integer lanes
+		inst = arm64.VNEG
+	} else { // Floating point lanes
 		inst = arm64.VFNEG
-	case wazeroir.ShapeF64x2:
-		arr = arm64.VectorArrangement2D
-		inst = arm64.VFNEG
-	default:
-		// TODO: support for integer neg.
-		return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
 	}
-	return c.compileV128UniOp(inst, arr)
+	return c.compileV128UniOp(inst, defaultArrangementForShape(o.Shape))
 }
 
 // compileV128Sqrt implements compiler.compileV128Sqrt for arm64.
@@ -1087,65 +1138,70 @@ func (c *arm64Compiler) compileV128Sqrt(o *wazeroir.OperationV128Sqrt) error {
 // compileV128Abs implements compiler.compileV128Abs for arm64.
 func (c *arm64Compiler) compileV128Abs(o *wazeroir.OperationV128Abs) error {
 	var inst asm.Instruction
-	var arr arm64.VectorArrangement
-	switch o.Shape {
-	case wazeroir.ShapeF32x4:
+	if o.Shape <= wazeroir.ShapeI64x2 { // Integer lanes
+		inst = arm64.VABS
+	} else { // Floating point lanes
 		inst = arm64.VFABS
-		arr = arm64.VectorArrangement4S
-	case wazeroir.ShapeF64x2:
-		inst = arm64.VFABS
-		arr = arm64.VectorArrangement2D
-	default:
-		// TODO: support for integer abs.
-		return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
 	}
-	return c.compileV128UniOp(inst, arr)
+	return c.compileV128UniOp(inst, defaultArrangementForShape(o.Shape))
 }
 
 // compileV128Popcnt implements compiler.compileV128Popcnt for arm64.
 func (c *arm64Compiler) compileV128Popcnt(o *wazeroir.OperationV128Popcnt) error {
-	return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
+	return c.compileV128UniOp(arm64.VCNT, defaultArrangementForShape(o.Shape))
 }
 
 // compileV128Min implements compiler.compileV128Min for arm64.
 func (c *arm64Compiler) compileV128Min(o *wazeroir.OperationV128Min) error {
 	var inst asm.Instruction
-	var arr arm64.VectorArrangement
-	switch o.Shape {
-	case wazeroir.ShapeF32x4:
+	if o.Shape <= wazeroir.ShapeI64x2 { // Integer lanes
+		if o.Signed {
+			inst = arm64.SMIN
+		} else {
+			inst = arm64.UMIN
+		}
+	} else { // Floating point lanes
 		inst = arm64.VFMIN
+	}
+	return c.compileV128x2BinOp(inst, defaultArrangementForShape(o.Shape))
+}
+
+func defaultArrangementForShape(s wazeroir.Shape) (arr arm64.VectorArrangement) {
+	switch s {
+	case wazeroir.ShapeI8x16:
+		arr = arm64.VectorArrangement16B
+	case wazeroir.ShapeI16x8:
+		arr = arm64.VectorArrangement8H
+	case wazeroir.ShapeI32x4:
+		arr = arm64.VectorArrangement4S
+	case wazeroir.ShapeI64x2:
+		arr = arm64.VectorArrangement2D
+	case wazeroir.ShapeF32x4:
 		arr = arm64.VectorArrangement4S
 	case wazeroir.ShapeF64x2:
-		inst = arm64.VFMIN
 		arr = arm64.VectorArrangement2D
-	default:
-		// TODO: support for integer min.
-		return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
 	}
-	return c.compileV128x2BinOp(inst, arr)
+	return
 }
 
 // compileV128Max implements compiler.compileV128Max for arm64.
 func (c *arm64Compiler) compileV128Max(o *wazeroir.OperationV128Max) error {
 	var inst asm.Instruction
-	var arr arm64.VectorArrangement
-	switch o.Shape {
-	case wazeroir.ShapeF32x4:
-		inst = arm64.VFMAX
-		arr = arm64.VectorArrangement4S
-	case wazeroir.ShapeF64x2:
+	if o.Shape <= wazeroir.ShapeI64x2 { // Integer lanes
+		if o.Signed {
+			inst = arm64.SMAX
+		} else {
+			inst = arm64.UMAX
+		}
+	} else { // Floating point lanes
 		inst = arm64.VFMAX
-		arr = arm64.VectorArrangement2D
-	default:
-		// TODO: support for integer max.
-		return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
 	}
-	return c.compileV128x2BinOp(inst, arr)
+	return c.compileV128x2BinOp(inst, defaultArrangementForShape(o.Shape))
 }
 
 // compileV128AvgrU implements compiler.compileV128AvgrU for arm64.
 func (c *arm64Compiler) compileV128AvgrU(o *wazeroir.OperationV128AvgrU) error {
-	return fmt.Errorf("TODO: %s is not implemented yet on arm64 compiler", o.Kind())
+	return c.compileV128x2BinOp(arm64.URHADD, defaultArrangementForShape(o.Shape))
 }
 
 // compileV128Pmin implements compiler.compileV128Pmin for arm64.


Test patch:
diff --git a/internal/asm/arm64/impl_test.go b/internal/asm/arm64/impl_test.go
index b1977aee..a7ee7866 100644
--- a/internal/asm/arm64/impl_test.go
+++ b/internal/asm/arm64/impl_test.go
@@ -94,18 +94,6 @@ func TestNodeImpl_String(t *testing.T) {
 			in:  &NodeImpl{Instruction: MOVD, Types: OperandTypesConstToRegister, SrcConst: 0x123, DstReg: RegR8},
 			exp: "MOVD 0x123, R8",
 		},
-		{
-			in:  &NodeImpl{Instruction: VCNT, Types: OperandTypesSIMDByteToSIMDByte, SrcReg: RegV1, DstReg: RegV2},
-			exp: "VCNT V1.B8, V2.B8",
-		},
-		{
-			in:  &NodeImpl{Instruction: VUADDLV, Types: OperandTypesSIMDByteToRegister, SrcReg: RegV1, DstReg: RegV2},
-			exp: "VUADDLV V1.B8, V2",
-		},
-		{
-			in:  &NodeImpl{Instruction: VBIT, Types: OperandTypesTwoSIMDBytesToSIMDByteRegister, SrcReg: RegV1, SrcReg2: RegV2, DstReg: RegV3},
-			exp: "VBIT (V1.B8, V2.B8), V3.B8",
-		},
 		{
 			in: &NodeImpl{Instruction: VMOV, Types: OperandTypesMemoryToVectorRegister,
 				SrcReg: RegR1, DstReg: RegV29, VectorArrangement: VectorArrangement2S},
@@ -342,40 +330,6 @@ func Test_CompileLeftShiftedRegisterToRegister(t *testing.T) {
 	require.Equal(t, OperandTypeRegister, actualNode.Types.dst)
 }
 
-func Test_CompileSIMDByteToSIMDByte(t *testing.T) {
-	a := NewAssemblerImpl(RegR10)
-	a.CompileSIMDByteToSIMDByte(VCNT, RegV0, RegV2)
-	actualNode := a.Current
-	require.Equal(t, VCNT, actualNode.Instruction)
-	require.Equal(t, RegV0, actualNode.SrcReg)
-	require.Equal(t, RegV2, actualNode.DstReg)
-	require.Equal(t, OperandTypeSIMDByte, actualNode.Types.src)
-	require.Equal(t, OperandTypeSIMDByte, actualNode.Types.dst)
-}
-
-func Test_CompileTwoSIMDBytesToSIMDByteRegister(t *testing.T) {
-	a := NewAssemblerImpl(RegR10)
-	a.CompileTwoSIMDBytesToSIMDByteRegister(VBIT, RegV0, RegV10, RegV2)
-	actualNode := a.Current
-	require.Equal(t, VBIT, actualNode.Instruction)
-	require.Equal(t, RegV0, actualNode.SrcReg)
-	require.Equal(t, RegV10, actualNode.SrcReg2)
-	require.Equal(t, RegV2, actualNode.DstReg)
-	require.Equal(t, OperandTypeTwoSIMDBytes, actualNode.Types.src)
-	require.Equal(t, OperandTypeSIMDByte, actualNode.Types.dst)
-}
-
-func Test_CompileSIMDByteToRegister(t *testing.T) {
-	a := NewAssemblerImpl(RegR10)
-	a.CompileSIMDByteToRegister(VUADDLV, RegV0, RegV10)
-	actualNode := a.Current
-	require.Equal(t, VUADDLV, actualNode.Instruction)
-	require.Equal(t, RegV0, actualNode.SrcReg)
-	require.Equal(t, RegV10, actualNode.DstReg)
-	require.Equal(t, OperandTypeSIMDByte, actualNode.Types.src)
-	require.Equal(t, OperandTypeRegister, actualNode.Types.dst)
-}
-
 func Test_CompileConditionalRegisterSet(t *testing.T) {
 	a := NewAssemblerImpl(RegR10)
 	a.CompileConditionalRegisterSet(CondNE, RegR10)
@@ -888,6 +842,126 @@ func TestAssemblerImpl_EncodeVectorRegisterToVectorRegister(t *testing.T) {
 		srcIndex, dstIndex VectorIndex
 		exp                []byte
 	}{
+		{
+			inst: XTN,
+			name: "xtn v10.2s, v2.2d",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement2D,
+			exp:  []byte{0x4a, 0x28, 0xa1, 0xe},
+		},
+		{
+			inst: XTN,
+			name: "xtn v10.4h, v2.4s",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement4S,
+			exp:  []byte{0x4a, 0x28, 0x61, 0xe},
+		},
+		{
+			inst: XTN,
+			name: "xtn v10.8b, v2.8h",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement8H,
+			exp:  []byte{0x4a, 0x28, 0x21, 0xe},
+		},
+		{
+			inst: REV64,
+			name: "rev64 v10.16b, v2.16b",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement16B,
+			exp:  []byte{0x4a, 0x8, 0x20, 0x4e},
+		},
+		{
+			inst: REV64,
+			name: "rev64 v10.4s, v2.4s",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement4S,
+			exp:  []byte{0x4a, 0x8, 0xa0, 0x4e},
+		},
+		{
+			inst: VCNT,
+			name: "cnt v10.16b, v2.16b",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement16B,
+			exp:  []byte{0x4a, 0x58, 0x20, 0x4e},
+		},
+		{
+			inst: VCNT,
+			name: "cnt v10.8b, v2.8b",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement8B,
+			exp:  []byte{0x4a, 0x58, 0x20, 0xe},
+		},
+		{
+			inst: VNEG,
+			name: "neg v10.16b, v2.16b",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement16B,
+			exp:  []byte{0x4a, 0xb8, 0x20, 0x6e},
+		},
+		{
+			inst: VNEG,
+			name: "neg v10.8h, v2.18h",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement8H,
+			exp:  []byte{0x4a, 0xb8, 0x60, 0x6e},
+		},
+		{
+			inst: VNEG,
+			name: "neg v10.4s, v2.4s",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement4S,
+			exp:  []byte{0x4a, 0xb8, 0xa0, 0x6e},
+		},
+		{
+			inst: VNEG,
+			name: "neg v10.2d, v2.2d",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement2D,
+			exp:  []byte{0x4a, 0xb8, 0xe0, 0x6e},
+		},
+		{
+			inst: VABS,
+			name: "abs v10.16b, v2.16b",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement16B,
+			exp:  []byte{0x4a, 0xb8, 0x20, 0x4e},
+		},
+		{
+			inst: VABS,
+			name: "abs v10.8h, v2.18h",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement8H,
+			exp:  []byte{0x4a, 0xb8, 0x60, 0x4e},
+		},
+		{
+			inst: VABS,
+			name: "abs v10.4s, v2.4s",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement4S,
+			exp:  []byte{0x4a, 0xb8, 0xa0, 0x4e},
+		},
+		{
+			inst: VABS,
+			name: "abs v10.2d, v2.2d",
+			x1:   RegV2,
+			x2:   RegV10,
+			arr:  VectorArrangement2D,
+			exp:  []byte{0x4a, 0xb8, 0xe0, 0x4e},
+		},
 		{
 			inst: ZIP1,
 			name: "zip1 v10.16b, v10.16b, v2.16b",
@@ -1104,14 +1178,6 @@ func TestAssemblerImpl_EncodeVectorRegisterToVectorRegister(t *testing.T) {
 			arr:  VectorArrangement2D,
 			c:    1,
 		},
-		{
-			name: "sshll v10.8h, v2.8b, #0",
-			x1:   RegV2,
-			x2:   RegV10,
-			inst: SSHLLIMM,
-			exp:  []byte{0x4a, 0xa4, 0x8, 0xf},
-			arr:  VectorArrangement8B,
-		},
 		{
 			name: "sshll v10.8h, v2.8b, #7",
 			x1:   RegV2,
@@ -1640,6 +1706,54 @@ func TestAssemblerImpl_EncodeVectorRegisterToVectorRegister(t *testing.T) {
 			exp:  []byte{0x3e, 0x8b, 0x61, 0x4e},
 			arr:  VectorArrangement2D,
 		},
+		{
+			x1:   RegV25,
+			x2:   RegV30,
+			name: "shll v30.8h, v25.8b, #8",
+			inst: SHLL,
+			exp:  []byte{0x3e, 0x3b, 0x21, 0x2e},
+			arr:  VectorArrangement8B,
+		},
+		{
+			x1:   RegV25,
+			x2:   RegV30,
+			name: "shll v30.4s, v25.4h, #16",
+			inst: SHLL,
+			exp:  []byte{0x3e, 0x3b, 0x61, 0x2e},
+			arr:  VectorArrangement4H,
+		},
+		{
+			x1:   RegV25,
+			x2:   RegV30,
+			name: "shll v30.2d, v25.2s, #32",
+			inst: SHLL,
+			exp:  []byte{0x3e, 0x3b, 0xa1, 0x2e},
+			arr:  VectorArrangement2S,
+		},
+		{
+			x1:   RegV25,
+			x2:   RegV30,
+			name: "uaddlv h30, v25.16b",
+			inst: UADDLV,
+			exp:  []byte{0x3e, 0x3b, 0x30, 0x6e},
+			arr:  VectorArrangement16B,
+		},
+		{
+			x1:   RegV25,
+			x2:   RegV30,
+			name: "uaddlv s30, v25.8h",
+			inst: UADDLV,
+			exp:  []byte{0x3e, 0x3b, 0x70, 0x6e},
+			arr:  VectorArrangement8H,
+		},
+		{
+			x1:   RegV25,
+			x2:   RegV30,
+			name: "uaddlv d30, v25.4s",
+			inst: UADDLV,
+			exp:  []byte{0x3e, 0x3b, 0xb0, 0x6e},
+			arr:  VectorArrangement4S,
+		},
 	}
 
 	for _, tt := range tests {
@@ -2178,6 +2292,281 @@ func TestAssemblerImpl_encodeTwoVectorRegistersToVectorRegister(t *testing.T) {
 			},
 			exp: []byte{0x9e, 0xf4, 0x6b, 0x4e},
 		},
+		{
+			name: "mul v30.4s, v4.4s, v11.4s",
+			n: &NodeImpl{
+				Instruction:       VMUL,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement4S,
+			},
+			exp: []byte{0x9e, 0x9c, 0xab, 0x4e},
+		},
+		{
+			name: "mul v30.16b, v4.16b, v11.16b",
+			n: &NodeImpl{
+				Instruction:       VMUL,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement16B,
+			},
+			exp: []byte{0x9e, 0x9c, 0x2b, 0x4e},
+		},
+		{
+			name: "sqadd v30.2d, v4.2d, v11.2d",
+			n: &NodeImpl{
+				Instruction:       VSQADD,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement2D,
+			},
+			exp: []byte{0x9e, 0xc, 0xeb, 0x4e},
+		},
+		{
+			name: "sqadd v30.8h, v4.8h, v11.8h",
+			n: &NodeImpl{
+				Instruction:       VSQADD,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8H,
+			},
+			exp: []byte{0x9e, 0xc, 0x6b, 0x4e},
+		},
+		{
+			name: "uqadd v30.4s, v4.4s, v11.4s",
+			n: &NodeImpl{
+				Instruction:       VUQADD,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement4S,
+			},
+			exp: []byte{0x9e, 0xc, 0xab, 0x6e},
+		},
+		{
+			name: "uqadd v30.8h, v4.8h, v11.8h",
+			n: &NodeImpl{
+				Instruction:       VUQADD,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8H,
+			},
+			exp: []byte{0x9e, 0xc, 0x6b, 0x6e},
+		},
+		{
+			name: "smax v30.4s, v4.4s, v11.4s",
+			n: &NodeImpl{
+				Instruction:       SMAX,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement4S,
+			},
+			exp: []byte{0x9e, 0x64, 0xab, 0x4e},
+		},
+		{
+			name: "smax v30.8h, v4.8h, v11.8h",
+			n: &NodeImpl{
+				Instruction:       SMAX,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8H,
+			},
+			exp: []byte{0x9e, 0x64, 0x6b, 0x4e},
+		},
+		{
+			name: "smin v30.16b, v4.16b, v11.16b",
+			n: &NodeImpl{
+				Instruction:       SMIN,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement16B,
+			},
+			exp: []byte{0x9e, 0x6c, 0x2b, 0x4e},
+		},
+		{
+			name: "smin v30.4s, v4.4s, v11.4s",
+			n: &NodeImpl{
+				Instruction:       SMIN,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement4S,
+			},
+			exp: []byte{0x9e, 0x6c, 0xab, 0x4e},
+		},
+		{
+			name: "umin v30.16b, v4.16b, v11.16b",
+			n: &NodeImpl{
+				Instruction:       UMIN,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement16B,
+			},
+			exp: []byte{0x9e, 0x6c, 0x2b, 0x6e},
+		},
+		{
+			name: "umin v30.4s, v4.4s, v11.4s",
+			n: &NodeImpl{
+				Instruction:       UMIN,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement4S,
+			},
+			exp: []byte{0x9e, 0x6c, 0xab, 0x6e},
+		},
+		{
+			name: "umax v30.4s, v4.4s, v11.4s",
+			n: &NodeImpl{
+				Instruction:       UMAX,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement4S,
+			},
+			exp: []byte{0x9e, 0x64, 0xab, 0x6e},
+		},
+		{
+			name: "umax v30.8h, v4.8h, v11.8h",
+			n: &NodeImpl{
+				Instruction:       UMAX,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8H,
+			},
+			exp: []byte{0x9e, 0x64, 0x6b, 0x6e},
+		},
+		{
+			name: "umax v30.8h, v4.8h, v11.8h",
+			n: &NodeImpl{
+				Instruction:       URHADD,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8H,
+			},
+			exp: []byte{0x9e, 0x14, 0x6b, 0x6e},
+		},
+		{
+			name: "umax v30.16b, v4.16b, v11.16b",
+			n: &NodeImpl{
+				Instruction:       URHADD,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement16B,
+			},
+			exp: []byte{0x9e, 0x14, 0x2b, 0x6e},
+		},
+		{
+			name: "sqsub v30.16b, v4.16b, v11.16b",
+			n: &NodeImpl{
+				Instruction:       VSQSUB,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement16B,
+			},
+			exp: []byte{0x9e, 0x2c, 0x2b, 0x4e},
+		},
+		{
+			name: "sqsub v308hb, v4.8h, v11.8h",
+			n: &NodeImpl{
+				Instruction:       VSQSUB,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8H,
+			},
+			exp: []byte{0x9e, 0x2c, 0x6b, 0x4e},
+		},
+		{
+			name: "uqsub v30.16b, v4.16b, v11.16b",
+			n: &NodeImpl{
+				Instruction:       VUQSUB,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement16B,
+			},
+			exp: []byte{0x9e, 0x2c, 0x2b, 0x6e},
+		},
+		{
+			name: "uqsub v308hb, v4.8h, v11.8h",
+			n: &NodeImpl{
+				Instruction:       VUQSUB,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8H,
+			},
+			exp: []byte{0x9e, 0x2c, 0x6b, 0x6e},
+		},
+		{
+			name: "umlal v0.2d, v6.2s, v2.2s",
+			n: &NodeImpl{
+				Instruction:       VUMLAL,
+				DstReg:            RegV0,
+				SrcReg:            RegV2,
+				SrcReg2:           RegV6,
+				VectorArrangement: VectorArrangement2S,
+			},
+			exp: []byte{0xc0, 0x80, 0xa2, 0x2e},
+		},
+		{
+			name: "umlal v0.4s, v6.4h, v2.4h",
+			n: &NodeImpl{
+				Instruction:       VUMLAL,
+				DstReg:            RegV0,
+				SrcReg:            RegV2,
+				SrcReg2:           RegV6,
+				VectorArrangement: VectorArrangement4H,
+			},
+			exp: []byte{0xc0, 0x80, 0x62, 0x2e},
+		},
+		{
+			name: "umlal v0.8h, v6.8b, v2.8b",
+			n: &NodeImpl{
+				Instruction:       VUMLAL,
+				DstReg:            RegV0,
+				SrcReg:            RegV2,
+				SrcReg2:           RegV6,
+				VectorArrangement: VectorArrangement8B,
+			},
+			exp: []byte{0xc0, 0x80, 0x22, 0x2e},
+		},
+		{
+			name: "bit v30.16b, v4.16b, v11.16b",
+			n: &NodeImpl{
+				Instruction:       VBIT,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement16B,
+			},
+			exp: []byte{0x9e, 0x1c, 0xab, 0x6e},
+		},
+		{
+			name: "bit v30.8b, v4.8b, v11.8b",
+			n: &NodeImpl{
+				Instruction:       VBIT,
+				DstReg:            RegV30,
+				SrcReg:            RegV11,
+				SrcReg2:           RegV4,
+				VectorArrangement: VectorArrangement8B,
+			},
+			exp: []byte{0x9e, 0x1c, 0xab, 0x2e},
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/internal/engine/compiler/compiler_vec_test.go b/internal/engine/compiler/compiler_vec_test.go
index 3ff2d34d..e4ad2130 100644
--- a/internal/engine/compiler/compiler_vec_test.go
+++ b/internal/engine/compiler/compiler_vec_test.go
@@ -3385,11 +3385,6 @@ func TestCompiler_compileV128Cmp(t *testing.T) {
 }
 
 func TestCompiler_compileV128AvgrU(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name        string
 		shape       wazeroir.Shape
@@ -3540,11 +3535,6 @@ func TestCompiler_compileV128Sqrt(t *testing.T) {
 }
 
 func TestCompiler_compileV128Mul(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name        string
 		shape       wazeroir.Shape
@@ -3635,11 +3625,6 @@ func TestCompiler_compileV128Mul(t *testing.T) {
 }
 
 func TestCompiler_compileV128Neg(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name   string
 		shape  wazeroir.Shape
@@ -3737,11 +3722,6 @@ func TestCompiler_compileV128Neg(t *testing.T) {
 }
 
 func TestCompiler_compileV128Abs(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name   string
 		shape  wazeroir.Shape
@@ -3915,10 +3895,6 @@ func TestCompiler_compileV128Div(t *testing.T) {
 }
 
 func TestCompiler_compileV128Min(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
 
 	tests := []struct {
 		name        string
@@ -4109,11 +4085,6 @@ func TestCompiler_compileV128Min(t *testing.T) {
 }
 
 func TestCompiler_compileV128Max(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name        string
 		shape       wazeroir.Shape
@@ -4317,11 +4288,6 @@ func TestCompiler_compileV128Max(t *testing.T) {
 }
 
 func TestCompiler_compileV128AddSat(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name        string
 		shape       wazeroir.Shape
@@ -4434,11 +4400,6 @@ func TestCompiler_compileV128AddSat(t *testing.T) {
 }
 
 func TestCompiler_compileV128SubSat(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name        string
 		shape       wazeroir.Shape
@@ -4551,11 +4512,6 @@ func TestCompiler_compileV128SubSat(t *testing.T) {
 }
 
 func TestCompiler_compileV128Popcnt(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO: implement on amd64.
-		t.Skip()
-	}
-
 	tests := []struct {
 		name   string
 		v, exp [16]byte
diff --git a/internal/integration_test/asm/arm64_debug/debug_assembler.go b/internal/integration_test/asm/arm64_debug/debug_assembler.go
index 24c772e9..1a891276 100644
--- a/internal/integration_test/asm/arm64_debug/debug_assembler.go
+++ b/internal/integration_test/asm/arm64_debug/debug_assembler.go
@@ -232,24 +232,6 @@ func (ta *testAssembler) CompileLeftShiftedRegisterToRegister(
 	ta.a.CompileLeftShiftedRegisterToRegister(instruction, shiftedSourceReg, shiftNum, srcReg, dstReg)
 }
 
-func (ta *testAssembler) CompileSIMDByteToSIMDByte(instruction asm.Instruction, srcReg, dstReg asm.Register) {
-	ta.goasm.CompileSIMDByteToSIMDByte(instruction, srcReg, dstReg)
-	ta.a.CompileSIMDByteToSIMDByte(instruction, srcReg, dstReg)
-}
-
-func (ta *testAssembler) CompileTwoSIMDBytesToSIMDByteRegister(
-	instruction asm.Instruction,
-	srcReg1, srcReg2, dstReg asm.Register,
-) {
-	ta.goasm.CompileTwoSIMDBytesToSIMDByteRegister(instruction, srcReg1, srcReg2, dstReg)
-	ta.a.CompileTwoSIMDBytesToSIMDByteRegister(instruction, srcReg1, srcReg2, dstReg)
-}
-
-func (ta *testAssembler) CompileSIMDByteToRegister(instruction asm.Instruction, srcReg, dstReg asm.Register) {
-	ta.goasm.CompileSIMDByteToRegister(instruction, srcReg, dstReg)
-	ta.a.CompileSIMDByteToRegister(instruction, srcReg, dstReg)
-}
-
 func (ta *testAssembler) CompileConditionalRegisterSet(cond asm.ConditionalRegisterState, dstReg asm.Register) {
 	ta.goasm.CompileConditionalRegisterSet(cond, dstReg)
 	ta.a.CompileConditionalRegisterSet(cond, dstReg)
diff --git a/internal/integration_test/asm/arm64_debug/golang_asm.go b/internal/integration_test/asm/arm64_debug/golang_asm.go
index 50e63b2d..03fa844d 100644
--- a/internal/integration_test/asm/arm64_debug/golang_asm.go
+++ b/internal/integration_test/asm/arm64_debug/golang_asm.go
@@ -282,56 +282,6 @@ func simdRegisterForScalarFloatRegister(freg int16) int16 {
 	return freg + (arm64.REG_F31 - arm64.REG_F0) + 1
 }
 
-// CompileTwoSIMDBytesToSIMDByteRegister implements the same method as documented on arm64.Assembler.
-func (a *assemblerGoAsmImpl) CompileTwoSIMDBytesToSIMDByteRegister(instruction asm.Instruction, srcReg1, srcReg2, dstReg asm.Register) {
-	src1FloatReg, src2FloatReg, dstFloatReg := castAsGolangAsmRegister[srcReg1], castAsGolangAsmRegister[srcReg2], castAsGolangAsmRegister[dstReg]
-	src1VReg, src2VReg, dstVReg := simdRegisterForScalarFloatRegister(src1FloatReg), simdRegisterForScalarFloatRegister(src2FloatReg), simdRegisterForScalarFloatRegister(dstFloatReg)
-
-	// * https://github.com/twitchyliquid64/golang-asm/blob/v0.15.1/obj/link.go#L172-L177
-	// * https://github.com/golang/go/blob/739328c694d5e608faa66d17192f0a59f6e01d04/src/cmd/compile/internal/arm64/ssa.go#L972
-	inst := a.NewProg()
-	inst.As = castAsGolangAsmInstruction[instruction]
-	inst.To.Type = obj.TYPE_REG
-	inst.To.Reg = dstVReg&31 + arm64.REG_ARNG + (arm64.ARNG_8B&15)<<5
-	inst.From.Type = obj.TYPE_REG
-	inst.From.Reg = src1VReg&31 + arm64.REG_ARNG + (arm64.ARNG_8B&15)<<5
-	inst.Reg = src2VReg&31 + arm64.REG_ARNG + (arm64.ARNG_8B&15)<<5
-	a.AddInstruction(inst)
-
-}
-
-// CompileSIMDByteToSIMDByte implements the same method as documented on arm64.Assembler.
-func (a *assemblerGoAsmImpl) CompileSIMDByteToSIMDByte(instruction asm.Instruction, srcReg, dstReg asm.Register) {
-	srcFloatReg, dstFloatReg := castAsGolangAsmRegister[srcReg], castAsGolangAsmRegister[dstReg]
-	srcVReg, dstVReg := simdRegisterForScalarFloatRegister(srcFloatReg), simdRegisterForScalarFloatRegister(dstFloatReg)
-
-	// * https://github.com/twitchyliquid64/golang-asm/blob/v0.15.1/obj/link.go#L172-L177
-	// * https://github.com/golang/go/blob/739328c694d5e608faa66d17192f0a59f6e01d04/src/cmd/compile/internal/arm64/ssa.go#L972
-	inst := a.NewProg()
-	inst.As = castAsGolangAsmInstruction[instruction]
-	inst.To.Type = obj.TYPE_REG
-	inst.To.Reg = dstVReg&31 + arm64.REG_ARNG + (arm64.ARNG_8B&15)<<5
-	inst.From.Type = obj.TYPE_REG
-	inst.From.Reg = srcVReg&31 + arm64.REG_ARNG + (arm64.ARNG_8B&15)<<5
-	a.AddInstruction(inst)
-}
-
-// CompileSIMDByteToRegister implements the same method as documented on arm64.Assembler.
-func (a *assemblerGoAsmImpl) CompileSIMDByteToRegister(instruction asm.Instruction, srcReg, dstReg asm.Register) {
-	srcFloatReg, dstFlaotReg := castAsGolangAsmRegister[srcReg], castAsGolangAsmRegister[dstReg]
-	srcVReg, dstVReg := simdRegisterForScalarFloatRegister(srcFloatReg), simdRegisterForScalarFloatRegister(dstFlaotReg)
-
-	// * https://github.com/twitchyliquid64/golang-asm/blob/v0.15.1/obj/link.go#L172-L177
-	// * https://github.com/golang/go/blob/739328c694d5e608faa66d17192f0a59f6e01d04/src/cmd/compile/internal/arm64/ssa.go#L972
-	inst := a.NewProg()
-	inst.As = castAsGolangAsmInstruction[instruction]
-	inst.To.Type = obj.TYPE_REG
-	inst.To.Reg = dstVReg
-	inst.From.Type = obj.TYPE_REG
-	inst.From.Reg = srcVReg&31 + arm64.REG_ARNG + (arm64.ARNG_8B&15)<<5
-	a.AddInstruction(inst)
-}
-
 // CompileMemoryToVectorRegister implements the same method as documented on arm64.Assembler.
 func (a *assemblerGoAsmImpl) CompileMemoryToVectorRegister(
 	_ asm.Instruction, _ asm.Register, _ asm.ConstantValue, _ asm.Register, _ asm_arm64.VectorArrangement,
@@ -713,7 +663,7 @@ var castAsGolangAsmInstruction = [...]obj.As{
 	asm_arm64.UDIVW:    arm64.AUDIVW,
 	asm_arm64.VBIT:     arm64.AVBIT,
 	asm_arm64.VCNT:     arm64.AVCNT,
-	asm_arm64.VUADDLV:  arm64.AVUADDLV,
+	asm_arm64.UADDLV:   arm64.AVUADDLV,
 	asm_arm64.VMOV:     arm64.AVMOV,
 	asm_arm64.VADD:     arm64.AVADD,
 	asm_arm64.VSUB:     arm64.AVSUB,
diff --git a/internal/integration_test/asm/arm64_debug/impl_test.go b/internal/integration_test/asm/arm64_debug/impl_test.go
index bae42276..c9652400 100644
--- a/internal/integration_test/asm/arm64_debug/impl_test.go
+++ b/internal/integration_test/asm/arm64_debug/impl_test.go
@@ -765,96 +765,6 @@ func TestAssemblerImpl_EncodeConstToRegister(t *testing.T) {
 	}
 }
 
-func TestAssemblerImpl_EncodeSIMDByteToSIMDByte(t *testing.T) {
-	t.Run("error", func(t *testing.T) {
-		tests := []struct {
-			n      *arm64.NodeImpl
-			expErr string
-		}{
-			{
-				n:      &arm64.NodeImpl{Instruction: arm64.ADR, Types: arm64.OperandTypesSIMDByteToSIMDByte},
-				expErr: "ADR is unsupported for from:simd-byte,to:simd-byte type",
-			},
-		}
-
-		for _, tt := range tests {
-			tc := tt
-			a := arm64.NewAssemblerImpl(asm.NilRegister)
-			err := a.EncodeSIMDByteToSIMDByte(tc.n)
-			require.EqualError(t, err, tc.expErr)
-		}
-	})
-
-	const inst = arm64.VCNT
-	t.Run(arm64.InstructionName(inst), func(t *testing.T) {
-		floatRegs := []asm.Register{arm64.RegV0, arm64.RegV10, arm64.RegV21, arm64.RegV31}
-		for _, src := range floatRegs {
-			for _, dst := range floatRegs {
-				src, dst := src, dst
-				t.Run(fmt.Sprintf("src=%s,dst=%s", arm64.RegisterName(src), arm64.RegisterName(dst)), func(t *testing.T) {
-					goasm := newGoasmAssembler(t, asm.NilRegister)
-					goasm.CompileSIMDByteToSIMDByte(inst, src, dst)
-					expected, err := goasm.Assemble()
-					require.NoError(t, err)
-
-					a := arm64.NewAssemblerImpl(arm64.RegR27)
-					err = a.EncodeSIMDByteToSIMDByte(&arm64.NodeImpl{Instruction: inst, SrcReg: src, DstReg: dst})
-					require.NoError(t, err)
-
-					actual := a.Bytes()
-					require.Equal(t, expected, actual)
-
-				})
-			}
-		}
-	})
-}
-
-func TestAssemblerImpl_EncodeSIMDByteToRegister(t *testing.T) {
-	t.Run("error", func(t *testing.T) {
-		tests := []struct {
-			n      *arm64.NodeImpl
-			expErr string
-		}{
-			{
-				n:      &arm64.NodeImpl{Instruction: arm64.ADR, Types: arm64.OperandTypesSIMDByteToRegister},
-				expErr: "ADR is unsupported for from:simd-byte,to:register type",
-			},
-		}
-
-		for _, tt := range tests {
-			tc := tt
-			a := arm64.NewAssemblerImpl(asm.NilRegister)
-			err := a.EncodeSIMDByteToRegister(tc.n)
-			require.EqualError(t, err, tc.expErr)
-		}
-	})
-
-	const inst = arm64.VUADDLV
-	t.Run(arm64.InstructionName(inst), func(t *testing.T) {
-		floatRegs := []asm.Register{arm64.RegV0, arm64.RegV10, arm64.RegV21, arm64.RegV31}
-		for _, src := range floatRegs {
-			for _, dst := range floatRegs {
-				src, dst := src, dst
-				t.Run(fmt.Sprintf("src=%s,dst=%s", arm64.RegisterName(src), arm64.RegisterName(dst)), func(t *testing.T) {
-					goasm := newGoasmAssembler(t, asm.NilRegister)
-					goasm.CompileSIMDByteToRegister(inst, src, dst)
-					expected, err := goasm.Assemble()
-					require.NoError(t, err)
-
-					a := arm64.NewAssemblerImpl(arm64.RegR27)
-					err = a.EncodeSIMDByteToRegister(&arm64.NodeImpl{Instruction: inst, SrcReg: src, DstReg: dst})
-					require.NoError(t, err)
-
-					actual := a.Bytes()
-					require.Equal(t, expected, actual)
-
-				})
-			}
-		}
-	})
-}
-
 func TestAssemblerImpl_EncodeRegisterToMemory(t *testing.T) {
 	t.Run("error", func(t *testing.T) {
 		tests := []struct {
@@ -1230,51 +1140,6 @@ func TestAssemblerImpl_multipleLargeOffest(t *testing.T) {
 	require.Equal(t, expected, actual)
 }
 
-func TestAssemblerImpl_EncodeTwoSIMDBytesToSIMDByteRegister(t *testing.T) {
-	t.Run("error", func(t *testing.T) {
-		tests := []struct {
-			n      *arm64.NodeImpl
-			expErr string
-		}{
-			{
-				n:      &arm64.NodeImpl{Instruction: arm64.B, Types: arm64.OperandTypesTwoSIMDBytesToSIMDByteRegister},
-				expErr: "B is unsupported for from:two-simd-bytes,to:simd-byte type",
-			},
-		}
-
-		for _, tt := range tests {
-			tc := tt
-			a := arm64.NewAssemblerImpl(asm.NilRegister)
-			err := a.EncodeTwoSIMDBytesToSIMDByteRegister(tc.n)
-			require.EqualError(t, err, tc.expErr)
-		}
-	})
-
-	for _, inst := range []asm.Instruction{arm64.VBIT} {
-		regs := []asm.Register{arm64.RegV0, arm64.RegV10, arm64.RegV30}
-		for _, src1 := range regs {
-			for _, src2 := range regs {
-				for _, dst := range regs {
-					n := &arm64.NodeImpl{Instruction: inst, SrcReg: src1, SrcReg2: src2, DstReg: dst,
-						Types: arm64.OperandTypesTwoSIMDBytesToSIMDByteRegister}
-					t.Run(n.String(), func(t *testing.T) {
-						goasm := newGoasmAssembler(t, asm.NilRegister)
-						goasm.CompileTwoSIMDBytesToSIMDByteRegister(n.Instruction, n.SrcReg, n.SrcReg2, n.DstReg)
-						expected, err := goasm.Assemble()
-						require.NoError(t, err)
-
-						a := arm64.NewAssemblerImpl(arm64.RegR27)
-						err = a.EncodeTwoSIMDBytesToSIMDByteRegister(n)
-						require.NoError(t, err)
-						actual := a.Bytes()
-						require.Equal(t, expected, actual)
-					})
-				}
-			}
-		}
-	}
-}
-
 func conditionalRegisterToState(r asm.Register) asm.ConditionalRegisterState {
 	switch r {
 	case arm64.RegCondEQ:
diff --git a/internal/integration_test/spectest/v2/spec_test.go b/internal/integration_test/spectest/v2/spec_test.go
index 808a538a..21eef59a 100644
--- a/internal/integration_test/spectest/v2/spec_test.go
+++ b/internal/integration_test/spectest/v2/spec_test.go
@@ -26,10 +26,7 @@ func TestCompiler(t *testing.T) {
 
 	spectest.Run(t, testcases, compiler.NewEngine, enabledFeatures, func(jsonname string) bool {
 		switch path.Base(jsonname) {
-		case "simd_i16x8_arith.json", "simd_i64x2_arith.json", "simd_i32x4_arith.json", "simd_i8x16_arith.json",
-			"simd_i16x8_sat_arith.json", "simd_i8x16_sat_arith.json",
-			"simd_i16x8_arith2.json", "simd_i8x16_arith2.json", "simd_i32x4_arith2.json", "simd_i64x2_arith2.json",
-			"simd_f64x2_pmin_pmax.json", "simd_f32x4_pmin_pmax.json", "simd_int_to_int_extend.json",
+		case "simd_f64x2_pmin_pmax.json", "simd_f32x4_pmin_pmax.json", "simd_int_to_int_extend.json",
 			"simd_i64x2_extmul_i32x4.json", "simd_i32x4_extmul_i16x8.json", "simd_i16x8_extmul_i8x16.json",
 			"simd_i16x8_q15mulr_sat_s.json", "simd_i16x8_extadd_pairwise_i8x16.json", "simd_i32x4_extadd_pairwise_i16x8.json",
 			"simd_i32x4_dot_i16x8.json", "simd_i32x4_trunc_sat_f32x4.json",