Due to the discussion on the software emulation of other systems on the
MEGADEV mailing list, I am uploading this comp.sys.amiga.emulations
discussion which occured in 1991. It does contain quite a bit of useful
information and ideas for anyone interested in producing their own
emulators. It specifically concentrates on the 6502 and Z-80, although
the concepts are generally applicable for other systems as well.
Ian.
>From: jnmoyne@lbl.gov (Jean-Noel MOYNE)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <10652@dog.ee.lbl.gov>
>Date: 6 Mar 91 03:03:52 GMT
>Organization: Lawrence Berkeley Laboratory
>References:<4992@mindlink.UUCP> <1991Mar6.010141.5905@mintaka.lcs.mit.edu>
>
>
> Yes, insteresting indeed. I've _heard_ (i.e. don't quote me on
>that) that once a company did such a "application-translator", on unix.
>Where you could take an Ms/Dos exe file, and the program would generate a
>unix C source code, maping all the Ms/Dos int traps into legal unix os
>calls. I've heard this program was able to translate well-known commercial
>programs, and that these programs were able to run after that under normal
>unix multi-user configuration, the end of the story is that the people
>that made this soft could never even try to sell it (guess why).
>
> Anyway, doing such a thing wouldn't be impossible technically (but
>it'd be hard for sure ! (-:), especially for ms/dos programs. All these
>big softs are made to run on all the different flavors of IBM clones, that
>means they use no dirty tricks, they stick to BIOS calls so it'll run even
>on an Amstrad (or under the transformer or IBeM for instance). That means
>you could quite easily put all the BIOS ints in an Amiga shared lib, and
>taking the 8088 binary, generate C code from it. Programs a'-la
>"re-sourcer" allready exist, they take the .exe file, and generate a 8088
>source code file from it, at this point it's possible to generate a C
>source code that would do the same thing. You could optimise it to
>recognise patterns in the ASM instructions (don't forget most of these big
>programs, the one you're interested in to run on the Amiga, are usually
>written in C or some other high-level language, and so the binary is
>generated by a compiler, thus creating patterns ...), and eventually build
>a C source code not to far from the original (the guys who wrote Microsoft
>C could eventually write a reverse compiler that would generate a code
>very close to the original, and such a program wouldn't be machine
>dependent at all).
>
> An other problem who be to catch the busy wait loops in these
>mono-tasking programs (I think most of these loops are in the BIOS, like
>waiting for a key, easy to take care of). So these programs would be
>multitasking friendly, and so that you could eventually run more than one
>at the same time without loosing performance.
>
> Anyways, all this is my mind wandering sideways (I've thought
>about that before), and most of what I wrote is closer to dreams than to
>reality (and in bad English, sorry about that, still learning (-:). Mostly
>because, if it's not impossible to write such a program, it for sure very
>hard ! And so, it'll take a lot of time and effort, more than what a
>standalone guy doing that on the side of his regular job could invest. A
>team in a company could do it, but no company's gonna take such a risk,
>there's too much potential danger on that, even if the potential sales are
>very big ! Sure one could say that if you buy the original program, you
>should be able to run it ... even on another machine, but I'm sure the
>army of lawyers from let's say Microsoft or Aston-Tate would have
>something to say about that ! And they could sue you for years without
>sweat, preventing you from selling the program before the end of the
>trial... etc ... etc ...
>
> Eventually, if the program was freeware, written by a bunch of
>programers not earning money for it, this would be a different figure,
>much different. But I'm really no lawyer, I'm still thinking sideways ....
>(-:
>
>
> JNM
>
>--
>These are my own ideas (not LBL's)
>
>
>From: Chris_Johnsen@mindlink.UUCP (Chris Johnsen)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Emulator Mechanics (sorry long post)
>Message-ID: <4992@mindlink.UUCP>
>Date: 4 Mar 91 15:20:48 GMT
>Organization: MIND LINK! - British Columbia, Canada
>
>
> The following messages were shared in an email environment between Charlie
>Gibbs and myself over the last couple of days. We decided that it would be a
>good idea to share these thoughts with the readership of
>comp.sys.amiga.emulations. The messages speak for themselves for the most
>part.
>
> ------------ Included text of messages ------------
>
>Sun Mar 3 6:40:53 1991 From: Chris Johnsen [547] Subject : Emulators
>
>Hello Charlie! Long time no talk to you eh? I haven't seen you for quite some
>time. I was particularly fond of those after-PaNorAmA meetings at Wendy's a
>few years ago. I trust you recall me from back then.
>
>I have been following the comp.sys.amiga.emulations newsgroup on Usenet for
>quite awhile now and was quite interested in the IBeM program that is being
>posted about recently. In one of the near Alpha/Theta states that, being a
>programmer, such as yourself, one recognizes as some kind of "source"; I had
>an idea. Since there are not many "new" ideas spawned I wanted to get some
>feedback from a person with the expertise you possess. The reasons I thought
>of you for this private consultation are: 1) you've written an emulator -
>SimCPM 2) you've written an assembler - A68K 3) you have a broad knowledge of
>the computing field beyond lowly PC's and 4) you're such a nice guy!
>
>I was musing about how an emulator would work. I must confess I have no
>concrete knowledge of this. It has been said that "Not knowing how to do a job
>'right' frees you to discover new and better ways of accomplishing the desired
>result". Freeman Patterson (a Canadian photographer), in his book Photography
>and the Art of Seeing, called this "thinking sideways". I believe I've
>thought of a way of writing an emulator that would run at least as fast on the
>Amiga as it would on the source machine.
>
>My questions for you are:
>
>Would you be interested in being a mentor to me in developing further this idea
>or in fact ascertaining whether my concept has any validity?
>
>I'm reticent to spill this on the net until I'm somewhat confident that it is
>indeed practicable. I have thought about the possible legal considerations of
>producing an emulator. There are potential commercial possibilities that one
>could consider also.
>
>Would you please give me just a quick, superficial rundown of the basic
>algorithms used in developing an emulator?
>
>I have assumed that you would read in the object module of say an IBM
>executable, read it by opcode or routine, decipher the intent and then call a
>library of glue routines to do the job that the program would have on an IBM
>or clone. I have no idea how the interrupt structure would be handled but know
>that you have done it with SimCPM.
>
>I don't want to waste your time, but I would appreciate this information. I
>would like to get your feedback on these questions to see if you are interested
>in further discussion with me on this matter. If you are not interested or
>don't have the time I'll certainly understand. I realize I'm asking you for
>more information than I'm sharing but an idea is a tiny property and I'd like
>to at least savor this for a while before I decide what to do with it. That is
>the sole reason I have not gone public with it yet.
>
>If you are indeed interested, after you tell me on the highest level how an
>emulator functions, I'll be able to describe this idea on some kind of
>comprehensible basis. I'm looking forward to your response! Thanks Charlie.
>
>csj
>
>Sun Mar 3 23:12:32 1991 From: Charlie Gibbs [218] Subject : Emulators
>
> Indeed I am somewhat short of time these days, but I wouldn't mind kicking
>the odd idea around without getting too wrapped up in it. I do understand your
>idea of "thinking sideways" and enjoy being able to do it myself from time to
>time. A similar way I've heard it described is that even though it's been
>proven that bumblebees can't fly, they don't realize this and so do it anyway.
>Or to put it another way, I like to write programs that are too stupid to know
>what they're doing, so they can do anything.
>
> Your ideas on emulation are basically in line with what's considered the
>standard way of doing things. A machine instruction is analyzed as to just
>what it's supposed to do, and appropriate code then carries out the operation.
>The guts of SimCPM appeared in Dr. Dobb's journal as an emulator that was meant
>to run under CP/M-68K. This made the job a bit easier for the original author,
>since the CP/M-68K system calls were quite similar to the CP/M calls that he
>was emulating. I had to replace this portion of code with appropriate AmigaDOS
>routines. In addition, I extended the code to handle the full Z-80 instruction
>set, since the original code could only handle the 8080 subset.
>
> Since emulating another processor in software is quite a CPU-intensive
>process (several machine instructions have to be executed to emulate a single
>machine instruction on the target machine) I tried to optimize SimCPM for speed
>at the expense of memory and redundant code. The overhead of a single
>subroutine call, plus any extraction and interpretation of arguments, would
>require several times as much time as a hand-picked set of instructions
>dedicated to a single opcode.
>
> For system calls there's easy out - as soon as I recognize what the
>emulated program is trying to do (e.g. read a block from a disk file), I call
>the corresponding AmigaDOS routine, so I/O can proceed pretty well at native
>speeds. Therefore, even though CPU-bound programs might run 10% as fast as
>they would on the target machine, I/O bound programs might get up to 50% of
>speed.
>
> Interrupts were easy - since most CP/M systems don't use hardware
>interrupts, except possibly for a very few hardware-dependent programs, I
>simply didn't worry about them. Software interrupts (the RST instruction) were
>a snap on the other hand, since they're basically a special-purpose subroutine
>call.
>
> The Intel 8080 is fairly easy to emulate because the opcode is uniquely
>determined by the first byte of the instruction. Some instructions might have
>register numbers encoded in a few bits of that first byte, but I just treat
>them as special cases. To decode the byte, I just multiply its value by 4
>(shift left 2 bits) and use the result as an index into a table of 256 pointers
>to the actual emulation routines. Since there are 64 possible MOV instructions
>(well, 63 because one of the bit combinations is actually HLT) I actually have
>63 MOV emulations, one for each combination of registers. This means that I
>don't have to do any register decoding, since each routine consists of a
>dedicated 68000 MOVE instruction, followed by a jump back to the main emulation
>loop. Lots of almost-redundant code, but it's about as fast as it can get.
>
> This is getting kind of long-winded. I'd be interested in hearing any
>ideas you may have; although I wouldn't have time to get into the programming
>of such stuff, I'm willing to act as a sounding board. Talk to you soon... CJG
>
>Sun Mar 3 23:18:48 1991 From: Charlie Gibbs [218] Subject : Emulators
>
> Another approach I've heard of is to "compile" the code to be emulated
>into native machine code. This would involve a front-end program which would
>read the target machine's program and analyze the instructions. For instance,
>if the "compiler" detects an instruction that does a move between two of the
>emulated machine's registers, it would simply generate a move instruction in
>the emulating machine's code. It could generate either a translated assembly
>language source file or a machine-language file ready to load into the
>emulating machine. This would require the "compilation" process to be run once
>on the program to be emulated, and you'd then run the output of this
>"compiler." There are special tricks to consider here, such as resolving
>addresses - you couldn't just copy the memory addresses across because the
>emulated routines would likely be a different size. It might be easier to
>generate a label (e.g. Axxxx where xxxx is the hex address in question) in an
>assembly source file and let the emulating machine's assembler sort it all out.
>
> I've never actually seen this process in action, but it's another
>possibility. --CJG
>
>Mon Mar 4 12:38:31 1991 From: Chris Johnsen [547] Subject : Emulators
>
>Thanks a lot for your effort in explaining SimCPM to me man. As you describe
>it, it would seem that I had intuitively understood the basic concepts. I
>would think that interrupts would be the hardest part to get down to reliable
>operation. What I had in mind, while thinking about this, in general terms,
>was an emulator that was non-specific as to the machine, therefore I was
>attempting to contemplate it handling say IBM, Mac, (hey it may even be
>possible to deal with Amiga emulation!) and Atari ST on the Amiga and
>imagining what the various architectures would require. All this on a very
>abstract level.
>
>Your second message hit the nail on the head! I got bogged down at about the
>level you describe in your first message. Lots of details to be sought and
>worked out. Gee, I'm really not even available to code another program just
>yet anyway. I was giving the whole concept a rest when, what I thought of,
>kind of sideways (lazy minds tend to look for an easier way around an
>obstacle, sometimes unconsciously, even though this can lead to harder, though
>more elegant solutions to problems), was to read the opcodes from the "source
>executable" of the emulated machine, producing an assembly listing of the
>program. This I imagine would be a two pass process, sort of like a C
>compiler, followed by an assembler's two passes, and finished off with a
>linker.
>
>I thought that, if the compiler was "intelligent" enough, the output, though
>likely larger, would be much faster than the common "interpreter type
>emulator". I had never heard of such an idea and since there are none out
>there, wanted to discuss this with you. I have developed the idea no further
>than this in essence.
>
>I did think of a few other considerations however. If one could, indeed,
>compile an executable image of say Lotus 123 from the IBM into a program which,
>on a base Amiga, could run at half speed, or on a A2500 or A3000 at twice the
>speed, it would be a viable alternative, besides being a neat toy. However,
>the standalone program generated would likely infringe on the copyright of
>Lotus because the Amiga executable would actually be Lotus 123. Take
>WordPerfect for instance. The latest version available is 4.1 or just a
>micro-point higher, no problem, get hold of the IBM version 5.1, I believe it
>is, and compile it and you have something some other people are wailing for. Of
>course the rebuttal (I can hear you thinking?) is that, if a person owns
>WordPerfect he has an inalienable right to run it. Run it on an IBM. Run it on
>a clone. Run it through an Amiga compiler. You know, if it's for personal
>use, etc.
>
>As to the increase in size of the "compiled emulation" program, I have a couple
>of ideas. First, the executable, though larger, would be standalone, except
>for any support libraries. This doesn't mean that this "form" of emulator,
>more like a "translator of executables", would be any less efficient than the
>"interpreter type". Perhaps more memory efficient in a couple of possible
>ways. Since the interpretation section of the program is in the compiler, and
>the source executable is not required at runtime, memory usage may well be less
>with a "compiled emulation". The second concept is to use link libraries which
>would bind only the emulation routines required to the final program. Possibly
>a combination of bound-at-link-time modules of less frequently used routines
>and a shared library of essential routines all programs would need. A solely
>link library approach would leave this concept open to claims that pirates
>could produce "warez" that need no extra code or setup to work. Of course,
>pirates appear to be capable of ripping anything off anyway!
>
>This "compiled emulation" would, given sufficient memory and CPU
>speed/efficiency, allow the running of multiple programs. Both emulated
>programs and standard Amiga programs. Through the use of a shared library more
>than one emulating program could be run without the overhead of multiple
>"emulation interpreters" resident in memory.
>
>The compiler could generate C statements so that you could take advantage of
>the advancements in technology in the compiler, assembler and linker, without
>having to deal, directly, with those parts of the system. I know this would
>make the compiler operation more unwieldy. More operations, therefore it
>would take longer, but theoretically the source is bugless, so you would
>expect the output of this "emulation compiler" to either succeed or fail.
>You'd run the emulator on the program only once. The beauty of producing
>assembler (C would be better here), is that if it didn't work first time, a
>programmer type could patch it up in source and get it running. I'm really
>intrigued by this idea. Where did you hear about it, do you remember?
>
>My knee-jerk reaction initially was to file the idea, but then I got to
>wondering why no one had done it. There were many emulators out there for
>various source machines. Why were none of them compilers? Another idea I had
>was to contact the dude in Oz (or is he a Kiwi?) that wrote IBeM. He already
>has the emulation working except for the parallel and serial ports. It would
>appear that he reads the IBM object code, deciphers it and runs a routine, or
>simply does a MOVE using an opcode lookup table, as you suggest; an
>interpreter. If he instead simply wrote out an instruction in ASCII to do the
>call or move instead, using a shared library of his emulation routines, he'd
>basically have it. The end user would also have to have an assembler or C
>compiler, however. This type of approach has got to produce faster emulation,
>if it is possible. I believe it to be.
>
>Anyway, that's what I had in mind Charlie. I really do appreciate your
>feedback on this. Care to comment on any directions you think could be
>followed? Do you know anyone with enough venture capital to fund the further
>development of this concept? ;-) Do you think I should approach the author of
>IBeM (cute name) directly? Or, should this private discussion we've been
>having be moved to Usenet? Thanks again Charlie! I appreciate you man.
>
>csj
>
>Mon Mar 4 15:36:53 1991 From: Charlie Gibbs [218] Subject : Emulators
>
> I can't remember where I first heard of the idea. The converted code
>won't necessarily be smaller than the original, depending on the relative sizes
>of corresponding machine instructions on both machines. However, if you could
>make the compiler really smart it might be able to recognize certain sequences
>of instructions and replace them by sequences designed to accomplish the same
>thing more efficiently. For instance, since the 8080 doesn't have a multiply
>instruction it needs to fake it with a bunch of adds and shifts. A smart
>compiler, if it could recognize such a routine, could replace it with a single
>68000 multiply instruction and see huge savings.
>
> I'd stay away from calling subroutines; the overhead could kill you.
>
> The copyright issue could be a sticky one, although I can't see any
>problems if you run the converter on your own copy of the emulated software and
>don't try to sell the result. It would no doubt be classified as a "derivative
>work".
>
> Perhaps it might be interesting to throw this discussion out to Usenet. It
>won't be a trivial job, which is probably why we haven't seen it done
>elsewhere. Remember that a straight machine-code emulation duplicates all the
>register fiddling that is required by the target machine's architecture (and
>the 80x86 family needs a LOT of register fiddling). This code is replaced by
>the 680x0's own internal fiddling if you're re-compiling source code. One way
>of looking at it is to decompile the original machine code, then recompile it
>for the new machine.
>
> Interesting stuff... CJG
>
> ------------ End of included text of messages. -----------
>
>Both Charlie Gibbs and myself frequent this newsgroup and look forward to any
>additions to this discussion with which others may respond. Sorry that the
>posting is so long but I felt there was little enough chaff contained in the
>messages to warrant including all of them.
>
>csj
>
>The hard way is usually the disguised easy way, you take your choice. Usenet:
>a542@mindlink.UUCP Phone: (604)853-5426 FAX: (604)854-8104
>
>
>From: rjc@pogo.ai.mit.edu (Ray Cromwell)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <1991Mar6.010141.5905@mintaka.lcs.mit.edu>
>Date: 6 Mar 91 01:01:41 GMT
>References: <4992@mindlink.UUCP>
>Organization: None
>
>
> Very interesting article. I myself have been tempted several times
>to try and write an emulator. Since I programmed 6502 assembly on the
>C64 for 4 years, and I know 68000 on the Amiga, I was tempted to
>try to beat the speed of the other emulators. Then I realized
>the sheer magnitude of the project. Emulating the instruction set is
>easy. In fact, I am quite confident I can make a 6502 emulator run
>faster on the Amiga then the C64. The hard part is the hardware.
>Most C64 programs discard the oS entirely and bang on the hardware.
>Further more, most of them use polling loops, like polling the
>raster beam register and using precisely cycle timed delays. Moreover,
>the VIC chip contains several glitches that allow programmers to
>use tricks to remove the borders, vertically scroll the screen to
>ANY raster location, horizontally shift the screen, vertically and
>horizonally interlace the screen, stretch pixels (double, triple,
>quaduple) length vertically. This is virtually IMPOSSIBLE to
>detect, unless the emulator is artifically inteligent. And, any
>program that has a fastloader won't work. This is because fastloaders
>usually transfer data over the serial clock line, and data line. This
>doubles bandwidth, unforunately it requires PERFECT timing, so perfect
>in fact that it won't work on PAL computers, and vice versa.
>Sprites are another problem, since Amiga sprites are only 16 pixels wide, and
>C64 sprites can have their width and heigth doubled, and they rely
>on a chunky pixel format. Text is another problem since the
>C64 has a builtin Text mode.
>
> The Mac is the easiest computer to emulate because it's not a computer
>at all. The Macintosh computer does not exist, it's nothing more
>than a ROM chip.
>
>A few days ago, I was impressed. I downloaded a demo from ab20 called
>C64Music.zap. This demo emulates 6502 at 100% (in fact, it emulates it
>at perfect timing because the music is exactly the same speed.) This
>demo emulates the SID chip PERFECTLY, and I mean perfect. These guys
>should join together with the maker of A64.
>
>
> I can't speak for other 6502 emulators, but if I wrote one, the fastest
>method looks like table lookup, with careful optimization to make
>sure things are long word aligned. For instance, I might do something like
>
>pc6502 equr a5
>accum equr d5
>xindex equr d6
>yindex equr d7
>stack equr a4 ; 6502 stack, which is base address + $0100 on the C64
>stat equr d4 ;status register
>
>
>
> [allocmem the 6502's address space, load in an
> executable and set the pc to it's start]
>
> lea jumptbl(pc),a2
> sub.l d0,d0
>loop move.b (pc6502)+,d0
> lsl.l #2,d0
> move.l (a2,d0),a3
> jmp (a3)
>
>
>then every instruction would be emulated (even undoc's) and put into
>the jumptbl. The code for 'LDA address' might look like:
>
>lda sub.l d0,d0
> move.b (pc6502)+,d0
> lsl.l #8,d0
> or.b (pc6502)+,d0
> add.l addresspace,d0 ;this code inverts the 6502 little-endian
> ; and then add's the base address of the
> ; memory that was alloc's for it
> move.l d0,a3
> move.b (a3),accum
> jsr GetCC() ? ;It might be better to use move SR, providing you
> ; check the machine you were running on and did
> ; and did a move ccr otherwise
> ; status reg is now in d0
> and #mask,d0 ; mask off everything but the Z bit
> bne whatever
>whatever bclr #1,stat
> jmp loop
> bset #1,stat
> jmp loop
>
>(note: this code can be optimized, its off the tip of my tongue, and
>probably bugged since I haven't coded in asm in awhile)
>
>>From my quick calculations, the jump table dispatcher incurs about a 3-4
>microsecond delay in the fetch of each instruction. This is equivelent
>to about 4 cycles on a 6502 @1.02mhz. If you had infinite amounts of ram,
>the object code loader could 'inline' the code for each instruction
>and get rid of this delay, I beleive this is probably how the C64Music
>demo does it, since music players on the C64 were only about 1k of code.
>
>The Lda routine itself looks like about 2.2 times slower than a true 6502
>delay which 4 cycles. However a 25mhz 68030 would run more than
>twice as fast.
>
>
>Theoretically speaking, an IBM emulator running on an Amiga3000
>should be running at atleast 5mhz 80286 speed. Consider SoftPC on
>the NeXT which runs at 12mhz UNDER UNIX. 68040's are about 2-3 times
>faster then 68030's, so SoftPC on the Amy should run at about 5mhz.
>
>
> Maybe we all should trying something like 'NetIBM'. What I mean, is
>like Nethack, we should all participate in coding an IBM emulator.
>Each person might post a small code segment (in assembler), the rest
>of us can compete optimize it. I remember having a contest with
>some trying to optimize the 'size' of a binary to decimal print
>routine, the final result was the code was reduced 300% in size.
>(we kept passing the optimized source back and forth, each shedding
>a few bytes.)
>
>
>Regardless of what happens. Let's keep the discussion up, it's interesting
>and educational.
>
>
>
>
>
>From: ifarqhar@sunb.mqcc.mq.oz.au (Ian Farquhar)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <1303@macuni.mqcc.mq.oz>
>Date: 6 Mar 91 12:57:34 GMT
>References: <4992@mindlink.UUCP> <1991Mar6.010141.5905@mintaka.lcs.mit.edu>
>Organization: Macquarie University, Sydney, Australia.
>
>In article <1991Mar6.010141.5905@mintaka.lcs.mit.edu> rjc@pogo.ai.mit.edu (Ray Cromwell) writes:
>> The Mac is the easiest computer to emulate because it's not a computer
>>at all. The Macintosh computer does not exist, it's nothing more
>>than a ROM chip.
>
>The best description of a Mac I've ever read! :-)
>
>> I can't speak for other 6502 emulators, but if I wrote one, the fastest
>>method looks like table lookup, with careful optimization to make
>>sure things are long word aligned. For instance, I might do something like
>
>How about this?
>
>Write code for every one of the 256 possible opcodes, and make sure that
>it follows these important considerations:
>
>1) The code is responsible for updating all registers, the 6502PC,
> and also for checking special functions if a hardware location
> is called.
>2) It should be 256 bytes per opcode or less.
>3) It should jump back to STLP (see below) when done.
>4) It should intelligently introduce timing delays (very hard)
>5) Something else I've forgotten.
>
>Take each piece of code, and distribute it in a 64K memory area, so that
>the code for opcode N starts at base + (n << 8). There may be a lot of
>wasted space, but on any reasonable Amiga, this space can be sacrificed
>for speed IMO.
>
> ; Base reg of instruction code in A0. 6502PC in A1.
>
>STLP MOVE.B (A1), lcna ; lcn is the upper byte of the
> ; dsp displacement below
> JMP dsp (A0)
>
>
>Excuse my poor 68K code. I think this will work, but it has been three
>years since I even looked at assembler on the 68000. Before anyone
>screams about this code failing on a 68030, remember that the
>modification made above is only needed until the JMP. After that, we do
>not need to see it again. If I read the info on the 68030 cache
>properly, this should be okay. At worst, the instruction cache can be
>disabled.
>
>This should be considerably faster than any table driven system. On any
>system with multi-byte opcodes (eg. the 8088), this system can be easily
>extended, and minor modifications can be made to emulate most modern CPU
>with reasonable speed.
>
>Now a suggestion for dealing with hardware locations (harder on memory
>mapped systems than on things like Intel and Zilog chips which have I/O
>instructions.) This is another memory-expensive solution, BTW.
>
>For every location, have two flags, one for read and one for write. If
>the opcode handlers write to the location, they can check the write flag
>and if it is set, call a handler which determines which location is
>being modified, and pass control to a routine to do it.
>
>Now for the VERY memory expensive solution.
>
>Have one 16 bit displacements per memory location (ie. for 1M of
>simulated RAM you must have 3M of real RAM.) This location contains the
>displacement from a base register to a routine which handles that memory
>location. If this word is non-zero, an instruction that reads or write
>to it calls this routine. You could even have two displacements, one
>for read and one for write, but this would only be practical for systems
>that have small amounts of simulated memory (eg. C64).
>
>At a rough estimate, for a C64 emulator (IMO the hardest of all
>emulators.)
>
> Simulated Memory 64K
> Read Displacements 128K
> Write Displacements 128K
> Opcode handlers 64K
> Memory Location Handlrs 28K (?)
> Rest 100K (??)
> ----
> 512K
>
>So, for an average 1M Amiga, this is quite possible.
>
>As for the project, why not start with something much simpler? An Atari
>2600 emulator. The hardware is quite simple to simulate, though the
>timing will have to be *very* precise. This would be a good starting
>point. Opinions, anyone?
>
>--
>Ian Farquhar Phone : + 61 2 805-9400
>Office of Computing Services Fax : + 61 2 805-7433
>Macquarie University NSW 2109 Also : + 61 2 805-7420
>Australia EMail : ifarqhar@suna.mqcc.mq.oz.au
>
>
>From: ifarqhar@sunb.mqcc.mq.oz.au (Ian Farquhar)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <1304@macuni.mqcc.mq.oz>
>Date: 6 Mar 91 13:52:25 GMT
>References: <4992@mindlink.UUCP> <1991Mar6.010141.5905@mintaka.lcs.mit.edu> <1303@macuni.mqcc.mq.oz>
>Organization: Macquarie University, Sydney, Australia.
>
>An idea about code compilation, rather than interpretation.
>
>If you assume that a program does not employ self-modifying code, this
>may not be nearly as had as it first appears (I am not saying that it is
>trivial, just not too bad.) This assumption can be made if the program
>runs out of ROM, and also in 99% of non-ROM cases.
>
>The problems of compiling code for one CPU into that for another are
>fairly easy, but a major problem occurs when table-driven code is
>employed (common.)
>
>What I am suggesting is this. It is reasonably elegant, and quite
>simple to perform:
>
>Store the loaded memory image of the original program as well as the
>compiled code. For every instruction in this image, a pointer to the
>compiled code is generated indicating where the corresponding code
>actually is. As the program executes, the working store is this memory
>image, and if a piece of data is read, it can be dealt with normally.
>However, if a program attempt to jump, branch or call a location using
>data loaded (as would happen with a table), then the corresponding
>location can be determined and the correct code called.
>
>This has a high memory overhead (3-5 times original image size *plus*
>compiled code).
>
>I am sure that there is a more memory-effective way of doing this by
>identifying such tables during the compile, but it seems a difficult
>problem. Has anyone got any better solutions?
>
>BTW, an idea for semi-compiled code. Have two branches for every location,
>and simulate the machine that way. Reading an opcode calls the
>appropriate opcode handler, writing it calls a reevaluation routine that
>changes the pointers for the two locations. System and special
>locations are handled similarly. This may actually be a quite
>reasonable solution, as inelegant as it first sounds.
>
>--
>Ian Farquhar Phone : + 61 2 805-9400
>Office of Computing Services Fax : + 61 2 805-7433
>Macquarie University NSW 2109 Also : + 61 2 805-7420
>Australia EMail : ifarqhar@suna.mqcc.mq.oz.au
>
>
>From: rjc@geech.ai.mit.edu (Ray Cromwell)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Emulator Mechanics
>Message-ID: <1991Mar7.093149.18707@mintaka.lcs.mit.edu>
>Date: 7 Mar 91 09:31:49 GMT
>Organization: None
>
>
> I got an idea. How about combining both methods? (compile and interpret)
>
> First compile the executable with flow analysis into 68k code. Any
>instruction that tries to touch a hardware register will become
>a trap instruction(or use an MMU to trap it) to emulate the hardware.
>
> Where does the interpreter come in? Any code that tries to self modify
>or do a change of state (table lookup, indirect jumps, etc) with be
>interpreted.
>
> Sounds hard? You bet. The easier solution of all is to throw faster
>CPUs at the problem.
>
>
>Now for another question:
>
> Why doesn't AMAX multitask? It should be EASY to run multiple copies
>of the Mac ROM as a task (since its a rom, its mostly pure code, except
>each task would need to alter where the ROM things the system memory is.)
>
> For things like the Atari emulator, or another 68000 emulator, the compile
>technique should work great! Just recompile the parts of the code
>that bang on the hardware, or use an MMU to trap them.
>
>
>The whole compilation process is made easier when the machine
>your trying to emulate has an object code format that contains
>seperate data and code chunks, and perhaps some relocation data.
>Further more, if the machine has rules against self modifying code,
>and a device independent OS it becomes trivial.
>
>Could someone run SI or dhrystone on IBeM and tell me how it performs?
>Itis said that SoftPC on a Mac @25mhz 68030 runs at 6mhz AT speed.
>
>Does anyone know if IBM code uses self modifying code, or
>jump tables? What kind of code does their compilers produce?
>And, does the IBM has a special object code format that seperates
>code and data?
>
>
>The compilation technique could work well, but the compiler would have
>to be VERY smart in its flow analysis of detecting code/data, jump
>tables, self modifying code, PC counter and stack manipulation, etc.
>
>I'll clairfy my thoughts tommorow, it's going on 4:30am here, and I
>need to get some well deserved sleep. :-)
>
>
>From: stevek@amiglynx.UUCP (Steve K)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID:
>Date: 6 Mar 91 23:12:59 GMT
>References: <4992@mindlink.UUCP>
>Organization: Amiga-Lynx Bbs Multi-Node 201-368-0463 NJ,USA
>
>The idea of a "translator compiler" is very interesting. I could have sworn I
>saw some talk about a IBM->Atari ST translator that exists on FidoNET. But
>why is everyone talking about IBM? Why not Macintosh programs? Though I am
>not anyting close to a professional programmer, I'd imagine programs that run
>off different computers with the same processor would share some op-codes,
>right? Even if that is not true, they do both have similar GUIs, windows,
>gadgets, and menu bars, ect. which shold make the translation easier and more
>like the original. I sincerly hope someone will pick up and persue these
>ideas, it would be very benificial for me and others - I'd love to run a nice
>pascal compiler like Turbo Pascal, and an excellent ANSI editor like TheDraw!
>
>- Steve Krulewitz - Fair Lawn, NJ -
>
>
>From: dclemans@mentorg.com (Dave Clemans @ APD x1292)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <1991Mar6.212548.9641@mentorg.com>
>Date: 6 Mar 91 21:25:48 GMT
>References: <4992@mindlink.UUCP>
>Organization: Mentor Graphics Corporation
>
>On the "compiled" approach to emulation:
>
>There definitely has been previous work in this area. The
>system I've heard of was an internal tool that was used experimentally
>to port some games from the Intel world to the 68K world.
>
>To use it, you basically had to develop enough information to
>get a clean disassembly of the Intel code; i.e., so that you "knew"
>where all the code and data was in the source object file.
>That then was used to drive the tool that produced the "compiled"
>68K file. After that was done you had to go over the output
>for correctness, system dependencies, etc.; it was not intended
>as a turn key system.
>
>...
>
>As a side issue, to bring over some of the bigger DOS packages
>you'll have to worry about more than just converting a single
>file. You have to find and convert all of their code overlay files....
>
>dgc
>
>
>From: ifarqhar@sunb.mqcc.mq.oz.au (Ian Farquhar)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <1312@macuni.mqcc.mq.oz>
>Date: 8 Mar 91 03:51:21 GMT
>References: <4992@mindlink.UUCP> <1991Mar6.212548.9641@mentorg.com>
>Organization: Macquarie University, Sydney, Australia.
>
>In article <1991Mar6.212548.9641@mentorg.com> dclemans@mentorg.com (Dave Clemans @ APD x1292) writes:
>>To use it, you basically had to develop enough information to
>>get a clean disassembly of the Intel code; i.e., so that you "knew"
>>where all the code and data was in the source object file.
>>That then was used to drive the tool that produced the "compiled"
>>68K file. After that was done you had to go over the output
>>for correctness, system dependencies, etc.; it was not intended
>>as a turn key system.
>
>Well, on a 6502, it is practically impossible to truly decide what is
>code and what is data. Let's imagine that you are (as I have done),
>writing a 6502 disassembler. For every byte you store a status thst
>says DATA, OPCODE, ARGUMENT, and also non-exclusive flags (eg.
>BRANCHENTERSHERE, BRANCHISNOTHERE.) Initially, all bytes are set to DATA,
>and BRANCHISNOTHERE.
>
>Write a recursive procedure that starts at the program entry point, and
>goes through the code. For every byte read as an opcode, tag it as an
>OPCODE, and the bytes following as ARGUMENT. If you get to a branch
>instruction, recursively call the new branch point, and continue
>processing that until you hit a byte that has already been processed
>(ie. not tagged DATA.) You should continue until the whole procedure
>exits, then run the same thing on the RESET, INT and NMI vectors. Calls
>are treated the same way as branches, except that the routine exits to a
>higher level invocation when it hits a RET or RTI.
>
>Now, you should have all the data tagged as either program (OPCODE and
>ARGUMENT), or DATA. Right? Wrong. Why? Because the 6502 has no
>branch always instruction, and your program may continue past what
>appears to be a conditional branch, into data, and screw everything up
>completely.
>
>I experimented with using a two pass approach to this problem. First,
>the program was scanned sequentially, treating every byte as an opcode,
>and tagging every point referenced by some branch, call, jump or vector.
>Then, when a branch was found during the second recursive pass, the
>program would backtrack and examine every last opcode till it hit a
>branch in point (after which no assumptions could be made), to see if
>the flags were left in a deterministic state. At this point I lost
>interest in the whole idea.
>
>Anyway, on the 6502 and anything without a BRA or equivalent, the
>problem of automatically determining what is data and what is code is
>extremely difficult.
>
>However, on the 68K, this approach is probably quite profitable. Why?
>Because there is enough correspondence between the 6502 and 68K
>instructions sets (both having the same ancestor, the 6800) to mean that
>the compilation process is reasonably simple.
>
>Simulating the hardware is still a problem, and I'll have to give that
>one some thought... I still tend to favor the idea that I presented in
>a previous article, carrying around a compiled image (of code only), and
>uncompiled data with labels to the compiled code and handlers for the
>I/O locations.
>
>--
>Ian Farquhar Phone : + 61 2 805-9400
>Office of Computing Services Fax : + 61 2 805-7433
>Macquarie University NSW 2109 Also : + 61 2 805-7420
>Australia EMail : ifarqhar@suna.mqcc.mq.oz.au
>
>
>From: drysdale@cbmvax.commodore.com (Scott Drysdale)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <19614@cbmvax.commodore.com>
>Date: 7 Mar 91 20:15:07 GMT
>References: <4992@mindlink.UUCP>
>Reply-To: drysdale@cbmvax.commodore.com (Scott Drysdale)
>Organization: Commodore, West Chester, PA
>
>In article stevek@amiglynx.UUCP (Steve K) writes:
>>The idea of a "translator compiler" is very interesting. I could have sworn I
>>saw some talk about a IBM->Atari ST translator that exists on FidoNET. But
>>why is everyone talking about IBM? Why not Macintosh programs? Though I am
>
>IBM to Atari ST ports should be relatively simple. the ST essentially runs
>CP/M 68K with several extensions, much like ms-dos. so low level calls
>will pretty much translate directly, and you only have to worry about access
>to hardware.
>
>>- Steve Krulewitz - Fair Lawn, NJ -
>
> --Scotty
>--
>=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>Scott Drysdale Software Engineer
>Commodore Amiga Inc. UUCP {allegra|burdvax|rutgers|ihnp4}!cbmvax!drysdale
> PHONE - yes.
>"Have you hugged your hog today?"
>=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
>
>From: cg@ami-cg.UUCP (Chris Gray)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID:
>Date: 9 Mar 91 08:11:28 GMT
>References: <4992@mindlink.UUCP> <1991Mar6.212548.9641@mentorg.com> <1312@macuni.mqcc.mq.oz>
>Organization: Not an Organization
>
>In article <1312@macuni.mqcc.mq.oz> ifarqhar@sunb.mqcc.mq.oz.au (Ian Farquhar)
>writes:
>
>[Discussion of using a recursive approach to run through all branches and
>calls to tag bytes as being code/data.]
>
>>However, on the 68K, this approach is probably quite profitable. Why?
>>Because there is enough correspondence between the 6502 and 68K
>>instructions sets (both having the same ancestor, the 6800) to mean that
>>the compilation process is reasonably simple.
>
>My Amiga disassembler, Dis (which is available somewhere or other; I believe
>I sent it out last year some time) does this. The thing it has troubles
>with are things like function variables. In writing disk-resident libraries,
>a lot of that is done, so it doesn't work too well on such things. It has
>special code to handle case/switch statements generated by several compilers,
>but an assembler program doing a branch table will usually mess it up. I
>don't think there is much hope of an automated translater. Perhaps some
>kind of interactive one, so that the user can aid in identifying what is
>code and what is data.
>
>--
>Chris Gray alberta!ami-cg!cg or cg%ami-cg@scapa.cs.UAlberta.CA
>
>
>From: finkel@TAURUS.BITNET
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <2406@taurus.BITNET>
>Date: 9 Mar 91 21:26:03 GMT
>References: <4992@mindlink.UUCP> <1991Mar6.004247.8964@cpsc.ucalgary.ca>
>Reply-To: finkel%math.tau.ac.il@CUNYVM.CUNY.EDU (Udi Finkelstein)
>Organization: Tel-Aviv Univesity Math and CS school, Israel
>
>as someone who wrote a 8085 emulator/disassembler/monitor for the C64
>I would like to contribute my on thoughts on the subject.
>
>I have toyed the idea of writing an IBM PC program translator that
>would take an IBM program and 'translate' it to run on the amiga, but
>after careful examination of the idea I decided to drop it for a few
>reasons:
>
>1. There is no way to find out at compile time which memory references
>are accessing special RAM areas such as the text/graphics video screen.
>
>2. self modifying code breaks such schemes easily
>
>3. code/data seperation can be tough. for example, it's very hard to detect
>if memory block contains code ( translate it) , data ( don't touch it)
>or worse - near or far pointers.
>
>(2) is rare, but (1) and (3) are common, so I guess many programs will
>break.
>
>
>even commercial systems claiming the ability to 'compile' PC binaries
>into UNIX programs such as XDOS (anyone heard of them lately??) aren't
>automatic.
>
>Instead, I decided to try concentating on the 'usual' type of emulators
>such as IBeM and Transofrmer.
>
>What caught my attention is that a large portion of the time an emulator
>is spending while emulating an instruction is to check whether a memory
>read/write accesses video memory. every address being written to memory must
>be checked whether it lies in the $BXXXXX range, and if it does, it should
>be written to the screen.
>
>What I really wanted to do if I had an MMU based machine is to write an
>emulator that will use the MMU to track such memory accesses. The emulator's
>memory will be referenced without translation, but every address in the range
>where the video memory is located will be caught by the MMU and special code
>will be run to handle it. This would speed things up.
>
>Udi
>
>
>From: ifarqhar@sunb.mqcc.mq.oz.au (Ian Farquhar)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <1323@macuni.mqcc.mq.oz>
>Date: 10 Mar 91 03:33:49 GMT
>References: <4992@mindlink.UUCP> <1991Mar6.004247.8964@cpsc.ucalgary.ca> <2406@taurus.BITNET>
>Organization: Macquarie University, Sydney, Australia.
>
>In article <2406@taurus.BITNET> finkel%math.tau.ac.il@CUNYVM.CUNY.EDU (Udi Finkelstein) writes:
>>as someone who wrote a 8085 emulator/disassembler/monitor for the C64
>>I would like to contribute my on thoughts on the subject.
>
>A 8085 toolkit on a C64? The mind boggles. Why?! :-)
>
>>2. self modifying code breaks such schemes easily
>
>I have yet to see a piece of self-modifying code on an IBM PC, and it
>will cause problems on the many 386DX and 486 systems that have instruction
>caches without write-through.
>
>>What I really wanted to do if I had an MMU based machine is to write an
>>emulator that will use the MMU to track such memory accesses. The emulator's
>>memory will be referenced without translation, but every address in the range
>>where the video memory is located will be caught by the MMU and special code
>>will be run to handle it. This would speed things up.
>
>Check my article on using lots of memory to very quickly tag this
>occurence on non-PMMU systems, by vectoring every location to a
>handler.
>
>--
>Ian Farquhar Phone : + 61 2 805-9400
>Office of Computing Services Fax : + 61 2 805-7433
>Macquarie University NSW 2109 Also : + 61 2 805-7420
>Australia EMail : ifarqhar@suna.mqcc.mq.oz.au
>
>
>From: ecarroll@maths.tcd.ie (Eddy Carroll)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics (sorry long post)
>Message-ID: <1991Mar9.225807.26560@maths.tcd.ie>
>Date: 9 Mar 91 22:58:07 GMT
>References: <4992@mindlink.UUCP>
>Organization: Dept. of Maths, Trinity College, Dublin, Ireland.
>
>In article <4992@mindlink.UUCP> Chris_Johnsen@mindlink.UUCP (Chris Johnsen)
>writes:
>>
>> [ Interesting discussion about a new sort of PC emulator ]
>
>My final year project for college last year tackled exactly this problem, i.e.
>given a PC executable file, produce an Amiga executable file which will
>perform the same function. The end result worked, in a limited sort of way;
>it was fairly easy for it to be misled by any program of reasonable size.
>
>There are a few tricky problems that must be handled if you want to achieve
>a good degree of success:
>
> o Given the instruction MOV reg,VAL do you treat VAL as a constant value
> or as an offset to an address in one of the PC's segments? The 8086
> uses the same opcode for both cases, and it is far from easy to work out
> which meaning to use. It's important to get it right because in the
> translated program, all the constant values should remain the same
> but address offsets will be different.
>
> o How do you handle jump tables? Most compilers implement switch/case
> statements with jump tables, but it is not always clear what the bounds
> of such tables are.
>
> o On the PC, byte values can be pushed onto the stack as byte values. On
> the 68000, you can only push word values. You can see why this might be
> a problem if you consider a function accessing a parameter at an offset
> of 8 from the stack pointer. If the preceding parameters were four words,
> then this is okay. If they were two words and four bytes however, then
> the offset on the 68000 needs to be 12 to access the same data.
>
> o Given that most major PC programs access the PC's video RAM directly
> for speed reasons, such accesses must be mapped to act equivalently
> on the Amiga. The problem is that the usual method for doing this is to
> set a segment register to point to the video RAM and then to access the
> RAM through this. The same register is likely used for for all sorts of
> other data access elsewhere in the program.
>
>Of course, there are other problems too. The main thing I discovered during
>the course of the project was that it's a lot harder to do translation than
>it might first seem.
>
>My program performs the translation in two passes. The first pass traces out
>all possible paths through the PC code, building up a symbol table and
>separating code from data as it goes. The second pass then walks sequentially
>through the code, producing 68K assembly source code for each line. Certain
>instructions generate macros instead of opcodes, which are later expanded
>to calls to library functions. The resulting source is fed into Charlie's A68K
>and then linked with a library that sets up a PC-like environment (custom
>screen, ibm.font etc.) and handles the INT calls. The result is a standalone
>executable file.
>
>If anyone else has a shot at it, I'd be interested in seeing how it turns out.
>Perhaps a more practical route to take is to produce a translator that can
>take reasonably well written PC source code (say, C or assembly) and
>automatically convert it to Amiga source code. If such a tool existed and
>worked well, it might encourage more companies to port their products to the
>Amiga.
>
>In the meantime, back to IBem.
>--
>Eddy Carroll ----* Genuine MUD Wizard | "You haven't lived until
>ADSPnet: cbmuk!cbmuka!quartz!ecarroll | you've died in MUD!"
>Internet: ecarroll@maths.tcd.ie | -- Richard Bartle
>
>
>From: srwmpnm@windy.dsir.govt.nz
>Newsgroups: comp.sys.amiga.emulations
>Subject: 8 methods to emulate a Z80
>Summary: 8 methods to emulate a Z80 on a 68000
>Keywords: Z80 68000 Amiga
>Message-ID: <18847.27d80900@windy.dsir.govt.nz>
>Date: 8 Mar 91 21:58:24 GMT
>Organization: DSIR, Wellington, New Zealand
>
>Ok folks, here are 8 methods for doing z80 emulation on a 68000, in software.
>(Well, 8 methods to get to decode a z80 instruction and get to the right
>emulation routine, anyway.)
>
>Trade-offs are speed, space and cleanliness. They all fall short of
>"compiling and optimising", but most of these methods will speed up most
>existing emulators. As you might expect, the largest and dirtiest code is
>usually the fastest (and least portable). The same methods should work with
>emulation of 6502, PDP-11 and any other 16-bit processors.
>
>In all methods, I assume there is a 64kb block of memory representing the z80's
>address space, allocated by AllocMem (say), and pointed to by "z80ram".
>
>-------------------------------------------------------------------------------
>Method 1: The "standard" method:
>
>I call this method "standard" because it's used in both of the CP/M z80
>emulators I know about. The general idea is to decode the current instruction
>and jump to the appropriate emulation routine via a vector table. That is,
>like a CASE statement with 256 selections. The code is clean and re-entrant.
>
>; Setup
> move.l z80ram,a2 ; load pseudopc
> lea.l optabl(pc),a1 ; a1 always points to optabl
> lea.l mloop(pc),a3 ; a3 always points to mloop
>
>; Main loop (decode) starts here
>mloop: moveq #0,d0 ; 4 Execute appropriate subroutine.
> move.b (a2)+,d0 ; 8 Grab the next opcode and inc pc.
> asl #2,d0 ;10 D0 high word is still zero!
> move.l 0(a1,d0.w),a0 ;18 Get address of routine from table
> jmp (a0) ; 8 Do the subroutine.
> ;48 total cycles to decode
> even
>optabl: dc.l nop00,lxib,staxb,inxb,inrb,dcrb,mvib,rlc
> dc.l ...
>
>Each z80 instruction emulation routine ends with:
>
> jmp (a3)
>
>-------------------------------------------------------------------------------
>Method 2: The "position-independent" method:
>
>This is slightly quicker, the executable is more than 1500 bytes smaller, and
>you get another register to play with in the emulator (a1 in this case). I
>currently use this method (or close to it) in my Spectrum emulator. The code
>is clean and re-entrant.
>
> move.l z80ram,a2 ; load pseudopc
> lea.l mloop(pc),a3 ; a3 always points to mloop
>mloop: moveq #0,d0 ; 4 clear opcode word
> move.b (a2)+,d0 ; 8 get opcode byte
> add.w d0,d0 ; 4 2 bytes per entry
> move.w optabl(pc,d0.w),d0 ;14 get offset of routine
> jmp optabl(pc,d0.w) ;14 do instruction
> ;44 total to decode
> even
>optabl: dc.w nop00-optabl,lxib-optabl,staxb-optabl,inxb-optabl
> dc.w inrb-optabl,dcrb-optabl,mvib-optabl,rlc-optabl
> dc.w ...
>
>Each instruction emulation routine ends with:
>
> jmp (a3)
>
>-------------------------------------------------------------------------------
>Method 3: The "decode-at-end-of-instruction" method:
>
>(There are really 2 methods described here.) Take either method 1 or method 2.
>Instead of ending each emulation routine with "jmp (a3)", end each one with a
>complete copy of the code from mloop to the indirect jmp. There is no longer
>a main loop, because each instruction jumps directly to the next one.
>
>This method is slightly faster, takes maybe twice as much code, is clean, and
>is re-entrant. It also saves yet another reserved register, in this case a3.
>(Personally, I find that a z80 emulator needs as many free registers as you
>can get your fingers on.)
>
>-------------------------------------------------------------------------------
>Method 4: The "threaded jsr's" method:
>
>Warning: This method uses self-modifying, non-re-entrant code, and therefore
>is not recommended. This code is hazardous to your cache! (No flames please
>--- read on).
>
>Introduce a 390kb contiguous block of code (called thread) which looks like
>this:
>
>thread: jsr patch ; 0
> jsr patch ; 1
> ...
> jsr patch ; 65535
> jmp thread
>
>That is, there is a jsr instruction for each byte in the z80's address space.
>This is in addition to z80ram.
>
>To start the emulator, you transfer control to "thread". What the "patch"
>routine does is to replace the current "jsr patch" with "jsr this_routine",
>where this_routine is the emulation routine for the corresponding opcode in
>z80ram. Then patch jmps to the this_routine to execute the instruction and to
>return to the next jsr in the thread. After a while, patch will no longer be
>called (except by z80 self modifying code), and every jsr made will be to
>emulate a z80 opcode directly.
>
>Whenever a z80 instruction writes to RAM, it patches the corresponding
>"jsr this_routine" with "jsr patch". As a variation, it could patch
>"jsr this_routine" with "jsr new_routine", but that would probably be slower
>in general.
>
>Advantage:
>
>It would be faster than methods 1 to 3, --- I think, --- especially in the
>Spectrum emulator, which has to do a lot of work with every write to RAM to
>check for ROM and video RAM anyway. The main reason for the extra speed is
>that it no longer has to decode the opcode on every instruction. There are
>the extra overheads of call and return though, and extra work to do on every
>RAM write.
>
>Disadvantages:
>
>1: The code breaks C='s self-modifying code law. To run on Amiga's with
>caches, it would have to either disable the caches or update them manually
>after every patch. The code is extremely dirty, not re-entrant, and
>definitely not recommended;
>
>2: You need 390k contiguous memory (plus another 64k somewhere else, plus
>whatever else you need for video).
>
>Other characteristics:
>
>Code would run slowly the first time round the loop, then speed up.
>
>--------------------------------------------------------------------------
>Method 5: The "replicated code" method.
>
>Warning: This also uses self-modifying, non-re-entrant code and is therefore
>not recommended.
>
>Thread consists of 65536 blocks of code, each long enough to emulate the
>trickiest z80 instruction. Initially it contains 65536 copies of patch. (You
>will need A LOT of contiguous memory.) What patch does is to actually copy
>the code for the opcode over itself, then transfer control to the beginning of
>itself. (Tricky, but it can be done.) Every emulation routine finishes with
>a "bra.s next_instr" so they are all really the same length. That saves the
>call and return overhead.
>
>If an emulation routine is too long, then just use a jmp to somewhere. In
>practice, you would probably start with:
>
> jsr patch
> bra.s next_instr
>
>in every slot, rather than a complete copy of patch. Z80 RAM writes would
>copy the above code to the corresponding slot, if necessary, rather than
>copying the whole patch routine.
>
>Short of "compiling and optimising", this is the fastest method I can think of,
>but it is incredibly space-wasting, self-modifying, extremely dirty, and
>definitely not recommended.
>
>--------------------------------------------------------------------------
>Method 6: The "threaded vector table" method:
>
>Ok, now to fix the self-modifying code problem. Take method 4 (threaded jsr's),
>but use a 262kb vector table in a private data segment, instead of a thread in
>the code segment.
>
>vectors: dc.l patch ; 0
> dc.l patch ; 1
> ...
> dc.l patch ; 65535
> dc.l jmp_thread
>
>The main instruction loop looks like:
>
> lea.l vectors,a0
> lea.l mloop(pc),a2
>mloop: move.l (a0)+,a1 ;12 cycles
> jmp (a1) ; 8 cycles
>
>and every instruction finishes with "jmp (a2)". A0 is acting as a "pseudo-pc"
>into the vector table. Of course patch performs the same functions as before
>(except it is no longer self modifying, it just patches a vector). The vector
>table still needs to be updated by every write to Z80 RAM. The code is
>re-entrant provided each task has a separate copy of the vector table.
>
>--------------------------------------------------------------------------
>Method 7: The "position-independent threaded vector table" method:
>
>Same as method 6, except that now the private data segment is:
>
>thread: dc.w patch-base ; 0
> dc.w patch-base ; 1
> ...
> dc.w patch-base ; 65535
> dc.w jmp_thread-base
>
>and the main loop is:
>
> lea.l thread,a0
> lea.l mloop(pc),a1
>mloop: move.w (a0)+,d0 ; 8 cycles
> jmp base(pc,d0.w) ;14 cycles
>base:
>patch: ...
>op00: ...
>op01: ...
>jmp_thread: ...
>
>Now it is position-independent, only 128kb contiguous memory, the executable
>is 1500 bytes smaller, and it is slightly slower (only by 2 cycles per z80
>instruction though). The code is re-entrant provided each task has a separate
>copy of the vector table.
>
>--------------------------------------------------------------------------
>Method 8: The "decode-at-end-of-instruction threaded vector table" method:
>
>Same as method 6 except that every opcode emulation routine finishes with:
>
> move.l (a0)+,a1
> jmp (a1)
>
>instead of "jmp (a2)". Now isn't that faster? And it saves a2 for more
>important things.
>
>Unfortunately you can't do exactly the same thing to method 7 unless you can
>write a complete z80 emulator in 256 bytes 8-) . But you could take method 7
>and end each emulation routine with:
>
>mloop: move.w (a0)+,d0
> lea.l base(pc),a1
> jmp 0(a1,d0.w)
>
>instead. The code is re-entrant provided each task has a separate copy of
>the vector table.
>
>--------------------------------------------------------------------------
>Personally I'm considering using one of the methods 6, 7 or 8 in the next
>version of the Spectrum emulator (probably method 8) (That is, if I ever get
>enough spare time without more interesting things to do.) I'll probably make
>the source public domain. That will use more Amiga RAM, but should go faster
>(I hope). Any guesses as to which method will be the fastest, and still fit
>comfortably in a 512k machine?
>
>Unfortunately I don't think any of the methods (except the first 3) are
>suitable for an 8088 emulator because of the huge memory requirements.
>
>I'm interested in any ideas anyone might have along these lines. The
>discussion of "compiling and optimising" is very interesting, but I don't see
>how the details would work. In particular, how do you cope with self-modifying
>code, code loaders, overlays etc?
>
>
>Peter McGavin. (srwmpnm@wnv.dsir.govt.nz)
>
>Disclaimer: I haven't tested any of the above ideas (except 1 and 2). If you
>see any bugs, point them out.
>
>
>From: daveh@cbmvax.commodore.com (Dave Haynie)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics
>Message-ID: <19749@cbmvax.commodore.com>
>Date: 11 Mar 91 20:25:55 GMT
>References: <1991Mar7.093149.18707@mintaka.lcs.mit.edu>
>Reply-To: daveh@cbmvax.commodore.com (Dave Haynie)
>Organization: Commodore, West Chester, PA
>
>In article <1991Mar7.093149.18707@mintaka.lcs.mit.edu> rjc@geech.ai.mit.edu (Ray Cromwell) writes:
>
>> Why doesn't AMAX multitask? It should be EASY to run multiple copies
>>of the Mac ROM as a task (since its a rom, its mostly pure code, except
>>each task would need to alter where the ROM things the system memory is.)
>
>Without massive patching of the Mac ROM, I don't think so. The same reason
>you don't have more sophisticated multitasking on the Mac itself. You can't
>run multiple copies of the same Mac ROM code, since the code is not reentrant
>like Amiga code. Without some clever MMU tricks, I don't think you could
>easily relocate things such that several different copies of the ROM code
>could coexist. At least, you would expect Apple to have considered any of
>the more mundane tricks available on any 680x0 system. Apple does seem to have]
>decent technical folks, I doubt they missed any easy tricks...
>
>Via MMU, you could certainly get further. Multifinder didn't do that, since
>it would have required an MMU based system for any multitasking. I'm surprised
>Apple didn't work out anything like that for their MacOS-under-UNIX, though.
>
>>Does anyone know if IBM code uses self modifying code, or
>>jump tables?
>
>Self modifying code and other uglies are very prevalent in MS-DOS code. That's
>the main reason Intel went for a unified code/data cache for the 80486.
>Separate I and D caches with internal Harvard architecture (like the '030 and
>'040) can yield a much faster system, all else being equal. But that extra
>performance would not have been worth tossing out what was apparently a large
>portion of the MS-DOS programs out there.
>
>MS-DOS programs, more and more often, think they're the operating system.
>Every program is responsible for managing differences between CPUs, managing
>memory (beyond the 8088 model), graphics, etc.
>
>--
>Dave Haynie Commodore-Amiga (Amiga 3000) "The Crew That Never Rests"
> {uunet|pyramid|rutgers}!cbmvax!daveh PLINK: hazy BIX: hazy
> "What works for me might work for you" -Jimmy Buffett
>
>
>From: srwmpnm@windy.dsir.govt.nz
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: 8 methods to emulate a Z80
>Summary: 4 more methods to emulate a Z80
>Keywords: Z80 68000 Amiga Emulator
>Message-ID: <18850.27dbf20e@windy.dsir.govt.nz>
>Date: 11 Mar 91 21:09:34 GMT
>References: <18847.27d80900@windy.dsir.govt.nz>
>Organization: DSIR, Wellington, New Zealand
>
>Here are 4 more methods for doing z80 instruction decoding on a 68000. These
>methods are all based on fixed-size instruction emulation routines.
>
>There are some general comments, on handling multiple-byte opcodes, writing to
>hardware registers, and flag handling, at the end of this post.
>
>These 4 methods are faster than methods 1..3 (see previous post), they do not
>have the RAM-write overheads of methods 4..8, and they do not require tables of
>opcode routine address offsets. Some of these methods might be superior to all
>previous methods.
>
>In all these methods, each z80 instruction emulation routine is fixed at 256
>bytes in length. (See earlier post by Ian Farquhar.) They are coded in the
>sequence op_80, op_81, ... op_ff, op_00, op_01, ... op_7f. So there is exactly
>64k of code. If a routine is shorter than 256 bytes, the extra space is
>wasted. If a routine is longer than 256 bytes then it will need a jsr to
>somewhere.
>
>-------------------------------------------------------------------------------
>Method 9: The "self-modifying fixed-size routine" method:
>
>Warning: Self modifying code follows.
>
>This method is almost the same as in Ian Farquhar's earlier c.s.a.e post.
>
>setup: lea.l op_00(pc),a1 ; a1 always points to op_00
> move.l z80ram,a2 ; load pseudopc
>
>mloop: move.b (a2)+,1$-op_00+4(a1) ;16 patch $ff in jmp instruction, inc pc
>1$: jmp $ff00(a1) ;10 Jump to routine.
> ;26 total cycles
>
>Every instruction emulation routine ends with a copy of mloop, rather than a
>jump back to mloop.
>
>The move.b patches the high byte of the offset in the second instruction, so
>the jump goes to the right routine. (1$-op_00+4 might be 1$-op_00+2 --- I
>haven't checked.)
>
>The code is extremely fast (maybe the fastest yet), but it does not work on
>Amigas with memory caches.
>
>I thought of making it even faster by permanently setting a4 to the address of
>the byte to patch, and then using:
>
>mloop: move.b (a2)+,(a4) ;12 Patch $ff in jmp instruction, inc pc
> jmp $ff00(a1) ;10 Jump to routine.
> ;22 total cycles
>
>but you run out of reserved registers if there are lots of copies of mloop.
>(I.e, you can't use the decode-at-end-of-instruction technique.) Using
>"jmp (a3)" at the end of every routine makes it slower.
>
>-------------------------------------------------------------------------------
>Method 10: The "standard fixed-size routine" method:
>
>Now we eliminate self-modifying code.
>
>The main loop is coded into the wasted space at the end of op_ff (so that it is
>within 128 bytes of op_00 --- Remember that op_00 is in the middle of the 64k
>code block).
>
>setup: subq.l #2,sp ; make room for scratch area on stack
> clr.w (sp) ; low byte of scratch area is always 0
> lea.l mloop(pc),a3 ; a3 always points to mloop
> move.l z80ram,a2 ; load pseudopc
>
>mloop: move.b (a2)+,(sp) ;12 Opcode to scratch high byte, inc pc
> move.w (sp),d0 ; 8 high byte is opcode, low byte is 0
> jmp op_00(pc,d0.w) ;14 Jump to routine.
>
>Each z80 instruction emulation routine ends with:
>
> jmp (a3) ;10
> ;44 total cycles
>
>Unfortunately it's quite a bit slower. We can do better...
>
>-------------------------------------------------------------------------------
>Method 11: The "decode-at-end-of-instruction fixed-size routine" method:
>
>Register a3 always points to op_00 instead of to mloop, and we have:
>
>setup: subq.l #2,sp ; make room for scratch area on stack
> clr.w (sp) ; low byte of scratch area is always 0
> lea.l op_00(pc),a3 ; a3 always points to op_00
> move.l z80ram,a2 ; load pseudopc
>
>mloop: move.b (a2)+,(sp) ;12 Opcode to scratch high byte, inc pc
> move.w (sp),d0 ; 8 high byte is opcode, low byte is 0
> jmp 0(a3,d0.w) ;14 Jump to routine.
> ;34 total cycles
>
>Each z80 instruction emulation routine ends with a copy of the decode routine.
>This is faster than method 10, and mloop can be coded anywhere.
>
>Can we avoid using scratch memory and still be as fast? Think about how you
>might do this before you read on. An 8-bit shift of register d0 avoids using
>scratch memory, but is slower (on a plain 68000). The next method shows how to
>make the decode faster and avoid using scratch memory, but it (possibly)
>introduces overhead elsewhere.
>
>-------------------------------------------------------------------------------
>Method 12: The "stretched-address-space fixed-size-routine" method:
>
>This method assumes that the z80 address space (z80ram) is stretched to 128k,
>so that each byte in the z80's address space takes up a word in the Amiga.
>The low order byte of every word must always be 0.
>
>setup: move.l z80ram,a2 ; load pseudopc
> lea.l op_00(pc),a3 ; a3 always points to op_00
>
>mloop: move.w (a2)+,d0 ; 8 Opcode to d0 high byte, inc pc
> jmp 0(a3,d0.w) ;14 Jump to routine.
> ;22 total cycles
>
>For best results, every routine ends with the mloop code (decode at end of
>instruction). The instruction decode is faster than method 11, but now many
>instructions will have extra work to do to convert byte z80 addresses to word
>amiga addresses. Still, this code looks good enough to try.
>
>Miscellaneous hint #9: To convert a byte offset to a word offset, use
>"add.w d0,d0", not "lsl.w #1,d0".
>
>Another miscellaneous hint: Maybe there's a use for movep here.
>
>You could maintain 2 copies of the z80 address space --- one in 64k and the
>other in 128k. Then it's just a simple matter of writing a byte to both places
>whenever the z80 does a write. That gets rid of the overhead of converting
>between offset types on memory reads.
>
>But now our method is starting to look like threaded code (method 8) again.
>The threaded code method uses the 128k block to store the offset to the
>handling routine, rather than storing the opcode itself. The overhead in doing
>a memory write is the same in both methods, and threaded code has other
>advantages (like not having to pad code to 256 bytes, multiple-byte opcodes
>handled better). So we're back to threaded code again.
>
>-------------------------------------------------------------------------------
>A note on multiple-byte opcode instructions:
>
>The z80 uses these. They are prefixed with $cb, $dd, $ed and $fd. There are
>also $ddcb and $fdcb prefixed instructions.
>
>For fixed-size methods, (methods 9..12), the fastest way to cope with long
>instructions is to use more tables. But that means multiplying the number of
>tables by 5 or 7. 64k of code has just jumped to 320k or 448k. That's no good
>on a small machine. Also, if you reserve a register to point to op_00 in each
>table, that's 5 or 7 registers gone. Oops.
>
>-------------------------------------------------------------------------------
>Some notes on threaded code:
>
>I spent last evening trying threaded code (method 8) in the Spectrum emulator.
>(See previous post.) I got a 20..40% speed improvement over the position-
>independent standard method (256-way CASE statement). It's still several times
>slower than a real Spectrum, unfortunately. There is some slow code in places
>where there wasn't before, so there is scope for more improvement.
>Unfortunately I introduced some bugs during the systematic changes, and they
>are proving hard to track down. Everything in the Spectrum ROM seems to work
>ok. Some machine-code programs that worked before have stopped working.
>
>Threaded code is extremely fast for multiple-opcode instructions. Control is
>vectored directly to the right routine first time, without having to decode
>multiple tables. A problem with this is that if a Spectrum program overwrites
>the second opcode of a multiple-byte instruction ($cb, $dd, $ed, $fd) without
>writing to the first byte, then the emulator doesn't cope.
>
>-------------------------------------------------------------------------------
>Note on hardware registers:
>
>Handling writes to hardware registers in the Spectrum isn't really very hard.
>The z80 has a separate IO address space with a separate set of instructions for
>handling it. (The same is true of the 8088.) The only thing to watch for is
>writing to video RAM. It is fixed size and at a fixed place, so it takes 2
>tests. (There doesn't seem to be a faster way of doing a single bit test ---
>the video RAM doesn't end on a power-of-2 boundary.) I have a separate task
>(sort of) which uses the blitter to keep the screen up-to-date with the video
>RAM. So when there is a write to video RAM, the emulator task doesn't have to
>do much. It just flags the blitter task "Hey, there's something to update in
>character row n, when you wake up". The blitter task doesn't slow the emulator
>down much, because it's mostly running on another processor, and it sleeps when
>there's nothing to update.
>
>-------------------------------------------------------------------------------
>Some notes on flag handling:
>
>Both of the CP/M emulators I know about spend a lot of time handling z80 flags
>(condition codes). After just about every instruction they do a "move sr,d0"
>or "move ccr,d0" or call GetCC() to get the 68000 flags, then they do a table
>lookup to translate them to z80 format. After every logical instruction (not,
>or, xor etc), a second table lookup is done to set the z80 parity flag. (The
>68000 does not have a parity flag.) These table lookups are slow. In fact,
>they often take several times as long as the guts of the instruction itself.
>
>Both these table lookups are totally unnecessary! It's faster to save the
>flags in 68000 format (in a register). Routines that test flags simply test
>the corresponding 68000 flag. For logical instructions, simply save the parity
>byte away somewhere, and set another bit in the register to say to use the
>parity byte and not v flag. The parity testing instructions (e.g, "jp po,nn")
>look at that bit, and then test either the v flag or the saved parity byte.
>The only times you need to translate flags between z80 and 68000 formats are in
>"push af" and "pop af" instructions.
>
>I got a 10..20% speedup in my Spectrum emulator this way.
>
>-------------------------------------------------------------------------------
>I said in my previous post that threaded code for 8088 emulation would use too
>much memory to be practical. In fact it would be perfectly practical on an
>Amiga equipped with 3 Mbytes or more.
>
>Peter McGavin. (srwmpnm@wnv.dsir.govt.nz)
>
>
>From: Chris_Johnsen@mindlink.UUCP (Chris Johnsen)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Emulator Mechanics [Transpiler]
>Message-ID: <5097@mindlink.UUCP>
>Date: 10 Mar 91 17:54:43 GMT
>Organization: MIND LINK! - British Columbia, Canada
>
>
> Thank you all for the valued input into this discussion to date, both
>pro and con. I must say I find it very stimulating.
>
> When discussing this form platform porting translator/compiler with
>anyone, I find the need for a short word to use. In a humble attempt to coin
>a descriptive phrase, may I suggest transpiler?
>Charlie Gibbs (Charlie_Gibbs@mindlink.UUCP) Jean-Noel Moyne (jnmoyne@lbl.gov)
>Dave Clemans (dclemans@mentorg.com) Dwight Hubbard (uunet.uu.net!easy!lron)
>Pete Ashdown (pashdown@javelin.es.com) Jyrki Kuoppala (jkp@cs.HUT.FI) confirm
>that, indeed some research and even program development has been done in this
>direction.
>
>Eddy Carroll (ecarroll@maths.tcd.ie) has written such a transpiler, as a last
>year project, with some success, some reservations.
>
>Chris Gray (cg@ami-cg.UUCP) suggests that the most practicable route to
>desinging a viable transpiler would be to make it interactive. BTW Chris, I
>very much enjoyed your compiler articles in the Amiga Transactor.
>
>Ray Cromwell (rjc@pogo.ai.mit.edu) suggested an interesting thought, a sort of
>Usenetware combined effort for development, he also thinks reasonable execution
>speed can be achieved.
>
> Those are what I percieve to be the ideas supporting the transpiler
>concept. The statements of contrary considerations are more voluminous. These
>appear to fall into a number of categories.
> o Self-modifying code
> o Separating code from data
> o Determining video access
> o Stack handling
> o Jump table problems
> o Handling overlay segments
>Ian Farquhar (ifarqhar@sunb.mqcc.mq.oz.au) suggested that a compiled module be
>run concurrent with an emulator type section so that in some parallel way, any
>references within the source executable, which would also be loaded during
>runtime of the emulation, could be validated. It could be argued that this
>should be placed on the pro side of the ledger, but the incurred overhead
>during execution would be large. This function, I had imagined initially,
>would be carried out during the transpiler phase and not attached to, or
>burdening, the runtime execution.
>
>Brad Pepers (pepers@enme1.ucalgary.ca) Jyrki Kuoppala (jkp@cs.HUT.FI) Jonathan
>David Abbey (jonabbey@cs.utexas.edu) were somewhat concerned with
>self-modifying code. There were a significant number of voices that dismissed
>this concern. Personally, I wouldn't worry about it. If a particular program
>used this technique, for whatever reason, I would accept the fact that not all
>programs can be transpiled.
>
>Ian Farquhar (ifarqhar@sunb.mqcc.mq.oz.au) Dave Clemans (dclemans@mentorg.com)
>Sullivan (Radagast@cup.portal.com) Jean-Noel Moyne (jnmoyne@lbl.gov) Chris
>Gray (cg@ami-cg.UUCP) raised concerns about determining code from bytes of the
>data persuation. This is what I had thought would be the biggest stumbling
>block. I hadn't thought there would be so many others. :-) It's great to hear
>how how long the road is before you begin the journey.
>
>Udi Finkel (finkel@TAURUS.BITNET) Eddy Carroll (ecarroll@maths.tcd.ie) are
>concerned about determining when the access to memory is video ram. This, I
>believe, can be solved, if it is dealt with in the same manner as the code/data
>resolution. Please read on.
>
>Eddy Carroll (ecarroll@maths.tcd.ie) points out problems with processor stack
>handling. How did you resolve this with the transpiler you developed? It
>occurs to me that every emulator whether it be a transpiler, or interpretive
>type must handle the stack properly. To me, it would be more difficult to
>approach this problem if I were writting an emulator, as opposed to a
>transpiler, as less executable size constraints would inhibit producing an
>intelligent stack handler. On the 68000 the stack would be handled as
>word/longword only. Any bytewise stack functions within the source executable
>would be transpiled into wordwise handling. A problem, but surmountable.
>
>Chris Gray (cg@ami-cg.UUCP) Eddy Carroll (ecarroll@maths.tcd.ie) raised the
>problem of coping with jump or branch tables properly. Weighty point. This I
>would describe as a grey area between code and data where it may be actual jump
>instructions, or a table of label locations, the code to be emulated
>calculating an offset into it. This must be handled in a similar fashion to
>the code/data recognition problem.
>
>Dave Clemans (dclemans@mentorg.com) Kurt Tappe (JKT100@psuvm.psu.edu) Jonathan
>David Abbey (jonabbey@cs.utexas.edu) were concerned with the handling of
>overlay segments. This bothers me too. With the Amiga, it would be possible
>to either use overlays, in the case of very large programs, or convert to
>all-in-one programs by consolidating the overlay hunks. The main problem is
>determining that overlays are employed, loading them and transpiling. This is
>closely related to the code/data determination problem.
>
>Dwight Hubbard (uunet.uu.net!easy!lron) suggest that this would work, kind of
>like DSM. I have DSM and must say it was a model for me when contemplating
>this idea. Chris Gray (cg@ami-cg.UUCP) believes that an interactive compiler
>holds some promise. In one of my initial messages to Charlie Gibbs I
>entertained the reality of having to fall back on human intervention, at the
>transpiler output source code level. This would be determined at runtime,
>when the emulated program failed to operate correctly or at all. A programmer
>would be required to fix the problem.
>
> What I interpert the huge human parallel processor the net represents,
>to be saying, is that human intervention must be employed. My only reservation
>in this regard is that there are interperative emulators that run a wide
>variety of software on-the-fly. To me, this feat is more difficult than a
>transpiler, which can ruminate over the executable for as long as say a
>raytracer.
>
> To incorporate the above concepts, and arrive at a workable resolution,
>what is required is an expert system, probably requiring a resident expert (not
>software, though brain matter is soft), to resolve the code/data, video access,
>jump/branch table and overlay problems. I don't suppose that the average
>emulator user is prepared to deal with or even understand the problems we have
>been discussing. I don't think it would be worthwhile writing a transpiler
>unless it could be made to work in some standalone fashion. Feed it the
>source executable and out pops the Amiga version.
>
> Mind shifting stage left...
>
> I have a suggestion, since it is not considered practicable to write a
>transpiler that will work unassisted, that may resolve the percieved problems
>using some of the concepts from this message thread.
>
> First, an off-the-wall analogy. Here he goes again. :-)
>
> Consider a desirable program, running on another platform, useful to
>an Amiga user, but with a very large dongle attached. This useful program must
>be run on the dongle in fact. This is inconvient. What do I do if I loose my
>dongle? I propose you think of this as a form of copy protection for a
>moment, obstructiing the Amiga owner, who also owns a program that runs on
>another platform. Follow me so far? The legitimate program for the other
>platform cannot be used on the favoured, Amiga machine, so it needs to be
>decopy-protected. What do you use if you wish to backup and/or deprotect
>software? A copier program. Most copiers can be employed by users who have
>little knowledge of copy protection, yet they succeed in making the copy. The
>more difficult protection schemes require "brain files" which are written by
>experts to achieve this end. End of transpiler/copy-protection analogy.
>
> Take a basic transpiler, such as the one Eddy Carroll wrote, and add a
>toolkit. The transpiler would do its best to translate and compile the source
>executable. If this failed, an expert, not just the average user, would either
>run the transpiler in expert mode, or a debug tool from the toolkit, which
>would work through any problem areas. The result of this would be an expert
>transpiler file. The beauty of this approach is that any user could run the
>transpiler, given access to the expert file. These expert files could be
>included with the release package and any new ones could be included in any
>updates or shared by conventional electronic means as PD.
>
>What do you think?
>
>csj
>
> No really officer, I wasn't speeding, just keeping a safe distance in front of
>the car behind me!
>
>Usenet: a542@mindlink.UUCP Phone: (604)853-5426 FAX: (604)854-8104
>
>
>From: Chris_Johnsen@mindlink.UUCP (Chris Johnsen)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Emulator Mechanics [Transpiler]
>Message-ID: <5097@mindlink.UUCP>
>Date: 10 Mar 91 17:54:43 GMT
>Organization: MIND LINK! - British Columbia, Canada
>
>
> Thank you all for the valued input into this discussion to date, both
>pro and con. I must say I find it very stimulating.
>
> When discussing this form platform porting translator/compiler with
>anyone, I find the need for a short word to use. In a humble attempt to coin
>a descriptive phrase, may I suggest transpiler?
>Charlie Gibbs (Charlie_Gibbs@mindlink.UUCP) Jean-Noel Moyne (jnmoyne@lbl.gov)
>Dave Clemans (dclemans@mentorg.com) Dwight Hubbard (uunet.uu.net!easy!lron)
>Pete Ashdown (pashdown@javelin.es.com) Jyrki Kuoppala (jkp@cs.HUT.FI) confirm
>that, indeed some research and even program development has been done in this
>direction.
>
>Eddy Carroll (ecarroll@maths.tcd.ie) has written such a transpiler, as a last
>year project, with some success, some reservations.
>
>Chris Gray (cg@ami-cg.UUCP) suggests that the most practicable route to
>desinging a viable transpiler would be to make it interactive. BTW Chris, I
>very much enjoyed your compiler articles in the Amiga Transactor.
>
>Ray Cromwell (rjc@pogo.ai.mit.edu) suggested an interesting thought, a sort of
>Usenetware combined effort for development, he also thinks reasonable execution
>speed can be achieved.
>
> Those are what I percieve to be the ideas supporting the transpiler
>concept. The statements of contrary considerations are more voluminous. These
>appear to fall into a number of categories.
> o Self-modifying code
> o Separating code from data
> o Determining video access
> o Stack handling
> o Jump table problems
> o Handling overlay segments
>Ian Farquhar (ifarqhar@sunb.mqcc.mq.oz.au) suggested that a compiled module be
>run concurrent with an emulator type section so that in some parallel way, any
>references within the source executable, which would also be loaded during
>runtime of the emulation, could be validated. It could be argued that this
>should be placed on the pro side of the ledger, but the incurred overhead
>during execution would be large. This function, I had imagined initially,
>would be carried out during the transpiler phase and not attached to, or
>burdening, the runtime execution.
>
>Brad Pepers (pepers@enme1.ucalgary.ca) Jyrki Kuoppala (jkp@cs.HUT.FI) Jonathan
>David Abbey (jonabbey@cs.utexas.edu) were somewhat concerned with
>self-modifying code. There were a significant number of voices that dismissed
>this concern. Personally, I wouldn't worry about it. If a particular program
>used this technique, for whatever reason, I would accept the fact that not all
>programs can be transpiled.
>
>Ian Farquhar (ifarqhar@sunb.mqcc.mq.oz.au) Dave Clemans (dclemans@mentorg.com)
>Sullivan (Radagast@cup.portal.com) Jean-Noel Moyne (jnmoyne@lbl.gov) Chris
>Gray (cg@ami-cg.UUCP) raised concerns about determining code from bytes of the
>data persuation. This is what I had thought would be the biggest stumbling
>block. I hadn't thought there would be so many others. :-) It's great to hear
>how how long the road is before you begin the journey.
>
>Udi Finkel (finkel@TAURUS.BITNET) Eddy Carroll (ecarroll@maths.tcd.ie) are
>concerned about determining when the access to memory is video ram. This, I
>believe, can be solved, if it is dealt with in the same manner as the code/data
>resolution. Please read on.
>
>Eddy Carroll (ecarroll@maths.tcd.ie) points out problems with processor stack
>handling. How did you resolve this with the transpiler you developed? It
>occurs to me that every emulator whether it be a transpiler, or interpretive
>type must handle the stack properly. To me, it would be more difficult to
>approach this problem if I were writting an emulator, as opposed to a
>transpiler, as less executable size constraints would inhibit producing an
>intelligent stack handler. On the 68000 the stack would be handled as
>word/longword only. Any bytewise stack functions within the source executable
>would be transpiled into wordwise handling. A problem, but surmountable.
>
>Chris Gray (cg@ami-cg.UUCP) Eddy Carroll (ecarroll@maths.tcd.ie) raised the
>problem of coping with jump or branch tables properly. Weighty point. This I
>would describe as a grey area between code and data where it may be actual jump
>instructions, or a table of label locations, the code to be emulated
>calculating an offset into it. This must be handled in a similar fashion to
>the code/data recognition problem.
>
>Dave Clemans (dclemans@mentorg.com) Kurt Tappe (JKT100@psuvm.psu.edu) Jonathan
>David Abbey (jonabbey@cs.utexas.edu) were concerned with the handling of
>overlay segments. This bothers me too. With the Amiga, it would be possible
>to either use overlays, in the case of very large programs, or convert to
>all-in-one programs by consolidating the overlay hunks. The main problem is
>determining that overlays are employed, loading them and transpiling. This is
>closely related to the code/data determination problem.
>
>Dwight Hubbard (uunet.uu.net!easy!lron) suggest that this would work, kind of
>like DSM. I have DSM and must say it was a model for me when contemplating
>this idea. Chris Gray (cg@ami-cg.UUCP) believes that an interactive compiler
>holds some promise. In one of my initial messages to Charlie Gibbs I
>entertained the reality of having to fall back on human intervention, at the
>transpiler output source code level. This would be determined at runtime,
>when the emulated program failed to operate correctly or at all. A programmer
>would be required to fix the problem.
>
> What I interpert the huge human parallel processor the net represents,
>to be saying, is that human intervention must be employed. My only reservation
>in this regard is that there are interperative emulators that run a wide
>variety of software on-the-fly. To me, this feat is more difficult than a
>transpiler, which can ruminate over the executable for as long as say a
>raytracer.
>
> To incorporate the above concepts, and arrive at a workable resolution,
>what is required is an expert system, probably requiring a resident expert (not
>software, though brain matter is soft), to resolve the code/data, video access,
>jump/branch table and overlay problems. I don't suppose that the average
>emulator user is prepared to deal with or even understand the problems we have
>been discussing. I don't think it would be worthwhile writing a transpiler
>unless it could be made to work in some standalone fashion. Feed it the
>source executable and out pops the Amiga version.
>
> Mind shifting stage left...
>
> I have a suggestion, since it is not considered practicable to write a
>transpiler that will work unassisted, that may resolve the percieved problems
>using some of the concepts from this message thread.
>
> First, an off-the-wall analogy. Here he goes again. :-)
>
> Consider a desirable program, running on another platform, useful to
>an Amiga user, but with a very large dongle attached. This useful program must
>be run on the dongle in fact. This is inconvient. What do I do if I loose my
>dongle? I propose you think of this as a form of copy protection for a
>moment, obstructiing the Amiga owner, who also owns a program that runs on
>another platform. Follow me so far? The legitimate program for the other
>platform cannot be used on the favoured, Amiga machine, so it needs to be
>decopy-protected. What do you use if you wish to backup and/or deprotect
>software? A copier program. Most copiers can be employed by users who have
>little knowledge of copy protection, yet they succeed in making the copy. The
>more difficult protection schemes require "brain files" which are written by
>experts to achieve this end. End of transpiler/copy-protection analogy.
>
> Take a basic transpiler, such as the one Eddy Carroll wrote, and add a
>toolkit. The transpiler would do its best to translate and compile the source
>executable. If this failed, an expert, not just the average user, would either
>run the transpiler in expert mode, or a debug tool from the toolkit, which
>would work through any problem areas. The result of this would be an expert
>transpiler file. The beauty of this approach is that any user could run the
>transpiler, given access to the expert file. These expert files could be
>included with the release package and any new ones could be included in any
>updates or shared by conventional electronic means as PD.
>
>What do you think?
>
>csj
>
> No really officer, I wasn't speeding, just keeping a safe distance in front of
>the car behind me!
>
>Usenet: a542@mindlink.UUCP Phone: (604)853-5426 FAX: (604)854-8104
>
>
>From: daveh@cbmvax.commodore.com (Dave Haynie)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics
>Message-ID: <19792@cbmvax.commodore.com>
>Date: 12 Mar 91 22:39:53 GMT
>References: <1991Mar7.093149.18707@mintaka.lcs.mit.edu> <19749@cbmvax.commodore.com> <1991Mar12.011418.24768@mintaka.lcs.mit.edu>
>Reply-To: daveh@cbmvax.commodore.com (Dave Haynie)
>Organization: Commodore, West Chester, PA
>
>In article <1991Mar12.011418.24768@mintaka.lcs.mit.edu> rjc@geech.ai.mit.edu (Ray Cromwell) writes:
>>In article <19749@cbmvax.commodore.com> daveh@cbmvax.commodore.com (Dave Haynie) writes:
>>>In article <1991Mar7.093149.18707@mintaka.lcs.mit.edu> rjc@geech.ai.mit.edu (Ray Cromwell) writes:
>
>>>> Why doesn't AMAX multitask?
>
>>>Without massive patching of the Mac ROM, I don't think so.
>
>> Well it's not a heavy loss if you can't make the Mac ROM resident, but
>>why does AMAX have to take over the Amiga's operating system? The only
>>thing that would make it really diffcult to run MacOS under
>>AmigaDOS is if Mac code fiddles with absolute memory locations or the
>>OS implements function calls as traps/interupts.
>
>Well, the Mac OS fiddles with absolute memory locations, and the OS implements
>function calls as line-A exceptions. Apparently, all the absolute locations
>are in low memory and get swapped as part of the process context when you run
>Multifinder.
>
>>I also wonder why readysoft used a special disformat for Mac disks
>>instead of reading Amiga disks.
>
>No doubt this was to make Mac software work on Amiga disks. The Mac isn't
>as nice about filesystem independence as the Amiga is, so you can't really
>provide a loadable Mac filesystem kind of thing that maps Mac filespace
>into Amiga filespace adequately. So ReadySoft essentially just built a new
>device driver, which uses Amiga-readable formats, but Mac filesystem
>organization.
>
>This is apparently why Mac's don't generally talk to MS-DOS disks via an
>alternate filesystem like CrossDOS or MSH, but instead use a user program for
>the conversion, along the lines of the old PC Utilities.
>--
>Dave Haynie Commodore-Amiga (Amiga 3000) "The Crew That Never Rests"
> {uunet|pyramid|rutgers}!cbmvax!daveh PLINK: hazy BIX: hazy
> "What works for me might work for you" -Jimmy Buffett
>
>
>From: ifarqhar@sunb.mqcc.mq.oz.au (Ian Farquhar)
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: Emulator Mechanics [Transpiler]
>Message-ID: <1338@macuni.mqcc.mq.oz>
>Date: 13 Mar 91 03:24:04 GMT
>References: <5097@mindlink.UUCP>
>Organization: Macquarie University, Sydney, Australia.
>
>In article <5097@mindlink.UUCP> Chris_Johnsen@mindlink.UUCP (Chris Johnsen) writes:
>>Ian Farquhar (ifarqhar@sunb.mqcc.mq.oz.au) suggested that a compiled module be
>>run concurrent with an emulator type section so that in some parallel way, any
>>references within the source executable, which would also be loaded during
>>runtime of the emulation, could be validated. It could be argued that this
>>should be placed on the pro side of the ledger, but the incurred overhead
>>during execution would be large. This function, I had imagined initially,
>>would be carried out during the transpiler phase and not attached to, or
>>burdening, the runtime execution.
>
>No, I suggested that an image of the original code, without translation,
>be carried around with the compiled code, with indexes into the compiled
>code's equivalent sections that would allow jump tables and so forth to
>function correctly. This would be a memory intensive but low-time-overhead
>time way of resolving problems. It should also be noted that such a
>system would allow trapping of addresses that need to be handled by
>special code (hardware locations etc.), and that the image is also used
>for data storage, meaning that once loaded and allocated, the program
>would be unlikely to need any further allocation of heap.
>
>This system solves two problems: the data/code differentiation (if you
>accidentally compile some data, it is no great problem) though a much
>more minor problem remains if a couple of opcodes are missed because of
>data being accidentally compiled and the compiler assuming an opcode is
>the data for a false opcode, and also the problem of jump tables
>and jumping to locations stored in registers.
>
>--
>Ian Farquhar Phone : + 61 2 805-9400
>Office of Computing Services Fax : + 61 2 805-7433
>Macquarie University NSW 2109 Also : + 61 2 805-7420
>Australia EMail : ifarqhar@suna.mqcc.mq.oz.au
>
>
>From: srwmpnm@windy.dsir.govt.nz
>Newsgroups: comp.sys.amiga.emulations
>Subject: Re: CPU-emulators
>Message-ID: <18878.2801a4ad@windy.dsir.govt.nz>
>Date: 9 Apr 91 11:25:31 GMT
>Organization: DSIR, Wellington, New Zealand
>
>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)
>
>