extension: Simplify rotation code

This commit is contained in:
MerryMage 2017-02-18 19:21:10 +00:00
parent cc9d2c4603
commit 6edcfeba0b
2 changed files with 33 additions and 27 deletions

View file

@ -9,29 +9,18 @@
namespace Dynarmic { namespace Dynarmic {
namespace Arm { namespace Arm {
IR::Value ArmTranslatorVisitor::SignZeroExtendRor(Reg m, SignExtendRotation rotate) { static IR::Value Rotate(IR::IREmitter& ir, Reg m, SignExtendRotation rotate) {
IR::Value rotated, reg_m = ir.GetRegister(m); const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
switch (rotate) { return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
case SignExtendRotation::ROR_0:
rotated = reg_m;
break;
case SignExtendRotation::ROR_8:
rotated = ir.RotateRight(reg_m, ir.Imm8(8), ir.Imm1(0)).result;
break;
case SignExtendRotation::ROR_16:
rotated = ir.RotateRight(reg_m, ir.Imm8(16), ir.Imm1(0)).result;
break;
case SignExtendRotation::ROR_24:
rotated = ir.RotateRight(reg_m, ir.Imm8(24), ir.Imm1(0)).result;
}
return rotated;
} }
bool ArmTranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// SXTAB <Rd>, <Rn>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto reg_n = ir.GetRegister(n); auto reg_n = ir.GetRegister(n);
auto result = ir.Add(reg_n, ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated))); auto result = ir.Add(reg_n, ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated)));
ir.SetRegister(d, result); ir.SetRegister(d, result);
@ -47,8 +36,10 @@ bool ArmTranslatorVisitor::arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotati
bool ArmTranslatorVisitor::arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// SXTAH <Rd>, <Rn>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto reg_n = ir.GetRegister(n); auto reg_n = ir.GetRegister(n);
auto result = ir.Add(reg_n, ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated))); auto result = ir.Add(reg_n, ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
ir.SetRegister(d, result); ir.SetRegister(d, result);
@ -59,8 +50,10 @@ bool ArmTranslatorVisitor::arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation
bool ArmTranslatorVisitor::arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// SXTB <Rd>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto result = ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated)); auto result = ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated));
ir.SetRegister(d, result); ir.SetRegister(d, result);
} }
@ -75,8 +68,10 @@ bool ArmTranslatorVisitor::arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotat
bool ArmTranslatorVisitor::arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// SXTH <Rd>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto result = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated)); auto result = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated));
ir.SetRegister(d, result); ir.SetRegister(d, result);
} }
@ -86,8 +81,10 @@ bool ArmTranslatorVisitor::arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate,
bool ArmTranslatorVisitor::arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// UXTAB <Rd>, <Rn>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto reg_n = ir.GetRegister(n); auto reg_n = ir.GetRegister(n);
auto result = ir.Add(reg_n, ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated))); auto result = ir.Add(reg_n, ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated)));
ir.SetRegister(d, result); ir.SetRegister(d, result);
@ -98,8 +95,10 @@ bool ArmTranslatorVisitor::arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation
bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC || n == Reg::PC) if (d == Reg::PC || m == Reg::PC || n == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// UXTAB16 <Rd>, <Rn>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto result = ir.And(rotated, ir.Imm32(0x00FF00FF)); auto result = ir.And(rotated, ir.Imm32(0x00FF00FF));
auto reg_n = ir.GetRegister(n); auto reg_n = ir.GetRegister(n);
result = ir.PackedAddU16(reg_n, result).result; result = ir.PackedAddU16(reg_n, result).result;
@ -111,8 +110,10 @@ bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotati
bool ArmTranslatorVisitor::arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// UXTAH <Rd>, <Rn>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto reg_n = ir.GetRegister(n); auto reg_n = ir.GetRegister(n);
auto result = ir.Add(reg_n, ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated))); auto result = ir.Add(reg_n, ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
ir.SetRegister(d, result); ir.SetRegister(d, result);
@ -123,8 +124,10 @@ bool ArmTranslatorVisitor::arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation
bool ArmTranslatorVisitor::arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// UXTB <Rd>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto result = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated)); auto result = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated));
ir.SetRegister(d, result); ir.SetRegister(d, result);
} }
@ -134,8 +137,10 @@ bool ArmTranslatorVisitor::arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate,
bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// UXTB16 <Rd>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto lower_half = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated)); auto lower_half = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated));
auto upper_half = ir.And(rotated, ir.Imm32(0x00FF0000)); auto upper_half = ir.And(rotated, ir.Imm32(0x00FF0000));
auto result = ir.Or(lower_half, upper_half); auto result = ir.Or(lower_half, upper_half);
@ -147,8 +152,10 @@ bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotat
bool ArmTranslatorVisitor::arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { bool ArmTranslatorVisitor::arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) if (d == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
// UXTH <Rd>, <Rm>, <rotate>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto rotated = SignZeroExtendRor(m, rotate); auto rotated = Rotate(ir, m, rotate);
auto result = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated)); auto result = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated));
ir.SetRegister(d, result); ir.SetRegister(d, result);
} }

View file

@ -64,7 +64,6 @@ struct ArmTranslatorVisitor final {
IR::IREmitter::ResultAndCarry EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in); IR::IREmitter::ResultAndCarry EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in);
IR::IREmitter::ResultAndCarry EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in); IR::IREmitter::ResultAndCarry EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in);
IR::Value SignZeroExtendRor(Reg m, SignExtendRotation rotate);
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn); template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn);
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn); template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn);