Welcome to Emulationworld

Forum Index | FAQ | New User | Login | Search

Make a New PostPrevious ThreadView All ThreadsNext Thread*Show in Threaded Mode


SubjectSome 68k questions new Reply to this message
Posted byerikduijs
Posted on08/03/04 10:55 AM



I'm trying to write an 68k emulator and I'm wondering about a few things.

* Is there any reference available where I can find how many cycles the instructions take? I couldn't find it in the motorola programmer's reference. Can I cheat here a bit?

* Since I want to use it primarily for arcade emulation, are there some things in the 68k which are almost never used (so I can make life a bit easier at first :-) ?

* What is a good arcade game to start with, so a simple to emulate yet fun machine? So that I won't have to torture myself trying to get Galaxy Force to show anything, you know... :-)

Thanks,
Erik




SubjectRe: Some 68k questions new Reply to this message
Posted byJan_Klaassen
Posted on08/03/04 02:13 PM



> I'm trying to write an 68k emulator and I'm wondering about a few things.
>
> * Is there any reference available where I can find how many cycles the
> instructions take? I couldn't find it in the motorola programmer's reference.
> Can I cheat here a bit?

There is documentation, a document (available as .pdf file) named M68000 (fill in the rest of the series too) 8/16/32bit Microprocessor User's Manual. It has all the timing info, have fun with the multiply instructions (as soon as you see the description for those, you will start to cheat a bit). ;)

> * Since I want to use it primarily for arcade emulation, are there some things
> in the 68k which are almost never used (so I can make life a bit easier at first
> :-) ?

Yes, you can avoid dealing esoteric details like the way multiple memory spaces are supported without any adverse consequences for arcade emulation (or 99.99% of any emulation). You can also neglect the prefetch on the 68K (though you'll need it for e.g. Amiga or Atari ST emulation). You can avoid other (fairly) esoteric stuff like trace mode or alignment exceptions as well.

> * What is a good arcade game to start with, so a simple to emulate yet fun
> machine? So that I won't have to torture myself trying to get Galaxy Force to
> show anything, you know... :-)

I wouldn't know a good example, though there definately are some. Maybe Biomechanical Toy?




SubjectRe: Some 68k questions Reply to this message
Posted byBart T.
Posted on08/03/04 02:23 PM



> Yes, you can avoid dealing esoteric details like the way multiple memory spaces
> are supported without any adverse consequences for arcade emulation (or 99.99%
> of any emulation). You can also neglect the prefetch on the 68K (though you'll
> need it for e.g. Amiga or Atari ST emulation). You can avoid other (fairly)
> esoteric stuff like trace mode or alignment exceptions as well.

And to add to that: Emulate instructions and features as you encounter them. Run your emulator until you hit an unimplemented opcode, add it in, rinse, lather, repeat.


> > * What is a good arcade game to start with, so a simple to emulate yet fun
> > machine? So that I won't have to torture myself trying to get Galaxy Force to
> > show anything, you know... :-)
>
> I wouldn't know a good example, though there definately are some. Maybe
> Biomechanical Toy?

One word: Food Fight.



SubjectRe: Some 68k questions new Reply to this message
Posted byR. Belmont
Posted on08/03/04 07:35 PM



> And to add to that: Emulate instructions and features as you encounter them. Run
> your emulator until you hit an unimplemented opcode, add it in, rinse, lather,
> repeat.

Lemme just back up Bart here - everyone's first mistake when writing a CPU emulator is just to implement all the opcodes and *then* test it. Don't ever do that, it makes it nearly impossible to debug :-)





SubjectRe: Some 68k questions new Reply to this message
Posted byerikduijs
Posted on08/04/04 03:05 AM



> > And to add to that: Emulate instructions and features as you encounter them.
> Run
> > your emulator until you hit an unimplemented opcode, add it in, rinse, lather,
> > repeat.
>
> Lemme just back up Bart here - everyone's first mistake when writing a CPU
> emulator is just to implement all the opcodes and *then* test it. Don't ever do
> that, it makes it nearly impossible to debug :-)
>

Yeah, I know. I made that mistake once with my Z80 core. Never again :-)




Subjectoh my gawd... new Reply to this message
Posted byerikduijs
Posted on08/04/04 03:29 AM



It is a difficult one to implement. I've only seen one example written in java and that one had a generated source (almost 4Mb of sheer uglyness).
I am *trying* to do it with a more generic OO approach and less code, but man it's not an easy one. Since many instructions seem to have many different combinations in operands and addressing modes, I'm trying to do something with an Operand interface which I can use for the registers, the effective address, a pointer to memory etc. That way I hope to be able to create for example all ADD opcodes by creating the correct Operands in the constructor of the ADD class, so that the instruction can basically always do 'void add(Operand, Operand)' then. The Operands could be the EA, a register or anything else. Would that be a sensible approach? Any remarks here?




SubjectRe: Some 68k questions new Reply to this message
Posted byElSemi
Posted on08/04/04 05:11 AM



> > And to add to that: Emulate instructions and features as you encounter them.
> Run
> > your emulator until you hit an unimplemented opcode, add it in, rinse, lather,
> > repeat.
>
> Lemme just back up Bart here - everyone's first mistake when writing a CPU
> emulator is just to implement all the opcodes and *then* test it. Don't ever do
> that, it makes it nearly impossible to debug :-)
>

Heh, so you mean all I've done it the wrong way in all my CPU emulation cores? :)







SubjectRe: Some 68k questions new Reply to this message
Posted byfinaldave
Posted on08/04/04 05:42 AM



> I'm trying to write an 68k emulator and I'm wondering about a few things.
>
> * Is there any reference available where I can find how many cycles the
> instructions take? I couldn't find it in the motorola programmer's reference.
> Can I cheat here a bit?

I'd quite like to know this as well, since I end up scraping together bits and pieces!

> * Since I want to use it primarily for arcade emulation, are there some things
> in the 68k which are almost never used (so I can make life a bit easier at first
> :-) ?
>
> * What is a good arcade game to start with, so a simple to emulate yet fun
> machine? So that I won't have to torture myself trying to get Galaxy Force to
> show anything, you know... :-)

I'd actually start with a console game instead: Sonic the Hedgehog on the MD is quite easy to get up and running.
If it's has to be an arcade game, TMNT was fairly straightforward in retrospect. Or maybe CPS1?

>
> Thanks,
> Erik
>


You learn something old everyday...



SubjectRe: Some 68k questions new Reply to this message
Posted byerikduijs
Posted on08/04/04 05:48 AM



> Heh, so you mean all I've done it the wrong way in all my CPU emulation cores?
> :)
>

Show-off ;-)





SubjectRe: oh my gawd... new Reply to this message
Posted byBart T.
Posted on08/04/04 10:44 AM



> I am *trying* to do it with a more generic OO approach and less code, but man
> it's not an easy one.

I wonder if this is one of those cases where OO actually makes things more difficult. There are 68K emulators written entirely in C such as the one in MAME so you might want to give those a look.


----
Bart


SubjectRe: Link to user manual with timing info new Reply to this message
Posted byJan_Klaassen
Posted on08/04/04 12:21 PM



http://www.freescale.com/webapp/sps/library/documentationlist.jsp?rootNodeId=01&nodeId=018rH3YTLC4622&Device=MC68000&DocTypeKey=A0&Set=1&Results=25




SubjectRe: Some 68k questions new Reply to this message
Posted byRiff
Posted on08/04/04 03:16 PM



> > And to add to that: Emulate instructions and features as you encounter them.
> Run
> > your emulator until you hit an unimplemented opcode, add it in, rinse, lather,
> > repeat.
>
> Lemme just back up Bart here - everyone's first mistake when writing a CPU
> emulator is just to implement all the opcodes and *then* test it. Don't ever do
> that, it makes it nearly impossible to debug :-)
>

I don't think its strictly necessary that the test is done before all instructions are implemented and rather the important part is that the instruction set emulation is independently tested to some extent prior to debugging large applications.

My preference is to create a reasonably exhaustive test program which exercises all instruction forms and associated flag settings. This is a laborious task, to be sure, but with judicious use of macros and a structured test procedure, most of the work is reduced to calculating initial and expected values. This is a pretty boring task, so I don't expect it will be the only testing method used but such a program comes in extremely handy for regression testing.

This is my prefered method for implementing instruction handlers and testing functionality:

1) Implement load immediate and store immediate. Use a custom test jig to test all the instruction forms.

2) Implement jumps and branches. Again, implement all forms and step through custom test programs to make sure they work

3) Implement memory loads and stores. At this point, I'd ignore control registers that have side effects or otherwise behave differently from RAM.

4) Start implementing all of the other instructions, using custom test programs that are easily understood and have easily determined initial conditions at the point of test. The benefit of writing small test programs is that you don't have to spend time stepping through massive chunks of code that don't have anything to do with the test being performed.

When writing an exhaustive test program, you generally want to test that all instruction forms calculate the expected results for several operand combinations distributed throughout the valid operand domain. Boundary conditions and exceptional combinations are particularly important. The goal should be to obtain maximum coverage of the instruction handler code. You also want to catch "stuck-at" errors, particularly for flag calculations. This is usually done by setting initial values to the inverse of the expected results. A more difficult matter is testing that the final results get written to the desired location without modifying other parts of the processor state. Exhaustive testing would be a pain, but at least some testing should be done when chances for screw-ups are easily identified.

It would be interesting to hear how other people test their emulators. It seemed to me that many emulators are tested only when someone else reports a particular problem with a game or application. The stance often seems to be "we'll fix bugs when we find out about them" rather than doing the upfront work to test for correctness early on so that these situations occur less in the future.


SubjectRe: oh my gawd... new Reply to this message
Posted byerikduijs
Posted on08/04/04 06:00 PM



> > I am *trying* to do it with a more generic OO approach and less code, but man
> > it's not an easy one.
>
> I wonder if this is one of those cases where OO actually makes things more
> difficult. There are 68K emulators written entirely in C such as the one in MAME
> so you might want to give those a look.
>

Yes, I saw the MAME code. It looks mighty complex to me, but maybe that's just me :-)
I think I'll have a basic concept down, although I haven't implemented any instructions yet (except for ADD/ADDA). I'm still struggling to get the addressing modes down in a generic way, so I won't have to implement so many different versions of the same instruction, or have too many branches in one instruction.
I don't know yet what I will encounter, but I feel I'm headed in the right direction. Now only hope I get it running fast enough...




SubjectRe: Some 68k questions new Reply to this message
Posted byR. Belmont
Posted on08/04/04 06:42 PM



> Heh, so you mean all I've done it the wrong way in all my CPU emulation cores?
> :)

Did you ever find the bug that occurs when you emulate the geometrizer SHARC on 2B? If not, you have ;-)






SubjectRe: Link to user manual with timing info new Reply to this message
Posted byfinaldave
Posted on08/05/04 05:32 AM



http://www.freescale.com/webapp/sps/library/documentationlist.jsp?r> ootNodeId=01&nodeId=018rH3YTLC4622&Device=MC68000&DocTypeKey=A0&Set=1&Results=25
>


cheers!


You learn something old everyday...



SubjectRe: Some 68k questions new Reply to this message
Posted byfinaldave
Posted on08/05/04 05:43 AM



> > > And to add to that: Emulate instructions and features as you encounter them.
> > Run
> > > your emulator until you hit an unimplemented opcode, add it in, rinse,
> lather,
> > > repeat.
> >
> > Lemme just back up Bart here - everyone's first mistake when writing a CPU
> > emulator is just to implement all the opcodes and *then* test it. Don't ever
> do
> > that, it makes it nearly impossible to debug :-)
> >
>
> I don't think its strictly necessary that the test is done before all
> instructions are implemented and rather the important part is that the
> instruction set emulation is independently tested to some extent prior to
> debugging large applications.
>
> My preference is to create a reasonably exhaustive test program which exercises
> all instruction forms and associated flag settings. This is a laborious task,
> to be sure, but with judicious use of macros and a structured test procedure,
> most of the work is reduced to calculating initial and expected values.

That's personally not my cup of tea, because I'm lazy ;-)

Instead I use real programs. For example if I don't know how addx works yet, I leave it out of the core and wait till a real game I plan to run uses it. I then look at the docs on the opcode, and how it is being used.
I implement it exactly how the docs say, BUT as a sanity check make sure that the first usage of addx in the program gets the right result and flags. It's the mix of theory and practice which tends to give me the confident I have a good implementation.

I can't be 100% confident, but the confidence level is fairly high and it's a lot less work.

I'll put my hand up an admit that I do currently have a problem with ABCD or SBCD after using this method, but I'm sure I can solve it by stepping through Sword of Vermillion. Or I could always revert to a structures test procedure later.


You learn something old everyday...



SubjectRe: oh my gawd... new Reply to this message
Posted byR. Belmont
Posted on08/05/04 11:09 PM



MAME's code actually does something extremely smart for a processor as complex as the 68000: it's a generator. Meaning you write a program that outputs the actual emulator source in your desired language. That means you can generate the emulator in various configurations without ugly #ifdefs or the like, and it also reduces the chance of things like copy/paste typos.





SubjectRe: oh my gawd... new Reply to this message
Posted byerikduijs
Posted on08/08/04 05:57 PM



> MAME's code actually does something extremely smart for a processor as complex
> as the 68000: it's a generator. Meaning you write a program that outputs the
> actual emulator source in your desired language. That means you can generate
> the emulator in various configurations without ugly #ifdefs or the like, and it
> also reduces the chance of things like copy/paste typos.
>

Yes, that is smart :-)
I think STonX does something like that too.
What I'm trying to do is using OOP to create objects that will execute the instructions (from classes implementing an 'Instruction' interface, which is basically nothing more that 'void exec()'). The constructor of the Instruction classes will define how they will actually behave at runtime, ie it will set the size of a move, the istruction mode, the affected registers etc. In the end, the created objects will have no or almost no branches in their 'exec()' method. Then I create an array (of I think 1024) of all instruction objects at initialization, and do something like the following at runtime:

while (cyclesLeft > 0) {
int iw = fetchInstructionWord();
Instruction i = instructionArray[iw];
i.exec();
// do the rest here...
}

I think (hope) it's going to work out.




SubjectHere's another link that might be helpful new Reply to this message
Posted byerikduijs
Posted on08/13/04 07:31 PM



http://www.ticalc.org/pub/text/68k/




Previous ThreadView All ThreadsNext Thread*Show in Threaded Mode