[xcc,sim,opcodes] more rvc instructions and bug 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 | ((uint32_t)hi << 16);
29
30 return insn;
31 }
32
33 load_func(uint8)
34 load_func(uint16)
35 load_func(uint32)
36 load_func(uint64)
37
38 load_func(int8)
39 load_func(int16)
40 load_func(int32)
41 load_func(int64)
42
43 store_func(uint8)
44 store_func(uint16)
45 store_func(uint32)
46 store_func(uint64)
47
48 reg_t get_badvaddr() { return badvaddr; }
49
50 private:
51 char* mem;
52 size_t memsz;
53 reg_t badvaddr;
54
55 void check_align(reg_t addr, int size, bool fetch)
56 {
57 if(addr & (size-1))
58 {
59 badvaddr = addr;
60 if(fetch)
61 throw trap_instruction_address_misaligned;
62 throw trap_data_address_misaligned;
63 }
64 }
65
66 void check_bounds(reg_t addr, int size, bool store, bool fetch)
67 {
68 if(addr >= memsz || addr + size > memsz)
69 {
70 badvaddr = addr;
71 if(fetch)
72 throw trap_instruction_access_fault;
73 throw store ? trap_store_access_fault : trap_load_access_fault;
74 }
75 }
76
77 void check_align_and_bounds(reg_t addr, int size, bool store, bool fetch)
78 {
79 check_align(addr, size, fetch);
80 check_bounds(addr, size, store, fetch);
81 }
82 };