[comp.sys.amiga.emulations] CPU-emulators

iheitla@cs.vu.nl (Ilja Heitlager) (04/08/91)

I'm writing to this group 'cause (As far as I know) it's the only group for
emulations.
I'm planning to write a 6502 (and maybe when I like it some others) emulator.
I know that there are more of these emulators, but I want to do it myself.
I want to do it in C or Assembly. 

At this moment I think there are two ways of doing it:
	1- Compare every Opcode and jump to a routine which executes the
	   instruction
	2- Do it more or less the way the microcode does it.
	   Ok in software you can't do more operations at the same moment.
	
Questions:
	1- Is there any reaction on these ways.
	   (Or: I want to start a discussion)
	2- Are there any books about 6502, Z-80, 8088 microcoding.
	   or is this real TOP-SECRET.
	3- Are there any books about microcoding at all.
	4- Any ftp-sites which have sources-codes of CPU-emulators.
	5- How do you handle memory usage (For memory-mapped IO).

The only knowledge I have is A. Tanenbaum's book "Structered Computer Organisation", a apple II+ emulator and some diggin' in the 6502 (binary) opcodes
So any reply would be welcome.

BTW. Is there a newsgroup for CPU-emulator programming.

Ilja, 

        ====================================================                  
	Ilja Heitlager          | 
	Vrije Universiteit      | E-Mail <iheitla@cs.vu.nl>
	Amsterdam               |
	The NetherLands.	|            
        =====================================================                 

Fletcher@cup.portal.com (fletcher sullivan segall) (04/09/91)

>
>At this moment I think there are two ways of doing it:
>	1- Compare every Opcode and jump to a routine which executes the
>	   instruction

This was discussed in depth just recently.

>	2- Do it more or less the way the microcode does it.
>	   Ok in software you can't do more operations at the same moment.
>	
Your emulation routines will essentially be the microcode of the processor.
Trying to emulate an intermediate processor would only slow the whole
thing down.

On the other hand, if you can rewrite the microcode in the 68000....

>Questions:
>	1- Is there any reaction on these ways.
>	   (Or: I want to start a discussion)
>	2- Are there any books about 6502, Z-80, 8088 microcoding.
>	   or is this real TOP-SECRET.

At least until the Z80-B, all Z80's were hard-coded.  I imagine this
is also true of the 6502.


                           -F. Sullivan Segall
_______________________________________________________________
 
/V\  E-Credibility:  (n -- ME) The unguaranteed likelyhood that
 '   the electronic mail you are reading is genuine rather than
someone's made up crap.
_______________________________________________________________
 
Mail to: ...sun!portal!cup.portal.com!fletcher or
         fletcher@cup.portal.com
 
 

srwmpnm@windy.dsir.govt.nz (04/09/91)

Ilja Heitlager (iheitla@cs.vu.nl) wrote:
>I'm planning to write a 6502 (and maybe when I like it some others) emulator.

Good on you!  I've played around with the Z80 emulators for the Amiga, by Ulf
Nordquist and Charlie Gibbs, making them faster.  I have never touched 6502 but
the same techniques should apply.

>At this moment I think there are two ways of doing it:
>	1- Compare every Opcode and jump to a routine which executes the
>	   instruction
>	2- Do it more or less the way the microcode does it.
>	   Ok in software you can't do more operations at the same moment.

I found at several more fundamentally different ways of doing it, and many
variations on those.  So far the fastest practical method seems to be threaded
code.  You can avoid decoding an opcode for every 6502 instruction altogether!
The emulation routine for each 6502 opcode ends with:

		move.l	(a3)+,a0
		jmp	(a0)

So each emulation routine jumps directly to the next emulation routine without
any decoding at all.  Register a3 is acts like a "pseudo pc" into a 256 kbyte
table in which there is a longword pointer to the emulation routine for each
corresponding opcode in the 64 kbyte 6502 address space.

Now, every time the 6502 writes to RAM, you need to update an entry in the
256 kbyte table.  At first it looks as if you have to do an instruction decode
to compute the new table value every time the 6502 writes to RAM.  But in fact
that is not necessary either!

What you do, when the 6502 writes to RAM, is to write a constant address into
the table.  That constant address points to a special routine called "patch".
When patch is called, you finally get to do an instruction decode.  Patch
computes the address of the routine for the current instruction, stuffs it
in the 256 kbyte table, then jumps to the routine for the current instruction.
Next time this instruction is executed, control bypasses patch and goes
directly to the right routine.

A variation of this method which saves memory but is slightly slower, is to use
word offsets in a 128 kbyte table, instead of longword addresses in a 256 kbyte
table.  Each routine ends with:

		move.w	(a3)+,d0
		jmp	0(a2,d0.w)

where a2 holds the base from which all the routine offsets are computed.

This method has more advantages:

1: To handle known ROM entry points, just point the vector for the entry point
at an optimised 68000 routine to do what the ROM routine does.  There is no
overhead at all in checking for ROM entry points.

2: To handle multiple-byte opcodes (e.g, prefix instructions), patch can be made
smart enough to point the vector for the prefix byte to the routine for the
entire instruction.  There is no need to decode opcodes after the prefix every
time the instruction is executed.

3: Patch can be made smart enough to recognise common sequences of 6502
instructions, and to point the vector at an optimised 68000 routine for the
whole sequence.

Note that 2 and 3 above (if implemented) won't correctly emulate certain types
of self-modifying code.

There was a good article on "Portable Fast Direct Threaded Code" by Eliot
Miranda in comp.compilers recently.  He uses GCC to write "machine independent"
threaded code that is just about as efficient as my 68000-specific code.

Hope this helps.  Regards, Peter McGavin.   (srwmpnm@wnv.dsir.govt.nz)