COSC2325 Exam 1 Lab

We are about to begin building a simulator for a real machine. Not one you can buy, but one we will invent for learning what is going in in the machine.

Part of that simulation involves decoding data stored in memory. In this lab, we will explore a piece of that decoding process.

Packed Data

You are used to storing a significant chunk of data in a variable or array and not worrying much about where in memory that data lives. Unfortunately, instructions are “packed” into memory in such a way that several pieces of information are located in a single memory storage area.

In this lab, instructions are all represented as unsigned 16 bit data, and inside those 16 bits are three “fields”:

  • opcode - 6 bits of opcode (code for an instruction)
  • op1 - 5 bits for a first operand (0-31)
  • op2 - 5 bits for a second operand (0-31)

These fields are located as indicated left to right.

C++ provides a way to specify exactly how big a data item is, without worrying about looking things up in the documentation>

The cstdlib library provides the data type we need:

  • uint16_t - unsigned 16-bit data item

You can set values into variables defined with this type easily:

Here is the sample code array you will need to decode:

uint16_t code[] = {
   0b0000000000100010,
   0b1111110100011000,
   0b1101101001001000,
   0b0101010001100001
}

Decoding an Instruction

We need to “unpack” the three fields from the 6 bit data item. Fortunately, C++ makes this easy, using two simple operators:

  • “>>” - shift bits to the right (the right operand is an integer, indicating the number of positions to shift.
  • “&” - “mask” bits by performing a bitwise “and” with the pattern provided (see below).

To understand that “mask” operation, just line up the data item (16 bits) and the “mask” (also 16 bits) and perform a logical “and” operation on the bit pairs in each bit position. The mask is used to strip off bits you do not want to show in the final result. The “mask” has a one in every bit position you want to keep, and zeros everywhere else. In the final result, only those bits from the data item where a bit was a one will pass through unchanged. Look at the example code below to see this in action:

Displaying Binary data

It will be nice if we provide a way to display the binary data as a string of 0’s and 1’s. The easiest way to do this in C++ involves using a new data type called bitset. The sample program below shows how to do this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <bitset>
#include <cstdlib>

void display(uint16_t data) {
    std::bitset<16> x(data);
    std::cout << x << std::endl;
}

int main(void) {
    int a = -58;
    display(a);
    display(58);
    display(58 << 4);
    display(58 & 0xfff0);

    return 0;
}

That bitset declaration is a C++ “template”. The number in angle brackets is the number of bits you want to allocate for this data item. Formally, the data type defines something like ab array of bits, each one able to store only a zero or a one. Hopefully, your C++ class mentioned templates. If not, just use the code shown and things should work fine. We will use templates in our future labs as well. (You do not need to write thm, just use them.)

Your Job

Write a single-file C++ program what has a main function and a decode function. Create the code array as show above in main or global data.

In main set up a loop that “fetches” a 16-bit data item from the code array and passes that value to the decode function.

Your decode function must split the 16-bit parameter into the three fields, and display the result on a line in binary. The line should look like this:

opcode: bbbbbb op1: rnn op2: Rnn

Where the b’s indicate a binary field, and the n’s indicate a decimal (0-31) field. Do not show the register number (Rnn) in binary. Just display the letter R followed by the decimal value.

When is this due?

This lab must be completed by Monday, Oct 8. Place it in your homework repository under a folder names EXAM1.