Z80 emulation
- Christuserloeser
- Moderator
- Posts: 5948
- https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
- Joined: Thu Aug 28, 2003 12:16 am
- Location: DCEvolution.net
- Has thanked: 10 times
- Been thanked: 0
- Contact:
- Stef.D
- DCEmu Respected
- Posts: 114
- Joined: Wed Oct 15, 2003 1:46 am
- Has thanked: 0
- Been thanked: 0
- Contact:
Thanks for the link the core is really advanced but 20 Mhz isn't that much for an ASM core. It's a good base for anyone who want to do a fast Z80 asm core, we can easily improve speed of this core by replacing the functions pointers table by a simple jump table and remove the call for each fetch but right now, this core shouldn't be really faster than actual C core.DcSteve wrote:Sayten himself gave me the link to his unfinished z80 sh4 core. It has a basic exec loop, and has ~ 1/2-2/3 of the opcodes implemented. He didn't implement opcodes as he needed them. He took the opcode list for the z80 and started at the top and worked his way down. While he's tested what he's written and it seems to work ok, he hasnt actually used the core in anything real. Its not pretty or fast. Just a basic interpreted cpu emu. He figured max speed on a dc was about 20MHz. Here is his work.
http://www.wolfnet.org/~jkf/dc/src/dc_z80.tar.gz
On my side, i prefer to stay with C, i believe it's possible to have a 40/50 Mhz Z80 even with a C core
-
- DC Developer
- Posts: 453
- Joined: Thu May 16, 2002 8:29 am
- Location: ice88's house
- Has thanked: 0
- Been thanked: 0
- Contact:
Stef,
I made an initial stab at doing z80 work with a jump table - it's working but I have only implemented a fraction of the opcodes at the moment .
How do you remove the call for each fetch though? I will carry on with my hack - I'm sure yours will be much better - but I don't see how you can eliminate the fetch. One thought I had is to use the much-maligned cache to speed things up - by pointing it at the location that represents the current PC for the z80 - will that help?
Anyway - any insight!
I made an initial stab at doing z80 work with a jump table - it's working but I have only implemented a fraction of the opcodes at the moment .
How do you remove the call for each fetch though? I will carry on with my hack - I'm sure yours will be much better - but I don't see how you can eliminate the fetch. One thought I had is to use the much-maligned cache to speed things up - by pointing it at the location that represents the current PC for the z80 - will that help?
Anyway - any insight!
Read my blog: http://unrational.blogspot.com
-
- Insane DCEmu
- Posts: 190
- Joined: Sun Jun 27, 2004 8:35 pm
- Location: stillwater, ok
- Has thanked: 0
- Been thanked: 0
- Contact:
looking at Sayten's code - isn't making a global pointer to a struct, allocating memory THEN access the stuct pointers members everytime you need to access registers or memory or ports a bit wasteful. i mean every time you access the variable "z80" it must be dereferenced and the the offset of the memeber in the struct must be calculated from the resulting address. THEN port_read and port_write are put into function pointers. depending on how often they are called, the more defrefencing for EACH call as well as the overhead for the function call itself.
- Stef.D
- DCEmu Respected
- Posts: 114
- Joined: Wed Oct 15, 2003 1:46 am
- Has thanked: 0
- Been thanked: 0
- Contact:
As i done in C68K : in a standard CPU emulator, you store the current PC of emulated cpu in a variable (register is better) we can just call "PC"Warmtoe wrote:Stef,
I made an initial stab at doing z80 work with a jump table - it's working but I have only implemented a fraction of the opcodes at the moment .
How do you remove the call for each fetch though? I will carry on with my hack - I'm sure yours will be much better - but I don't see how you can eliminate the fetch. One thought I had is to use the much-maligned cache to speed things up - by pointing it at the location that represents the current PC for the z80 - will that help?
Anyway - any insight!
Then when you need to fetch the next opcode (and opcode parameter) you'll have to read data at this address.
Since we execute code from this area, we can see it as a large memory space : RAM / ROM , this is the "fetch area".
Imagine we define fetch area as follow (for a Z80 CPU) :
0x0000-0x7FFF = rom_data
0xE000-0xFFFF = ram_data
(code can't be executed from IO port, that doesn't make sense.)
Well, the trick is that PC is equal to (cpu PC + fetch base)
Imagine we the following instruction : bra 0x450
with a conventionnal CPU core we only need to do :
...
NewPC = FetchWord;
PC = NewPC;
...
but here we'll do :
...
NewPC = FetchWord;
PC = FetchBase[NewPC >> X] + NewPC;
...
where FetchBase is a (0x10000 >> X) sized table containing Fetch base area (X can be 4-12, depending what we need).
Then when you need to fetch data, you only have to do :
data = *(u8*)PC; for byte
data = *(u16*)PC; for word
....
That make stuff a bit more complexe, since PC doesn't contain the real PC value, but it's a lot faster for fetch then
My english is really limited, i hope you can understand my explainations.
Edit : That trick about PC can also be done on SP (stack pointer) since we *normally* use it only to store datas in memory area (no ports), but imo it doesn't worth the effort.
Last edited by Stef.D on Wed Jul 07, 2004 9:22 am, edited 2 times in total.
-
- Insane DCEmu
- Posts: 190
- Joined: Sun Jun 27, 2004 8:35 pm
- Location: stillwater, ok
- Has thanked: 0
- Been thanked: 0
- Contact:
-
- Insane DCEmu
- Posts: 190
- Joined: Sun Jun 27, 2004 8:35 pm
- Location: stillwater, ok
- Has thanked: 0
- Been thanked: 0
- Contact:
-
- Modder Of Rage
- Posts: 805
- Joined: Mon Mar 18, 2002 12:41 pm
- Location: Midwest
- Has thanked: 0
- Been thanked: 0
- Contact:
warmtoe- how do you have sound working now? Does it still loop like it did in preview 3?
Check out the beats of rage community at http://borrevolution.vg-network.com/
-
- DC Developer
- Posts: 453
- Joined: Thu May 16, 2002 8:29 am
- Location: ice88's house
- Has thanked: 0
- Been thanked: 0
- Contact:
It still sucks - I'm not going to release it until it sucks a lot less - don't fret, it will get out - but it's just not worth it at the moment. Remember too that others are working on bits for this:-DcSteve wrote:warmtoe- how do you have sound working now? Does it still loop like it did in preview 3?
Stef. D is looking into the z80 emulation properly (unlike my hacking)
BlackAura has been looking at the graphics code some more.
It'll be worth the wait, trust me.
Read my blog: http://unrational.blogspot.com
-
- Insane DCEmu
- Posts: 190
- Joined: Sun Jun 27, 2004 8:35 pm
- Location: stillwater, ok
- Has thanked: 0
- Been thanked: 0
- Contact:
how much memory mapped i/o and interrupts does the z80 in the genesis have to deal with?
Last edited by Rev. Layle on Wed Jul 07, 2004 11:44 am, edited 1 time in total.
-
- Modder Of Rage
- Posts: 805
- Joined: Mon Mar 18, 2002 12:41 pm
- Location: Midwest
- Has thanked: 0
- Been thanked: 0
- Contact:
i think speud can help with saving like he did with neocd
Check out the beats of rage community at http://borrevolution.vg-network.com/
-
- Insane DCEmu
- Posts: 190
- Joined: Sun Jun 27, 2004 8:35 pm
- Location: stillwater, ok
- Has thanked: 0
- Been thanked: 0
- Contact:
-
- DC Developer
- Posts: 9951
- Joined: Sun Dec 30, 2001 9:02 am
- Has thanked: 0
- Been thanked: 1 time
Anything that's connected directly to the Z80 (the PSG and YM2612, I think) should be accessed through ports (Z80-based machines usually use ports). Anything that's connected to the 68k's address space (the PSG and YM2612 again, the VDP) uses memory mapped I/O (because the 68k doesn't have any ports).
-
- Insane DCEmu
- Posts: 190
- Joined: Sun Jun 27, 2004 8:35 pm
- Location: stillwater, ok
- Has thanked: 0
- Been thanked: 0
- Contact:
hmm, at least (well, to me, because i am no emulation expert) that port programming would be easier to emulate. with memory mapped i/o, you have to detect on EVERY memory write weather the write is going an i/o device or just regular memory (or even trying to write to a ROM portion which is read only)
- Stef.D
- DCEmu Respected
- Posts: 114
- Joined: Wed Oct 15, 2003 1:46 am
- Has thanked: 0
- Been thanked: 0
- Contact:
Unfortunatly nothing is connected to the Z80 IO ports on genesis :-/
All IO stuff (PSG, YM2612, VDP, bank register...) are directly mapped to memory if this was your question... so yeah, on memory writes and reads we have to test them.
< 0x4000 = RAM
0x60XX = bank register
0x70XX = IO ports (VDP, PSG, YM2612)
>= 0x8000 = banked area
But it's still a very simple memory map, test for ram first, then banked area and io port last...
All IO stuff (PSG, YM2612, VDP, bank register...) are directly mapped to memory if this was your question... so yeah, on memory writes and reads we have to test them.
< 0x4000 = RAM
0x60XX = bank register
0x70XX = IO ports (VDP, PSG, YM2612)
>= 0x8000 = banked area
But it's still a very simple memory map, test for ram first, then banked area and io port last...
-
- Insane DCEmu
- Posts: 190
- Joined: Sun Jun 27, 2004 8:35 pm
- Location: stillwater, ok
- Has thanked: 0
- Been thanked: 0
- Contact:
well poo - luckily you know which portion of memory has the memory mapped i/o - so you only have to test the first byte - then maybe have a second switch to test the second byte
something like
but i guess you have something like that already - maybe more optimized
edit: just read your post again, i guess you would want to test for RAM and banked area first becuase they are going to be hit the most. and (againe dit) come to think of it: a few "if"s may do the trick better and faster than the stupid shifts, ands, and swtiches i used.
is there anything in the 0x50XX range of memory?
something like
Code: Select all
// nAddr is unsigned int with memory address
unsigned int char nFirstByte = nAddr >> 8;
unsigned int nSecondByte = nAddr & 255;
switch (nFirstByte)
{
case 0x60:
switch (nSecondByte)
{
// do bank register stuff
}
break;
case 0x70:
switch (nSecondByte)
{
// i/o stuff here
}
break;
default:
if (nFirstByte <= 0x40)
// RAM
else
// banked area
}
edit: just read your post again, i guess you would want to test for RAM and banked area first becuase they are going to be hit the most. and (againe dit) come to think of it: a few "if"s may do the trick better and faster than the stupid shifts, ands, and swtiches i used.
is there anything in the 0x50XX range of memory?
Last edited by Rev. Layle on Thu Jul 08, 2004 10:34 am, edited 4 times in total.