Repository: tetratelabs/wazero
Pull request #1919 (2024-01-15 08:20:26)

threads: add encoding of arm64 instructions needed for threads


Patch:
diff --git a/internal/asm/arm64/assembler.go b/internal/asm/arm64/assembler.go
index 628350d4..b83c8b99 100644
--- a/internal/asm/arm64/assembler.go
+++ b/internal/asm/arm64/assembler.go
@@ -12,10 +12,18 @@ type Assembler interface {
 	// specified as `srcBaseReg + srcOffsetReg` and dst is the register `dstReg`.
 	CompileMemoryWithRegisterOffsetToRegister(instruction asm.Instruction, srcBaseReg, srcOffsetReg, dstReg asm.Register)
 
+	// CompileMemoryWithRegisterSourceToRegister adds an instruction where source operand is the memory address
+	// and dst is the register `dstReg`.
+	CompileMemoryWithRegisterSourceToRegister(instruction asm.Instruction, srcReg, dstReg asm.Register)
+
 	// CompileRegisterToMemoryWithRegisterOffset adds an instruction where source operand is the register `srcReg`,
 	// and the destination is the memory address specified as `dstBaseReg + dstOffsetReg`
 	CompileRegisterToMemoryWithRegisterOffset(instruction asm.Instruction, srcReg, dstBaseReg, dstOffsetReg asm.Register)
 
+	// CompileRegisterToMemoryWithRegisterDest adds an instruction where source operand is the register `srcReg`,
+	// and the destination is the memory address specified as `dstReg`
+	CompileRegisterToMemoryWithRegisterDest(instruction asm.Instruction, srcReg, dstReg asm.Register)
+
 	// CompileTwoRegistersToRegister adds an instruction where source operands consists of two registers `src1` and `src2`,
 	// and the destination is the register `dst`.
 	CompileTwoRegistersToRegister(instruction asm.Instruction, src1, src2, dst asm.Register)
diff --git a/internal/asm/arm64/consts.go b/internal/asm/arm64/consts.go
index 47ed3cc2..3a9e3cf2 100644
--- a/internal/asm/arm64/consts.go
+++ b/internal/asm/arm64/consts.go
@@ -469,6 +469,10 @@ const (
 	ANDIMM64
 	// ANDW is the AND instruction, in 64-bit mode. https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/AND--register-
 	ANDW
+	// ANDS is the ANDS instruction in 64-bit mode https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ANDS--immediate---Bitwise-AND--immediate---setting-flags-?lang=en
+	ANDS
+	// ANDSW is the ANDS instruction in 32-bit mode https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ANDS--immediate---Bitwise-AND--immediate---setting-flags-?lang=en
+	ANDSW
 	// ASR is the ASR instruction. https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/ASR--register-
 	ASR
 	// ASRW is the ASR instruction, in 64-bit mode. https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/ASR--register-
@@ -669,6 +673,10 @@ const (
 	ORR
 	// ORRW is the ORR instruction, in 64-bit mode. https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/ORR--shifted-register-
 	ORRW
+	// ORN is the ORN instruction. https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/ORN--shifted-register---Bitwise-OR-NOT--shifted-register--?lang=en#ORN_32_log_shift
+	ORN
+	// ORNW is the ORN instruction, in 32-bit mode. https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/ORN--shifted-register---Bitwise-OR-NOT--shifted-register--?lang=en#ORN_32_log_shift
+	ORNW
 	// RBIT is the RBIT instruction. https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/RBIT
 	RBIT
 	// RBITW is the RBIT instruction, in 64-bit mode. https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/RBIT
@@ -931,6 +939,87 @@ const (
 	// FCVTN is the FCVTN instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/FCVTN--FCVTN2--Floating-point-Convert-to-lower-precision-Narrow--vector--?lang=en
 	FCVTN
 
+	// LDARD is the LDAR instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDAR--Load-Acquire-Register-
+	LDARD
+	// LDARD is the LDAR instruction in 32-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDAR--Load-Acquire-Register-
+	LDARW
+	// LDARH is the LDARH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDARH--Load-Acquire-Register-Halfword-
+	LDARH
+	// LDARB is the LDARB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDARB--Load-Acquire-Register-Byte-
+	LDARB
+
+	// STLRD is the STLR instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/STLR--Store-Release-Register-
+	STLRD
+	// STLRW is the STLR instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/STLR--Store-Release-Register-
+	STLRW
+	// STLRH is the STLRH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/STLRH--Store-Release-Register-Halfword-
+	STLRH
+	// STLRB is the STLRB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/STLRB--Store-Release-Register-Byte-
+	STLRB
+
+	// Note, there is no LDSUB type of instruction, so sub needs to be implemented by first negating the second parameter.
+
+	// LDADDALD is the LDADDAL instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDADD--LDADDA--LDADDAL--LDADDL--Atomic-add-on-word-or-doubleword-in-memory-
+	LDADDALD
+	// LDADDALW is the LDADDAL instruction in 32-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDADD--LDADDA--LDADDAL--LDADDL--Atomic-add-on-word-or-doubleword-in-memory-
+	LDADDALW
+	// LDADDALH is the LDADDALH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDADDH--LDADDAH--LDADDALH--LDADDLH--Atomic-add-on-halfword-in-memory-
+	LDADDALH
+	// LDADDALB is the LDADDALB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDADDB--LDADDAB--LDADDALB--LDADDLB--Atomic-add-on-byte-in-memory-
+	LDADDALB
+
+	// Note, arm's CLR is equivalent to AND NOT
+
+	// LDCLRALD is the LDCLRAL instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDCLR--LDCLRA--LDCLRAL--LDCLRL--Atomic-bit-clear-on-word-or-doubleword-in-memory-
+	LDCLRALD
+	// LDCLRALW is the LDCLRAL instruction in 32-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDCLR--LDCLRA--LDCLRAL--LDCLRL--Atomic-bit-clear-on-word-or-doubleword-in-memory-
+	LDCLRALW
+	// LDCLRALH is the LDCLRALH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDCLRH--LDCLRAH--LDCLRALH--LDCLRLH--Atomic-bit-clear-on-halfword-in-memory-
+	LDCLRALH
+	// LDCLRALB is the LDCLRALB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDCLRB--LDCLRAB--LDCLRALB--LDCLRLB--Atomic-bit-clear-on-byte-in-memory-
+	LDCLRALB
+
+	// Note, arm's SET is equivalent to OR
+
+	// LDSETALD is the LDSETAL instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDSET--LDSETA--LDSETAL--LDSETL--Atomic-bit-set-on-word-or-doubleword-in-memory-
+	LDSETALD
+	// LDSETALW is the LDSETAL instruction in 32-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDSET--LDSETA--LDSETAL--LDSETL--Atomic-bit-set-on-word-or-doubleword-in-memory-
+	LDSETALW
+	// LDSETALH is the LDSETALH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDSETH--LDSETAH--LDSETALH--LDSETLH--Atomic-bit-set-on-halfword-in-memory-
+	LDSETALH
+	// LDSETALB is the LDSETALB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDSETB--LDSETAB--LDSETALB--LDSETLB--Atomic-bit-set-on-byte-in-memory-
+	LDSETALB
+
+	// LDEORALD is the LDEORAL instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDEOR--LDEORA--LDEORAL--LDEORL--Atomic-bitwise-exclusive-OR-on-word-or-doubleword-in-memory-
+	LDEORALD
+	// LDEORALW is the LDEORAL instruction in 32-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDEOR--LDEORA--LDEORAL--LDEORL--Atomic-bitwise-exclusive-OR-on-word-or-doubleword-in-memory-
+	LDEORALW
+	// LDEORALH is the LDEORALH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDEORH--LDEORAH--LDEORALH--LDEORLH--Atomic-bitwise-exclusive-OR-on-halfword-in-memory-
+	LDEORALH
+	// LDEORALB is the LDEORALB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDEORB--LDEORAB--LDEORALB--LDEORLB--Atomic-bitwise-exclusive-OR-on-byte-in-memory-
+	LDEORALB
+
+	// SWPALD is the SWPAL instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/SWP--SWPA--SWPAL--SWPL--Swap-word-or-doubleword-in-memory-
+	SWPALD
+	// SWPALW is the SWPAL instruction in 32-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/SWP--SWPA--SWPAL--SWPL--Swap-word-or-doubleword-in-memory-
+	SWPALW
+	// SWPALH is the SWPALH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/SWPH--SWPAH--SWPALH--SWPLH--Swap-halfword-in-memory-
+	SWPALH
+	// SWPALB is the SWPALB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/SWPB--SWPAB--SWPALB--SWPLB--Swap-byte-in-memory-
+	SWPALB
+
+	// CASALD is the CASAL instruction in 64-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/CAS--CASA--CASAL--CASL--Compare-and-swap-word-or-doubleword-in-memory-
+	CASALD
+	// CASALW is the CASAL instruction in 32-bit mode https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/CAS--CASA--CASAL--CASL--Compare-and-swap-word-or-doubleword-in-memory-
+	CASALW
+	// CASALH is the CASALH instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/CASH--CASA--CASALH--CASLH--Compare-and-swap-halfword-in-memory-
+	CASALH
+	// CASALB is the CASALB instruction https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/CASB--CASAB--CASALB--CASLB--Compare-and-swap-byte-in-memory-
+	CASALB
+
+	// DMB is the DMB instruction for inner-sharable domain https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/DMB--Data-Memory-Barrier-
+	DMB
+
 	// UDF is the UDF instruction https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/UDF--Permanently-Undefined-?lang=en
 	UDF
 
@@ -1043,6 +1132,10 @@ func InstructionName(i asm.Instruction) string {
 		return "ANDIMM64"
 	case ANDW:
 		return "ANDW"
+	case ANDS:
+		return "ANDS"
+	case ANDSW:
+		return "ANDSW"
 	case ASR:
 		return "ASR"
 	case ASRW:
@@ -1225,6 +1318,10 @@ func InstructionName(i asm.Instruction) string {
 		return "ORR"
 	case ORRW:
 		return "ORRW"
+	case ORN:
+		return "ORN"
+	case ORNW:
+		return "ORNW"
 	case RBIT:
 		return "RBIT"
 	case RBITW:
@@ -1457,6 +1554,72 @@ func InstructionName(i asm.Instruction) string {
 		return "FCVTL"
 	case FCVTN:
 		return "FCVTN"
+	case LDARD:
+		return "LDARD"
+	case LDARW:
+		return "LDARW"
+	case LDARH:
+		return "LDARH"
+	case LDARB:
+		return "LDARB"
+	case STLRD:
+		return "STLRD"
+	case STLRW:
+		return "STLRW"
+	case STLRH:
+		return "STLRH"
+	case STLRB:
+		return "STLRB"
+	case LDADDALD:
+		return "LDADDALD"
+	case LDADDALW:
+		return "LDADDALW"
+	case LDADDALH:
+		return "LDADDALH"
+	case LDADDALB:
+		return "LDADDALB"
+	case LDCLRALD:
+		return "LDCLRALD"
+	case LDCLRALW:
+		return "LDCLRALW"
+	case LDCLRALH:
+		return "LDCLRALH"
+	case LDCLRALB:
+		return "LDCLRALB"
+	case LDSETALD:
+		return "LDSETALD"
+	case LDSETALW:
+		return "LDSETALW"
+	case LDSETALH:
+		return "LDSETALH"
+	case LDSETALB:
+		return "LDSETALB"
+	case LDEORALD:
+		return "LDEORALD"
+	case LDEORALW:
+		return "LDEORALW"
+	case LDEORALH:
+		return "LDEORALH"
+	case LDEORALB:
+		return "LDEORALB"
+	case SWPALD:
+		return "SWPALD"
+	case SWPALW:
+		return "SWPALW"
+	case SWPALH:
+		return "SWPALH"
+	case SWPALB:
+		return "SWPALB"
+	case CASALD:
+		return "CASALD"
+	case CASALW:
+		return "CASALW"
+	case CASALH:
+		return "CASALH"
+	case CASALB:
+		return "CASALB"
+	case DMB:
+		return "DMB"
 	case FSTRD:
 		return "FSTRD"
 	case FSTRS:
diff --git a/internal/asm/arm64/impl.go b/internal/asm/arm64/impl.go
index 00bc0d99..eacc2ecd 100644
--- a/internal/asm/arm64/impl.go
+++ b/internal/asm/arm64/impl.go
@@ -544,6 +544,13 @@ func (a *AssemblerImpl) CompileMemoryWithRegisterOffsetToRegister(
 	n.srcReg2 = srcOffsetReg
 }
 
+// CompileMemoryWithRegisterSourceToRegister implements Assembler.CompileMemoryWithRegisterSourceToRegister
+func (a *AssemblerImpl) CompileMemoryWithRegisterSourceToRegister(instruction asm.Instruction, srcReg, dstReg asm.Register) {
+	n := a.newNode(instruction, operandTypesMemoryToRegister)
+	n.dstReg = dstReg
+	n.srcReg = srcReg
+}
+
 // CompileRegisterToMemoryWithRegisterOffset implements Assembler.CompileRegisterToMemoryWithRegisterOffset
 func (a *AssemblerImpl) CompileRegisterToMemoryWithRegisterOffset(
 	instruction asm.Instruction,
@@ -555,6 +562,13 @@ func (a *AssemblerImpl) CompileRegisterToMemoryWithRegisterOffset(
 	n.dstReg2 = dstOffsetReg
 }
 
+// CompileRegisterToMemoryWithRegisterDest implements Assembler.CompileRegisterToMemoryWithRegisterDest
+func (a *AssemblerImpl) CompileRegisterToMemoryWithRegisterDest(instruction asm.Instruction, srcReg, dstReg asm.Register) {
+	n := a.newNode(instruction, operandTypesRegisterToMemory)
+	n.srcReg = srcReg
+	n.dstReg = dstReg
+}
+
 // CompileTwoRegistersToRegister implements Assembler.CompileTwoRegistersToRegister
 func (a *AssemblerImpl) CompileTwoRegistersToRegister(instruction asm.Instruction, src1, src2, dst asm.Register) {
 	n := a.newNode(instruction, operandTypesTwoRegistersToRegister)
@@ -765,6 +779,15 @@ func (a *AssemblerImpl) encodeNoneToNone(buf asm.Buffer, n *nodeImpl) error {
 	case UDF:
 		buf.Append4Bytes(0, 0, 0, 0)
 		return nil
+	case DMB:
+		// InnerSharable, All
+		buf.Append4Bytes(
+			0b10111111,
+			0b00111011,
+			0b00000011,
+			0b11010101,
+		)
+		return nil
 	case NOP:
 		return nil
 	default:
@@ -1456,11 +1479,11 @@ func (a *AssemblerImpl) encodeLeftShiftedRegisterToRegister(buf asm.Buffer, n *n
 
 func (a *AssemblerImpl) encodeTwoRegistersToRegister(buf asm.Buffer, n *nodeImpl) (err error) {
 	switch inst := n.instruction; inst {
-	case AND, ANDW, ORR, ORRW, EOR, EORW:
+	case AND, ANDW, ORR, ORRW, ORN, ORNW, EOR, EORW:
 		// See "Logical (shifted register)" in
 		// https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Register?lang=en
 		srcRegBits, srcReg2Bits, dstRegBits := registerBits(n.srcReg), registerBits(n.srcReg2), registerBits(n.dstReg)
-		var sf, opc byte
+		var sf, opc, n byte
 		switch inst {
 		case AND:
 			sf, opc = 0b1, 0b00
@@ -1470,6 +1493,10 @@ func (a *AssemblerImpl) encodeTwoRegistersToRegister(buf asm.Buffer, n *nodeImpl
 			sf, opc = 0b1, 0b01
 		case ORRW:
 			sf, opc = 0b0, 0b01
+		case ORN:
+			sf, opc, n = 0b1, 0b01, 0b1
+		case ORNW:
+			sf, opc, n = 0b0, 0b01, 0b1
 		case EOR:
 			sf, opc = 0b1, 0b10
 		case EORW:
@@ -1478,7 +1505,7 @@ func (a *AssemblerImpl) encodeTwoRegistersToRegister(buf asm.Buffer, n *nodeImpl
 		buf.Append4Bytes(
 			(srcReg2Bits<<5)|dstRegBits,
 			srcReg2Bits>>3,
-			srcRegBits,
+			(n<<5)|srcRegBits,
 			sf<<7|opc<<5|0b01010,
 		)
 	case ASR, ASRW, LSL, LSLW, LSR, LSRW, ROR, RORW:
@@ -1565,6 +1592,89 @@ func (a *AssemblerImpl) encodeTwoRegistersToRegister(buf asm.Buffer, n *nodeImpl
 			tp<<6|0b00_1_00000|srcRegBits,
 			0b0_00_11110,
 		)
+
+	case LDADDALD, LDADDALW, LDADDALH, LDADDALB,
+		LDCLRALD, LDCLRALW, LDCLRALH, LDCLRALB,
+		LDSETALD, LDSETALW, LDSETALH, LDSETALB,
+		LDEORALD, LDEORALW, LDEORALH, LDEORALB,
+		SWPALD, SWPALW, SWPALH, SWPALB:
+		srcRegBits, srcReg2Bits, dstRegBits := registerBits(n.srcReg), registerBits(n.srcReg2), registerBits(n.dstReg)
+
+		// While arm's docs don't group the opcodes together for the arithmetic and swap instructions, they are
+		// actually identical except for the single bit before the opcode being 1 for swap, so we encode them together.
+		var size, opcode byte
+		switch n.instruction {
+		case LDADDALD:
+			size, opcode = 0b11, 0b0000
+		case LDADDALW:
+			size, opcode = 0b10, 0b0000
+		case LDADDALH:
+			size, opcode = 0b01, 0b0000
+		case LDADDALB:
+			size, opcode = 0b00, 0b0000
+		case LDCLRALD:
+			size, opcode = 0b11, 0b0001
+		case LDCLRALW:
+			size, opcode = 0b10, 0b0001
+		case LDCLRALH:
+			size, opcode = 0b01, 0b0001
+		case LDCLRALB:
+			size, opcode = 0b00, 0b0001
+		case LDSETALD:
+			size, opcode = 0b11, 0b0011
+		case LDSETALW:
+			size, opcode = 0b10, 0b0011
+		case LDSETALH:
+			size, opcode = 0b01, 0b0011
+		case LDSETALB:
+			size, opcode = 0b00, 0b0011
+		case LDEORALD:
+			size, opcode = 0b11, 0b0010
+		case LDEORALW:
+			size, opcode = 0b10, 0b0010
+		case LDEORALH:
+			size, opcode = 0b01, 0b0010
+		case LDEORALB:
+			size, opcode = 0b00, 0b0010
+		case SWPALD:
+			size, opcode = 0b11, 0b1000
+		case SWPALW:
+			size, opcode = 0b10, 0b1000
+		case SWPALH:
+			size, opcode = 0b01, 0b1000
+		case SWPALB:
+			size, opcode = 0b00, 0b1000
+		}
+
+		buf.Append4Bytes(
+			(srcReg2Bits<<5)|dstRegBits,
+			(opcode<<4)|(srcReg2Bits>>3),
+			0b111_00000|srcRegBits,
+			(size<<6)|0b00_111_000,
+		)
+
+	case CASALD, CASALW, CASALH, CASALB:
+		srcRegBits, srcReg2Bits, dstRegBits := registerBits(n.srcReg), registerBits(n.srcReg2), registerBits(n.dstReg)
+
+		var size byte
+		switch n.instruction {
+		case CASALD:
+			size = 0b11
+		case CASALW:
+			size = 0b10
+		case CASALH:
+			size = 0b01
+		case CASALB:
+			size = 0b00
+		}
+
+		buf.Append4Bytes(
+			(srcReg2Bits<<5)|dstRegBits,
+			0b111111_00|(srcReg2Bits>>3),
+			0b111_00000|srcRegBits,
+			(size<<6)|0b00_001_000,
+		)
+
 	default:
 		return errorEncodingUnsupported(n)
 	}
@@ -1606,6 +1716,7 @@ func (a *AssemblerImpl) encodeThreeRegistersToRegister(buf asm.Buffer, n *nodeIm
 			sf<<7|0b00_11011,
 		)
 		return nil
+
 	default:
 		return errorEncodingUnsupported(n)
 	}
@@ -1711,6 +1822,17 @@ func (a *AssemblerImpl) encodeLoadOrStoreWithRegisterOffset(
 	)
 }
 
+func (a *AssemblerImpl) encodeLoadOrStoreWithAcquireRelease(
+	buf asm.Buffer, baseRegBits, targetRegBits byte, l, size byte,
+) {
+	buf.Append4Bytes(
+		(baseRegBits<<5)|targetRegBits,
+		0b1_11111_00|(baseRegBits>>3),
+		0b1_0_011111|l<<6,
+		size<<6|0b00_001000,
+	)
+}
+
 // validateMemoryOffset validates the memory offset if the given offset can be encoded in the assembler.
 // In theory, offset can be any, but for simplicity of our homemade assembler, we limit the offset range
 // that can be encoded enough for supporting compiler.
@@ -1842,6 +1964,7 @@ func (a *AssemblerImpl) encodeRegisterToMemory(buf asm.Buffer, n *nodeImpl) (err
 		size, v                byte
 		datasize, datasizeLog2 int64
 		isTargetFloat          bool
+		isRelease              bool
 	)
 	switch n.instruction {
 	case STRD:
@@ -1856,6 +1979,14 @@ func (a *AssemblerImpl) encodeRegisterToMemory(buf asm.Buffer, n *nodeImpl) (err
 		size, v, datasize, datasizeLog2, isTargetFloat = 0b11, 0x1, 8, 3, true
 	case FSTRS:
 		size, v, datasize, datasizeLog2, isTargetFloat = 0b10, 0x1, 4, 2, true
+	case STLRD:
+		size, isRelease = 0b11, true
+	case STLRW:
+		size, isRelease = 0b10, true
+	case STLRH:
+		size, isRelease = 0b01, true
+	case STLRB:
+		size, isRelease = 0b00, true
 	default:
 		return errorEncodingUnsupported(n)
 	}
@@ -1875,6 +2006,11 @@ func (a *AssemblerImpl) encodeRegisterToMemory(buf asm.Buffer, n *nodeImpl) (err
 		return err
 	}
 
+	if isRelease {
+		a.encodeLoadOrStoreWithAcquireRelease(buf, baseRegBits, srcRegBits, 0, size)
+		return nil
+	}
+
 	const opcode = 0x00 // opcode for store instructions.
 	if n.dstReg2 != asm.NilRegister {
 		offsetRegBits, err := intRegisterBits(n.dstReg2)
@@ -1965,6 +2101,7 @@ func (a *AssemblerImpl) encodeMemoryToRegister(buf asm.Buffer, n *nodeImpl) (err
 		size, v, opcode        byte
 		datasize, datasizeLog2 int64
 		isTargetFloat          bool
+		isAcquire              bool
 	)
 	switch n.instruction {
 	case ADR:
@@ -1991,6 +2128,14 @@ func (a *AssemblerImpl) encodeMemoryToRegister(buf asm.Buffer, n *nodeImpl) (err
 		size, v, datasize, datasizeLog2, opcode = 0b00, 0x0, 1, 0, 0b01
 	case LDRSW:
 		size, v, datasize, datasizeLog2, opcode = 0b10, 0x0, 4, 2, 0b10
+	case LDARD:
+		size, isAcquire = 0b11, true
+	case LDARW:
+		size, isAcquire = 0b10, true
+	case LDARH:
+		size, isAcquire = 0b01, true
+	case LDARB:
+		size, isAcquire = 0b00, true
 	default:
 		return errorEncodingUnsupported(n)
 	}
@@ -2009,6 +2154,11 @@ func (a *AssemblerImpl) encodeMemoryToRegister(buf asm.Buffer, n *nodeImpl) (err
 		return err
 	}
 
+	if isAcquire {
+		a.encodeLoadOrStoreWithAcquireRelease(buf, baseRegBits, dstRegBits, 1, size)
+		return nil
+	}
+
 	if n.srcReg2 != asm.NilRegister {
 		offsetRegBits, err := intRegisterBits(n.srcReg2)
 		if err != nil {
@@ -2161,30 +2311,38 @@ func (a *AssemblerImpl) encodeConstToRegister(buf asm.Buffer, n *nodeImpl) (err
 	// See "Logical (immediate)" in
 	// https://developer.arm.com/documentation/ddi0596/2021-12/Index-by-Encoding/Data-Processing----Immediate
 	switch n.instruction {
-	case ANDIMM32:
-		var sf, opc byte = 0b0, 0b00
+	case ANDIMM32, ANDIMM64, ANDSW, ANDS:
 		if !isBitMaskImmediate(uint64(c)) {
-			err = fmt.Errorf("const %d must be valid bitmask immediate for %s", c, InstructionName(ANDIMM64))
+			err = fmt.Errorf("const %d must be valid bitmask immediate for %s", c, InstructionName(n.instruction))
 			return
 		}
-		immr, imms, N := bitmaskImmediate(uint64(c), false)
-		buf.Append4Bytes(
-			(dstRegBits<<5)|dstRegBits,
-			imms<<2|dstRegBits>>3,
-			N<<6|immr,
-			sf<<7|opc<<5|0b10010,
-		)
-		return
-	case ANDIMM64:
-		var sf, opc byte = 0b1, 0b00
-		if !isBitMaskImmediate(uint64(c)) {
-			err = fmt.Errorf("const %d must be valid bitmask immediate for %s", c, InstructionName(ANDIMM64))
-			return
+		srcRegBits := dstRegBits
+		var sf, opc, immr, imms, N byte
+		switch n.instruction {
+		case ANDIMM32:
+			sf, opc = 0b0, 0b00
+			immr, imms, N = bitmaskImmediate(uint64(c), false)
+		case ANDIMM64:
+			sf, opc = 0b1, 0b00
+			immr, imms, N = bitmaskImmediate(uint64(c), true)
+		case ANDSW:
+			srcRegBits, err = intRegisterBits(n.srcReg)
+			if err != nil {
+				return err
+			}
+			sf, opc = 0b0, 0b11
+			immr, imms, N = bitmaskImmediate(uint64(c), false)
+		case ANDS:
+			srcRegBits, err = intRegisterBits(n.srcReg)
+			if err != nil {
+				return err
+			}
+			sf, opc = 0b1, 0b11
+			immr, imms, N = bitmaskImmediate(uint64(c), true)
 		}
-		immr, imms, N := bitmaskImmediate(uint64(c), true)
 		buf.Append4Bytes(
-			(dstRegBits<<5)|dstRegBits,
-			imms<<2|dstRegBits>>3,
+			(srcRegBits<<5)|dstRegBits,
+			imms<<2|srcRegBits>>3,
 			N<<6|immr,
 			sf<<7|opc<<5|0b10010,
 		)
diff --git a/internal/engine/interpreter/interpreter.go b/internal/engine/interpreter/interpreter.go
index c60d0584..f67c0c72 100644
--- a/internal/engine/interpreter/interpreter.go
+++ b/internal/engine/interpreter/interpreter.go
@@ -3897,6 +3897,361 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, m *wasm.ModuleInstance
 			ce.pushValue(retLo)
 			ce.pushValue(retHi)
 			frame.pc++
+		case wazeroir.OperationKindAtomicMemoryWait:
+			timeout := int64(ce.popValue())
+			exp := ce.popValue()
+			offset := ce.popMemoryOffset(op)
+			// Runtime instead of validation error because the spec intends to allow binaries to include
+			// such instructions as long as they are not executed.
+			if !memoryInst.Shared {
+				panic(wasmruntime.ErrRuntimeExpectedSharedMemory)
+			}
+
+			switch wazeroir.UnsignedType(op.B1) {
+			case wazeroir.UnsignedTypeI32:
+				if offset%4 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				if int(offset) > len(memoryInst.Buffer)-4 {
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				ce.pushValue(memoryInst.Wait32(offset, uint32(exp), timeout, func(mem *wasm.MemoryInstance, offset uint32) uint32 {
+					mem.Mux.Lock()
+					defer mem.Mux.Unlock()
+					value, _ := mem.ReadUint32Le(offset)
+					return value
+				}))
+			case wazeroir.UnsignedTypeI64:
+				if offset%8 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				if int(offset) > len(memoryInst.Buffer)-8 {
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				ce.pushValue(memoryInst.Wait64(offset, exp, timeout, func(mem *wasm.MemoryInstance, offset uint32) uint64 {
+					mem.Mux.Lock()
+					defer mem.Mux.Unlock()
+					value, _ := mem.ReadUint64Le(offset)
+					return value
+				}))
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicMemoryNotify:
+			count := ce.popValue()
+			offset := ce.popMemoryOffset(op)
+			if offset%4 != 0 {
+				panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+			}
+			// Just a bounds check
+			if offset >= memoryInst.Size() {
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			res := memoryInst.Notify(offset, uint32(count))
+			ce.pushValue(uint64(res))
+			frame.pc++
+		case wazeroir.OperationKindAtomicFence:
+			// Memory not required for fence only
+			if memoryInst != nil {
+				// An empty critical section can be used as a synchronization primitive, which is what
+				// fence is. Probably, there are no spectests or defined behavior to confirm this yet.
+				memoryInst.Mux.Lock()
+				memoryInst.Mux.Unlock() //nolint:staticcheck
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicLoad:
+			offset := ce.popMemoryOffset(op)
+			switch wazeroir.UnsignedType(op.B1) {
+			case wazeroir.UnsignedTypeI32:
+				if offset%4 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				val, ok := memoryInst.ReadUint32Le(offset)
+				memoryInst.Mux.Unlock()
+				if !ok {
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				ce.pushValue(uint64(val))
+			case wazeroir.UnsignedTypeI64:
+				if offset%8 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				val, ok := memoryInst.ReadUint64Le(offset)
+				memoryInst.Mux.Unlock()
+				if !ok {
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				ce.pushValue(val)
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicLoad8:
+			offset := ce.popMemoryOffset(op)
+			memoryInst.Mux.Lock()
+			val, ok := memoryInst.ReadByte(offset)
+			memoryInst.Mux.Unlock()
+			if !ok {
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			ce.pushValue(uint64(val))
+			frame.pc++
+		case wazeroir.OperationKindAtomicLoad16:
+			offset := ce.popMemoryOffset(op)
+			if offset%2 != 0 {
+				panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+			}
+			memoryInst.Mux.Lock()
+			val, ok := memoryInst.ReadUint16Le(offset)
+			memoryInst.Mux.Unlock()
+			if !ok {
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			ce.pushValue(uint64(val))
+			frame.pc++
+		case wazeroir.OperationKindAtomicStore:
+			val := ce.popValue()
+			offset := ce.popMemoryOffset(op)
+			switch wazeroir.UnsignedType(op.B1) {
+			case wazeroir.UnsignedTypeI32:
+				if offset%4 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				ok := memoryInst.WriteUint32Le(offset, uint32(val))
+				memoryInst.Mux.Unlock()
+				if !ok {
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+			case wazeroir.UnsignedTypeI64:
+				if offset%8 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				ok := memoryInst.WriteUint64Le(offset, val)
+				memoryInst.Mux.Unlock()
+				if !ok {
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicStore8:
+			val := byte(ce.popValue())
+			offset := ce.popMemoryOffset(op)
+			memoryInst.Mux.Lock()
+			ok := memoryInst.WriteByte(offset, val)
+			memoryInst.Mux.Unlock()
+			if !ok {
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicStore16:
+			val := uint16(ce.popValue())
+			offset := ce.popMemoryOffset(op)
+			if offset%2 != 0 {
+				panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+			}
+			memoryInst.Mux.Lock()
+			ok := memoryInst.WriteUint16Le(offset, val)
+			memoryInst.Mux.Unlock()
+			if !ok {
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicRMW:
+			val := ce.popValue()
+			offset := ce.popMemoryOffset(op)
+			switch wazeroir.UnsignedType(op.B1) {
+			case wazeroir.UnsignedTypeI32:
+				if offset%4 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				old, ok := memoryInst.ReadUint32Le(offset)
+				if !ok {
+					memoryInst.Mux.Unlock()
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				var newVal uint32
+				switch wazeroir.AtomicArithmeticOp(op.B2) {
+				case wazeroir.AtomicArithmeticOpAdd:
+					newVal = old + uint32(val)
+				case wazeroir.AtomicArithmeticOpSub:
+					newVal = old - uint32(val)
+				case wazeroir.AtomicArithmeticOpAnd:
+					newVal = old & uint32(val)
+				case wazeroir.AtomicArithmeticOpOr:
+					newVal = old | uint32(val)
+				case wazeroir.AtomicArithmeticOpXor:
+					newVal = old ^ uint32(val)
+				case wazeroir.AtomicArithmeticOpNop:
+					newVal = uint32(val)
+				}
+				memoryInst.WriteUint32Le(offset, newVal)
+				memoryInst.Mux.Unlock()
+				ce.pushValue(uint64(old))
+			case wazeroir.UnsignedTypeI64:
+				if offset%8 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				old, ok := memoryInst.ReadUint64Le(offset)
+				if !ok {
+					memoryInst.Mux.Unlock()
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				var newVal uint64
+				switch wazeroir.AtomicArithmeticOp(op.B2) {
+				case wazeroir.AtomicArithmeticOpAdd:
+					newVal = old + val
+				case wazeroir.AtomicArithmeticOpSub:
+					newVal = old - val
+				case wazeroir.AtomicArithmeticOpAnd:
+					newVal = old & val
+				case wazeroir.AtomicArithmeticOpOr:
+					newVal = old | val
+				case wazeroir.AtomicArithmeticOpXor:
+					newVal = old ^ val
+				case wazeroir.AtomicArithmeticOpNop:
+					newVal = val
+				}
+				memoryInst.WriteUint64Le(offset, newVal)
+				memoryInst.Mux.Unlock()
+				ce.pushValue(old)
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicRMW8:
+			val := ce.popValue()
+			offset := ce.popMemoryOffset(op)
+			memoryInst.Mux.Lock()
+			old, ok := memoryInst.ReadByte(offset)
+			if !ok {
+				memoryInst.Mux.Unlock()
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			arg := byte(val)
+			var newVal byte
+			switch wazeroir.AtomicArithmeticOp(op.B2) {
+			case wazeroir.AtomicArithmeticOpAdd:
+				newVal = old + arg
+			case wazeroir.AtomicArithmeticOpSub:
+				newVal = old - arg
+			case wazeroir.AtomicArithmeticOpAnd:
+				newVal = old & arg
+			case wazeroir.AtomicArithmeticOpOr:
+				newVal = old | arg
+			case wazeroir.AtomicArithmeticOpXor:
+				newVal = old ^ arg
+			case wazeroir.AtomicArithmeticOpNop:
+				newVal = arg
+			}
+			memoryInst.WriteByte(offset, newVal)
+			memoryInst.Mux.Unlock()
+			ce.pushValue(uint64(old))
+			frame.pc++
+		case wazeroir.OperationKindAtomicRMW16:
+			val := ce.popValue()
+			offset := ce.popMemoryOffset(op)
+			if offset%2 != 0 {
+				panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+			}
+			memoryInst.Mux.Lock()
+			old, ok := memoryInst.ReadUint16Le(offset)
+			if !ok {
+				memoryInst.Mux.Unlock()
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			arg := uint16(val)
+			var newVal uint16
+			switch wazeroir.AtomicArithmeticOp(op.B2) {
+			case wazeroir.AtomicArithmeticOpAdd:
+				newVal = old + arg
+			case wazeroir.AtomicArithmeticOpSub:
+				newVal = old - arg
+			case wazeroir.AtomicArithmeticOpAnd:
+				newVal = old & arg
+			case wazeroir.AtomicArithmeticOpOr:
+				newVal = old | arg
+			case wazeroir.AtomicArithmeticOpXor:
+				newVal = old ^ arg
+			case wazeroir.AtomicArithmeticOpNop:
+				newVal = arg
+			}
+			memoryInst.WriteUint16Le(offset, newVal)
+			memoryInst.Mux.Unlock()
+			ce.pushValue(uint64(old))
+			frame.pc++
+		case wazeroir.OperationKindAtomicRMWCmpxchg:
+			rep := ce.popValue()
+			exp := ce.popValue()
+			offset := ce.popMemoryOffset(op)
+			switch wazeroir.UnsignedType(op.B1) {
+			case wazeroir.UnsignedTypeI32:
+				if offset%4 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				old, ok := memoryInst.ReadUint32Le(offset)
+				if !ok {
+					memoryInst.Mux.Unlock()
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				if old == uint32(exp) {
+					memoryInst.WriteUint32Le(offset, uint32(rep))
+				}
+				memoryInst.Mux.Unlock()
+				ce.pushValue(uint64(old))
+			case wazeroir.UnsignedTypeI64:
+				if offset%8 != 0 {
+					panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+				}
+				memoryInst.Mux.Lock()
+				old, ok := memoryInst.ReadUint64Le(offset)
+				if !ok {
+					memoryInst.Mux.Unlock()
+					panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+				}
+				if old == exp {
+					memoryInst.WriteUint64Le(offset, rep)
+				}
+				memoryInst.Mux.Unlock()
+				ce.pushValue(old)
+			}
+			frame.pc++
+		case wazeroir.OperationKindAtomicRMW8Cmpxchg:
+			rep := byte(ce.popValue())
+			exp := byte(ce.popValue())
+			offset := ce.popMemoryOffset(op)
+			memoryInst.Mux.Lock()
+			old, ok := memoryInst.ReadByte(offset)
+			if !ok {
+				memoryInst.Mux.Unlock()
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			if old == exp {
+				memoryInst.WriteByte(offset, rep)
+			}
+			memoryInst.Mux.Unlock()
+			ce.pushValue(uint64(old))
+			frame.pc++
+		case wazeroir.OperationKindAtomicRMW16Cmpxchg:
+			rep := uint16(ce.popValue())
+			exp := uint16(ce.popValue())
+			offset := ce.popMemoryOffset(op)
+			if offset%2 != 0 {
+				panic(wasmruntime.ErrRuntimeUnalignedAtomic)
+			}
+			memoryInst.Mux.Lock()
+			old, ok := memoryInst.ReadUint16Le(offset)
+			if !ok {
+				memoryInst.Mux.Unlock()
+				panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess)
+			}
+			if old == exp {
+				memoryInst.WriteUint16Le(offset, rep)
+			}
+			memoryInst.Mux.Unlock()
+			ce.pushValue(uint64(old))
+			frame.pc++
 		default:
 			frame.pc++
 		}
diff --git a/internal/wasm/memory.go b/internal/wasm/memory.go
index 38781449..f0688e08 100644
--- a/internal/wasm/memory.go
+++ b/internal/wasm/memory.go
@@ -1,14 +1,18 @@
 package wasm
 
 import (
+	"container/list"
 	"encoding/binary"
 	"fmt"
 	"math"
 	"reflect"
+	"sync"
+	"time"
 	"unsafe"
 
 	"github.com/tetratelabs/wazero/api"
 	"github.com/tetratelabs/wazero/internal/internalapi"
+	"github.com/tetratelabs/wazero/internal/wasmruntime"
 )
 
 const (
@@ -26,6 +30,11 @@ const (
 // compile-time check to ensure MemoryInstance implements api.Memory
 var _ api.Memory = &MemoryInstance{}
 
+type waiters struct {
+	mux sync.Mutex
+	l   *list.List
+}
+
 // MemoryInstance represents a memory instance in a store, and implements api.Memory.
 //
 // Note: In WebAssembly 1.0 (20191205), there may be up to one Memory per store, which means the precise memory is always
@@ -39,6 +48,14 @@ type MemoryInstance struct {
 	Shared        bool
 	// definition is known at compile time.
 	definition api.MemoryDefinition
+
+	// Mux is used in interpreter mode to prevent overlapping calls to atomic instructions,
+	// introduced with WebAssembly threads proposal.
+	Mux sync.Mutex
+
+	// waiters implements atomic wait and notify. It is implemented similarly to golang.org/x/sync/semaphore,
+	// with a fixed weight of 1 and no spurious notifications.
+	waiters sync.Map
 }
 
 // NewMemoryInstance creates a new instance based on the parameters in the SectionIDMemory.
@@ -279,3 +296,103 @@ func (m *MemoryInstance) writeUint64Le(offset uint32, v uint64) bool {
 	binary.LittleEndian.PutUint64(m.Buffer[offset:], v)
 	return true
 }
+
+// Wait32 suspends the caller until the offset is notified by a different agent.
+func (m *MemoryInstance) Wait32(offset uint32, exp uint32, timeout int64, reader func(mem *MemoryInstance, offset uint32) uint32) uint64 {
+	w := m.getWaiters(offset)
+	w.mux.Lock()
+
+	cur := reader(m, offset)
+	if cur != exp {
+		w.mux.Unlock()
+		return 1
+	}
+
+	return m.wait(w, timeout)
+}
+
+// Wait64 suspends the caller until the offset is notified by a different agent.
+func (m *MemoryInstance) Wait64(offset uint32, exp uint64, timeout int64, reader func(mem *MemoryInstance, offset uint32) uint64) uint64 {
+	w := m.getWaiters(offset)
+	w.mux.Lock()
+
+	cur := reader(m, offset)
+	if cur != exp {
+		w.mux.Unlock()
+		return 1
+	}
+
+	return m.wait(w, timeout)
+}
+
+func (m *MemoryInstance) wait(w *waiters, timeout int64) uint64 {
+	if w.l == nil {
+		w.l = list.New()
+	}
+
+	// The specification requires a trap if the number of existing waiters + 1 == 2^32, so we add a check here.
+	// In practice, it is unlikely the application would ever accumulate such a large number of waiters as it
+	// indicates several GB of RAM used just for the list of waiters.
+	// https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#wait
+	if uint64(w.l.Len()+1) == 1<<32 {
+		w.mux.Unlock()
+		panic(wasmruntime.ErrRuntimeTooManyWaiters)
+	}
+
+	ready := make(chan struct{})
+	elem := w.l.PushBack(ready)
+	w.mux.Unlock()
+
+	if timeout < 0 {
+		<-ready
+		return 0
+	} else {
+		select {
+		case <-ready:
+			return 0
+		case <-time.After(time.Duration(timeout)):
+			// While we could see if the channel completed by now and ignore the timeout, similar to x/sync/semaphore,
+			// the Wasm spec doesn't specify this behavior, so we keep things simple by prioritizing the timeout.
+			w.mux.Lock()
+			w.l.Remove(elem)
+			w.mux.Unlock()
+			return 2
+		}
+	}
+}
+
+func (m *MemoryInstance) getWaiters(offset uint32) *waiters {
+	wAny, ok := m.waiters.Load(offset)
+	if !ok {
+		// The first time an address is waited on, simultaneous waits will cause extra allocations.
+		// Further operations will be loaded above, which is also the general pattern of usage with
+		// mutexes.
+		wAny, _ = m.waiters.LoadOrStore(offset, &waiters{})
+	}
+
+	return wAny.(*waiters)
+}
+
+// Notify wakes up at most count waiters at the given offset.
+func (m *MemoryInstance) Notify(offset uint32, count uint32) uint32 {
+	wAny, ok := m.waiters.Load(offset)
+	if !ok {
+		return 0
+	}
+	w := wAny.(*waiters)
+
+	w.mux.Lock()
+	defer w.mux.Unlock()
+	if w.l == nil {
+		return 0
+	}
+
+	res := uint32(0)
+	for num := w.l.Len(); num > 0 && res < count; num = w.l.Len() {
+		w := w.l.Remove(w.l.Front()).(chan struct{})
+		close(w)
+		res++
+	}
+
+	return res
+}
diff --git a/internal/wasmruntime/errors.go b/internal/wasmruntime/errors.go
index 43f951e0..556e5de8 100644
--- a/internal/wasmruntime/errors.go
+++ b/internal/wasmruntime/errors.go
@@ -27,6 +27,12 @@ var (
 	ErrRuntimeInvalidTableAccess = New("invalid table access")
 	// ErrRuntimeIndirectCallTypeMismatch indicates that the type check failed during call_indirect.
 	ErrRuntimeIndirectCallTypeMismatch = New("indirect call type mismatch")
+	// ErrRuntimeUnalignedAtomic indicates that an atomic operation was made with incorrect memory alignment.
+	ErrRuntimeUnalignedAtomic = New("unaligned atomic")
+	// ErrRuntimeExpectedSharedMemory indicates that an operation was made against unshared memory when not allowed.
+	ErrRuntimeExpectedSharedMemory = New("expected shared memory")
+	// ErrRuntimeTooManyWaiters indicates that atomic.wait was called with too many waiters.
+	ErrRuntimeTooManyWaiters = New("too many waiters")
 )
 
 // Error is returned by a wasm.Engine during the execution of Wasm functions, and they indicate that the Wasm runtime


Test patch:
diff --git a/internal/asm/arm64/impl_1_test.go b/internal/asm/arm64/impl_1_test.go
index 982444be..e3a0960e 100644
--- a/internal/asm/arm64/impl_1_test.go
+++ b/internal/asm/arm64/impl_1_test.go
@@ -665,6 +665,18 @@ func TestAssemblerImpl_encodeNoneToNone(t *testing.T) {
 		actual := buf.Bytes()
 		require.Equal(t, []byte{0x0, 0x0, 0x0, 0x0}, actual, hex.EncodeToString(actual))
 	})
+	t.Run("dmb ish", func(t *testing.T) {
+		code := asm.CodeSegment{}
+		defer func() { require.NoError(t, code.Unmap()) }()
+
+		a := NewAssembler(asm.NilRegister)
+		buf := code.NextCodeSection()
+		err := a.encodeNoneToNone(buf, &nodeImpl{instruction: DMB})
+		require.NoError(t, err)
+
+		actual := buf.Bytes()
+		require.Equal(t, []byte{0xbf, 0x3b, 0x3, 0xd5}, actual, hex.EncodeToString(actual))
+	})
 }
 
 func Test_validateMemoryOffset(t *testing.T) {
diff --git a/internal/asm/arm64/impl_3_test.go b/internal/asm/arm64/impl_3_test.go
index eefbfbc9..652f230e 100644
--- a/internal/asm/arm64/impl_3_test.go
+++ b/internal/asm/arm64/impl_3_test.go
@@ -151,6 +151,60 @@ func TestAssemblerImpl_EncodeTwoRegistersToRegister(t *testing.T) {
 		{name: "src=R30,src2=R30,dst=RZR", inst: ORRW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x1e, 0x2a}},
 		{name: "src=R30,src2=R30,dst=R10", inst: ORRW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x1e, 0x2a}},
 		{name: "src=R30,src2=R30,dst=R30", inst: ORRW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x1e, 0x2a}},
+		{name: "mvn xzr, xzr", inst: ORN, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x3f, 0xaa}},
+		{name: "mvn x10, xzr", inst: ORN, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x3f, 0xaa}},
+		{name: "mvn x30, xzr", inst: ORN, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0x3f, 0xaa}},
+		{name: "orn xzr, x10, xzr", inst: ORN, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0x3f, 0xaa}},
+		{name: "orn x10, x10, xzr", inst: ORN, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0x3f, 0xaa}},
+		{name: "orn x30, x10, xzr", inst: ORN, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0x3f, 0xaa}},
+		{name: "orn xzr, x30, xzr", inst: ORN, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x3f, 0xaa}},
+		{name: "orn x10, x30, xzr", inst: ORN, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x3f, 0xaa}},
+		{name: "orn x30, x30, xzr", inst: ORN, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x3f, 0xaa}},
+		{name: "mvn xzr, x10", inst: ORN, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x2a, 0xaa}},
+		{name: "mvn x10, x10", inst: ORN, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x2a, 0xaa}},
+		{name: "mvn x30, x10", inst: ORN, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0x2a, 0xaa}},
+		{name: "orn xzr, x10, x10", inst: ORN, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0x2a, 0xaa}},
+		{name: "orn x10, x10, x10", inst: ORN, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0x2a, 0xaa}},
+		{name: "orn x30, x10, x10", inst: ORN, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0x2a, 0xaa}},
+		{name: "orn x30, x10, x10", inst: ORN, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x2a, 0xaa}},
+		{name: "orn x10, x30, x10", inst: ORN, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x2a, 0xaa}},
+		{name: "orn x30, x30, x10", inst: ORN, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x2a, 0xaa}},
+		{name: "mvn xzr, x30", inst: ORN, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x3e, 0xaa}},
+		{name: "mvn x10, x30", inst: ORN, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x3e, 0xaa}},
+		{name: "mvn x30, x30", inst: ORN, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0x3e, 0xaa}},
+		{name: "orn xzr, x10, x30", inst: ORN, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0x3e, 0xaa}},
+		{name: "orn x10, x10, x30", inst: ORN, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0x3e, 0xaa}},
+		{name: "orn x30, x10, x30", inst: ORN, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0x3e, 0xaa}},
+		{name: "orn xzr, x30, x30", inst: ORN, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x3e, 0xaa}},
+		{name: "orn x10, x30, x30", inst: ORN, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x3e, 0xaa}},
+		{name: "orn x30, x30, x30", inst: ORN, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x3e, 0xaa}},
+		{name: "mvn wzr, wzr", inst: ORNW, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x3f, 0x2a}},
+		{name: "mvn w10, wzr", inst: ORNW, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x3f, 0x2a}},
+		{name: "mvn w30, wzr", inst: ORNW, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0x3f, 0x2a}},
+		{name: "orn wzr, w10, wzr", inst: ORNW, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0x3f, 0x2a}},
+		{name: "orn w10, w10, wzr", inst: ORNW, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0x3f, 0x2a}},
+		{name: "orn w30, w10, wzr", inst: ORNW, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0x3f, 0x2a}},
+		{name: "orn wzr, w30, wzr", inst: ORNW, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x3f, 0x2a}},
+		{name: "orn w10, w30, wzr", inst: ORNW, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x3f, 0x2a}},
+		{name: "orn w30, w30, wzr", inst: ORNW, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x3f, 0x2a}},
+		{name: "mvn wzr, w10", inst: ORNW, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x2a, 0x2a}},
+		{name: "mvn w10, w10", inst: ORNW, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x2a, 0x2a}},
+		{name: "mvn w30, w10", inst: ORNW, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0x2a, 0x2a}},
+		{name: "orn wzr, w10, w10", inst: ORNW, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0x2a, 0x2a}},
+		{name: "orn w10, w10, w10", inst: ORNW, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0x2a, 0x2a}},
+		{name: "orn w30, w10, w10", inst: ORNW, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0x2a, 0x2a}},
+		{name: "orn w30, w10, w10", inst: ORNW, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x2a, 0x2a}},
+		{name: "orn w10, w30, w10", inst: ORNW, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x2a, 0x2a}},
+		{name: "orn w30, w30, w10", inst: ORNW, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x2a, 0x2a}},
+		{name: "mvn wzr, w30", inst: ORNW, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x3e, 0x2a}},
+		{name: "mvn w10, w30", inst: ORNW, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x3e, 0x2a}},
+		{name: "mvn w30, w30", inst: ORNW, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0x3e, 0x2a}},
+		{name: "orn wzr, w10, w30", inst: ORNW, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0x3e, 0x2a}},
+		{name: "orn w10, w10, w30", inst: ORNW, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0x3e, 0x2a}},
+		{name: "orn w30, w10, w30", inst: ORNW, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0x3e, 0x2a}},
+		{name: "orn wzr, w30, w30", inst: ORNW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x3e, 0x2a}},
+		{name: "orn w10, w30, w30", inst: ORNW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x3e, 0x2a}},
+		{name: "orn w30, w30, w30", inst: ORNW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x3e, 0x2a}},
 		{name: "src=RZR,src2=RZR,dst=RZR", inst: EOR, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0x1f, 0xca}},
 		{name: "src=RZR,src2=RZR,dst=R10", inst: EOR, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0x1f, 0xca}},
 		{name: "src=RZR,src2=RZR,dst=R30", inst: EOR, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0x1f, 0xca}},
@@ -583,6 +637,654 @@ func TestAssemblerImpl_EncodeTwoRegistersToRegister(t *testing.T) {
 		{name: "src=R30,src2=R30,dst=RZR", inst: SUBW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0x1e, 0x4b}},
 		{name: "src=R30,src2=R30,dst=R10", inst: SUBW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0x1e, 0x4b}},
 		{name: "src=R30,src2=R30,dst=R30", inst: SUBW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0x1e, 0x4b}},
+		{name: "ldaddal xzr, xzr, [sp]", inst: LDADDALD, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xff, 0xf8}},
+		{name: "ldaddal xzr, x10, [sp]", inst: LDADDALD, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xff, 0xf8}},
+		{name: "ldaddal xzr, x30, [sp]", inst: LDADDALD, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xff, 0xf8}},
+		{name: "ldaddal xzr, xzr, [x10]", inst: LDADDALD, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xff, 0xf8}},
+		{name: "ldaddal xzr, x10, [x10]", inst: LDADDALD, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xff, 0xf8}},
+		{name: "ldaddal xzr, x30, [x10]", inst: LDADDALD, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xff, 0xf8}},
+		{name: "ldaddal xzr, xzr, [x30]", inst: LDADDALD, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xff, 0xf8}},
+		{name: "ldaddal xzr, x10, [x30]", inst: LDADDALD, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xff, 0xf8}},
+		{name: "ldaddal xzr, x30, [x30]", inst: LDADDALD, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xff, 0xf8}},
+		{name: "ldaddal x10, xzr, [sp]", inst: LDADDALD, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xea, 0xf8}},
+		{name: "ldaddal x10, x10, [sp]", inst: LDADDALD, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xea, 0xf8}},
+		{name: "ldaddal x10, x30, [sp]", inst: LDADDALD, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xea, 0xf8}},
+		{name: "ldaddal x10, xzr, [x10]", inst: LDADDALD, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xea, 0xf8}},
+		{name: "ldaddal x10, x10, [x10]", inst: LDADDALD, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xea, 0xf8}},
+		{name: "ldaddal x10, x30, [x10]", inst: LDADDALD, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xea, 0xf8}},
+		{name: "ldaddal x10, xzr, [x30]", inst: LDADDALD, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xea, 0xf8}},
+		{name: "ldaddal x10, x10, [x30]", inst: LDADDALD, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xea, 0xf8}},
+		{name: "ldaddal x10, x30, [x30]", inst: LDADDALD, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xea, 0xf8}},
+		{name: "ldaddal x30, xzr, [sp]", inst: LDADDALD, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xfe, 0xf8}},
+		{name: "ldaddal x30, x10, [sp]", inst: LDADDALD, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xfe, 0xf8}},
+		{name: "ldaddal x30, x30, [sp]", inst: LDADDALD, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xfe, 0xf8}},
+		{name: "ldaddal x30, xzr, [x10]", inst: LDADDALD, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xfe, 0xf8}},
+		{name: "ldaddal x30, x10, [x10]", inst: LDADDALD, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xfe, 0xf8}},
+		{name: "ldaddal x30, x30, [x10]", inst: LDADDALD, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xfe, 0xf8}},
+		{name: "ldaddal x30, xzr, [x30]", inst: LDADDALD, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xfe, 0xf8}},
+		{name: "ldaddal x30, x10, [x30]", inst: LDADDALD, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xfe, 0xf8}},
+		{name: "ldaddal x30, x30, [x30]", inst: LDADDALD, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xfe, 0xf8}},
+		{name: "ldaddal wzr, wzr, [sp]", inst: LDADDALW, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xff, 0xb8}},
+		{name: "ldaddal wzr, w10, [sp]", inst: LDADDALW, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xff, 0xb8}},
+		{name: "ldaddal wzr, w30, [sp]", inst: LDADDALW, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xff, 0xb8}},
+		{name: "ldaddal wzr, wzr, [x10]", inst: LDADDALW, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xff, 0xb8}},
+		{name: "ldaddal wzr, w10, [x10]", inst: LDADDALW, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xff, 0xb8}},
+		{name: "ldaddal wzr, w30, [x10]", inst: LDADDALW, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xff, 0xb8}},
+		{name: "ldaddal wzr, wzr, [x30]", inst: LDADDALW, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xff, 0xb8}},
+		{name: "ldaddal wzr, w10, [x30]", inst: LDADDALW, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xff, 0xb8}},
+		{name: "ldaddal wzr, w30, [x30]", inst: LDADDALW, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xff, 0xb8}},
+		{name: "ldaddal w10, wzr, [sp]", inst: LDADDALW, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xea, 0xb8}},
+		{name: "ldaddal w10, w10, [sp]", inst: LDADDALW, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xea, 0xb8}},
+		{name: "ldaddal w10, w30, [sp]", inst: LDADDALW, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xea, 0xb8}},
+		{name: "ldaddal w10, wzr, [x10]", inst: LDADDALW, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xea, 0xb8}},
+		{name: "ldaddal w10, w10, [x10]", inst: LDADDALW, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xea, 0xb8}},
+		{name: "ldaddal w10, w30, [x10]", inst: LDADDALW, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xea, 0xb8}},
+		{name: "ldaddal w10, wzr, [x30]", inst: LDADDALW, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xea, 0xb8}},
+		{name: "ldaddal w10, w10, [x30]", inst: LDADDALW, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xea, 0xb8}},
+		{name: "ldaddal w10, w30, [x30]", inst: LDADDALW, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xea, 0xb8}},
+		{name: "ldaddal w30, wzr, [sp]", inst: LDADDALW, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xfe, 0xb8}},
+		{name: "ldaddal w30, w10, [sp]", inst: LDADDALW, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xfe, 0xb8}},
+		{name: "ldaddal w30, w30, [sp]", inst: LDADDALW, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xfe, 0xb8}},
+		{name: "ldaddal w30, wzr, [x10]", inst: LDADDALW, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xfe, 0xb8}},
+		{name: "ldaddal w30, w10, [x10]", inst: LDADDALW, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xfe, 0xb8}},
+		{name: "ldaddal w30, w30, [x10]", inst: LDADDALW, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xfe, 0xb8}},
+		{name: "ldaddal w30, wzr, [x30]", inst: LDADDALW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xfe, 0xb8}},
+		{name: "ldaddal w30, w10, [x30]", inst: LDADDALW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xfe, 0xb8}},
+		{name: "ldaddal w30, w30, [x30]", inst: LDADDALW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xfe, 0xb8}},
+		{name: "ldaddalh wzr, wzr, [sp]", inst: LDADDALH, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xff, 0x78}},
+		{name: "ldaddalh wzr, w10, [sp]", inst: LDADDALH, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xff, 0x78}},
+		{name: "ldaddalh wzr, w30, [sp]", inst: LDADDALH, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xff, 0x78}},
+		{name: "ldaddalh wzr, wzr, [x10]", inst: LDADDALH, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xff, 0x78}},
+		{name: "ldaddalh wzr, w10, [x10]", inst: LDADDALH, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xff, 0x78}},
+		{name: "ldaddalh wzr, w30, [x10]", inst: LDADDALH, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xff, 0x78}},
+		{name: "ldaddalh wzr, wzr, [x30]", inst: LDADDALH, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xff, 0x78}},
+		{name: "ldaddalh wzr, w10, [x30]", inst: LDADDALH, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xff, 0x78}},
+		{name: "ldaddalh wzr, w30, [x30]", inst: LDADDALH, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xff, 0x78}},
+		{name: "ldaddalh w10, wzr, [sp]", inst: LDADDALH, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xea, 0x78}},
+		{name: "ldaddalh w10, w10, [sp]", inst: LDADDALH, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xea, 0x78}},
+		{name: "ldaddalh w10, w30, [sp]", inst: LDADDALH, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xea, 0x78}},
+		{name: "ldaddalh w10, wzr, [x10]", inst: LDADDALH, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xea, 0x78}},
+		{name: "ldaddalh w10, w10, [x10]", inst: LDADDALH, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xea, 0x78}},
+		{name: "ldaddalh w10, w30, [x10]", inst: LDADDALH, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xea, 0x78}},
+		{name: "ldaddalh w10, wzr, [x30]", inst: LDADDALH, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xea, 0x78}},
+		{name: "ldaddalh w10, w10, [x30]", inst: LDADDALH, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xea, 0x78}},
+		{name: "ldaddalh w10, w30, [x30]", inst: LDADDALH, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xea, 0x78}},
+		{name: "ldaddalh w30, wzr, [sp]", inst: LDADDALH, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xfe, 0x78}},
+		{name: "ldaddalh w30, w10, [sp]", inst: LDADDALH, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xfe, 0x78}},
+		{name: "ldaddalh w30, w30, [sp]", inst: LDADDALH, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xfe, 0x78}},
+		{name: "ldaddalh w30, wzr, [x10]", inst: LDADDALH, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xfe, 0x78}},
+		{name: "ldaddalh w30, w10, [x10]", inst: LDADDALH, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xfe, 0x78}},
+		{name: "ldaddalh w30, w30, [x10]", inst: LDADDALH, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xfe, 0x78}},
+		{name: "ldaddalh w30, wzr, [x30]", inst: LDADDALH, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xfe, 0x78}},
+		{name: "ldaddalh w30, w10, [x30]", inst: LDADDALH, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xfe, 0x78}},
+		{name: "ldaddalh w30, w30, [x30]", inst: LDADDALH, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xfe, 0x78}},
+		{name: "ldaddalb wzr, wzr, [sp]", inst: LDADDALB, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xff, 0x38}},
+		{name: "ldaddalb wzr, w10, [sp]", inst: LDADDALB, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xff, 0x38}},
+		{name: "ldaddalb wzr, w30, [sp]", inst: LDADDALB, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xff, 0x38}},
+		{name: "ldaddalb wzr, wzr, [x10]", inst: LDADDALB, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xff, 0x38}},
+		{name: "ldaddalb wzr, w10, [x10]", inst: LDADDALB, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xff, 0x38}},
+		{name: "ldaddalb wzr, w30, [x10]", inst: LDADDALB, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xff, 0x38}},
+		{name: "ldaddalb wzr, wzr, [x30]", inst: LDADDALB, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xff, 0x38}},
+		{name: "ldaddalb wzr, w10, [x30]", inst: LDADDALB, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xff, 0x38}},
+		{name: "ldaddalb wzr, w30, [x30]", inst: LDADDALB, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xff, 0x38}},
+		{name: "ldaddalb w10, wzr, [sp]", inst: LDADDALB, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xea, 0x38}},
+		{name: "ldaddalb w10, w10, [sp]", inst: LDADDALB, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xea, 0x38}},
+		{name: "ldaddalb w10, w30, [sp]", inst: LDADDALB, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xea, 0x38}},
+		{name: "ldaddalb w10, wzr, [x10]", inst: LDADDALB, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xea, 0x38}},
+		{name: "ldaddalb w10, w10, [x10]", inst: LDADDALB, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xea, 0x38}},
+		{name: "ldaddalb w10, w30, [x10]", inst: LDADDALB, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xea, 0x38}},
+		{name: "ldaddalb w10, wzr, [x30]", inst: LDADDALB, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xea, 0x38}},
+		{name: "ldaddalb w10, w10, [x30]", inst: LDADDALB, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xea, 0x38}},
+		{name: "ldaddalb w10, w30, [x30]", inst: LDADDALB, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xea, 0x38}},
+		{name: "ldaddalb w30, wzr, [sp]", inst: LDADDALB, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x3, 0xfe, 0x38}},
+		{name: "ldaddalb w30, w10, [sp]", inst: LDADDALB, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x3, 0xfe, 0x38}},
+		{name: "ldaddalb w30, w30, [sp]", inst: LDADDALB, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x3, 0xfe, 0x38}},
+		{name: "ldaddalb w30, wzr, [x10]", inst: LDADDALB, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x1, 0xfe, 0x38}},
+		{name: "ldaddalb w30, w10, [x10]", inst: LDADDALB, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x1, 0xfe, 0x38}},
+		{name: "ldaddalb w30, w30, [x10]", inst: LDADDALB, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x1, 0xfe, 0x38}},
+		{name: "ldaddalb w30, wzr, [x30]", inst: LDADDALB, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x3, 0xfe, 0x38}},
+		{name: "ldaddalb w30, w10, [x30]", inst: LDADDALB, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x3, 0xfe, 0x38}},
+		{name: "ldaddalb w30, w30, [x30]", inst: LDADDALB, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x3, 0xfe, 0x38}},
+		{name: "ldclral xzr, xzr, [sp]", inst: LDCLRALD, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xff, 0xf8}},
+		{name: "ldclral xzr, x10, [sp]", inst: LDCLRALD, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xff, 0xf8}},
+		{name: "ldclral xzr, x30, [sp]", inst: LDCLRALD, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xff, 0xf8}},
+		{name: "ldclral xzr, xzr, [x10]", inst: LDCLRALD, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xff, 0xf8}},
+		{name: "ldclral xzr, x10, [x10]", inst: LDCLRALD, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xff, 0xf8}},
+		{name: "ldclral xzr, x30, [x10]", inst: LDCLRALD, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xff, 0xf8}},
+		{name: "ldclral xzr, xzr, [x30]", inst: LDCLRALD, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xff, 0xf8}},
+		{name: "ldclral xzr, x10, [x30]", inst: LDCLRALD, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xff, 0xf8}},
+		{name: "ldclral xzr, x30, [x30]", inst: LDCLRALD, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xff, 0xf8}},
+		{name: "ldclral x10, xzr, [sp]", inst: LDCLRALD, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xea, 0xf8}},
+		{name: "ldclral x10, x10, [sp]", inst: LDCLRALD, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xea, 0xf8}},
+		{name: "ldclral x10, x30, [sp]", inst: LDCLRALD, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xea, 0xf8}},
+		{name: "ldclral x10, xzr, [x10]", inst: LDCLRALD, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xea, 0xf8}},
+		{name: "ldclral x10, x10, [x10]", inst: LDCLRALD, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xea, 0xf8}},
+		{name: "ldclral x10, x30, [x10]", inst: LDCLRALD, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xea, 0xf8}},
+		{name: "ldclral x10, xzr, [x30]", inst: LDCLRALD, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xea, 0xf8}},
+		{name: "ldclral x10, x10, [x30]", inst: LDCLRALD, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xea, 0xf8}},
+		{name: "ldclral x10, x30, [x30]", inst: LDCLRALD, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xea, 0xf8}},
+		{name: "ldclral x30, xzr, [sp]", inst: LDCLRALD, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xfe, 0xf8}},
+		{name: "ldclral x30, x10, [sp]", inst: LDCLRALD, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xfe, 0xf8}},
+		{name: "ldclral x30, x30, [sp]", inst: LDCLRALD, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xfe, 0xf8}},
+		{name: "ldclral x30, xzr, [x10]", inst: LDCLRALD, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xfe, 0xf8}},
+		{name: "ldclral x30, x10, [x10]", inst: LDCLRALD, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xfe, 0xf8}},
+		{name: "ldclral x30, x30, [x10]", inst: LDCLRALD, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xfe, 0xf8}},
+		{name: "ldclral x30, xzr, [x30]", inst: LDCLRALD, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xfe, 0xf8}},
+		{name: "ldclral x30, x10, [x30]", inst: LDCLRALD, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xfe, 0xf8}},
+		{name: "ldclral x30, x30, [x30]", inst: LDCLRALD, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xfe, 0xf8}},
+		{name: "ldclral wzr, wzr, [sp]", inst: LDCLRALW, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xff, 0xb8}},
+		{name: "ldclral wzr, w10, [sp]", inst: LDCLRALW, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xff, 0xb8}},
+		{name: "ldclral wzr, w30, [sp]", inst: LDCLRALW, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xff, 0xb8}},
+		{name: "ldclral wzr, wzr, [x10]", inst: LDCLRALW, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xff, 0xb8}},
+		{name: "ldclral wzr, w10, [x10]", inst: LDCLRALW, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xff, 0xb8}},
+		{name: "ldclral wzr, w30, [x10]", inst: LDCLRALW, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xff, 0xb8}},
+		{name: "ldclral wzr, wzr, [x30]", inst: LDCLRALW, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xff, 0xb8}},
+		{name: "ldclral wzr, w10, [x30]", inst: LDCLRALW, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xff, 0xb8}},
+		{name: "ldclral wzr, w30, [x30]", inst: LDCLRALW, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xff, 0xb8}},
+		{name: "ldclral w10, wzr, [sp]", inst: LDCLRALW, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xea, 0xb8}},
+		{name: "ldclral w10, w10, [sp]", inst: LDCLRALW, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xea, 0xb8}},
+		{name: "ldclral w10, w30, [sp]", inst: LDCLRALW, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xea, 0xb8}},
+		{name: "ldclral w10, wzr, [x10]", inst: LDCLRALW, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xea, 0xb8}},
+		{name: "ldclral w10, w10, [x10]", inst: LDCLRALW, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xea, 0xb8}},
+		{name: "ldclral w10, w30, [x10]", inst: LDCLRALW, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xea, 0xb8}},
+		{name: "ldclral w10, wzr, [x30]", inst: LDCLRALW, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xea, 0xb8}},
+		{name: "ldclral w10, w10, [x30]", inst: LDCLRALW, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xea, 0xb8}},
+		{name: "ldclral w10, w30, [x30]", inst: LDCLRALW, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xea, 0xb8}},
+		{name: "ldclral w30, wzr, [sp]", inst: LDCLRALW, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xfe, 0xb8}},
+		{name: "ldclral w30, w10, [sp]", inst: LDCLRALW, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xfe, 0xb8}},
+		{name: "ldclral w30, w30, [sp]", inst: LDCLRALW, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xfe, 0xb8}},
+		{name: "ldclral w30, wzr, [x10]", inst: LDCLRALW, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xfe, 0xb8}},
+		{name: "ldclral w30, w10, [x10]", inst: LDCLRALW, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xfe, 0xb8}},
+		{name: "ldclral w30, w30, [x10]", inst: LDCLRALW, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xfe, 0xb8}},
+		{name: "ldclral w30, wzr, [x30]", inst: LDCLRALW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xfe, 0xb8}},
+		{name: "ldclral w30, w10, [x30]", inst: LDCLRALW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xfe, 0xb8}},
+		{name: "ldclral w30, w30, [x30]", inst: LDCLRALW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xfe, 0xb8}},
+		{name: "ldclralh wzr, wzr, [sp]", inst: LDCLRALH, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xff, 0x78}},
+		{name: "ldclralh wzr, w10, [sp]", inst: LDCLRALH, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xff, 0x78}},
+		{name: "ldclralh wzr, w30, [sp]", inst: LDCLRALH, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xff, 0x78}},
+		{name: "ldclralh wzr, wzr, [x10]", inst: LDCLRALH, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xff, 0x78}},
+		{name: "ldclralh wzr, w10, [x10]", inst: LDCLRALH, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xff, 0x78}},
+		{name: "ldclralh wzr, w30, [x10]", inst: LDCLRALH, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xff, 0x78}},
+		{name: "ldclralh wzr, wzr, [x30]", inst: LDCLRALH, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xff, 0x78}},
+		{name: "ldclralh wzr, w10, [x30]", inst: LDCLRALH, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xff, 0x78}},
+		{name: "ldclralh wzr, w30, [x30]", inst: LDCLRALH, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xff, 0x78}},
+		{name: "ldclralh w10, wzr, [sp]", inst: LDCLRALH, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xea, 0x78}},
+		{name: "ldclralh w10, w10, [sp]", inst: LDCLRALH, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xea, 0x78}},
+		{name: "ldclralh w10, w30, [sp]", inst: LDCLRALH, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xea, 0x78}},
+		{name: "ldclralh w10, wzr, [x10]", inst: LDCLRALH, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xea, 0x78}},
+		{name: "ldclralh w10, w10, [x10]", inst: LDCLRALH, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xea, 0x78}},
+		{name: "ldclralh w10, w30, [x10]", inst: LDCLRALH, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xea, 0x78}},
+		{name: "ldclralh w10, wzr, [x30]", inst: LDCLRALH, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xea, 0x78}},
+		{name: "ldclralh w10, w10, [x30]", inst: LDCLRALH, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xea, 0x78}},
+		{name: "ldclralh w10, w30, [x30]", inst: LDCLRALH, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xea, 0x78}},
+		{name: "ldclralh w30, wzr, [sp]", inst: LDCLRALH, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xfe, 0x78}},
+		{name: "ldclralh w30, w10, [sp]", inst: LDCLRALH, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xfe, 0x78}},
+		{name: "ldclralh w30, w30, [sp]", inst: LDCLRALH, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xfe, 0x78}},
+		{name: "ldclralh w30, wzr, [x10]", inst: LDCLRALH, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xfe, 0x78}},
+		{name: "ldclralh w30, w10, [x10]", inst: LDCLRALH, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xfe, 0x78}},
+		{name: "ldclralh w30, w30, [x10]", inst: LDCLRALH, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xfe, 0x78}},
+		{name: "ldclralh w30, wzr, [x30]", inst: LDCLRALH, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xfe, 0x78}},
+		{name: "ldclralh w30, w10, [x30]", inst: LDCLRALH, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xfe, 0x78}},
+		{name: "ldclralh w30, w30, [x30]", inst: LDCLRALH, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xfe, 0x78}},
+		{name: "ldclralb wzr, wzr, [sp]", inst: LDCLRALB, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xff, 0x38}},
+		{name: "ldclralb wzr, w10, [sp]", inst: LDCLRALB, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xff, 0x38}},
+		{name: "ldclralb wzr, w30, [sp]", inst: LDCLRALB, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xff, 0x38}},
+		{name: "ldclralb wzr, wzr, [x10]", inst: LDCLRALB, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xff, 0x38}},
+		{name: "ldclralb wzr, w10, [x10]", inst: LDCLRALB, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xff, 0x38}},
+		{name: "ldclralb wzr, w30, [x10]", inst: LDCLRALB, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xff, 0x38}},
+		{name: "ldclralb wzr, wzr, [x30]", inst: LDCLRALB, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xff, 0x38}},
+		{name: "ldclralb wzr, w10, [x30]", inst: LDCLRALB, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xff, 0x38}},
+		{name: "ldclralb wzr, w30, [x30]", inst: LDCLRALB, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xff, 0x38}},
+		{name: "ldclralb w10, wzr, [sp]", inst: LDCLRALB, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xea, 0x38}},
+		{name: "ldclralb w10, w10, [sp]", inst: LDCLRALB, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xea, 0x38}},
+		{name: "ldclralb w10, w30, [sp]", inst: LDCLRALB, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xea, 0x38}},
+		{name: "ldclralb w10, wzr, [x10]", inst: LDCLRALB, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xea, 0x38}},
+		{name: "ldclralb w10, w10, [x10]", inst: LDCLRALB, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xea, 0x38}},
+		{name: "ldclralb w10, w30, [x10]", inst: LDCLRALB, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xea, 0x38}},
+		{name: "ldclralb w10, wzr, [x30]", inst: LDCLRALB, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xea, 0x38}},
+		{name: "ldclralb w10, w10, [x30]", inst: LDCLRALB, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xea, 0x38}},
+		{name: "ldclralb w10, w30, [x30]", inst: LDCLRALB, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xea, 0x38}},
+		{name: "ldclralb w30, wzr, [sp]", inst: LDCLRALB, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x13, 0xfe, 0x38}},
+		{name: "ldclralb w30, w10, [sp]", inst: LDCLRALB, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x13, 0xfe, 0x38}},
+		{name: "ldclralb w30, w30, [sp]", inst: LDCLRALB, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x13, 0xfe, 0x38}},
+		{name: "ldclralb w30, wzr, [x10]", inst: LDCLRALB, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x11, 0xfe, 0x38}},
+		{name: "ldclralb w30, w10, [x10]", inst: LDCLRALB, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x11, 0xfe, 0x38}},
+		{name: "ldclralb w30, w30, [x10]", inst: LDCLRALB, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x11, 0xfe, 0x38}},
+		{name: "ldclralb w30, wzr, [x30]", inst: LDCLRALB, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x13, 0xfe, 0x38}},
+		{name: "ldclralb w30, w10, [x30]", inst: LDCLRALB, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x13, 0xfe, 0x38}},
+		{name: "ldclralb w30, w30, [x30]", inst: LDCLRALB, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x13, 0xfe, 0x38}},
+		{name: "ldsetal xzr, xzr, [sp]", inst: LDSETALD, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xff, 0xf8}},
+		{name: "ldsetal xzr, x10, [sp]", inst: LDSETALD, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xff, 0xf8}},
+		{name: "ldsetal xzr, x30, [sp]", inst: LDSETALD, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xff, 0xf8}},
+		{name: "ldsetal xzr, xzr, [x10]", inst: LDSETALD, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xff, 0xf8}},
+		{name: "ldsetal xzr, x10, [x10]", inst: LDSETALD, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xff, 0xf8}},
+		{name: "ldsetal xzr, x30, [x10]", inst: LDSETALD, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xff, 0xf8}},
+		{name: "ldsetal xzr, xzr, [x30]", inst: LDSETALD, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xff, 0xf8}},
+		{name: "ldsetal xzr, x10, [x30]", inst: LDSETALD, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xff, 0xf8}},
+		{name: "ldsetal xzr, x30, [x30]", inst: LDSETALD, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xff, 0xf8}},
+		{name: "ldsetal x10, xzr, [sp]", inst: LDSETALD, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xea, 0xf8}},
+		{name: "ldsetal x10, x10, [sp]", inst: LDSETALD, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xea, 0xf8}},
+		{name: "ldsetal x10, x30, [sp]", inst: LDSETALD, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xea, 0xf8}},
+		{name: "ldsetal x10, xzr, [x10]", inst: LDSETALD, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xea, 0xf8}},
+		{name: "ldsetal x10, x10, [x10]", inst: LDSETALD, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xea, 0xf8}},
+		{name: "ldsetal x10, x30, [x10]", inst: LDSETALD, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xea, 0xf8}},
+		{name: "ldsetal x10, xzr, [x30]", inst: LDSETALD, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xea, 0xf8}},
+		{name: "ldsetal x10, x10, [x30]", inst: LDSETALD, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xea, 0xf8}},
+		{name: "ldsetal x10, x30, [x30]", inst: LDSETALD, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xea, 0xf8}},
+		{name: "ldsetal x30, xzr, [sp]", inst: LDSETALD, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xfe, 0xf8}},
+		{name: "ldsetal x30, x10, [sp]", inst: LDSETALD, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xfe, 0xf8}},
+		{name: "ldsetal x30, x30, [sp]", inst: LDSETALD, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xfe, 0xf8}},
+		{name: "ldsetal x30, xzr, [x10]", inst: LDSETALD, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xfe, 0xf8}},
+		{name: "ldsetal x30, x10, [x10]", inst: LDSETALD, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xfe, 0xf8}},
+		{name: "ldsetal x30, x30, [x10]", inst: LDSETALD, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xfe, 0xf8}},
+		{name: "ldsetal x30, xzr, [x30]", inst: LDSETALD, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xfe, 0xf8}},
+		{name: "ldsetal x30, x10, [x30]", inst: LDSETALD, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xfe, 0xf8}},
+		{name: "ldsetal x30, x30, [x30]", inst: LDSETALD, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xfe, 0xf8}},
+		{name: "ldsetal wzr, wzr, [sp]", inst: LDSETALW, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xff, 0xb8}},
+		{name: "ldsetal wzr, w10, [sp]", inst: LDSETALW, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xff, 0xb8}},
+		{name: "ldsetal wzr, w30, [sp]", inst: LDSETALW, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xff, 0xb8}},
+		{name: "ldsetal wzr, wzr, [x10]", inst: LDSETALW, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xff, 0xb8}},
+		{name: "ldsetal wzr, w10, [x10]", inst: LDSETALW, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xff, 0xb8}},
+		{name: "ldsetal wzr, w30, [x10]", inst: LDSETALW, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xff, 0xb8}},
+		{name: "ldsetal wzr, wzr, [x30]", inst: LDSETALW, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xff, 0xb8}},
+		{name: "ldsetal wzr, w10, [x30]", inst: LDSETALW, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xff, 0xb8}},
+		{name: "ldsetal wzr, w30, [x30]", inst: LDSETALW, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xff, 0xb8}},
+		{name: "ldsetal w10, wzr, [sp]", inst: LDSETALW, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xea, 0xb8}},
+		{name: "ldsetal w10, w10, [sp]", inst: LDSETALW, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xea, 0xb8}},
+		{name: "ldsetal w10, w30, [sp]", inst: LDSETALW, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xea, 0xb8}},
+		{name: "ldsetal w10, wzr, [x10]", inst: LDSETALW, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xea, 0xb8}},
+		{name: "ldsetal w10, w10, [x10]", inst: LDSETALW, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xea, 0xb8}},
+		{name: "ldsetal w10, w30, [x10]", inst: LDSETALW, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xea, 0xb8}},
+		{name: "ldsetal w10, wzr, [x30]", inst: LDSETALW, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xea, 0xb8}},
+		{name: "ldsetal w10, w10, [x30]", inst: LDSETALW, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xea, 0xb8}},
+		{name: "ldsetal w10, w30, [x30]", inst: LDSETALW, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xea, 0xb8}},
+		{name: "ldsetal w30, wzr, [sp]", inst: LDSETALW, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xfe, 0xb8}},
+		{name: "ldsetal w30, w10, [sp]", inst: LDSETALW, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xfe, 0xb8}},
+		{name: "ldsetal w30, w30, [sp]", inst: LDSETALW, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xfe, 0xb8}},
+		{name: "ldsetal w30, wzr, [x10]", inst: LDSETALW, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xfe, 0xb8}},
+		{name: "ldsetal w30, w10, [x10]", inst: LDSETALW, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xfe, 0xb8}},
+		{name: "ldsetal w30, w30, [x10]", inst: LDSETALW, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xfe, 0xb8}},
+		{name: "ldsetal w30, wzr, [x30]", inst: LDSETALW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xfe, 0xb8}},
+		{name: "ldsetal w30, w10, [x30]", inst: LDSETALW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xfe, 0xb8}},
+		{name: "ldsetal w30, w30, [x30]", inst: LDSETALW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xfe, 0xb8}},
+		{name: "ldsetalh wzr, wzr, [sp]", inst: LDSETALH, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xff, 0x78}},
+		{name: "ldsetalh wzr, w10, [sp]", inst: LDSETALH, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xff, 0x78}},
+		{name: "ldsetalh wzr, w30, [sp]", inst: LDSETALH, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xff, 0x78}},
+		{name: "ldsetalh wzr, wzr, [x10]", inst: LDSETALH, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xff, 0x78}},
+		{name: "ldsetalh wzr, w10, [x10]", inst: LDSETALH, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xff, 0x78}},
+		{name: "ldsetalh wzr, w30, [x10]", inst: LDSETALH, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xff, 0x78}},
+		{name: "ldsetalh wzr, wzr, [x30]", inst: LDSETALH, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xff, 0x78}},
+		{name: "ldsetalh wzr, w10, [x30]", inst: LDSETALH, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xff, 0x78}},
+		{name: "ldsetalh wzr, w30, [x30]", inst: LDSETALH, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xff, 0x78}},
+		{name: "ldsetalh w10, wzr, [sp]", inst: LDSETALH, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xea, 0x78}},
+		{name: "ldsetalh w10, w10, [sp]", inst: LDSETALH, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xea, 0x78}},
+		{name: "ldsetalh w10, w30, [sp]", inst: LDSETALH, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xea, 0x78}},
+		{name: "ldsetalh w10, wzr, [x10]", inst: LDSETALH, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xea, 0x78}},
+		{name: "ldsetalh w10, w10, [x10]", inst: LDSETALH, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xea, 0x78}},
+		{name: "ldsetalh w10, w30, [x10]", inst: LDSETALH, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xea, 0x78}},
+		{name: "ldsetalh w10, wzr, [x30]", inst: LDSETALH, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xea, 0x78}},
+		{name: "ldsetalh w10, w10, [x30]", inst: LDSETALH, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xea, 0x78}},
+		{name: "ldsetalh w10, w30, [x30]", inst: LDSETALH, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xea, 0x78}},
+		{name: "ldsetalh w30, wzr, [sp]", inst: LDSETALH, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xfe, 0x78}},
+		{name: "ldsetalh w30, w10, [sp]", inst: LDSETALH, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xfe, 0x78}},
+		{name: "ldsetalh w30, w30, [sp]", inst: LDSETALH, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xfe, 0x78}},
+		{name: "ldsetalh w30, wzr, [x10]", inst: LDSETALH, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xfe, 0x78}},
+		{name: "ldsetalh w30, w10, [x10]", inst: LDSETALH, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xfe, 0x78}},
+		{name: "ldsetalh w30, w30, [x10]", inst: LDSETALH, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xfe, 0x78}},
+		{name: "ldsetalh w30, wzr, [x30]", inst: LDSETALH, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xfe, 0x78}},
+		{name: "ldsetalh w30, w10, [x30]", inst: LDSETALH, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xfe, 0x78}},
+		{name: "ldsetalh w30, w30, [x30]", inst: LDSETALH, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xfe, 0x78}},
+		{name: "ldsetalb wzr, wzr, [sp]", inst: LDSETALB, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xff, 0x38}},
+		{name: "ldsetalb wzr, w10, [sp]", inst: LDSETALB, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xff, 0x38}},
+		{name: "ldsetalb wzr, w30, [sp]", inst: LDSETALB, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xff, 0x38}},
+		{name: "ldsetalb wzr, wzr, [x10]", inst: LDSETALB, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xff, 0x38}},
+		{name: "ldsetalb wzr, w10, [x10]", inst: LDSETALB, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xff, 0x38}},
+		{name: "ldsetalb wzr, w30, [x10]", inst: LDSETALB, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xff, 0x38}},
+		{name: "ldsetalb wzr, wzr, [x30]", inst: LDSETALB, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xff, 0x38}},
+		{name: "ldsetalb wzr, w10, [x30]", inst: LDSETALB, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xff, 0x38}},
+		{name: "ldsetalb wzr, w30, [x30]", inst: LDSETALB, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xff, 0x38}},
+		{name: "ldsetalb w10, wzr, [sp]", inst: LDSETALB, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xea, 0x38}},
+		{name: "ldsetalb w10, w10, [sp]", inst: LDSETALB, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xea, 0x38}},
+		{name: "ldsetalb w10, w30, [sp]", inst: LDSETALB, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xea, 0x38}},
+		{name: "ldsetalb w10, wzr, [x10]", inst: LDSETALB, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xea, 0x38}},
+		{name: "ldsetalb w10, w10, [x10]", inst: LDSETALB, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xea, 0x38}},
+		{name: "ldsetalb w10, w30, [x10]", inst: LDSETALB, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xea, 0x38}},
+		{name: "ldsetalb w10, wzr, [x30]", inst: LDSETALB, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xea, 0x38}},
+		{name: "ldsetalb w10, w10, [x30]", inst: LDSETALB, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xea, 0x38}},
+		{name: "ldsetalb w10, w30, [x30]", inst: LDSETALB, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xea, 0x38}},
+		{name: "ldsetalb w30, wzr, [sp]", inst: LDSETALB, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x33, 0xfe, 0x38}},
+		{name: "ldsetalb w30, w10, [sp]", inst: LDSETALB, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x33, 0xfe, 0x38}},
+		{name: "ldsetalb w30, w30, [sp]", inst: LDSETALB, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x33, 0xfe, 0x38}},
+		{name: "ldsetalb w30, wzr, [x10]", inst: LDSETALB, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x31, 0xfe, 0x38}},
+		{name: "ldsetalb w30, w10, [x10]", inst: LDSETALB, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x31, 0xfe, 0x38}},
+		{name: "ldsetalb w30, w30, [x10]", inst: LDSETALB, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x31, 0xfe, 0x38}},
+		{name: "ldsetalb w30, wzr, [x30]", inst: LDSETALB, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x33, 0xfe, 0x38}},
+		{name: "ldsetalb w30, w10, [x30]", inst: LDSETALB, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x33, 0xfe, 0x38}},
+		{name: "ldsetalb w30, w30, [x30]", inst: LDSETALB, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x33, 0xfe, 0x38}},
+		{name: "ldeoral xzr, xzr, [sp]", inst: LDEORALD, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xff, 0xf8}},
+		{name: "ldeoral xzr, x10, [sp]", inst: LDEORALD, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xff, 0xf8}},
+		{name: "ldeoral xzr, x30, [sp]", inst: LDEORALD, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xff, 0xf8}},
+		{name: "ldeoral xzr, xzr, [x10]", inst: LDEORALD, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xff, 0xf8}},
+		{name: "ldeoral xzr, x10, [x10]", inst: LDEORALD, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xff, 0xf8}},
+		{name: "ldeoral xzr, x30, [x10]", inst: LDEORALD, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xff, 0xf8}},
+		{name: "ldeoral xzr, xzr, [x30]", inst: LDEORALD, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xff, 0xf8}},
+		{name: "ldeoral xzr, x10, [x30]", inst: LDEORALD, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xff, 0xf8}},
+		{name: "ldeoral xzr, x30, [x30]", inst: LDEORALD, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xff, 0xf8}},
+		{name: "ldeoral x10, xzr, [sp]", inst: LDEORALD, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xea, 0xf8}},
+		{name: "ldeoral x10, x10, [sp]", inst: LDEORALD, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xea, 0xf8}},
+		{name: "ldeoral x10, x30, [sp]", inst: LDEORALD, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xea, 0xf8}},
+		{name: "ldeoral x10, xzr, [x10]", inst: LDEORALD, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xea, 0xf8}},
+		{name: "ldeoral x10, x10, [x10]", inst: LDEORALD, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xea, 0xf8}},
+		{name: "ldeoral x10, x30, [x10]", inst: LDEORALD, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xea, 0xf8}},
+		{name: "ldeoral x10, xzr, [x30]", inst: LDEORALD, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xea, 0xf8}},
+		{name: "ldeoral x10, x10, [x30]", inst: LDEORALD, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xea, 0xf8}},
+		{name: "ldeoral x10, x30, [x30]", inst: LDEORALD, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xea, 0xf8}},
+		{name: "ldeoral x30, xzr, [sp]", inst: LDEORALD, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xfe, 0xf8}},
+		{name: "ldeoral x30, x10, [sp]", inst: LDEORALD, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xfe, 0xf8}},
+		{name: "ldeoral x30, x30, [sp]", inst: LDEORALD, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xfe, 0xf8}},
+		{name: "ldeoral x30, xzr, [x10]", inst: LDEORALD, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xfe, 0xf8}},
+		{name: "ldeoral x30, x10, [x10]", inst: LDEORALD, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xfe, 0xf8}},
+		{name: "ldeoral x30, x30, [x10]", inst: LDEORALD, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xfe, 0xf8}},
+		{name: "ldeoral x30, xzr, [x30]", inst: LDEORALD, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xfe, 0xf8}},
+		{name: "ldeoral x30, x10, [x30]", inst: LDEORALD, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xfe, 0xf8}},
+		{name: "ldeoral x30, x30, [x30]", inst: LDEORALD, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xfe, 0xf8}},
+		{name: "ldeoral wzr, wzr, [sp]", inst: LDEORALW, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xff, 0xb8}},
+		{name: "ldeoral wzr, w10, [sp]", inst: LDEORALW, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xff, 0xb8}},
+		{name: "ldeoral wzr, w30, [sp]", inst: LDEORALW, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xff, 0xb8}},
+		{name: "ldeoral wzr, wzr, [x10]", inst: LDEORALW, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xff, 0xb8}},
+		{name: "ldeoral wzr, w10, [x10]", inst: LDEORALW, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xff, 0xb8}},
+		{name: "ldeoral wzr, w30, [x10]", inst: LDEORALW, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xff, 0xb8}},
+		{name: "ldeoral wzr, wzr, [x30]", inst: LDEORALW, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xff, 0xb8}},
+		{name: "ldeoral wzr, w10, [x30]", inst: LDEORALW, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xff, 0xb8}},
+		{name: "ldeoral wzr, w30, [x30]", inst: LDEORALW, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xff, 0xb8}},
+		{name: "ldeoral w10, wzr, [sp]", inst: LDEORALW, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xea, 0xb8}},
+		{name: "ldeoral w10, w10, [sp]", inst: LDEORALW, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xea, 0xb8}},
+		{name: "ldeoral w10, w30, [sp]", inst: LDEORALW, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xea, 0xb8}},
+		{name: "ldeoral w10, wzr, [x10]", inst: LDEORALW, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xea, 0xb8}},
+		{name: "ldeoral w10, w10, [x10]", inst: LDEORALW, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xea, 0xb8}},
+		{name: "ldeoral w10, w30, [x10]", inst: LDEORALW, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xea, 0xb8}},
+		{name: "ldeoral w10, wzr, [x30]", inst: LDEORALW, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xea, 0xb8}},
+		{name: "ldeoral w10, w10, [x30]", inst: LDEORALW, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xea, 0xb8}},
+		{name: "ldeoral w10, w30, [x30]", inst: LDEORALW, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xea, 0xb8}},
+		{name: "ldeoral w30, wzr, [sp]", inst: LDEORALW, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xfe, 0xb8}},
+		{name: "ldeoral w30, w10, [sp]", inst: LDEORALW, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xfe, 0xb8}},
+		{name: "ldeoral w30, w30, [sp]", inst: LDEORALW, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xfe, 0xb8}},
+		{name: "ldeoral w30, wzr, [x10]", inst: LDEORALW, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xfe, 0xb8}},
+		{name: "ldeoral w30, w10, [x10]", inst: LDEORALW, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xfe, 0xb8}},
+		{name: "ldeoral w30, w30, [x10]", inst: LDEORALW, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xfe, 0xb8}},
+		{name: "ldeoral w30, wzr, [x30]", inst: LDEORALW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xfe, 0xb8}},
+		{name: "ldeoral w30, w10, [x30]", inst: LDEORALW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xfe, 0xb8}},
+		{name: "ldeoral w30, w30, [x30]", inst: LDEORALW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xfe, 0xb8}},
+		{name: "ldeoralh wzr, wzr, [sp]", inst: LDEORALH, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xff, 0x78}},
+		{name: "ldeoralh wzr, w10, [sp]", inst: LDEORALH, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xff, 0x78}},
+		{name: "ldeoralh wzr, w30, [sp]", inst: LDEORALH, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xff, 0x78}},
+		{name: "ldeoralh wzr, wzr, [x10]", inst: LDEORALH, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xff, 0x78}},
+		{name: "ldeoralh wzr, w10, [x10]", inst: LDEORALH, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xff, 0x78}},
+		{name: "ldeoralh wzr, w30, [x10]", inst: LDEORALH, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xff, 0x78}},
+		{name: "ldeoralh wzr, wzr, [x30]", inst: LDEORALH, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xff, 0x78}},
+		{name: "ldeoralh wzr, w10, [x30]", inst: LDEORALH, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xff, 0x78}},
+		{name: "ldeoralh wzr, w30, [x30]", inst: LDEORALH, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xff, 0x78}},
+		{name: "ldeoralh w10, wzr, [sp]", inst: LDEORALH, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xea, 0x78}},
+		{name: "ldeoralh w10, w10, [sp]", inst: LDEORALH, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xea, 0x78}},
+		{name: "ldeoralh w10, w30, [sp]", inst: LDEORALH, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xea, 0x78}},
+		{name: "ldeoralh w10, wzr, [x10]", inst: LDEORALH, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xea, 0x78}},
+		{name: "ldeoralh w10, w10, [x10]", inst: LDEORALH, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xea, 0x78}},
+		{name: "ldeoralh w10, w30, [x10]", inst: LDEORALH, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xea, 0x78}},
+		{name: "ldeoralh w10, wzr, [x30]", inst: LDEORALH, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xea, 0x78}},
+		{name: "ldeoralh w10, w10, [x30]", inst: LDEORALH, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xea, 0x78}},
+		{name: "ldeoralh w10, w30, [x30]", inst: LDEORALH, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xea, 0x78}},
+		{name: "ldeoralh w30, wzr, [sp]", inst: LDEORALH, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xfe, 0x78}},
+		{name: "ldeoralh w30, w10, [sp]", inst: LDEORALH, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xfe, 0x78}},
+		{name: "ldeoralh w30, w30, [sp]", inst: LDEORALH, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xfe, 0x78}},
+		{name: "ldeoralh w30, wzr, [x10]", inst: LDEORALH, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xfe, 0x78}},
+		{name: "ldeoralh w30, w10, [x10]", inst: LDEORALH, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xfe, 0x78}},
+		{name: "ldeoralh w30, w30, [x10]", inst: LDEORALH, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xfe, 0x78}},
+		{name: "ldeoralh w30, wzr, [x30]", inst: LDEORALH, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xfe, 0x78}},
+		{name: "ldeoralh w30, w10, [x30]", inst: LDEORALH, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xfe, 0x78}},
+		{name: "ldeoralh w30, w30, [x30]", inst: LDEORALH, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xfe, 0x78}},
+		{name: "ldeoralb wzr, wzr, [sp]", inst: LDEORALB, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xff, 0x38}},
+		{name: "ldeoralb wzr, w10, [sp]", inst: LDEORALB, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xff, 0x38}},
+		{name: "ldeoralb wzr, w30, [sp]", inst: LDEORALB, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xff, 0x38}},
+		{name: "ldeoralb wzr, wzr, [x10]", inst: LDEORALB, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xff, 0x38}},
+		{name: "ldeoralb wzr, w10, [x10]", inst: LDEORALB, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xff, 0x38}},
+		{name: "ldeoralb wzr, w30, [x10]", inst: LDEORALB, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xff, 0x38}},
+		{name: "ldeoralb wzr, wzr, [x30]", inst: LDEORALB, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xff, 0x38}},
+		{name: "ldeoralb wzr, w10, [x30]", inst: LDEORALB, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xff, 0x38}},
+		{name: "ldeoralb wzr, w30, [x30]", inst: LDEORALB, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xff, 0x38}},
+		{name: "ldeoralb w10, wzr, [sp]", inst: LDEORALB, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xea, 0x38}},
+		{name: "ldeoralb w10, w10, [sp]", inst: LDEORALB, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xea, 0x38}},
+		{name: "ldeoralb w10, w30, [sp]", inst: LDEORALB, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xea, 0x38}},
+		{name: "ldeoralb w10, wzr, [x10]", inst: LDEORALB, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xea, 0x38}},
+		{name: "ldeoralb w10, w10, [x10]", inst: LDEORALB, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xea, 0x38}},
+		{name: "ldeoralb w10, w30, [x10]", inst: LDEORALB, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xea, 0x38}},
+		{name: "ldeoralb w10, wzr, [x30]", inst: LDEORALB, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xea, 0x38}},
+		{name: "ldeoralb w10, w10, [x30]", inst: LDEORALB, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xea, 0x38}},
+		{name: "ldeoralb w10, w30, [x30]", inst: LDEORALB, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xea, 0x38}},
+		{name: "ldeoralb w30, wzr, [sp]", inst: LDEORALB, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x23, 0xfe, 0x38}},
+		{name: "ldeoralb w30, w10, [sp]", inst: LDEORALB, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x23, 0xfe, 0x38}},
+		{name: "ldeoralb w30, w30, [sp]", inst: LDEORALB, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x23, 0xfe, 0x38}},
+		{name: "ldeoralb w30, wzr, [x10]", inst: LDEORALB, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x21, 0xfe, 0x38}},
+		{name: "ldeoralb w30, w10, [x10]", inst: LDEORALB, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x21, 0xfe, 0x38}},
+		{name: "ldeoralb w30, w30, [x10]", inst: LDEORALB, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x21, 0xfe, 0x38}},
+		{name: "ldeoralb w30, wzr, [x30]", inst: LDEORALB, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x23, 0xfe, 0x38}},
+		{name: "ldeoralb w30, w10, [x30]", inst: LDEORALB, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x23, 0xfe, 0x38}},
+		{name: "ldeoralb w30, w30, [x30]", inst: LDEORALB, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x23, 0xfe, 0x38}},
+		{name: "swpal xzr, xzr, [sp]", inst: SWPALD, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xff, 0xf8}},
+		{name: "swpal xzr, x10, [sp]", inst: SWPALD, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xff, 0xf8}},
+		{name: "swpal xzr, x30, [sp]", inst: SWPALD, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xff, 0xf8}},
+		{name: "swpal xzr, xzr, [x10]", inst: SWPALD, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xff, 0xf8}},
+		{name: "swpal xzr, x10, [x10]", inst: SWPALD, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xff, 0xf8}},
+		{name: "swpal xzr, x30, [x10]", inst: SWPALD, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xff, 0xf8}},
+		{name: "swpal xzr, xzr, [x30]", inst: SWPALD, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xff, 0xf8}},
+		{name: "swpal xzr, x10, [x30]", inst: SWPALD, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xff, 0xf8}},
+		{name: "swpal xzr, x30, [x30]", inst: SWPALD, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xff, 0xf8}},
+		{name: "swpal x10, xzr, [sp]", inst: SWPALD, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xea, 0xf8}},
+		{name: "swpal x10, x10, [sp]", inst: SWPALD, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xea, 0xf8}},
+		{name: "swpal x10, x30, [sp]", inst: SWPALD, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xea, 0xf8}},
+		{name: "swpal x10, xzr, [x10]", inst: SWPALD, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xea, 0xf8}},
+		{name: "swpal x10, x10, [x10]", inst: SWPALD, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xea, 0xf8}},
+		{name: "swpal x10, x30, [x10]", inst: SWPALD, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xea, 0xf8}},
+		{name: "swpal x10, xzr, [x30]", inst: SWPALD, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xea, 0xf8}},
+		{name: "swpal x10, x10, [x30]", inst: SWPALD, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xea, 0xf8}},
+		{name: "swpal x10, x30, [x30]", inst: SWPALD, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xea, 0xf8}},
+		{name: "swpal x30, xzr, [sp]", inst: SWPALD, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xfe, 0xf8}},
+		{name: "swpal x30, x10, [sp]", inst: SWPALD, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xfe, 0xf8}},
+		{name: "swpal x30, x30, [sp]", inst: SWPALD, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xfe, 0xf8}},
+		{name: "swpal x30, xzr, [x10]", inst: SWPALD, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xfe, 0xf8}},
+		{name: "swpal x30, x10, [x10]", inst: SWPALD, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xfe, 0xf8}},
+		{name: "swpal x30, x30, [x10]", inst: SWPALD, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xfe, 0xf8}},
+		{name: "swpal x30, xzr, [x30]", inst: SWPALD, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xfe, 0xf8}},
+		{name: "swpal x30, x10, [x30]", inst: SWPALD, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xfe, 0xf8}},
+		{name: "swpal x30, x30, [x30]", inst: SWPALD, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xfe, 0xf8}},
+		{name: "swpal wzr, wzr, [sp]", inst: SWPALW, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xff, 0xb8}},
+		{name: "swpal wzr, w10, [sp]", inst: SWPALW, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xff, 0xb8}},
+		{name: "swpal wzr, w30, [sp]", inst: SWPALW, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xff, 0xb8}},
+		{name: "swpal wzr, wzr, [x10]", inst: SWPALW, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xff, 0xb8}},
+		{name: "swpal wzr, w10, [x10]", inst: SWPALW, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xff, 0xb8}},
+		{name: "swpal wzr, w30, [x10]", inst: SWPALW, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xff, 0xb8}},
+		{name: "swpal wzr, wzr, [x30]", inst: SWPALW, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xff, 0xb8}},
+		{name: "swpal wzr, w10, [x30]", inst: SWPALW, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xff, 0xb8}},
+		{name: "swpal wzr, w30, [x30]", inst: SWPALW, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xff, 0xb8}},
+		{name: "swpal w10, wzr, [sp]", inst: SWPALW, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xea, 0xb8}},
+		{name: "swpal w10, w10, [sp]", inst: SWPALW, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xea, 0xb8}},
+		{name: "swpal w10, w30, [sp]", inst: SWPALW, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xea, 0xb8}},
+		{name: "swpal w10, wzr, [x10]", inst: SWPALW, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xea, 0xb8}},
+		{name: "swpal w10, w10, [x10]", inst: SWPALW, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xea, 0xb8}},
+		{name: "swpal w10, w30, [x10]", inst: SWPALW, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xea, 0xb8}},
+		{name: "swpal w10, wzr, [x30]", inst: SWPALW, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xea, 0xb8}},
+		{name: "swpal w10, w10, [x30]", inst: SWPALW, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xea, 0xb8}},
+		{name: "swpal w10, w30, [x30]", inst: SWPALW, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xea, 0xb8}},
+		{name: "swpal w30, wzr, [sp]", inst: SWPALW, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xfe, 0xb8}},
+		{name: "swpal w30, w10, [sp]", inst: SWPALW, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xfe, 0xb8}},
+		{name: "swpal w30, w30, [sp]", inst: SWPALW, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xfe, 0xb8}},
+		{name: "swpal w30, wzr, [x10]", inst: SWPALW, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xfe, 0xb8}},
+		{name: "swpal w30, w10, [x10]", inst: SWPALW, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xfe, 0xb8}},
+		{name: "swpal w30, w30, [x10]", inst: SWPALW, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xfe, 0xb8}},
+		{name: "swpal w30, wzr, [x30]", inst: SWPALW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xfe, 0xb8}},
+		{name: "swpal w30, w10, [x30]", inst: SWPALW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xfe, 0xb8}},
+		{name: "swpal w30, w30, [x30]", inst: SWPALW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xfe, 0xb8}},
+		{name: "swpalh wzr, wzr, [sp]", inst: SWPALH, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xff, 0x78}},
+		{name: "swpalh wzr, w10, [sp]", inst: SWPALH, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xff, 0x78}},
+		{name: "swpalh wzr, w30, [sp]", inst: SWPALH, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xff, 0x78}},
+		{name: "swpalh wzr, wzr, [x10]", inst: SWPALH, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xff, 0x78}},
+		{name: "swpalh wzr, w10, [x10]", inst: SWPALH, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xff, 0x78}},
+		{name: "swpalh wzr, w30, [x10]", inst: SWPALH, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xff, 0x78}},
+		{name: "swpalh wzr, wzr, [x30]", inst: SWPALH, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xff, 0x78}},
+		{name: "swpalh wzr, w10, [x30]", inst: SWPALH, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xff, 0x78}},
+		{name: "swpalh wzr, w30, [x30]", inst: SWPALH, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xff, 0x78}},
+		{name: "swpalh w10, wzr, [sp]", inst: SWPALH, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xea, 0x78}},
+		{name: "swpalh w10, w10, [sp]", inst: SWPALH, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xea, 0x78}},
+		{name: "swpalh w10, w30, [sp]", inst: SWPALH, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xea, 0x78}},
+		{name: "swpalh w10, wzr, [x10]", inst: SWPALH, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xea, 0x78}},
+		{name: "swpalh w10, w10, [x10]", inst: SWPALH, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xea, 0x78}},
+		{name: "swpalh w10, w30, [x10]", inst: SWPALH, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xea, 0x78}},
+		{name: "swpalh w10, wzr, [x30]", inst: SWPALH, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xea, 0x78}},
+		{name: "swpalh w10, w10, [x30]", inst: SWPALH, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xea, 0x78}},
+		{name: "swpalh w10, w30, [x30]", inst: SWPALH, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xea, 0x78}},
+		{name: "swpalh w30, wzr, [sp]", inst: SWPALH, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xfe, 0x78}},
+		{name: "swpalh w30, w10, [sp]", inst: SWPALH, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xfe, 0x78}},
+		{name: "swpalh w30, w30, [sp]", inst: SWPALH, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xfe, 0x78}},
+		{name: "swpalh w30, wzr, [x10]", inst: SWPALH, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xfe, 0x78}},
+		{name: "swpalh w30, w10, [x10]", inst: SWPALH, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xfe, 0x78}},
+		{name: "swpalh w30, w30, [x10]", inst: SWPALH, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xfe, 0x78}},
+		{name: "swpalh w30, wzr, [x30]", inst: SWPALH, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xfe, 0x78}},
+		{name: "swpalh w30, w10, [x30]", inst: SWPALH, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xfe, 0x78}},
+		{name: "swpalh w30, w30, [x30]", inst: SWPALH, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xfe, 0x78}},
+		{name: "swpalb wzr, wzr, [sp]", inst: SWPALB, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xff, 0x38}},
+		{name: "swpalb wzr, w10, [sp]", inst: SWPALB, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xff, 0x38}},
+		{name: "swpalb wzr, w30, [sp]", inst: SWPALB, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xff, 0x38}},
+		{name: "swpalb wzr, wzr, [x10]", inst: SWPALB, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xff, 0x38}},
+		{name: "swpalb wzr, w10, [x10]", inst: SWPALB, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xff, 0x38}},
+		{name: "swpalb wzr, w30, [x10]", inst: SWPALB, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xff, 0x38}},
+		{name: "swpalb wzr, wzr, [x30]", inst: SWPALB, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xff, 0x38}},
+		{name: "swpalb wzr, w10, [x30]", inst: SWPALB, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xff, 0x38}},
+		{name: "swpalb wzr, w30, [x30]", inst: SWPALB, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xff, 0x38}},
+		{name: "swpalb w10, wzr, [sp]", inst: SWPALB, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xea, 0x38}},
+		{name: "swpalb w10, w10, [sp]", inst: SWPALB, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xea, 0x38}},
+		{name: "swpalb w10, w30, [sp]", inst: SWPALB, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xea, 0x38}},
+		{name: "swpalb w10, wzr, [x10]", inst: SWPALB, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xea, 0x38}},
+		{name: "swpalb w10, w10, [x10]", inst: SWPALB, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xea, 0x38}},
+		{name: "swpalb w10, w30, [x10]", inst: SWPALB, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xea, 0x38}},
+		{name: "swpalb w10, wzr, [x30]", inst: SWPALB, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xea, 0x38}},
+		{name: "swpalb w10, w10, [x30]", inst: SWPALB, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xea, 0x38}},
+		{name: "swpalb w10, w30, [x30]", inst: SWPALB, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xea, 0x38}},
+		{name: "swpalb w30, wzr, [sp]", inst: SWPALB, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0x83, 0xfe, 0x38}},
+		{name: "swpalb w30, w10, [sp]", inst: SWPALB, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0x83, 0xfe, 0x38}},
+		{name: "swpalb w30, w30, [sp]", inst: SWPALB, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0x83, 0xfe, 0x38}},
+		{name: "swpalb w30, wzr, [x10]", inst: SWPALB, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0x81, 0xfe, 0x38}},
+		{name: "swpalb w30, w10, [x10]", inst: SWPALB, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0x81, 0xfe, 0x38}},
+		{name: "swpalb w30, w30, [x10]", inst: SWPALB, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0x81, 0xfe, 0x38}},
+		{name: "swpalb w30, wzr, [x30]", inst: SWPALB, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0x83, 0xfe, 0x38}},
+		{name: "swpalb w30, w10, [x30]", inst: SWPALB, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0x83, 0xfe, 0x38}},
+		{name: "swpalb w30, w30, [x30]", inst: SWPALB, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0x83, 0xfe, 0x38}},
+		{name: "casal xzr, xzr, [sp]", inst: CASALD, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xff, 0xc8}},
+		{name: "casal xzr, x10, [sp]", inst: CASALD, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xff, 0xc8}},
+		{name: "casal xzr, x30, [sp]", inst: CASALD, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xff, 0xc8}},
+		{name: "casal xzr, xzr, [x10]", inst: CASALD, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xff, 0xc8}},
+		{name: "casal xzr, x10, [x10]", inst: CASALD, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xff, 0xc8}},
+		{name: "casal xzr, x30, [x10]", inst: CASALD, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xff, 0xc8}},
+		{name: "casal xzr, xzr, [x30]", inst: CASALD, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xff, 0xc8}},
+		{name: "casal xzr, x10, [x30]", inst: CASALD, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xff, 0xc8}},
+		{name: "casal xzr, x30, [x30]", inst: CASALD, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xff, 0xc8}},
+		{name: "casal x10, xzr, [sp]", inst: CASALD, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xea, 0xc8}},
+		{name: "casal x10, x10, [sp]", inst: CASALD, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xea, 0xc8}},
+		{name: "casal x10, x30, [sp]", inst: CASALD, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xea, 0xc8}},
+		{name: "casal x10, xzr, [x10]", inst: CASALD, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xea, 0xc8}},
+		{name: "casal x10, x10, [x10]", inst: CASALD, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xea, 0xc8}},
+		{name: "casal x10, x30, [x10]", inst: CASALD, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xea, 0xc8}},
+		{name: "casal x10, xzr, [x30]", inst: CASALD, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xea, 0xc8}},
+		{name: "casal x10, x10, [x30]", inst: CASALD, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xea, 0xc8}},
+		{name: "casal x10, x30, [x30]", inst: CASALD, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xea, 0xc8}},
+		{name: "casal x30, xzr, [sp]", inst: CASALD, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xfe, 0xc8}},
+		{name: "casal x30, x10, [sp]", inst: CASALD, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xfe, 0xc8}},
+		{name: "casal x30, x30, [sp]", inst: CASALD, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xfe, 0xc8}},
+		{name: "casal x30, xzr, [x10]", inst: CASALD, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xfe, 0xc8}},
+		{name: "casal x30, x10, [x10]", inst: CASALD, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xfe, 0xc8}},
+		{name: "casal x30, x30, [x10]", inst: CASALD, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xfe, 0xc8}},
+		{name: "casal x30, xzr, [x30]", inst: CASALD, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xfe, 0xc8}},
+		{name: "casal x30, x10, [x30]", inst: CASALD, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xfe, 0xc8}},
+		{name: "casal x30, x30, [x30]", inst: CASALD, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xfe, 0xc8}},
+		{name: "casal wzr, wzr, [sp]", inst: CASALW, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xff, 0x88}},
+		{name: "casal wzr, w10, [sp]", inst: CASALW, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xff, 0x88}},
+		{name: "casal wzr, w30, [sp]", inst: CASALW, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xff, 0x88}},
+		{name: "casal wzr, wzr, [x10]", inst: CASALW, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xff, 0x88}},
+		{name: "casal wzr, w10, [x10]", inst: CASALW, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xff, 0x88}},
+		{name: "casal wzr, w30, [x10]", inst: CASALW, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xff, 0x88}},
+		{name: "casal wzr, wzr, [x30]", inst: CASALW, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xff, 0x88}},
+		{name: "casal wzr, w10, [x30]", inst: CASALW, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xff, 0x88}},
+		{name: "casal wzr, w30, [x30]", inst: CASALW, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xff, 0x88}},
+		{name: "casal w10, wzr, [sp]", inst: CASALW, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xea, 0x88}},
+		{name: "casal w10, w10, [sp]", inst: CASALW, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xea, 0x88}},
+		{name: "casal w10, w30, [sp]", inst: CASALW, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xea, 0x88}},
+		{name: "casal w10, wzr, [x10]", inst: CASALW, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xea, 0x88}},
+		{name: "casal w10, w10, [x10]", inst: CASALW, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xea, 0x88}},
+		{name: "casal w10, w30, [x10]", inst: CASALW, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xea, 0x88}},
+		{name: "casal w10, wzr, [x30]", inst: CASALW, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xea, 0x88}},
+		{name: "casal w10, w10, [x30]", inst: CASALW, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xea, 0x88}},
+		{name: "casal w10, w30, [x30]", inst: CASALW, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xea, 0x88}},
+		{name: "casal w30, wzr, [sp]", inst: CASALW, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xfe, 0x88}},
+		{name: "casal w30, w10, [sp]", inst: CASALW, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xfe, 0x88}},
+		{name: "casal w30, w30, [sp]", inst: CASALW, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xfe, 0x88}},
+		{name: "casal w30, wzr, [x10]", inst: CASALW, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xfe, 0x88}},
+		{name: "casal w30, w10, [x10]", inst: CASALW, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xfe, 0x88}},
+		{name: "casal w30, w30, [x10]", inst: CASALW, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xfe, 0x88}},
+		{name: "casal w30, wzr, [x30]", inst: CASALW, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xfe, 0x88}},
+		{name: "casal w30, w10, [x30]", inst: CASALW, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xfe, 0x88}},
+		{name: "casal w30, w30, [x30]", inst: CASALW, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xfe, 0x88}},
+		{name: "casalh wzr, wzr, [sp]", inst: CASALH, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xff, 0x48}},
+		{name: "casalh wzr, w10, [sp]", inst: CASALH, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xff, 0x48}},
+		{name: "casalh wzr, w30, [sp]", inst: CASALH, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xff, 0x48}},
+		{name: "casalh wzr, wzr, [x10]", inst: CASALH, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xff, 0x48}},
+		{name: "casalh wzr, w10, [x10]", inst: CASALH, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xff, 0x48}},
+		{name: "casalh wzr, w30, [x10]", inst: CASALH, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xff, 0x48}},
+		{name: "casalh wzr, wzr, [x30]", inst: CASALH, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xff, 0x48}},
+		{name: "casalh wzr, w10, [x30]", inst: CASALH, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xff, 0x48}},
+		{name: "casalh wzr, w30, [x30]", inst: CASALH, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xff, 0x48}},
+		{name: "casalh w10, wzr, [sp]", inst: CASALH, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xea, 0x48}},
+		{name: "casalh w10, w10, [sp]", inst: CASALH, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xea, 0x48}},
+		{name: "casalh w10, w30, [sp]", inst: CASALH, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xea, 0x48}},
+		{name: "casalh w10, wzr, [x10]", inst: CASALH, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xea, 0x48}},
+		{name: "casalh w10, w10, [x10]", inst: CASALH, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xea, 0x48}},
+		{name: "casalh w10, w30, [x10]", inst: CASALH, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xea, 0x48}},
+		{name: "casalh w10, wzr, [x30]", inst: CASALH, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xea, 0x48}},
+		{name: "casalh w10, w10, [x30]", inst: CASALH, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xea, 0x48}},
+		{name: "casalh w10, w30, [x30]", inst: CASALH, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xea, 0x48}},
+		{name: "casalh w30, wzr, [sp]", inst: CASALH, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xfe, 0x48}},
+		{name: "casalh w30, w10, [sp]", inst: CASALH, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xfe, 0x48}},
+		{name: "casalh w30, w30, [sp]", inst: CASALH, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xfe, 0x48}},
+		{name: "casalh w30, wzr, [x10]", inst: CASALH, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xfe, 0x48}},
+		{name: "casalh w30, w10, [x10]", inst: CASALH, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xfe, 0x48}},
+		{name: "casalh w30, w30, [x10]", inst: CASALH, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xfe, 0x48}},
+		{name: "casalh w30, wzr, [x30]", inst: CASALH, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xfe, 0x48}},
+		{name: "casalh w30, w10, [x30]", inst: CASALH, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xfe, 0x48}},
+		{name: "casalh w30, w30, [x30]", inst: CASALH, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xfe, 0x48}},
+		{name: "casalb wzr, wzr, [sp]", inst: CASALB, src: RegRZR, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xff, 0x8}},
+		{name: "casalb wzr, w10, [sp]", inst: CASALB, src: RegRZR, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xff, 0x8}},
+		{name: "casalb wzr, w30, [sp]", inst: CASALB, src: RegRZR, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xff, 0x8}},
+		{name: "casalb wzr, wzr, [x10]", inst: CASALB, src: RegRZR, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xff, 0x8}},
+		{name: "casalb wzr, w10, [x10]", inst: CASALB, src: RegRZR, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xff, 0x8}},
+		{name: "casalb wzr, w30, [x10]", inst: CASALB, src: RegRZR, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xff, 0x8}},
+		{name: "casalb wzr, wzr, [x30]", inst: CASALB, src: RegRZR, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xff, 0x8}},
+		{name: "casalb wzr, w10, [x30]", inst: CASALB, src: RegRZR, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xff, 0x8}},
+		{name: "casalb wzr, w30, [x30]", inst: CASALB, src: RegRZR, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xff, 0x8}},
+		{name: "casalb w10, wzr, [sp]", inst: CASALB, src: RegR10, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xea, 0x8}},
+		{name: "casalb w10, w10, [sp]", inst: CASALB, src: RegR10, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xea, 0x8}},
+		{name: "casalb w10, w30, [sp]", inst: CASALB, src: RegR10, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xea, 0x8}},
+		{name: "casalb w10, wzr, [x10]", inst: CASALB, src: RegR10, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xea, 0x8}},
+		{name: "casalb w10, w10, [x10]", inst: CASALB, src: RegR10, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xea, 0x8}},
+		{name: "casalb w10, w30, [x10]", inst: CASALB, src: RegR10, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xea, 0x8}},
+		{name: "casalb w10, wzr, [x30]", inst: CASALB, src: RegR10, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xea, 0x8}},
+		{name: "casalb w10, w10, [x30]", inst: CASALB, src: RegR10, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xea, 0x8}},
+		{name: "casalb w10, w30, [x30]", inst: CASALB, src: RegR10, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xea, 0x8}},
+		{name: "casalb w30, wzr, [sp]", inst: CASALB, src: RegR30, src2: RegRZR, dst: RegRZR, exp: []byte{0xff, 0xff, 0xfe, 0x8}},
+		{name: "casalb w30, w10, [sp]", inst: CASALB, src: RegR30, src2: RegRZR, dst: RegR10, exp: []byte{0xea, 0xff, 0xfe, 0x8}},
+		{name: "casalb w30, w30, [sp]", inst: CASALB, src: RegR30, src2: RegRZR, dst: RegR30, exp: []byte{0xfe, 0xff, 0xfe, 0x8}},
+		{name: "casalb w30, wzr, [x10]", inst: CASALB, src: RegR30, src2: RegR10, dst: RegRZR, exp: []byte{0x5f, 0xfd, 0xfe, 0x8}},
+		{name: "casalb w30, w10, [x10]", inst: CASALB, src: RegR30, src2: RegR10, dst: RegR10, exp: []byte{0x4a, 0xfd, 0xfe, 0x8}},
+		{name: "casalb w30, w30, [x10]", inst: CASALB, src: RegR30, src2: RegR10, dst: RegR30, exp: []byte{0x5e, 0xfd, 0xfe, 0x8}},
+		{name: "casalb w30, wzr, [x30]", inst: CASALB, src: RegR30, src2: RegR30, dst: RegRZR, exp: []byte{0xdf, 0xff, 0xfe, 0x8}},
+		{name: "casalb w30, w10, [x30]", inst: CASALB, src: RegR30, src2: RegR30, dst: RegR10, exp: []byte{0xca, 0xff, 0xfe, 0x8}},
+		{name: "casalb w30, w30, [x30]", inst: CASALB, src: RegR30, src2: RegR30, dst: RegR30, exp: []byte{0xde, 0xff, 0xfe, 0x8}},
 		{name: "src=V0,src2=V0,dst=V0", inst: FSUBD, src: RegV0, src2: RegV0, dst: RegV0, exp: []byte{0x0, 0x38, 0x60, 0x1e}},
 		{name: "src=V0,src2=V0,dst=V31", inst: FSUBD, src: RegV0, src2: RegV0, dst: RegV31, exp: []byte{0x1f, 0x38, 0x60, 0x1e}},
 		{name: "src=V0,src2=V31,dst=V0", inst: FSUBD, src: RegV0, src2: RegV31, dst: RegV0, exp: []byte{0xe0, 0x3b, 0x60, 0x1e}},
diff --git a/internal/asm/arm64/impl_4_test.go b/internal/asm/arm64/impl_4_test.go
index cffb0f99..d73e28d1 100644
--- a/internal/asm/arm64/impl_4_test.go
+++ b/internal/asm/arm64/impl_4_test.go
@@ -658,6 +658,14 @@ func TestAssemblerImpl_EncodeMemoryToRegister(t *testing.T) {
 		{name: "FLDRS/RegisterOffset/dst=V30,base=R30,offset=0x100008", n: &nodeImpl{instruction: FLDRS, srcReg: RegR30, srcConst: 1048584, dstReg: RegV30}, exp: []byte{0xdb, 0x3, 0x44, 0x91, 0x7e, 0xb, 0x40, 0xbd}},
 		{name: "FLDRS/RegisterOffset/dst=V30,base=R30,offset=0xffff8", n: &nodeImpl{instruction: FLDRS, srcReg: RegR30, srcConst: 1048568, dstReg: RegV30}, exp: []byte{0xdb, 0xf3, 0x43, 0x91, 0x7e, 0xfb, 0x7f, 0xbd}},
 		{name: "FLDRS/RegisterOffset/dst=V30,base=R30,offset=RegR8", n: &nodeImpl{instruction: FLDRS, srcReg: RegR30, srcReg2: RegR8, dstReg: RegV30}, exp: []byte{0xde, 0x6b, 0x68, 0xbc}},
+		{name: "ldar x11, [x5]", n: &nodeImpl{instruction: LDARD, srcReg: RegR5, dstReg: RegR11}, exp: []byte{0xab, 0xfc, 0xdf, 0xc8}},
+		{name: "ldar x11, [x30]", n: &nodeImpl{instruction: LDARD, srcReg: RegR30, dstReg: RegR11}, exp: []byte{0xcb, 0xff, 0xdf, 0xc8}},
+		{name: "ldar w11, [x5]", n: &nodeImpl{instruction: LDARW, srcReg: RegR5, dstReg: RegR11}, exp: []byte{0xab, 0xfc, 0xdf, 0x88}},
+		{name: "ldar w11, [x30]", n: &nodeImpl{instruction: LDARW, srcReg: RegR30, dstReg: RegR11}, exp: []byte{0xcb, 0xff, 0xdf, 0x88}},
+		{name: "ldarh w11, [x5]", n: &nodeImpl{instruction: LDARH, srcReg: RegR5, dstReg: RegR11}, exp: []byte{0xab, 0xfc, 0xdf, 0x48}},
+		{name: "ldarh w11, [x30]", n: &nodeImpl{instruction: LDARH, srcReg: RegR30, dstReg: RegR11}, exp: []byte{0xcb, 0xff, 0xdf, 0x48}},
+		{name: "ldarb w11, [x5]", n: &nodeImpl{instruction: LDARB, srcReg: RegR5, dstReg: RegR11}, exp: []byte{0xab, 0xfc, 0xdf, 0x8}},
+		{name: "ldarb w11, [x30]", n: &nodeImpl{instruction: LDARB, srcReg: RegR30, dstReg: RegR11}, exp: []byte{0xcb, 0xff, 0xdf, 0x8}},
 	}
 
 	for _, tc := range tests {
diff --git a/internal/asm/arm64/impl_5_test.go b/internal/asm/arm64/impl_5_test.go
index 74161a82..28f51190 100644
--- a/internal/asm/arm64/impl_5_test.go
+++ b/internal/asm/arm64/impl_5_test.go
@@ -804,6 +804,22 @@ func TestAssemblerImpl_EncodeRegisterToMemory(t *testing.T) {
 		{name: "FSTRS/ConstOffset/src=V30,base=R30,offset=0x7ffffff8", n: &nodeImpl{instruction: FSTRS, srcReg: RegV30, dstReg: RegR30, dstConst: 2147483640}, exp: []byte{0x1b, 0x0, 0x0, 0x18, 0xde, 0x6b, 0x3b, 0xbc}},
 		{name: "FSTRS/ConstOffset/src=V30,base=R30,offset=0x10000004", n: &nodeImpl{instruction: FSTRS, srcReg: RegV30, dstReg: RegR30, dstConst: 268435460}, exp: []byte{0x1b, 0x0, 0x0, 0x18, 0xde, 0x6b, 0x3b, 0xbc}},
 		{name: "FSTRS/RegisterOffset/src=V30,base=R30,offset=RegR8", n: &nodeImpl{instruction: FSTRS, srcReg: RegV30, dstReg: RegR30, dstReg2: RegR8}, exp: []byte{0xde, 0x6b, 0x28, 0xbc}},
+		{name: "stlr x0, [x0]", n: &nodeImpl{instruction: STLRD, srcReg: RegR0, dstReg: RegR0}, exp: []byte{0x0, 0xfc, 0x9f, 0xc8}},
+		{name: "stlr x0, [x30]", n: &nodeImpl{instruction: STLRD, srcReg: RegR0, dstReg: RegR30}, exp: []byte{0xc0, 0xff, 0x9f, 0xc8}},
+		{name: "stlr x30, [x0]", n: &nodeImpl{instruction: STLRD, srcReg: RegR30, dstReg: RegR0}, exp: []byte{0x1e, 0xfc, 0x9f, 0xc8}},
+		{name: "stlr x30, [x30]", n: &nodeImpl{instruction: STLRD, srcReg: RegR30, dstReg: RegR30}, exp: []byte{0xde, 0xff, 0x9f, 0xc8}},
+		{name: "stlr w0, [x0]", n: &nodeImpl{instruction: STLRW, srcReg: RegR0, dstReg: RegR0}, exp: []byte{0x0, 0xfc, 0x9f, 0x88}},
+		{name: "stlr w0, [x30]", n: &nodeImpl{instruction: STLRW, srcReg: RegR0, dstReg: RegR30}, exp: []byte{0xc0, 0xff, 0x9f, 0x88}},
+		{name: "stlr w30, [x0]", n: &nodeImpl{instruction: STLRW, srcReg: RegR30, dstReg: RegR0}, exp: []byte{0x1e, 0xfc, 0x9f, 0x88}},
+		{name: "stlr w30, [x30]", n: &nodeImpl{instruction: STLRW, srcReg: RegR30, dstReg: RegR30}, exp: []byte{0xde, 0xff, 0x9f, 0x88}},
+		{name: "stlrh w0, [x0]", n: &nodeImpl{instruction: STLRH, srcReg: RegR0, dstReg: RegR0}, exp: []byte{0x0, 0xfc, 0x9f, 0x48}},
+		{name: "stlrh w0, [x30]", n: &nodeImpl{instruction: STLRH, srcReg: RegR0, dstReg: RegR30}, exp: []byte{0xc0, 0xff, 0x9f, 0x48}},
+		{name: "stlrh w30, [x0]", n: &nodeImpl{instruction: STLRH, srcReg: RegR30, dstReg: RegR0}, exp: []byte{0x1e, 0xfc, 0x9f, 0x48}},
+		{name: "stlrh w30, [x30]", n: &nodeImpl{instruction: STLRH, srcReg: RegR30, dstReg: RegR30}, exp: []byte{0xde, 0xff, 0x9f, 0x48}},
+		{name: "stlrb w0, [x0]", n: &nodeImpl{instruction: STLRB, srcReg: RegR0, dstReg: RegR0}, exp: []byte{0x0, 0xfc, 0x9f, 0x8}},
+		{name: "stlrb w0, [x30]", n: &nodeImpl{instruction: STLRB, srcReg: RegR0, dstReg: RegR30}, exp: []byte{0xc0, 0xff, 0x9f, 0x8}},
+		{name: "stlrb w30, [x0]", n: &nodeImpl{instruction: STLRB, srcReg: RegR30, dstReg: RegR0}, exp: []byte{0x1e, 0xfc, 0x9f, 0x8}},
+		{name: "stlrb w30, [x30]", n: &nodeImpl{instruction: STLRB, srcReg: RegR30, dstReg: RegR30}, exp: []byte{0xde, 0xff, 0x9f, 0x8}},
 	}
 
 	for _, tc := range tests {
diff --git a/internal/integration_test/spectest/spectest.go b/internal/integration_test/spectest/spectest.go
index 77c16d59..87bc6fa1 100644
--- a/internal/integration_test/spectest/spectest.go
+++ b/internal/integration_test/spectest/spectest.go
@@ -287,6 +287,8 @@ func (c command) expectedError() (err error) {
 		panic("unreachable")
 	}
 	switch c.Text {
+	case "expected shared memory":
+		err = wasmruntime.ErrRuntimeExpectedSharedMemory
 	case "out of bounds memory access":
 		err = wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess
 	case "indirect call type mismatch", "indirect call":
@@ -299,6 +301,8 @@ func (c command) expectedError() (err error) {
 		err = wasmruntime.ErrRuntimeInvalidConversionToInteger
 	case "integer divide by zero":
 		err = wasmruntime.ErrRuntimeIntegerDivideByZero
+	case "unaligned atomic":
+		err = wasmruntime.ErrRuntimeUnalignedAtomic
 	case "unreachable":
 		err = wasmruntime.ErrRuntimeUnreachable
 	default:
@@ -336,7 +340,7 @@ func Run(t *testing.T, testDataFS embed.FS, ctx context.Context, config wazero.R
 
 	// If the go:embed path resolution was wrong, this fails.
 	// https://github.com/tetratelabs/wazero/issues/247
-	require.True(t, len(caseNames) > 1, "len(caseNames)=%d (not greater than one)", len(caseNames))
+	require.True(t, len(caseNames) > 0, "len(caseNames)=%d (not greater than zero)", len(caseNames))
 
 	for _, f := range caseNames {
 		RunCase(t, testDataFS, f, ctx, config, -1, 0, math.MaxInt)
diff --git a/internal/integration_test/spectest/threads/spec_test.go b/internal/integration_test/spectest/threads/spec_test.go
index 3bbbb042..966f7acb 100644
--- a/internal/integration_test/spectest/threads/spec_test.go
+++ b/internal/integration_test/spectest/threads/spec_test.go
@@ -26,6 +26,5 @@ func TestCompiler(t *testing.T) {
 }
 
 func TestInterpreter(t *testing.T) {
-	t.Skip() // TODO: Delete after implementing interpreter support
 	spectest.Run(t, testcases, context.Background(), wazero.NewRuntimeConfigInterpreter().WithCoreFeatures(enabledFeatures))
 }
diff --git a/internal/wasm/memory_test.go b/internal/wasm/memory_test.go
index 5957741d..e37c5ba4 100644
--- a/internal/wasm/memory_test.go
+++ b/internal/wasm/memory_test.go
@@ -5,6 +5,7 @@ import (
 	"reflect"
 	"strings"
 	"testing"
+	"time"
 	"unsafe"
 
 	"github.com/tetratelabs/wazero/api"
@@ -797,3 +798,143 @@ func BenchmarkWriteString(b *testing.B) {
 		})
 	}
 }
+
+func TestMemoryInstance_WaitNotifyOnce(t *testing.T) {
+	reader := func(mem *MemoryInstance, offset uint32) uint32 {
+		val, _ := mem.ReadUint32Le(offset)
+		return val
+	}
+	t.Run("no waiters", func(t *testing.T) {
+		mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1, Shared: true}
+
+		notifyWaiters(t, mem, 0, 1, 0)
+	})
+
+	t.Run("single wait, notify", func(t *testing.T) {
+		mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1, Shared: true}
+
+		ch := make(chan string)
+		// Reuse same offset 3 times to verify reuse
+		for i := 0; i < 3; i++ {
+			go func() {
+				res := mem.Wait32(0, 0, -1, reader)
+				propagateWaitResult(t, ch, res)
+			}()
+
+			requireChannelEmpty(t, ch)
+			notifyWaiters(t, mem, 0, 1, 1)
+			require.Equal(t, "", <-ch)
+
+			notifyWaiters(t, mem, 0, 1, 0)
+		}
+	})
+
+	t.Run("multiple waiters, notify all", func(t *testing.T) {
+		mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1, Shared: true}
+
+		ch := make(chan string)
+		go func() {
+			res := mem.Wait32(0, 0, -1, reader)
+			propagateWaitResult(t, ch, res)
+		}()
+		go func() {
+			res := mem.Wait32(0, 0, -1, reader)
+			propagateWaitResult(t, ch, res)
+		}()
+
+		requireChannelEmpty(t, ch)
+
+		notifyWaiters(t, mem, 0, 2, 2)
+		require.Equal(t, "", <-ch)
+		require.Equal(t, "", <-ch)
+	})
+
+	t.Run("multiple waiters, notify one", func(t *testing.T) {
+		mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1, Shared: true}
+
+		ch := make(chan string)
+		go func() {
+			res := mem.Wait32(0, 0, -1, reader)
+			propagateWaitResult(t, ch, res)
+		}()
+		go func() {
+			res := mem.Wait32(0, 0, -1, reader)
+			propagateWaitResult(t, ch, res)
+		}()
+
+		requireChannelEmpty(t, ch)
+		notifyWaiters(t, mem, 0, 1, 1)
+		require.Equal(t, "", <-ch)
+		requireChannelEmpty(t, ch)
+		notifyWaiters(t, mem, 0, 1, 1)
+		require.Equal(t, "", <-ch)
+	})
+
+	t.Run("multiple offsets", func(t *testing.T) {
+		mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1, Shared: true}
+
+		ch := make(chan string)
+		go func() {
+			res := mem.Wait32(0, 0, -1, reader)
+			propagateWaitResult(t, ch, res)
+		}()
+		go func() {
+			res := mem.Wait32(1, 268435456, -1, reader)
+			propagateWaitResult(t, ch, res)
+		}()
+
+		requireChannelEmpty(t, ch)
+		notifyWaiters(t, mem, 0, 2, 1)
+		require.Equal(t, "", <-ch)
+		requireChannelEmpty(t, ch)
+		notifyWaiters(t, mem, 1, 2, 1)
+		require.Equal(t, "", <-ch)
+	})
+
+	t.Run("timeout", func(t *testing.T) {
+		mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1, Shared: true}
+
+		ch := make(chan string)
+		go func() {
+			res := mem.Wait32(0, 0, 10 /* ns */, reader)
+			propagateWaitResult(t, ch, res)
+		}()
+
+		require.Equal(t, "timeout", <-ch)
+	})
+}
+
+func notifyWaiters(t *testing.T, mem *MemoryInstance, offset, count, exp int) {
+	t.Helper()
+	cur := 0
+	tries := 0
+	for cur < exp {
+		if tries > 100 {
+			t.Fatal("too many tries waiting for wait and notify to converge")
+		}
+		n := mem.Notify(uint32(offset), uint32(count))
+		cur += int(n)
+		time.Sleep(1 * time.Millisecond)
+		tries++
+	}
+}
+
+func propagateWaitResult(t *testing.T, ch chan string, res uint64) {
+	t.Helper()
+	switch res {
+	case 2:
+		ch <- "timeout"
+	default:
+		ch <- ""
+	}
+}
+
+func requireChannelEmpty(t *testing.T, ch chan string) {
+	t.Helper()
+	select {
+	case <-ch:
+		t.Fatal("channel should be empty")
+	default:
+		// fallthrough
+	}
+}