From 63ba75fab668a263e8671ecc0554fb232610de62 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Mon, 3 Jun 2024 14:37:59 +0100 Subject: [PATCH] Add function for executing DPI instructions w/ S --- src/execute.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/execute.c b/src/execute.c index 6622812..3e8c57f 100644 --- a/src/execute.c +++ b/src/execute.c @@ -1,5 +1,88 @@ #include "execute.h" +// The number of bits to shift the immediate value in an immediate data processing instruction +// if the shift flag is enabled. +#define DPI_ARITHM_SHIFT 12 + +// 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 + } +} + +// Read from processor register, ensuring that a valid register specifier is given +// and accounting for the case where the zero register is accessed. Truncate +// the 32 most significant bits stored in the R register when reading W register. +static dword readRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType) { + assert(reg <= REGISTER_COUNT) + if (reg == ZERO_REGISTER) { + return 0; + } else { + return truncateValue(state->registers[reg], regType); + } +} + +// 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) { + state->registers[reg] = truncateValue(value, regType); +} + +// Execute a data processing immediate instruction +static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { + assert(inst->type == a64inst_DPIMMEDIATE); + 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: + + // 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; + dword srcVal = state->registers[inst->data.DPImmediateData.processOpData.arithmData.src]; + if (inst->data.DPImmediateData.processOpData.arithmData.shiftImmediate) { + immediate = truncateValue(immediate << DPI_ARITHM_SHIFT, regType); + } + + switch(inst->data.DPImmediateData.processOp) { + + case(a64inst_ADDS): + // Fall through + + case(a64inst_ADD): + *dest = truncateValue(srcVal + immediate, regType); + break; + + case(a64inst_SUBS): + // Fall through + + case(a64inst_SUB): + *dest = truncateValue(srcVal - immediate, regType); + break; + + // Unknown opcode detected! + default: + break; + } + + break; + + // Execute a wide move data processing instruction + case a64inst_DPI_WIDEMOV: + break; + + // Unknown instruction detected! + default: + break; + } +} + void execute(Machine *state, a64inst_instruction *inst) { switch (inst->type) {