CS 473

Homework 2: MIPS I

Due Monday, October 4, 2004

From the Book

2.29, 2.37, 2.46,

Programming: MIPS Simulator, Part I

Write an instruction decoder for MIPS (this assignment is going to grow into a simulation of the MIPS instruction set, so some things I'm asking you to do here won't make sense for a while).

You will need to:

  1. Use typedefs to create types called Instruction and Address. These are all really uint32_ts.

    Your Instruction type should not be a union of structs with specified-width fields. The C standard doesn't require such a struct pack the fields, so GCC doesn't necessarily pack them (so far as I'm concerned this is a bug in both the standard and GCC, but nobody asked me!).

  2. Declare some global (yes, you read correctly) variables: instructionMemory (an array of 1024 Instructions); instructionRegister (an Instruction); and programCounter (an Address).

    Naturally, you're very likely to need more variables than these. But these are variables I want you to have.

  3. Write an input routine which will read an input file from stdin. The input file will have an Address and an Instruction on each line, separated by a space. They'll both be hexadecimal; you can read them using a scanf with a format string of "%x %x".

    As Instructions are read, they should be put in instructionMemory. But notice! Since every memory word is four bytes wide, you need to put the Instruction into the specified address divided by four (so if you read address 10016, you need to put the Instruction into instructionMemory[0x40].

  4. Now use the programCounter to iterate through the instructionMemory array, and translate each instruction into MIPS assembly code. When you decode the instructions, use switch statements, not a huge if-else

You need to be able to handle the following instructions: add, sub, addiu, lw, beq, and j.

Output Format

New stuff! Each line of output should contain the address of the instruction being output (in hexadecimal), then a space, then the instruction machine code (also in hexadecimal), then a space, and then the instruction in MIPS assembly language, which I can best describe as saying is "like the examples on the cheat-sheet". Separate the instruction mnemonic from the operands with a single space; separate the operands with commas. Don't print anything for a line with an instruction you don't recognize.

So, for instance, if the first three instructions of your input were


00000000 00430820
00000004 20410050
00000008 8c410020

Then your first two lines of output would be


00000000 00430820 add $1,$2,$3
00000008 8c410020 lw $1, 32($2)

(Notice that the second instruction is one you haven't been told to handle).

In the case of beq, the displacement should be given in bytes, not words (take a look at the right side of the cheat sheet to see what I'm talking about).

Numbers in your output should be signed decimal (and you should use the real names like $7, not the names reflecting software conventions like $t3). Notice that this means that for things like branches to negative displacements you need to successfully sign-extend.

You really want to follow good structured programming conventions on this, and especially encapsulate your datatypes. For instance, you should define functions something like Instruction readInstructionMemory(Address addr) which will return the Instruction at byte address addr, and void writeInstructionMemory(Address addr, Instruction value), which will write the value into memory. Trust me on this.

I'll mention that these aren't the only instructions your simulation will eventually handle. But these instructions include examples of all three instruction formats, with both signed and unsigned operands, and with two R-format instructions that have the same opcode but differnt function fields.


Last modified: Mon Oct 4 08:12:59 MDT 2004