i2c tools better naming scheme
[cr816-sim.git] / access.c
blobfceb89020c100847778d238e5bf2999a67b8dee6
1 #include <string.h>
2 #include <stdlib.h>
3 #include "disasm.h"
4 #include "log.h"
5 #include "isa.h"
6 #include "ioregs.h"
8 static u8 mem_ram[0x800];
9 static u8 mem_flash[0x800];
11 static u16 trace_pc = 0;
13 //TODO use tracing for log RW
14 #define TRACE_REG_NUM 1000000
15 static unsigned trace_regs8_r_idx = 0;
16 static struct trace_regs8_r regs8_r_history[TRACE_REG_NUM];
17 static unsigned trace_regs8_w_idx = 0;
18 static struct trace_regs8_w regs8_w_history[TRACE_REG_NUM];
19 static struct trace_regs8_w regs8_curr[UTIL_REG_FLAGS+1]; //NOTICE last
21 #define TRACE_MEM_NUM 1000000
22 static unsigned trace_mem_r_idx = 0;
23 static unsigned trace_mem_w_idx = 0;
24 static struct trace_mem_r mem_r_history[TRACE_MEM_NUM];
25 static struct trace_mem_w mem_w_history[TRACE_MEM_NUM];
28 /** ****** access utils ******/
30 static u8 trace_add_read(
31 u16 pc,
32 unsigned reg_idx
35 u8 ret;
37 regs8_r_history[trace_regs8_r_idx].pc = pc;
38 regs8_r_history[trace_regs8_r_idx].reg = reg_idx;
40 trace_regs8_r_idx = (trace_regs8_r_idx+1)%TRACE_REG_NUM;
42 ret = regs8_curr[reg_idx].raw;
44 return ret;
47 static void trace_add_write(
48 u16 pc,
49 unsigned reg_idx,
50 u8 val
53 regs8_w_history[trace_regs8_w_idx].pc = pc;
54 regs8_w_history[trace_regs8_w_idx].reg = reg_idx;
55 regs8_w_history[trace_regs8_w_idx].raw = val;
57 trace_regs8_w_idx = (trace_regs8_w_idx+1)%TRACE_REG_NUM;
59 regs8_curr[reg_idx].raw = val;
62 //just read/write ... backtrace can be done in regs8_history[]
63 u16 read_pc(void)
65 return trace_pc;
68 void write_pc(u16 addr)
70 if (addr == (trace_pc+1) ) {
71 trace_pc = addr;
72 } else {
73 trace_pc = addr;
74 //log only jumps?
75 log_access_write_add("pc=%04hx ", addr);
79 u8 read_reg8(enum alu_regs reg, unsigned log)
81 u8 ret;
82 ret = trace_add_read(trace_pc, reg);
84 if (log)
85 log_access_read_add("%02hhx=%s ",
86 ret, get_regs_name(reg));
88 return ret;
91 void write_reg8(enum alu_regs reg, u8 val, unsigned log)
93 trace_add_write(trace_pc, reg, val);
95 if (log)
96 log_access_write_add("%s=%02hhx ",
97 get_regs_name(reg), val);
98 return ;
101 //maybe join with *reg functions
102 void write_flags(struct cpuflags cpuflags, unsigned log)
105 trace_add_write(trace_pc, UTIL_REG_FLAGS, cpuflags.raw);
107 if (log)
108 log_access_write_add("flags=%02hhx(%c%c%c) ",
109 cpuflags.raw,
110 cpuflags.z?'Z':'z',
111 cpuflags.c?'C':'c',
112 cpuflags.v?'V':'v'
116 struct cpuflags read_flags(unsigned log)
118 struct cpuflags ret;
120 ret.raw = trace_add_read(trace_pc, UTIL_REG_FLAGS);
122 if (log)
123 log_access_read_add("%02hhx(%c%c%c)=flags ",
124 ret.raw,
125 ret.z?'Z':'z',
126 ret.c?'C':'c',
127 ret.v?'V':'v'
130 return ret;
134 u16 read_ix(enum alu_ixs ixs, unsigned log)
136 u16 ret;
137 u8 lo, hi;
139 switch(ixs) {
140 case I_REG_0:
141 lo = read_reg8(MAIN_REG_I0L, 0);
142 hi = read_reg8(MAIN_REG_I0H, 0);
143 break;
144 case I_REG_1:
145 lo = read_reg8(MAIN_REG_I1L, 0);
146 hi = read_reg8(MAIN_REG_I1H, 0);
147 break;
148 case I_REG_2:
149 lo = read_reg8(MAIN_REG_I2L, 0);
150 hi = read_reg8(MAIN_REG_I2H, 0);
151 break;
152 case I_REG_3:
153 lo = read_reg8(MAIN_REG_I3L, 0);
154 hi = read_reg8(MAIN_REG_I3H, 0);
155 break;
156 default:
157 fprintf(stderr, "!!error read_ix unknown reg\n");
158 return 0xdead;
161 ret = lo | (hi << 8);
163 if (log)
164 log_access_read_add("%04hx=%s ", ret, get_ixs_name(ixs));
166 return ret;
170 void write_ix(enum alu_ixs ixs, u16 val, unsigned log)
172 u8 lo, hi;
174 lo = val & 0xff;
175 hi = (val >> 8) & 0xff;
177 switch(ixs) {
178 case I_REG_0:
179 write_reg8(MAIN_REG_I0L, lo, 0);
180 write_reg8(MAIN_REG_I0H, hi, 0);
181 break;
182 case I_REG_1:
183 write_reg8(MAIN_REG_I1L, lo, 0);
184 write_reg8(MAIN_REG_I1H, hi, 0);
185 break;
186 case I_REG_2:
187 write_reg8(MAIN_REG_I2L, lo, 0);
188 write_reg8(MAIN_REG_I2H, hi, 0);
189 break;
190 case I_REG_3:
191 write_reg8(MAIN_REG_I3L, lo, 0);
192 write_reg8(MAIN_REG_I3H, hi, 0);
193 break;
194 default:
195 fprintf(stderr, "!!error write_ix unknown reg\n");
196 return;
199 if (log)
200 log_access_write_add("%s=%04hx ", get_ixs_name(ixs), val);
203 u16 read_ip(unsigned log)
205 u16 ret;
207 ret = (read_reg8(MAIN_REG_IPH, 0) << 8) |
208 read_reg8(MAIN_REG_IPL, 0);
210 if (log)
211 log_access_read_add("%04hx=ip ", ret);
213 return ret;
217 void write_ip(u16 val, unsigned log)
219 write_reg8(MAIN_REG_IPL, val & 0xff, 0);
220 write_reg8(MAIN_REG_IPH, (val >> 8) & 0xff, 0);
222 if (log)
223 log_access_write_add("ip=%04hx ", val);
227 u8 read_ram(u16 addr)
229 //TODO watch special adresses?
231 //NOTICE these may be inaccurate
232 switch(addr) {
233 case 0:
234 log_comment_add(" smb_ctl\n");
235 break;
236 case 1:
237 log_comment_add(" smb_errno\n");
238 break;
239 case 2:
240 log_comment_add(" i2c_errno\n");
241 break;
242 case 5:
243 log_comment_add(" process_list MSB (%04hx)\n", (mem_ram[5]<<8) | mem_ram[6]);
244 break;
245 case 6:
246 log_comment_add(" process_list LSB (%04hx)\n", (mem_ram[5]<<8) | mem_ram[6]);
247 break;
248 case 7:
249 log_comment_add(" process_ptr MSB (%04hx)\n", (mem_ram[7]<<8) | mem_ram[8]);
250 break;
251 case 8:
252 log_comment_add(" process_ptr LSB (%04hx)\n", (mem_ram[7]<<8) | mem_ram[8]);
253 break;
254 case 9:
255 log_comment_add(" num processes = %hhd\n", mem_ram[addr]);
256 break;
257 case 0xa:
258 log_comment_add(" halt_mode = %hhd\n", mem_ram[addr]);
259 log_comment_add(" 0 (or other) = set gie, don't touch anything, halt\n");
260 log_comment_add(" 1 = disable osc+pll, set gie, halt\n");
261 log_comment_add(" 2 = disable pll, set gie, halt\n");
262 break;
265 return mem_ram[addr];
268 void write_ram(u16 addr, u8 val)
270 //TODO watch special adresses?
271 switch(addr) {
272 case 0:
273 log_comment_add(" smb_ctl\n");
274 break;
275 case 1:
276 log_comment_add(" smb_errno\n");
277 break;
278 case 2:
279 log_comment_add(" i2c_errno\n");
280 break;
281 case 5:
282 log_comment_add(" process_list MSB\n");
283 break;
284 case 6:
285 log_comment_add(" process_list LSB\n");
286 break;
287 case 7:
288 log_comment_add(" process_ptr MSB\n");
289 break;
290 case 8:
291 log_comment_add(" process_ptr LSB\n");
292 break;
293 case 9:
294 log_comment_add(" num processes = %hhd\n", val);
295 break;
296 case 0xa:
297 log_comment_add(" halt_mode = %hhd\n", val);
298 log_comment_add(" 0 (or other) = set gie, don't touch anything, halt\n");
299 log_comment_add(" 1 = disable osc+pll, set gie, halt\n");
300 log_comment_add(" 2 = disable pll, set gie, halt\n");
301 break;
304 mem_ram[addr] = val;
307 u8 read_data_flash(u16 addr)
309 //TODO watch special adresses?
310 return mem_flash[addr];
314 //TODO only FOR flash subroutine? CPU write probably not working?
315 void write_data_flash(u16 addr, u8 val)
317 //TODO watch special adresses?
318 mem_flash[addr] = val;
319 // fprintf(stderr, "%x %x\n",addr, mem_flash[addr]);
323 u8 read_mem(u16 addr, unsigned log)
325 u8 ret;
327 mem_r_history[trace_mem_r_idx].pc = trace_pc;
328 mem_r_history[trace_mem_r_idx].addr = addr;
330 trace_mem_r_idx = (trace_mem_r_idx+1)%TRACE_MEM_NUM;
332 if (addr < 0x4000) {
333 ret = read_ram(addr & 0x7ff);
334 } else if (addr < 0x8000) {
335 ret = read_data_flash(addr & 0x7ff);
336 } else {
337 ret = read_io(addr & 0xff);
340 if (log) {
341 if (addr < 0x4000) {
342 if (addr < 0x800) {
343 log_access_read_add("%02hhx=RAM[%03hx] ", ret, addr);
344 } else {
345 log_access_read_add("%02hhx=RAM?[%03hx] ", ret, addr);
347 } else if (addr < 0x8000) {
348 if (addr < 0x4800) {
349 //NOTICE print phys or region offset?
350 log_access_read_add("%02hhx=FLASH[%03hx] ", ret, addr & 0x7ff);
351 } else {
352 log_access_read_add("%02hhx=FLASH?[%03hx] ", ret, addr & 0x7ff);
354 } else {
355 if (addr < 0x8100) {
356 //NOTICE print phys or region offset?
357 log_access_read_add("%02hhx=IO[%02hx] ", ret, addr & 0xff);
358 } else {
359 log_access_read_add("%02hhx=IO?[%02hx] ", ret, addr & 0xff);
364 return ret;
367 void write_mem(u16 addr, u8 val, unsigned log)
369 mem_w_history[trace_mem_w_idx].pc = trace_pc;
370 mem_w_history[trace_mem_w_idx].addr = addr;
371 mem_w_history[trace_mem_w_idx].val = val;
373 trace_mem_w_idx = (trace_mem_w_idx+1)%TRACE_MEM_NUM;
375 if (addr < 0x4000) {
376 write_ram(addr & 0x7ff, val);
377 } else if (addr < 0x8000) {
378 write_data_flash(addr & 0x7ff, val);
379 sim_breakpoint_set(SIM_BREAKPOINT_DATA);
380 } else {
381 write_io(addr & 0xff, val);
384 if (log) {
385 if (addr < 0x4000) {
386 if (addr < 0x800) {
387 log_access_write_add("RAM[%03hx]=%02hhx ", addr, val);
388 } else {
389 log_access_write_add("RAM?[%03hx]=%02hhx ", addr, val);
391 } else if (addr < 0x8000) {
392 if (addr < 0x4800) {
393 //NOTICE print phys or region offset?
394 log_access_write_add("readonly! FLASH[%03hx]=%02hhx ", addr & 0x7ff, val);
395 } else {
396 log_access_write_add("readonly! FLASH?[%04hx]=%02hhx ", addr, val);
398 } else {
399 if (addr < 0x8100) {
400 //NOTICE print phys or region offset?
401 log_access_write_add("IO[%02hx]=%02hhx ", addr & 0xff, val);
402 } else {
403 log_access_write_add("IO?[%04hx]=%02hhx ", addr, val);
409 void init_access(char * filename_ram, char * filename_flash)
412 trace_pc = 0;
413 trace_regs8_r_idx = 0;
414 trace_regs8_w_idx = 0;
415 trace_mem_r_idx = 0;
416 trace_mem_w_idx = 0;
418 //TODO complete RAM/IO or soft only reset? (leave tracing)
419 memset(regs8_r_history, 0, TRACE_REG_NUM*sizeof(struct trace_regs8_r));
420 memset(regs8_w_history, 0, TRACE_REG_NUM*sizeof(struct trace_regs8_w));
421 memset(regs8_curr, 0, (UTIL_REG_FLAGS+1)*sizeof(struct trace_regs8_w)); //NOTICE last item
422 memset(mem_r_history, 0, TRACE_MEM_NUM*sizeof(struct trace_mem_r));
423 memset(mem_w_history, 0, TRACE_MEM_NUM*sizeof(struct trace_mem_w));
425 //stack empty if set after reset (probably)
426 struct cpuflags f;
427 f.raw = 0;
428 f.se = 1;
429 write_reg8(UTIL_REG_FLAGS, f.raw, 0);
431 //IRL/rom probably does "zeroing" by writing LO byte of address
432 for(unsigned addr=0; addr<sizeof(mem_ram);addr++) {
433 mem_ram[addr] = addr & 0xff;
435 // memset(mem_ram, 0xff, sizeof(mem_ram));
437 if (filename_ram) {
438 FILE * fp;
439 fp = fopen(filename_ram, "r");
440 if (fp == NULL) {
441 perror("ram dump opening");
442 exit(1);
444 fread(mem_ram, 0x800, 1, fp);
445 fclose(fp);
448 memset(mem_flash, 0xff, sizeof(mem_flash));
450 if (filename_flash) {
451 FILE * fp;
452 fp = fopen(filename_flash, "r");
453 if (fp == NULL) {
454 perror("flash dump opening");
455 exit(1);
457 fread(mem_flash, 0x800, 1, fp);
458 fclose(fp);