/** @file encode.c * @brief A function to encode the internal representation of ARMv8 * instructions, a64inst_instruction, into binary. * * @author Ethan Dias Alberto * @author George Niedringhaus * @author Saleh Bubshait */ #include "symboltable.h" #include #include "../util/binary_util.h" #include "encode.h" #define HALT_BINARY 2315255808 static int getLabelOffset(symbol_table* table, char* label, int currentIndex, int n_bits) { address target = st_get(table, label); return signExtend((unsigned int) (target - currentIndex), n_bits); } // Generates assembled code based on the two-pass assembly method static word encodeBranch(a64inst_instruction *instr, int index, symbol_table *st) { word wrd = 0; switch (instr->data.BranchData.BranchType) { case a64inst_UNCONDITIONAL: setBits(&wrd, 26, 29, 0x5); setBits(&wrd, 0, 26, getLabelOffset(st, instr->data.BranchData.processOpData.unconditionalData.label, index, 26)); break; case a64inst_REGISTER: setBits(&wrd, 16, 32, 0xD61F); setBits(&wrd, 5, 10, instr->data.BranchData.processOpData.registerData.src); break; case a64inst_CONDITIONAL: setBits(&wrd, 26, 32, 0x15); setBits(&wrd, 5, 24, getLabelOffset(st, instr->data.BranchData.processOpData.conditionalData.label, index, 19)); setBits(&wrd, 0, 4, instr->data.BranchData.processOpData.conditionalData.cond); break; } return wrd; } static word encodeDPImmediate(a64inst_instruction inst) { word wrd = 0; a64inst_DPImmediateData data = inst.data.DPImmediateData; setBits(&wrd, 31, 32, data.regType); // sf setBits(&wrd, 29, 31, data.processOp); // opc setBits(&wrd, 28, 29, 0x1); // constant value setBits(&wrd, 0, 5, data.dest); // rd if (data.DPIOpType == a64inst_DPI_ARITHM) { setBits(&wrd, 23, 26, 0x2); //opi setBits(&wrd, 5, 10, data.processOpData.arithmData.src); // rn setBits(&wrd, 22, 23, data.processOpData.arithmData.shiftImmediate); // sh setBits(&wrd, 10, 22, data.processOpData.arithmData.immediate); // imm12 } // if wide move else { setBits(&wrd, 23, 26, 0x5); //opi uint8_t hw = data.processOpData.wideMovData.shiftScalar / 16; setBits(&wrd, 21, 23, hw); // hw setBits(&wrd, 5, 21, data.processOpData.wideMovData.immediate); // imm16 } return wrd; } static word encodeDPRegister(a64inst_instruction inst) { word wrd = 0; a64inst_DPRegisterData data = inst.data.DPRegisterData; setBits(&wrd, 31, 32, data.regType); // sf setBits(&wrd, 29, 31, data.processOp); // opc setBits(&wrd, 28, 29, data.DPROpType); // M setBits(&wrd, 25 ,28, 0x5); setBits(&wrd, 16, 21, data.src2); // src2 setBits(&wrd, 5, 10, data.src1); // src1 setBits(&wrd, 0, 5, data.dest); // src2 if (data.DPROpType == a64inst_DPR_MULTIPLY) { setBits(&wrd, 21, 31, 0xD8); setBits(&wrd, 15, 16, data.processOpData.multiplydata.negProd); setBits(&wrd, 10, 15, data.processOpData.multiplydata.summand); } else { // Arithmetic Logic Instruction setBits(&wrd, 22, 24, data.processOpData.arithmLogicData.shiftType); setBits(&wrd, 10, 16, data.processOpData.arithmLogicData.shiftAmount); if (data.processOpData.arithmLogicData.type == a64inst_DPR_ARITHM) { // Arithmetic setBits(&wrd, 24, 25, 0x1); // bit 24 } else { setBits(&wrd, 21, 22, data.processOpData.arithmLogicData.negShiftedSrc2); } } return wrd; } static word encodeSingleDataTransfer(a64inst_instruction inst) { word wrd = 0; a64inst_SingleTransferData data = inst.data.SingleTransferData; a64inst_SingleDataTransferData data2 = data.processOpData.singleDataTransferData; setBits(&wrd, 22, 32, 0x2E0); setBits(&wrd, 30, 31, data.regType); setBits(&wrd, 24, 25, data2.addressingMode == a64inst_UNSIGNED_OFFSET); setBits(&wrd, 22, 23, data2.transferType); setBits(&wrd, 5, 10, data2.base); setBits(&wrd, 0, 5, data.target); switch (data2.addressingMode) { // register offset case a64inst_REGISTER_OFFSET: setBits(&wrd, 21, 22, 1); setBits(&wrd, 10, 16, 0x1A); setBits(&wrd, 16, 21, data2.a64inst_addressingModeData.offsetReg); break; // unsigned offset case a64inst_UNSIGNED_OFFSET: setBits(&wrd, 10, 22, data2.a64inst_addressingModeData.unsignedOffset); break; // pre/post indexed default: setBits(&wrd, 21, 22, 0); setBits(&wrd, 11, 12, data2.addressingMode == a64inst_PRE_INDEXED); setBits(&wrd, 10, 11, 1); setBits(&wrd, 12, 21, data2.a64inst_addressingModeData.indexedOffset); break; } return wrd; } static word encodeLoadLiteral(a64inst_instruction cI, int arrIndex, symbol_table *st) { word wrd = 0; a64inst_SingleTransferData data = cI.data.SingleTransferData; setBits(&wrd, 24, 32, 0x18); setBits(&wrd, 30, 31, data.regType); char *label = data.processOpData.loadLiteralData.label; int offset = getLabelOffset(st, label, arrIndex, 19); setBits(&wrd, 5, 24, offset); setBits(&wrd, 0, 5, data.target); return wrd; } word *encode(a64inst_instruction insts[], int instCount, symbol_table* st) { word *arr = (word*)malloc(sizeof(word) * instCount); int index = 0; for (int i = 0; i < instCount; i++) { a64inst_instruction inst = insts[i]; switch (inst.type) { case a64inst_DPIMMEDIATE: arr[index] = encodeDPImmediate(inst); index++; break; case a64inst_DPREGISTER: arr[index] = encodeDPRegister(inst); index++; break; case a64inst_SINGLETRANSFER: arr[index] = encodeSingleDataTransfer(inst); index++; break; case a64inst_LOADLITERAL: arr[index] = encodeLoadLiteral(inst, index, st); index++; break; case a64inst_DIRECTIVE: arr[index] = inst.data.DirectiveData.value; index++; break; case a64inst_HALT: arr[index] = HALT_BINARY; index++; break; case a64inst_LABEL: // Labels are handled in the first pass and used for addressing. break; case a64inst_BRANCH: arr[index] = encodeBranch(&inst, index, st); index++; default: break; } } return arr; }