void dataProcessingInstr(struct ProcessorState *processor, int address)
Executes a data processing instruction
uses: isValidCond(...), barrelShift(...)
void multiplyInstr(struct ProcessorState *processor, int address)
Executes a multiplication instruction
uses: isValidCond(...),
void dataTransferInstr(struct ProcessorState *processor, int address)
Executes a single data transfer instruction
uses: isValidCond(...), barrelShift(...)
void branchInstr(stuct ProcessorState *processor, int address)
uses: isValidCond(...),
struct ProcessorState *loadBinary(char* src)
creates a new processor and loads its memory from a binary file.
Helper functions (used in more than one method):
int32_t getBits(int source, int start, int end)
Reads bits from source in the range [start, end] (inclusive). Returns a uint32_t with the result as its least significant bits.
(e.g. getBits(8, 2, 3) == 2)
IMPLEMENTED
int isSet(int source, int index)
Shorthand for getBits(source, index, index)
IMPLEMENTED
int validCond(int cond, struct ProcessorState *processor)
Returns 1 if the condition code 'cond' is satisfied by the processor's current state, and 0 otherwise.
IMPLEMENTED
int32_t barrelShift(int immediate, int32_t operand, int *carry, struct ProcessorState *processor)
Implements the functionality of the barrel shifter
NOTE: for some reason the I bit is used in opposite ways for data processing instructions vs for data transfer instructions. Arbitrarily, let this method
assume that the data processing instruction interpretation is the right one (so for data transfer instructions just call this method with NOT i).
int32_t *accessMemory(struct ProcessorState *processor, int address)
Gets an address from memory while ensuring it's not out of bounds
(use if you want, you can always do bounds checking manually)