Add execute branch instruction, w/ T

This commit is contained in:
sBubshait 2024-06-03 17:43:21 +01:00
parent 84586b4768
commit 9c299b3be0

View File

@ -11,6 +11,7 @@
// Prototypes // Prototypes
void execute_SDT(Machine *state, a64inst_instruction *inst); void execute_SDT(Machine *state, a64inst_instruction *inst);
void execute_Branch(Machine *state, a64inst_instruction *inst);
// Return maximum of two dwords // Return maximum of two dwords
static dword max(dword a, dword b) { static dword max(dword a, dword b) {
@ -27,6 +28,28 @@ static dword truncateValue(dword value, a64inst_regType regType) {
} }
} }
// Sign extend a given value to a 64-bit signed integer given the number of bits
static int64_t signExtend(dword value, unsigned int n) {
if (n == 0 || n >= 64) {
// If n_bits is 0 or greater than or equal to 64, return the value as is
return (int64_t)value;
}
uint64_t sign_bit_mask = (uint64_t)1 << (n - 1);
// Mask to isolate the n-bit value
uint64_t n_bit_mask = (sign_bit_mask << 1) - 1;
// Check if the sign bit is set
if (value & sign_bit_mask) {
// Sign bit is set, extend the sign
return (int64_t)(value | ~n_bit_mask);
} else {
// Sign bit is not set, return the value as is
return (int64_t)(value & n_bit_mask);
}
}
// Read from processor register, ensuring that a valid register specifier is given // Read from processor register, ensuring that a valid register specifier is given
// and accounting for the case where the zero register is accessed. Truncate // 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. // the 32 most significant bits stored in the R register when reading W register.
@ -131,6 +154,7 @@ void execute(Machine *state, a64inst_instruction *inst) {
// Execute a branch instruction // Execute a branch instruction
case a64inst_BRANCH: case a64inst_BRANCH:
execute_Branch(state, inst);
break; break;
// Execute a data processing register instruction // Execute a data processing register instruction
@ -193,4 +217,41 @@ void execute_SDT(Machine *state, a64inst_instruction *inst) {
} }
} }
} }
static bool isConditionMet(Machine* state, a64inst_ConditionType cond) {
switch(cond) {
case EQ:
return state->conditionCodes.Zero;
case NE:
return !state->conditionCodes.Zero;
case GE:
return state->conditionCodes.Negative == state->conditionCodes.Overflow;
case LT:
return state->conditionCodes.Negative != state->conditionCodes.Overflow;
case GT:
return !state->conditionCodes.Zero && (state->conditionCodes.Negative == state->conditionCodes.Overflow);
case LE:
return state->conditionCodes.Zero || (state->conditionCodes.Negative != state->conditionCodes.Overflow);
case AL:
return true;
}
}
void execute_Branch(Machine *state, a64inst_instruction *inst) {
switch (inst->data.BranchData.BranchType) {
case a64inst_UNCONDITIONAL:
state->pc += signExtend(inst->data.BranchData.processOpData.unconditionalData.unconditionalOffset * 4, 26);
break;
case a64inst_REGISTER:
state->pc = state->registers[inst->data.BranchData.processOpData.registerData.src];
break;
case a64inst_CONDITIONAL:
if (isConditionMet(state, inst->data.BranchData.processOpData.conditionalData.cond)) {
state->pc += signExtend(inst->data.BranchData.processOpData.conditionalData.offset * 4, 19);
}
break;
}
}