6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat May 04, 2024 10:35 am

All times are UTC




Post new topic Reply to topic  [ 60 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
PostPosted: Sat Dec 08, 2012 7:48 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
If the monitor executes the wrong code, presumably it's either a misimplemented branch or a mistake in branching?


Top
 Profile  
Reply with quote  
PostPosted: Sat Dec 08, 2012 8:08 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Or a mistake in the flag handling.


Top
 Profile  
Reply with quote  
PostPosted: Sat Dec 08, 2012 8:21 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
Hee hee - that's what I meant to type!


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 4:47 am 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
One of the things that you can do is add some tracing to your simulator. For example, you can dedicate a memory location to a trace flag. Then whenever that location is set to 1, the simulator can start dumping a trace of the code that it's executing.

So, you can add some guards around the "help" code to turn this on and off. Or you can create a little more sophisticated command set (turn trace on, push current trace, turn trace off, pop trace status, reset trace status).

That way since "you know" your keyboard routine works (which is likely simply polling for a value), you can turn the trace off there while it loops for the next character, etc.

Run traces will tell you a lot. Add in some memory dumps to particular memory areas during the trace, that can help too.

Being on your own simulator makes things easier than if you were debugging this on a raw board, since you can get even greater insight into what the cpu is doing.


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 7:17 am 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
I've narrowed it down to either a bad ASL or JMP (address,X) opcode.

I'm pretty sure it's probably the JMP because that a CMOS opcode I coded myself. In the Monitor, it's used in a jump table to each command, and the addressing command is command 0. (Which is why that one works). The parser is fine and references the jump table via the X register perfectly. I'm really close on this one.

== EDIT ==
ASL is fine, X (address offset) is being incremented by 2 for every command in the list, which means I suck a C++ (known issue) and can't count correctly.

The offending command is here.

Code:
   case 0x7c:                      // JMP INDIR,X
      value = popWord();                                          // read address at PC and move up 2
      addr = memReadByte(value) + (memReadByte(value+1)<<8);  //read address at that location (Don't move PC)
      addr = addr +regX;                                            //add address given with what's in the X register
      if (addr > 0xFFFF) {addr = addr - 0xFFFF;}            //if the address is > 0xFFFF wrap around
      regPC = addr;                                                 //move PC to the new address
      break;                                                           //get the next opcode.


This is odd, because it appears to be coded right. I'm tracking the PC after this to see what happens...


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 8:42 am 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
AUGH!!!! I FIGURED IT OUT!!!! It *WAS* a bad JMP command. evidently, I can't read instructions properly!

You add X to the address that is read after the opcode, not added the PC after the jump
The correct command implementation

Code:
   case 0x7c:                      // JMP INDIR,X
      value = popWord();
      value = value + regX;
      if (value > 0xFFFF) {value = value - 0xFFFF;}
      addr = memReadByte(value) + (memReadByte(value+1)<<8);
      regPC = addr;
      break;


System's running OK now, the assembler is printing out WAY to many spaces, which means I have another opcode to fix somewhere. I'm going to turn TSB back on and see if it works OK. Good news is that I can now somewhat code directly on the device and test opcodes as they run. That's pretty pimp.

=== EDIT ===
Yup TSB is broken, I'm using the NMOS way of doing it. I have a feeling I botched another indexer too. Some functions are hard-crashing and tripping my BRK handler. Oh well, onward and forward, right?


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 9:43 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
Hi - I think your starting point was code which inherited some 20 bugs from the original 6502asm.com emulator, so I recommend you try to inherit the fixes, or run Klaus' testsuite and find them yourself!

For example, see the changes dating from the beginning of August in https://github.com/BigEd/6502js/commits/master

Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 4:23 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1683
Location: Sacramento, CA
halkun wrote:
AUGH!!!! I FIGURED IT OUT!!!! It *WAS* a bad JMP command. evidently, I can't read instructions properly!

You add X to the address that is read after the opcode, not added the PC after the jump
The correct command implementation

Code:
   case 0x7c:                      // JMP INDIR,X
      value = popWord();
      value = value + regX;
      if (value > 0xFFFF) {value = value - 0xFFFF;}
      addr = memReadByte(value) + (memReadByte(value+1)<<8);
      regPC = addr;
      break;


System's running OK now, the assembler is printing out WAY to many spaces, which means I have another opcode to fix somewhere. I'm going to turn TSB back on and see if it works OK. Good news is that I can now somewhat code directly on the device and test opcodes as they run. That's pretty pimp.

=== EDIT ===
Yup TSB is broken, I'm using the NMOS way of doing it. I have a feeling I botched another indexer too. Some functions are hard-crashing and tripping my BRK handler. Oh well, onward and forward, right?


Glad to hear you fixed it. However, your fix needs a little tweak to be 100% accurate. If value after adding X is > 0xffff, then you need to subtract 0x10000, not 0xffff. You could also just do a bitwise AND to adjust it.

If that is not enough, what about the case where value could equal 0xffff. The low byte comes from 0xffff but the high byte would come from 0x0000!

Here is the fix I suggest:

Code:
case 0x7c:                      // JMP INDIR,X
      value = (popWord() + regX) & 0xFFFF;  /* fixes value > 0xFFFF */
      addr = memReadByte(value) + (memReadByte((value+1) & 0xFFFF)<<8);  /* fixes result when value = 0xFFFF */
      regPC = addr;
      break;


When you say the assembler is printing out way too many spaces, what do you mean? Can you show an example?

thanks!

Daryl

_________________
Please visit my website -> https://sbc.rictor.org/


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 7:20 pm 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
The output looks like this....

Code:
65C02 Monitor v5.1.1 (12-02-12) Ready
By Lee Davison and Joshua Walker
(Press ? for help)
>E800
E800 - 4C
 4C E9 4C 88 E8 4C B9 - E8 4C B6 E8 4C B1 E8 4C
>L
BDDC-  ~^.                                                                                                                                                                                                                                                            FE 5E 15                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 INC  $155E,X
BDDF-  l..                                                                                                                                                                                                                                                            6C 0E 1C                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 JMP  ($1C0E)
BDE2-  .                                                                                                                                                                                                                                                              83                 

and the relvant chunk of code
Code:
               JSR   Print2Byte        ; print address
               LDA   #$2D              ;  "-"
               JSR   Output            ;
               JSR   Print2SP          ; print "  "
               LDX   #$01              ;---------
List4:          LDY   #$00              ;print up to 3 ascii chars...
List5:          CPY   HexDigCnt         ;  two spaces...
               BCS   List6             ;  up to three hex chars...
               LDA   (StartAddr),Y     ;  two spaces
               CPX   #$00              ;
               BNE   List8             ;
               JSR   Print1Byte        ;
               BRA   List7             ;
List6:          CPX   #$00              ;
               BNE   List7             ;
               JSR   Print2SP          ;
List7:          LDA   #$20              ; " "
List8:          AND   #$7F              ;
               CMP   #$7F              ;
               BEQ   List9             ;
               CMP   #$20              ; " "
               BCS   List10            ;
List9:          LDA   #$2E              ; "." use "." if not printable char
List10:         JSR   Output            ;
               INY                     ;
               CPY   #$03              ;
               BCC   List5             ;
               JSR   Print2SP          ;


I'm going to bet it's that indexer again :P


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 8:22 pm 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
BigEd wrote:
Hi - I think your starting point was code which inherited some 20 bugs from the original 6502asm.com emulator, so I recommend you try to inherit the fixes, or run Klaus' testsuite and find them yourself!

For example, see the changes dating from the beginning of August in https://github.com/BigEd/6502js/commits/master

Cheers
Ed


I'm going through that code now... I'll have to translate the java into C++ to merge the changes...

The problem with Klaus' test suite is that it makes the assumption there is some kind of tracer or stepping app outside the emulator that you can control. I don't have that luxury. Once I "Burn" a 6502 program onto the Arduino's AVR, I have no way to control the executing 6502 code or see what it's doing without the code itself outputting something to my little 16x2 display. (It can output out the serial connection too, that that's often busy running the code proper).

I'm running an emulator on an AVR, and the emulation code must fit a maximum of 256k (ROM) and only use 32k of ram. The actual memory map for the AVR looks like this.

0000-7FFF - AVR registers, stack, and Emulation variables
8000-FFFF - 6502 memory

The the space from 8000-FFFF is actually a 32k window and I can bank in and out of the 512K ram add-on. This means that the bottom half is mapped like this.

AVR RAM: 8000-FFFF (bank 0)
is equal to
6502 RAM: 0000-7FFF

and

AVR RAM: 8000-FFFF (bank 1)
is equal to
6502 RAM: 8000-FFFF

Did I mention that this ram is also not protected and I can overrun my emulation variables and stack into my 6502 memory space :)
So I don't have a lot of space to mess around in. It's also why the original Arduino emulation core only held 1024 bytes. Actually, I'm really quite shocked that this is running at all. I've made so many assumptions about how AVR works and how 6502 code runs, it shouldn't even be working. But now that It's halfway there, I guess I'm committed now.


Last edited by halkun on Sun Dec 09, 2012 8:31 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 8:28 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1683
Location: Sacramento, CA
If the data at address $BDDC is FE 5E 15 then the "indexer" is working fine.

Hexdigitcnt is set to the # of bytes in this opcode ( 1-3).
The code uses the X reg as a flag to print either the ASCII character or the Hex value.
The Y register is an index to the memory, where Startaddr points to the opcode.
X is set to 1 at the start - this sets up the printing of the ASCII characters.

The address get printed ok, as does the - after it and 2 spaces.

Next, I see the ASCII character are printed - this happens when
Code:
               CPX   #$00              ;
               BNE   List8             ;

jumps to List8. Good so far.

It seems to have a problem determining when to quit that part so it can do the DEX (below List10 - not shown)
Code:
               JSR   Print2SP          ;
               DEX                     ;
               BEQ   List4             ;---------

to start printing the HEX values. While stuck, it prints spaces.

After much scanning, here is my suggestion:

Check that you CPY command is setting the C flag. It is for sure setting the Z flag or other routines would be failing. List5 and just after List10 are the only two places in the entire source that CPY is followed by BCC or BCS. There are some BPL/BMI that use CPY so be sure the N flag is being adjusted too.

Let me know if that helps!

Daryl

_________________
Please visit my website -> https://sbc.rictor.org/


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 10:51 pm 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
I'm re-porting over the Java core with all the fixes. The current version is kind of a mess and I see where there are lots of improvements that need to be taken care of. I have a feeling when this is done, everything's going to be running much smoother.

or crumble under it's own weight

One of the two. Let's keep our fingers crossed :)


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 09, 2012 11:50 pm 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
Well, that's interesting, while unifying the comparators, all of them broke, which means there was something systematically wrong with them. Now to put it back together again. So much fun.


Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 10, 2012 1:10 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
You might be interested, or horrified, to see my emulator written in ARM assembly, where I tried to factor out as much commonality as I could - the result is very deeply nested macros.
https://github.com/BigEd/a6502/blob/master/emulator.S

My inspiration is Ian Piumarta's lib6502 core, written in C:
http://www.piumarta.com/software/lib650 ... /lib6502.c
and similarly dense with #defines - although his is the tidier code by a long way.

Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 10, 2012 2:04 am 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
Oh no, I'm happy programming my AVR in simple C.

Going through the code, I have discovered the opcodes that "kind of worked" and while reimplementing, broke them all the way. The comparators, bit testers, and bit shifters are now all broken, but better to have them broken then to have them sort of work. The cool thing is they have common core functions, so one I fix that, everything downstream will start working again.

In theory anyway.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 60 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


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: