Update decode, Restructure and add helper function

This commit is contained in:
sBubshait 2024-06-12 19:07:41 +01:00
parent 24fd0c4ad6
commit 5013abfe00
2 changed files with 172 additions and 131 deletions

View File

@ -1,157 +1,198 @@
/** @file decode.c
* @brief Decode Function from binary words to internal representation structs.
*
* This defines the decode function which takes a binary word (uint32_t) and
* decodes it into an a64inst_instruction conveying the same information.
*
* @author Saleh Bubshait
* @author Themis Demetriades
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "decode.h" #include "decode.h"
#include "../shared/binary_util.h" #include "../shared/binary_util.h"
// Given a binary word, return its internal representation as an a64instruction struct encoding the same #define getField(fieldname) getBits(wrd, fieldname##_LSB, fieldname##_MSB)
// information.
/************************************
* PROTOTYPES
************************************/
static void decodeDPI(word wrd, a64inst_instruction *inst);
static void decodeBranch(word wrd, a64inst_instruction *inst);
static void decodeDPRegister(word wrd, a64inst_instruction *inst);
static void decodeSingleTransfer(word wrd, a64inst_instruction *inst);
/** @brief The main decode function. Takes a word (uint32_t) representing the
* instruction and decodes it into an a64inst_instruction struct.
* @param wrd The word (uint32_t) to be decoded in binary.
* @return a pointer to the heap-allocated a64inst_instruction struct
* representing the decoded instruction if successful.
*/
a64inst_instruction *decode(word wrd) { a64inst_instruction *decode(word wrd) {
a64inst_instruction *inst = malloc(sizeof(a64inst_instruction)); a64inst_instruction *inst = malloc(sizeof(a64inst_instruction));
if (inst == NULL) { if (inst == NULL) {
fprintf(stderr, "Ran out of memory while attempting to decode an instruction!\n"); fprintf(stderr, "Error: Could not allocate memory for an instruction\n");
exit(1); exit(EXIT_FAILURE);
} }
word typeId = getBits(wrd, TYPE_ID_LSB, TYPE_ID_MSB); word typeId = getField(TYPE_ID);
// Halt interpretation
if (wrd == HALT_WORD) { if (wrd == HALT_WORD) {
inst->type = a64inst_HALT; inst->type = a64inst_HALT;
// Data Processing Immediate interpretation
} else if (typeId == DP_IMM_ID) { } else if (typeId == DP_IMM_ID) {
inst->type = a64inst_DPIMMEDIATE; inst->type = a64inst_DPIMMEDIATE;
inst->data.DPImmediateData.regType = getBits(wrd, DP_WIDTH_LSB, DP_WIDTH_MSB); decodeDPI(wrd, inst);
inst->data.DPImmediateData.processOp = getBits(wrd, DP_OP_LSB, DP_OP_MSB);
inst->data.DPImmediateData.dest = getBits(wrd, DP_DEST_LSB, DP_DEST_MSB);
switch(getBits(wrd, DP_IMM_OPTYPE_LSB, DP_IMM_OPTYPE_MSB)) {
case DP_IMM_OPTYPE_ARITHM:
inst->data.DPImmediateData.DPIOpType = a64inst_DPI_ARITHM;
inst->data.DPImmediateData.processOpData.arithmData.shiftImmediate = getBits(wrd, DP_IMM_ARITHM_SHIFTFLAG_LSB, DP_IMM_ARITHM_SHIFTFLAG_MSB);
inst->data.DPImmediateData.processOpData.arithmData.immediate = getBits(wrd, DP_IMM_ARITHM_IMMVAL_LSB, DP_IMM_ARITHM_IMMVAL_MSB);
inst->data.DPImmediateData.processOpData.arithmData.src = getBits(wrd, DP_IMM_ARITHM_DEST_LSB, DP_IMM_ARITHM_DEST_MSB);
break;
case DP_IMM_OPTYPE_WIDEMOV:
inst->data.DPImmediateData.DPIOpType = a64inst_DPI_WIDEMOV;
inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar = getBits(wrd, DP_IMM_WIDEMOV_SHIFTSCALAR_LSB, DP_IMM_WIDEMOV_SHIFTSCALAR_MSB);
inst->data.DPImmediateData.processOpData.wideMovData.immediate = getBits(wrd, DP_IMM_WIDEMOV_IMMVAL_LSB, DP_IMM_WIDEMOV_IMMVAL_MSB);
break;
default:
fprintf(stderr, "Unknown immediate data processing operation type found!\n");
exit(1);
break;
}
} else if (typeId == BRANCH_ID) { } else if (typeId == BRANCH_ID) {
inst->type = a64inst_BRANCH; inst->type = a64inst_BRANCH;
word branchTypeFlag = getBits(wrd, BRANCH_TYPE_LSB, BRANCH_TYPE_MSB); decodeBranch(wrd, inst);
inst->data.BranchData.BranchType = branchTypeFlag;
switch (branchTypeFlag) { } else if (getField(DP_REG_FLAG) == 1) {
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, "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;
}
// TODO: Some minor code duplication between DPR and DPI data interpretation
// Data Processing Register interpretation
} else if (getBits(wrd, DP_REG_LSB, DP_REG_MSB) == 1) {
inst->type = a64inst_DPREGISTER; inst->type = a64inst_DPREGISTER;
inst->data.DPRegisterData.regType = getBits(wrd, DP_WIDTH_LSB, DP_WIDTH_MSB); decodeDPRegister(wrd, inst);
inst->data.DPRegisterData.processOp = getBits(wrd, DP_OP_LSB, DP_OP_MSB);
inst->data.DPRegisterData.dest = getBits(wrd, DP_DEST_LSB, DP_DEST_MSB);
inst->data.DPRegisterData.src1 = getBits(wrd, DP_REG_SRC1_LSB, DP_REG_SRC1_MSB);
inst->data.DPRegisterData.src2 = getBits(wrd, DP_REG_SRC2_LSB, DP_REG_SRC2_MSB);
inst->data.DPRegisterData.DPROpType = getBits(wrd, DP_REG_OPTYPE_LSB, DP_REG_OPTYPE_MSB);
a64inst_DPRegister_ArithmLogicData *arithmLogicData = &inst->data.DPRegisterData.processOpData.arithmLogicData;
arithmLogicData->type = getBits(wrd, DP_REG_ARITHMLOGIC_ARITHMFLAG_LSB, DP_REG_ARITHMLOGIC_ARITHMFLAG_MSB);
arithmLogicData->shiftType = getBits(wrd, DP_REG_ARITHMLOGIC_SHIFTTYPE_LSB, DP_REG_ARITHMLOGIC_SHIFTTYPE_MSB);
arithmLogicData->negShiftedSrc2 = getBits(wrd, DP_REG_ARITHMLOGIC_NEGSRC2FLAG_LSB, DP_REG_ARITHMLOGIC_NEGSRC2FLAG_MSB);
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;
case a64inst_DPR_MULTIPLY:;
if (!(inst->data.DPRegisterData.processOp == DP_REG_MULTIPLY_PROCESSOP &&
arithmLogicData->type == DP_REG_MULTIPLY_ARITHMFLAG &&
arithmLogicData->shiftType == DP_REG_MULTIPLY_SHIFTTYPE &&
arithmLogicData->negShiftedSrc2 == DP_REG_MULTIPLY_NEGSRC2FLAG)) {
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);
break;
}
} else { } else {
// Load and Store, or unknown
// Ignore unknown for now
inst->type = a64inst_SINGLETRANSFER; inst->type = a64inst_SINGLETRANSFER;
inst->data.SingleTransferData.regType = getBits(wrd, SDT_REGTYPE_FLAG_LSB, SDT_REGTYPE_FLAG_MSB); decodeSingleTransfer(wrd, inst);
inst->data.SingleTransferData.target = getBits(wrd, SDT_TARGET_REG_LSB, SDT_TARGET_REG_MSB);
// TODO: Assert that the instruction is a Single Transfer indeed.
if(getBits(wrd, SDT_OPTYPE_FLAG_LSB, SDT_OPTYPE_FLAG_MSB) == a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER) {
// Single Data Transfer
inst->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER;
inst->data.SingleTransferData.processOpData.singleDataTransferData.transferType = getBits(wrd, SDT_TRANSFER_TYPE_LSB, SDT_TRANSFER_TYPE_MSB);
inst->data.SingleTransferData.processOpData.singleDataTransferData.base = getBits(wrd, SDT_BASE_REG_LSB, SDT_BASE_REG_MSB);
if (getBits(wrd, SDT_UNSIGNED_FLAG_LSB, SDT_UNSIGNED_FLAG_MSB) == 1) {
// Unsigned offset
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_UNSIGNED_OFFSET;
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = getBits(wrd, SDT_OFFSET_LSB, SDT_OFFSET_MSB);
} else if (getBits(wrd, SDT_REGISTER_FLAG_LSB, SDT_REGISTER_FLAG_MSB) == 1) {
// Register Offset
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_REGISTER_OFFSET;
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.offsetReg = getBits(wrd, SDT_REGISTER_REG_LSB, SDT_REGISTER_REG_MSB);
} else {
// Pre-Indexed or Post-Indexed
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = getBits(wrd, SDT_INDEXED_ADDRMODE_LSB, SDT_INDEXED_ADDRMODE_MSB);
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = getBits(wrd, SDT_INDEXED_OFFSET_LSB, SDT_INDEXED_OFFSET_MSB);
}
} else {
// Load Literal
inst->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_LOAD_LITERAL;
inst->data.SingleTransferData.processOpData.loadLiteralData.offset = getBits(wrd, SDT_LOAD_LITERAL_OFFSET_LSB, SDT_LOAD_LITERAL_OFFSET_MSB);
}
} }
return inst; return inst;
} }
/************************************
* HELPER FUNCTIONS
************************************/
static void decodeDPI(word wrd, a64inst_instruction *inst) {
inst->data.DPImmediateData.regType = getField(DP_WIDTH);
inst->data.DPImmediateData.processOp = getField(DP_OP);
inst->data.DPImmediateData.dest = getField(DP_DEST);
switch(getField(DP_IMM_OPTYPE)) {
case DP_IMM_OPTYPE_ARITHM:
inst->data.DPImmediateData.DPIOpType = a64inst_DPI_ARITHM;
inst->data.DPImmediateData.processOpData.arithmData.shiftImmediate = getField(DP_IMM_ARITHM_SHIFTFLAG);
inst->data.DPImmediateData.processOpData.arithmData.immediate = getField(DP_IMM_ARITHM_IMMVAL);
inst->data.DPImmediateData.processOpData.arithmData.src = getField(DP_IMM_ARITHM_DEST);
break;
case DP_IMM_OPTYPE_WIDEMOV:
inst->data.DPImmediateData.DPIOpType = a64inst_DPI_WIDEMOV;
inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar = getField(DP_IMM_WIDEMOV_SHIFTSCALAR);
inst->data.DPImmediateData.processOpData.wideMovData.immediate = getField(DP_IMM_WIDEMOV_IMMVAL);
break;
default:
fprintf(stderr, "Unknown immediate data processing operation type found!\n");
exit(1);
break;
}
}
static void decodeBranch(word wrd, a64inst_instruction *inst) {
word branchTypeFlag = getField(BRANCH_TYPE);
inst->data.BranchData.BranchType = branchTypeFlag;
switch (branchTypeFlag) {
case a64inst_UNCONDITIONAL:
inst->data.BranchData.processOpData.unconditionalData.unconditionalOffset = getField(BRANCH_UNCONDITIONAL_OFFSET);
break;
case a64inst_CONDITIONAL:
inst->data.BranchData.processOpData.conditionalData.offset = getField(BRANCH_CONDITIONAL_OFFSET);
word conditionFlag = getField(BRANCH_CONDITIONAL_COND);
if(conditionFlag <= 1 || (conditionFlag >= 10 && conditionFlag <= 14)) {
inst->data.BranchData.processOpData.conditionalData.cond = conditionFlag;
} else {
fprintf(stderr, "Unknown condition detected!\n");
exit(1);
}
break;
case a64inst_REGISTER:
inst->data.BranchData.processOpData.registerData.src = getField(BRANCH_REGISTER_SRC);
break;
default:
fprintf(stderr, "Undefined branch type detected!\n");
exit(1);
break;
}
}
static void decodeDPRegister(word wrd, a64inst_instruction *inst) {
inst->data.DPRegisterData.regType = getField(DP_WIDTH);
inst->data.DPRegisterData.processOp = getField(DP_OP);
inst->data.DPRegisterData.dest = getField(DP_DEST);
inst->data.DPRegisterData.src1 = getField(DP_REG_SRC1);
inst->data.DPRegisterData.src2 = getField(DP_REG_SRC2);
inst->data.DPRegisterData.DPROpType = getField(DP_REG_OPTYPE);
a64inst_DPRegister_ArithmLogicData *arithmLogicData = &inst->data.DPRegisterData.processOpData.arithmLogicData;
arithmLogicData->type = getField(DP_REG_ARITHMLOGIC_ARITHMFLAG);
arithmLogicData->shiftType = getField(DP_REG_ARITHMLOGIC_SHIFTTYPE);
arithmLogicData->negShiftedSrc2 = getField(DP_REG_ARITHMLOGIC_NEGSRC2FLAG);
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 = getField(DP_REG_ARITHMLOGIC_SHIFTAMOUNT);
break;
case a64inst_DPR_MULTIPLY:;
if (!(inst->data.DPRegisterData.processOp == DP_REG_MULTIPLY_PROCESSOP &&
arithmLogicData->type == DP_REG_MULTIPLY_ARITHMFLAG &&
arithmLogicData->shiftType == DP_REG_MULTIPLY_SHIFTTYPE &&
arithmLogicData->negShiftedSrc2 == DP_REG_MULTIPLY_NEGSRC2FLAG)) {
fprintf(stderr, "Attempting to decode multiply DPR instruction with invalid format!\n");
}
inst->data.DPRegisterData.processOpData.multiplydata.summand = getField(DP_REG_MULTIPLY_SUMMAND);
inst->data.DPRegisterData.processOpData.multiplydata.negProd = getField(DP_REG_MULTIPLY_NEGPROD);
break;
}
}
static void decodeSingleTransfer(word wrd, a64inst_instruction *inst) {
inst->data.SingleTransferData.regType = getField(SDT_REGTYPE_FLAG);
inst->data.SingleTransferData.target = getField(SDT_TARGET_REG);
bool singleTransferOptype = getField(SDT_OPTYPE_FLAG);
if(singleTransferOptype == a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER) {
// Single Data Transfer
inst->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER;
inst->data.SingleTransferData.processOpData.singleDataTransferData.transferType = getField(SDT_TRANSFER_TYPE);
inst->data.SingleTransferData.processOpData.singleDataTransferData.base = getField(SDT_BASE_REG);
if (getField(SDT_UNSIGNED_FLAG) == 1) {
// Unsigned offset
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_UNSIGNED_OFFSET;
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = getField(SDT_OFFSET);
} else if (getField(SDT_REGISTER_FLAG) == 1) {
// Register Offset
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_REGISTER_OFFSET;
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.offsetReg = getField(SDT_REGISTER_REG);
} else {
// Pre-Indexed or Post-Indexed
inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = getField(SDT_INDEXED_ADDRMODE);
inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = getField(SDT_INDEXED_OFFSET);
}
} else {
// Load Literal
inst->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_LOAD_LITERAL;
inst->data.SingleTransferData.processOpData.loadLiteralData.offset = getField(SDT_LOAD_LITERAL_OFFSET);
}
}

View File

@ -8,8 +8,8 @@
#define DP_IMM_ID 4 #define DP_IMM_ID 4
#define BRANCH_ID 5 #define BRANCH_ID 5
#define DP_REG_LSB 25 #define DP_REG_FLAG_LSB 25
#define DP_REG_MSB 26 #define DP_REG_FLAG_MSB 26
#define DP_WIDTH_LSB 31 #define DP_WIDTH_LSB 31
#define DP_WIDTH_MSB 32 #define DP_WIDTH_MSB 32