Add decode and execute structure for DPI instructions w/ S
This commit is contained in:
parent
8b0bb1888b
commit
024044afc7
@ -113,6 +113,9 @@ a64inst_instruction *decode(word wrd) {
|
|||||||
switch(inst->data.DPRegisterData.DPROpType) {
|
switch(inst->data.DPRegisterData.DPROpType) {
|
||||||
|
|
||||||
case a64inst_DPR_ARITHMLOGIC:
|
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);
|
arithmLogicData.shiftAmount = getBits(wrd, DP_REG_ARITHMLOGIC_SHIFTAMOUNT_LSB, DP_REG_ARITHMLOGIC_SHIFTAMOUNT_MSB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -121,7 +124,7 @@ a64inst_instruction *decode(word wrd) {
|
|||||||
arithmLogicData.type == DP_REG_MULTIPLY_ARITHMFLAG &&
|
arithmLogicData.type == DP_REG_MULTIPLY_ARITHMFLAG &&
|
||||||
arithmLogicData.shiftType == DP_REG_MULTIPLY_SHIFTTYPE &&
|
arithmLogicData.shiftType == DP_REG_MULTIPLY_SHIFTTYPE &&
|
||||||
arithmLogicData.negShiftedSrc2 == DP_REG_MULTIPLY_NEGSRC2FLAG)) {
|
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.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);
|
inst->data.DPRegisterData.processOpData.multiplydata.negProd = getBits(wrd, DP_REG_MULTIPLY_NEGPROD_LSB, DP_REG_MULTIPLY_NEGPROD_MSB);
|
||||||
|
|||||||
167
src/execute.c
167
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
|
// 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) {
|
static dword truncateValue(dword value, a64inst_regType regType) {
|
||||||
if (regType == a64inst_R) {
|
if (regType == a64inst_X) {
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
//return value & ~(dword)((1 << WORD_BITS) - 1)
|
return (word)value;
|
||||||
return value & (dword)(((dword)1 << WORD_BITS) - 1);
|
//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
|
// 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) {
|
static void writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value) {
|
||||||
assert(reg <= REGISTER_COUNT);
|
assert(reg <= REGISTER_COUNT);
|
||||||
if (regType == a64inst_R) {
|
state->registers[reg] = truncateValue(value, regType);
|
||||||
state->registers[reg] = truncateValue(value, regType);
|
}
|
||||||
} else {
|
|
||||||
*(word*)(state->registers + reg) = (word)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
|
// Updates N and Z condition codes given the machine and a result value
|
||||||
static void updateCondNZ(Machine *state, dword result, a64inst_regType regType) {
|
static void updateCondNZ(Machine *state, dword result, a64inst_regType regType) {
|
||||||
size_t msb = (regType ? DWORD_BITS : WORD_BITS) - 1;
|
state->conditionCodes.Negative = getMSB(result, regType);
|
||||||
|
|
||||||
state->conditionCodes.Negative = result >> msb;
|
|
||||||
state->conditionCodes.Zero = result == 0;
|
state->conditionCodes.Zero = result == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute a data processing immediate instruction
|
// Execute a data processing immediate instruction
|
||||||
static void executeDPImmediate(Machine *state, a64inst_instruction *inst) {
|
static void executeDPImmediate(Machine *state, a64inst_instruction *inst) {
|
||||||
|
|
||||||
assert(inst->type == a64inst_DPIMMEDIATE);
|
assert(inst->type == a64inst_DPIMMEDIATE);
|
||||||
|
|
||||||
a64inst_regType regType = inst->data.DPImmediateData.regType;
|
a64inst_regType regType = inst->data.DPImmediateData.regType;
|
||||||
a64inst_regSpecifier dest = inst->data.DPImmediateData.dest;
|
a64inst_regSpecifier dest = inst->data.DPImmediateData.dest;
|
||||||
|
|
||||||
switch(inst->data.DPImmediateData.DPIOpType) {
|
switch(inst->data.DPImmediateData.DPIOpType) {
|
||||||
|
|
||||||
// Execute an arithmetic data processing instruction
|
// Execute an arithmetic immediate 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
|
// 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) {
|
switch(inst->data.DPImmediateData.processOp) {
|
||||||
|
|
||||||
dword result;
|
dword result;
|
||||||
|
|
||||||
case(a64inst_ADDS):
|
case(a64inst_ADDS):
|
||||||
result = srcVal + arithmImm;
|
result = srcVal + arithmImm;
|
||||||
writeRegister(state, dest, regType, result);
|
writeRegister(state, dest, regType, result);
|
||||||
@ -131,6 +136,7 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case(a64inst_SUB):
|
case(a64inst_SUB):
|
||||||
|
printf("wag1\n");
|
||||||
writeRegister(state, dest, regType, srcVal - arithmImm);
|
writeRegister(state, dest, regType, srcVal - arithmImm);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -141,7 +147,7 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Execute a wide move data processing instruction
|
// Execute a wide move immediate data processing instruction
|
||||||
case a64inst_DPI_WIDEMOV:;
|
case a64inst_DPI_WIDEMOV:;
|
||||||
uint8_t shiftScalar = inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar;
|
uint8_t shiftScalar = inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar;
|
||||||
dword wideMovImm = inst->data.DPImmediateData.processOpData.wideMovData.immediate;
|
dword wideMovImm = inst->data.DPImmediateData.processOpData.wideMovData.immediate;
|
||||||
@ -173,6 +179,131 @@ static void executeDPImmediate(Machine *state, a64inst_instruction *inst) {
|
|||||||
|
|
||||||
// Unknown instruction detected!
|
// Unknown instruction detected!
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +328,7 @@ void execute(Machine *state, a64inst_instruction *inst) {
|
|||||||
|
|
||||||
// Execute a data processing register instruction
|
// Execute a data processing register instruction
|
||||||
case a64inst_DPREGISTER:
|
case a64inst_DPREGISTER:
|
||||||
readRegister(state, 0, 0); //FOR COMPILATION PURPOSES
|
executeDPRegister(state, inst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case a64inst_SINGLETRANSFER:
|
case a64inst_SINGLETRANSFER:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user