76 lines
2.6 KiB
C
76 lines
2.6 KiB
C
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "decode.h"
|
|
|
|
// Retrieve the bits between positions 'lsb' (inclusive) and 'msb' (exclusive) from a given word
|
|
// as a new zero-extended word.
|
|
static word getBits(word wrd, uint8_t lsb, uint8_t msb) {
|
|
|
|
// Ensure LSB and MSB are within range of word size, and in the correct order
|
|
assert(lsb < msb && msb < BYTE_BITS);
|
|
|
|
wrd &= (1 << msb) - 1;
|
|
return wrd >> lsb;
|
|
}
|
|
|
|
a64inst_instruction *decode(word wrd) {
|
|
|
|
a64inst_instruction *inst = malloc(sizeof(a64inst_instruction));
|
|
if (inst == NULL) {
|
|
fprintf(stderr, "Ran out of memory while attempting to decode an instruction!\n");
|
|
exit(1);
|
|
}
|
|
|
|
word DPImmFlag = getBits(wrd, BRANCH_CONDITIONAL_COND_LSB, BRANCH_CONDITIONAL_COND_MSB);
|
|
if (wrd == HALT_WORD) {
|
|
inst->type = a64inst_HALT;
|
|
|
|
} else if (DPImmFlag == 0) {
|
|
inst->type = a64inst_DPIMMEDIATE;
|
|
|
|
}else if (DPImmFlag == 1) {
|
|
inst->type = a64inst_BRANCH;
|
|
word branchTypeFlag = getBits(wrd, BRANCH_TYPE_LSB, BRANCH_TYPE_MSB);
|
|
|
|
inst->data.BranchData.BranchType = branchTypeFlag;
|
|
|
|
switch (branchTypeFlag) {
|
|
case a64inst_UNCONDITIONAL:
|
|
inst->data.BranchData.processOpData.unconditionalData.unconditionalOffset = getBits(wrd, BRANCH_UNCONDITIONAL_OFFSET_LSB, BRANCH_UNCONDITIONAL_OFFSET_MSB);
|
|
break;
|
|
|
|
case a64inst_CONDITIONAL:
|
|
inst->data.BranchData.processOpData.conditionalData.offset = getBits(wrd, BRANCH_CONDITIONAL_OFFSET_LSB, BRANCH_CONDITIONAL_OFFSET_MSB);
|
|
|
|
word conditionFlag = getBits(wrd, BRANCH_CONDITIONAL_COND_LSB, BRANCH_CONDITIONAL_COND_MSB);
|
|
|
|
if(conditionFlag <= 1 || (conditionFlag >= 10 && conditionFlag <= 14)) {
|
|
inst->data.BranchData.processOpData.conditionalData.cond = conditionFlag;
|
|
} else {
|
|
fprintf(stderr, "Error: Unknown condition detected.\n");
|
|
exit(1);
|
|
}
|
|
|
|
break;
|
|
|
|
case a64inst_REGISTER:
|
|
inst->data.BranchData.processOpData.registerData.src = getBits(wrd, BRANCH_REGISTER_SRC_LSB, BRANCH_REGISTER_SRC_MSB);
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "Undefined branch type detected!\n");
|
|
exit(1);
|
|
break;
|
|
}
|
|
|
|
} else if (getBits(wrd, DATA_PROCESSING_REG_LSB, DATA_PROCESSING_REG_MSB) == 1) {
|
|
inst->type = a64inst_DPREGISTER;
|
|
|
|
} else {
|
|
// Load and Store, or unknown
|
|
}
|
|
|
|
|
|
}
|