TranslateArm: Implement MRS, MSR (imm), MSR (reg)

This commit is contained in:
MerryMage 2016-08-14 19:39:16 +01:00
parent 30f3d869cc
commit e164ede4dc
9 changed files with 95 additions and 10 deletions

View file

@ -209,6 +209,16 @@ void EmitX64::EmitSetZFlag(IR::Block&, IR::Inst* inst) {
} }
} }
void EmitX64::EmitGetCpsr(IR::Block&, IR::Inst* inst) {
X64Reg result = reg_alloc.DefRegister(inst, any_gpr);
code->MOV(32, R(result), MJitStateCpsr());
}
void EmitX64::EmitSetCpsr(IR::Block&, IR::Inst* inst) {
X64Reg arg = reg_alloc.UseRegister(inst->GetArg(0), any_gpr);
code->MOV(32, MJitStateCpsr(), R(arg));
}
void EmitX64::EmitGetCFlag(IR::Block&, IR::Inst* inst) { void EmitX64::EmitGetCFlag(IR::Block&, IR::Inst* inst) {
X64Reg result = reg_alloc.DefRegister(inst, any_gpr); X64Reg result = reg_alloc.DefRegister(inst, any_gpr);
code->MOV(32, R(result), MJitStateCpsr()); code->MOV(32, R(result), MJitStateCpsr());

View file

@ -343,8 +343,9 @@ std::vector<ArmMatcher<V>> GetArmDecodeTable() {
// Status Register Access instructions // Status Register Access instructions
INST(&V::arm_CPS, "CPS", "111100010000---00000000---0-----"), // v6 INST(&V::arm_CPS, "CPS", "111100010000---00000000---0-----"), // v6
INST(&V::arm_SETEND, "SETEND", "1111000100000001000000e000000000"), // v6 INST(&V::arm_SETEND, "SETEND", "1111000100000001000000e000000000"), // v6
INST(&V::arm_MRS, "MRS", "----00010-00--------00--00000000"), // v3 INST(&V::arm_MRS, "MRS", "cccc000100001111dddd000000000000"), // v3
INST(&V::arm_MSR, "MSR", "----00-10-10----1111------------"), // v3 INST(&V::arm_MSR_imm, "MSR (imm)", "cccc00110010mm001111rrrrvvvvvvvv"), // v3
INST(&V::arm_MSR_reg, "MSR (reg)", "cccc00010010mm00111100000000nnnn"), // v3
INST(&V::arm_RFE, "RFE", "----0001101-0000---------110----"), // v6 INST(&V::arm_RFE, "RFE", "----0001101-0000---------110----"), // v6
INST(&V::arm_SRS, "SRS", "0000011--0-00000000000000001----"), // v6 INST(&V::arm_SRS, "SRS", "0000011--0-00000000000000001----"), // v6

View file

@ -749,8 +749,19 @@ public:
// Status register access instructions // Status register access instructions
std::string arm_CPS() { return "ice"; } std::string arm_CPS() { return "ice"; }
std::string arm_MRS() { return "ice"; } std::string arm_MRS(Cond cond, Reg d) {
std::string arm_MSR() { return "ice"; } return Common::StringFromFormat("mrs%s %s, apsr", CondToString(cond), RegToString(d));
}
std::string arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8) {
bool write_nzcvq = Common::Bit<1>(mask);
bool write_g = Common::Bit<0>(mask);
return Common::StringFromFormat("msr%s apsr_%s%s, #%u", CondToString(cond), write_nzcvq ? "nzcvq" : "", write_g ? "g" : "", ArmExpandImm(rotate, imm8));
}
std::string arm_MSR_reg(Cond cond, int mask, Reg n) {
bool write_nzcvq = Common::Bit<1>(mask);
bool write_g = Common::Bit<0>(mask);
return Common::StringFromFormat("msr%s apsr_%s%s, %s", CondToString(cond), write_nzcvq ? "nzcvq" : "", write_g ? "g" : "", RegToString(n));
}
std::string arm_RFE() { return "ice"; } std::string arm_RFE() { return "ice"; }
std::string arm_SETEND(bool E) { std::string arm_SETEND(bool E) {
return E ? "setend be" : "setend le"; return E ? "setend be" : "setend le";

View file

@ -102,6 +102,14 @@ void IREmitter::PushRSB(const LocationDescriptor& return_location) {
Inst(IR::Opcode::PushRSB, {IR::Value(return_location.UniqueHash())}); Inst(IR::Opcode::PushRSB, {IR::Value(return_location.UniqueHash())});
} }
IR::Value IREmitter::GetCpsr() {
return Inst(IR::Opcode::GetCpsr, {});
}
void IREmitter::SetCpsr(const IR::Value& value) {
Inst(IR::Opcode::SetCpsr, {value});
}
IR::Value IREmitter::GetCFlag() { IR::Value IREmitter::GetCFlag() {
return Inst(IR::Opcode::GetCFlag, {}); return Inst(IR::Opcode::GetCFlag, {});
} }

View file

@ -56,6 +56,8 @@ public:
void CallSupervisor(const IR::Value& value); void CallSupervisor(const IR::Value& value);
void PushRSB(const LocationDescriptor& return_location); void PushRSB(const LocationDescriptor& return_location);
IR::Value GetCpsr();
void SetCpsr(const IR::Value& value);
IR::Value GetCFlag(); IR::Value GetCFlag();
void SetNFlag(const IR::Value& value); void SetNFlag(const IR::Value& value);
void SetZFlag(const IR::Value& value); void SetZFlag(const IR::Value& value);

View file

@ -10,6 +10,8 @@ OPCODE(GetExtendedRegister64, T::F64, T::ExtRegRef
OPCODE(SetRegister, T::Void, T::RegRef, T::U32 ) OPCODE(SetRegister, T::Void, T::RegRef, T::U32 )
OPCODE(SetExtendedRegister32, T::Void, T::ExtRegRef, T::F32 ) OPCODE(SetExtendedRegister32, T::Void, T::ExtRegRef, T::F32 )
OPCODE(SetExtendedRegister64, T::Void, T::ExtRegRef, T::F64 ) OPCODE(SetExtendedRegister64, T::Void, T::ExtRegRef, T::F64 )
OPCODE(GetCpsr, T::U32, )
OPCODE(SetCpsr, T::Void, T::U32 )
OPCODE(GetNFlag, T::U1, ) OPCODE(GetNFlag, T::U1, )
OPCODE(SetNFlag, T::Void, T::U1 ) OPCODE(SetNFlag, T::Void, T::U1 )
OPCODE(GetZFlag, T::U1, ) OPCODE(GetZFlag, T::U1, )

View file

@ -13,12 +13,54 @@ bool ArmTranslatorVisitor::arm_CPS() {
return InterpretThisInstruction(); return InterpretThisInstruction();
} }
bool ArmTranslatorVisitor::arm_MRS() { bool ArmTranslatorVisitor::arm_MRS(Cond cond, Reg d) {
return InterpretThisInstruction(); if (d == Reg::PC)
return UnpredictableInstruction();
// MRS <Rd>, APSR
if (ConditionPassed(cond)) {
ir.SetRegister(d, ir.GetCpsr());
}
return true;
} }
bool ArmTranslatorVisitor::arm_MSR() { bool ArmTranslatorVisitor::arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8) {
return InterpretThisInstruction(); bool write_nzcvq = Common::Bit<1>(mask);
bool write_g = Common::Bit<0>(mask);
u32 imm32 = ArmExpandImm(rotate, imm8);
ASSERT_MSG(write_nzcvq || write_g, "Decode error");
// MSR <spec_reg>, #<imm32>
if (ConditionPassed(cond)) {
u32 cpsr_mask = 0;
if (write_nzcvq)
cpsr_mask |= 0xF8000000;
if (write_g)
cpsr_mask |= 0x000F0000;
auto old_cpsr = ir.And(ir.GetCpsr(), ir.Imm32(~cpsr_mask));
auto new_cpsr = ir.Imm32(imm32 & cpsr_mask);
ir.SetCpsr(ir.Or(old_cpsr, new_cpsr));
}
return true;
}
bool ArmTranslatorVisitor::arm_MSR_reg(Cond cond, int mask, Reg n) {
bool write_nzcvq = Common::Bit<1>(mask);
bool write_g = Common::Bit<0>(mask);
if (!write_nzcvq && !write_g)
return UnpredictableInstruction();
if (n == Reg::PC)
return UnpredictableInstruction();
// MSR <spec_reg>, #<imm32>
if (ConditionPassed(cond)) {
u32 cpsr_mask = 0;
if (write_nzcvq)
cpsr_mask |= 0xF8000000;
if (write_g)
cpsr_mask |= 0x000F0000;
auto old_cpsr = ir.And(ir.GetCpsr(), ir.Imm32(~cpsr_mask));
auto new_cpsr = ir.And(ir.GetRegister(n), ir.Imm32(cpsr_mask));
ir.SetCpsr(ir.Or(old_cpsr, new_cpsr));
}
return true;
} }
bool ArmTranslatorVisitor::arm_RFE() { bool ArmTranslatorVisitor::arm_RFE() {

View file

@ -318,8 +318,9 @@ struct ArmTranslatorVisitor final {
// Status register access instructions // Status register access instructions
bool arm_CPS(); bool arm_CPS();
bool arm_MRS(); bool arm_MRS(Cond cond, Reg d);
bool arm_MSR(); bool arm_MSR_imm(Cond cond, int mask, int rotate, Imm8 imm8);
bool arm_MSR_reg(Cond cond, int mask, Reg n);
bool arm_RFE(); bool arm_RFE();
bool arm_SETEND(bool E); bool arm_SETEND(bool E);
bool arm_SRS(); bool arm_SRS();

View file

@ -92,6 +92,14 @@ void GetSetElimination(IR::Block& block) {
do_get(v_info, inst); do_get(v_info, inst);
break; break;
} }
case IR::Opcode::SetCpsr:
case IR::Opcode::GetCpsr: {
n_info = {};
z_info = {};
c_info = {};
v_info = {};
break;
}
default: default:
break; break;
} }