[xcc, sim] added rvc insn c.li; misc fixes
[riscv-isa-sim.git] / riscv / mmu.h
1 #include "decode.h"
2 #include "trap.h"
3
4 class mmu_t
5 {
6 public:
7 mmu_t(char* _mem, size_t _memsz) : mem(_mem), memsz(_memsz), badvaddr(0) {}
8
9 #define load_func(type) \
10 type##_t load_##type(reg_t addr) { \
11 check_align_and_bounds(addr, sizeof(type##_t), false, false); \
12 return *(type##_t*)(mem+addr); \
13 }
14
15 #define store_func(type) \
16 void store_##type(reg_t addr, type##_t val) { \
17 check_align_and_bounds(addr, sizeof(type##_t), true, false); \
18 *(type##_t*)(mem+addr) = val; \
19 }
20
21 insn_t load_insn(reg_t addr, bool rvc)
22 {
23 check_align_and_bounds(addr, rvc ? 2 : 4, false, true);
24 uint16_t lo = *(uint16_t*)(mem+addr);
25 uint16_t hi = *(uint16_t*)(mem+addr+2);
26
27 insn_t insn;
28 insn.bits = lo;
29 if((lo & 0x3) == 0x3)
30 insn.bits |= (uint32_t)hi << 16;
31
32 return insn;
33 }
34
35 load_func(uint8)
36 load_func(uint16)
37 load_func(uint32)
38 load_func(uint64)
39
40 load_func(int8)
41 load_func(int16)
42 load_func(int32)
43 load_func(int64)
44
45 store_func(uint8)
46 store_func(uint16)
47 store_func(uint32)
48 store_func(uint64)
49
50 reg_t get_badvaddr() { return badvaddr; }
51
52 private:
53 char* mem;
54 size_t memsz;
55 reg_t badvaddr;
56
57 void check_align(reg_t addr, int size, bool fetch)
58 {
59 if(addr & (size-1))
60 {
61 badvaddr = addr;
62 if(fetch)
63 throw trap_instruction_address_misaligned;
64 throw trap_data_address_misaligned;
65 }
66 }
67
68 void check_bounds(reg_t addr, int size, bool store, bool fetch)
69 {
70 if(addr >= memsz || addr + size > memsz)
71 {
72 badvaddr = addr;
73 if(fetch)
74 throw trap_instruction_access_fault;
75 throw store ? trap_store_access_fault : trap_load_access_fault;
76 }
77 }
78
79 void check_align_and_bounds(reg_t addr, int size, bool store, bool fetch)
80 {
81 check_align(addr, size, fetch);
82 check_bounds(addr, size, store, fetch);
83 }
84 };