1 /* This file is part of the dynarmic project. 2 * Copyright (c) 2018 MerryMage 3 * SPDX-License-Identifier: 0BSD 4 */ 5 6 #pragma once 7 8 #include <array> 9 #include <map> 10 11 #include <dynarmic/A64/a64.h> 12 13 #include "common/assert.h" 14 #include "common/common_types.h" 15 16 using Vector = Dynarmic::A64::Vector; 17 18 class A64TestEnv final : public Dynarmic::A64::UserCallbacks { 19 public: 20 u64 ticks_left = 0; 21 22 bool code_mem_modified_by_guest = false; 23 u64 code_mem_start_address = 0; 24 std::vector<u32> code_mem; 25 26 std::map<u64, u8> modified_memory; 27 std::vector<std::string> interrupts; 28 IsInCodeMem(u64 vaddr)29 bool IsInCodeMem(u64 vaddr) const { 30 return vaddr >= code_mem_start_address && vaddr < code_mem_start_address + code_mem.size() * 4; 31 } 32 MemoryReadCode(u64 vaddr)33 std::uint32_t MemoryReadCode(u64 vaddr) override { 34 if (!IsInCodeMem(vaddr)) { 35 return 0x14000000; // B . 36 } 37 38 const size_t index = (vaddr - code_mem_start_address) / 4; 39 return code_mem[index]; 40 } 41 MemoryRead8(u64 vaddr)42 std::uint8_t MemoryRead8(u64 vaddr) override { 43 if (IsInCodeMem(vaddr)) { 44 return reinterpret_cast<u8*>(code_mem.data())[vaddr - code_mem_start_address]; 45 } 46 if (auto iter = modified_memory.find(vaddr); iter != modified_memory.end()) { 47 return iter->second; 48 } 49 return static_cast<u8>(vaddr); 50 } MemoryRead16(u64 vaddr)51 std::uint16_t MemoryRead16(u64 vaddr) override { 52 return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8; 53 } MemoryRead32(u64 vaddr)54 std::uint32_t MemoryRead32(u64 vaddr) override { 55 return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16; 56 } MemoryRead64(u64 vaddr)57 std::uint64_t MemoryRead64(u64 vaddr) override { 58 return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32; 59 } MemoryRead128(u64 vaddr)60 Vector MemoryRead128(u64 vaddr) override { 61 return {MemoryRead64(vaddr), MemoryRead64(vaddr + 8)}; 62 } 63 MemoryWrite8(u64 vaddr,std::uint8_t value)64 void MemoryWrite8(u64 vaddr, std::uint8_t value) override { 65 if (IsInCodeMem(vaddr)) { 66 code_mem_modified_by_guest = true; 67 } 68 modified_memory[vaddr] = value; 69 } MemoryWrite16(u64 vaddr,std::uint16_t value)70 void MemoryWrite16(u64 vaddr, std::uint16_t value) override { 71 MemoryWrite8(vaddr, static_cast<u8>(value)); 72 MemoryWrite8(vaddr + 1, static_cast<u8>(value >> 8)); 73 } MemoryWrite32(u64 vaddr,std::uint32_t value)74 void MemoryWrite32(u64 vaddr, std::uint32_t value) override { 75 MemoryWrite16(vaddr, static_cast<u16>(value)); 76 MemoryWrite16(vaddr + 2, static_cast<u16>(value >> 16)); 77 } MemoryWrite64(u64 vaddr,std::uint64_t value)78 void MemoryWrite64(u64 vaddr, std::uint64_t value) override { 79 MemoryWrite32(vaddr, static_cast<u32>(value)); 80 MemoryWrite32(vaddr + 4, static_cast<u32>(value >> 32)); 81 } MemoryWrite128(u64 vaddr,Vector value)82 void MemoryWrite128(u64 vaddr, Vector value) override { 83 MemoryWrite64(vaddr, value[0]); 84 MemoryWrite64(vaddr + 8, value[1]); 85 } 86 MemoryWriteExclusive8(u64 vaddr,std::uint8_t value,std::uint8_t expected)87 bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, [[maybe_unused]] std::uint8_t expected) override { 88 MemoryWrite8(vaddr, value); 89 return true; 90 } MemoryWriteExclusive16(u64 vaddr,std::uint16_t value,std::uint16_t expected)91 bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, [[maybe_unused]] std::uint16_t expected) override { 92 MemoryWrite16(vaddr, value); 93 return true; 94 } MemoryWriteExclusive32(u64 vaddr,std::uint32_t value,std::uint32_t expected)95 bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, [[maybe_unused]] std::uint32_t expected) override { 96 MemoryWrite32(vaddr, value); 97 return true; 98 } MemoryWriteExclusive64(u64 vaddr,std::uint64_t value,std::uint64_t expected)99 bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, [[maybe_unused]] std::uint64_t expected) override { 100 MemoryWrite64(vaddr, value); 101 return true; 102 } MemoryWriteExclusive128(u64 vaddr,Vector value,Vector expected)103 bool MemoryWriteExclusive128(u64 vaddr, Vector value, [[maybe_unused]] Vector expected) override { 104 MemoryWrite128(vaddr, value); 105 return true; 106 } 107 InterpreterFallback(u64 pc,size_t num_instructions)108 void InterpreterFallback(u64 pc, size_t num_instructions) override { ASSERT_MSG(false, "InterpreterFallback({:016x}, {})", pc, num_instructions); } 109 CallSVC(std::uint32_t swi)110 void CallSVC(std::uint32_t swi) override { ASSERT_MSG(false, "CallSVC({})", swi); } 111 ExceptionRaised(u64 pc,Dynarmic::A64::Exception)112 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception /*exception*/) override { ASSERT_MSG(false, "ExceptionRaised({:016x})", pc); } 113 AddTicks(std::uint64_t ticks)114 void AddTicks(std::uint64_t ticks) override { 115 if (ticks > ticks_left) { 116 ticks_left = 0; 117 return; 118 } 119 ticks_left -= ticks; 120 } GetTicksRemaining()121 std::uint64_t GetTicksRemaining() override { 122 return ticks_left; 123 } GetCNTPCT()124 std::uint64_t GetCNTPCT() override { 125 return 0x10000000000 - ticks_left; 126 } 127 }; 128