http://www.aros.orgAROS-ExecAROS-Exec ArchivesPower2People

Home

English

Česky

Deutsch

Ελληυικά

Français

Italiano

Nederlands

Polski

Português

Русский

Español

Suomi

Svenska


Neues

Archiv

Einleitung

Status
Screenshots
Portierungen
Lizens

Download


Dokumentation

Benutzer
Installation
Benutzung
Shell
Anwendungen
FAQ
Entwickler
Mitwirken
Roadmap
Fehlermeldung
Arbeiten mit Subversion
Kompilierung
Anwendungs Entwicklungs Handbuch
Zune Anwendungs Entwicklungs Handbuch
System Entwicklungs Handbuch
Debugging Handbuch
Referenz
Spezifikationen
Benutzeroberflächen Richtlinien
Dokumentierung
Portierung
Übersetzung
Zusammenfassungen
Links

Kontakt

Mailinglisten
IRC-Kanäle

Danksagung

Acknowledgements


Bilder

Entwickler
Entwicklertreffen

Sponsoren

Verlinkung

Links

Get AROS Research Operating System at SourceForge.net. Fast, secure and Free Open Source software downloads

Summary: M68k emulator

Abstract

This is a cut and paste summary of the "m68k emulator" thread on the aros-dev mailing list during Februari 2001.

Writing emulator for AROS to run native programs

AROS is pretty stable and pretty complete too, as far as I can see. There are tons of software out of there that are waiting fot being executed under our wonderful AmigaOS(tm) replacement, so why don't we allow them to have fun? :)

  • Emulator to be more compatible with Amiga computers.
  • Amiga computers have special custom chips.
  • Amiga computers uses 68k CPUs.
  • Allowing native Amiga apps running on AROS/i386 etc.
  • Emulator for bigendian and little endian machines.

Different types of software to emulate

  • Software using the hardware(games).
  • Software depending on Amiga 500 timings.
  • Software using bitplane formats for graphics.
  • System friendly software which uses features which are not easy to implement on other systems (copper, own viewports, 880K floppy disks).
  • Mostly system friendly software which uses some hardware 'hacks' like macros to disable interrupts/display.
  • System friendly software only avaible in binary format.
  • System friendly software avaible as sourcecode.

Emulator types

  • Interpreter
  • JIT
  • Compiler (compiling of whole executable before start)
  • It should be easy to use the system on different hardware (CPUs).

AROS kickstart/worbench for UAE

  • Only 68k binaries.
  • AROS in native code of machine
  • When UAE calls the setup routines of AROS, AROS must disable the emulation of all these parts of UAE that are not necessary (video chips, for example) and do these things directly.
  • When all chips have been disabled, we can switch of the code that tries to synchronize the virtual chips with the virtual CPU.
  • Rigth now, with the picasso emulation, all that you need to emulate are the cia's and paula. Is not that big effort. After the AHI emulation is finished it'll be necessary only the cia emulation.

Example:

  • m68k code calls OpenLibrary()
  • UAE read SysBase from virtual address 0x4
  • SysBase must point to real SysBase in AROS (which is always outside of UAEs virtual address space).

I see no way to make UAE work inside AROS under the assumption that UAE directly calls something in the AROS kernel.

You must prevent the chipset from running too fast. You could do this by using a timer so that the chipset stops when it doesn't need to run, but you would need a very high resolution timer, just like the cia's one, and not all computers have got it, specially the PC's. So, once again, you must synchronize the 68k with the chipset.

By running native code inside the 68k emulator you stop the emulation. The multitasking stops, the chipset emulation stops, ALL stop but the native code. It's not faster. Look at how picasso can slow down the whole emulation: it's coded using such a technique you mentioned.

Allowing native code to call 68k code?

How do we allow native AROS code to call 68k code without knowing it's 68k code?

  • Hooks.

  • Recompilation of 68k code? We could do that in the same way as the AmigaDE's VP does, the only difference would be that our VP code is the 68k code.

    We could do this only once and then store the translated software in a sort of cache. We could implement performance tracking, so that the code could get more optimized every time it's executed. We could use, in order to do this, a modified version of the UAE JIT compiler, with the help of the author, of course.

Last year I spent about three monts seeing how possible this is and wrote a small program that would convert 68K instructions into a C type language (sort of intermediate between C and 68K ASM). Then wrote another progam that would convert my intermediate lanugage into whatever code.

The big problem was that AmigaOS executable files are in some kind of weird structure that I don't really know with strange headers etc... secondly the code always assumes that it knows the hardware it's running on (with AROS this is not true), thirdly the code generated was always poor (large and slow executing).

My solution was to forget about using a translator. Instead I started on a Heuristic Amiga simulator, which would run the code and try and figure out what the code was trying to do then generate code (probably C) to do the same. The Amiga hardware could be changed for OS calls, so there would be no hardware problems. I am a chemist, not a computer sientist so I found the whole thing too hard to do and by this time my A1200 was failing so I gave up.

> [...] how do you handle the case in wich the 68k program tells to the OS > the address of a 68k routine to be executed by the OS later on? > The only viable solution that I see is the translation on load.

My solution to such a problem was to use the MMU to trap access to the Amiga hardware address range (about 2meg...) and then emulate the registers else where in memory (ie. an interupt with a handler to read the psuedo registers and then deal with the data in them correctly, maybe using code from UAE)

Besides, this could be handled using the mmu or the sigsegv exception under linux, just like the UAE JIT does.

Another possibility is to use the MMU. Emulated code pointers point to wrong memory in the native environment. The exception when this code is called will (re)start the interpretor/translator.

For now this would require the use of the mmap() function and so the emulator should, be part of the kernel, exec's perhaps. Later on we could use the mmu.hid, also to gain OS indipendency.

I know that JIT engines (UAE-JIT and Kaffe come to mind) use so-called "trampolines" to detect when a not-yet-translated subroutine is called. I'm sorry I don't know the details, but I'm sure the problem has been already solved.

Endianess is a concern but Georg made a proposal how to run m68k files on a little endian processor and switch between emulated and native execution. Hm, maybe some analyzer (disassembler) for m68k files would also be interesting and sufficient at the beginning to see whether this can be done. Can one for example avoid translating (= disassembling) hardcoded structures, i.e.

Endianess

For example if an 68k program would call OpenWindow. It gets back a pointer to a struct Window. If you only convert the Window Pointer to big endian then the 68k emu has the correct pointer, but the stuff in the structure is still all little endian. So if the 68k program reads something from this structure:

winwidth = window->Width;

then it will get the wrong value, because normal 68k emus are big endian.

The other problem (endianess) has been solved with C++ templates but they are not complete. We need someone with some time or a lot of C++ knowledge to fill the missing gaps:

int i;
ULONG a, b;

a = b;
i = a;

In the first case, there is no need for endianess conversion and in the second, there is. A C++ compile can figure this out but C can't (the developer has to and he better doesn't make any mistakes). I think with this technique, we have these advantages:

  • Compiler adds conversions only when necessary
  • Compiler warns about missing conversions (-> template defines no conversion). It simply cannot happen anymore that a necessary conversion is missing.
  • Much better readable.

Hmm :-

68k program:

struct NewWindow nw = {10,20,30, ...} /* DATA hunk */
win = OpenWindow(&nw);

Does this mean that the AROS native OpenWindow() when accessing the NewWindow structure must be prepaired that the newwindow might be big endian -> it must use some macro to access the fields?

NewWindow is a small problem, as it is only used by OpenWindow(). But what for example about struct Gadget. There is tons of AROS native code which deals (peeks inside structure) with gadgets.

Same with taglists.

Another problem:

68k program:

WORD var;

case IDCMP_MENUPICK:
    menuitem = ItemAddress();
    var = menuitem->MutualExclude;

Assuming the menuitem is native(little endian), because it was created with gadtools.library/CreateMenusA(). The 68k program above saves (stupid example) the menuitem's MutualExclude in a WORD (16 bit) variable, but the menuitem's MutualExclude field is actually LONG (32 bit). If you are lucky the 68k code looks like this:

move.l menuitem,a0
move.l MutualExclude(a0),d0
move   d0, var

but if you are unlucky it could look like this:

move.l menuitem,a0
move   MutualExclude+2(a0),var

Assuming menuitem->MutualExclude contains 0x00001234, then in little endian it is:

0x34 0x12 0x00 00

So your 68k emu in the unlucky case from above, will put "0" into var, instead of 0x1234.

To switch between native and emulated execution is not a problem. It could for example be done with an illegal m68k code in the jump tables where the emulator realizes that it has to execute i386 (or whatever) code now and has to pass the arguments in the registers to the function.

The problem is the endianness of the m68k program and the environment it is supposed to be running in. A NewWindow structure that is hard coded into the m68k program cannot be passed as is to the OpenWindow() function for example. All the data in the structure are in bi endian whereas the function expects them to be in little endian. So you would have to swap all data before you pass it to the function and swap it back when it returns from the OpenWindow(). Then what is returned by the OpenWindow() function is a pointer to a Window structure where all data are in little endian but here you must not swap the content since the system needs the content to be alright for its own purposes. The endianness really is the problem and I really also believe that AROS can have an emulator on a big endian (!) machine like PPC that would work just fine.

Disassemble Amiga binaries

  • Sometimes it works but often data and code is not seperated so it is not easy to decide what is a 68k command and what is data.
  • Some assumption about the compiler, compiler version and compiler options could be helpful.

I just finished an "intelligent" disassembler specialized into KickStart disassembly. The way it works is really simple : it follows the code and when an opcode like JSR, BSR, (cp)Bcc or (cp)DBcc is found, the address is saved in a stack. When a JMP or BRA is found, the disassembler's PC is loaded with the new address. And, when an RTS or RTE is found, the PC is loaded with the stack.

Digitials solution for this in their x86 emulator for Alpha CPUs was to run the code through a normal (step-by-step emulation) and "learning" what the code did (ie. converting it to Alpha code). When the code jumped to a place which already had been converted, the Alpha code was used directly. Maybe something we can learn from?

Copyright

Who owns the code generated?

The copyright would probably lie with the original owner. Anything automatic translation of a file should, I guess, be considered a mere a copy, if one stored in a rather unusual way.

Conclusion

An easy solution would be a 68k emulation for big endian machines only for 100% system friendly software which dont use any hardware features of AmigaOS but could be speeded up with a JIT plus kickstart/workbench in native format.

Then additional software could be supported with emulation (parts) of the Amiga hardware.

On little endian machines an AROS version which works internally always with big endian could be a (slow?) solution.


Copyright © 1995-2009, The AROS Development Team. All rights reserved.
Amiga®, AmigaOS®, Workbench und Intuition sind eingetragene Warenzeichen von Amiga Inc. Alle anderen Warenzeichen gehören dem jeweiligen Besitzer.