Emulator Logo

Manual Pages


Introduction

Please note and remember that this manual is very much a work in progress and is released in this state so that I can get the software out to people who wish to use it sooner rather than later.

Overview

The Feersum Pic Emulator is a Java program that emulates a Pic Micro 16x84 Microcontroller. It can assemble and diassemble Pic source and object (.hex) files. Pic software can be run on an emulated Pic microcontroller connected to virtual hardware, such as switches, leds and other more complex components.

The software runs as either an applet or a stand-alone application and can load assembled (.hex) Pic code produced by assemblers and compilers for the 16x84 series of 8-bit processors. Assembled code is disassembled into a listing and can be run or singled stepped while registers and chip inputs and outputs are examined or changed. Source code can be loaded, edited and assembled to be run in a similar manner.

The great strength of the Feersum Pic Emulator is that it uses Java to implement a system of Plugins. Plugins can emulate real physical devices connected to the emulated processor - generating input, or responding to output as the emulator runs. The Plugin Interface is completely open so plugins can easily be written to emulate any device. A simple set of plugins are already available, including demonstration code to help developing new plugins.

The Emulator is fast too. On a 200MHz PC, running Sun's Java 1.2 VM, emulated speeds of over 20MHz can be reached. More modern machines can easily exceed the speeds that current real chips are capable of.

The Emulator is written in standard Java and will run under Java 1.1 or newer Java VMs. It requires no special hardware or software other than that needed to run Java itself, and the distribution is less than 100K.

History

This project was bourn out of embarassment. A colleague kindly introduced me to some friends who were looking for a Java engineer. My contract at the time was reaching its end, so I went along to meet them in a local pub (traditional interview territory for Cambridge). Not expecting a full interview and distracted by my work, I didn't prepare for the meeting. When it turned into a Java test halfway through the roast-beef sandwiches I was caught off-guard (and with a mouthful of crusty roll). To my embarassment, and as a great disservice to my colleage, I did not shine in the interview.

One of the technical areas we discussed was how to write 'efficient' Java programs. Of course there are some simple rules that help - don't directly manipulate Strings, don't create unnecessary Objects and so on. I didn't manage to communicate any of this to my interviewers and spent the rest of the day brooding over my poor performance.

As I was brooding, I started to think about emulators. The core problem is interpreting a machine code instruction, deciding what it means and executing a small piece of code that emulates that function. In classic procedural languages, this task is often written as a big (very big) switch statement. In Java, you could take a similar approach, but there is an interesting alternative. I won't go into the full details here (see the How it Works section for that), but I wanted to try it out and see what would happen.

I had just been reading some of the sites of people who were squeezing more out of the Pic than could possibly be expected. People like Rickard Gunée were making this tiny, simple, cheap chip do tricks like generating TV signals and playing Tetris. Suddenly, I knew what I wanted to do.

Three and a half thousand lines of code later, the Pic Emulator reached a stage where it was more than a quick fiddle. I could play Tetris (which, now I come to think about it is perhaps not that much of an achievement) and run my own Pic programs. It seemed like a good idea to release the program to the world in general and see what they thought.

Resources

Not yet written...

User Guide

Running PicEm

PicEm is released as a Java archive (.jar) and Microsoft Cabinet File (.cab) which together allow the software to be run as an applet under Netscape Communicator and Internet Explorer, as well as being run as a standalone application. The web pages that this document is part of include a page with the appropriate links to run the Applet within your browser.

Running within a browser however introduces a number of limitations - the main one being that files cannot be saved from the Emulator. Running the Emulator as a standalone application allows edited and assembled files to be saved and provides much more helpful file dialogs.

To run the Emulator as an application, you will need at least Sun's Java Runtime Environment (JRE), version 1.1 or higher. JRE 1.3 is recommended - it makes a significant improvement in the emulation speed, and as the software is largely developed using Java 1.3 SDK, it is the most thoroughly tested environment. You can download the JRE from Sun's Site: www.javasoft.com

With the JRE or full Java release installed (you will need the SDK if you wish to compile your own Java software or PicEm Plugins) you can then run PicEm. Start up a command prompt and change to the directory that contains the picemulator.jar file that came with the software release. This directory also contains the plugins.txt file that PicEm uses to identify Plugin classes and a few other files. You can run the emulator under Windows 9x or NT simply by typing:

java -classpath $CLASSPATH$;picemulator.jar picem.PicEmulator

This must be modified if running under Unix (e.g. Linux) to use a colon rather than semi-colon to separate classpath entries:

java -classpath $CLASSPATH$:picemulator.jar picem.PicEmulator

This tells java to use your existing classpath (if any), and add the .jar file to it to find the classes that make up the PicEmulator. It then calls up the main class (picem.PicEmulator) which starts up the software and displays the user interface.

At the moment the emulator must be run from the directory that contains the additional files. In future, it should be possible to use an environment variable to define the home for the emulator, so it can be run more conveniently from any location.

The PicEm Environment

The main view of PicEm shows a number of menu buttons along the top of the frame, a main, tabbed set of windows and below them information on the status of the emulated chip and finally a status bar.

The menu buttons include a 'File' button that brings up a menu allowing files to be loaded and saved, new text files created and listings to be assembled. Next to it are a series of buttons that allow the emulation to be started, stopped, and single stepped. The Reset button resets the emulation and sets the program counter to 0. The Current button displays the current instruction being emulated in the Processor View. Clicking Step will execute exactly one instruction (unless that instruction is part of a DECFSZ/GOTO delay loop, in which case the emulator will execute the entire loop). The 'Over' button acts in much the same manner except that if it is clicked when the processor is about to execute a DECFSZ instruction, the processor will run until the loop instruction completes. If the Over button is clicked when the processor is about to execute a CALL instruction, the entire called routine will be executed and the emulator will stop at the instruction immediately following the Call. For both Step and Over, the number of machine cycles emulated are shown in the status bar at the bottom of the emulator display. The Run button runs the emulation, which can then be stopped with the 'Stop' button - at which point the emulated speed of the processor is displayed on the status bar. The final button presents the About dialog.

When first started, the tabbed windows include:

In addition, text files may be loaded or created and later assembled. For each file an additional simple File Edit View is created.

The line below the tabbed windows shows some details of the processor state. The program counter (PC) is shown and the contents of the W register. Individual flags can be examined by entering the flag address in the Flag box and pressing the '=' (Equals) button or single stepping the emulator, at which point the content of that flag location is shown. A new value may be entered in the field and the flag set to that value by clicking the 'Set' button. Both flag number and contents are displayed in Hexadecimal.

Log View

The Log View is a scrollable list of actions that have been carried out by the emulator. This includes loading files, assembling and assembly errors and running the emulator itself. The log view cannot be edited or saved.

Processor View

Plugin View

Plugins may be selected in the left hand window. This will then show information about that plugin and the configuration string for that plugin in the right hand view. Plugins can be displayed by clicking 'Show' - at which point the Plugin will be linked to the processor and can respond to the emulator running. Closing the plugin window should result in that plugin disconnecting from the emulator - in some cases this will dramatically improve emulation speed.

File Edit View

Files can be opened by clicking File -> Open.. or created by clicking File -> New. The editor is simple, but includes the following additions:

When a text file is visible in the tabbed windows, it can be assembled by clicking File -> Assemble. Errors encountered during assembly are reported on the status bar and in the Log View. The editor will go to the line that caused the error to occur.

The Assembler

Instructions

This is not meant as an introduction to the Pic processor family, as there are much better written texts on the subject. However, when writing code, the following Instructions are understood by the Assembler:

Opcode (Hex)InstructionParametersMeaning
0000NOPNo operation
018fCLRFfClear f
0100CLRWClear W
30vvMOVLWvMove Literal to W
008fMOVWFfMove W to f
08ffMOVFf,dMove f
3EvvADDLWvAdd literal to W
3CvvSUBLWvSubtract W from literal
39vvANDLWvAND literal and W
38vvIORLWvIncl. OR literal and W
3AvvXORLWvExclusive OR literal and W
07ffADDWFf,dAdd W and f
02ffSUBWFf,dSubtract W from f
05ffANDWFf,dAND W and f
04ffIORWFf,dInclusive OR W and f
06ffXORWFf,dExclusive OR W and f
0EffSWAPFf,dSwap halves f
09ffCOMFf,dComplement f
2kkkCALLkCall subroutine
2kkkGOTOkGoto address (k is nine bits)
0008RETURNReturn from subroutine
0009RETFIEReturn from Interrupt
34vvRETLWvReturn with literal in W
0062OPTIONLoad OPTION register
006fTRISfTristate port f
03ffDECFf,dDecrement f
0BffDECFSZf,dDecrement f, skip if zero
0AffINCFf,dIncrement f
0FffINCFSZf,dIncrement f, skip if zero
0DffRLFf,dRotate left f
0CffRRFf,dRotate right f
1bffBCFf,bBit clear f
1bffBSFf,bBit set f
1bffBTFSCf,bBit test, skip if clear
1bffBTFSSf,bBit test, skip if set

Key:

These are the core instructions for the 16x84 family, with the exception of the SLEEP and CLRWDT instructions which are not currently implemented. In addition to these core instructions, the standard Microchip assembler supports a number of 'Special' instructions which are short forms of those above. Some special instructions encode to a specific single opcode. Others may encode to two separate processor instructions. The special instructions are listed below:

InstructionParametersMeaningEquivalent
ADDCFf,dAdd Carry to FileBTFSC 3,0
INCF f,d
ADDDCFf,dAdd Digit Carry to FileBTFSC f,d
INCF 3,1
BkBranchGOTO k
BCkBranch on CarryBTFSC 3,0
GOTO k
BDCkBranch on Digit CarryBTFSC 3,1
GOTO k
BNCkBranch on No CarryBTFSS 3,0
GOTO k
BNDCkBranch on No Digit CarryBTFSS 3,1
GOTO k
BNZkBranch on No ZeroBTFSS 3,2
GOTO k
BZkBranch on ZeroBTFSC 3,2
GOTO k
CLRCClear CarryBCF 3,0
CLRDCClear Digit CarryBCF 3,1
CLRZClear ZeroBCF 3,2
MOVFWfMove File to WMOVF f,0
NEGFf,dNegate FileCOMF f,1
INCF f,d
SETCSet CarryBSF 3,0
SETDCSet Digit CarryBSF 3,1
SETZSet ZeroBSF 3,2
SKPCSkip on CarryBTFSS 3,0
SKPDCSkip on Digit CarryBTFSS 3,1
SKPNCSkip on No CarryBTFSC 3,0
SKPNDCSkip on No Digit CarryBTFSC 3,1
SKPNZSkip on Non ZeroBTFSC 3,2
SKPZSkip on ZeroBTFSS 3,2
SUBCFf,dSubtract Carry from FileBTFSC 3,0
DECF f,d
SUBDCFf,dSubtract Digit Carry from FileBTFSC 3,1
DECF f,d
TSTFfTest FileMOVF f,1

Numeric Literals

The assembler recognises literals in the following formats: So 0x30E is equivalent to 0b1100001110 or 0d782. The default base (radix) for numbers is base 10, so 1234 = 0d1234. However, the LIST command (explained later) allows the default base to be changed to hexadecimal.

At present character and string literals are not recognised by the Assembler. (For example 'c' or "This is a message" will not be assembled into their numeric equivalents).

Comments

Comments in the listing start with the semi-colon ';' character and continue to the end of the line. Comments may contain any combination of characters and are ignored by the assembler.

For example:

; This is my comment, It was written on 16th Jan 2001

Labels

A Label is a text string that has an associated numeric value. A label is any sequence of characters, starting with a letter (A..Z,a..z) and including letters, numbers and underscore characters. Valid labels are 'myLabel', 'an_address', 'label234'. Invalid labels are '3again' (starts with a number) or 'as-were' (minus symbol is not valid in a label). Labels are not case-sensitive, so 'Hello' and 'hELLO' are treated as the same. Instructions, special instructions and assembler commands are reserved and cannot be used as labels.

Address labels must start at the beginning of a new line. It is not necessary to append a colon ':' character to address labels. The value of the address label will be the address immediately following the last assembled instruction.

Expressions

Numeric expressions consist of numeric literals and labels, and the operators '+' (addition) ,'-' (subtraction) ,'*' (multiplication) ,'/' (division) and '^' (to the power). Normal operator precedence is observed, and brackets ('(' and ')') can be used to control evaluation.

Assembler Commands

The assembler recognises a number of commands that allow the assembly process to be controlled. These are not assembled into opcodes, but will affect the way in which the file is assembled.

ORG address

The ORG command sets the address that subsequent instructions are assembled from. The assembler normally starts assembling the first instruction it encounters at address 1, the second at address 2 and so on. An ORG command can instruct the assembler to assemble to another set of locations.

For example: ORG 0x100 ;Assembles from address 256 onwards.

LIST param=value,param2=value2...

The LIST command allows assembler settings to be controlled. At present, only two parameters are supported. These are 'p', which identifies the target processor for assembly (and must be either '16c84' or 'PIC16c84') and 'r' which sets the default radix (base) for numeric literals, and can be either 'hex' or 'dec'. As the 'p' parameter may be accidentally interpreted as a hex value if the radix is set first, the target processor should be set first, or be given as 'PIC16c84' to avoid ambiguity.

For example: LIST p=PIC16c84,r=hex

label EQU value

The EQU command allows a label to be assigned a value. The value may be any valid numeric expression.

For example:

     countReg EQU 0x34
     minValue EQU 20
     maxValue EQU 45
     range    EQU maxValue - minValue

DW value1,value2...

The DW command allows data to be specified to be stored at the current address. Each value may be any valid numeric expression. For the PIC, addresses 0x2100 onwards are part of the EEPROM non-volatile memory, so the following code snippet will store data into this for later retrieval by the software:

        ORG 0x2100
	DW      0x01, 0x02, 0x03
	DW      0x01, 0x03, 0x05

END

The End command normally marks the end of the assembly file, but is ignored by PicEm.

label MACRO

Macros are short pieces of code that can be written once, and then referred to by name in the rest of your code, saving having to type them out more than once. Note that macros are expanded into the original code before assembly is carried out so they do not save on code space, they only reduce typing (and potentially make code more readable).

The Macro facility in the assembler is very simple. Macros cannot take parameters. Labels in macros must be declared using the LOCAL command, which takes a single label as its parameter. Local labels are expanded into different (unique) labels each time the macro is expanded. The Macro definition ends with the ENDM command.

This is an example of a simple macro that provides a delay:

delay         MACRO
              LOCAL   loop
              movwf   delaycnt
loop          decfsz  delaycnt
              goto    loop
              ENDM

This code declares a macro 'delay' which stores the value of the W register in delaycnt, then loops that many times, introducing a short delay. The delay macro can then be used as follows:

              movlw   0x09  ; Loop nine times
              delay

When this is assembled it will be expanded to look like the following code:

              movlw    0x09   ; Loop nine times
              movwf    delaycnt
delay_loop_2  decfsz   delaycnt
              goto     delay_loop_2

Technical Section

How It Works

Let me stress that this is quite probably not the most efficient way to write an emulator. However, it does provide some interesting things 'for free' and is an neat demonstration of Object Oriented design.

The core of any emulator is the process of interpreting the bits that make up a machine instruction, deciding what that instruction is and executing some code that emulates the function. Emulators essentially are comprised of a big loop that interprets each instruction in turn and gives some feedback of the state of the machine to the user.

The simplest form of instruction emulation uses a switch statement to match the bit pattern of the instruction to a few lines of code to emulate the function. Though compilers can dramatically improve the execution of a switch statement, the basic behaviour is 'Is it this instruction? No.. Is it this instruction? No..' and so on until a match is found. In C we can explicity do what a compiler might do for us, making the whole process more efficient by using a lookup table.

The lookup table matches an instruction against a function that will emulate it. The code simply has to lookup the function for a given instruction and call it. Unfortunately this is not possible in Java, because we don't have the equivalent of function pointers and can't produce an lookup table as we would in C.

However, there is a neat solution. We can represent an instruction as an object that knows how to emulate itself. Instead of a table that allows us to lookup functions, we have a table that allows us to lookup Instruction objects. We can then just ask the relevant Instruction to 'emulate yourself' and we have quickly called the right code.

The Feersum Pic Emulator uses exactly this approach. An abstract class 'Instruction' provides all the common things that an instruction needs to know about and do. For each of the different processor instructions, we can then extend that class and implement the missing 'emulate yourself' method that will be specific to that instruction.

As the Pic uses a Harvard Architecture, our emulation job is easy. The machine cannot change the code that it runs, so we can read the program, transform it into an array of Instructions and we are then ready to emulate the processor. To run the emulation, we start at the beginning of the array, ask the first Instruction to emulate itself, then the next, then the next and so on..

We get some things 'for free' from this approach. With a few simple additions, an instruction can know what it looks like to a programmer (its Mnemonic), how to display itself in a listing and even how to build itself from source code. Our Instruction class can then do more than emulate the processor, it can act as a disassembler and an assembler. Suddenly we have a complete development environment.

Writing Plugins

Plugins are comprised of two distinct elements - The User Interface which is displayed by the Emulator application and one or more Processor Listeners which connect to and communicate with the emulated processor. The plugin has access to much of the state information for the processor, so that Plugins can not only emulate hardware, they can provide views on the processor's memory, registers and other information.

The user interface is written by extending the Plugin interface class and provides methods for the plugin loader to initialise and display the plugin when requested. The PortListener interface can also be implemented, and allows the plugin to detect and respond to changes on the Pic's ports. At present there is no means to synchronise writing data to the Pic with the execution speed - though this shall eventually be provided by a PortWriter interface (which sadly will somewhat reduce the speed at which emulation can be run).

This explanation of Plugins will be based on the LED Plugin. The source code for the LED plugin is included in the Emulator distribution and important sections are reproduced here.

More to be written here..

What Is Missing

The Emulator and the Development Environment are not complete, reflecting the fact that this is free software developed during contributor's spare time. Though not exhaustive, this is a list of the items that are not currently part of the software:

Processor - Instructions

Both the SLEEP and CLRWDT instructions are not coded and cannot be assembled or disassembled. Otherwise, all the Instructions listed in Microchip's PIC16C84 manual are implemented. Special instructions, as provided by the MPASM assembler, are correctly assembled into one or more proper PIC opcodes. (As an example, SKPZ is assembled into BTFSC Status,3).

Processor - Hardware

The Interrupt subsystem is not currently implemented. As a result, the watchdog timer, interrupt on Port B and other interrupt sources are not emulated.

Assembler - MACROS

The Macro expander is very simple. It does not support parameters for macros, conditional assembly or looping constructs.

Assembler - Expressions

Again, the expression evaluation in the assembler is very basic. Only the essential four arithmetic operators and '^' (to the power of) are supported.

Assembler - Include Files

Include files are not supported.

Back