diff --git a/src/dynarmic/frontend/A32/a32_ir_emitter.cpp b/src/dynarmic/frontend/A32/a32_ir_emitter.cpp index 8363f81f..8d2b9db7 100644 --- a/src/dynarmic/frontend/A32/a32_ir_emitter.cpp +++ b/src/dynarmic/frontend/A32/a32_ir_emitter.cpp @@ -229,55 +229,55 @@ void IREmitter::ClearExclusive() { Inst(Opcode::A32ClearExclusive); } -IR::UAny IREmitter::ReadMemory(size_t bitsize, const IR::U32& vaddr) { +IR::UAny IREmitter::ReadMemory(size_t bitsize, const IR::U32& vaddr, IR::AccType acc_type) { switch (bitsize) { case 8: - return ReadMemory8(vaddr); + return ReadMemory8(vaddr, acc_type); case 16: - return ReadMemory16(vaddr); + return ReadMemory16(vaddr, acc_type); case 32: - return ReadMemory32(vaddr); + return ReadMemory32(vaddr, acc_type); case 64: - return ReadMemory64(vaddr); + return ReadMemory64(vaddr, acc_type); } ASSERT_FALSE("Invalid bitsize"); } -IR::U8 IREmitter::ReadMemory8(const IR::U32& vaddr) { - return Inst(Opcode::A32ReadMemory8, vaddr); +IR::U8 IREmitter::ReadMemory8(const IR::U32& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A32ReadMemory8, vaddr, IR::Value{acc_type}); } -IR::U16 IREmitter::ReadMemory16(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ReadMemory16, vaddr); +IR::U16 IREmitter::ReadMemory16(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ReadMemory16, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseHalf(value) : value; } -IR::U32 IREmitter::ReadMemory32(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ReadMemory32, vaddr); +IR::U32 IREmitter::ReadMemory32(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ReadMemory32, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseWord(value) : value; } -IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ReadMemory64, vaddr); +IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ReadMemory64, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseDual(value) : value; } -IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U32& vaddr) { - return Inst(Opcode::A32ExclusiveReadMemory8, vaddr); +IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U32& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A32ExclusiveReadMemory8, vaddr, IR::Value{acc_type}); } -IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ExclusiveReadMemory16, vaddr); +IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory16, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseHalf(value) : value; } -IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ExclusiveReadMemory32, vaddr); +IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory32, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseWord(value) : value; } -std::pair IREmitter::ExclusiveReadMemory64(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ExclusiveReadMemory64, vaddr); +std::pair IREmitter::ExclusiveReadMemory64(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory64, vaddr, IR::Value{acc_type}); const auto lo = LeastSignificantWord(value); const auto hi = MostSignificantWord(value).result; if (current_location.EFlag()) { @@ -287,80 +287,80 @@ std::pair IREmitter::ExclusiveReadMemory64(const IR::U32& vadd return std::make_pair(lo, hi); } -void IREmitter::WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value) { +void IREmitter::WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value, IR::AccType acc_type) { switch (bitsize) { case 8: - return WriteMemory8(vaddr, value); + return WriteMemory8(vaddr, value, acc_type); case 16: - return WriteMemory16(vaddr, value); + return WriteMemory16(vaddr, value, acc_type); case 32: - return WriteMemory32(vaddr, value); + return WriteMemory32(vaddr, value, acc_type); case 64: - return WriteMemory64(vaddr, value); + return WriteMemory64(vaddr, value, acc_type); } ASSERT_FALSE("Invalid bitsize"); } -void IREmitter::WriteMemory8(const IR::U32& vaddr, const IR::U8& value) { - Inst(Opcode::A32WriteMemory8, vaddr, value); +void IREmitter::WriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type) { + Inst(Opcode::A32WriteMemory8, vaddr, value, IR::Value{acc_type}); } -void IREmitter::WriteMemory16(const IR::U32& vaddr, const IR::U16& value) { +void IREmitter::WriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseHalf(value); - Inst(Opcode::A32WriteMemory16, vaddr, v); + Inst(Opcode::A32WriteMemory16, vaddr, v, IR::Value{acc_type}); } else { - Inst(Opcode::A32WriteMemory16, vaddr, value); + Inst(Opcode::A32WriteMemory16, vaddr, value, IR::Value{acc_type}); } } -void IREmitter::WriteMemory32(const IR::U32& vaddr, const IR::U32& value) { +void IREmitter::WriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseWord(value); - Inst(Opcode::A32WriteMemory32, vaddr, v); + Inst(Opcode::A32WriteMemory32, vaddr, v, IR::Value{acc_type}); } else { - Inst(Opcode::A32WriteMemory32, vaddr, value); + Inst(Opcode::A32WriteMemory32, vaddr, value, IR::Value{acc_type}); } } -void IREmitter::WriteMemory64(const IR::U32& vaddr, const IR::U64& value) { +void IREmitter::WriteMemory64(const IR::U32& vaddr, const IR::U64& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseDual(value); - Inst(Opcode::A32WriteMemory64, vaddr, v); + Inst(Opcode::A32WriteMemory64, vaddr, v, IR::Value{acc_type}); } else { - Inst(Opcode::A32WriteMemory64, vaddr, value); + Inst(Opcode::A32WriteMemory64, vaddr, value, IR::Value{acc_type}); } } -IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value) { - return Inst(Opcode::A32ExclusiveWriteMemory8, vaddr, value); +IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type) { + return Inst(Opcode::A32ExclusiveWriteMemory8, vaddr, value, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value) { +IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseHalf(value); - return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, v); + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, v, IR::Value{acc_type}); } else { - return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, value); + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, value, IR::Value{acc_type}); } } -IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value) { +IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseWord(value); - return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, v); + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, v, IR::Value{acc_type}); } else { - return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, value); + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, value, IR::Value{acc_type}); } } -IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi) { +IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi, IR::AccType acc_type) { if (current_location.EFlag()) { const auto vlo = ByteReverseWord(value_lo); const auto vhi = ByteReverseWord(value_hi); - return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(vlo, vhi)); + return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(vlo, vhi), IR::Value{acc_type}); } else { - return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(value_lo, value_hi)); + return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(value_lo, value_hi), IR::Value{acc_type}); } } diff --git a/src/dynarmic/frontend/A32/a32_ir_emitter.h b/src/dynarmic/frontend/A32/a32_ir_emitter.h index 7b6b1b03..0f36958a 100644 --- a/src/dynarmic/frontend/A32/a32_ir_emitter.h +++ b/src/dynarmic/frontend/A32/a32_ir_emitter.h @@ -80,24 +80,24 @@ public: void SetFpscrNZCV(const IR::NZCV& new_fpscr_nzcv); void ClearExclusive(); - IR::UAny ReadMemory(size_t bitsize, const IR::U32& vaddr); - IR::U8 ReadMemory8(const IR::U32& vaddr); - IR::U16 ReadMemory16(const IR::U32& vaddr); - IR::U32 ReadMemory32(const IR::U32& vaddr); - IR::U64 ReadMemory64(const IR::U32& vaddr); - IR::U8 ExclusiveReadMemory8(const IR::U32& vaddr); - IR::U16 ExclusiveReadMemory16(const IR::U32& vaddr); - IR::U32 ExclusiveReadMemory32(const IR::U32& vaddr); - std::pair ExclusiveReadMemory64(const IR::U32& vaddr); - void WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value); - void WriteMemory8(const IR::U32& vaddr, const IR::U8& value); - void WriteMemory16(const IR::U32& vaddr, const IR::U16& value); - void WriteMemory32(const IR::U32& vaddr, const IR::U32& value); - void WriteMemory64(const IR::U32& vaddr, const IR::U64& value); - IR::U32 ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value); - IR::U32 ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value); - IR::U32 ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value); - IR::U32 ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi); + IR::UAny ReadMemory(size_t bitsize, const IR::U32& vaddr, IR::AccType acc_type); + IR::U8 ReadMemory8(const IR::U32& vaddr, IR::AccType acc_type); + IR::U16 ReadMemory16(const IR::U32& vaddr, IR::AccType acc_type); + IR::U32 ReadMemory32(const IR::U32& vaddr, IR::AccType acc_type); + IR::U64 ReadMemory64(const IR::U32& vaddr, IR::AccType acc_type); + IR::U8 ExclusiveReadMemory8(const IR::U32& vaddr, IR::AccType acc_type); + IR::U16 ExclusiveReadMemory16(const IR::U32& vaddr, IR::AccType acc_type); + IR::U32 ExclusiveReadMemory32(const IR::U32& vaddr, IR::AccType acc_type); + std::pair ExclusiveReadMemory64(const IR::U32& vaddr, IR::AccType acc_type); + void WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value, IR::AccType acc_type); + void WriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type); + void WriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type); + void WriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type); + void WriteMemory64(const IR::U32& vaddr, const IR::U64& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi, IR::AccType acc_type); void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, size_t opc2); void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2, const IR::U32& word); diff --git a/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp b/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp index ec56443d..4afd0b1f 100644 --- a/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp @@ -103,7 +103,7 @@ bool TranslatorVisitor::v8_VST_multiple(bool D, Reg n, size_t Vd, Imm<4> type, s const ExtReg ext_reg = d + i * inc + r; const IR::U64 shifted_element = ir.LogicalShiftRight(ir.GetExtendedRegister(ext_reg), ir.Imm8(static_cast(e * ebytes * 8))); const IR::UAny element = ir.LeastSignificant(8 * ebytes, shifted_element); - ir.WriteMemory(8 * ebytes, address, element); + ir.WriteMemory(8 * ebytes, address, element, IR::AccType::NORMAL); address = ir.Add(address, ir.Imm32(static_cast(ebytes))); } @@ -156,7 +156,7 @@ bool TranslatorVisitor::v8_VLD_multiple(bool D, Reg n, size_t Vd, Imm<4> type, s for (size_t r = 0; r < regs; r++) { for (size_t e = 0; e < elements; e++) { for (size_t i = 0; i < nelem; i++) { - const IR::U64 element = ir.ZeroExtendToLong(ir.ReadMemory(ebytes * 8, address)); + const IR::U64 element = ir.ZeroExtendToLong(ir.ReadMemory(ebytes * 8, address, IR::AccType::NORMAL)); const IR::U64 shifted_element = ir.LogicalShiftLeft(element, ir.Imm8(static_cast(e * ebytes * 8))); const ExtReg ext_reg = d + i * inc + r; @@ -221,7 +221,7 @@ bool TranslatorVisitor::v8_VLD_all_lanes(bool D, Reg n, size_t Vd, size_t nn, si auto address = ir.GetRegister(n); for (size_t i = 0; i < nelem; i++) { - const auto element = ir.ReadMemory(ebytes * 8, address); + const auto element = ir.ReadMemory(ebytes * 8, address, IR::AccType::NORMAL); const auto replicated_element = ir.VectorBroadcast(ebytes * 8, element); for (size_t r = 0; r < regs; r++) { @@ -291,7 +291,7 @@ bool TranslatorVisitor::v8_VST_single(bool D, Reg n, size_t Vd, size_t sz, size_ const ExtReg ext_reg = d + i * inc; const auto element = ir.VectorGetElement(ebytes * 8, ir.GetVector(ext_reg), index); - ir.WriteMemory(ebytes * 8, address, element); + ir.WriteMemory(ebytes * 8, address, element, IR::AccType::NORMAL); address = ir.Add(address, ir.Imm32(static_cast(ebytes))); } @@ -352,7 +352,7 @@ bool TranslatorVisitor::v8_VLD_single(bool D, Reg n, size_t Vd, size_t sz, size_ auto address = ir.GetRegister(n); for (size_t i = 0; i < nelem; i++) { - const auto element = ir.ReadMemory(ebytes * 8, address); + const auto element = ir.ReadMemory(ebytes * 8, address, IR::AccType::NORMAL); const ExtReg ext_reg = d + i * inc; const auto new_reg = ir.VectorSetElement(ebytes * 8, ir.GetVector(ext_reg), index, element); diff --git a/src/dynarmic/frontend/A32/translate/impl/load_store.cpp b/src/dynarmic/frontend/A32/translate/impl/load_store.cpp index b511e441..77df6a4d 100644 --- a/src/dynarmic/frontend/A32/translate/impl/load_store.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/load_store.cpp @@ -71,7 +71,7 @@ bool TranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12) { const bool add = U; const u32 base = ir.AlignPC(4); const u32 address = add ? (base + imm12.ZeroExtend()) : (base - imm12.ZeroExtend()); - const auto data = ir.ReadMemory32(ir.Imm32(address)); + const auto data = ir.ReadMemory32(ir.Imm32(address), IR::AccType::NORMAL); if (t == Reg::PC) { ir.LoadWritePC(data); @@ -102,7 +102,7 @@ bool TranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Re const u32 imm32 = imm12.ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.LoadWritePC(data); @@ -138,7 +138,7 @@ bool TranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Re 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); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.LoadWritePC(data); @@ -164,7 +164,7 @@ bool TranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> 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))); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -193,7 +193,7 @@ bool TranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = imm12.ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -217,7 +217,7 @@ bool TranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, R 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)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -243,11 +243,17 @@ bool TranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm 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); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = ir.ReadMemory64(ir.Imm32(address), IR::AccType::ATOMIC); + + if (ir.current_location.EFlag()) { + ir.SetRegister(t, ir.MostSignificantWord(data).result); + ir.SetRegister(t2, ir.LeastSignificantWord(data)); + } else { + ir.SetRegister(t, ir.LeastSignificantWord(data)); + ir.SetRegister(t2, ir.MostSignificantWord(data).result); + } return true; } @@ -282,13 +288,18 @@ bool TranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); 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 address = GetAddress(ir, P, U, W, n, offset); - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (ir.current_location.EFlag()) { + ir.SetRegister(t, ir.MostSignificantWord(data).result); + ir.SetRegister(t2, ir.LeastSignificantWord(data)); + } else { + ir.SetRegister(t, ir.LeastSignificantWord(data)); + ir.SetRegister(t2, ir.MostSignificantWord(data).result); + } return true; } @@ -317,13 +328,18 @@ bool TranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, R 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); + const auto address = GetAddress(ir, P, U, W, n, offset); - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (ir.current_location.EFlag()) { + ir.SetRegister(t, ir.MostSignificantWord(data).result); + ir.SetRegister(t2, ir.LeastSignificantWord(data)); + } else { + ir.SetRegister(t, ir.LeastSignificantWord(data)); + ir.SetRegister(t2, ir.MostSignificantWord(data).result); + } return true; } @@ -346,7 +362,7 @@ bool TranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, I 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))); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -375,7 +391,7 @@ bool TranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -399,7 +415,7 @@ bool TranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = ir.GetRegister(m); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -420,7 +436,7 @@ bool TranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Im 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 auto data = ir.SignExtendByteToWord(ir.ReadMemory8(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -449,7 +465,7 @@ bool TranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -473,7 +489,7 @@ bool TranslatorVisitor::arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, const auto offset = ir.GetRegister(m); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -493,7 +509,7 @@ bool TranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Im 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))); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -522,7 +538,7 @@ bool TranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -546,7 +562,7 @@ bool TranslatorVisitor::arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, const auto offset = ir.GetRegister(m); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -565,7 +581,7 @@ bool TranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Re const auto offset = ir.Imm32(imm12.ZeroExtend()); const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory32(address, ir.GetRegister(t)); + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::NORMAL); return true; } @@ -586,7 +602,7 @@ bool TranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Re 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)); + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::NORMAL); return true; } @@ -607,7 +623,7 @@ bool TranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = ir.Imm32(imm12.ZeroExtend()); const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)), IR::AccType::NORMAL); return true; } @@ -628,7 +644,7 @@ bool TranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, R 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))); + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)), IR::AccType::NORMAL); return true; } @@ -658,13 +674,15 @@ bool TranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); 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 address = GetAddress(ir, P, U, W, n, offset); 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); + const IR::U64 data = ir.current_location.EFlag() ? ir.Pack2x32To1x64(value_b, value_a) + : ir.Pack2x32To1x64(value_a, value_b); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + ir.WriteMemory64(address, data, IR::AccType::ATOMIC); return true; } @@ -693,13 +711,15 @@ bool TranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, R } 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 address = GetAddress(ir, P, U, W, n, offset); 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); + const IR::U64 data = ir.current_location.EFlag() ? ir.Pack2x32To1x64(value_b, value_a) + : ir.Pack2x32To1x64(value_a, value_b); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + ir.WriteMemory64(address, data, IR::AccType::ATOMIC); return true; } @@ -722,7 +742,7 @@ bool TranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, R 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)), IR::AccType::NORMAL); return true; } @@ -744,7 +764,7 @@ bool TranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = ir.GetRegister(m); 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)), IR::AccType::NORMAL); return true; } @@ -752,7 +772,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.SetRegister(static_cast(i), ir.ReadMemory32(address)); + ir.SetRegister(static_cast(i), ir.ReadMemory32(address, IR::AccType::ATOMIC)); address = ir.Add(address, ir.Imm32(4)); } } @@ -760,7 +780,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s ir.SetRegister(n, writeback_address); } if (Common::Bit<15>(list)) { - ir.LoadWritePC(ir.ReadMemory32(address)); + ir.LoadWritePC(ir.ReadMemory32(address, IR::AccType::ATOMIC)); if (n == Reg::R13) ir.SetTerm(IR::Term::PopRSBHint{}); else @@ -854,7 +874,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.WriteMemory32(address, ir.GetRegister(static_cast(i))); + ir.WriteMemory32(address, ir.GetRegister(static_cast(i)), IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -862,7 +882,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s ir.SetRegister(n, writeback_address); } if (Common::Bit<15>(list)) { - ir.WriteMemory32(address, ir.Imm32(ir.PC())); + ir.WriteMemory32(address, ir.Imm32(ir.PC()), IR::AccType::ATOMIC); } return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp b/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp index 653732b4..e9f04b70 100644 --- a/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp @@ -24,8 +24,9 @@ bool TranslatorVisitor::arm_SWP(Cond cond, Reg n, Reg t, Reg t2) { return true; } - const auto data = ir.ReadMemory32(ir.GetRegister(n)); - ir.WriteMemory32(ir.GetRegister(n), ir.GetRegister(t2)); + // TODO (HACK): Implement bus locking here + const auto data = ir.ReadMemory32(ir.GetRegister(n), IR::AccType::SWAP); + ir.WriteMemory32(ir.GetRegister(n), ir.GetRegister(t2), IR::AccType::SWAP); // TODO: Alignment check ir.SetRegister(t, data); return true; @@ -42,8 +43,9 @@ bool TranslatorVisitor::arm_SWPB(Cond cond, Reg n, Reg t, Reg t2) { return true; } - const auto data = ir.ReadMemory8(ir.GetRegister(n)); - ir.WriteMemory8(ir.GetRegister(n), ir.LeastSignificantByte(ir.GetRegister(t2))); + // TODO (HACK): Implement bus locking here + const auto data = ir.ReadMemory8(ir.GetRegister(n), IR::AccType::SWAP); + ir.WriteMemory8(ir.GetRegister(n), ir.LeastSignificantByte(ir.GetRegister(t2)), IR::AccType::SWAP); // TODO: Alignment check ir.SetRegister(t, ir.ZeroExtendByteToWord(data)); return true; @@ -60,7 +62,7 @@ bool TranslatorVisitor::arm_LDA(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ReadMemory32(address)); // AccType::Ordered + ir.SetRegister(t, ir.ReadMemory32(address, IR::AccType::ORDERED)); return true; } // LDAB , [] @@ -74,7 +76,7 @@ bool TranslatorVisitor::arm_LDAB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory8(address))); // AccType::Ordered + ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory8(address, IR::AccType::ORDERED))); return true; } // LDAH , [] @@ -88,7 +90,7 @@ bool TranslatorVisitor::arm_LDAH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory16(address))); // AccType::Ordered + ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory16(address, IR::AccType::ORDERED))); return true; } @@ -103,7 +105,7 @@ bool TranslatorVisitor::arm_LDAEX(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ExclusiveReadMemory32(address)); // AccType::Ordered + ir.SetRegister(t, ir.ExclusiveReadMemory32(address, IR::AccType::ORDERED)); return true; } @@ -118,7 +120,7 @@ bool TranslatorVisitor::arm_LDAEXB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address))); // AccType::Ordered + ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address, IR::AccType::ORDERED))); return true; } @@ -133,7 +135,7 @@ bool TranslatorVisitor::arm_LDAEXD(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto [lo, hi] = ir.ExclusiveReadMemory64(address); // AccType::Ordered + const auto [lo, hi] = ir.ExclusiveReadMemory64(address, IR::AccType::ORDERED); // DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR ir.SetRegister(t, lo); ir.SetRegister(t + 1, hi); @@ -151,7 +153,7 @@ bool TranslatorVisitor::arm_LDAEXH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address))); // AccType::Ordered + ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address, IR::AccType::ORDERED))); return true; } @@ -166,7 +168,7 @@ bool TranslatorVisitor::arm_STL(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory32(address, ir.GetRegister(t)); // AccType::Ordered + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::ORDERED); return true; } @@ -181,7 +183,7 @@ bool TranslatorVisitor::arm_STLB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); // AccType::Ordered + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)), IR::AccType::ORDERED); return true; } @@ -196,7 +198,7 @@ bool TranslatorVisitor::arm_STLH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); // AccType::Ordered + ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t)), IR::AccType::ORDERED); return true; } @@ -216,7 +218,7 @@ bool TranslatorVisitor::arm_STLEXB(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantByte(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory8(address, value); // AccType::Ordered + const auto passed = ir.ExclusiveWriteMemory8(address, value, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -238,7 +240,7 @@ bool TranslatorVisitor::arm_STLEXD(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value_lo = ir.GetRegister(t); const auto value_hi = ir.GetRegister(t2); - const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi); // AccType::Ordered + const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -259,7 +261,7 @@ bool TranslatorVisitor::arm_STLEXH(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantHalf(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory16(address, value); // AccType::Ordered + const auto passed = ir.ExclusiveWriteMemory16(address, value, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -280,7 +282,7 @@ bool TranslatorVisitor::arm_STLEX(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.GetRegister(t); - const auto passed = ir.ExclusiveWriteMemory32(address, value); + const auto passed = ir.ExclusiveWriteMemory32(address, value, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -296,7 +298,7 @@ bool TranslatorVisitor::arm_LDREX(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ExclusiveReadMemory32(address)); + ir.SetRegister(t, ir.ExclusiveReadMemory32(address, IR::AccType::ATOMIC)); return true; } @@ -311,7 +313,7 @@ bool TranslatorVisitor::arm_LDREXB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address))); + ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address, IR::AccType::ATOMIC))); return true; } @@ -326,7 +328,7 @@ bool TranslatorVisitor::arm_LDREXD(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto [lo, hi] = ir.ExclusiveReadMemory64(address); + const auto [lo, hi] = ir.ExclusiveReadMemory64(address, IR::AccType::ATOMIC); // DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR ir.SetRegister(t, lo); ir.SetRegister(t + 1, hi); @@ -344,7 +346,7 @@ bool TranslatorVisitor::arm_LDREXH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address))); + ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address, IR::AccType::ATOMIC))); return true; } @@ -364,7 +366,7 @@ bool TranslatorVisitor::arm_STREX(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.GetRegister(t); - const auto passed = ir.ExclusiveWriteMemory32(address, value); + const auto passed = ir.ExclusiveWriteMemory32(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -385,7 +387,7 @@ bool TranslatorVisitor::arm_STREXB(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantByte(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory8(address, value); + const auto passed = ir.ExclusiveWriteMemory8(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -408,7 +410,7 @@ bool TranslatorVisitor::arm_STREXD(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value_lo = ir.GetRegister(t); const auto value_hi = ir.GetRegister(t2); - const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi); + const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -429,7 +431,7 @@ bool TranslatorVisitor::arm_STREXH(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantHalf(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory16(address, value); + const auto passed = ir.ExclusiveWriteMemory16(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp index d5797115..dbaf5f08 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp @@ -444,7 +444,7 @@ bool TranslatorVisitor::thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) { bool TranslatorVisitor::thumb16_LDR_literal(Reg t, Imm<8> imm8) { const u32 imm32 = imm8.ZeroExtend() << 2; const u32 address = ir.AlignPC(4) + imm32; - const auto data = ir.ReadMemory32(ir.Imm32(address)); + const auto data = ir.ReadMemory32(ir.Imm32(address), IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -456,7 +456,7 @@ bool TranslatorVisitor::thumb16_STR_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); const auto data = ir.GetRegister(t); - ir.WriteMemory32(address, data); + ir.WriteMemory32(address, data, IR::AccType::NORMAL); return true; } @@ -466,7 +466,7 @@ bool TranslatorVisitor::thumb16_STRH_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); const auto data = ir.LeastSignificantHalf(ir.GetRegister(t)); - ir.WriteMemory16(address, data); + ir.WriteMemory16(address, data, IR::AccType::NORMAL); return true; } @@ -476,7 +476,7 @@ bool TranslatorVisitor::thumb16_STRB_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); const auto data = ir.LeastSignificantByte(ir.GetRegister(t)); - ir.WriteMemory8(address, data); + ir.WriteMemory8(address, data, IR::AccType::NORMAL); return true; } @@ -484,7 +484,7 @@ bool TranslatorVisitor::thumb16_STRB_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRSB_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -494,7 +494,7 @@ bool TranslatorVisitor::thumb16_LDRSB_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDR_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -504,7 +504,7 @@ bool TranslatorVisitor::thumb16_LDR_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRH_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -514,7 +514,7 @@ bool TranslatorVisitor::thumb16_LDRH_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRB_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -524,7 +524,7 @@ bool TranslatorVisitor::thumb16_LDRB_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRSH_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -537,7 +537,7 @@ bool TranslatorVisitor::thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.GetRegister(t); - ir.WriteMemory32(address, data); + ir.WriteMemory32(address, data, IR::AccType::NORMAL); return true; } @@ -546,7 +546,7 @@ bool TranslatorVisitor::thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) { bool TranslatorVisitor::thumb16_LDR_imm_t1(Imm<5> imm5, Reg n, Reg t) { const u32 imm32 = imm5.ZeroExtend() << 2; const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -559,7 +559,7 @@ bool TranslatorVisitor::thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.LeastSignificantByte(ir.GetRegister(t)); - ir.WriteMemory8(address, data); + ir.WriteMemory8(address, data, IR::AccType::NORMAL); return true; } @@ -568,7 +568,7 @@ bool TranslatorVisitor::thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) { bool TranslatorVisitor::thumb16_LDRB_imm(Imm<5> imm5, Reg n, Reg t) { const u32 imm32 = imm5.ZeroExtend(); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -580,7 +580,7 @@ bool TranslatorVisitor::thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.LeastSignificantHalf(ir.GetRegister(t)); - ir.WriteMemory16(address, data); + ir.WriteMemory16(address, data, IR::AccType::NORMAL); return true; } @@ -588,7 +588,7 @@ bool TranslatorVisitor::thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) { bool TranslatorVisitor::thumb16_LDRH_imm(Imm<5> imm5, Reg n, Reg t) { const u32 imm32 = imm5.ZeroExtend() << 1; const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -602,7 +602,7 @@ bool TranslatorVisitor::thumb16_STR_imm_t2(Reg t, Imm<8> imm8) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.GetRegister(t); - ir.WriteMemory32(address, data); + ir.WriteMemory32(address, data, IR::AccType::NORMAL); return true; } @@ -612,7 +612,7 @@ bool TranslatorVisitor::thumb16_LDR_imm_t2(Reg t, Imm<8> imm8) { const u32 imm32 = imm8.ZeroExtend() << 2; const Reg n = Reg::SP; const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -766,7 +766,7 @@ bool TranslatorVisitor::thumb16_PUSH(bool M, RegList reg_list) { if (Common::Bit(i, reg_list)) { // TODO: Deal with alignment const auto Ri = ir.GetRegister(static_cast(i)); - ir.WriteMemory32(address, Ri); + ir.WriteMemory32(address, Ri, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -789,7 +789,7 @@ bool TranslatorVisitor::thumb16_POP(bool P, RegList reg_list) { for (size_t i = 0; i < 15; i++) { if (Common::Bit(i, reg_list)) { // TODO: Deal with alignment - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.SetRegister(static_cast(i), data); address = ir.Add(address, ir.Imm32(4)); } @@ -797,7 +797,7 @@ bool TranslatorVisitor::thumb16_POP(bool P, RegList reg_list) { if (Common::Bit<15>(reg_list)) { // TODO(optimization): Possible location for an RSB pop. - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.UpdateUpperLocationDescriptor(); ir.LoadWritePC(data); address = ir.Add(address, ir.Imm32(4)); @@ -879,7 +879,7 @@ bool TranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) { for (size_t i = 0; i < 8; i++) { if (Common::Bit(i, reg_list)) { const auto Ri = ir.GetRegister(static_cast(i)); - ir.WriteMemory32(address, Ri); + ir.WriteMemory32(address, Ri, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -899,7 +899,7 @@ bool TranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) { for (size_t i = 0; i < 8; i++) { if (Common::Bit(i, reg_list)) { - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.SetRegister(static_cast(i), data); address = ir.Add(address, ir.Imm32(4)); } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp index 3f00efa8..42b2ebf4 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp @@ -31,7 +31,7 @@ static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, const u32 imm32 = imm12.ZeroExtend(); const u32 base = v.ir.AlignPC(4); const u32 address = U ? (base + imm32) : (base - imm32); - const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(v.ir.Imm32(address))); + const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(v.ir.Imm32(address), IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -46,7 +46,7 @@ static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re const auto reg_m = v.ir.GetRegister(m); const auto offset = v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(imm2.ZeroExtend())); const auto address = v.ir.Add(reg_n, offset); - const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address)); + const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address, IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -58,7 +58,7 @@ static bool LoadByteImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32)) : v.ir.Sub(reg_n, v.ir.Imm32(imm32)); const IR::U32 address = P ? offset_address : reg_n; - const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address)); + const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address, IR::AccType::NORMAL)); v.ir.SetRegister(t, data); if (W) { diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp index f1bba517..5b9f1639 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp @@ -13,7 +13,7 @@ static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, const auto imm32 = imm12.ZeroExtend(); const auto base = v.ir.AlignPC(4); const auto address = U ? (base + imm32) : (base - imm32); - const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory16(v.ir.Imm32(address))); + const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory16(v.ir.Imm32(address), IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -28,7 +28,7 @@ static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re const IR::U32 reg_n = v.ir.GetRegister(n); const IR::U32 offset = v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(imm2.ZeroExtend())); const IR::U32 address = v.ir.Add(reg_n, offset); - const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address)); + const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address, IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -41,7 +41,7 @@ static bool LoadHalfImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U : v.ir.Sub(reg_n, v.ir.Imm32(imm32)); const IR::U32 address = P ? offset_address : reg_n; - const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address)); + const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address, IR::AccType::NORMAL)); if (W) { v.ir.SetRegister(n, offset_address); diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp index af539b25..374cc906 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp @@ -24,10 +24,10 @@ static bool TableBranch(TranslatorVisitor& v, Reg n, Reg m, bool half) { IR::U32 halfwords; if (half) { - const auto data = v.ir.ReadMemory16(v.ir.Add(reg_n, v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(1)))); + const auto data = v.ir.ReadMemory16(v.ir.Add(reg_n, v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(1))), IR::AccType::NORMAL); halfwords = v.ir.ZeroExtendToWord(data); } else { - halfwords = v.ir.ZeroExtendToWord(v.ir.ReadMemory8(v.ir.Add(reg_n, reg_m))); + halfwords = v.ir.ZeroExtendToWord(v.ir.ReadMemory8(v.ir.Add(reg_n, reg_m), IR::AccType::NORMAL)); } const auto current_pc = v.ir.Imm32(v.ir.PC()); @@ -51,12 +51,18 @@ static bool LoadDualImmediate(TranslatorVisitor& v, bool P, bool U, bool W, Reg const IR::U32 reg_n = v.ir.GetRegister(n); const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm)) : v.ir.Sub(reg_n, v.ir.Imm32(imm)); - const IR::U32 address_1 = P ? offset_address - : reg_n; - const IR::U32 address_2 = v.ir.Add(address_1, v.ir.Imm32(4)); + const IR::U32 address = P ? offset_address : reg_n; - v.ir.SetRegister(t, v.ir.ReadMemory32(address_1)); - v.ir.SetRegister(t2, v.ir.ReadMemory32(address_2)); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = v.ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (v.ir.current_location.EFlag()) { + v.ir.SetRegister(t, v.ir.MostSignificantWord(data).result); + v.ir.SetRegister(t2, v.ir.LeastSignificantWord(data)); + } else { + v.ir.SetRegister(t, v.ir.LeastSignificantWord(data)); + v.ir.SetRegister(t2, v.ir.MostSignificantWord(data).result); + } if (W) { v.ir.SetRegister(n, offset_address); @@ -73,12 +79,20 @@ static bool LoadDualLiteral(TranslatorVisitor& v, bool U, bool W, Reg t, Reg t2, } const auto imm = imm8.ZeroExtend() << 2; - const auto address_1 = U ? v.ir.Add(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)) - : v.ir.Sub(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)); - const auto address_2 = v.ir.Add(address_1, v.ir.Imm32(4)); + const auto address = U ? v.ir.Add(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)) + : v.ir.Sub(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = v.ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (v.ir.current_location.EFlag()) { + v.ir.SetRegister(t, v.ir.MostSignificantWord(data).result); + v.ir.SetRegister(t2, v.ir.LeastSignificantWord(data)); + } else { + v.ir.SetRegister(t, v.ir.LeastSignificantWord(data)); + v.ir.SetRegister(t2, v.ir.MostSignificantWord(data).result); + } - v.ir.SetRegister(t, v.ir.ReadMemory32(address_1)); - v.ir.SetRegister(t2, v.ir.ReadMemory32(address_2)); return true; } @@ -97,12 +111,13 @@ static bool StoreDual(TranslatorVisitor& v, bool P, bool U, bool W, Reg n, Reg t const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm)) : v.ir.Sub(reg_n, v.ir.Imm32(imm)); - const IR::U32 address_1 = P ? offset_address - : reg_n; - const IR::U32 address_2 = v.ir.Add(address_1, v.ir.Imm32(4)); + const IR::U32 address = P ? offset_address : reg_n; - v.ir.WriteMemory32(address_1, reg_t); - v.ir.WriteMemory32(address_2, reg_t2); + const IR::U64 data = v.ir.current_location.EFlag() ? v.ir.Pack2x32To1x64(reg_t2, reg_t) + : v.ir.Pack2x32To1x64(reg_t, reg_t2); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + v.ir.WriteMemory64(address, data, IR::AccType::ATOMIC); if (W) { v.ir.SetRegister(n, offset_address); @@ -116,7 +131,7 @@ bool TranslatorVisitor::thumb32_LDA(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ReadMemory32(address)); // AccType::Ordered + ir.SetRegister(t, ir.ReadMemory32(address, IR::AccType::ORDERED)); return true; } @@ -150,7 +165,7 @@ bool TranslatorVisitor::thumb32_LDREX(Reg n, Reg t, Imm<8> imm8) { } const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm8.ZeroExtend() << 2)); - const auto value = ir.ExclusiveReadMemory32(address); + const auto value = ir.ExclusiveReadMemory32(address, IR::AccType::ATOMIC); ir.SetRegister(t, value); return true; @@ -162,7 +177,7 @@ bool TranslatorVisitor::thumb32_LDREXB(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory8(address)); + const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory8(address, IR::AccType::ATOMIC)); ir.SetRegister(t, value); return true; @@ -174,7 +189,7 @@ bool TranslatorVisitor::thumb32_LDREXD(Reg n, Reg t, Reg t2) { } const auto address = ir.GetRegister(n); - const auto [lo, hi] = ir.ExclusiveReadMemory64(address); + const auto [lo, hi] = ir.ExclusiveReadMemory64(address, IR::AccType::ATOMIC); // DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR ir.SetRegister(t, lo); @@ -188,7 +203,7 @@ bool TranslatorVisitor::thumb32_LDREXH(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory16(address)); + const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory16(address, IR::AccType::ATOMIC)); ir.SetRegister(t, value); return true; @@ -200,7 +215,7 @@ bool TranslatorVisitor::thumb32_STL(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory32(address, ir.GetRegister(t)); // AccType::Ordered + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::ORDERED); return true; } @@ -214,7 +229,7 @@ bool TranslatorVisitor::thumb32_STREX(Reg n, Reg t, Reg d, Imm<8> imm8) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm8.ZeroExtend() << 2)); const auto value = ir.GetRegister(t); - const auto passed = ir.ExclusiveWriteMemory32(address, value); + const auto passed = ir.ExclusiveWriteMemory32(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -229,7 +244,7 @@ bool TranslatorVisitor::thumb32_STREXB(Reg n, Reg t, Reg d) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantByte(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory8(address, value); + const auto passed = ir.ExclusiveWriteMemory8(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -245,7 +260,7 @@ bool TranslatorVisitor::thumb32_STREXD(Reg n, Reg t, Reg t2, Reg d) { const auto address = ir.GetRegister(n); const auto value_lo = ir.GetRegister(t); const auto value_hi = ir.GetRegister(t2); - const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi); + const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -260,7 +275,7 @@ bool TranslatorVisitor::thumb32_STREXH(Reg n, Reg t, Reg d) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantHalf(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory16(address, value); + const auto passed = ir.ExclusiveWriteMemory16(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp index da6e6e65..c4ff0766 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp @@ -15,7 +15,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32 auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.SetRegister(static_cast(i), ir.ReadMemory32(address)); + ir.SetRegister(static_cast(i), ir.ReadMemory32(address, IR::AccType::ATOMIC)); address = ir.Add(address, ir.Imm32(4)); } } @@ -24,7 +24,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32 } if (Common::Bit<15>(list)) { ir.UpdateUpperLocationDescriptor(); - ir.LoadWritePC(ir.ReadMemory32(address)); + ir.LoadWritePC(ir.ReadMemory32(address, IR::AccType::ATOMIC)); if (n == Reg::R13) { ir.SetTerm(IR::Term::PopRSBHint{}); } else { @@ -39,7 +39,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32 auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.WriteMemory32(address, ir.GetRegister(static_cast(i))); + ir.WriteMemory32(address, ir.GetRegister(static_cast(i)), IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp index caa370ad..b92e27fc 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp @@ -18,7 +18,7 @@ bool TranslatorVisitor::thumb32_LDR_lit(bool U, Reg t, Imm<12> imm12) { const u32 imm32 = imm12.ZeroExtend(); const u32 base = ir.AlignPC(4); const u32 address = U ? base + imm32 : base - imm32; - const auto data = ir.ReadMemory32(ir.Imm32(address)); + const auto data = ir.ReadMemory32(ir.Imm32(address), IR::AccType::NORMAL); if (t == Reg::PC) { ir.UpdateUpperLocationDescriptor(); @@ -48,7 +48,7 @@ bool TranslatorVisitor::thumb32_LDR_imm8(Reg n, Reg t, bool P, bool U, bool W, I : ir.Sub(reg_n, ir.Imm32(imm32)); const IR::U32 address = P ? offset_address : reg_n; - const IR::U32 data = ir.ReadMemory32(address); + const IR::U32 data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (W) { ir.SetRegister(n, offset_address); @@ -79,7 +79,7 @@ bool TranslatorVisitor::thumb32_LDR_imm12(Reg n, Reg t, Imm<12> imm12) { const auto imm32 = imm12.ZeroExtend(); const auto reg_n = ir.GetRegister(n); const auto address = ir.Add(reg_n, ir.Imm32(imm32)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.UpdateUpperLocationDescriptor(); @@ -104,7 +104,7 @@ bool TranslatorVisitor::thumb32_LDR_reg(Reg n, Reg t, Imm<2> imm2, Reg m) { const auto reg_n = ir.GetRegister(n); const auto offset = ir.LogicalShiftLeft(reg_m, ir.Imm8(imm2.ZeroExtend())); const auto address = ir.Add(reg_n, offset); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.UpdateUpperLocationDescriptor(); diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp index 9a977423..93c38375 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp @@ -32,15 +32,15 @@ static bool StoreRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m using StoreImmFn = void (*)(TranslatorVisitor&, const IR::U32&, const IR::U32&); static void StoreImmByteFn(TranslatorVisitor& v, const IR::U32& address, const IR::U32& data) { - v.ir.WriteMemory8(address, v.ir.LeastSignificantByte(data)); + v.ir.WriteMemory8(address, v.ir.LeastSignificantByte(data), IR::AccType::NORMAL); } static void StoreImmHalfFn(TranslatorVisitor& v, const IR::U32& address, const IR::U32& data) { - v.ir.WriteMemory16(address, v.ir.LeastSignificantHalf(data)); + v.ir.WriteMemory16(address, v.ir.LeastSignificantHalf(data), IR::AccType::NORMAL); } static void StoreImmWordFn(TranslatorVisitor& v, const IR::U32& address, const IR::U32& data) { - v.ir.WriteMemory32(address, data); + v.ir.WriteMemory32(address, data, IR::AccType::NORMAL); } static bool StoreImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, StoreImmFn store_fn) { @@ -110,7 +110,7 @@ bool TranslatorVisitor::thumb32_STRBT(Reg n, Reg t, Imm<8> imm8) { bool TranslatorVisitor::thumb32_STRB(Reg n, Reg t, Imm<2> imm2, Reg m) { return StoreRegister(*this, n, t, imm2, m, [this](const IR::U32& offset_address, const IR::U32& data) { - ir.WriteMemory8(offset_address, ir.LeastSignificantByte(data)); + ir.WriteMemory8(offset_address, ir.LeastSignificantByte(data), IR::AccType::NORMAL); }); } @@ -163,7 +163,7 @@ bool TranslatorVisitor::thumb32_STRHT(Reg n, Reg t, Imm<8> imm8) { bool TranslatorVisitor::thumb32_STRH(Reg n, Reg t, Imm<2> imm2, Reg m) { return StoreRegister(*this, n, t, imm2, m, [this](const IR::U32& offset_address, const IR::U32& data) { - ir.WriteMemory16(offset_address, ir.LeastSignificantHalf(data)); + ir.WriteMemory16(offset_address, ir.LeastSignificantHalf(data), IR::AccType::NORMAL); }); } @@ -216,7 +216,7 @@ bool TranslatorVisitor::thumb32_STRT(Reg n, Reg t, Imm<8> imm8) { bool TranslatorVisitor::thumb32_STR_reg(Reg n, Reg t, Imm<2> imm2, Reg m) { return StoreRegister(*this, n, t, imm2, m, [this](const IR::U32& offset_address, const IR::U32& data) { - ir.WriteMemory32(offset_address, data); + ir.WriteMemory32(offset_address, data, IR::AccType::NORMAL); }); } diff --git a/src/dynarmic/frontend/A32/translate/impl/vfp.cpp b/src/dynarmic/frontend/A32/translate/impl/vfp.cpp index 58300efb..f68c8f38 100644 --- a/src/dynarmic/frontend/A32/translate/impl/vfp.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/vfp.cpp @@ -1186,16 +1186,16 @@ bool TranslatorVisitor::vfp_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> i for (size_t i = 0; i < regs; ++i) { if (sz) { - auto lo = ir.ReadMemory32(address); + auto lo = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - auto hi = ir.ReadMemory32(address); + auto hi = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); if (ir.current_location.EFlag()) { std::swap(lo, hi); } ir.SetExtendedRegister(d + i, ir.Pack2x32To1x64(lo, hi)); } else { - const auto res = ir.ReadMemory32(address); + const auto res = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.SetExtendedRegister(d + i, res); address = ir.Add(address, ir.Imm32(4)); } @@ -1232,12 +1232,12 @@ bool TranslatorVisitor::vfp_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> auto hi = ir.MostSignificantWord(reg_d).result; if (ir.current_location.EFlag()) std::swap(lo, hi); - ir.WriteMemory32(address, lo); + ir.WriteMemory32(address, lo, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - ir.WriteMemory32(address, hi); + ir.WriteMemory32(address, hi, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } else { - ir.WriteMemory32(address, ir.GetExtendedRegister(d + i)); + ir.WriteMemory32(address, ir.GetExtendedRegister(d + i), IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -1258,14 +1258,14 @@ bool TranslatorVisitor::vfp_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bo const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32)); if (sz) { - auto lo = ir.ReadMemory32(address); - auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4))); + auto lo = ir.ReadMemory32(address, IR::AccType::ATOMIC); + auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4)), IR::AccType::ATOMIC); if (ir.current_location.EFlag()) { std::swap(lo, hi); } ir.SetExtendedRegister(d, ir.Pack2x32To1x64(lo, hi)); } else { - ir.SetExtendedRegister(d, ir.ReadMemory32(address)); + ir.SetExtendedRegister(d, ir.ReadMemory32(address, IR::AccType::ATOMIC)); } return true; @@ -1289,10 +1289,10 @@ bool TranslatorVisitor::vfp_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bo if (ir.current_location.EFlag()) { std::swap(lo, hi); } - ir.WriteMemory32(address, lo); - ir.WriteMemory32(ir.Add(address, ir.Imm32(4)), hi); + ir.WriteMemory32(address, lo, IR::AccType::ATOMIC); + ir.WriteMemory32(ir.Add(address, ir.Imm32(4)), hi, IR::AccType::ATOMIC); } else { - ir.WriteMemory32(address, ir.GetExtendedRegister(d)); + ir.WriteMemory32(address, ir.GetExtendedRegister(d), IR::AccType::ATOMIC); } return true; @@ -1341,9 +1341,9 @@ bool TranslatorVisitor::vfp_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, R std::swap(word1, word2); } - ir.WriteMemory32(address, word1); + ir.WriteMemory32(address, word1, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - ir.WriteMemory32(address, word2); + ir.WriteMemory32(address, word2, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } @@ -1386,7 +1386,7 @@ bool TranslatorVisitor::vfp_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, R } for (size_t i = 0; i < regs; i++) { const auto word = ir.GetExtendedRegister(d + i); - ir.WriteMemory32(address, word); + ir.WriteMemory32(address, word, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } @@ -1428,9 +1428,9 @@ bool TranslatorVisitor::vfp_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, R ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); } for (size_t i = 0; i < regs; i++) { - auto word1 = ir.ReadMemory32(address); + auto word1 = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - auto word2 = ir.ReadMemory32(address); + auto word2 = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); if (ir.current_location.EFlag()) { @@ -1478,7 +1478,7 @@ bool TranslatorVisitor::vfp_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, R ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); } for (size_t i = 0; i < regs; i++) { - const auto word = ir.ReadMemory32(address); + const auto word = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); ir.SetExtendedRegister(d + i, word); } diff --git a/src/dynarmic/ir/acc_type.h b/src/dynarmic/ir/acc_type.h index 1452596a..f259660b 100644 --- a/src/dynarmic/ir/acc_type.h +++ b/src/dynarmic/ir/acc_type.h @@ -23,6 +23,7 @@ enum class AccType { IC, DCZVA, AT, + SWAP, // TODO: Remove }; } // namespace Dynarmic::IR diff --git a/src/dynarmic/ir/opcodes.inc b/src/dynarmic/ir/opcodes.inc index cf44893b..79719306 100644 --- a/src/dynarmic/ir/opcodes.inc +++ b/src/dynarmic/ir/opcodes.inc @@ -688,22 +688,22 @@ OPCODE(FPVectorToUnsignedFixed64, U128, U128 // A32 Memory access A32OPC(ClearExclusive, Void, ) -A32OPC(ReadMemory8, U8, U32 ) -A32OPC(ReadMemory16, U16, U32 ) -A32OPC(ReadMemory32, U32, U32 ) -A32OPC(ReadMemory64, U64, U32 ) -A32OPC(ExclusiveReadMemory8, U8, U32 ) -A32OPC(ExclusiveReadMemory16, U16, U32 ) -A32OPC(ExclusiveReadMemory32, U32, U32 ) -A32OPC(ExclusiveReadMemory64, U64, U32 ) -A32OPC(WriteMemory8, Void, U32, U8 ) -A32OPC(WriteMemory16, Void, U32, U16 ) -A32OPC(WriteMemory32, Void, U32, U32 ) -A32OPC(WriteMemory64, Void, U32, U64 ) -A32OPC(ExclusiveWriteMemory8, U32, U32, U8 ) -A32OPC(ExclusiveWriteMemory16, U32, U32, U16 ) -A32OPC(ExclusiveWriteMemory32, U32, U32, U32 ) -A32OPC(ExclusiveWriteMemory64, U32, U32, U64 ) +A32OPC(ReadMemory8, U8, U32, AccType ) +A32OPC(ReadMemory16, U16, U32, AccType ) +A32OPC(ReadMemory32, U32, U32, AccType ) +A32OPC(ReadMemory64, U64, U32, AccType ) +A32OPC(ExclusiveReadMemory8, U8, U32, AccType ) +A32OPC(ExclusiveReadMemory16, U16, U32, AccType ) +A32OPC(ExclusiveReadMemory32, U32, U32, AccType ) +A32OPC(ExclusiveReadMemory64, U64, U32, AccType ) +A32OPC(WriteMemory8, Void, U32, U8, AccType ) +A32OPC(WriteMemory16, Void, U32, U16, AccType ) +A32OPC(WriteMemory32, Void, U32, U32, AccType ) +A32OPC(WriteMemory64, Void, U32, U64, AccType ) +A32OPC(ExclusiveWriteMemory8, U32, U32, U8, AccType ) +A32OPC(ExclusiveWriteMemory16, U32, U32, U16, AccType ) +A32OPC(ExclusiveWriteMemory32, U32, U32, U32, AccType ) +A32OPC(ExclusiveWriteMemory64, U32, U32, U64, AccType ) // A64 Memory access A64OPC(ClearExclusive, Void, )