diff --git a/src/a64instruction.h b/src/a64instruction.h index f0f617f..31fc602 100644 --- a/src/a64instruction.h +++ b/src/a64instruction.h @@ -1,5 +1,7 @@ #include "a64instruction_DPImmediate.h" #include "a64instruction_Branch.h" +#include "a64instruction_SingleTransfer.h" + // Define the types of instructions in subset of the AArch64 Instruction Set implemented. // Each type is defined by the format of the instruction's operand(s). typedef enum { @@ -17,5 +19,6 @@ typedef struct { union { a64inst_DPImmediateData DPImmediateData; a64inst_BranchData BranchData; + a64inst_SingleTransferData SingleTransferData; } data; } a64inst_instruction; diff --git a/src/decode.c b/src/decode.c index 3610811..3f13a5f 100644 --- a/src/decode.c +++ b/src/decode.c @@ -97,6 +97,36 @@ a64inst_instruction *decode(word wrd) { } else { // Load and Store, or unknown + // Ignore unknown for now + inst->type = a64inst_SINGLETRANSFER; + inst->data.SingleTransferData.regType = getBits(wrd, SINGLE_TRANSFER_REGTYPE_FLAG_LSB, SINGLE_TRANSFER_REGTYPE_FLAG_MSB); + inst->data.SingleTransferData.target = getBits(wrd, SINGLE_TRANSFER_TARGET_REG_LSB, SINGLE_TRANSFER_TARGET_REG_MSB); + + // TODO: Assert that the instruction is a Single Transfer indeed. + + if(getBits(wrd, SINGLE_TRANSFER_OPTYPE_FLAG_LSB, SINGLE_TRANSFER_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, SINGLE_DATA_TRANSFER_TRANSFER_TYPE_LSB, SINGLE_DATA_TRANSFER_TRANSFER_TYPE_MSB); + inst->data.SingleTransferData.processOpData.singleDataTransferData.base = getBits(wrd, SINGLE_DATA_TRANSFER_BASE_REG_LSB, SINGLE_DATA_TRANSFER_BASE_REG_MSB); + if (getBits(wrd, SINGLE_DATA_TRANSFER_UNSIGNED_FLAG_LSB, SINGLE_DATA_TRANSFER_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, SINGLE_DATA_TRANSFER_OFFSET_LSB, SINGLE_DATA_TRANSFER_OFFSET_MSB); + } else if (getBits(wrd, SINGLE_DATA_TRANSFER_REGISTER_FLAG_LSB, SINGLE_DATA_TRANSFER_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, SINGLE_DATA_TRANSFER_REGISTER_REG_LSB, SINGLE_DATA_TRANSFER_REGISTER_REG_MSB); + } else { + // Pre-Indexed or Post-Indexed + inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = getBits(wrd, SINGLE_DATA_TRANSFER_INDEXED_ADDRMODE_LSB, SINGLE_DATA_TRANSFER_INDEXED_ADDRMODE_MSB); + inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = getBits(wrd, SINGLE_DATA_TRANSFER_INDEXED_OFFSET_LSB, SINGLE_DATA_TRANSFER_INDEXED_OFFSET_MSB); + } + } else { + // Load Literal + inst->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_LOAD_LITERAL; + inst->data.SingleTransferData.processOpData.loadLiteralData.offset = getBits(wrd, SINGLE_DATA_TRANSFER_LOAD_LITERAL_OFFSET_LSB, SINGLE_DATA_TRANSFER_LOAD_LITERAL_OFFSET_MSB); + } } return inst; diff --git a/src/decode.h b/src/decode.h index 6494f0f..a141a8f 100644 --- a/src/decode.h +++ b/src/decode.h @@ -33,6 +33,32 @@ #define DP_IMM_WIDEMOV_IMMVAL_LSB 5 #define DP_IMM_WIDEMOV_IMMVAL_MSB 21 +#define SINGLE_TRANSFER_OPTYPE_FLAG_LSB 31 +#define SINGLE_TRANSFER_OPTYPE_FLAG_MSB 32 +#define SINGLE_TRANSFER_REGTYPE_FLAG_LSB 30 +#define SINGLE_TRANSFER_REGTYPE_FLAG_MSB 31 +#define SINGLE_TRANSFER_TARGET_REG_LSB 0 +#define SINGLE_TRANSFER_TARGET_REG_MSB 5 + +#define SINGLE_DATA_TRANSFER_BASE_REG_LSB 5 +#define SINGLE_DATA_TRANSFER_BASE_REG_MSB 10 +#define SINGLE_DATA_TRANSFER_OFFSET_LSB 10 +#define SINGLE_DATA_TRANSFER_OFFSET_MSB 22 +#define SINGLE_DATA_TRANSFER_TRANSFER_TYPE_LSB 22 +#define SINGLE_DATA_TRANSFER_TRANSFER_TYPE_MSB 23 +#define SINGLE_DATA_TRANSFER_UNSIGNED_FLAG_LSB 24 +#define SINGLE_DATA_TRANSFER_UNSIGNED_FLAG_MSB 25 +#define SINGLE_DATA_TRANSFER_REGISTER_FLAG_LSB 21 +#define SINGLE_DATA_TRANSFER_REGISTER_FLAG_MSB 22 +#define SINGLE_DATA_TRANSFER_REGISTER_REG_LSB 16 +#define SINGLE_DATA_TRANSFER_REGISTER_REG_MSB 21 +#define SINGLE_DATA_TRANSFER_INDEXED_ADDRMODE_LSB 11 +#define SINGLE_DATA_TRANSFER_INDEXED_ADDRMODE_MSB 12 +#define SINGLE_DATA_TRANSFER_INDEXED_OFFSET_LSB 12 +#define SINGLE_DATA_TRANSFER_INDEXED_OFFSET_MSB 21 +#define SINGLE_DATA_TRANSFER_LOAD_LITERAL_OFFSET_LSB 5 +#define SINGLE_DATA_TRANSFER_LOAD_LITERAL_OFFSET_MSB 24 + #define BRANCH_TYPE_LSB 30 #define BRANCH_TYPE_MSB 32 #define BRANCH_UNCONDITIONAL_OFFSET_LSB 0