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:
- Halt - Stop the processor
- LoadImmediate - Store the value in
immediate
to registerdst
. - Add - Add the value from register
src
to the value in registerdst
and store the result indst
. - AddImmediate - Add the value in
immediate
to registersrc
and store the result in registerdst
. - And - Bitwise
and
the value from registersrc
to the value in registerdst
and store the result indst
. - Or - Bitwise
or
the value from registersrc
to the value in registerdst
and store the result indst
. - Xor - Bitwise
xor
the value from registersrc
to the value in registerdst
and store the result indst
. - Jump - Jump to the absolute position stored in the
immediate
value. - BranchOnEqual - Jump to the absolute position stored in the
immediate
value if and only if the values in thesrc
anddst
registers are equal. - LoadDirect - Load the value stored in the memory location pointed to by
immediate
into thedst
register. - StoreDirect - Store the value stored in register
src
into the memory location pointed to by theimmediate
value. - LoadIndirect - Load the value stored in the memory location pointed to by the value in
src
into thedst
register. - StoreIndirect - Store the value stored in register
src
into the memory location pointed to by the value stored indst
.
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
.
Running
The emulator can be compiled and tested by invoking:
make
Debugging Tips
A couple of tools are provided to make debugging easier.
print_instruction
can be used to pretty print an instruction. For example:
// Print the instruction stored in `inst`
print_instruction(inst);
print_registers
can pretty print register values. For example:
// Print the current register values stored in `registers`:
print_registers(registers);
-
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. -
printf
can be used to print any values of interest.