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