Repository: tetratelabs/wazero
Pull request #1655 (2023-08-23 15:01:06)

wazevo: add bitwise ops and, or, xor, rotr, rotl
adding bitwise ops and, or, xor (eor), rotr and rotl (as neg+rotr)

mathetake: Make sure adding reference to #1496 ! 

Patch:
diff --git a/internal/engine/wazevo/backend/isa/arm64/instr.go b/internal/engine/wazevo/backend/isa/arm64/instr.go
index 6c64c6c9..c321e2f1 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr.go
@@ -733,21 +733,16 @@ func (i *instruction) String() (str string) {
 	case aluRRR:
 		size := is64SizeBitToSize(i.u3)
 		str = fmt.Sprintf("%s %s, %s, %s", aluOp(i.u1).String(),
-			formatVRegSized(i.rd.nr(), size), formatVRegSized(i.rn.nr(), size), formatVRegSized(i.rm.nr(), size))
+			formatVRegSized(i.rd.nr(), size), formatVRegSized(i.rn.nr(), size),
+			i.rm.format(size))
 	case aluRRRR:
 		size := is64SizeBitToSize(i.u3)
 		str = fmt.Sprintf("%s %s, %s, %s, %s", aluOp(i.u1).String(),
 			formatVRegSized(i.rd.nr(), size), formatVRegSized(i.rn.nr(), size), formatVRegSized(i.rm.nr(), size), formatVRegSized(i.ra.nr(), size))
 	case aluRRImm12:
 		size := is64SizeBitToSize(i.u3)
-		v, shiftBit := i.rm.imm12()
-		if shiftBit == 1 {
-			str = fmt.Sprintf("%s %s, %s, #%#x", aluOp(i.u1).String(),
-				formatVRegSized(i.rd.nr(), size), formatVRegSized(i.rn.nr(), size), uint64(v)<<12)
-		} else {
-			str = fmt.Sprintf("%s %s, %s, #%#x", aluOp(i.u1).String(),
-				formatVRegSized(i.rd.nr(), size), formatVRegSized(i.rn.nr(), size), v)
-		}
+		str = fmt.Sprintf("%s %s, %s, %s", aluOp(i.u1).String(),
+			formatVRegSized(i.rd.nr(), size), formatVRegSized(i.rn.nr(), size), i.rm.format(size))
 	case aluRRBitmaskImm:
 		size := is64SizeBitToSize(i.u3)
 		rd, rn := formatVRegSized(i.rd.nr(), size), formatVRegSized(i.rn.nr(), size)
@@ -770,16 +765,15 @@ func (i *instruction) String() (str string) {
 			aluOp(i.u1).String(),
 			formatVRegSized(i.rd.nr(), size),
 			formatVRegSized(i.rn.nr(), size),
-			formatVRegSized(i.rm.nr(), size),
+			i.rm.format(size),
 		)
 	case aluRRRExtend:
-		rm, e, _ := i.rm.er()
 		size := is64SizeBitToSize(i.u3)
-		str = fmt.Sprintf("%s %s, %s, %s %s", aluOp(i.u1).String(),
+		str = fmt.Sprintf("%s %s, %s, %s", aluOp(i.u1).String(),
 			formatVRegSized(i.rd.nr(), size),
 			formatVRegSized(i.rn.nr(), size),
-			formatVRegSized(rm, e.srcBits()),
-			e,
+			// Regardless of the source size, the register is formatted in 32-bit.
+			i.rm.format(32),
 		)
 	case bitRR:
 		size := is64SizeBitToSize(i.u2)
@@ -824,13 +818,13 @@ func (i *instruction) String() (str string) {
 		str = fmt.Sprintf("mov %s, %s", formatVRegSized(i.rd.nr(), 32), formatVRegSized(i.rn.nr(), 32))
 	case movZ:
 		size := is64SizeBitToSize(i.u3)
-		str = fmt.Sprintf("movz %s, #%#x, LSL %d", formatVRegSized(i.rd.nr(), size), uint16(i.u1), i.u2*16)
+		str = fmt.Sprintf("movz %s, #%#x, lsl %d", formatVRegSized(i.rd.nr(), size), uint16(i.u1), i.u2*16)
 	case movN:
 		size := is64SizeBitToSize(i.u3)
-		str = fmt.Sprintf("movn %s, #%#x, LSL %d", formatVRegSized(i.rd.nr(), size), uint16(i.u1), i.u2*16)
+		str = fmt.Sprintf("movn %s, #%#x, lsl %d", formatVRegSized(i.rd.nr(), size), uint16(i.u1), i.u2*16)
 	case movK:
 		size := is64SizeBitToSize(i.u3)
-		str = fmt.Sprintf("movk %s, #%#x, LSL %d", formatVRegSized(i.rd.nr(), size), uint16(i.u1), i.u2*16)
+		str = fmt.Sprintf("movk %s, #%#x, lsl %d", formatVRegSized(i.rd.nr(), size), uint16(i.u1), i.u2*16)
 	case extend:
 		fromBits, toBits := byte(i.u1), byte(i.u2)
 
@@ -1342,7 +1336,7 @@ func (a aluOp) String() string {
 	case aluOpUDiv64:
 		return "uDiv64"
 	case aluOpRotR:
-		return "rotR"
+		return "ror"
 	case aluOpLsr:
 		return "lsr"
 	case aluOpAsr:
@@ -1617,13 +1611,13 @@ const (
 func (s shiftOp) String() string {
 	switch s {
 	case shiftOpLSL:
-		return "LSL"
+		return "lsl"
 	case shiftOpLSR:
-		return "LSR"
+		return "lsr"
 	case shiftOpASR:
-		return "ASR"
+		return "asr"
 	case shiftOpROR:
-		return "ROR"
+		return "ror"
 	}
 	panic(int(s))
 }
diff --git a/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go b/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
index 43b74ce7..5ec880e5 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
@@ -814,6 +814,7 @@ func encodeAluRRImm12(op aluOp, rd, rn uint32, imm12 uint16, shiftBit byte, _64b
 // https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en#addsub_shift
 func encodeAluRRRShift(op aluOp, rd, rn, rm, amount uint32, shiftOp shiftOp, _64bit bool) uint32 {
 	var _31to24 uint32
+	var opc, n uint32
 	switch op {
 	case aluOpAdd:
 		_31to24 = 0b00001011
@@ -823,6 +824,17 @@ func encodeAluRRRShift(op aluOp, rd, rn, rm, amount uint32, shiftOp shiftOp, _64
 		_31to24 = 0b01001011
 	case aluOpSubS:
 		_31to24 = 0b01101011
+	case aluOpAnd, aluOpOrr, aluOpEor:
+		// "Logical (shifted register)".
+		switch op {
+		case aluOpAnd:
+			// all zeros
+		case aluOpOrr:
+			opc = 0b01
+		case aluOpEor:
+			opc = 0b10
+		}
+		_31to24 = 0b000_01010
 	default:
 		panic(op.String())
 	}
@@ -842,7 +854,7 @@ func encodeAluRRRShift(op aluOp, rd, rn, rm, amount uint32, shiftOp shiftOp, _64
 	default:
 		panic(shiftOp.String())
 	}
-	return _31to24<<24 | shift<<22 | rm<<16 | (amount << 10) | (rn << 5) | rd
+	return opc<<29 | n<<21 | _31to24<<24 | shift<<22 | rm<<16 | (amount << 10) | (rn << 5) | rd
 }
 
 // encodeAluRRR encodes as Data Processing (register), depending on aluOp.
@@ -880,7 +892,19 @@ func encodeAluRRR(op aluOp, rd, rn, rm uint32, _64bit, isRnSp bool) uint32 {
 		}
 		// "Shifted register" with shift = 0
 		_31to21 = 0b01101011_000
-	case aluOpLsl, aluOpAsr, aluOpLsr:
+	case aluOpAnd, aluOpOrr, aluOpEor:
+		// "Logical (shifted register)".
+		var opc, n uint32
+		switch op {
+		case aluOpAnd:
+			// all zeros
+		case aluOpOrr:
+			opc = 0b01
+		case aluOpEor:
+			opc = 0b10
+		}
+		_31to21 = 0b000_01010_000 | opc<<8 | n
+	case aluOpLsl, aluOpAsr, aluOpLsr, aluOpRotR:
 		// "Data-processing (2 source)".
 		_31to21 = 0b00011010_110
 		switch op {
@@ -890,6 +914,8 @@ func encodeAluRRR(op aluOp, rd, rn, rm uint32, _64bit, isRnSp bool) uint32 {
 			_15to10 = 0b001001
 		case aluOpAsr:
 			_15to10 = 0b001010
+		case aluOpRotR:
+			_15to10 = 0b001011
 		}
 	default:
 		panic(op.String())
diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_instr.go b/internal/engine/wazevo/backend/isa/arm64/lower_instr.go
index 674add4a..9266d62b 100644
--- a/internal/engine/wazevo/backend/isa/arm64/lower_instr.go
+++ b/internal/engine/wazevo/backend/isa/arm64/lower_instr.go
@@ -151,6 +151,12 @@ func (m *machine) LowerInstr(instr *ssa.Instruction) {
 		m.lowerCall(instr)
 	case ssa.OpcodeIcmp:
 		m.lowerIcmp(instr)
+	case ssa.OpcodeBand:
+		m.lowerBitwiseAluOp(instr, aluOpAnd)
+	case ssa.OpcodeBor:
+		m.lowerBitwiseAluOp(instr, aluOpOrr)
+	case ssa.OpcodeBxor:
+		m.lowerBitwiseAluOp(instr, aluOpEor)
 	case ssa.OpcodeIshl:
 		m.lowerShifts(instr, extModeNone, aluOpLsl)
 	case ssa.OpcodeSshr:
@@ -165,6 +171,10 @@ func (m *machine) LowerInstr(instr *ssa.Instruction) {
 		} else {
 			m.lowerShifts(instr, extModeZeroExtend32, aluOpAsr)
 		}
+	case ssa.OpcodeRotl:
+		m.lowerRotl(instr)
+	case ssa.OpcodeRotr:
+		m.lowerRotr(instr)
 	case ssa.OpcodeSExtend, ssa.OpcodeUExtend:
 		from, to, signed := instr.ExtendData()
 		m.lowerExtend(instr.Arg(), instr.Return(), from, to, signed)
@@ -343,6 +353,61 @@ func (m *machine) lowerShifts(si *ssa.Instruction, ext extMode, aluOp aluOp) {
 	m.insert(alu)
 }
 
+func (m *machine) lowerBitwiseAluOp(si *ssa.Instruction, op aluOp) {
+	x, y := si.BinaryData()
+	if !x.Type().IsInt() {
+		panic("BUG?")
+	}
+
+	xDef, yDef := m.compiler.ValueDefinition(x), m.compiler.ValueDefinition(y)
+	rn := m.getOperand_NR(xDef, extModeNone)
+	rm := m.getOperand_SR_NR(yDef, extModeNone)
+	rd := operandNR(m.compiler.VRegOf(si.Return()))
+
+	alu := m.allocateInstr()
+	alu.asALU(op, rd, rn, rm, si.Return().Type().Bits() == 64)
+	m.insert(alu)
+}
+
+func (m *machine) lowerRotl(si *ssa.Instruction) {
+	x, y := si.BinaryData()
+	if !x.Type().IsInt() {
+		panic("BUG?")
+	}
+
+	// Encode rotl as neg + rotr: neg is really a sub against the zero-reg.
+
+	xDef, yDef := m.compiler.ValueDefinition(x), m.compiler.ValueDefinition(y)
+	rn := m.getOperand_NR(xDef, extModeNone)
+	rm := m.getOperand_NR(yDef, extModeNone)
+	rd := operandNR(m.compiler.VRegOf(si.Return()))
+
+	// Encode neg as sub $reg, xzr, $reg.
+	neg := m.allocateInstr()
+	neg.asALU(aluOpSub, rn, operandNR(xzrVReg), rn, si.Return().Type().Bits() == 64)
+	m.insert(neg)
+
+	alu := m.allocateInstr()
+	alu.asALU(aluOpRotR, rd, rn, rm, si.Return().Type().Bits() == 64)
+	m.insert(alu)
+}
+
+func (m *machine) lowerRotr(si *ssa.Instruction) {
+	x, y := si.BinaryData()
+	if !x.Type().IsInt() {
+		panic("BUG?")
+	}
+
+	xDef, yDef := m.compiler.ValueDefinition(x), m.compiler.ValueDefinition(y)
+	rn := m.getOperand_NR(xDef, extModeNone)
+	rm := m.getOperand_NR(yDef, extModeNone)
+	rd := operandNR(m.compiler.VRegOf(si.Return()))
+
+	alu := m.allocateInstr()
+	alu.asALU(aluOpRotR, rd, rn, rm, si.Return().Type().Bits() == 64)
+	m.insert(alu)
+}
+
 func (m *machine) lowerExtend(arg, ret ssa.Value, from, to byte, signed bool) {
 	rd := m.compiler.VRegOf(ret)
 	rn := m.getOperand_NR(m.compiler.ValueDefinition(arg), extModeNone)
diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go
index d16e6324..c0804ce3 100644
--- a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go
+++ b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go
@@ -40,19 +40,23 @@ const (
 )
 
 // String implements fmt.Stringer for debugging.
-func (o operand) String() string {
+func (o operand) format(size byte) string {
 	switch o.kind {
 	case operandKindNR:
-		return fmt.Sprintf("r%d", o.nr())
+		return formatVRegSized(o.nr(), size)
 	case operandKindSR:
 		r, amt, sop := o.sr()
-		return fmt.Sprintf("r%d, #%d, %s", r, amt, sop)
+		return fmt.Sprintf("%s, %s #%d", formatVRegSized(r, size), sop, amt)
 	case operandKindER:
-		r, eop, to := o.er()
-		return fmt.Sprintf("r%d, %s, %d", r, eop, to)
+		r, eop, _ := o.er()
+		return fmt.Sprintf("%s %s", formatVRegSized(r, size), eop)
 	case operandKindImm12:
 		imm12, shiftBit := o.imm12()
-		return fmt.Sprintf("#%d<<%d", imm12, 12*shiftBit)
+		if shiftBit == 1 {
+			return fmt.Sprintf("#%#x", uint64(imm12)<<12)
+		} else {
+			return fmt.Sprintf("#%#x", imm12)
+		}
 	default:
 		panic(fmt.Sprintf("unknown operand kind: %d", o.kind))
 	}
diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_mem.go b/internal/engine/wazevo/backend/isa/arm64/lower_mem.go
index 36863c7e..e570caa4 100644
--- a/internal/engine/wazevo/backend/isa/arm64/lower_mem.go
+++ b/internal/engine/wazevo/backend/isa/arm64/lower_mem.go
@@ -110,7 +110,7 @@ func (a addressMode) format(dstSizeBits byte) (ret string) {
 		ret = fmt.Sprintf("[%s, %s, %s #%#x]", base, formatVRegSized(a.rm, a.indexRegBits()), a.extOp, amount)
 	case addressModeKindRegScaled:
 		amount := a.sizeInBitsToShiftAmount(dstSizeBits)
-		ret = fmt.Sprintf("[%s, %s, LSL #%#x]", base, formatVRegSized(a.rm, a.indexRegBits()), amount)
+		ret = fmt.Sprintf("[%s, %s, lsl #%#x]", base, formatVRegSized(a.rm, a.indexRegBits()), amount)
 	case addressModeKindRegExtended:
 		ret = fmt.Sprintf("[%s, %s, %s]", base, formatVRegSized(a.rm, a.indexRegBits()), a.extOp)
 	case addressModeKindRegReg:
diff --git a/internal/engine/wazevo/backend/isa/arm64/reg.go b/internal/engine/wazevo/backend/isa/arm64/reg.go
index 7e51469b..c2bc68f8 100644
--- a/internal/engine/wazevo/backend/isa/arm64/reg.go
+++ b/internal/engine/wazevo/backend/isa/arm64/reg.go
@@ -249,7 +249,7 @@ func formatVRegSized(r regalloc.VReg, size byte) (ret string) {
 				ret = strings.Replace(ret, "x", "w", 1)
 			case 64:
 			default:
-				panic("BUG: invalid register size")
+				panic("BUG: invalid register size: " + strconv.Itoa(int(size)))
 			}
 		case 'v':
 			switch size {
diff --git a/internal/engine/wazevo/frontend/lower.go b/internal/engine/wazevo/frontend/lower.go
index e9b155a5..66380eac 100644
--- a/internal/engine/wazevo/frontend/lower.go
+++ b/internal/engine/wazevo/frontend/lower.go
@@ -425,6 +425,36 @@ func (c *Compiler) lowerOpcode(op wasm.Opcode) {
 		builder.InsertInstruction(neg)
 		value := neg.Return()
 		state.push(value)
+	case wasm.OpcodeI32And, wasm.OpcodeI64And:
+		if state.unreachable {
+			return
+		}
+		y, x := state.pop(), state.pop()
+		and := builder.AllocateInstruction()
+		and.AsBand(x, y)
+		builder.InsertInstruction(and)
+		value := and.Return()
+		state.push(value)
+	case wasm.OpcodeI32Or, wasm.OpcodeI64Or:
+		if state.unreachable {
+			return
+		}
+		y, x := state.pop(), state.pop()
+		or := builder.AllocateInstruction()
+		or.AsBor(x, y)
+		builder.InsertInstruction(or)
+		value := or.Return()
+		state.push(value)
+	case wasm.OpcodeI32Xor, wasm.OpcodeI64Xor:
+		if state.unreachable {
+			return
+		}
+		y, x := state.pop(), state.pop()
+		xor := builder.AllocateInstruction()
+		xor.AsBxor(x, y)
+		builder.InsertInstruction(xor)
+		value := xor.Return()
+		state.push(value)
 	case wasm.OpcodeI32Shl, wasm.OpcodeI64Shl:
 		if state.unreachable {
 			return
@@ -455,6 +485,26 @@ func (c *Compiler) lowerOpcode(op wasm.Opcode) {
 		builder.InsertInstruction(ishl)
 		value := ishl.Return()
 		state.push(value)
+	case wasm.OpcodeI32Rotl, wasm.OpcodeI64Rotl:
+		if state.unreachable {
+			return
+		}
+		y, x := state.pop(), state.pop()
+		rotl := builder.AllocateInstruction()
+		rotl.AsRotl(x, y)
+		builder.InsertInstruction(rotl)
+		value := rotl.Return()
+		state.push(value)
+	case wasm.OpcodeI32Rotr, wasm.OpcodeI64Rotr:
+		if state.unreachable {
+			return
+		}
+		y, x := state.pop(), state.pop()
+		rotr := builder.AllocateInstruction()
+		rotr.AsRotr(x, y)
+		builder.InsertInstruction(rotr)
+		value := rotr.Return()
+		state.push(value)
 	case wasm.OpcodeI32Clz, wasm.OpcodeI64Clz:
 		if state.unreachable {
 			return
diff --git a/internal/engine/wazevo/ssa/instructions.go b/internal/engine/wazevo/ssa/instructions.go
index f7c3ad55..22374f22 100644
--- a/internal/engine/wazevo/ssa/instructions.go
+++ b/internal/engine/wazevo/ssa/instructions.go
@@ -826,6 +826,11 @@ var instructionSideEffects = [opcodeEnd]sideEffect{
 	OpcodeImul:               sideEffectFalse,
 	OpcodeIsub:               sideEffectFalse,
 	OpcodeIcmp:               sideEffectFalse,
+	OpcodeBand:               sideEffectFalse,
+	OpcodeBor:                sideEffectFalse,
+	OpcodeBxor:               sideEffectFalse,
+	OpcodeRotl:               sideEffectFalse,
+	OpcodeRotr:               sideEffectFalse,
 	OpcodeFcmp:               sideEffectFalse,
 	OpcodeFadd:               sideEffectFalse,
 	OpcodeClz:                sideEffectFalse,
@@ -879,6 +884,11 @@ func (i *Instruction) HasSideEffects() bool {
 
 // instructionReturnTypes provides the function to determine the return types of an instruction.
 var instructionReturnTypes = [opcodeEnd]returnTypesFn{
+	OpcodeBand:      returnTypesFnSingle,
+	OpcodeBor:       returnTypesFnSingle,
+	OpcodeBxor:      returnTypesFnSingle,
+	OpcodeRotl:      returnTypesFnSingle,
+	OpcodeRotr:      returnTypesFnSingle,
 	OpcodeIshl:      returnTypesFnSingle,
 	OpcodeSshr:      returnTypesFnSingle,
 	OpcodeUshr:      returnTypesFnSingle,
@@ -1083,6 +1093,30 @@ func (i *Instruction) AsFcmp(x, y Value, c FloatCmpCond) {
 	i.typ = TypeI32
 }
 
+// AsBand initializes this instruction as an integer bitwise and instruction with OpcodeBand.
+func (i *Instruction) AsBand(x, amount Value) {
+	i.opcode = OpcodeBand
+	i.v = x
+	i.v2 = amount
+	i.typ = x.Type()
+}
+
+// AsBor initializes this instruction as an integer bitwise or instruction with OpcodeBor.
+func (i *Instruction) AsBor(x, amount Value) {
+	i.opcode = OpcodeBor
+	i.v = x
+	i.v2 = amount
+	i.typ = x.Type()
+}
+
+// AsBxor initializes this instruction as an integer bitwise xor instruction with OpcodeBxor.
+func (i *Instruction) AsBxor(x, amount Value) {
+	i.opcode = OpcodeBxor
+	i.v = x
+	i.v2 = amount
+	i.typ = x.Type()
+}
+
 // AsIshl initializes this instruction as an integer shift left instruction with OpcodeIshl.
 func (i *Instruction) AsIshl(x, amount Value) {
 	i.opcode = OpcodeIshl
@@ -1107,6 +1141,22 @@ func (i *Instruction) AsSshr(x, amount Value) {
 	i.typ = x.Type()
 }
 
+// AsRotl initializes this instruction as a word rotate left instruction with OpcodeRotl.
+func (i *Instruction) AsRotl(x, amount Value) {
+	i.opcode = OpcodeRotl
+	i.v = x
+	i.v2 = amount
+	i.typ = x.Type()
+}
+
+// AsRotr initializes this instruction as a word rotate right instruction with OpcodeRotr.
+func (i *Instruction) AsRotr(x, amount Value) {
+	i.opcode = OpcodeRotr
+	i.v = x
+	i.v2 = amount
+	i.typ = x.Type()
+}
+
 // IcmpData returns the operands and comparison condition of this integer comparison instruction.
 func (i *Instruction) IcmpData() (x, y Value, c IntegerCmpCond) {
 	return i.v, i.v2, IntegerCmpCond(i.u64)
@@ -1551,7 +1601,7 @@ func (i *Instruction) Format(b Builder) string {
 			}
 		}
 		instSuffix += "]"
-	case OpcodeIshl, OpcodeSshr, OpcodeUshr:
+	case OpcodeBand, OpcodeBor, OpcodeBxor, OpcodeRotr, OpcodeRotl, OpcodeIshl, OpcodeSshr, OpcodeUshr:
 		instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b))
 	case OpcodeUndefined:
 	case OpcodeClz, OpcodeCtz, OpcodePopcnt, OpcodeFneg, OpcodeFcvtFromSint, OpcodeFcvtFromUint, OpcodeFpromote,


Test patch:
diff --git a/internal/engine/wazevo/backend/backend_test.go b/internal/engine/wazevo/backend/backend_test.go
index db775d55..e9272aac 100644
--- a/internal/engine/wazevo/backend/backend_test.go
+++ b/internal/engine/wazevo/backend/backend_test.go
@@ -247,7 +247,7 @@ L1 (SSA Block: blk0):
 L3 (SSA Block: blk1):
 	ret
 L2 (SSA Block: blk2):
-	movz x27, #0x3, LSL 0
+	movz x27, #0x3, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 `,
@@ -260,7 +260,7 @@ L3 (SSA Block: blk1):
 	ldr x30, [sp], #0x10
 	ret
 L2 (SSA Block: blk2):
-	movz x27, #0x3, LSL 0
+	movz x27, #0x3, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 `,
@@ -559,7 +559,7 @@ L1 (SSA Block: blk0):
 	mov x0, x0?
 	mov x1, x1?
 	mov x2, x2?
-	movz w3, #0x5, LSL 0
+	movz w3, #0x5, lsl 0
 	bl f2
 	mov x4?, x0
 	str x1?, [x0?, #0x8]
@@ -591,7 +591,7 @@ L1 (SSA Block: blk0):
 	str x8, [x9, #0x8]
 	mov x0, x9
 	mov x1, x8
-	movz w3, #0x5, LSL 0
+	movz w3, #0x5, lsl 0
 	str x9, [sp]
 	str x8, [sp, #0x8]
 	bl f2
@@ -1308,6 +1308,61 @@ L1 (SSA Block: blk0):
 	ldr x19, [sp], #0x10
 	ldr x30, [sp], #0x10
 	ret
+`,
+		},
+		{
+			name: "integer_bitwise",
+			m:    testcases.IntegerBitwise.Module,
+			afterLoweringARM64: `
+L1 (SSA Block: blk0):
+	mov x2?, x2
+	mov x3?, x3
+	mov x4?, x4
+	mov x5?, x5
+	and w6?, w2?, w3?
+	orr w7?, w2?, w3?
+	eor w8?, w2?, w3?
+	ror w9?, w2?, w3?
+	and x10?, x4?, x5?
+	orr x11?, x4?, x5?
+	eor x12?, x4?, x5?
+	eor x15?, x4?, x5?, lsl #8
+	sub x4?, xzr, x4?
+	ror x16?, x4?, x5?
+	ror x17?, x4?, x5?
+	str x17?, [#ret_space, #0x8]
+	str x16?, [#ret_space, #0x0]
+	mov x7, x15?
+	mov x6, x12?
+	mov x5, x11?
+	mov x4, x10?
+	mov x3, x9?
+	mov x2, x8?
+	mov x1, x7?
+	mov x0, x6?
+	ret
+`,
+			afterFinalizeARM64: `
+L1 (SSA Block: blk0):
+	str x30, [sp, #-0x10]!
+	mov x10, x2
+	mov x8, x4
+	mov x9, x5
+	and w0, w10, w3
+	orr w1, w10, w3
+	eor w2, w10, w3
+	ror w3, w10, w3
+	and x4, x8, x9
+	orr x5, x8, x9
+	eor x6, x8, x9
+	eor x7, x8, x9, lsl #8
+	sub x8, xzr, x8
+	ror x10, x8, x9
+	ror x8, x8, x9
+	str x8, [sp, #0x18]
+	str x10, [sp, #0x10]
+	ldr x30, [sp], #0x10
+	ret
 `,
 		},
 		{
@@ -1558,7 +1613,7 @@ L1 (SSA Block: blk0):
 	madd w9?, w2?, w159?, wzr
 	orr w158?, wzr, #0x4
 	madd w11?, w2?, w158?, wzr
-	movz w157?, #0x5, LSL 0
+	movz w157?, #0x5, lsl 0
 	madd w13?, w2?, w157?, wzr
 	orr w156?, wzr, #0x6
 	madd w15?, w2?, w156?, wzr
@@ -1566,15 +1621,15 @@ L1 (SSA Block: blk0):
 	madd w17?, w2?, w155?, wzr
 	orr w154?, wzr, #0x8
 	madd w19?, w2?, w154?, wzr
-	movz w153?, #0x9, LSL 0
+	movz w153?, #0x9, lsl 0
 	madd w21?, w2?, w153?, wzr
-	movz w152?, #0xa, LSL 0
+	movz w152?, #0xa, lsl 0
 	madd w23?, w2?, w152?, wzr
-	movz w151?, #0xb, LSL 0
+	movz w151?, #0xb, lsl 0
 	madd w25?, w2?, w151?, wzr
 	orr w150?, wzr, #0xc
 	madd w27?, w2?, w150?, wzr
-	movz w149?, #0xd, LSL 0
+	movz w149?, #0xd, lsl 0
 	madd w29?, w2?, w149?, wzr
 	orr w148?, wzr, #0xe
 	madd w31?, w2?, w148?, wzr
@@ -1582,13 +1637,13 @@ L1 (SSA Block: blk0):
 	madd w33?, w2?, w147?, wzr
 	orr w146?, wzr, #0x10
 	madd w35?, w2?, w146?, wzr
-	movz w145?, #0x11, LSL 0
+	movz w145?, #0x11, lsl 0
 	madd w37?, w2?, w145?, wzr
-	movz w144?, #0x12, LSL 0
+	movz w144?, #0x12, lsl 0
 	madd w39?, w2?, w144?, wzr
-	movz w143?, #0x13, LSL 0
+	movz w143?, #0x13, lsl 0
 	madd w41?, w2?, w143?, wzr
-	movz w142?, #0x14, LSL 0
+	movz w142?, #0x14, lsl 0
 	madd w43?, w2?, w142?, wzr
 	add w44?, w41?, w43?
 	add w45?, w39?, w44?
@@ -1702,7 +1757,7 @@ L1 (SSA Block: blk0):
 	madd w10, w2, w10, wzr
 	orr w11, wzr, #0x4
 	madd w11, w2, w11, wzr
-	movz w12, #0x5, LSL 0
+	movz w12, #0x5, lsl 0
 	madd w12, w2, w12, wzr
 	orr w13, wzr, #0x6
 	madd w13, w2, w13, wzr
@@ -1710,15 +1765,15 @@ L1 (SSA Block: blk0):
 	madd w14, w2, w14, wzr
 	orr w15, wzr, #0x8
 	madd w15, w2, w15, wzr
-	movz w16, #0x9, LSL 0
+	movz w16, #0x9, lsl 0
 	madd w16, w2, w16, wzr
-	movz w17, #0xa, LSL 0
+	movz w17, #0xa, lsl 0
 	madd w17, w2, w17, wzr
-	movz w18, #0xb, LSL 0
+	movz w18, #0xb, lsl 0
 	madd w18, w2, w18, wzr
 	orr w19, wzr, #0xc
 	madd w19, w2, w19, wzr
-	movz w20, #0xd, LSL 0
+	movz w20, #0xd, lsl 0
 	madd w20, w2, w20, wzr
 	orr w21, wzr, #0xe
 	madd w21, w2, w21, wzr
@@ -1726,13 +1781,13 @@ L1 (SSA Block: blk0):
 	madd w22, w2, w22, wzr
 	orr w23, wzr, #0x10
 	madd w23, w2, w23, wzr
-	movz w24, #0x11, LSL 0
+	movz w24, #0x11, lsl 0
 	madd w24, w2, w24, wzr
-	movz w25, #0x12, LSL 0
+	movz w25, #0x12, lsl 0
 	madd w25, w2, w25, wzr
-	movz w26, #0x13, LSL 0
+	movz w26, #0x13, lsl 0
 	madd w26, w2, w26, wzr
-	movz w28, #0x14, LSL 0
+	movz w28, #0x14, lsl 0
 	madd w28, w2, w28, wzr
 	add w26, w26, w28
 	add w25, w25, w26
@@ -1952,7 +2007,7 @@ L1 (SSA Block: blk0):
 	add x6?, x4?, #0x4
 	subs xzr, x5?, x6?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	ldr x8?, [x1?, #0x8]
@@ -1969,7 +2024,7 @@ L1 (SSA Block: blk0):
 	add x9, x8, #0x4
 	subs xzr, x10, x9
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	ldr x9, [x1, #0x8]
@@ -1990,7 +2045,7 @@ L1 (SSA Block: blk0):
 	add x9, x10, #0x4
 	subs xzr, x8, x9
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	ldr x9, [x1, #0x8]
@@ -2001,7 +2056,7 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x8
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x10, x9, x11
@@ -2011,7 +2066,7 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x4
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x10, x9, x11
@@ -2021,7 +2076,7 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x8
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x10, x9, x11
@@ -2031,17 +2086,17 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x1
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x10, x9, x11
 	strb w2, [x10]
-	movz w10, #0x28, LSL 0
+	movz w10, #0x28, lsl 0
 	uxtw x11, w10
 	add x10, x11, #0x2
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x10, x9, x11
@@ -2051,7 +2106,7 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x1
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x10, x9, x11
@@ -2061,7 +2116,7 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x2
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x10, x9, x11
@@ -2071,7 +2126,7 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x4
 	subs xzr, x8, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0]
 	exit_sequence x0
 	add x8, x9, x11
@@ -2092,7 +2147,7 @@ L1 (SSA Block: blk0):
 	add x6?, x4?, #0x4
 	subs xzr, x5?, x6?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	ldr x8?, [x1?, #0x8]
@@ -2102,7 +2157,7 @@ L1 (SSA Block: blk0):
 	add x13?, x12?, #0x8
 	subs xzr, x5?, x13?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x199?, x8?, x12?
@@ -2111,7 +2166,7 @@ L1 (SSA Block: blk0):
 	add x19?, x18?, #0x4
 	subs xzr, x5?, x19?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x198?, x8?, x18?
@@ -2120,7 +2175,7 @@ L1 (SSA Block: blk0):
 	add x25?, x24?, #0x8
 	subs xzr, x5?, x25?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x197?, x8?, x24?
@@ -2129,7 +2184,7 @@ L1 (SSA Block: blk0):
 	add x31?, x30?, #0x13
 	subs xzr, x5?, x31?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x196?, x8?, x30?
@@ -2138,7 +2193,7 @@ L1 (SSA Block: blk0):
 	add x37?, x36?, #0x17
 	subs xzr, x5?, x37?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x195?, x8?, x36?
@@ -2147,7 +2202,7 @@ L1 (SSA Block: blk0):
 	add x43?, x42?, #0x13
 	subs xzr, x5?, x43?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x194?, x8?, x42?
@@ -2156,7 +2211,7 @@ L1 (SSA Block: blk0):
 	add x49?, x48?, #0x17
 	subs xzr, x5?, x49?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x193?, x8?, x48?
@@ -2165,7 +2220,7 @@ L1 (SSA Block: blk0):
 	add x55?, x54?, #0x1
 	subs xzr, x5?, x55?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x192?, x8?, x54?
@@ -2174,7 +2229,7 @@ L1 (SSA Block: blk0):
 	add x61?, x60?, #0x10
 	subs xzr, x5?, x61?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x191?, x8?, x60?
@@ -2183,7 +2238,7 @@ L1 (SSA Block: blk0):
 	add x67?, x66?, #0x1
 	subs xzr, x5?, x67?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x190?, x8?, x66?
@@ -2192,7 +2247,7 @@ L1 (SSA Block: blk0):
 	add x73?, x72?, #0x10
 	subs xzr, x5?, x73?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x189?, x8?, x72?
@@ -2201,7 +2256,7 @@ L1 (SSA Block: blk0):
 	add x79?, x78?, #0x2
 	subs xzr, x5?, x79?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x188?, x8?, x78?
@@ -2210,7 +2265,7 @@ L1 (SSA Block: blk0):
 	add x85?, x84?, #0x11
 	subs xzr, x5?, x85?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x187?, x8?, x84?
@@ -2219,7 +2274,7 @@ L1 (SSA Block: blk0):
 	add x91?, x90?, #0x2
 	subs xzr, x5?, x91?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x186?, x8?, x90?
@@ -2228,7 +2283,7 @@ L1 (SSA Block: blk0):
 	add x97?, x96?, #0x11
 	subs xzr, x5?, x97?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x185?, x8?, x96?
@@ -2237,7 +2292,7 @@ L1 (SSA Block: blk0):
 	add x103?, x102?, #0x1
 	subs xzr, x5?, x103?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x184?, x8?, x102?
@@ -2246,7 +2301,7 @@ L1 (SSA Block: blk0):
 	add x109?, x108?, #0x10
 	subs xzr, x5?, x109?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x183?, x8?, x108?
@@ -2255,7 +2310,7 @@ L1 (SSA Block: blk0):
 	add x115?, x114?, #0x1
 	subs xzr, x5?, x115?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x182?, x8?, x114?
@@ -2264,7 +2319,7 @@ L1 (SSA Block: blk0):
 	add x121?, x120?, #0x10
 	subs xzr, x5?, x121?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x181?, x8?, x120?
@@ -2273,7 +2328,7 @@ L1 (SSA Block: blk0):
 	add x127?, x126?, #0x2
 	subs xzr, x5?, x127?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x180?, x8?, x126?
@@ -2282,7 +2337,7 @@ L1 (SSA Block: blk0):
 	add x133?, x132?, #0x11
 	subs xzr, x5?, x133?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x179?, x8?, x132?
@@ -2291,7 +2346,7 @@ L1 (SSA Block: blk0):
 	add x139?, x138?, #0x2
 	subs xzr, x5?, x139?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x178?, x8?, x138?
@@ -2300,7 +2355,7 @@ L1 (SSA Block: blk0):
 	add x145?, x144?, #0x11
 	subs xzr, x5?, x145?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x177?, x8?, x144?
@@ -2309,7 +2364,7 @@ L1 (SSA Block: blk0):
 	add x151?, x150?, #0x4
 	subs xzr, x5?, x151?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x176?, x8?, x150?
@@ -2318,7 +2373,7 @@ L1 (SSA Block: blk0):
 	add x157?, x156?, #0x13
 	subs xzr, x5?, x157?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x175?, x8?, x156?
@@ -2327,7 +2382,7 @@ L1 (SSA Block: blk0):
 	add x163?, x162?, #0x4
 	subs xzr, x5?, x163?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x174?, x8?, x162?
@@ -2336,7 +2391,7 @@ L1 (SSA Block: blk0):
 	add x169?, x168?, #0x13
 	subs xzr, x5?, x169?
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x0?]
 	exit_sequence x0?
 	add x173?, x8?, x168?
@@ -2390,7 +2445,7 @@ L1 (SSA Block: blk0):
 	add x10, x11, #0x4
 	subs xzr, x9, x10
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	ldr x10, [x1, #0x8]
@@ -2400,7 +2455,7 @@ L1 (SSA Block: blk0):
 	add x11, x12, #0x8
 	subs xzr, x9, x11
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x11, x10, x12
@@ -2409,7 +2464,7 @@ L1 (SSA Block: blk0):
 	add x11, x12, #0x4
 	subs xzr, x9, x11
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x11, x10, x12
@@ -2418,7 +2473,7 @@ L1 (SSA Block: blk0):
 	add x11, x12, #0x8
 	subs xzr, x9, x11
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x11, x10, x12
@@ -2427,7 +2482,7 @@ L1 (SSA Block: blk0):
 	add x11, x12, #0x13
 	subs xzr, x9, x11
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x11, x10, x12
@@ -2436,7 +2491,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x17
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2445,7 +2500,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x13
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2454,7 +2509,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x17
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2463,7 +2518,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x1
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2472,7 +2527,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x10
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2481,7 +2536,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x1
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2490,7 +2545,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x10
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2499,7 +2554,7 @@ L1 (SSA Block: blk0):
 	add x12, x13, #0x2
 	subs xzr, x9, x12
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x12, x10, x13
@@ -2508,7 +2563,7 @@ L1 (SSA Block: blk0):
 	add x13, x14, #0x11
 	subs xzr, x9, x13
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x13, x10, x14
@@ -2517,7 +2572,7 @@ L1 (SSA Block: blk0):
 	add x14, x15, #0x2
 	subs xzr, x9, x14
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x14, x10, x15
@@ -2526,7 +2581,7 @@ L1 (SSA Block: blk0):
 	add x15, x16, #0x11
 	subs xzr, x9, x15
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x15, x10, x16
@@ -2535,7 +2590,7 @@ L1 (SSA Block: blk0):
 	add x16, x17, #0x1
 	subs xzr, x9, x16
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x16, x10, x17
@@ -2544,7 +2599,7 @@ L1 (SSA Block: blk0):
 	add x17, x18, #0x10
 	subs xzr, x9, x17
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x17, x10, x18
@@ -2553,7 +2608,7 @@ L1 (SSA Block: blk0):
 	add x18, x19, #0x1
 	subs xzr, x9, x18
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x18, x10, x19
@@ -2562,7 +2617,7 @@ L1 (SSA Block: blk0):
 	add x19, x20, #0x10
 	subs xzr, x9, x19
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x19, x10, x20
@@ -2571,7 +2626,7 @@ L1 (SSA Block: blk0):
 	add x20, x21, #0x2
 	subs xzr, x9, x20
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x20, x10, x21
@@ -2580,7 +2635,7 @@ L1 (SSA Block: blk0):
 	add x21, x22, #0x11
 	subs xzr, x9, x21
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x21, x10, x22
@@ -2589,7 +2644,7 @@ L1 (SSA Block: blk0):
 	add x22, x23, #0x2
 	subs xzr, x9, x22
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x22, x10, x23
@@ -2598,7 +2653,7 @@ L1 (SSA Block: blk0):
 	add x23, x24, #0x11
 	subs xzr, x9, x23
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x23, x10, x24
@@ -2607,7 +2662,7 @@ L1 (SSA Block: blk0):
 	add x24, x25, #0x4
 	subs xzr, x9, x24
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x24, x10, x25
@@ -2616,7 +2671,7 @@ L1 (SSA Block: blk0):
 	add x25, x26, #0x13
 	subs xzr, x9, x25
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x25, x10, x26
@@ -2625,7 +2680,7 @@ L1 (SSA Block: blk0):
 	add x26, x28, #0x4
 	subs xzr, x9, x26
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x26, x10, x28
@@ -2634,7 +2689,7 @@ L1 (SSA Block: blk0):
 	add x28, x29, #0x13
 	subs xzr, x9, x28
 	b.hs #0x20
-	movz x27, #0x4, LSL 0
+	movz x27, #0x4, lsl 0
 	str w27, [x8]
 	exit_sequence x8
 	add x8, x10, x29
@@ -2806,7 +2861,7 @@ L10 (SSA Block: blk5):
 	ret
 L4 (SSA Block: blk9):
 L11 (SSA Block: blk4):
-	movz w0, #0xd, LSL 0
+	movz w0, #0xd, lsl 0
 	ret
 L5 (SSA Block: blk10):
 L12 (SSA Block: blk3):
@@ -2822,7 +2877,7 @@ L14 (SSA Block: blk1):
 	ret
 L8 (SSA Block: blk13):
 L9 (SSA Block: blk6):
-	movz w0, #0xb, LSL 0
+	movz w0, #0xb, lsl 0
 	ret
 `,
 			afterFinalizeARM64: `
@@ -2841,7 +2896,7 @@ L10 (SSA Block: blk5):
 	ret
 L4 (SSA Block: blk9):
 L11 (SSA Block: blk4):
-	movz w0, #0xd, LSL 0
+	movz w0, #0xd, lsl 0
 	ldr x30, [sp], #0x10
 	ret
 L5 (SSA Block: blk10):
@@ -2861,7 +2916,7 @@ L14 (SSA Block: blk1):
 	ret
 L8 (SSA Block: blk13):
 L9 (SSA Block: blk6):
-	movz w0, #0xb, LSL 0
+	movz w0, #0xb, lsl 0
 	ldr x30, [sp], #0x10
 	ret
 `,
diff --git a/internal/engine/wazevo/backend/isa/arm64/abi_go_call_test.go b/internal/engine/wazevo/backend/isa/arm64/abi_go_call_test.go
index f19a389d..a11d1848 100644
--- a/internal/engine/wazevo/backend/isa/arm64/abi_go_call_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/abi_go_call_test.go
@@ -69,7 +69,7 @@ func TestMachine_CompileGoFunctionTrampoline(t *testing.T) {
 	str x1, [x0, #0x460]
 	add x15, x0, #0x468
 	str d0, [x15], #0x8
-	movz w17, #0x6406, LSL 0
+	movz w17, #0x6406, lsl 0
 	str w17, [x0]
 	mov x27, sp
 	str x27, [x0, #0x38]
@@ -151,7 +151,7 @@ func TestMachine_CompileGoFunctionTrampoline(t *testing.T) {
 	str d1, [x15], #0x8
 	str x2, [x15], #0x8
 	str x3, [x15], #0x8
-	movz w17, #0x6406, LSL 0
+	movz w17, #0x6406, lsl 0
 	str w17, [x0]
 	mov x27, sp
 	str x27, [x0, #0x38]
diff --git a/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go b/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
index 26a2ed68..010e2513 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
@@ -116,6 +116,45 @@ func TestInstruction_encode(t *testing.T) {
 		{want: "fb633b8b", setup: func(i *instruction) {
 			i.asALU(aluOpAdd, operandNR(tmpRegVReg), operandNR(spVReg), operandNR(tmpRegVReg), true)
 		}},
+		{want: "2000020a", setup: func(i *instruction) {
+			i.asALU(aluOpAnd, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), false)
+		}},
+		{want: "2000028a", setup: func(i *instruction) {
+			i.asALU(aluOpAnd, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), true)
+		}},
+		{want: "2010028a", setup: func(i *instruction) {
+			i.asALU(aluOpAnd, operandNR(x0VReg), operandNR(x1VReg), operandSR(x2VReg, 4, shiftOpLSL), true)
+		}},
+		{want: "2030428a", setup: func(i *instruction) {
+			i.asALU(aluOpAnd, operandNR(x0VReg), operandNR(x1VReg), operandSR(x2VReg, 12, shiftOpLSR), true)
+		}},
+		{want: "2000022a", setup: func(i *instruction) {
+			i.asALU(aluOpOrr, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), false)
+		}},
+		{want: "200002aa", setup: func(i *instruction) {
+			i.asALU(aluOpOrr, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), true)
+		}},
+		{want: "201002aa", setup: func(i *instruction) {
+			i.asALU(aluOpOrr, operandNR(x0VReg), operandNR(x1VReg), operandSR(x2VReg, 4, shiftOpLSL), true)
+		}},
+		{want: "201082aa", setup: func(i *instruction) {
+			i.asALU(aluOpOrr, operandNR(x0VReg), operandNR(x1VReg), operandSR(x2VReg, 4, shiftOpASR), true)
+		}},
+		{want: "2000024a", setup: func(i *instruction) {
+			i.asALU(aluOpEor, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), false)
+		}},
+		{want: "200002ca", setup: func(i *instruction) {
+			i.asALU(aluOpEor, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), true)
+		}},
+		{want: "201002ca", setup: func(i *instruction) {
+			i.asALU(aluOpEor, operandNR(x0VReg), operandNR(x1VReg), operandSR(x2VReg, 4, shiftOpLSL), true)
+		}},
+		{want: "202cc21a", setup: func(i *instruction) {
+			i.asALU(aluOpRotR, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), false)
+		}},
+		{want: "202cc29a", setup: func(i *instruction) {
+			i.asALU(aluOpRotR, operandNR(x0VReg), operandNR(x1VReg), operandNR(x2VReg), true)
+		}},
 		{want: "30000010", setup: func(i *instruction) { i.asAdr(v16VReg, 4) }},
 		{want: "50050030", setup: func(i *instruction) { i.asAdr(v16VReg, 169) }},
 		{want: "5000001c020000140000803f", setup: func(i *instruction) {
diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_constant_test.go b/internal/engine/wazevo/backend/isa/arm64/lower_constant_test.go
index 29a84eab..0fa236b0 100644
--- a/internal/engine/wazevo/backend/isa/arm64/lower_constant_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/lower_constant_test.go
@@ -77,15 +77,15 @@ func TestMachine_lowerConstantI32(t *testing.T) {
 		val uint32
 		exp []string
 	}{
-		{val: 0, exp: []string{"movz w0, #0x0, LSL 0"}},
-		{val: 0xffff, exp: []string{"movz w0, #0xffff, LSL 0"}},
-		{val: 0xffff_0000, exp: []string{"movz w0, #0xffff, LSL 16"}},
-		{val: 0xffff_fffe, exp: []string{"movn w0, #0x1, LSL 0"}},
+		{val: 0, exp: []string{"movz w0, #0x0, lsl 0"}},
+		{val: 0xffff, exp: []string{"movz w0, #0xffff, lsl 0"}},
+		{val: 0xffff_0000, exp: []string{"movz w0, #0xffff, lsl 16"}},
+		{val: 0xffff_fffe, exp: []string{"movn w0, #0x1, lsl 0"}},
 		{val: 0x2, exp: []string{"orr w0, wzr, #0x2"}},
 		{val: 0x80000001, exp: []string{"orr w0, wzr, #0x80000001"}},
 		{val: 0xf00000f, exp: []string{
-			"movz w0, #0xf, LSL 0",
-			"movk w0, #0xf00, LSL 16",
+			"movz w0, #0xf, lsl 0",
+			"movk w0, #0xf00, lsl 16",
 		}},
 	} {
 		tc := tc
@@ -104,43 +104,43 @@ func TestMachine_lowerConstantI64(t *testing.T) {
 		val uint64
 		exp []string
 	}{
-		{val: 0x0, exp: []string{"movz x0, #0x0, LSL 0"}},
+		{val: 0x0, exp: []string{"movz x0, #0x0, lsl 0"}},
 		{val: 0x1, exp: []string{"orr x0, xzr, #0x1"}},
 		{val: 0x3, exp: []string{"orr x0, xzr, #0x3"}},
 		{val: 0xfff000, exp: []string{"orr x0, xzr, #0xfff000"}},
-		{val: 0x8001 << 16, exp: []string{"movz x0, #0x8001, LSL 16"}},
-		{val: 0x8001 << 32, exp: []string{"movz x0, #0x8001, LSL 32"}},
-		{val: 0x8001 << 48, exp: []string{"movz x0, #0x8001, LSL 48"}},
-		{val: invert(0x8001 << 16), exp: []string{"movn x0, #0x8001, LSL 16"}},
-		{val: invert(0x8001 << 32), exp: []string{"movn x0, #0x8001, LSL 32"}},
-		{val: invert(0x8001 << 48), exp: []string{"movn x0, #0x8001, LSL 48"}},
+		{val: 0x8001 << 16, exp: []string{"movz x0, #0x8001, lsl 16"}},
+		{val: 0x8001 << 32, exp: []string{"movz x0, #0x8001, lsl 32"}},
+		{val: 0x8001 << 48, exp: []string{"movz x0, #0x8001, lsl 48"}},
+		{val: invert(0x8001 << 16), exp: []string{"movn x0, #0x8001, lsl 16"}},
+		{val: invert(0x8001 << 32), exp: []string{"movn x0, #0x8001, lsl 32"}},
+		{val: invert(0x8001 << 48), exp: []string{"movn x0, #0x8001, lsl 48"}},
 		{val: 0x80000001 << 16, exp: []string{
-			"movz x0, #0x1, LSL 16",
-			"movk x0, #0x8000, LSL 32",
+			"movz x0, #0x1, lsl 16",
+			"movk x0, #0x8000, lsl 32",
 		}},
 		{val: 0x40000001, exp: []string{
-			"movz x0, #0x1, LSL 0",
-			"movk x0, #0x4000, LSL 16",
+			"movz x0, #0x1, lsl 0",
+			"movk x0, #0x4000, lsl 16",
 		}},
 		{val: 0xffffffffff001000, exp: []string{
-			"movn x0, #0xefff, LSL 0",
-			"movk x0, #0xff00, LSL 16",
+			"movn x0, #0xefff, lsl 0",
+			"movk x0, #0xff00, lsl 16",
 		}},
 		{val: 0xffff0000c466361f, exp: []string{
-			"movz x0, #0x361f, LSL 0",
-			"movk x0, #0xc466, LSL 16",
-			"movk x0, #0xffff, LSL 48",
+			"movz x0, #0x361f, lsl 0",
+			"movk x0, #0xc466, lsl 16",
+			"movk x0, #0xffff, lsl 48",
 		}},
 		{val: 0x89705f4136b4a598, exp: []string{
-			"movz x0, #0xa598, LSL 0",
-			"movk x0, #0x36b4, LSL 16",
-			"movk x0, #0x5f41, LSL 32",
-			"movk x0, #0x8970, LSL 48",
+			"movz x0, #0xa598, lsl 0",
+			"movk x0, #0x36b4, lsl 16",
+			"movk x0, #0x5f41, lsl 32",
+			"movk x0, #0x8970, lsl 48",
 		}},
 		{val: 0xffff_0001_0001_0001, exp: []string{
-			"movn x0, #0xfffe, LSL 0",
-			"movk x0, #0x1, LSL 16",
-			"movk x0, #0x1, LSL 32",
+			"movn x0, #0xfffe, lsl 0",
+			"movk x0, #0x1, lsl 16",
+			"movk x0, #0x1, lsl 32",
 		}},
 	} {
 		tc := tc
diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go
index ce7664c5..8b18e7e7 100644
--- a/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands_test.go
@@ -79,8 +79,8 @@ func TestMachine_getOperand_NR(t *testing.T) {
 			},
 			exp: operandNR(regalloc.VReg(100).SetRegType(regalloc.RegTypeInt)),
 			instructions: []string{
-				"movz w100?, #0xf, LSL 0",
-				"movk w100?, #0xf00, LSL 16",
+				"movz w100?, #0xf, lsl 0",
+				"movk w100?, #0xf00, lsl 16",
 			},
 		},
 		{
diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go b/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go
index 31ca7353..11a34491 100644
--- a/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/lower_mem_test.go
@@ -77,7 +77,7 @@ func TestAddressMode_format(t *testing.T) {
 	})
 	t.Run("addressModeKindRegScaled", func(t *testing.T) {
 		require.Equal(t,
-			"[x1, w0, LSL #0x1]",
+			"[x1, w0, lsl #0x1]",
 			addressMode{
 				kind:  addressModeKindRegScaled,
 				rn:    regalloc.FromRealReg(x1, regalloc.RegTypeInt),
@@ -87,7 +87,7 @@ func TestAddressMode_format(t *testing.T) {
 			}.format(16),
 		)
 		require.Equal(t,
-			"[x1, w0, LSL #0x1]",
+			"[x1, w0, lsl #0x1]",
 			addressMode{
 				kind:  addressModeKindRegScaled,
 				rn:    regalloc.FromRealReg(x1, regalloc.RegTypeInt),
@@ -97,7 +97,7 @@ func TestAddressMode_format(t *testing.T) {
 			}.format(16),
 		)
 		require.Equal(t,
-			"[x1, w0, LSL #0x2]",
+			"[x1, w0, lsl #0x2]",
 			addressMode{
 				kind:  addressModeKindRegScaled,
 				rn:    regalloc.FromRealReg(x1, regalloc.RegTypeInt),
@@ -107,7 +107,7 @@ func TestAddressMode_format(t *testing.T) {
 			}.format(32),
 		)
 		require.Equal(t,
-			"[x1, w0, LSL #0x2]",
+			"[x1, w0, lsl #0x2]",
 			addressMode{
 				kind:  addressModeKindRegScaled,
 				rn:    regalloc.FromRealReg(x1, regalloc.RegTypeInt),
@@ -117,7 +117,7 @@ func TestAddressMode_format(t *testing.T) {
 			}.format(32),
 		)
 		require.Equal(t,
-			"[x1, w0, LSL #0x3]",
+			"[x1, w0, lsl #0x3]",
 			addressMode{
 				kind:  addressModeKindRegScaled,
 				rn:    regalloc.FromRealReg(x1, regalloc.RegTypeInt),
@@ -127,7 +127,7 @@ func TestAddressMode_format(t *testing.T) {
 			}.format(64),
 		)
 		require.Equal(t,
-			"[x1, w0, LSL #0x3]",
+			"[x1, w0, lsl #0x3]",
 			addressMode{
 				kind:  addressModeKindRegScaled,
 				rn:    regalloc.FromRealReg(x1, regalloc.RegTypeInt),
@@ -508,8 +508,8 @@ func TestMachine_addConstToReg64(t *testing.T) {
 		ctx, _, m := newSetupWithMockContext()
 		ctx.vRegCounter = nextVRegID - 1
 		m.addConstToReg64(regalloc.FromRealReg(x15, regalloc.RegTypeInt), c)
-		require.Equal(t, `movz x101?, #0x1, LSL 0
-movk x101?, #0x1, LSL 32
+		require.Equal(t, `movz x101?, #0x1, lsl 0
+movk x101?, #0x1, lsl 32
 add x100?, x15, x101?`, formatEmittedInstructionsInCurrentBlock(m))
 	})
 }
diff --git a/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue_test.go b/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue_test.go
index d8c2a8cc..0a89bf11 100644
--- a/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue_test.go
@@ -170,12 +170,12 @@ func TestMachine_insertStackBoundsCheck(t *testing.T) {
 		{
 			requiredStackSize: 0xfff_0,
 			exp: `
-	movz x27, #0xfff0, LSL 0
+	movz x27, #0xfff0, lsl 0
 	sub x27, sp, x27
 	ldr x11, [x0, #0x28]
 	subs xzr, x27, x11
 	b.ge #0x14
-	movz x27, #0xfff0, LSL 0
+	movz x27, #0xfff0, lsl 0
 	str x27, [x0, #0x40]
 	ldr x27, [x0, #0x50]
 	bl w27
diff --git a/internal/engine/wazevo/backend/isa/arm64/machine_test.go b/internal/engine/wazevo/backend/isa/arm64/machine_test.go
index cced4065..b7560e92 100644
--- a/internal/engine/wazevo/backend/isa/arm64/machine_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/machine_test.go
@@ -69,8 +69,8 @@ func TestMachine_resolveAddressingMode(t *testing.T) {
 		m.rootInstr = root
 		require.Equal(t, `
 	udf
-	movz x27, #0x1, LSL 0
-	movk x27, #0x4000, LSL 16
+	movz x27, #0x1, lsl 0
+	movk x27, #0x4000, lsl 16
 	ldr x17, [sp, x27]
 `, m.Format())
 	})
diff --git a/internal/engine/wazevo/frontend/frontend_test.go b/internal/engine/wazevo/frontend/frontend_test.go
index a069f8ed..61892bd2 100644
--- a/internal/engine/wazevo/frontend/frontend_test.go
+++ b/internal/engine/wazevo/frontend/frontend_test.go
@@ -570,6 +570,25 @@ blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64)
 	v24:i32 = Icmp ge_u, v2, v3
 	v25:i32 = Icmp ge_u, v4, v5
 	Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25
+`,
+		},
+		{
+			name: "integer bitwise", m: testcases.IntegerBitwise.Module,
+			exp: `
+blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64)
+	v6:i32 = Band v2, v3
+	v7:i32 = Bor v2, v3
+	v8:i32 = Bxor v2, v3
+	v9:i32 = Rotr v2, v3
+	v10:i64 = Band v4, v5
+	v11:i64 = Bor v4, v5
+	v12:i64 = Bxor v4, v5
+	v13:i64 = Iconst_64 0x8
+	v14:i64 = Ishl v5, v13
+	v15:i64 = Bxor v4, v14
+	v16:i64 = Rotl v4, v5
+	v17:i64 = Rotr v4, v5
+	Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v15, v16, v17
 `,
 		},
 		{
diff --git a/internal/engine/wazevo/testcases/testcases.go b/internal/engine/wazevo/testcases/testcases.go
index 0016389a..16cac353 100644
--- a/internal/engine/wazevo/testcases/testcases.go
+++ b/internal/engine/wazevo/testcases/testcases.go
@@ -653,6 +653,57 @@ var (
 			wasm.OpcodeEnd,
 		}, []wasm.ValueType{}),
 	}
+	IntegerBitwise = TestCase{
+		Name: "integer_bitwise",
+		Module: SingleFunctionModule(wasm.FunctionType{
+			Params:  []wasm.ValueType{i32, i32, i64, i64},
+			Results: []wasm.ValueType{i32, i32, i32, i32, i64, i64, i64, i64, i64, i64},
+		}, []byte{
+			wasm.OpcodeLocalGet, 0,
+			wasm.OpcodeLocalGet, 1,
+			wasm.OpcodeI32And,
+
+			wasm.OpcodeLocalGet, 0,
+			wasm.OpcodeLocalGet, 1,
+			wasm.OpcodeI32Or,
+
+			wasm.OpcodeLocalGet, 0,
+			wasm.OpcodeLocalGet, 1,
+			wasm.OpcodeI32Xor,
+
+			wasm.OpcodeLocalGet, 0,
+			wasm.OpcodeLocalGet, 1,
+			wasm.OpcodeI32Rotr,
+
+			wasm.OpcodeLocalGet, 2,
+			wasm.OpcodeLocalGet, 3,
+			wasm.OpcodeI64And,
+
+			wasm.OpcodeLocalGet, 2,
+			wasm.OpcodeLocalGet, 3,
+			wasm.OpcodeI64Or,
+
+			wasm.OpcodeLocalGet, 2,
+			wasm.OpcodeLocalGet, 3,
+			wasm.OpcodeI64Xor,
+
+			wasm.OpcodeLocalGet, 2,
+			wasm.OpcodeLocalGet, 3,
+			wasm.OpcodeI64Const, 8,
+			wasm.OpcodeI64Shl,
+			wasm.OpcodeI64Xor,
+
+			wasm.OpcodeLocalGet, 2,
+			wasm.OpcodeLocalGet, 3,
+			wasm.OpcodeI64Rotl,
+
+			wasm.OpcodeLocalGet, 2,
+			wasm.OpcodeLocalGet, 3,
+			wasm.OpcodeI64Rotr,
+
+			wasm.OpcodeEnd,
+		}, []wasm.ValueType{}),
+	}
 	IntegerShift = TestCase{
 		Name: "integer_shift",
 		Module: SingleFunctionModule(wasm.FunctionType{