diff --git a/emulate b/emulate index 2b6454ac5fd81aef59995318ea10b84c1fa09f40..c8c397028477ff6c3fce7138a96d91e50f22f186 100755 Binary files a/emulate and b/emulate differ diff --git a/emulate.c b/emulate.c index 565c9295ab9019f6928a4f9b737c1d250cc91a39..c690fbed43214de7d30ea60ba5d6cf5150e63f76 100644 --- a/emulate.c +++ b/emulate.c @@ -298,7 +298,7 @@ void dataProcessingInstr(struct ProcessorState *processor, int address) // Set the CPSR flags if(isSet(instr, 20)){ - uint32_t *cprs = processor->registers[16]; + uint32_t *cprs = &processor->registers[16]; // C setBit(cprs, 29, carry); // Z (I think this should be set to 0 if the result isn't all zeros, but the spec is a little unclear) @@ -308,6 +308,102 @@ void dataProcessingInstr(struct ProcessorState *processor, int address) } } +void branchInstr(struct ProcessorState *processor, uint32_t address) +{ + // Check if address is valid + verifyAddress(address); + uint32_t instr = processor->memory[address]; + + // Check if the instruction should be executed according to its condition codes + if(!validCond(getBits(instr, 28, 31), processor)){ + return; + } + + // Get offset and sign + int32_t offset = getBits(instr, 0, 23); + bool sign = getBits(offset, 23, 23); + + // New address calculated with left shift and sign extension (and offset of 8) + uint32_t branchAddr = processor->registers[14] + ((offset * 4) | ((sign) ? 0xFC000000 : 0)) + 8; + + // New address verified + verifyAddress(branchAddr); + + // New address loaded to PC + processor->registers[14] = branchAddr; + + return; +} + +// Steps through pipeline calling appropriate instruction method. +// Sets teminate if instruction is all-0. +void step(struct ProcessorState *processor, bool *terminate) +{ + // Fetches next instruction location (including offset) + uint32_t nextAddr = processor->registers[14] + 8; + + // Fetches next instruction to be executed + uint32_t nextInstr = processor->memory[nextAddr]; + + // Checks for all-0 + if (nextInstr == 0) + { + *terminate = 1; + return; + } + + // Check instruction type and call appropriate method + switch (getBits(nextInstr, 26, 27)) + { + case 0: + if ((getBits(nextInstr, 25, 25) == 0) && (getBits(nextInstr, 4, 8) == 9)) { + multiplyInstr(processor, nextAddr); + } else { + dataProcessingInstr(processor, nextAddr); + } + case 1: + dataTransferInstr(processor, nextAddr); + case 2: + branchInstr(processor, nextAddr); + } + return; +} + +/* creates a new processor, setting all registers to 0. Dynamically allocated - call free()! */ +struct ProcessorState *makeProcessor(void) +{ + struct ProcessorState *processor = (struct ProcessorState *)malloc(sizeof(struct ProcessorState)); + for (int i = 0; i < 17; i++) + { + processor->registers[i] = 0; + } + return processor; +} + +int main(int argc, char *argv[]) +{ + struct ProcessorState *processor; + + // Load file into processor state + if (argc == 2) { + processor = loadBinary(argv[1]); + } else if (argc > 2) { + printf("Too many arguments"); + return 0; + } else { + printf("No file given"); + return 0; + } + + bool terminate = 0; + + // Loop through instructions until all-0 met + while (!terminate) { + step(processor, &terminate); + } + + free(processor); +} //*** TESTING FUNCTIONS ***// @@ -377,22 +473,3 @@ void testBarrelShifter(void) free(processor); } - -/* creates a new processor, setting all registers to 0. Dynamically allocated - call free()! */ -struct ProcessorState *makeProcessor(void) -{ - struct ProcessorState *processor = (struct ProcessorState *)malloc(sizeof(struct ProcessorState)); - for (int i = 0; i < 17; i++) - { - processor->registers[i] = 0; - } - return processor; -} - -int main(void) -{ - testBitGetters(); - printf("\n"); - testBarrelShifter(); - return 0; -} \ No newline at end of file