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