TranslateArm: Implement MRS, MSR (imm), MSR (reg)
This commit is contained in:
parent
30f3d869cc
commit
e164ede4dc
9 changed files with 95 additions and 10 deletions
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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, {});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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, )
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue