CSE 378 - Spring 1998

Machine Organization and Assembly Language Programming

Problem Set #5

Due Friday, May 8, 1998

 

This assignment continues the construction of the Java Virtual Machine (JVM) you began writing in Assignment 3.  Hopefully you designed the code in an extensible fashion, and it is debugged.

You have two alternatives:  extend your JVM code to implement the features in this assignment, or extend Zack's sample program.  If you are to use the sample solution, you'll need to answer the following questions:

  1. What is the purpose of the .align directives in the data segment?  Why is the second field (the number of arguments) considered to be 2 bytes away from the start of the record, and why is the string 4 bytes away?
  2. Describe (briefly) what each function/procedure in the program does, and what it returns.  (Please don't give a re-hash of the comments in the program!)

You'll need to add the following new bytecodes:

Name Bytecode Instruction Format Operations Description
IALOAD 0x2e IALOAD POP v1, PUSH *(v1) Load from index at top of stack
IASTORE 0x4f IASTORE POP v1, POP v2, *(v1) = v2 Store at index at top of stack
IDIV 0x6b IDIV POP v1, POP v2, PUSH (v2/v1) Integer division (no rounding)
END 0x00 END End program End your program

Plus the original set, whose operations are described in more detail here:

Name Bytecode Instruction Format Operations Description
IADD 0x60 IADD POP v1, POP v2, PUSH (v2+v1) Integer add
ISUB 0x64 ISUB POP v1, POP v2, PUSH (v2-v1) Integer sub
IMUL 0x68 IMUL POP v1, POP v2, PUSH (v2*v1) Integer mul
ILOAD 0x15 ILOAD index PUSH *(index) Load from mem at index
ISTORE 0x36 ISTORE index POP v1; *index = v1 Store to mem at index
BIPUSH 0x10 BIPUSH immed PUSH immed Byte Immediate push
SIPUSH 0x17 SIPUSH immedhi immedlo PUSH immedhi_immedlo Short Immediate push
POP 0x57 POP POP v1 POP value, discard
IFEQ 0x99 IFEQ offsethi offsetlo POP v1; cond. br. to PC+ offsethi_offsetlo Branch if v1==0
IFNE 0x9A IFNE offsethi offsetlo POP v1; cond. br. to PC+ offsethi_offsetlo Branch if v1!=0
IFLT 0x9B IFLT offsethi offsetlo POP v1; cond. br. to PC+ offsethi_offsetlo Branch if v1<0
IFLE 0x9E IFLE offsethi offsetlo POP v1; cond. br. to PC+ offsethi_offsetlo Branch if v1<=0
IFGT 0x9D IFGT offsethi offsetlo POP v1; cond. br. to PC+ offsethi_offsetlo Branch if v1>0
IFGE 0x9C IFGE offsethi offsetlo POP v1; cond. br. to PC+ offsethi_offsetlo Branch if v1>=0
GOTO 0xA7 GOTO offsethi offsetlo Jump to PC+ offsethi_offsetlo Unconditional branch
IRETURN 0xAC IRETURN POP v1 Integer return

 

JVM Design

Remember that the JVM is a stack machine.  This means it has a stack of operands in some portion of memory; and all instructions will deal with operands taken from that stack.  In addition, there is an area of local memory which the JVM can use.   Basically, the stack works similarly to MIPS registers, and the local memory is just like standard RAM.

For the purposes of this class, assume that all storage is in 32-bit words; your stack will need to hold up to 256 instructions, and memory will need to be able to store up to 256 words.  You'll need to make space in your JVM data segment for these areas, as well as the area for code (assume we won't give you a program more than 1024 bytes, and you won't have to write one longer than that, either).  Note that you'll need to keep track of the JVM's current instruction (i.e. its internal program counter), as well as the JVM's internal stack pointer.

Instruction Semantics

Hopefully the description of what each instruction does is clear from the table above.   All concatenations of values, e.g. offsethi_offsetlo mean that you have to combine two 8-bit results into a single 16-bit result ((offsethi << 8) | offsetlo).   The arithmetic instructions deal with signed 32-bit numbers from the stack.   Note that the only values that can be put on the stack are 8-bit or 16-bit values.   Both BIPUSH and SIPUSH need to sign-extend the values they push to the full 32 bits.

The branch and goto instructions look at the top value of the stack, and if it meets the conditions, they will do a branch.  Again, the offset needs to be a sign-extended value, because you need to add it to the PC to get the new result.

The IASTORE and IALOAD are both indirect instructions, which go to a location in memory in order to get the value for the stack.  This is how you can create variables; simply reserve space somewhere in memory to hold them, and you can pass values to and from the stack.

The END instruction is not really part of the real JVM, but we will use it to make your job easier, in terms of handling program termination.

Your Job

You need to write the Execute and Store stages of the JVM.  Most of the instructions should only take a few real MIPS instructions to implement.  You may start with your code from Assignment 3, or from Zack's sample code.

Make sure your entire JVM is inside a function called jvm.  The function accepts the address of the bytecode program in $a0, the address of the top of the stack in $a1, and the address of location 0 for local storage in $a2.  The JVM function should also copy the value at the top of the stack to register $v0 and return it when exiting.

You should write a small test program using Java bytecodes for each instruction, to verify that your JVM works properly.

The final step is to write a Java bytecode program to sum the contents of an array, returning the result on the stack, and to verify that it runs on your JVM program.   The array should be in the JVM's local memory area, with the values:

1 2 3 4 5 6 7 8 9 99 100 101 500 999

Note that we will be testing your program with other values in the array, but these should be sufficient for testing.

What to Turn In

Your program should include your name; it is always a good idea to put a comment in your code to tell the reader who wrote the code.

Turn in a hardcopy (printout) of the program, as well as an electronic submission using the turnin program.