kc5tja wrote:
A C programmer just kind of guesses, based on gdb observations. I want to know what led you to check the memory array!
That's kind of reassuring! Here's the story:
I was running two instances of the emulator, one of which was broken. The first visible divergence is the memory size report.
The loop which checks memory was exiting far too early - I was able to put gdb breakpoints on the memory read hook, either for an instruction fetch or a plain read (was also able to breakpoint on a write) and it turned out that a pointer in zero page was changing value without being written to. Eventually I realised I could single step in gdb, and could start that process right before the problem by careful use of counted breakpoints.
I was keeping notes, but don't seem to have all of them - I remember now that I lost my X session in a swapfest after unwisely trying to load an overlarge 6502 related image.
Here are some surviving notes, not entirely coherent:
Quote:
(gdb) break MEM_writeMem
Breakpoint 1 at 0x8e00
(gdb) ignore 1 10000
Will ignore next 10000 crossings of breakpoint 1.
(gdb) run
(gdb) info break 1
Num Type Disp Enb Address What
1 breakpoint keep y 0x00008e00 <MEM_writeMem>
breakpoint already hit 4538 times
ignore next 5462 hits
A couple of gdb tipsheet links:
Quote:
(gdb) display PC.A
1: PC.A = 55757
(gdb) condition 2 flags==1 // allows us to break on IFETCH
(gdb) clear MEM_writeMem
(gdb) cont
(gdb) display /x PC.A
15: /x PC.A = 0xd9f2
(gdb) display /x addressSpace[address]
14: /x addressSpace[address] = 0xf0
I was able to check writes to the RAM size byte at 028e using a line-oriented break with a condition:
Quote:
(gdb) list MEM_writeMem
249 void MEM_writeMem(word32 address, byte b, word32 timestamp)
250 {
251 address = address % MEMSIZE;
(gdb) break 251
Breakpoint 4 at 0x8e08: file run65816.c, line 251.
(gdb) condition 4 address==0x028e
(gdb) info breakpoints
Num Type Disp Enb Address What
4 breakpoint keep y 0x00008e08 in MEM_writeMem at run65816.c:251
stop only if address==0x028e
and so I could find the routine which sets the RAM size.
Now I want to trace the hits to some crucial instruction
perhaps the INX which counts memory size, at D9F8
Quote:
printf "A: %04x X: %04x Y: %04x S: %04x PC: %06x\n", A.W, X.W, Y.W, S.W, PC.A
Quote:
(gdb) break 137
Breakpoint 3 at 0x4010d5: file run65816.c, line 137.
(gdb) condition 3 flags==1 && address == 0xd9f8
(gdb) display /x PC.A
2: /x PC.A = 0xd9f4
actually monitoring PC.A is pointless because our trap is on SYNC with a fixed address.
and of course on ARM it turns out we never hit the increment - X remains at 4.
But why?
We need to single-step from D9E7 and watch all the condition codes.
Quote:
(gdb) info breakpoints
Num Type Disp Enb Address What
8 breakpoint keep y 0x00009050 in MEM_readMem at run65816.c:137
stop only if flags==1 && address==0xd9e9
breakpoint already hit 1 time
9 breakpoint keep y 0x00009050 in MEM_readMem at run65816.c:137
stop only if flags==1
breakpoint already hit 1 time
Looks like we may have a point of divergence.
ARM is hopping straight from d9e9 to d9eb and changing two bytes in zero page, both wrong:
Quote:
(gdb) printf "A: %04x X: %04x Y: %04x P: %02x S: %04x PC: %06x\n", A.W, X.W, Y.W, P, S.W, PC.A
A: 0000 X: 0004 Y: 0000 P: 34 S: 01fe PC: 00d9e9
(gdb) print addressSpace[0]
$7 = 0 '\0'
(gdb) print addressSpace[1]
$8 = 0 '\0'
(gdb) cont
Continuing.
Breakpoint 9, MEM_readMem (address=55787, timestamp=0, flags=1) at run65816.c:137
137 address = address % MEMSIZE;
(gdb) printf "A: %04x X: %04x Y: %04x P: %02x S: %04x PC: %06x\n", A.W, X.W, Y.W, P, S.W, PC.A
A: 0000 X: 0004 Y: 0000 P: 34 S: 01fe PC: 00d9eb
(gdb) print addressSpace[0]
$9 = 253 '???
(gdb) print addressSpace[1]
$10 = 3 '\003'
Whereas x86 is doing the right thing:
Quote:
(gdb) printf "A: %04x X: %04x Y: %04x P: %02x S: %04x PC: %06x\n", A.W, X.W, Y.W, P, S.W, PC.A
A: 0000 X: 0004 Y: 0000 P: 34 S: 01fe PC: 00d9e9
(gdb) print addressSpace[0]
$4 = 0 '\000'
(gdb) print addressSpace[1]
$5 = 0 '\000'
(gdb) cont
Continuing.