Add writable ibuf and data registers.
[riscv-isa-sim.git] / riscv / debug_module.cc
1 #include <cassert>
2
3 #include "debug_module.h"
4 #include "debug_defines.h"
5 #include "mmu.h"
6
7 #include "debug_rom/debug_rom.h"
8
9 #if 1
10 # define D(x) x
11 #else
12 # define D(x)
13 #endif
14
15 debug_module_t::debug_module_t() :
16 dmcontrol(1 << DMI_DMCONTROL_VERSION_OFFSET |
17 1 << DMI_DMCONTROL_AUTHENTICATED_OFFSET),
18 abstractcs(datacount << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
19 {
20 }
21
22 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
23 {
24 addr = DEBUG_START + addr;
25
26 if (addr >= DEBUG_RAM_START && addr + len <= DEBUG_RAM_END) {
27 memcpy(bytes, debug_ram + addr - DEBUG_RAM_START, len);
28 return true;
29 }
30
31 if (addr >= DEBUG_ROM_START && addr + len <= DEBUG_ROM_END) {
32 memcpy(bytes, debug_rom_raw + addr - DEBUG_ROM_START, len);
33 return true;
34 }
35
36 fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
37 PRIx64 "\n", len, addr);
38 return false;
39 }
40
41 bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
42 {
43 addr = DEBUG_START + addr;
44
45 if (addr & (len-1)) {
46 fprintf(stderr, "ERROR: unaligned store to debug module: %zd bytes at 0x%016"
47 PRIx64 "\n", len, addr);
48 return false;
49 }
50
51 if (addr >= DEBUG_RAM_START && addr + len <= DEBUG_RAM_END) {
52 memcpy(debug_ram + addr - DEBUG_RAM_START, bytes, len);
53 return true;
54 } else if (len == 4 && addr == DEBUG_CLEARDEBINT) {
55 clear_interrupt(bytes[0] | (bytes[1] << 8) |
56 (bytes[2] << 16) | (bytes[3] << 24));
57 return true;
58 } else if (len == 4 && addr == DEBUG_SETHALTNOT) {
59 set_halt_notification(bytes[0] | (bytes[1] << 8) |
60 (bytes[2] << 16) | (bytes[3] << 24));
61 return true;
62 }
63
64 fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
65 PRIx64 "\n", len, addr);
66 return false;
67 }
68
69 void debug_module_t::ram_write32(unsigned int index, uint32_t value)
70 {
71 char* base = debug_ram + index * 4;
72 base[0] = value & 0xff;
73 base[1] = (value >> 8) & 0xff;
74 base[2] = (value >> 16) & 0xff;
75 base[3] = (value >> 24) & 0xff;
76 }
77
78 uint32_t debug_module_t::ram_read32(unsigned int index)
79 {
80 // It'd be better for raw_page (and all memory) to be unsigned chars, but mem
81 // in sim_t is just chars, so I'm following that convention.
82 unsigned char* base = (unsigned char*) (debug_ram + index * 4);
83 uint32_t value = ((uint32_t) base[0]) |
84 (((uint32_t) base[1]) << 8) |
85 (((uint32_t) base[2]) << 16) |
86 (((uint32_t) base[3]) << 24);
87 return value;
88 }
89
90 bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
91 {
92 D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
93 if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
94 *value = data[address - DMI_DATA0];
95 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
96 *value = ibuf[address - DMI_IBUF0];
97 } else {
98 switch (address) {
99 case DMI_DMCONTROL:
100 *value = dmcontrol;
101 break;
102 case DMI_ABSTRACTCS:
103 *value = abstractcs;
104 break;
105 case DMI_ACCESSCS:
106 *value = progsize << DMI_ACCESSCS_PROGSIZE_OFFSET;
107 break;
108 default:
109 D(fprintf(stderr, "error\n"));
110 return false;
111 }
112 }
113 D(fprintf(stderr, "0x%x\n", *value));
114 return true;
115 }
116
117 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
118 {
119 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
120 if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
121 data[address - DMI_DATA0] = value;
122 return true;
123 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
124 ibuf[address - DMI_IBUF0] = value;
125 return true;
126 }
127 return false;
128 }