diff --git a/src/frontend/A32/translate/translate_arm/load_store.cpp b/src/frontend/A32/translate/translate_arm/load_store.cpp index 70a3df76..8642bb57 100644 --- a/src/frontend/A32/translate/translate_arm/load_store.cpp +++ b/src/frontend/A32/translate/translate_arm/load_store.cpp @@ -55,555 +55,689 @@ static IR::U32 GetAddress(A32::IREmitter& ir, bool P, bool U, bool W, Reg n, IR: return address; } +// LDR , [PC, #+/-] bool ArmTranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm12 imm12) { - const bool add = U; - - // LDR , [PC, #+/-] - if (ConditionPassed(cond)) { - const u32 base = ir.AlignPC(4); - const u32 address = add ? (base + imm12) : (base - imm12); - const auto data = ir.ReadMemory32(ir.Imm32(address)); - - if (t == Reg::PC) { - ir.LoadWritePC(data); - ir.SetTerm(IR::Term::FastDispatchHint{}); - return false; - } - - ir.SetRegister(t, data); + if (!ConditionPassed(cond)) { + return true; } + + const bool add = U; + const u32 base = ir.AlignPC(4); + const u32 address = add ? (base + imm12) : (base - imm12); + const auto data = ir.ReadMemory32(ir.Imm32(address)); + + if (t == Reg::PC) { + ir.LoadWritePC(data); + ir.SetTerm(IR::Term::FastDispatchHint{}); + return false; + } + + ir.SetRegister(t, data); return true; } +// LDR , [, #+/-]{!} +// LDR , [], #+/- bool ArmTranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { - if (n == Reg::PC) + if (n == Reg::PC) { return UnpredictableInstruction(); + } + ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if ((!P || W) && n == t) + if ((!P || W) && n == t) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = imm12; + const auto offset = ir.Imm32(imm32); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.ReadMemory32(address); - // LDR , [, #+/-]{!} - // LDR , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ReadMemory32(address); + if (t == Reg::PC) { + ir.LoadWritePC(data); - if (t == Reg::PC) { - ir.LoadWritePC(data); - if (!P && W && n == Reg::R13) - ir.SetTerm(IR::Term::PopRSBHint{}); - else - ir.SetTerm(IR::Term::FastDispatchHint{}); - return false; + if (!P && W && n == Reg::R13) { + ir.SetTerm(IR::Term::PopRSBHint{}); + } else { + ir.SetTerm(IR::Term::FastDispatchHint{}); } - ir.SetRegister(t, data); + return false; } + + ir.SetRegister(t, data); return true; } +// LDR , [, #+/-]{!} +// LDR , [], #+/- bool ArmTranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if (m == Reg::PC) + if (m == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // LDR , [, #+/-]{!} - // LDR , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ReadMemory32(address); - - if (t == Reg::PC) { - ir.LoadWritePC(data); - ir.SetTerm(IR::Term::FastDispatchHint{}); - return false; - } - - ir.SetRegister(t, data); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.ReadMemory32(address); + + if (t == Reg::PC) { + ir.LoadWritePC(data); + ir.SetTerm(IR::Term::FastDispatchHint{}); + return false; + } + + ir.SetRegister(t, data); return true; } +// LDRB , [PC, #+/-] bool ArmTranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm12 imm12) { - if (t == Reg::PC) + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = imm12; const bool add = U; + const u32 base = ir.AlignPC(4); + const u32 address = add ? (base + imm32) : (base - imm32); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(ir.Imm32(address))); - // LDRB , [PC, #+/-] - if (ConditionPassed(cond)) { - const u32 base = ir.AlignPC(4); - const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(ir.Imm32(address))); - - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRB , [, #+/-]{!} +// LDRB , [], #+/- bool ArmTranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { - if (n == Reg::PC) + if (n == Reg::PC) { return UnpredictableInstruction(); + } + ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if ((!P || W) && n == t) + if ((!P || W) && n == t) { return UnpredictableInstruction(); - if (t == Reg::PC) + } + + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = imm12; + const auto offset = ir.Imm32(imm32); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); - // LDRB , [, #+/-]{!} - // LDRB , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); - - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRB , [, #+/-]{!} +// LDRB , [], #+/- bool ArmTranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if (t == Reg::PC || m == Reg::PC) + if (t == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // LDRB , [, #+/-]{!} - // LDRB , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); - - ir.SetRegister(t, data); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + + ir.SetRegister(t, data); return true; } +// LDRD , , [PC, #+/-] bool ArmTranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (RegNumber(t) % 2 == 1) + if (RegNumber(t) % 2 == 1) { return UnpredictableInstruction(); - if (t+1 == Reg::PC) + } + + if (t+1 == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const Reg t2 = t+1; const u32 imm32 = (imm8a << 4) | imm8b; const bool add = U; - // LDRD , , [PC, #+/-] - if (ConditionPassed(cond)) { - const u32 base = ir.AlignPC(4); - const u32 address = add ? (base + imm32) : (base - imm32); - const auto data_a = ir.ReadMemory32(ir.Imm32(address)); - const auto data_b = ir.ReadMemory32(ir.Imm32(address + 4)); + const u32 base = ir.AlignPC(4); + const u32 address = add ? (base + imm32) : (base - imm32); + const auto data_a = ir.ReadMemory32(ir.Imm32(address)); + const auto data_b = ir.ReadMemory32(ir.Imm32(address + 4)); - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); - } + ir.SetRegister(t, data_a); + ir.SetRegister(t2, data_b); return true; } +// LDRD , [, #+/-]{!} +// LDRD , [], #+/- bool ArmTranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (n == Reg::PC) + if (n == Reg::PC) { return UnpredictableInstruction(); - if (RegNumber(t) % 2 == 1) + } + + if (RegNumber(t) % 2 == 1) { return UnpredictableInstruction(); - if (!P && W) + } + + if (!P && W) { return UnpredictableInstruction(); - if ((!P || W) && (n == t || n == t+1)) + } + + if ((!P || W) && (n == t || n == t+1)) { return UnpredictableInstruction(); - if (t+1 == Reg::PC) + } + + if (t+1 == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const Reg t2 = t+1; const u32 imm32 = (imm8a << 4) | imm8b; - // LDRD , [, #+/-]{!} - // LDRD , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto data_a = ir.ReadMemory32(address_a); - const auto data_b = ir.ReadMemory32(address_b); + const auto offset = ir.Imm32(imm32); + const auto address_a = GetAddress(ir, P, U, W, n, offset); + const auto address_b = ir.Add(address_a, ir.Imm32(4)); + const auto data_a = ir.ReadMemory32(address_a); + const auto data_b = ir.ReadMemory32(address_b); - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); - } + ir.SetRegister(t, data_a); + ir.SetRegister(t2, data_b); return true; } +// LDRD , [, #+/-]{!} +// LDRD , [], #+/- bool ArmTranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { - if (RegNumber(t) % 2 == 1) + if (RegNumber(t) % 2 == 1) { return UnpredictableInstruction(); - if (!P && W) + } + + if (!P && W) { return UnpredictableInstruction(); - if (t+1 == Reg::PC || m == Reg::PC || m == t || m == t+1) + } + + if (t+1 == Reg::PC || m == Reg::PC || m == t || m == t+1) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t || n == t+1)) + } + + if ((!P || W) && (n == Reg::PC || n == t || n == t+1)) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const Reg t2 = t+1; + const auto offset = ir.GetRegister(m); + const auto address_a = GetAddress(ir, P, U, W, n, offset); + const auto address_b = ir.Add(address_a, ir.Imm32(4)); + const auto data_a = ir.ReadMemory32(address_a); + const auto data_b = ir.ReadMemory32(address_b); - // LDRD , [, #+/-]{!} - // LDRD , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.GetRegister(m); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto data_a = ir.ReadMemory32(address_a); - const auto data_b = ir.ReadMemory32(address_b); - - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); - } + ir.SetRegister(t, data_a); + ir.SetRegister(t2, data_b); return true; } +// LDRH , [PC, #-/+] bool ArmTranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm4 imm8a, Imm4 imm8b) { ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if (P == W) + if (P == W) { return UnpredictableInstruction(); - if (t == Reg::PC) + } + + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = (imm8a << 4) | imm8b; const bool add = U; + const u32 base = ir.AlignPC(4); + const u32 address = add ? (base + imm32) : (base - imm32); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address))); - // LDRH , [PC, #-/+] - if (ConditionPassed(cond)) { - const u32 base = ir.AlignPC(4); - const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address))); - - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRH , [, #+/-]{!} +// LDRH , [], #+/- bool ArmTranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (n == Reg::PC) + if (n == Reg::PC) { return UnpredictableInstruction(); + } + ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if ((!P || W) && n == t) + if ((!P || W) && n == t) { return UnpredictableInstruction(); - if (t == Reg::PC) + } + + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = (imm8a << 4) | imm8b; + const auto offset = ir.Imm32(imm32); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); - // LDRH , [, #+/-]{!} - // LDRH , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); - - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRH , [, #+/-]{!} +// LDRH , [], #+/- bool ArmTranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if (t == Reg::PC || m == Reg::PC) + if (t == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // LDRH , [, #+/-]{!} - // LDRH , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.GetRegister(m); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); - - ir.SetRegister(t, data); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = ir.GetRegister(m); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + + ir.SetRegister(t, data); return true; } +// LDRSB , [PC, #+/-] bool ArmTranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (t == Reg::PC) + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = (imm8a << 4) | imm8b; const bool add = U; - // LDRSB , [PC, #+/-] - if (ConditionPassed(cond)) { - const u32 base = ir.AlignPC(4); - const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(ir.Imm32(address))); + const u32 base = ir.AlignPC(4); + const u32 address = add ? (base + imm32) : (base - imm32); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(ir.Imm32(address))); - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRSB , [, #+/-]{!} +// LDRSB , [], #+/- bool ArmTranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (n == Reg::PC) + if (n == Reg::PC) { return UnpredictableInstruction(); + } + ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if ((!P || W) && n == t) + if ((!P || W) && n == t) { return UnpredictableInstruction(); - if (t == Reg::PC) + } + + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = (imm8a << 4) | imm8b; + const auto offset = ir.Imm32(imm32); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); - // LDRSB , [, #+/-]{!} - // LDRSB , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); - - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRSB , [, #+/-]{!} +// LDRSB , [], #+/- bool ArmTranslatorVisitor::arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if (t == Reg::PC || m == Reg::PC) + if (t == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // LDRSB , [, #+/-]{!} - // LDRSB , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.GetRegister(m); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); - - ir.SetRegister(t, data); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = ir.GetRegister(m); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); + + ir.SetRegister(t, data); return true; } +// LDRSH , [PC, #-/+] bool ArmTranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (t == Reg::PC) + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = (imm8a << 4) | imm8b; const bool add = U; + const u32 base = ir.AlignPC(4); + const u32 address = add ? (base + imm32) : (base - imm32); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address))); - // LDRSH , [PC, #-/+] - if (ConditionPassed(cond)) { - const u32 base = ir.AlignPC(4); - const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address))); - - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRSH , [, #+/-]{!} +// LDRSH , [], #+/- bool ArmTranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (n == Reg::PC) + if (n == Reg::PC) { return UnpredictableInstruction(); + } + ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if ((!P || W) && n == t) + if ((!P || W) && n == t) { return UnpredictableInstruction(); - if (t == Reg::PC) + } + + if (t == Reg::PC) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = (imm8a << 4) | imm8b; + const auto offset = ir.Imm32(imm32); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); - // LDRSH , [, #+/-]{!} - // LDRSH , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); - - ir.SetRegister(t, data); - } + ir.SetRegister(t, data); return true; } +// LDRSH , [, #+/-]{!} +// LDRSH , [], #+/- bool ArmTranslatorVisitor::arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { ASSERT_MSG(!(!P && W), "T form of instruction unimplemented"); - if (t == Reg::PC || m == Reg::PC) + if (t == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // LDRSH , [, #+/-]{!} - // LDRSH , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.GetRegister(m); - const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); - - ir.SetRegister(t, data); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = ir.GetRegister(m); + const auto address = GetAddress(ir, P, U, W, n, offset); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); + + ir.SetRegister(t, data); return true; } +// STR , [, #+/-]{!} +// STR , [], #+/- bool ArmTranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { - if ((!P || W) && (n == Reg::PC || n == t)) + if ((!P || W) && (n == Reg::PC || n == t)) { return UnpredictableInstruction(); - - // STR , [, #+/-]{!} - // STR , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm12); - const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory32(address, ir.GetRegister(t)); } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = ir.Imm32(imm12); + const auto address = GetAddress(ir, P, U, W, n, offset); + ir.WriteMemory32(address, ir.GetRegister(t)); return true; } +// STR , [, #+/-]{!} +// STR , [], #+/- bool ArmTranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { - if (m == Reg::PC) + if (m == Reg::PC) { return UnpredictableInstruction(); - - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // STR , [, #+/-]{!} - // STR , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; - const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory32(address, ir.GetRegister(t)); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; + const auto address = GetAddress(ir, P, U, W, n, offset); + ir.WriteMemory32(address, ir.GetRegister(t)); return true; } +// STRB , [, #+/-]{!} +// STRB , [], #+/- bool ArmTranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm12 imm12) { - if (t == Reg::PC) + if (t == Reg::PC) { return UnpredictableInstruction(); - - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // STRB , [, #+/-]{!} - // STRB , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm12); - const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = ir.Imm32(imm12); + const auto address = GetAddress(ir, P, U, W, n, offset); + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); return true; } +// STRB , [, #+/-]{!} +// STRB , [], #+/- bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm5 imm5, ShiftType shift, Reg m) { - if (t == Reg::PC || m == Reg::PC) + if (t == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); - - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // STRB , [, #+/-]{!} - // STRB , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; - const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; + const auto address = GetAddress(ir, P, U, W, n, offset); + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); return true; } +// STRD , [, #+/-]{!} +// STRD , [], #+/- bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (size_t(t) % 2 != 0) + if (size_t(t) % 2 != 0) { return UnpredictableInstruction(); - if (!P && W) + } + + if (!P && W) { return UnpredictableInstruction(); + } + + const Reg t2 = t + 1; + if ((!P || W) && (n == Reg::PC || n == t || n == t2)) { + return UnpredictableInstruction(); + } + + if (t2 == Reg::PC) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = imm8a << 4 | imm8b; - const Reg t2 = t + 1; + const auto offset = ir.Imm32(imm32); + const auto address_a = GetAddress(ir, P, U, W, n, offset); + const auto address_b = ir.Add(address_a, ir.Imm32(4)); + const auto value_a = ir.GetRegister(t); + const auto value_b = ir.GetRegister(t2); - if ((!P || W) && (n == Reg::PC || n == t || n == t2)) - return UnpredictableInstruction(); - if (t2 == Reg::PC) - return UnpredictableInstruction(); - - // STRD , [, #+/-]{!} - // STRD , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto value_a = ir.GetRegister(t); - const auto value_b = ir.GetRegister(t2); - ir.WriteMemory32(address_a, value_a); - ir.WriteMemory32(address_b, value_b); - } + ir.WriteMemory32(address_a, value_a); + ir.WriteMemory32(address_b, value_b); return true; } +// STRD , [, #+/-]{!} +// STRD , [], #+/- bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { - if (size_t(t) % 2 != 0) + if (size_t(t) % 2 != 0) { return UnpredictableInstruction(); - if (!P && W) + } + + if (!P && W) { return UnpredictableInstruction(); + } const Reg t2 = t + 1; - - if (t2 == Reg::PC || m == Reg::PC) + if (t2 == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t || n == t2)) - return UnpredictableInstruction(); - - // STRD , [, #+/-]{!} - // STRD , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.GetRegister(m); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto value_a = ir.GetRegister(t); - const auto value_b = ir.GetRegister(t2); - ir.WriteMemory32(address_a, value_a); - ir.WriteMemory32(address_b, value_b); } + + if ((!P || W) && (n == Reg::PC || n == t || n == t2)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = ir.GetRegister(m); + const auto address_a = GetAddress(ir, P, U, W, n, offset); + const auto address_b = ir.Add(address_a, ir.Imm32(4)); + const auto value_a = ir.GetRegister(t); + const auto value_b = ir.GetRegister(t2); + + ir.WriteMemory32(address_a, value_a); + ir.WriteMemory32(address_b, value_b); return true; } +// STRH , [, #+/-]{!} +// STRH , [], #+/- bool ArmTranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { - if (t == Reg::PC) + if (t == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t)) + } + + if ((!P || W) && (n == Reg::PC || n == t)) { return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } const u32 imm32 = imm8a << 4 | imm8b; + const auto offset = ir.Imm32(imm32); + const auto address = GetAddress(ir, P, U, W, n, offset); - // STRH , [, #+/-]{!} - // STRH , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.Imm32(imm32); - const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); - } + ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); return true; } +// STRH , [, #+/-]{!} +// STRH , [], #+/- bool ArmTranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { - if (t == Reg::PC || m == Reg::PC) + if (t == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); - if ((!P || W) && (n == Reg::PC || n == t)) - return UnpredictableInstruction(); - - // STRH , [, #+/-]{!} - // STRH , [], #+/- - if (ConditionPassed(cond)) { - const auto offset = ir.GetRegister(m); - const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); } + + if ((!P || W) && (n == Reg::PC || n == t)) { + return UnpredictableInstruction(); + } + + if (!ConditionPassed(cond)) { + return true; + } + + const auto offset = ir.GetRegister(m); + const auto address = GetAddress(ir, P, U, W, n, offset); + + ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); return true; } @@ -629,52 +763,64 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s return true; } +// LDM {!}, bool ArmTranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // LDM {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.GetRegister(n); - auto writeback_address = ir.Add(start_address, ir.Imm32(u32(Common::BitCount(list) * 4))); - return LDMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.GetRegister(n); + const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(Common::BitCount(list) * 4))); + return LDMHelper(ir, W, n, list, start_address, writeback_address); } +// LDMDA {!}, bool ArmTranslatorVisitor::arm_LDMDA(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // LDMDA {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list) - 4))); - auto writeback_address = ir.Sub(start_address, ir.Imm32(4)); - return LDMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list) - 4))); + const auto writeback_address = ir.Sub(start_address, ir.Imm32(4)); + return LDMHelper(ir, W, n, list, start_address, writeback_address); } +// LDMDB {!}, bool ArmTranslatorVisitor::arm_LDMDB(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // LDMDB {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); - auto writeback_address = start_address; - return LDMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); + const auto writeback_address = start_address; + return LDMHelper(ir, W, n, list, start_address, writeback_address); } +// LDMIB {!}, bool ArmTranslatorVisitor::arm_LDMIB(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // LDMIB {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4)); - auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); - return LDMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4)); + const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); + return LDMHelper(ir, W, n, list, start_address, writeback_address); } bool ArmTranslatorVisitor::arm_LDM_usr() { @@ -702,52 +848,64 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s return true; } +// STM {!}, bool ArmTranslatorVisitor::arm_STM(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // STM {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.GetRegister(n); - auto writeback_address = ir.Add(start_address, ir.Imm32(u32(Common::BitCount(list) * 4))); - return STMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.GetRegister(n); + const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(Common::BitCount(list) * 4))); + return STMHelper(ir, W, n, list, start_address, writeback_address); } +// STMDA {!}, bool ArmTranslatorVisitor::arm_STMDA(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // STMDA {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list) - 4))); - auto writeback_address = ir.Sub(start_address, ir.Imm32(4)); - return STMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list) - 4))); + const auto writeback_address = ir.Sub(start_address, ir.Imm32(4)); + return STMHelper(ir, W, n, list, start_address, writeback_address); } +// STMDB {!}, bool ArmTranslatorVisitor::arm_STMDB(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // STMDB {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); - auto writeback_address = start_address; - return STMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); + const auto writeback_address = start_address; + return STMHelper(ir, W, n, list, start_address, writeback_address); } +// STMIB {!}, bool ArmTranslatorVisitor::arm_STMIB(Cond cond, bool W, Reg n, RegList list) { - if (n == Reg::PC || Common::BitCount(list) < 1) + if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); - // STMIB {!}, - if (ConditionPassed(cond)) { - auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4)); - auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); - return STMHelper(ir, W, n, list, start_address, writeback_address); } - return true; + + if (!ConditionPassed(cond)) { + return true; + } + + const auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4)); + const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * Common::BitCount(list)))); + return STMHelper(ir, W, n, list, start_address, writeback_address); } bool ArmTranslatorVisitor::arm_STM_usr() {