diff --git a/src/execute.c b/src/execute.c index 78e0efd..4e0f608 100644 --- a/src/execute.c +++ b/src/execute.c @@ -1,4 +1,9 @@ +#include #include "execute.h" +#include "print.h" + +// Defines the maximum value that can be held in a register +#define MAX_REG_VAL ((1 << DWORD_BITS) - 1) // The number of bits to shift the immediate value in an immediate data processing instruction // if the shift flag is enabled. @@ -7,13 +12,18 @@ // Prototypes void execute_SDT(Machine *state, a64inst_instruction *inst); +// Return maximum of two dwords +static dword max(dword a, dword b) { + return a > b ? a : b; +} + // Truncate a given value to the size of a word or dword depending on the register type static dword truncateValue(dword value, a64inst_regType regType) { if (regType == a64inst_R) { return value; } else { //return value & ~(dword)((1 << WORD_BITS) - 1) - return value & (1 << WORD_BITS) - 1; + return value & (((dword)1 << WORD_BITS) - 1); } } @@ -31,20 +41,27 @@ static dword readRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regT // Read from processor register, ensuring that a valid register specifier is given // and truncating the value being written when it can't fit in the specified register. -static dword writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value) { +static void writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value) { state->registers[reg] = truncateValue(value, regType); } +// Updates N and Z condition codes given the machine and a result value +static void updateCondNZ(Machine *state, dword result, a64inst_regType regType) { + state->conditionCodes.Negative = result & ((1 << (regType ? DWORD_BITS : WORD_BITS)) - 1); + state->conditionCodes.Zero = result == 0; +} + // Execute a data processing immediate instruction static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { + assert(inst->type == a64inst_DPIMMEDIATE); + a64inst_regType regType = inst->data.DPImmediateData.regType; + a64inst_regSpecifier dest = inst->data.DPImmediateData.dest; + switch(inst->data.DPImmediateData.DPIOpType) { - - a64inst_regType regType = inst->data.DPImmediateData.regType; - word *dest = state->registers + inst->data.DPImmediateData.dest; - + // Execute an arithmetic data processing instruction - case a64inst_DPI_ARITHM: + case a64inst_DPI_ARITHM:; // If shift flag is enabled, logical left shift by the number of bits specified by the architecture dword immediate = inst->data.DPImmediateData.processOpData.arithmData.immediate; @@ -54,26 +71,39 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { } switch(inst->data.DPImmediateData.processOp) { + dword result; case(a64inst_ADDS): - // Fall through + result = srcVal + immediate; + writeRegister(state, dest, regType, result); + + updateCondNZ(state, result, regType); + state->conditionCodes.Overflow = max(srcVal, immediate) > result; + state->conditionCodes.Carry = state->conditionCodes.Overflow; + break; case(a64inst_ADD): - *dest = truncateValue(srcVal + immediate, regType); + writeRegister(state, dest, regType, srcVal + immediate); break; case(a64inst_SUBS): - // Fall through + result = srcVal - immediate; + writeRegister(state, dest, regType, result); + + updateCondNZ(state, result, regType); + state->conditionCodes.Overflow = srcVal < result; + state->conditionCodes.Carry = state->conditionCodes.Overflow; + break; case(a64inst_SUB): - *dest = truncateValue(srcVal - immediate, regType); + writeRegister(state, dest, regType, srcVal - immediate); break; // Unknown opcode detected! default: + fprintf(stderr, "Unknown opcode detected in a DPI arithmetic instruction!\n"); break; } - break; // Execute a wide move data processing instruction @@ -96,6 +126,7 @@ void execute(Machine *state, a64inst_instruction *inst) { // Execute a data processing immediate instruction case a64inst_DPIMMEDIATE: + executeDPImmediate(state, inst); break; // Execute a branch instruction @@ -104,6 +135,7 @@ void execute(Machine *state, a64inst_instruction *inst) { // Execute a data processing register instruction case a64inst_DPREGISTER: + readRegister(state, 0, 0); //FOR COMPILATION PURPOSES break; case a64inst_SINGLETRANSFER: diff --git a/src/execute.h b/src/execute.h index debc341..fcf39ec 100644 --- a/src/execute.h +++ b/src/execute.h @@ -2,7 +2,6 @@ #define __EXECUTE__ #include "a64instruction.h" #include "emulator.h" -#include "print.c" void execute(Machine *state, a64inst_instruction *inst); #endif