The 6809 Emulator A design and development tool (C) Steven Goodwin 1994-7 Abstract A complete system for writting, running, and debugging machine code to be run on the 6809e processor (the fore-runner to the Amiga's 68000). It includes an assembler, very fast emulator system, and full development GUI. -- Comments -- From the first line I'll admit it...this is my excuse to start work on a Dragon emulator! Why? You might ask. Well, primarily, because I loved the machine. It had the nicest processor I've ever worked on (except the 68000 :-) ) and I even enjoyed its brand of BASIC! It's a shame the Dragon never really caught on. It was a very good computer. Unfortunately, it had no lower case letters - only inverse text. It was this (coupled with the slightly too bright green background colour) that caused it to fail in the marketplace, in my humble opinion. But, in attempt to re-live those days, I started work on this. However, this is a 6809 Emulator - NOT A DRAGON EMULATOR. It's purpose to simulate the running of the processor code, not programs written for the Dragon. There is a difference: none of the Dragon specific hardware is emulated. So, what does the 6809 Emulator do? Primarily, it permits the development of machine code software to run in a virtual environment under the control of your Amiga. The reason being it is easier and safer to do so. Knowing that any 'endless loops' can be aborted, and the stack/registers/memory can be inspected. This makes it ideal for students learning a simple (!!?!?!) machine code language (or anyone who doesn't want the hassle of link libraries, DLL's or operating system calls). It is also ideal for designing software for a microprocessor controlled system. You can run and test the system under the emulator, and when complete, the code can burnt in EPROM. Incidentally, it is not too difficult to extend this idea to build your own micro-computer! I kid you not. -- Copyright Notice -- This software, and all its associated documents, is copyright 1996 by Steven Goodwin. The version provided here may be freely distributed as long as no files are edited or deleted, and the copyright notice contained herein is not modified. No warranties, implied or otherwise, are given and this software is used at the users own risk, and no liability can be accepted for any damaged caused, either directly or indirectly, from this software. The 'Dragon32' machine snapshot file continues code that is Copyright 1982 by Microsoft Ltd. It is illegal to use this file if you do not own a Dragon 32 from which this data could be taken. This file is included in good faith, if you do not own a Dragon then this file must be deleted immediately. The programmer and distributors of this disk can take no liability for its misuse. -- Operation -- There are two halves: 1) ASA - An assembler to produce 6809 op-codes from their associated meumonics. Its actions are dealt with in a separate document - ASA_Manual.doc - also on this disc. 2) The Emulator - This runs a virtual 6809 processor inside your Amiga. It is fronted by a full GUI that allows easy access to the registers, condition codes and memory. The main emulator is controlled by a task bar with a number of buttons. Each button opens a window pertaining to that task. The buttons are: - Load - This is a generic load requester, and can load any of the following: i) 6809e snapshots - complete memory map, and details of the registers and condition flags. ii) Assembler snapshots - as produced by ASA. iii) Raw data The software will deduce from the file which type it is looking at, and load it accordingly. If it can not deduce the type it will be loaded as raw data, and you will be prompted for a start address. - Save - This opens a small window. From here you can save: i) 6809e snapshot. ii) Raw memory. You can then proceed to enter the start and end points. iii) Disassembly. Also takes start and end points, but produces a disassembled listed of the memory between the locations specified. The lower text requester accepts a file name and path, whilst the button on its right will open a file requester and enter the chosen file name into this gadget. Above the filename requester are two other text gadgets. These take the start and end addresses (inclusive) of the raw memory, or disassembly, block that will be saved to disk. - Hex View - Produces a scrolling list that covers the entire 64K memory map. Each line shows 8 bytes of memory that can be grouped as bytes, words (two bytes), integers (also two bytes, but displayed in decimal) and characters. In the case of the latter, any non-printable characters are shown as a dot. The list can be re-positioned by using the slider bar, or arrow buttons. In addition, the text requester beneath the list will take you to that specific address. Upon pressing return (or hitting the 'Goto Addr' button on its left) the list will redraw at the new position. The 'Goto PC' will jump directly to the line of the current program counter. You can open several hex view windows at once, each showing different areas of memory. - Disassembly - This window shows a disassembled version of the current memory. It functions in a similar fashion to the hex view window, insomuch as it has the 'Goto Addr' and 'Goto PC' functions, but the nature of the window makes it slightly more difficult to control. Here's why. The contents of the scrolling list will start at a particular address, and disassemble memory until it reaches the bottom of the list box. The number of assembly lines it produces will vary, because each 6809 instruction can occupy a variable number of bytes (between 1 and 4). It is not therefore sufficient to say one screen holds 20 instructions. So, when scrolling the list (particularly upwards) you might find the window starts at an address that lies inside another instruction, and incorrect or illegal instructions appear. To rectify this, move the list one byte a time (using the arrow buttons, or the text requester) until the instructions make sense. Unfortunately, this only comes with experience. Like hex view windows, you can open several disassembly windows at once, if you so wish. - Registers - This window covers several areas, and is usually open for the entirety of your work. On the left hand side are the main 6809 registers. Each can be altered as required, by inputted the required values in decimal, hexadecimal (with the '$' prefix) or binary (with the '%' prefix). After changing any register it is polite to press return! This has no relation on performance, but in the case of the PC it will update the disassembled instruction in the central portion of the window. On the right is the condition codes (CC) register, given as a series of check boxes. A tick indicates the flag is set. You can manipulate these at will, also. Finally, the far right has a series of buttons. 'Asm' opens a disassembly window and 'Hex' opens a hex view window. 'Step' will execute the instruction at the current program counter. 'Exec' will execute code on the virtual 6809 until a terminating condition is reached. That is: 1) The stack is exhausted, and an RTS is reached. 2) The 'Help' key is pressed. 3) A breakpoint is reached (see later) Note: To improve the emulators' speed the help key is detected by reading the keyboard directly. This means that if your keyboard doesn't produce $41 on a key down of the help key, the emulator won't stop. You should then either find which key does correspond...or register the 6809 Emulator to gain access to prefs, which allows you to change it. Before every 'exec' or 'step' command every register is copied into memory ready for the assembler to use. Similarly when the command completes, the entire display is updated, correcting the values in the registers, and any of the data shown in the hex view, disassembly or stack windows. Important Note: Stack Base This is not a real register. This is my creation for allowing the emulator to determine when the assembler routine has completed. When a subroutine exits (with an RTS instruction), the return address is popped off the stack, and the processor then jumps to this address. However, when using the stack base register, the virtual processor will exit emulation if the stack pointer has returned to the value of the stack base. You might like to think of it as a return address that points to the GUI environment. - Stacks - This window shows both system and user stacks, with the stack pointer and each return address shown thus: $7FBC : $4E20 Where $7FBC is the memory location of the stack, and $4E20 is the return address that will be used. The return address can be altered by using the text requester, if desired. Each stack is shown as a list, where the address at the top is the current stack pointer. - Memory Edit - This is a quick and easy method for reading information out of, and putting information back into, memory. It acts like the Peek and Poke commands. The basic window has a 'Location' requester (which indicates the memory location, from 0 to 65535), and a 'Data' requester (for numeric or string data). Below this are a set of buttons, arranged in two rows. The top row is labelled 'Write' and will place the data into memory, starting from the location given. A 'null' string means that the text string will automatically be appended with a null character (zero) before being written. The bottom row is to 'Read' data, and will extract data from the memory location given and place it in the 'data' requester. In both cases, the machine acts like a little endian machine. This (rather fancy phrase) means that if the number 12 is written into memory as a 'word' it will occupy two bytes: the most significant (rightmost, or upper) byte will read zero (0), and the least significant (leftmost, or lower) will be twelve (12). The distinction between 'byte' and 'word' is important, and must be used with care. - Breakpoints - These clever devices will stop the emulation when a register has reached a pre-determined value. In fact, emulation will halt when a particular 'expression' has occured. This could be when 'X > 1024' or when 'A=2', for example. The possible combinations are, Registers Comparisons Equivalent instr. A > Greater than bgt and bhi B < Less than blt and blo X >= Greater than or equals bge Y <= Less than or equals ble S = Equals beq U <> or != Not equals bne PC Sb Note: The 'Sb' breakpoint would not normally be used, as it can not be altered from within the virtual processor. To create a new breakpoint, just hit 'New'. This will duplicate the currently selected breakpoint. You then have access to the other gadgets to modify it accordingly. Whenever a change is made, it will be seen in the list. The buttons along the bottom of the window are self-explainatory, but there are a couple of further notes. The 'enable' check box only applies to the currently selected breakpoint. This is visible from the list box, as any disabled breakpoints are shown in blue. These breakpoints will not be active whilst running the emulator, but can be brought back to life without having to re-program them. To disable all the breakpoints just de- select the 'Use Breakpoints' check box. Although nothing will appear to happen, none of the breakpoints listed (whether enabled, or not) will halt the program. Finally, a note about the two forms of greater than. The difference between 'bgt' (branch greater than) and 'bhi' (branch higher) is that 'bhi' ignores the sign bit (i.e. it is an unsigned operator), whilst bgt considers it. 'blo' is also an unsigned operator. For example: 128 is bhi than 2 but 128 is not bgt 2, because, when signed, 128 is -128 - Symbols - To make memory access easier, the emulator supports a symbol table. This is nothing more complex than a look-up table featuring a list of symbols (or labels, if you prefer) and a number that is equivalent. To add a new symbol, simple press the 'Add' button. This will create a new symbol. By default this is called 'Unlisted', and is assign to zero (0). You can then alter these values as desired in the requesters at the bottom (labelled 'address' and 'label'), pressing return to set each value. The buttons on the bottom of the window have obvious functions. One feature that has extra functionality however, is the 'Load' button. If a symbol table already exists in memory, it is possible to merge another symbol file with the one in memory up to the memory limit (30 symbols in the shareware version). A requester will be opened, prompted you for an answer, whether you want to merge the symbol files or not. Important Note: When a symbol list exists, it is searched whenever a text requester is used. That means that instead of entering an address as '$4e20' into the PC register (for example), you can use a symbol (like mc_start) from the symbol table. - About - Now really...do I need to explain this? -- What I did to speed it up. -- * Used the Amigas status register as the equivalent in the 6809. I could do this easily because the main 4 flags (NZVC) are in the same bit positions on both processors. The only time they are manipulating individually is on the instructions ANDCC and ORCC, so I wrote code to change my style of CCR to that of the actual 6809. This code is also used when the CCR is PUSHed or PULLed from the stack, as it is possible to change the entire CCR by pulling the 'wrong' value of it. However, in future versions I may have to vary this code, as higher processors require the use of GetCC and PutCC, that will take longer to execute than specific code. * Used macros instead of subroutines (in most cases except, for example, the index addressing mode where the resultant code becomes obtuse and takes instructions out of range for the branch instructions). * Used self-modifying code to create breakpoints and change between 'Step' and 'Exec' modes. This is very bad practise, and is the first time I've done it since...well, the last time! * Used equivalent 68K instructions at all times, because this sets the appropiate flags, saving perhaps an extra cycle. * Kept all the virtual registers in the 6809's registers. i.e. the A reg was held in d2 AT ALL TIMES. So no clock cycles were wasted reading data from memory. * Used .b and .w to save code checking for overflow etc. I'm glad I read the manual before I starting implementing this :-) But it's still my weakest area. * Separate code routines for decoding an instruction during emulation, and reading it in disassembly. I could have modularised it (as a *real* software engineer would have) but it would have slowed it down too much. As it is, I can change the macros if I wanted, but the first version of the disassembler was in AMOS, so I thought it would be quicker just to port it! Besides - the 6809 is not going to be updated is it! * Used a jump table consisting of 'bra xxx' instructions. Although two jumps take extra time, it also reduces the instruction decode routine to the equivalent of: Goto OP_CODE * 4 Which saves a great deal time over, If OP_CODE = 0 Goto 232 Else If OP_CODE = 1 Goto 353 ... -- What I WILL do to speed it up. -- * Refine my macros. Remove any redundant code. Re-generate the source (with macros replaced) and produce tailored versions of each instruction. This will take some time, and may only save a few clock cycles so this is quite low on my priority list :-(. * Buy a new computer with a 68040 in it :-) Learn a bit more 68K code, as I'm hoping I'll an instruction on later processors that lets me define an area of memory (i.e. that of my pseudo text screen) and get the processor to call my routine (interuppt style) when an attempted access is made. -- What I WOULD LIKE to do to speed it up -- (by I am prevented by doing it) * Read a word from any memory location - even if it DOESN'T fall on an even word boundary. It's my only niggle about the 68K (that I've found so far). -- New Features -- Software is never finished before it's out of date! I believe that. As a consequence, I am hoping (time and workload permitting) to add several new features to the emulator. They include, but are not limitted to: Keyboard, joystick and mouse (!) input. Memory-mapped I/O triggers (executes user-programmed code when specific memory areas are used) The Dragon graphic modes Different ASM modules holding optimised assembler for different processor configurations. Full menu bar allowing access to more 'little' options (search routines, hex calculator etc). At this stage, that is purely a wish list. But, as time arises, I will sit down and work on each feature. But I will only be encouraged to do so knowing that somebody else is using the product. And if you are, you must register... -- Registering -- Let's face it. This is mean package! And you can't expect me to do all this work for nostalgia, can you? So, if you use this system for more than 30 days, or find it useful, you are encouraged to register it for the measily sum of £5. This gets you the complete source (to both Amos and assembler parts) and the latest version of the system itself. Q. Where do I send my money? A. Steven Goodwin 105 St. Johns Road Clacton-on-Sea Essex CO16 8DB Q. What do I say? A. Try printing this off.... (or copying the relevant bits if you're without a printer) o/_________________________ CUT HERE ________________________________ O\ Your Name:_______________ Address :_______________ _______________ _______________ _______________ Hi Mr. Steven Goodwin, I would like to register my copy of the 6809 Emulator because, a) There's no high pressure sales talk... b) I want access to the good bits you left out! c) I don't believe your self-modifying assembler will confuse me! d) It brought back some good memories...before the days of the Guru! e) I have a tremendous guilt complex! f) All of the above (circle as appropriate) I enclose a cheque/postal order for £5 (which includes P&P) because I'm a kind hearted soul whos cares about the people who make my software. Thanks very much, Name ________________ (not completely necessary, but ties up the letter nicely) o/_________________________ CUT HERE ________________________________ O\ That's all folks!!!! See you on the next release...