6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 10:46 pm

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Fri Oct 21, 2011 9:50 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
I mentioned some time ago a problem I had with BBC emulation using run65816:

Code:
$ ./run65816 -B -l 0 bbc.img
loading ROM file bbc.img
WARP FACTOR 5

BBC Computer 16K

BASIC

>p

Mistake
>p

Mistake

Bad program
>

(Actually two problems: the memory test is wrong, and then the second Mistake blows up)

Well, I got around to looking into it, and it turns out to be specific to my builds on ARM - it's OK on x86. Haven't got to the root cause yet.

I'm digging in with gdb...


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Oct 21, 2011 10:15 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
... phew. My problem entirely: a declaration should have been static, and wasn't. So one of Samuel's structures was sitting on top of one of mine, and the Beeb's memory was being corrupted by one of the emulator's pieces of machinery.

I think I've learnt a bit more about gdb anyway. I'm not sure how a C programmer is supposed to find a problem like that.

Code:
*** ../lib65816/run65816.c      Fri Oct 21 15:33:04 2011
--- ./run65816.c        Fri Oct 21 22:10:44 2011
***************
*** 6,12 ****
  #include "cpu.h"
 
  #define MEMSIZE (1024 * 1024)
! byte addressSpace[MEMSIZE];
  static byte bank[0x10][0x4000];
 
  static char *program= 0;
--- 6,12 ----
  #include "cpu.h"
 
  #define MEMSIZE (1024 * 1024)
! static byte addressSpace[MEMSIZE];
  static byte bank[0x10][0x4000];
 
  static char *program= 0;


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Oct 21, 2011 10:22 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
(A possibly interesting thing to do with lib65816 is to try to run up John Kortink's port of BBC Basic which allows for 448K of RAM for variables. He doesn't generally publish source, but the interface to the TUBE-like OS will be fairly clean.)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Nov 05, 2011 5:11 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
A C programmer just kind of guesses, based on gdb observations. I want to know what led you to check the memory array!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Nov 05, 2011 7:00 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 24 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: