Add function for executing DPI instructions w/ S
This commit is contained in:
parent
34119916de
commit
63ba75fab6
@ -1,5 +1,88 @@
|
|||||||
#include "execute.h"
|
#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) {
|
void execute(Machine *state, a64inst_instruction *inst) {
|
||||||
|
|
||||||
switch (inst->type) {
|
switch (inst->type) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user