diff --git a/src/xenia/cpu/backend/a64/a64_sequences.cc b/src/xenia/cpu/backend/a64/a64_sequences.cc index 21fcde1de..2f7cb96e3 100644 --- a/src/xenia/cpu/backend/a64/a64_sequences.cc +++ b/src/xenia/cpu/backend/a64/a64_sequences.cc @@ -2440,36 +2440,52 @@ EMITTER_OPCODE_TABLE(OPCODE_SHL, SHL_I8, SHL_I16, SHL_I32, SHL_I64, SHL_V128); // ============================================================================ // OPCODE_SHR // ============================================================================ -// TODO(benvanik): optimize common shifts. -template -void EmitShrXX(A64Emitter& e, const ARGS& i) { - SEQ::EmitAssociativeBinaryOp( - e, i, - [](A64Emitter& e, REG dest_src, REG src) { - e.LSR(dest_src, dest_src, src); - }, - [](A64Emitter& e, REG dest_src, int8_t constant) { - e.LSR(dest_src, dest_src, constant); - }); -} struct SHR_I8 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitShrXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, WReg dest_src, WReg src) { + e.LSR(dest_src, dest_src, src); + }, + [](A64Emitter& e, WReg dest_src, int8_t constant) { + e.LSR(dest_src, dest_src, constant); + }); } }; -struct SHR_I16 : Sequence> { +struct SHR_I16 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitShrXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, WReg dest_src, WReg src) { + e.LSR(dest_src, dest_src, src); + }, + [](A64Emitter& e, WReg dest_src, int8_t constant) { + e.LSR(dest_src, dest_src, constant); + }); } }; -struct SHR_I32 : Sequence> { +struct SHR_I32 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitShrXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, WReg dest_src, WReg src) { + e.LSR(dest_src, dest_src, src); + }, + [](A64Emitter& e, WReg dest_src, int8_t constant) { + e.LSR(dest_src, dest_src, constant); + }); } }; -struct SHR_I64 : Sequence> { +struct SHR_I64 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitShrXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, XReg dest_src, WReg src) { + e.LSR(dest_src, dest_src, src.toX()); + }, + [](A64Emitter& e, XReg dest_src, int8_t constant) { + e.LSR(dest_src, dest_src, constant); + }); } }; struct SHR_V128 : Sequence> { @@ -2503,36 +2519,55 @@ EMITTER_OPCODE_TABLE(OPCODE_SHR, SHR_I8, SHR_I16, SHR_I32, SHR_I64, SHR_V128); // ============================================================================ // OPCODE_SHA // ============================================================================ -// TODO(benvanik): optimize common shifts. -template -void EmitSarXX(A64Emitter& e, const ARGS& i) { - SEQ::EmitAssociativeBinaryOp( - e, i, - [](A64Emitter& e, REG dest_src, REG src) { - e.ASR(dest_src, dest_src, src); - }, - [](A64Emitter& e, REG dest_src, int8_t constant) { - e.ASR(dest_src, dest_src, constant); - }); -} struct SHA_I8 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitSarXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, WReg dest_src, WReg src) { + e.SXTB(dest_src, dest_src); + e.ASR(dest_src, dest_src, src); + }, + [](A64Emitter& e, WReg dest_src, int8_t constant) { + e.SXTB(dest_src, dest_src); + e.ASR(dest_src, dest_src, constant); + }); } }; struct SHA_I16 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitSarXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, WReg dest_src, WReg src) { + e.SXTH(dest_src, dest_src); + e.ASR(dest_src, dest_src, src); + }, + [](A64Emitter& e, WReg dest_src, int8_t constant) { + e.ASR(dest_src, dest_src, constant); + }); } }; struct SHA_I32 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitSarXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, WReg dest_src, WReg src) { + e.ASR(dest_src, dest_src, src); + }, + [](A64Emitter& e, WReg dest_src, int8_t constant) { + e.ASR(dest_src, dest_src, constant); + }); } }; -struct SHA_I64 : Sequence> { +struct SHA_I64 : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - EmitSarXX(e, i); + Sequence::EmitAssociativeBinaryOp( + e, i, + [](A64Emitter& e, XReg dest_src, WReg src) { + e.ASR(dest_src, dest_src, src.toX()); + }, + [](A64Emitter& e, XReg dest_src, int8_t constant) { + e.ASR(dest_src, dest_src, constant); + }); } }; EMITTER_OPCODE_TABLE(OPCODE_SHA, SHA_I8, SHA_I16, SHA_I32, SHA_I64);