CSC 6Fh Final Assignment: VM6Fh An Excercise in Meta-Assembly A "virtual machine" is the specification of a cpu architecture. It includes descriptions of registers, stack usage, interrupts, and an instruction set (that is, a virtual assembly language). To implement a virtual machine, we use an underlining "meta-machine". The virtual machine's functionality is implemented as a program on the meta-machine, written in meta-assembly. For example, the x86 architecture can be thought of as a virtual machine. It's implemented in modern Intel cpus using an internal, RISC-style meta-machine (this is called "microprogramming"). The Java Virtual Machine is another typical example. To run java on a real machine, you need to implement a JVM interpreter in the real machine's native langauge. In this assignment, I will specify a simple virtual machine called VM6Fh, and you will implement it in Sparc assembly. The Sparc CPU will be our meta-machine. Virtual Machine 6Fh Specification: VM6fh is a simple, stack-based machine. It has no general-purpose registers whatsoever (not even a simple ax). All action take place on the stack. For example, the instruction "add" will add the top two elements of the stack, pop both elements, and pushes the result on top of the stack. VM6fh has only 512 bytes of memory. They are divided into the following sections (using gcc syntax): vmcode: .skip 128 vmdata: .skip 128 vmstack: .skip 128 vmbios: .skip 128 ! reserved for future use Data in vmdata and vmstack are stored in units of 4-bytes each. Data in vmcode are in units of one byte each, because each instruction will be only one byte long. VM6Fh does have three internal registers: vpc: holds the address of the next instruction (in vmcode region) to execute. vir: holds the current instruction being executed vsp: points to top element of stack. The stack grows backwards as in x86 and sparc. Initially, vpc should point to vmcode, and vsp should point to vmstack+128. VM6Fh has a very simple instruction set : there are only eight instructions. An instruction is represented with a single byte. The most significant (left) three bits of the instruction byte determines the "opcode", and the remaining 5 bits are used for the operand. The bit patterns of the instructions and their meanings are as follows: 000: add adds the top two elements of the stack, popping them. stores result on top of stack. [vsp+4] = [vsp] + [vsp+4]; vsp += 4; 001: sub subtracts, works like above (may replace this with something more interesting later). [vsp+4] = [vsp] - [vsp+4]; vsp += 4; 010: nand takes the bitwise nand (!(A&B)) of the top two elements on the stack (popping the two elements). pushes result on stack. If you took a class in digital logic you should know that nand can be used to implement any other logical operator. [vsp+4] = not([vsp] and [vsp+4]); vsp += 4; 011: push This instruction takes an operand. The last 5 bits of the instruction byte is shifted 2 bits to the left to form a 7-bit offset into the vmdata region (because data are stored in units 4-bytes each). The (4-byte) value stored in the indicated location will be pushed on top of the stack vsp -=4; [vsp] = [vmdata+operand*4]; 100: pop The last 5 bits are interpreted as a memory offset in the same way as the push instruction. The top element of the stack is stored (and popped) into the indicated memory location [vmdata+operand*4] = [vsp]; vsp +=4; 101: pushc push constant. The last 5 bits is used as a constant operand. It is expanded to 32 bits and pushed onto the stack. vsp -=4; [vsp] = operand; 110: jz Interprets the last 5 bits as a positive displacement from the current instruction, and jumps to that location by changing vpc, if the top stack element is zero. Note: you can only move forward by up to 31 instructions from the current one (useful for jumping out of loops). if ([vsp]==0) vpc = vpc + operand -1; (-1 since fetch stage should have automatically incremented vpc) 111: ja Interprets the last 7 bits of the top stack element as a memory offset into the vmcode region. It pops the stack, and resumes the program at the new address by changing vpc. Note: this works very differently from jz; it doesn't have an explicit operand. vpc = vmcode + ([vsp] & 0x0000007f); vsp += 4; Be sure to check for stack over/underflow where appropriate. With imagination you can use these instructions to implement numerous other functionalities. To simulate this architecture, you must first decide which meta-level (that is, Sparc) registers you will use. Do NOT use %sp for vsp - that will be a big mistake. I suggest you use %o0 for vir, %g5 for vpc, and %g7 for vsp. Your virtual machine needs to execute in a basic fetch-decode-execute cycle: Fetch: load instruction byte pointed to by vpc into vir. advance vpc Decode: examine first 3 bits of vir to find out which instruction it is, extract operand if necessary. Execute: execute appropriate function. I suggest you define leaf procedures for the 8 instructions, and combine decode and execute into one procedure that decodes the instruction, extracts the operand, and calls the appropriate function. On the web page you will find a C file vm6fh.c, which contains some C functions that you can call from your assembly program (I will explain them in detail in class). The functions include ones that translates the ascii represention of instructions into binary form, and loading the contents of vmcode with a couple of small programs. The "main" procedure will need to be written as part of your assembly code. It will initialize the virtual machine, load a program (by calling a C function), and start the fetch-decode-execute loop. Compile your program with: gcc -O6 vm6fh.c yourfile.s ----------------------------------- I have done a lot of the work already and will provide you with many useful tools and hints. But this is undoubtedly the most sophisticated assignment I've given you this semester. It is meant to take the place of a final exam (it's important). This assignment can be completed by teams of AT MOST TWO people each. The two team members will be: Technical Leader Design and Documentation Leader This does not mean that only the technical leader will code: both people must work together, but each person should be mindful of their emphasized area of responsibility. I will be keeping track of your progress. The assignment is due at the time of the final exam on 5/15. (please come during final exam time to demonstrate your final program).