Dragon emulator written in Python ???

A place to discuss everything Dragon related that doesn't fall into the other categories.
jedie
Posts: 655
Joined: Wed Aug 14, 2013 12:23 pm
Location: germany
Contact:

Re: Dragon emulator written in Python ???

Post by jedie »

I implement more ops and the Indexed addressing modes: https://github.com/jedie/DragonPy/blob/ ... 09.py#L672

think there must be exist a few bugs :(

Current output:

Code: Select all

init 16384 Bytes ROM (0x8000 - 0xc000)
Read 16383Bytes from d32.rom into ROM 0x8000-0xbfff
init 32768 Bytes RAM (0x0 - 0x8000)
$b3ba *** new op code: $8e (LDX_immediate)
$b3bd addressing 'immediate word' value: $401 	| $b3bd: $a000-$bfff - CoCo - Color BASIC ROM
$b3bd LDX immediate: set $401 to index X |: $b3bd: $a000-$bfff - CoCo - Color BASIC ROM
$b3bd *** new op code: $6f (CLR_indexed)
$b3bf indexed addressing mode: postbyte: $83 == 10000011
$b3bf indexed addressing mode ea=$3ff
write $0 to: $3ff: $3ff - D64 - %PRNSEL% selects default printer port 0x00 Parallel, non-0x00 Serial (0x00)
$b3bf *** new op code: $30 (LEAX_indexed)
$b3c1 indexed addressing mode: postbyte: $1 == 00000001
$b3c1 LEAX indexed: set $402 to index X |: $b3c1: $a000-$bfff - CoCo - Color BASIC ROM
$b3c1 *** UNKNOWN OP $26
Opcode $26 seems to be a wrong value. Because i didn't find any information about this value.

I also didn't know where to start. Now i simply set the programm counter to $b3ba, see: https://github.com/jedie/DragonPy/blob/ ... 09.py#L398
Didn't know if this makes any sense...
... too many ideas and too little time ... Related stuff written in Python:
Dragon 32 emulator / PyDC - Python Dragon 32 converter: https://github.com/jedie/DragonPy
DWLOAD server / Dragon-Lib and other stuff: https://github.com/6809
User avatar
tormod
Posts: 416
Joined: Sat Apr 27, 2013 12:06 pm
Location: Switzerland
Contact:

Re: Dragon emulator written in Python ???

Post by tormod »

jedie wrote:$b3c1 LEAX indexed: set $402 to index X |: $b3c1: $a000-$bfff - CoCo - Color BASIC ROM
The comment should rather annotate $402 than $b3c1...
$b3c1 *** UNKNOWN OP $26[/code]

Opcode $26 seems to be a wrong value. Because i didn't find any information about this value.
Isn't that BNE? Those opcodes seems to almost have burned themselves into my memory from childhood :)

From a quick look at your cpu6809.py it seems that you have only implemented a few opcodes. How do you think it can work if you don't fill them in?
I also didn't know where to start. Now i simply set the programm counter to $b3ba, see: https://github.com/jedie/DragonPy/blob/ ... 09.py#L398
Didn't know if this makes any sense...
The CPU looks at the reset vector at $fffe when it is reset. On the Dragon/CoCo $fff0-$ffff is a mirror of $bff0-$bffe (I think the SAM does this). The emulator should do it the same way to work correctly with any ROM.

Get an overview of the 6809 command set. See "Inside the Dragon" for a start, then "Programming the 6809" for a more complete reference.

Note also how the 6809 opcodes are nicely and systematically laid out, and orthogonal with respect to addressing modes: Most opcodes work for all similar registers, and most address modes. So you have for instance LEAX, but also LEAY, LEAS and LEAU. And you have a sequence with opcodes on A, with the equivalents for B just offset with a multiple of 16: LDA # = $86 and LDB # = $C6 etc.
jedie
Posts: 655
Joined: Wed Aug 14, 2013 12:23 pm
Location: germany
Contact:

Re: Dragon emulator written in Python ???

Post by jedie »

tormod wrote:From a quick look at your cpu6809.py it seems that you have only implemented a few opcodes. How do you think it can work if you don't fill them in?
Yes, i implement the lastes "unknown" opcode... step-by-step... Maybe later i can merge some of the code...
tormod wrote:The CPU looks at the reset vector at $fffe when it is reset. On the Dragon/CoCo $fff0-$ffff is a mirror of $bff0-$bffe (I think the SAM does this). The emulator should do it the same way to work correctly with any ROM.
On which information does the SAM mirrored some memory segments? Does this exist somewhere in the ROM?
tormod wrote:Get an overview of the 6809 command set. See "Inside the Dragon" for a start, then "Programming the 6809" for a more complete reference.
Thanks. There exist many information around the 6809 and i have a few references... Too many references ;)
btw. Seems that this CPU used in some university for teaching, too.
tormod wrote:Note also how the 6809 opcodes are nicely and systematically laid out, and orthogonal with respect to addressing modes: Most opcodes work for all similar registers, and most address modes. So you have for instance LEAX, but also LEAY, LEAS and LEAU. And you have a sequence with opcodes on A, with the equivalents for B just offset with a multiple of 16: LDA # = $86 and LDB # = $C6 etc.
Yes, but code merging and refactoring is a later step for me...

EDIT: Opcode 0x26 seems to exist, see: https://github.com/jedie/XRoar/blob/mas ... 1177-L1188
... too many ideas and too little time ... Related stuff written in Python:
Dragon 32 emulator / PyDC - Python Dragon 32 converter: https://github.com/jedie/DragonPy
DWLOAD server / Dragon-Lib and other stuff: https://github.com/6809
jedie
Posts: 655
Joined: Wed Aug 14, 2013 12:23 pm
Location: germany
Contact:

Re: Dragon emulator written in Python ???

Post by jedie »

jedie wrote:Opcode 0x26 seems to exist
Implemented with https://github.com/jedie/DragonPy/commi ... 846#L0R902

I started to adoped the complete branch_cond() stuff from: https://github.com/jedie/XRoar/blob/mas ... #L546-L570 but it seems that there is some mismatched with information from "The 6309 Book"...

EDIT: Oh fuck :oops: I have mismatch 6309 and 6809 :roll:
... too many ideas and too little time ... Related stuff written in Python:
Dragon 32 emulator / PyDC - Python Dragon 32 converter: https://github.com/jedie/DragonPy
DWLOAD server / Dragon-Lib and other stuff: https://github.com/6809
jedie
Posts: 655
Joined: Wed Aug 14, 2013 12:23 pm
Location: germany
Contact:

Re: Dragon emulator written in Python ???

Post by jedie »

With https://github.com/jedie/DragonPy/commi ... e246b934a7 i hope to fixed the indexed addressing modes.
I have now looked into "Programming the 6809" and here: http://www.maddes.net/m6809pm/sections.htm#sec2_2_5_1
... too many ideas and too little time ... Related stuff written in Python:
Dragon 32 emulator / PyDC - Python Dragon 32 converter: https://github.com/jedie/DragonPy
DWLOAD server / Dragon-Lib and other stuff: https://github.com/6809
jedie
Posts: 655
Joined: Wed Aug 14, 2013 12:23 pm
Location: germany
Contact:

Re: Dragon emulator written in Python ???

Post by jedie »

Some commits later: https://github.com/jedie/DragonPy/compa ... .e06708126 looks the output like this:
init 16384 Bytes ROM (0x8000 - 0xc000)
Read 16383Bytes from d32.rom into ROM 0x8000-0xbfff
init 32768 Bytes RAM (0x0 - 0x8000)
$b3ba *** new op code: $8e (LD16)
$b3bd addressing 'immediate word' value: $401 | $b3bd: $a000-$bfff - CoCo - Color BASIC ROM
$b3bd get_ea16(): ea: $401 accessed by immediate_word (op:$8e) | $401: $400-$5ff - Default Text screen
$b3bd LD16 load register index_x from $401 | $401: $400-$5ff - Default Text screen
$b3bd *** new op code: $6f (CLR_indexed)
$b3bf indexed addressing mode: postbyte: $83 == 10000011
$b3bf indexed addressing mode ea=$3ff | $3ff: $3ff - D64 - %PRNSEL% selects default printer port 0x00 Parallel, non-0x00 Serial (0x00)
**** write $0 to $3ff - mem info:
$0: $0 - BREAK message flag - if negative print BREAK
$3ff: $3ff - D64 - %PRNSEL% selects default printer port 0x00 Parallel, non-0x00 Serial (0x00)
$b3bf *** new op code: $30 (LEAX_indexed)
$b3c1 indexed addressing mode: postbyte: $1 == 00000001
$b3c1 LEAX indexed: set $402 to index X |: $b3c1: $a000-$bfff - CoCo - Color BASIC ROM
$b3c1 *** new op code: $26 (BNE)
$b3c2 BNE: set pc to $b3c4: $b3c4: $a000-$bfff - CoCo - Color BASIC ROM
$b3c4 *** new op code: $ba (ORA_extended)
$b3c7 addressing 'extended indirect' value: $776f | $776f: UNKNOWN
$b3c7 ORA extended: set A to $776f ($0 | $776f) | $776f: UNKNOWN
**** Set cc overflow from 8-bit accumulator A, value: $776f
^^^^ Value for A truncated to $6f

$b3c7 *** new op code: $80 (SUBA_immediate)
$b3ca addressing 'immediate word' value: $9f19 | $b3ca: $a000-$bfff - CoCo - Color BASIC ROM
$b3ca ORA extended: set A to $-9eaa ($6f - $9f19) | $9f19: $8000-$9fff - CoCo - Extended Color BASIC ROM
$b3ca *** new op code: $a6 (LD8)
$b3cc indexed addressing mode: postbyte: $2 == 00000010
$b3cc get_ea16(): ea: $404 accessed by indexed (op:$a6) | $404: $400-$5ff - Default Text screen
$b3cc *** UNKNOWN OP $43
But makes no sence, that the 8-bit accumulator A should be set to $776f (a value in 16-bit range) ?!?

I have made the accumulators as a object and check the overflow in get methods, see: https://github.com/jedie/DragonPy/blob/ ... ors.py#L20
Don't know if that's the right way.

I also seperate the "condition code register bits" here: https://github.com/jedie/DragonPy/blob/ ... ter.py#L43
There are some FIXME comments, because i think is doesn't work as aspected.
In a unittests, a faked additional, the overflow flag would not be set.

Code: Select all

        a = 0xff
        b = 1
        r = a + b
        self.cpu.cc.set_NZVC8(a, b, r)
        self.assertEqual(self.cpu.cc.N, 0)
        self.assertEqual(self.cpu.cc.Z, 1)
        self.assertEqual(self.cpu.cc.V, 1) # FIXME
        self.assertEqual(self.cpu.cc.C, 0)
see: https://github.com/jedie/DragonPy/blob/ ... py#L73-L80

Seems that V = 1 if (a ^ b ^ r ^ (r >> 1)) & 0x80 else 0 is not ok?!?

A simple test:

Code: Select all

for a in xrange(254, 258):
    print "a=", a
    b = 1
    print "b=", b
    r = a + b
    print "r= a + b =", r, "=",hex(r)
    V = 1 if (a ^ b ^ r ^ (r >> 1)) & 0x80 else 0
    print "V=",V
    print "(a ^ b ^ r ^ (r >> 1)) & 0x80=", (a ^ b ^ r ^ (r >> 1)) & 0x80
    print
Output:

Code: Select all

a= 254
b= 1
r= a + b = 255 = 0xff
V= 0
(a ^ b ^ r ^ (r >> 1)) & 0x80= 0

a= 255
b= 1
r= a + b = 256 = 0x100
V= 0
(a ^ b ^ r ^ (r >> 1)) & 0x80= 0

a= 256
b= 1
r= a + b = 257 = 0x101
V= 1
(a ^ b ^ r ^ (r >> 1)) & 0x80= 128

a= 257
b= 1
r= a + b = 258 = 0x102
V= 1
(a ^ b ^ r ^ (r >> 1)) & 0x80= 128
r = 256 is a overflow, isn't it?
... too many ideas and too little time ... Related stuff written in Python:
Dragon 32 emulator / PyDC - Python Dragon 32 converter: https://github.com/jedie/DragonPy
DWLOAD server / Dragon-Lib and other stuff: https://github.com/6809
sixxie
Posts: 1346
Joined: Fri Jul 18, 2008 8:36 am
Location: Hertfordshire
Contact:

Re: Dragon emulator written in Python ???

Post by sixxie »

The flag indicates signed overflow:

When you add 255 + 1, you're actually adding -1 and 1, which does not overflow.

Annoyingly, I discovered that the 6809's overflow flag operates differently to, say, the ARM one - which meant my idea of performing all the operations in ARM assembly by shifting things 24 bits left, performing the op, then getting the flags "for free" fell a bit flat ;)
jedie
Posts: 655
Joined: Wed Aug 14, 2013 12:23 pm
Location: germany
Contact:

Re: Dragon emulator written in Python ???

Post by jedie »

It it's allways a signed overflow? So, adding a number bigger than 8bit to a 8bit register, will not set the overflow flag?
... too many ideas and too little time ... Related stuff written in Python:
Dragon 32 emulator / PyDC - Python Dragon 32 converter: https://github.com/jedie/DragonPy
DWLOAD server / Dragon-Lib and other stuff: https://github.com/6809
sixxie
Posts: 1346
Joined: Fri Jul 18, 2008 8:36 am
Location: Hertfordshire
Contact:

Re: Dragon emulator written in Python ???

Post by sixxie »

jedie wrote:It it's allways a signed overflow? So, adding a number bigger than 8bit to a 8bit register, will not set the overflow flag?
Well I'm not sure how you'd even do that...

Whatever two 8-bit numbers you add, for the purposes of the overflow flag they're considered signed, i.e., in the range -128 to +127. If the result goes over 127 or under -128, it's an overflow. Of course as it's all two's complement, you can still go and treat the operands and the result as unsigned values and ignore V.
jedie
Posts: 655
Joined: Wed Aug 14, 2013 12:23 pm
Location: germany
Contact:

Re: Dragon emulator written in Python ???

Post by jedie »

I will start a new implementation.

I hacked some data scraping scripts: https://github.com/jedie/DragonPy/commi ... 5f6e75d903

These script will collect information from:
http://www.maddes.net/m6809pm/sections.htm#sec4_4
http://www.burgins.com/m6809.html
http://www.maddes.net/m6809pm/appendix_a.htm#appA

With the scraper i will create a "python script data file" with all merged data. Something like a poorman database :oops:
Will look like this:

Code: Select all

OP_DATA = (

    #### 8-Bit Accumulator and Memory Instructions

    {
        "opcode": 0x0, "instruction": "NEG", "mnemonic": "NEG", 
        "desc": "Negate accumulator or memory",
        "addr_mode": 1, "operant": None,
        "cycles": "6", "bytes": "2", "HNZVC": "uaaaa", "category": 0
    },
    {
        "opcode": 0x3, "instruction": "COM", "mnemonic": "COM", 
        "desc": "Complement accumulator or memory location",
        "addr_mode": 1, "operant": None,
        "cycles": "6", "bytes": "2", "HNZVC": "-aa01", "category": 0
    },
    {
        "opcode": 0x4, "instruction": "LSR", "mnemonic": "LSR", 
        "desc": "Logical shift right accumulator or memory location",
        "addr_mode": 1, "operant": None,
        "cycles": "6", "bytes": "2", "HNZVC": "-0a-s", "category": 0
    },
...
Then i started to create a "make skeleton" script. To create something like this, automatic:

Code: Select all

class CPU6809(object):

    #### 8-Bit Accumulator and Memory Instructions

    # ADC - Add memory to accumulator with carry
    @opcode((
        0x89, "ADCA", IMMEDIATE, operant=A
        0x99, "ADCA", DIRECT, operant=A
        0xa9, "ADCA", INDEXED, operant=A
        0xb9, "ADCA", EXTENDED, operant=A
        0xc9, "ADCB", IMMEDIATE, operant=B
        0xd9, "ADCB", DIRECT, operant=B
        0xe9, "ADCB", INDEXED, operant=B
        0xf9, "ADCB", EXTENDED, operant=B
    ))
    def ADC(self, op, ea=None, operant=None):
        raise NotImplementedError("TODO: $%x ADC") % op

    # ADD - Add memory to accumulator
    @opcode((
        0x8b, "ADDA", IMMEDIATE, operant=A
        0x9b, "ADDA", DIRECT, operant=A
        0xab, "ADDA", INDEXED, operant=A
        0xbb, "ADDA", EXTENDED, operant=A
        0xcb, "ADDB", IMMEDIATE, operant=B
        0xdb, "ADDB", DIRECT, operant=B
        0xeb, "ADDB", INDEXED, operant=B
        0xfb, "ADDB", EXTENDED, operant=B
    ))
    def ADD(self, op, ea=None, operant=None):
        raise NotImplementedError("TODO: $%x ADD") % op

    # AND - AND memory with accumulator
    @opcode((
        0x84, "ANDA", IMMEDIATE, operant=A
        0x94, "ANDA", DIRECT, operant=A
        0xa4, "ANDA", INDEXED, operant=A
        0xb4, "ANDA", EXTENDED, operant=A
        0xc4, "ANDB", IMMEDIATE, operant=B
        0xd4, "ANDB", DIRECT, operant=B
        0xe4, "ANDB", INDEXED, operant=B
        0xf4, "ANDB", EXTENDED, operant=B
    ))
    def AND(self, op, ea=None, operant=None):
        raise NotImplementedError("TODO: $%x AND") % op

...
... too many ideas and too little time ... Related stuff written in Python:
Dragon 32 emulator / PyDC - Python Dragon 32 converter: https://github.com/jedie/DragonPy
DWLOAD server / Dragon-Lib and other stuff: https://github.com/6809
Post Reply