diff --git a/src/execute.c b/src/execute.c index 755a0f9..3afa99c 100644 --- a/src/execute.c +++ b/src/execute.c @@ -6,10 +6,14 @@ // 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. +// The number of bits to shift the immediate value in an arithmetic immediate data processing +// instruction if the shift flag is enabled. #define DPI_ARITHM_SHIFT 12 +// The number of bits to shift the immediate value in a wide move immediate data processing +// instruction if the shift flag is enabled. +#define DPI_WIDEMOV_SHIFT 16 + // Prototypes void execute_SDT(Machine *state, a64inst_instruction *inst); void execute_Branch(Machine *state, a64inst_instruction *inst); @@ -126,12 +130,37 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { // Unknown opcode detected! default: fprintf(stderr, "Unknown opcode detected in a DPI arithmetic instruction!\n"); - break; + break; } break; // Execute a wide move data processing instruction - case a64inst_DPI_WIDEMOV: + case a64inst_DPI_WIDEMOV:; + uint8_t shiftScalar = inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar; + uint16_t immediate = inst->data.DPImmediateData.processOpData.wideMovData.immediate; + + // NOTE: Not checking that shiftScalar has valid value for 32bit registers. Possibly add explicit error. + immediate = truncateValue(shiftScalar * DPI_WIDEMOV_SHIFT, regType); + switch(inst->data.DPImmediateData.processOp) { + + case(a64inst_MOVN): + writeRegister(state, dest, regType, ~immediate); + break; + + case(a64inst_MOVZ): + writeRegister(state, dest, regType, immediate); + break; + + case(a64inst_MOVK):; + dword result = readRegister(state, dest, regType); + result = (result & ~(((1 << DPI_WIDEMOV_SHIFT) - 1) << shiftScalar)) | immediate; + writeRegister(state, dest, regType, result); + break; + + default: + fprintf(stderr, "Unknown opcode detected in a DPI wide move instruction!\n"); + break; + } break; // Unknown instruction detected!