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