1 #ifndef RSP_HPP__
2 #define RSP_HPP__
3 
4 #include <memory>
5 #include <stdint.h>
6 #include <string.h>
7 #include <string>
8 #include <unordered_map>
9 
10 #include "debug_jit.hpp"
11 #include "llvm_jit.hpp"
12 #include "rsp_op.hpp"
13 #include "state.hpp"
14 
15 namespace RSP
16 {
17 #ifdef DEBUG_JIT
18 using Block = JIT::DebugBlock;
19 #else
20 using Block = JIT::Block;
21 #endif
22 using Func = JIT::Func;
23 
24 
25 class alignas(64) CPU
26 {
27 public:
28 	CPU();
29 	~CPU();
30 
31 	CPU(CPU &&) = delete;
32 	void operator=(CPU &&) = delete;
33 
set_dmem(uint32_t * dmem)34 	void set_dmem(uint32_t *dmem)
35 	{
36 		state.dmem = dmem;
37 	}
38 
set_imem(uint32_t * imem)39 	void set_imem(uint32_t *imem)
40 	{
41 		state.imem = imem;
42 	}
43 
set_rdram(uint32_t * rdram)44 	void set_rdram(uint32_t *rdram)
45 	{
46 		state.rdram = rdram;
47 	}
48 
49 	void invalidate_imem();
50 
get_state()51 	CPUState &get_state()
52 	{
53 		return state;
54 	}
55 
56 	ReturnMode run();
57 
58 	void enter(uint32_t pc);
59 	void call(uint32_t target, uint32_t ret);
60 	int ret(uint32_t pc);
61 	void exit(ReturnMode mode);
62 
63 	void print_registers();
64 
65 private:
66 	CPUState state;
67 	Func blocks[IMEM_WORDS] = {};
68 	std::unordered_map<std::string, uint64_t> symbol_table;
69 #ifndef DEBUG_JIT
70 	JIT::LLVMEngine jit_engine;
71 #endif
72 	std::unordered_map<uint64_t, std::unique_ptr<Block>> cached_blocks[IMEM_WORDS];
73 
74 	void invalidate_code();
75 	uint64_t hash_imem(unsigned pc, unsigned count) const;
76 	Func jit_region(uint64_t hash, unsigned pc, unsigned count);
77 
78 	std::string full_code;
79 	std::string body;
80 
81 	void init_symbol_table();
82 
83 	alignas(64) uint32_t cached_imem[IMEM_WORDS] = {};
84 
85 	// Platform specific.
86 #ifdef __GNUC__
87 	intptr_t env[64];
88 	// We're reading this after setjmp returns so need to make sure the read happens when we expect it to.
89 	volatile ReturnMode return_mode;
90 #else
91 #error "Need __builtin_setjmp/longjmp support alternative for other compilers ..."
92 #endif
93 
94 #define CALL_STACK_SIZE 32
95 	uint32_t call_stack[CALL_STACK_SIZE] = {};
96 	unsigned call_stack_ptr = 0;
97 
98 	unsigned analyze_static_end(unsigned pc, unsigned end);
99 };
100 } // namespace RSP
101 
102 #endif
103