From 024044afc74da74d9c7be232355573caf004ce81 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Wed, 5 Jun 2024 20:11:56 +0100 Subject: [PATCH] Add decode and execute structure for DPI instructions w/ S --- src/decode.c | 5 +- src/execute.c | 167 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 153 insertions(+), 19 deletions(-) diff --git a/src/decode.c b/src/decode.c index 6c969d8..7634753 100644 --- a/src/decode.c +++ b/src/decode.c @@ -113,6 +113,9 @@ a64inst_instruction *decode(word wrd) { switch(inst->data.DPRegisterData.DPROpType) { case a64inst_DPR_ARITHMLOGIC: + if (arithmLogicData.type == a64inst_DPR_ARITHM && (arithmLogicData.negShiftedSrc2 || arithmLogicData.shiftType == a64inst_ROR)) { + fprintf(stderr, "Attempting to decode arithmetic DPR instruction with invalid format!\n"); + } arithmLogicData.shiftAmount = getBits(wrd, DP_REG_ARITHMLOGIC_SHIFTAMOUNT_LSB, DP_REG_ARITHMLOGIC_SHIFTAMOUNT_MSB); break; @@ -121,7 +124,7 @@ a64inst_instruction *decode(word wrd) { arithmLogicData.type == DP_REG_MULTIPLY_ARITHMFLAG && arithmLogicData.shiftType == DP_REG_MULTIPLY_SHIFTTYPE && arithmLogicData.negShiftedSrc2 == DP_REG_MULTIPLY_NEGSRC2FLAG)) { - fprintf(stderr, "Attempting to decode multiply instruction with invalid format!\n"); + fprintf(stderr, "Attempting to decode multiply DPR instruction with invalid format!\n"); } inst->data.DPRegisterData.processOpData.multiplydata.summand = getBits(wrd, DP_REG_MULTIPLY_SUMMAND_LSB, DP_REG_MULTIPLY_SUMMAND_MSB); inst->data.DPRegisterData.processOpData.multiplydata.negProd = getBits(wrd, DP_REG_MULTIPLY_NEGPROD_LSB, DP_REG_MULTIPLY_NEGPROD_MSB); diff --git a/src/execute.c b/src/execute.c index 8271719..42846b3 100644 --- a/src/execute.c +++ b/src/execute.c @@ -25,11 +25,11 @@ static dword max(dword a, dword 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) { + if (regType == a64inst_X) { return value; } else { - //return value & ~(dword)((1 << WORD_BITS) - 1) - return value & (dword)(((dword)1 << WORD_BITS) - 1); + return (word)value; + //return value & (dword)(((dword)1 << WORD_BITS) - 1); } } @@ -67,35 +67,40 @@ static dword readRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regT } } +// TODO: + // Write to a 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. +// and truncating the value being written when it can't fit in the specified register static void writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value) { assert(reg <= REGISTER_COUNT); - if (regType == a64inst_R) { - state->registers[reg] = truncateValue(value, regType); - } else { - *(word*)(state->registers + reg) = (word)truncateValue(value, regType); - } + state->registers[reg] = truncateValue(value, regType); +} + +// Returns the position of the MSB of the given register type +inline static dword getMSBPos(a64inst_regType regType) { + return (regType ? DWORD_BITS : WORD_BITS) - 1; +} + +// Returns the MSB of the given value assuming it's of the size stored in the given register type +inline static uint8_t getMSB(dword value, a64inst_regType regType) { + return value >> getMSBPos(regType); } // Updates N and Z condition codes given the machine and a result value static void updateCondNZ(Machine *state, dword result, a64inst_regType regType) { - size_t msb = (regType ? DWORD_BITS : WORD_BITS) - 1; - - state->conditionCodes.Negative = result >> msb; + state->conditionCodes.Negative = getMSB(result, regType); 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) { - // Execute an arithmetic data processing instruction + // Execute an arithmetic immediate data processing instruction case a64inst_DPI_ARITHM:; // If shift flag is enabled, logical left shift by the number of bits specified by the architecture @@ -106,8 +111,8 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { } switch(inst->data.DPImmediateData.processOp) { + dword result; - case(a64inst_ADDS): result = srcVal + arithmImm; writeRegister(state, dest, regType, result); @@ -131,6 +136,7 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { break; case(a64inst_SUB): + printf("wag1\n"); writeRegister(state, dest, regType, srcVal - arithmImm); break; @@ -141,7 +147,7 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { } break; - // Execute a wide move data processing instruction + // Execute a wide move immediate data processing instruction case a64inst_DPI_WIDEMOV:; uint8_t shiftScalar = inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar; dword wideMovImm = inst->data.DPImmediateData.processOpData.wideMovData.immediate; @@ -173,6 +179,131 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { // Unknown instruction detected! default: + fprintf(stderr, "Attempting to execute instruction with unknown DPI operand type!\n"); + break; + } +} + +// Execute a data processing register instruction +static void executeDPRegister(Machine *state, a64inst_instruction *inst) { + assert(inst->type == a64inst_DPREGISTER); + + a64inst_regType regType = inst->data.DPRegisterData.regType; + a64inst_regSpecifier dest = inst->data.DPRegisterData.dest; + dword src1Val = readRegister(state, inst->data.DPRegisterData.src1, regType); + dword src2Val = readRegister(state, inst->data.DPRegisterData.src2, regType); + + switch(inst->data.DPRegisterData.DPROpType) { + + // Execute an arithmetic or logic register data processing instruction + case a64inst_DPR_ARITHMLOGIC:; + + // Apply shift to value held in second register + a64inst_DPRegister_ArithmLogicData arithmLogicData = inst->data.DPRegisterData.processOpData.arithmLogicData; + uint8_t shiftAmount = arithmLogicData.shiftAmount; + switch(arithmLogicData.shiftType) { + + case a64inst_LSL: + src2Val = truncateValue(src2Val << shiftAmount, regType); + break; + + case a64inst_LSR: + src2Val = truncateValue(src2Val >> shiftAmount, regType); + break; + + case a64inst_ASR: + src2Val = truncateValue((int64_t)src2Val >> shiftAmount, regType); + break; + + case a64inst_ROR: + if (arithmLogicData.type != a64inst_DPR_LOGIC) { + fprintf(stderr, "Attempting to perform ROR shift on non-logic register data processing instruction!\n"); + } + src2Val = truncateValue(src2Val >> shiftAmount | src2Val << (getMSBPos(regType) - shiftAmount), regType); + break; + + default: + fprintf(stderr, "Attempting to execute arithmetic/logic register data processing instruction with invalid shift type!\n"); + break; + } + + dword result; + switch(arithmLogicData.type) { + + case a64inst_DPR_ARITHM: + switch(inst->data.DPRegisterData.processOp) { + + case(a64inst_ADDS): + result = src1Val + src2Val; + writeRegister(state, dest, regType, result); + + updateCondNZ(state, result, regType); + state->conditionCodes.Overflow = max(src1Val, src2Val) > result; + state->conditionCodes.Carry = state->conditionCodes.Overflow; + break; + + case(a64inst_ADD): + writeRegister(state, dest, regType, src1Val + src2Val); + break; + + case(a64inst_SUBS): + result = src1Val - src2Val; + writeRegister(state, dest, regType, result); + + updateCondNZ(state, result, regType); + state->conditionCodes.Overflow = src1Val < result; + state->conditionCodes.Carry = state->conditionCodes.Overflow; + break; + + case(a64inst_SUB): + writeRegister(state, dest, regType, src1Val - src2Val); + break; + + // Unknown opcode detected! + default: + fprintf(stderr, "Unknown opcode detected in a DPI arithmetic instruction!\n"); + break; + } + break; + + case a64inst_DPR_LOGIC: + switch(inst->data.DPRegisterData.processOp) { + + case a64inst_AND: + writeRegister(state, dest, regType, src1Val & src2Val); + break; + + case a64inst_OR: + writeRegister(state, dest, regType, src1Val | src2Val); + break; + + case a64inst_XOR: + writeRegister(state, dest, regType, src1Val ^ src2Val); + break; + + case a64inst_AND_FLAGGED:; + result = src1Val & src2Val; + writeRegister(state, dest, regType, result); + state->conditionCodes.Overflow = 0; + state->conditionCodes.Carry = 0; + updateCondNZ(state, result, regType); + break; + } + break; + + default: + fprintf(stderr, "Attempting to execute an instruction with an unknown DPR arithmetic or logic subtype!\n"); + break; + } + break; + + // Execute a multiply register data processing instruction + case a64inst_DPR_MULTIPLY: + break; + + // Unknown instruction detected! + default: + fprintf(stderr, "Attempting to execute instruction with unknown DPR operand type!\n"); break; } } @@ -197,7 +328,7 @@ void execute(Machine *state, a64inst_instruction *inst) { // Execute a data processing register instruction case a64inst_DPREGISTER: - readRegister(state, 0, 0); //FOR COMPILATION PURPOSES + executeDPRegister(state, inst); break; case a64inst_SINGLETRANSFER: