Emulator

This project implementats of a very simple processor to execute instructions.

CPU Overview

The CPU being emulated uses a custom 32-bit architecture. Instructions are all 32 bits in length. Data words in registers are also 32 bits in length.

The following registers are available:

  • R0 - General data register
  • R1 - General data register
  • R2 - General data register
  • R3 - General data register
  • R4 - General data register
  • IP - Instruction pointer (Points to the next instruction to execute)
  • IR - Instruction register (holds the current instruction)

Instruction Format

Instructions are all 4 bytes. Each byte represents the following:

Byte 0 Byte 1 Byte 2 Byte 3
op dst src immediate
  • op - Operation to execute
  • dst - Destination register
  • src - Source register
  • immediate - Immediate Value (signed)

Specifically, instructions can be represented using the following struct:

typedef struct {
  Operation op;
  Register dst;
  Register src;
  signed char immediate;
} Instruction;

Operations

This simple processor supports the following operations:

  1. Halt - Stop the processor
  2. LoadImmediate - Store the value in immediate to register dst.
  3. Add - Add the value from register src to the value in register dst and store the result in dst.
  4. AddImmediate - Add the value in immediate to register src and store the result in register dst.
  5. And - Bitwise and the value from register src to the value in register dst and store the result in dst.
  6. Or - Bitwise or the value from register src to the value in register dst and store the result in dst.
  7. Xor - Bitwise xor the value from register src to the value in register dst and store the result in dst.
  8. Jump - Jump to the absolute position stored in the immediate value.
  9. BranchOnEqual - Jump to the absolute position stored in the immediate value if and only if the values in the src and dst registers are equal.
  10. LoadDirect - Load the value stored in the memory location pointed to by immediate into the dst register.
  11. StoreDirect - Store the value stored in register src into the memory location pointed to by the immediate value.
  12. LoadIndirect - Load the value stored in the memory location pointed to by the value in src into the dst register.
  13. StoreIndirect - Store the value stored in register src into the memory location pointed to by the value stored in dst.

Assembler Overview

An assembler translates assembly language code to machine code. Your task is to update your CPU emulator to include an complete assembler by completing the assembler.c file. There are a few TODO comments that must be taken care of. You should be able to convert the included test-program.asm to machine code and execute it correctly.

Fibonacci

Once you have a working assembler, you should create a working assembly language program to calculate the nth Fibonacci number that your emulator is able to execute. More details can be found in the fibonacci.asm file. Both files can be assembled, executed, and tested by simply calling make.

Array Sum

The array-sum.asm should add a single value (a scalar) to every item in an array. The values for this code segment are:

  • Memory location 100: value to add to each item in the array
  • Memory location 101: length of the array
  • Memory location 102: first array item
  • Memory location 103: second array item
  • Memory location 104+: subsequent array items

Memory-mapped I/O

The display device is a 16x3 character display that may look something like the following:

Display device

The device is mapped to memory locations 64-127, so the overall memory map of our device is now:

Range Type
0x00 - 0x4e Program Memory
0x4f - 0x7f Display
0x80 - 0xff Main memory

We can interface with our device using the following memory locations:

  • 0x4f - Display update
    • Set to 1 to copy 3x16 character back buffer located at 0x50-0x7f to display
  • 0x50 - 0x7f - Words representing the characters on the screen as a 3x16 integer array (int[3][16]). The low byte of each integer represents the character value in ASCII.

Marquee

Your task is to create a program marquee.asm that creates a marquee text of your name:

output

This should scroll a few times and then halt the CPU.

Running

The emulator can be compiled and tested by invoking:

make

Debugging Tips

A couple of tools are provided to make debugging easier.

  1. print_instruction can be used to pretty print an instruction. For example:
// Print the instruction stored in `inst`
print_instruction(inst);
  1. print_registers can pretty print register values. For example:
// Print the current register values stored in `registers`:
print_registers(registers);
  1. TEST_CLOCK can be modified to adjust the clock speed of the CPU during testing. The emulator defaults to a 1 MHz CPU, but it may be helpful to run it much, much slower whole observing instruction and register values.

  2. printf can be used to print any values of interest.