davidgiven / cpm65

CP/M for the 6502
BSD 2-Clause "Simplified" License
261 stars 24 forks source link

Intel 8080 emulator #48

Open ivop opened 1 year ago

ivop commented 1 year ago

Hi,

Th last few days I have been working on this. Eventually I plan to run it on top of CP/M-65 to provide BIOS and possibly BDOS functionality. That would need some copying between 8080 and 6502 memory, for example for writestring if the string crosses a memory bank border. What do you think? I'm pretty excited about it. Something I'd wanted to do for years, emulating the 8080 on a 6502.

https://github.com/ivop/atari8080

Not sure how difficult it would be to port it to other systems, too. C64 REU is slow, but apparently there's also a 256kB banked memory upgrade. Master 128 sideways RAM has some limitations I believe, so that might not work or have less than 64kB for the 8080 environment. Apple 2e seems to have 48kB banks, so that'll probably work. You can even do the same BIT trick (see instruction fetcher in 8080.s) if you only use the lower 32kB of the bank and use two banks.

Regards, Ivo

Edit: I added a pre-assembled binary. Run with atari800 -xe 8080.xex.

davidgiven commented 1 year ago

Very nice --- what's the performance like? (I'm guessing, not great...)

Regarding memory access: it'd be nice to have something cross-platform. Traditionally CP/M does extended memory access via a ramdisk. Reading and writing blocks is pretty cheap, although much slower than access via banking, of course. I wonder if some kind of virtual memory would be feasible?

Thinking out loud:

That would be something like...

lda vaddr+1
and #0xc0
lsr a
lsr a
tax
lda mappings+1
beq no_mapping
clc
lda vaddr+0
adc mappings+0, x
sta paddr+0
lda vaddr+1
and #0x3f
adc mappings+1, x
sta paddr+1
<derefence paddr here>

That's.. not that bad? It's more work than your current code but it's portable. Coming up with a cache eviction strategy would be tricky. LRU would require overhead for every memory access, but apparently some ARM chips would just evict a block at random and that was considered good enough...

ivop commented 1 year ago

I'm afraid that will slow things down by at least a factor of two, not counting the load and save times to ramdisk. Most optimizations that I use can't be used, like the msb_to_bank and msb_to_adjusted tables, and checking for end of bank with the BIT instruction. Checks and adjustments that have to be done for almost each memory read or write (end-of-bank only during the optimized instruction fetcher).

But I see your point. It would be nice to have a cross-platform 8080.COM but IIUIC that would offload the bankswitching to a platform dependent ramdisk driver. IMHO it's better to keep the platform dependent code as close to the emulation as possible. It's slow enough as it is. Although it's faster than I had expected, I do not have a number yet. I need a proper benchmark program that I can run on a 2MHz or 4MHz 8080 and on the emulator to see how it performs. Do you know about such program?

I think I'll keep the bankswitching in for now. Later, if there's multiple drives and ramdisk support we can always change it or make it optional.

Regards, Ivo