diff --git a/src/alloy/backend/ivm/ivm_intcode.cc b/src/alloy/backend/ivm/ivm_intcode.cc index 54873c1a9..000908151 100644 --- a/src/alloy/backend/ivm/ivm_intcode.cc +++ b/src/alloy/backend/ivm/ivm_intcode.cc @@ -3054,6 +3054,46 @@ int Translate_SHR(TranslationContext& ctx, Instr* i) { return DispatchToC(ctx, i, fns[i->dest->type]); } +uint32_t IntCode_VECTOR_SHR_I8(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + const vec128_t& src2 = ics.rf[i->src2_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (int n = 0; n < 16; n++) { + dest.b16[n] = src1.b16[n] >> (src2.b16[n] & 0x7); + } + return IA_NEXT; +} +uint32_t IntCode_VECTOR_SHR_I16(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + const vec128_t& src2 = ics.rf[i->src2_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (int n = 0; n < 8; n++) { + dest.s8[n] = src1.s8[n] >> (src2.s8[n] & 0xF); + } + return IA_NEXT; +} +uint32_t IntCode_VECTOR_SHR_I32(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + const vec128_t& src2 = ics.rf[i->src2_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (int n = 0; n < 4; n++) { + dest.i4[n] = src1.i4[n] >> (src2.i4[n] & 0x1F); + } + return IA_NEXT; +} +int Translate_VECTOR_SHR(TranslationContext& ctx, Instr* i) { + static IntCodeFn fns[] = { + IntCode_VECTOR_SHR_I8, + IntCode_VECTOR_SHR_I16, + IntCode_VECTOR_SHR_I32, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + }; + return DispatchToC(ctx, i, fns[i->flags]); +} + uint32_t IntCode_SHA_I8(IntCodeState& ics, const IntCode* i) { ics.rf[i->dest_reg].i8 = ics.rf[i->src1_reg].i8 >> ics.rf[i->src2_reg].i8; return IA_NEXT; @@ -3083,6 +3123,46 @@ int Translate_SHA(TranslationContext& ctx, Instr* i) { return DispatchToC(ctx, i, fns[i->dest->type]); } +uint32_t IntCode_VECTOR_SHA_I8(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + const vec128_t& src2 = ics.rf[i->src2_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (int n = 0; n < 16; n++) { + dest.b16[n] = int8_t(src1.b16[n]) >> (src2.b16[n] & 0x7); + } + return IA_NEXT; +} +uint32_t IntCode_VECTOR_SHA_I16(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + const vec128_t& src2 = ics.rf[i->src2_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (int n = 0; n < 8; n++) { + dest.s8[n] = int16_t(src1.s8[n]) >> (src2.s8[n] & 0xF); + } + return IA_NEXT; +} +uint32_t IntCode_VECTOR_SHA_I32(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + const vec128_t& src2 = ics.rf[i->src2_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (int n = 0; n < 4; n++) { + dest.i4[n] = int32_t(src1.i4[n]) >> (src2.i4[n] & 0x1F); + } + return IA_NEXT; +} +int Translate_VECTOR_SHA(TranslationContext& ctx, Instr* i) { + static IntCodeFn fns[] = { + IntCode_VECTOR_SHA_I8, + IntCode_VECTOR_SHA_I16, + IntCode_VECTOR_SHA_I32, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + }; + return DispatchToC(ctx, i, fns[i->flags]); +} + template T ROTL(T v, int8_t sh) { return (T(v) << sh) | (T(v) >> ((sizeof(T) * 8) - sh)); @@ -3503,7 +3583,9 @@ static const TranslateFn dispatch_table[] = { Translate_SHL, Translate_VECTOR_SHL, Translate_SHR, + Translate_VECTOR_SHR, Translate_SHA, + Translate_VECTOR_SHA, Translate_ROTATE_LEFT, Translate_BYTE_SWAP, Translate_CNTLZ, diff --git a/src/alloy/backend/x64/lowering/lowering_sequences.cc b/src/alloy/backend/x64/lowering/lowering_sequences.cc index 052c54439..d76065b02 100644 --- a/src/alloy/backend/x64/lowering/lowering_sequences.cc +++ b/src/alloy/backend/x64/lowering/lowering_sequences.cc @@ -556,12 +556,24 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) { return true; }); + table->AddSequence(OPCODE_VECTOR_SHR, [](LIRBuilder& lb, Instr*& instr) { + // TODO + instr = instr->next; + return true; + }); + table->AddSequence(OPCODE_SHA, [](LIRBuilder& lb, Instr*& instr) { // TODO instr = instr->next; return true; }); + table->AddSequence(OPCODE_VECTOR_SHA, [](LIRBuilder& lb, Instr*& instr) { + // TODO + instr = instr->next; + return true; + }); + table->AddSequence(OPCODE_ROTATE_LEFT, [](LIRBuilder& lb, Instr*& instr) { // TODO instr = instr->next; diff --git a/src/alloy/frontend/ppc/ppc_disasm_altivec.cc b/src/alloy/frontend/ppc/ppc_disasm_altivec.cc index 0ab8a7922..19dc372e4 100644 --- a/src/alloy/frontend/ppc/ppc_disasm_altivec.cc +++ b/src/alloy/frontend/ppc/ppc_disasm_altivec.cc @@ -57,6 +57,13 @@ namespace ppc { namespace { +int GeneralVX(InstrData& i, InstrDisasm& d) { + d.AddRegOperand(InstrRegister::kVMX, i.VX.VD, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kVMX, i.VX.VA, InstrRegister::kRead); + d.AddRegOperand(InstrRegister::kVMX, i.VX.VB, InstrRegister::kRead); + return d.Finish(); +} + int GeneralVXA(InstrData& i, InstrDisasm& d) { d.AddRegOperand(InstrRegister::kVMX, i.VXA.VD, InstrRegister::kWrite); d.AddRegOperand(InstrRegister::kVMX, i.VXA.VA, InstrRegister::kRead); @@ -368,10 +375,7 @@ XEDISASMR(vaddcuw, 0x10000180, VX )(InstrData& i, InstrDisasm& d) { XEDISASMR(vaddfp, 0x1000000A, VX )(InstrData& i, InstrDisasm& d) { d.Init("vaddfp", "Vector Add Floating Point", InstrDisasm::kVMX); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VD, InstrRegister::kWrite); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VA, InstrRegister::kRead); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VB, InstrRegister::kRead); - return d.Finish(); + return GeneralVX(i, d); } XEDISASMR(vaddfp128, VX128(5, 16), VX128 )(InstrData& i, InstrDisasm& d) { @@ -437,10 +441,7 @@ XEDISASMR(vadduws, 0x10000280, VX )(InstrData& i, InstrDisasm& d) { XEDISASMR(vand, 0x10000404, VX )(InstrData& i, InstrDisasm& d) { d.Init("vand", "Vector Logical AND", InstrDisasm::kVMX); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VD, InstrRegister::kWrite); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VA, InstrRegister::kRead); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VB, InstrRegister::kRead); - return d.Finish(); + return GeneralVX(i, d); } XEDISASMR(vand128, VX128(5, 528), VX128 )(InstrData& i, InstrDisasm& d) { @@ -452,10 +453,7 @@ XEDISASMR(vand128, VX128(5, 528), VX128 )(InstrData& i, InstrDisasm& XEDISASMR(vandc, 0x10000444, VX )(InstrData& i, InstrDisasm& d) { d.Init("vandc", "Vector Logical AND with Complement", InstrDisasm::kVMX); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VD, InstrRegister::kWrite); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VA, InstrRegister::kRead); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VB, InstrRegister::kRead); - return d.Finish(); + return GeneralVX(i, d); } XEDISASMR(vandc128, VX128(5, 592), VX128 )(InstrData& i, InstrDisasm& d) { @@ -991,10 +989,7 @@ XEDISASMR(vnmsubfp128, VX128(5, 336), VX128 )(InstrData& i, InstrDisasm& XEDISASMR(vnor, 0x10000504, VX )(InstrData& i, InstrDisasm& d) { d.Init("vnor", "Vector Logical NOR", InstrDisasm::kVMX); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VD, InstrRegister::kWrite); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VA, InstrRegister::kRead); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VB, InstrRegister::kRead); - return d.Finish(); + return GeneralVX(i, d); } XEDISASMR(vnor128, VX128(5, 656), VX128 )(InstrData& i, InstrDisasm& d) { @@ -1006,10 +1001,7 @@ XEDISASMR(vnor128, VX128(5, 656), VX128 )(InstrData& i, InstrDisasm& XEDISASMR(vor, 0x10000484, VX )(InstrData& i, InstrDisasm& d) { d.Init("vor", "Vector Logical OR", InstrDisasm::kVMX); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VD, InstrRegister::kWrite); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VA, InstrRegister::kRead); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VB, InstrRegister::kRead); - return d.Finish(); + return GeneralVX(i, d); } XEDISASMR(vor128, VX128(5, 720), VX128 )(InstrData& i, InstrDisasm& d) { @@ -1421,67 +1413,67 @@ XEDISASMR(vspltw128, VX128_3(6, 1840), VX128_3)(InstrData& i, InstrDisasm& XEDISASMR(vsr, 0x100002C4, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsr", "Vector Shift Right", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsrab, 0x10000304, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsrab", "Vector Shift Right Algebraic Byte", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsrah, 0x10000344, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsrah", "Vector Shift Right Algebraic Half Word", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsraw, 0x10000384, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsraw", "Vector Shift Right Algebraic Word", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsraw128, VX128(6, 336), VX128 )(InstrData& i, InstrDisasm& d) { d.Init("vsraw128", "Vector128 Shift Right Arithmetic Word", InstrDisasm::kVMX); - return 1; + return GeneralVX128(i, d); } XEDISASMR(vsrb, 0x10000204, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsrb", "Vector Shift Right Byte", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsrh, 0x10000244, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsrh", "Vector Shift Right Half Word", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsro, 0x1000044C, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsro", "Vector Shift Right Octet", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsro128, VX128(5, 976), VX128 )(InstrData& i, InstrDisasm& d) { d.Init("vsro128", "Vector128 Shift Right Octet", InstrDisasm::kVMX); - return 1; + return GeneralVX128(i, d); } XEDISASMR(vsrw, 0x10000284, VX )(InstrData& i, InstrDisasm& d) { d.Init("vsrw", "Vector Shift Right Word", InstrDisasm::kVMX); - return 1; + return GeneralVX(i, d); } XEDISASMR(vsrw128, VX128(6, 464), VX128 )(InstrData& i, InstrDisasm& d) { d.Init("vsrw128", "Vector128 Shift Right Word", InstrDisasm::kVMX); - return 1; + return GeneralVX128(i, d); } XEDISASMR(vsubcuw, 0x10000580, VX )(InstrData& i, InstrDisasm& d) { @@ -1637,21 +1629,13 @@ XEDISASMR(vupklsh, 0x100002CE, VX )(InstrData& i, InstrDisasm& d) { XEDISASMR(vupkd3d128, VX128_3(6, 2032), VX128_3)(InstrData& i, InstrDisasm& d) { d.Init("vupkd3d128", "Vector128 Unpack D3Dtype", InstrDisasm::kVMX); - const uint32_t vd = VX128_3_VD128; - const uint32_t vb = VX128_3_VB128; - d.AddRegOperand(InstrRegister::kVMX, vd, InstrRegister::kWrite); - d.AddRegOperand(InstrRegister::kVMX, vb, InstrRegister::kRead); - d.AddUImmOperand(i.VX128_3.IMM, 1); - return d.Finish(); + return GeneralVX128_3(i, d); } XEDISASMR(vxor, 0x100004C4, VX )(InstrData& i, InstrDisasm& d) { d.Init("vxor", "Vector Logical XOR", InstrDisasm::kVMX); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VD, InstrRegister::kWrite); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VA, InstrRegister::kRead); - d.AddRegOperand(InstrRegister::kVMX, i.VX.VB, InstrRegister::kRead); - return d.Finish(); + return GeneralVX(i, d); } XEDISASMR(vxor128, VX128(5, 784), VX128 )(InstrData& i, InstrDisasm& d) { diff --git a/src/alloy/frontend/ppc/ppc_emit_altivec.cc b/src/alloy/frontend/ppc/ppc_emit_altivec.cc index ac64a52ba..7ad3cf6cd 100644 --- a/src/alloy/frontend/ppc/ppc_emit_altivec.cc +++ b/src/alloy/frontend/ppc/ppc_emit_altivec.cc @@ -1486,50 +1486,67 @@ XEEMITTER(vsr, 0x100002C4, VX )(PPCHIRBuilder& f, InstrData& i) { } XEEMITTER(vsrab, 0x10000304, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // (VD) <- (VA) >>a (VB) by bytes + Value* v = f.VectorSha(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT8_TYPE); + f.StoreVR(i.VX.VD, v); + return 0; } XEEMITTER(vsrah, 0x10000344, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // (VD) <- (VA) >>a (VB) by halfwords + Value* v = f.VectorSha(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT16_TYPE); + f.StoreVR(i.VX.VD, v); + return 0; } +int InstrEmit_vsraw_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) { + // (VD) <- (VA) >>a (VB) by words + Value* v = f.VectorSha(f.LoadVR(va), f.LoadVR(vb), INT32_TYPE); + f.StoreVR(vd, v); + return 0; +} XEEMITTER(vsraw, 0x10000384, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vsraw_(f, i.VX.VD, i.VX.VA, i.VX.VB); } XEEMITTER(vsraw128, VX128(6, 336), VX128 )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vsraw_(f, VX128_VD128, VX128_VA128, VX128_VB128); } XEEMITTER(vsrb, 0x10000204, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // (VD) <- (VA) >> (VB) by bytes + Value* v = f.VectorShr(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT8_TYPE); + f.StoreVR(i.VX.VD, v); + return 0; } XEEMITTER(vsrh, 0x10000244, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // (VD) <- (VA) >> (VB) by halfwords + Value* v = f.VectorShr(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT16_TYPE); + f.StoreVR(i.VX.VD, v); + return 0; } -XEEMITTER(vsro, 0x1000044C, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); +int InstrEmit_vsro_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) { return 1; } +XEEMITTER(vsro, 0x1000044C, VX )(PPCHIRBuilder& f, InstrData& i) { + return InstrEmit_vsro_(f, i.VX.VD, i.VX.VA, i.VX.VB); +} XEEMITTER(vsro128, VX128(5, 976), VX128 )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vsro_(f, VX128_VD128, VX128_VA128, VX128_VB128); } +int InstrEmit_vsrw_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) { + // (VD) <- (VA) >> (VB) by words + Value* v = f.VectorShr(f.LoadVR(va), f.LoadVR(vb), INT32_TYPE); + f.StoreVR(vd, v); + return 0; +} XEEMITTER(vsrw, 0x10000284, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vsrw_(f, i.VX.VD, i.VX.VA, i.VX.VB); } XEEMITTER(vsrw128, VX128(6, 464), VX128 )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vsrw_(f, VX128_VD128, VX128_VA128, VX128_VB128); } XEEMITTER(vsubcuw, 0x10000580, VX )(PPCHIRBuilder& f, InstrData& i) { diff --git a/src/alloy/hir/hir_builder.cc b/src/alloy/hir/hir_builder.cc index f5bd67e81..c08f96a72 100644 --- a/src/alloy/hir/hir_builder.cc +++ b/src/alloy/hir/hir_builder.cc @@ -1433,7 +1433,7 @@ Value* HIRBuilder::Shl(Value* value1, int8_t value2) { } Value* HIRBuilder::VectorShl(Value* value1, Value* value2, - TypeName part_type) { + TypeName part_type) { ASSERT_VECTOR_TYPE(value1); ASSERT_VECTOR_TYPE(value2); @@ -1469,6 +1469,20 @@ Value* HIRBuilder::Shr(Value* value1, int8_t value2) { return Shr(value1, LoadConstant(value2)); } +Value* HIRBuilder::VectorShr(Value* value1, Value* value2, + TypeName part_type) { + ASSERT_VECTOR_TYPE(value1); + ASSERT_VECTOR_TYPE(value2); + + Instr* i = AppendInstr( + OPCODE_VECTOR_SHR_info, part_type, + AllocValue(value1->type)); + i->set_src1(value1); + i->set_src2(value2); + i->src3.value = NULL; + return i->dest; +} + Value* HIRBuilder::Sha(Value* value1, Value* value2) { ASSERT_INTEGER_TYPE(value1); ASSERT_INTEGER_TYPE(value2); @@ -1492,6 +1506,20 @@ Value* HIRBuilder::Sha(Value* value1, int8_t value2) { return Sha(value1, LoadConstant(value2)); } +Value* HIRBuilder::VectorSha(Value* value1, Value* value2, + TypeName part_type) { + ASSERT_VECTOR_TYPE(value1); + ASSERT_VECTOR_TYPE(value2); + + Instr* i = AppendInstr( + OPCODE_VECTOR_SHA_info, part_type, + AllocValue(value1->type)); + i->set_src1(value1); + i->set_src2(value2); + i->src3.value = NULL; + return i->dest; +} + Value* HIRBuilder::RotateLeft(Value* value1, Value* value2) { ASSERT_INTEGER_TYPE(value1); ASSERT_INTEGER_TYPE(value2); diff --git a/src/alloy/hir/hir_builder.h b/src/alloy/hir/hir_builder.h index 88a193c60..78f156dfa 100644 --- a/src/alloy/hir/hir_builder.h +++ b/src/alloy/hir/hir_builder.h @@ -173,12 +173,14 @@ public: Value* Xor(Value* value1, Value* value2); Value* Not(Value* value); Value* Shl(Value* value1, Value* value2); - Value* VectorShl(Value* value1, Value* value2, TypeName part_type); Value* Shl(Value* value1, int8_t value2); + Value* VectorShl(Value* value1, Value* value2, TypeName part_type); Value* Shr(Value* value1, Value* value2); Value* Shr(Value* value1, int8_t value2); + Value* VectorShr(Value* value1, Value* value2, TypeName part_type); Value* Sha(Value* value1, Value* value2); Value* Sha(Value* value1, int8_t value2); + Value* VectorSha(Value* value1, Value* value2, TypeName part_type); Value* RotateLeft(Value* value1, Value* value2); Value* ByteSwap(Value* value); Value* CountLeadingZeros(Value* value); diff --git a/src/alloy/hir/opcodes.h b/src/alloy/hir/opcodes.h index c697f4bbd..67f49c8ee 100644 --- a/src/alloy/hir/opcodes.h +++ b/src/alloy/hir/opcodes.h @@ -157,7 +157,9 @@ enum Opcode { OPCODE_SHL, OPCODE_VECTOR_SHL, OPCODE_SHR, + OPCODE_VECTOR_SHR, OPCODE_SHA, + OPCODE_VECTOR_SHA, OPCODE_ROTATE_LEFT, OPCODE_BYTE_SWAP, OPCODE_CNTLZ, diff --git a/src/alloy/hir/opcodes.inl b/src/alloy/hir/opcodes.inl index eb5fd27c6..75e27014b 100644 --- a/src/alloy/hir/opcodes.inl +++ b/src/alloy/hir/opcodes.inl @@ -463,12 +463,24 @@ DEFINE_OPCODE( OPCODE_SIG_V_V_V, 0); +DEFINE_OPCODE( + OPCODE_VECTOR_SHR, + "vector_shr", + OPCODE_SIG_V_V_V, + 0); + DEFINE_OPCODE( OPCODE_SHA, "sha", OPCODE_SIG_V_V_V, 0); +DEFINE_OPCODE( + OPCODE_VECTOR_SHA, + "vector_sha", + OPCODE_SIG_V_V_V, + 0); + DEFINE_OPCODE( OPCODE_ROTATE_LEFT, "rotate_left",