From f57e0a786f10c3cf7c0021985c2fddda12765773 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Thu, 6 Jun 2024 17:14:56 +0100 Subject: [PATCH 01/19] rename assembler funcs for clarity --- src/twopassassembly.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/twopassassembly.c b/src/twopassassembly.c index cda97ec..50fe029 100644 --- a/src/twopassassembly.c +++ b/src/twopassassembly.c @@ -49,7 +49,7 @@ st* firstPass(a64inst_instruction instrs[], int numInstrs){ } return &table; } -word dpi(a64inst_instruction cI) { +word assembleDPI(a64inst_instruction cI) { word out = 0; a64inst_DPImmediateData data = cI.data.DPImmediateData; //sf @@ -78,7 +78,7 @@ word dpi(a64inst_instruction cI) { return out; } -word dpr(a64inst_instruction cI) { +word assembleDPR(a64inst_instruction cI) { word out = 0; a64inst_DPRegisterData data = cI.data.DPRegisterData; // sf @@ -131,7 +131,7 @@ word dpr(a64inst_instruction cI) { return out; } -word sts(a64inst_instruction cI) { +word assembleSTS(a64inst_instruction cI) { a64inst_SingleTransferData data = cI.data.SingleTransferData; word out = 0; a64inst_SingleDataTransferData data2 = data.processOpData.singleDataTransferData; @@ -166,7 +166,7 @@ word sts(a64inst_instruction cI) { return out; } -word ldl(a64inst_instruction cI) { +word assembleLDL(a64inst_instruction cI) { word out = 3*(2^27); a64inst_SingleTransferData data = cI.data.SingleTransferData; int sf = data.regType; From 1fa33798bfe7e62f878d0fc6e81e02b5be56a7d7 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Thu, 6 Jun 2024 17:38:54 +0100 Subject: [PATCH 02/19] rewrite DP classification logic --- src/parser.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/parser.c b/src/parser.c index 8b98cb0..3296dac 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,5 +1,6 @@ #include #include +#include #include "parser.h" #include "a64instruction.h" @@ -25,23 +26,23 @@ void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[]){ } else if( (strcmp(operandList[2][strlen(operandList[1])-1], "x") == 0) || (strcmp(operandList[2][strlen(operandList[1])-1], "w") == 0)){ //register - instr->data.processOpData.addressingMode = a64inst_REGISTER_OFFSET; + instr->data.SingleTransferData.singleDataTransferData.processOpData.addressingMode = a64inst_REGISTER_OFFSET; } else { instr->data.processOpData.addressingMode = a64inst_UNSIGNED_OFFSET; } } void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *operandList[]){ - switch(instr->data.type){ + switch(instr->type){ case a64inst_SINGLETRANSFER: if(strcmp(operandList[0][0], "x")==0){ //x-register - instr->data.regType = 1; + instr->data.SingleTransferData.regType = 1; } else { - instr->data.regType = 0; + instr->data.SingleTransferData.regType = 0; } char *endptr; - instr->data.target = strtol(operandList[0][0]+1, endptr, 2); + instr->data.SingleTransferData.target = strtol(operandList[0][0]+1, endptr, 2); calcluateAddressFormat(instr, operandList); break; case a64inst_LOADLITERAL: @@ -51,38 +52,48 @@ void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *o } void generateBranchOperands(a64inst_instruction *instr, char* opcode, char *operandList[]){ - switch(instr->data.BranchType){ + switch(instr->data.BranchData.BranchType){ case a64inst_UNCONDITIONAL: //define and sign extend immediate offset //use symbol table break; case a64inst_REGISTER: char *endptr; - instr->data.processOpData.src = strtol(operandList[0] + 1, endptr, 2) + instr->data.BranchData.processOpData.src = strtol(operandList[0] + 1, endptr, 2) break; case a64inst_CONDITIONAL: char* condition = strtok(strdup(opcode), "b."); condition = strtok(NULL, ""); if(strcmp(condition, "eq")==0){ - instr->data.processOpData.cond = EQ; + instr->data.branchData.processOpData.cond = EQ; } else if (strcmp(condition, "ne")==0){ - instr->data.processOpData.cond = NE; + instr->data.branchData.processOpData.cond = NE; } else if (strcmp(condition, "ge")==0){ - instr->data.processOpData.cond = GE; + instr->data.branchData.processOpData.cond = GE; } else if (strcmp(condition, "lt")==0){ - instr->data.processOpData.cond = LT; + instr->data.branchData.processOpData.cond = LT; } else if (strcmp(condition, "gt")==0){ - instr->data.processOpData.cond = GT; + instr->data.branchData.processOpData.cond = GT; } else if (strcmp(condition, "le")==0){ - instr->data.processOpData.cond = LE; + instr->data.branchData.processOpData.cond = LE; } else if (srtcmp(condition, "al")==0){ - instr->data.processOpData.cond = AL; + instr->data.branchData.processOpData.cond = AL; } break; //calculate offset from symbol table. } } +int isOperandRegister(char *operand){ + return((strcmp(operand[0], "x")==0) || (strcmp(operand[0], "w")==0)); +} + +int classifyDPInst(char *operandList[]){ + return(isOperandRegister(operandList[0]) && + isOperandRegister(operandList[1]) && + isOperandRegister(operandList[2])); +} + void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[]){ int isUnconditional = strcmp(opcode, "b"); int isRegister = strcmp(opcode, "br"); @@ -108,11 +119,11 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ if( *address == '['){ //type is register instr->type = a64inst_SINGLETRANSFER; - instr->data.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER; + instr->data.singleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER; if(isLoad == 0){ - instr->data.processOpData.transferType = a64inst_LOAD; + instr->data.SingleTransferData.transferType = a64inst_LOAD; } else { - instr->data.processOpData.transferType = a64inst_STORE; + instr->data.SingleTransferData.processOpData.transferType = a64inst_STORE; } } else { instr->type = a64inst_LOADLITERAL; @@ -121,7 +132,7 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ } else { int numOperands = sizeof(operandList) / sizeof(operandList[0]) - if(numOperands==3){ + if(classifyDPInst(operandList)){ instr->type = a64inst_DPREGISTER; } else { instr->type = a64inst_DPIMMEDIATE; @@ -172,7 +183,7 @@ a64inst_instruction *parser(char asmLine[]){ instr->type = a64inst_LABEL; char *opcodeCpy = strdup(opcode); char *labelData = strtok(opcodeCpy, ":"); - instr->data.label = labelData; + instr->data.labelData.label = labelData; } else { //type is instruction int operandCount = 0; From 34060c3fad86449822591cbd48e57d3b4fac5c08 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Thu, 6 Jun 2024 17:54:35 +0100 Subject: [PATCH 03/19] fix hierarchy of struct access in parser --- src/parser.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/parser.c b/src/parser.c index 3296dac..1bcf31e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -14,21 +14,22 @@ // - match opcode to a64 struct types (DONE) // - count operands and match type/values // - generate final a64inst and return +// - CREATE FUNC TO TIDY UP OPERANDS IN DP //calculate offsets from string void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[]){ if(strcmp(operandList[2][strlen(operandList[1])-1], "!")==0){ - instr->data.processOpData.addressingMode = a64inst_PRE_INDEXED; + instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_PRE_INDEXED; } else if(strcmp(operandList[1][strlen(operandList[0])-1], "]") == 0) { //post-indexed - instr->data.processOpData.addressingMode = a64inst_POST_INDEXED; + instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_POST_INDEXED; } else if( (strcmp(operandList[2][strlen(operandList[1])-1], "x") == 0) || (strcmp(operandList[2][strlen(operandList[1])-1], "w") == 0)){ //register - instr->data.SingleTransferData.singleDataTransferData.processOpData.addressingMode = a64inst_REGISTER_OFFSET; + instr->data.SingleTransferData.processOpData.singleDataTransferData.processOpData.addressingMode = a64inst_REGISTER_OFFSET; } else { - instr->data.processOpData.addressingMode = a64inst_UNSIGNED_OFFSET; + instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_UNSIGNED_OFFSET; } } @@ -59,25 +60,25 @@ void generateBranchOperands(a64inst_instruction *instr, char* opcode, char *oper break; case a64inst_REGISTER: char *endptr; - instr->data.BranchData.processOpData.src = strtol(operandList[0] + 1, endptr, 2) + instr->data.BranchData.processOpData.registerData.src = strtol(operandList[0] + 1, endptr, 2) break; case a64inst_CONDITIONAL: char* condition = strtok(strdup(opcode), "b."); condition = strtok(NULL, ""); if(strcmp(condition, "eq")==0){ - instr->data.branchData.processOpData.cond = EQ; + instr->data.branchData.processOpData.conditionalData.cond = EQ; } else if (strcmp(condition, "ne")==0){ - instr->data.branchData.processOpData.cond = NE; + instr->data.branchData.processOpData.conditionalData.cond = NE; } else if (strcmp(condition, "ge")==0){ - instr->data.branchData.processOpData.cond = GE; + instr->data.branchData.processOpData.conditionalData.cond = GE; } else if (strcmp(condition, "lt")==0){ - instr->data.branchData.processOpData.cond = LT; + instr->data.branchData.processOpData.conditionalData.cond = LT; } else if (strcmp(condition, "gt")==0){ - instr->data.branchData.processOpData.cond = GT; + instr->data.branchData.processOpData.conditionalData.cond = GT; } else if (strcmp(condition, "le")==0){ - instr->data.branchData.processOpData.cond = LE; + instr->data.branchData.processOpData.conditionalData.cond = LE; } else if (srtcmp(condition, "al")==0){ - instr->data.branchData.processOpData.cond = AL; + instr->data.branchData.processOpData.conditionalData.cond = AL; } break; //calculate offset from symbol table. From 04dda33987e478800ee7feee263221ab58b97a6f Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Sun, 9 Jun 2024 22:21:30 +0100 Subject: [PATCH 04/19] calculate base register from input --- src/parser.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/parser.c b/src/parser.c index 1bcf31e..192278e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -18,14 +18,21 @@ //calculate offsets from string void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[]){ + char *baseRegister = operandList[1]; + baseRegister++; + baseRegister++; + char *endptr; + uint8_t base = strtol(baseRegister, endptr, 10); + instr->data.SingleTransferData.processOpData.singleDataTransferData.base = base; if(strcmp(operandList[2][strlen(operandList[1])-1], "!")==0){ instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_PRE_INDEXED; + } else if(strcmp(operandList[1][strlen(operandList[0])-1], "]") == 0) { //post-indexed instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_POST_INDEXED; - } else if( (strcmp(operandList[2][strlen(operandList[1])-1], "x") == 0) - || (strcmp(operandList[2][strlen(operandList[1])-1], "w") == 0)){ + } else if( (strcmp(operandList[2][0], "x") == 0) + || (strcmp(operandList[2][0], "w") == 0)){ //register instr->data.SingleTransferData.processOpData.singleDataTransferData.processOpData.addressingMode = a64inst_REGISTER_OFFSET; } else { @@ -43,7 +50,7 @@ void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *o instr->data.SingleTransferData.regType = 0; } char *endptr; - instr->data.SingleTransferData.target = strtol(operandList[0][0]+1, endptr, 2); + instr->data.SingleTransferData.target = strtol(operandList[0][0]+1, endptr, 10); calcluateAddressFormat(instr, operandList); break; case a64inst_LOADLITERAL: @@ -60,7 +67,7 @@ void generateBranchOperands(a64inst_instruction *instr, char* opcode, char *oper break; case a64inst_REGISTER: char *endptr; - instr->data.BranchData.processOpData.registerData.src = strtol(operandList[0] + 1, endptr, 2) + instr->data.BranchData.processOpData.registerData.src = strtol(operandList[0] + 1, endptr, 10) break; case a64inst_CONDITIONAL: char* condition = strtok(strdup(opcode), "b."); From 4098ea5a5f26c8d243195219df43d376fb6a3fdb Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Sun, 9 Jun 2024 22:43:37 +0100 Subject: [PATCH 05/19] calculate offsets for different store instructions --- src/parser.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/parser.c b/src/parser.c index 192278e..699bdb6 100644 --- a/src/parser.c +++ b/src/parser.c @@ -17,8 +17,8 @@ // - CREATE FUNC TO TIDY UP OPERANDS IN DP //calculate offsets from string -void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[]){ - char *baseRegister = operandList[1]; +void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[], int numOperands){ + char *baseRegister = strdup(operandList[1]); baseRegister++; baseRegister++; char *endptr; @@ -27,20 +27,39 @@ void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[]){ if(strcmp(operandList[2][strlen(operandList[1])-1], "!")==0){ instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_PRE_INDEXED; - + char *offsetParam = strdup(operandList[2]); + offsetParam++; + instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = strtol(operandList[2], endptr, 10); } else if(strcmp(operandList[1][strlen(operandList[0])-1], "]") == 0) { //post-indexed instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_POST_INDEXED; + char *offsetParam = strdup(operandList[2]); + offsetParam++; + instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = strtol(operandList[2], endptr, 10); } else if( (strcmp(operandList[2][0], "x") == 0) || (strcmp(operandList[2][0], "w") == 0)){ //register - instr->data.SingleTransferData.processOpData.singleDataTransferData.processOpData.addressingMode = a64inst_REGISTER_OFFSET; + instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_REGISTER_OFFSET; + char *offsetRegister = strdup(operandList[2]); + offsetRegister++; + instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingModeData.offsetReg = strtol(offsetRegister, endptr, 10); } else { instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_UNSIGNED_OFFSET; + if(numOperands==3){ + char *offsetParam = strdup(operandList[2]); + offsetParam++; + int offset = strtol(operandList[2], endptr, 10); + if(instr->data.SingleTransferData.regType == 1){ + instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = offset/8; + } else { + instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = offset/4; + + } + } } } -void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *operandList[]){ +void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *operandList[], int numOperands){ switch(instr->type){ case a64inst_SINGLETRANSFER: if(strcmp(operandList[0][0], "x")==0){ @@ -51,7 +70,7 @@ void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *o } char *endptr; instr->data.SingleTransferData.target = strtol(operandList[0][0]+1, endptr, 10); - calcluateAddressFormat(instr, operandList); + calcluateAddressFormat(instr, operandList, numOperands); break; case a64inst_LOADLITERAL: break; @@ -102,7 +121,7 @@ int classifyDPInst(char *operandList[]){ isOperandRegister(operandList[2])); } -void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[]){ +void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[], int numOperands){ int isUnconditional = strcmp(opcode, "b"); int isRegister = strcmp(opcode, "br"); int isLoad = strcmp(opcode, "ldr"); @@ -149,7 +168,7 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ } } -char *tokeniseOperands(char* str, int operandCount, char *operands[]){ +char *tokeniseOperands(char* str, int operandCount, char *operands[], int numOperands){ char *operandsDupe = strdup(str); char *operand = strtok(operandsDupe, OPERAND_DELIMITER); operands[0] = operand; @@ -159,11 +178,13 @@ char *tokeniseOperands(char* str, int operandCount, char *operands[]){ operand = strtok(NULL, OPERAND_DELIMITER); operands[operandCount] = operand; } + numOperands = operandCount+1; } //takes inputted assembly line and returns a //pointer to an abstract representation of the instruction a64inst_instruction *parser(char asmLine[]){ + int numOperands = 0; a64inst_instruction *instr = malloc(sizeof(a64inst_instruction)); if (instr == NULL){ exit(EXIT_FAILURE); @@ -196,7 +217,7 @@ a64inst_instruction *parser(char asmLine[]){ //type is instruction int operandCount = 0; const char *operandList[4]; - tokeniseOperands(operands, &operandCount, operandList); + tokeniseOperands(operands, &operandCount, operandList, &numOperands); } From 44bb327b7d13a85d5095c0265cb9dd99fda9670d Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Sun, 9 Jun 2024 22:54:27 +0100 Subject: [PATCH 06/19] begin formulating parser pipeline --- src/parser.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/parser.c b/src/parser.c index 699bdb6..40e264f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -36,8 +36,8 @@ void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[], in char *offsetParam = strdup(operandList[2]); offsetParam++; instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = strtol(operandList[2], endptr, 10); - } else if( (strcmp(operandList[2][0], "x") == 0) - || (strcmp(operandList[2][0], "w") == 0)){ + } else if( (isOperandRegister(operandList[2][0], "x") == 1) + || (isOperandRegister(operandList[2][0], "w") == 1)){ //register instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_REGISTER_OFFSET; char *offsetRegister = strdup(operandList[2]); @@ -53,7 +53,6 @@ void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[], in instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = offset/8; } else { instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = offset/4; - } } } @@ -218,6 +217,27 @@ a64inst_instruction *parser(char asmLine[]){ int operandCount = 0; const char *operandList[4]; tokeniseOperands(operands, &operandCount, operandList, &numOperands); + classifyOpcode(opcode, instr, operandList, operandCount); + switch(instr->type){ + case a64inst_BRANCH: + generateBranchOperands(instr, opcode, operandList); + break; + case a64inst_SINGLETRANSFER: + generateLoadStoreOperands(instr, opcode, operandList, numOperands); + break; + case a64inst_LOADLITERAL: + generateLoadStoreOperands(instr, opcode, operandList, numOperands); + break; + case a64inst_DPREGISTER: + //generate DP operands; + break; + case a64inst_DPIMMEDIATE: + //generate DP operands; + break; + default: + printf("INVALID INSTRUCTION"); + break; + } } From d0be871e8f5bc3699a9710ea4ffaada01fc489c0 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Sun, 9 Jun 2024 23:07:45 +0100 Subject: [PATCH 07/19] generate offset operand for load literal with immediate value --- src/parser.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/parser.c b/src/parser.c index 40e264f..9a1ac25 100644 --- a/src/parser.c +++ b/src/parser.c @@ -153,11 +153,19 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ } } else { instr->type = a64inst_LOADLITERAL; - //instr->data.processOpData.offset = {} to be defined by symbol table + if(strcmp(operandList[0][0], "#")==0){ + //offset is immediate + char *immOffset = strdup(operandList[0]) + immOffset++; + char *endptr; + int offset = strtol(immOffset, endptr, 10); + instr->data.SingleTransferData.processOpData.loadLiteralData.offset = offset; + } else { + //offset is literal, use symbol table and calculate difference + } } } else { - int numOperands = sizeof(operandList) / sizeof(operandList[0]) if(classifyDPInst(operandList)){ instr->type = a64inst_DPREGISTER; } else { From 92719b6b33159a328624e95d341bc83ada815719 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Sun, 9 Jun 2024 23:10:39 +0100 Subject: [PATCH 08/19] comments for clarity in parser --- src/parser.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/parser.c b/src/parser.c index 9a1ac25..c0a3caa 100644 --- a/src/parser.c +++ b/src/parser.c @@ -136,7 +136,6 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ instr->data.BranchData.BranchType = a64inst_REGISTER; } else { instr->data.BranchData.BranchType = a64inst_CONDITIONAL; - //instr->data.branchData.processOpData.cond = {remove first two chars of opcode} } generateBranchOperands(instr, opcode, operandList); } else if(isLoad == 0 || isStore == 0){ @@ -224,8 +223,11 @@ a64inst_instruction *parser(char asmLine[]){ //type is instruction int operandCount = 0; const char *operandList[4]; + //generate list of operands tokeniseOperands(operands, &operandCount, operandList, &numOperands); + //categorise instruction type from opcode and operands classifyOpcode(opcode, instr, operandList, operandCount); + //define struct values according to operands and type switch(instr->type){ case a64inst_BRANCH: generateBranchOperands(instr, opcode, operandList); From 6153db77377dc812983096fff61e9337f49fa88d Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Tue, 11 Jun 2024 17:35:23 +0100 Subject: [PATCH 09/19] fix compile issues git add . :) --- src/assemble.c | 1 + src/emulate.c | 6 +++ src/parser.c | 130 ++++++++++++++++++++++++------------------------- src/parser.h | 3 -- 4 files changed, 72 insertions(+), 68 deletions(-) mode change 100755 => 100644 src/emulate.c diff --git a/src/assemble.c b/src/assemble.c index ae760c0..aa54b4e 100755 --- a/src/assemble.c +++ b/src/assemble.c @@ -1,5 +1,6 @@ #include #include +#include "parser.c" int main(int argc, char **argv) { diff --git a/src/emulate.c b/src/emulate.c old mode 100755 new mode 100644 index 82245e9..be41f56 --- a/src/emulate.c +++ b/src/emulate.c @@ -8,6 +8,11 @@ #include "decode.h" #include "execute.h" +int main(int arg, char **argv){ + return EXIT_SUCCESS; +} + +/* extern a64inst_instruction *decode(word w); int main(int argc, char **argv) { @@ -59,3 +64,4 @@ int main(int argc, char **argv) { return EXIT_SUCCESS; } +*/ diff --git a/src/parser.c b/src/parser.c index c0a3caa..fcef57b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -12,43 +12,37 @@ // - use string matching to get opcode, and operands (DONE) // - check operand count (DONE) // - match opcode to a64 struct types (DONE) -// - count operands and match type/values -// - generate final a64inst and return +// - count operands and match type/values (DONE) +// - generate final a64inst and return (TODO: DP instrs) +// - ASK ABOUT OFFSET CALCULATION // - CREATE FUNC TO TIDY UP OPERANDS IN DP +int isOperandRegister(char *operand){ + return((strcmp(&(operand[0]), "x")==0) || (strcmp(&(operand[0]), "w")==0)); +} + //calculate offsets from string void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[], int numOperands){ - char *baseRegister = strdup(operandList[1]); - baseRegister++; - baseRegister++; char *endptr; - uint8_t base = strtol(baseRegister, endptr, 10); + uint8_t base = strtol(&(operandList[1][2]), &endptr, 10); instr->data.SingleTransferData.processOpData.singleDataTransferData.base = base; - if(strcmp(operandList[2][strlen(operandList[1])-1], "!")==0){ + if(strcmp(&(operandList[2][strlen(operandList[1])-1]), "!")==0){ instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_PRE_INDEXED; - char *offsetParam = strdup(operandList[2]); - offsetParam++; - instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = strtol(operandList[2], endptr, 10); - } else if(strcmp(operandList[1][strlen(operandList[0])-1], "]") == 0) { + instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = strtol(&(operandList[2][1]), &endptr, 10); + } else if(strcmp(&(operandList[1][strlen(operandList[0])-1]), "]") == 0) { //post-indexed instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_POST_INDEXED; - char *offsetParam = strdup(operandList[2]); - offsetParam++; - instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = strtol(operandList[2], endptr, 10); - } else if( (isOperandRegister(operandList[2][0], "x") == 1) - || (isOperandRegister(operandList[2][0], "w") == 1)){ + instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset = strtol(&(operandList[2][1]), &endptr, 10); + } else if( (isOperandRegister(&(operandList[2][0])) == 1) + || (isOperandRegister(&(operandList[2][0])) == 1)){ //register instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_REGISTER_OFFSET; - char *offsetRegister = strdup(operandList[2]); - offsetRegister++; - instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingModeData.offsetReg = strtol(offsetRegister, endptr, 10); + instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.offsetReg = strtol(&(operandList[2][1]), &endptr, 10); } else { instr->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode = a64inst_UNSIGNED_OFFSET; if(numOperands==3){ - char *offsetParam = strdup(operandList[2]); - offsetParam++; - int offset = strtol(operandList[2], endptr, 10); + int offset = strtol(&(operandList[2][1]), &endptr, 10); if(instr->data.SingleTransferData.regType == 1){ instr->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset = offset/8; } else { @@ -61,59 +55,61 @@ void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[], in void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *operandList[], int numOperands){ switch(instr->type){ case a64inst_SINGLETRANSFER: - if(strcmp(operandList[0][0], "x")==0){ + if(strcmp(&(operandList[0][0]), "x")==0){ //x-register instr->data.SingleTransferData.regType = 1; } else { instr->data.SingleTransferData.regType = 0; } char *endptr; - instr->data.SingleTransferData.target = strtol(operandList[0][0]+1, endptr, 10); + instr->data.SingleTransferData.target = strtol(&(operandList[0][0])+1, &endptr, 10); calcluateAddressFormat(instr, operandList, numOperands); break; case a64inst_LOADLITERAL: break; + default: + break; } } void generateBranchOperands(a64inst_instruction *instr, char* opcode, char *operandList[]){ + char *endptr; switch(instr->data.BranchData.BranchType){ case a64inst_UNCONDITIONAL: //define and sign extend immediate offset //use symbol table + printf("unconditional"); break; case a64inst_REGISTER: - char *endptr; - instr->data.BranchData.processOpData.registerData.src = strtol(operandList[0] + 1, endptr, 10) + instr->data.BranchData.processOpData.registerData.src = strtol(operandList[0] + 1, &endptr, 10); break; case a64inst_CONDITIONAL: - char* condition = strtok(strdup(opcode), "b."); - condition = strtok(NULL, ""); - if(strcmp(condition, "eq")==0){ - instr->data.branchData.processOpData.conditionalData.cond = EQ; - } else if (strcmp(condition, "ne")==0){ - instr->data.branchData.processOpData.conditionalData.cond = NE; - } else if (strcmp(condition, "ge")==0){ - instr->data.branchData.processOpData.conditionalData.cond = GE; - } else if (strcmp(condition, "lt")==0){ - instr->data.branchData.processOpData.conditionalData.cond = LT; - } else if (strcmp(condition, "gt")==0){ - instr->data.branchData.processOpData.conditionalData.cond = GT; - } else if (strcmp(condition, "le")==0){ - instr->data.branchData.processOpData.conditionalData.cond = LE; - } else if (srtcmp(condition, "al")==0){ - instr->data.branchData.processOpData.conditionalData.cond = AL; + { + char *condition = NULL; + condition = strcpy(condition, opcode); + condition += 2; + if(strcmp(condition, "eq")==0){ + instr->data.BranchData.processOpData.conditionalData.cond = EQ; + } else if (strcmp(condition, "ne")==0){ + instr->data.BranchData.processOpData.conditionalData.cond = NE; + } else if (strcmp(condition, "ge")==0){ + instr->data.BranchData.processOpData.conditionalData.cond = GE; + } else if (strcmp(condition, "lt")==0){ + instr->data.BranchData.processOpData.conditionalData.cond = LT; + } else if (strcmp(condition, "gt")==0){ + instr->data.BranchData.processOpData.conditionalData.cond = GT; + } else if (strcmp(condition, "le")==0){ + instr->data.BranchData.processOpData.conditionalData.cond = LE; + } else if (strcmp(condition, "al")==0){ + instr->data.BranchData.processOpData.conditionalData.cond = AL; + } + break; + //calculate offset from symbol table. } - break; - //calculate offset from symbol table. } } -int isOperandRegister(char *operand){ - return((strcmp(operand[0], "x")==0) || (strcmp(operand[0], "w")==0)); -} - int classifyDPInst(char *operandList[]){ return(isOperandRegister(operandList[0]) && isOperandRegister(operandList[1]) && @@ -144,20 +140,21 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ if( *address == '['){ //type is register instr->type = a64inst_SINGLETRANSFER; - instr->data.singleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER; + instr->data.SingleTransferData.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER; if(isLoad == 0){ - instr->data.SingleTransferData.transferType = a64inst_LOAD; + instr->data.SingleTransferData.processOpData.singleDataTransferData.transferType = a64inst_LOAD; } else { - instr->data.SingleTransferData.processOpData.transferType = a64inst_STORE; + instr->data.SingleTransferData.processOpData.singleDataTransferData.transferType = a64inst_STORE; } } else { instr->type = a64inst_LOADLITERAL; - if(strcmp(operandList[0][0], "#")==0){ + if(operandList[0][0] =='#'){ //offset is immediate - char *immOffset = strdup(operandList[0]) + char *immOffset = NULL; + immOffset = strcpy(immOffset, operandList[0]); immOffset++; - char *endptr; - int offset = strtol(immOffset, endptr, 10); + char *endptr = NULL; + int offset = strtol(immOffset, &endptr, 10); instr->data.SingleTransferData.processOpData.loadLiteralData.offset = offset; } else { //offset is literal, use symbol table and calculate difference @@ -174,17 +171,18 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ } } -char *tokeniseOperands(char* str, int operandCount, char *operands[], int numOperands){ - char *operandsDupe = strdup(str); +void tokeniseOperands(char* str, int *operandCount, char *operands[], int *numOperands){ + char *operandsDupe = NULL; + operandsDupe = strcpy(operandsDupe, str); char *operand = strtok(operandsDupe, OPERAND_DELIMITER); operands[0] = operand; while (operand != NULL){ - operandCount++; + *operandCount = *(operandCount)+1; operand = strtok(NULL, OPERAND_DELIMITER); - operands[operandCount] = operand; + operands[*(operandCount)] = operand; } - numOperands = operandCount+1; + *(numOperands) = *(operandCount)+1; } //takes inputted assembly line and returns a @@ -203,7 +201,8 @@ a64inst_instruction *parser(char asmLine[]){ //"opcode operand1, {operand2}, ..." //duplicated as strtok modifies the input string - char *stringptr = strdup(asmLine); + char *stringptr = NULL; + stringptr = strcpy(stringptr, asmLine); char *opcode = strtok(stringptr, " "); char *operands = strtok(NULL, ""); @@ -212,17 +211,18 @@ a64inst_instruction *parser(char asmLine[]){ //type is directive instr->type = a64inst_DIRECTIVE; - } else if(strcmp(opcode[strlen(opcode)-1], ":") == 0) { + } else if(opcode[strlen(opcode)-1]== ':') { //type is label //add to symbol table instr->type = a64inst_LABEL; - char *opcodeCpy = strdup(opcode); + char *opcodeCpy = NULL; + opcodeCpy = strcpy(opcodeCpy, opcode); char *labelData = strtok(opcodeCpy, ":"); - instr->data.labelData.label = labelData; + instr->data.LabelData.label = labelData; } else { //type is instruction int operandCount = 0; - const char *operandList[4]; + char *operandList[4]; //generate list of operands tokeniseOperands(operands, &operandCount, operandList, &numOperands); //categorise instruction type from opcode and operands diff --git a/src/parser.h b/src/parser.h index 5c3a461..e303b58 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,5 +1,2 @@ -#ifndef __PARSERCONSTS__ -#define __PARSERCONSTS__ #define OPERAND_DELIMITER ", " #define HALT_ASM_CMD "and x0, x0, x0" -#endif \ No newline at end of file From 173bdf08ec6a6e59d0e63f18c29fb3799f1c3831 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Tue, 11 Jun 2024 20:23:00 +0100 Subject: [PATCH 10/19] fix incorrect fileio.c --- src/fileio.c | 88 ++++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 1dcdd77..96e5cd3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1,48 +1,56 @@ -#include #include #include -#include "fileio.h" -#include "global.h" -/* Loads a binary file located at filePath to memory, taking up a block of exactly memorySize bytes, - and returns the starting address of the data. If memorySize is insufficient to store the entire file, - an appropriate error is reported. Excess memory is set to 0 bit values. */ +#define MAX_ASM_LINE_LENGTH 100 -byte *fileio_loadBin(const char *filePath, size_t memorySize) { - FILE *file = fopen(filePath, "rb"); - if (file == NULL) { - fprintf(stderr, "Couldn't open %s!\n", filePath); - exit(EXIT_FAILURE); - } +int isValidFileFormat(char filename[], char expectedExtension[]){ + int *pointLoc = strrchr(filename, '.'); - byte *fileData = malloc(memorySize); - if (fileData == NULL) { - fprintf(stderr, "Ran out of memory attempting to load %s!\n", filePath); - exit(EXIT_FAILURE); - } - - // Loop while reading from the file yields data. Only terminates if EOF is reached or ERROR occurs. - // Explicitly deal with attempting to write too much data to memory block, rather than allow segfault. - const size_t byteCount = memorySize/sizeof(byte); - int i = 0; - while (fread(fileData + i, sizeof(byte), 1, file)) { - if (i >= byteCount) { - fprintf(stderr, "Attempting to load binary %s to memory of smaller size %zu!\n", filePath, memorySize); - exit(EXIT_FAILURE); + if(pointLoc != NULL){ + if(strcmp(pointLoc, expectedExtension)==0){ + return(1); } - - i++; } - - if (ferror(file)) { - fprintf(stderr, "Encountered error attempting to read %s!\n", filePath); - exit(EXIT_FAILURE); - } - assert(fclose(file) != EOF); - - // If part of memory block was left uninitialized, initialize it to zero. - if (i < byteCount) { - memset(fileData + i, 0, (byteCount - i) * sizeof(byte)); - } - return fileData; + return(0); +} + +int writeBinaryFile(word instrs[], char outputFile[]){ + + if (!isValidFileFormat(filename, "bin")){ + return(-1); + } + + FILE *fp; + + fp = fopen(outputFile, "wb"); + + if(fp == NULL){ + return(-1); + } + + fwrite(instrs, 4, sizeof(instrs), fp); + fclose(fp); + + return(0); +} + +int readAssemblyFile(char inputFile[]) { + if (!isValidFileFormat(filename, "s")){ + return(1); + } + + FILE *fp; + char savedLine[MAX_ASM_LINE_LENGTH]; + + fp = fopen(inputFile, "r"); + + if(fp == NULL){ + return(-1); + } + + while (fgets(savedLine, MAX_ASM_LINE_LENGTH-1, fp) != NULL) { + //pass line to parser + } + + return(0); } From 647f47e39d4ecf6019bd992a37e8c286048ba9e4 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Tue, 11 Jun 2024 21:16:47 +0100 Subject: [PATCH 11/19] rewrite fileio to load file into memory --- src/fileio.c | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 96e5cd3..32cfdb2 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1,7 +1,7 @@ #include #include -#define MAX_ASM_LINE_LENGTH 100 +#define MAX_ASM_LINE_LENGTH 30 int isValidFileFormat(char filename[], char expectedExtension[]){ int *pointLoc = strrchr(filename, '.'); @@ -34,23 +34,47 @@ int writeBinaryFile(word instrs[], char outputFile[]){ return(0); } -int readAssemblyFile(char inputFile[]) { +char **readAssemblyFile(char inputFile[]) { if (!isValidFileFormat(filename, "s")){ - return(1); + return(NULL); } - FILE *fp; - char savedLine[MAX_ASM_LINE_LENGTH]; + FILE *fp = fopen(inputFile, "r"); - fp = fopen(inputFile, "r"); + if (fp == NULL){ + return(NULL); + } - if(fp == NULL){ - return(-1); + int lineCount = 0; + char ch; + while ((ch = fgetc(fp)) != EOF) + { + if (ch == '\n' || ch == '\0') + { + count++; + } } - while (fgets(savedLine, MAX_ASM_LINE_LENGTH-1, fp) != NULL) { - //pass line to parser + char **heap = malloc(sizeof(char *) * count); + + rewind(fp); + + for( int i=0; i Date: Tue, 11 Jun 2024 21:23:26 +0100 Subject: [PATCH 12/19] fix syntax errors in fileio.c --- src/assemble.c | 2 +- src/fileio.c | 20 ++++++++++---------- src/twopassassembly.c | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/assemble.c b/src/assemble.c index aa54b4e..4ed2733 100755 --- a/src/assemble.c +++ b/src/assemble.c @@ -1,8 +1,8 @@ #include #include #include "parser.c" +#include "fileio.c" int main(int argc, char **argv) { - return EXIT_SUCCESS; } diff --git a/src/fileio.c b/src/fileio.c index 32cfdb2..85fd8d1 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -4,7 +4,7 @@ #define MAX_ASM_LINE_LENGTH 30 int isValidFileFormat(char filename[], char expectedExtension[]){ - int *pointLoc = strrchr(filename, '.'); + char *pointLoc = strrchr(filename, '.'); if(pointLoc != NULL){ if(strcmp(pointLoc, expectedExtension)==0){ @@ -14,9 +14,9 @@ int isValidFileFormat(char filename[], char expectedExtension[]){ return(0); } -int writeBinaryFile(word instrs[], char outputFile[]){ +int writeBinaryFile(word instrs[], char outputFile[], int numInstrs){ - if (!isValidFileFormat(filename, "bin")){ + if (!isValidFileFormat(outputFile, "bin")){ return(-1); } @@ -28,14 +28,14 @@ int writeBinaryFile(word instrs[], char outputFile[]){ return(-1); } - fwrite(instrs, 4, sizeof(instrs), fp); + fwrite(instrs, 4, sizeof(word) * numInstrs, fp); fclose(fp); return(0); } char **readAssemblyFile(char inputFile[]) { - if (!isValidFileFormat(filename, "s")){ + if (!isValidFileFormat(inputFile, "s")){ return(NULL); } @@ -51,24 +51,24 @@ char **readAssemblyFile(char inputFile[]) { { if (ch == '\n' || ch == '\0') { - count++; + lineCount++; } } - char **heap = malloc(sizeof(char *) * count); + char **heap = malloc(sizeof(char *) * lineCount); rewind(fp); - for( int i=0; i Date: Tue, 11 Jun 2024 23:02:26 +0100 Subject: [PATCH 13/19] Added all instruction in subfolder a64instruction --- src/{ => a64instruction}/a64instruction.h | 0 src/{ => a64instruction}/a64instruction_Branch.h | 2 +- src/{ => a64instruction}/a64instruction_DP.h | 0 src/{ => a64instruction}/a64instruction_DPImmediate.h | 0 src/{ => a64instruction}/a64instruction_DPRegister.h | 0 src/{ => a64instruction}/a64instruction_Directive.h | 2 +- src/{ => a64instruction}/a64instruction_Label.h | 0 src/{ => a64instruction}/a64instruction_SingleTransfer.h | 2 +- src/{ => a64instruction}/a64instruction_global.h | 0 src/assemble.c | 4 ++-- src/decode.h | 2 +- src/emulate.c | 2 +- src/execute.h | 2 +- src/parser.c | 2 +- src/twopassassembly.c | 2 +- 15 files changed, 10 insertions(+), 10 deletions(-) rename src/{ => a64instruction}/a64instruction.h (100%) rename src/{ => a64instruction}/a64instruction_Branch.h (97%) rename src/{ => a64instruction}/a64instruction_DP.h (100%) rename src/{ => a64instruction}/a64instruction_DPImmediate.h (100%) rename src/{ => a64instruction}/a64instruction_DPRegister.h (100%) rename src/{ => a64instruction}/a64instruction_Directive.h (71%) rename src/{ => a64instruction}/a64instruction_Label.h (100%) rename src/{ => a64instruction}/a64instruction_SingleTransfer.h (98%) rename src/{ => a64instruction}/a64instruction_global.h (100%) diff --git a/src/a64instruction.h b/src/a64instruction/a64instruction.h similarity index 100% rename from src/a64instruction.h rename to src/a64instruction/a64instruction.h diff --git a/src/a64instruction_Branch.h b/src/a64instruction/a64instruction_Branch.h similarity index 97% rename from src/a64instruction_Branch.h rename to src/a64instruction/a64instruction_Branch.h index b732d6d..2e525bb 100644 --- a/src/a64instruction_Branch.h +++ b/src/a64instruction/a64instruction_Branch.h @@ -1,6 +1,6 @@ #include #include "a64instruction_global.h" -#include "global.h" +#include "../global.h" typedef enum { a64inst_UNCONDITIONAL = 0, diff --git a/src/a64instruction_DP.h b/src/a64instruction/a64instruction_DP.h similarity index 100% rename from src/a64instruction_DP.h rename to src/a64instruction/a64instruction_DP.h diff --git a/src/a64instruction_DPImmediate.h b/src/a64instruction/a64instruction_DPImmediate.h similarity index 100% rename from src/a64instruction_DPImmediate.h rename to src/a64instruction/a64instruction_DPImmediate.h diff --git a/src/a64instruction_DPRegister.h b/src/a64instruction/a64instruction_DPRegister.h similarity index 100% rename from src/a64instruction_DPRegister.h rename to src/a64instruction/a64instruction_DPRegister.h diff --git a/src/a64instruction_Directive.h b/src/a64instruction/a64instruction_Directive.h similarity index 71% rename from src/a64instruction_Directive.h rename to src/a64instruction/a64instruction_Directive.h index da36624..5506b80 100644 --- a/src/a64instruction_Directive.h +++ b/src/a64instruction/a64instruction_Directive.h @@ -1,4 +1,4 @@ -#include "global.h" +#include "../global.h" typedef struct { word value; diff --git a/src/a64instruction_Label.h b/src/a64instruction/a64instruction_Label.h similarity index 100% rename from src/a64instruction_Label.h rename to src/a64instruction/a64instruction_Label.h diff --git a/src/a64instruction_SingleTransfer.h b/src/a64instruction/a64instruction_SingleTransfer.h similarity index 98% rename from src/a64instruction_SingleTransfer.h rename to src/a64instruction/a64instruction_SingleTransfer.h index f661116..cbd7529 100644 --- a/src/a64instruction_SingleTransfer.h +++ b/src/a64instruction/a64instruction_SingleTransfer.h @@ -1,6 +1,6 @@ #include #include "a64instruction_global.h" -#include "global.h" +#include "../global.h" typedef enum { a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER = 1, diff --git a/src/a64instruction_global.h b/src/a64instruction/a64instruction_global.h similarity index 100% rename from src/a64instruction_global.h rename to src/a64instruction/a64instruction_global.h diff --git a/src/assemble.c b/src/assemble.c index 4ed2733..856a097 100755 --- a/src/assemble.c +++ b/src/assemble.c @@ -1,7 +1,7 @@ #include #include -#include "parser.c" -#include "fileio.c" +#include "parser.h" +#include "fileio.h" int main(int argc, char **argv) { return EXIT_SUCCESS; diff --git a/src/decode.h b/src/decode.h index 132130e..d509ae1 100644 --- a/src/decode.h +++ b/src/decode.h @@ -1,5 +1,5 @@ #include "global.h" -#include "a64instruction.h" +#include "a64instruction/a64instruction.h" #define HALT_WORD 0x8a000000 diff --git a/src/emulate.c b/src/emulate.c index be41f56..4c7f42e 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -1,6 +1,6 @@ #include #include -#include "a64instruction.h" +#include "a64instruction/a64instruction.h" #include "emulator.h" #include "fileio.h" #include "global.h" diff --git a/src/execute.h b/src/execute.h index fcf39ec..8b691e6 100644 --- a/src/execute.h +++ b/src/execute.h @@ -1,6 +1,6 @@ #ifndef __EXECUTE__ #define __EXECUTE__ -#include "a64instruction.h" +#include "a64instruction/a64instruction.h" #include "emulator.h" void execute(Machine *state, a64inst_instruction *inst); diff --git a/src/parser.c b/src/parser.c index fcef57b..807f591 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3,7 +3,7 @@ #include #include "parser.h" -#include "a64instruction.h" +#include "a64instruction/a64instruction.h" //takes input string, read from asm file and returns //input as an a64 instruction diff --git a/src/twopassassembly.c b/src/twopassassembly.c index be94e5c..7f13f95 100644 --- a/src/twopassassembly.c +++ b/src/twopassassembly.c @@ -1,5 +1,5 @@ #include "global.h" -#include "a64instruction.h" +#include "a64instruction/a64instruction.h" #include "symboltable.h" //generates assembled code based on two pass assembly method From 31c1ae90f7109947460c64023c889e5d6616f02d Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 11 Jun 2024 23:13:23 +0100 Subject: [PATCH 14/19] Attempt to make code compile, fix syntax errors --- src/parser.c | 1 + src/symboltable.c | 48 +++++++++++++++++++++++++++++++++++++++++++ src/twopassassembly.c | 20 +++++++++--------- 3 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 src/symboltable.c diff --git a/src/parser.c b/src/parser.c index 807f591..8cb6609 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "parser.h" diff --git a/src/symboltable.c b/src/symboltable.c new file mode 100644 index 0000000..a4c99e1 --- /dev/null +++ b/src/symboltable.c @@ -0,0 +1,48 @@ +#include + +typedef struct st st; +typedef struct node node; // forward declaration + +typedef struct node { + const void* key; + void* value; + node* prev; + node* next; +} node; + +struct st { + node* head; + node* tail; +}; + +// add new node to the end +void st_add(st table, void* key, void* value) { + node n = {key, value, table.tail}; + if (table.head == NULL) { + table.head = &n; + table.tail = &n; + } + else { + (*(table.tail)).next = &n; + table.tail = &n; + } +} + +void* nodeSearch(node* n, void* key) { + if (n != NULL) { + if ((*n).key == key) { + return (*n).value; + } + else { + return nodeSearch((*n).next, key); + } + } + else { + return NULL; + } +} + +// returns the pointer to key of the specified node, or null, if it does not exist +void* st_search(st table, void* key) { + return nodeSearch(table.head, key); +} diff --git a/src/twopassassembly.c b/src/twopassassembly.c index 7f13f95..b5dccae 100644 --- a/src/twopassassembly.c +++ b/src/twopassassembly.c @@ -1,6 +1,6 @@ #include "global.h" #include "a64instruction/a64instruction.h" -#include "symboltable.h" +#include "symboltable.c" //generates assembled code based on two pass assembly method @@ -12,7 +12,7 @@ word assembleBranch(a64inst_instruction *instr){ case a64inst_UNCONDITIONAL: //000101 //25-0: sign extended simm26 - binInstr += instr->data.processOpData.unconditionalOffset; + binInstr += instr->data.BranchData.processOpData.unconditionalData.unconditionalOffset; break; case a64inst_REGISTER: //10000 @@ -20,14 +20,14 @@ word assembleBranch(a64inst_instruction *instr){ //000000 //9-5: address from register //0000 - binInstr += ((instr->processOpData.src)^5); + binInstr += ((instr->data.BranchData.processOpData.registerData.src)^5); break; case a64inst_CONDITIONAL: // 01010100 // 25-5: sign extended offset // 4-0: 0{condition} - binInstr += ((instr->processOpData.offset)^5); - binInstr += instr->processOpData.cond; + binInstr += ((instr->data.BranchData.processOpData.conditionalData.offset)^5); + binInstr += instr->data.BranchData.processOpData.conditionalData.cond; break; default: break; @@ -49,7 +49,7 @@ st* firstPass(a64inst_instruction instrs[], int numInstrs){ } return &table; } -word assembleDPI(a64inst_instruction cI) { +word dpi(a64inst_instruction cI) { word out = 0; a64inst_DPImmediateData data = cI.data.DPImmediateData; //sf @@ -78,7 +78,7 @@ word assembleDPI(a64inst_instruction cI) { return out; } -word assembleDPR(a64inst_instruction cI) { +word dpr(a64inst_instruction cI) { word out = 0; a64inst_DPRegisterData data = cI.data.DPRegisterData; // sf @@ -131,7 +131,7 @@ word assembleDPR(a64inst_instruction cI) { return out; } -word assembleSTS(a64inst_instruction cI) { +word sts(a64inst_instruction cI) { a64inst_SingleTransferData data = cI.data.SingleTransferData; word out = 0; a64inst_SingleDataTransferData data2 = data.processOpData.singleDataTransferData; @@ -166,7 +166,7 @@ word assembleSTS(a64inst_instruction cI) { return out; } -word assembleLDL(a64inst_instruction cI) { +word ldl(a64inst_instruction cI) { word out = 3*(2^27); a64inst_SingleTransferData data = cI.data.SingleTransferData; int sf = data.regType; @@ -216,7 +216,7 @@ void secondPass(a64inst_instruction instrs[], int numInstrs, st* table, word arr lbl++; break; case a64inst_BRANCH: - arr[index] = assembleBranch(&cI, table, lbl); + arr[index] = assembleBranch(&cI); index++; default: break; From 999f36facd4dd95bacf730a7b9b7357381126669 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 11 Jun 2024 23:19:04 +0100 Subject: [PATCH 15/19] Fix bugs to make code compile. Code now compiles --- src/symboltable.h | 49 ----------------- src/twopassassembly.c | 121 +++++++++++++++++++++--------------------- 2 files changed, 60 insertions(+), 110 deletions(-) delete mode 100644 src/symboltable.h diff --git a/src/symboltable.h b/src/symboltable.h deleted file mode 100644 index cd2037c..0000000 --- a/src/symboltable.h +++ /dev/null @@ -1,49 +0,0 @@ -#include - -typedef struct st st; - - - -typedef struct { - const void* key; - void* value; - node* prev; - node* next; -} node; - -struct st { - node* head; - node* tail; -}; - -// add new node to the end -void st_add(st table, void* key, void* value) { - node n = {key, value, table.tail}; - if (table.head == NULL) { - table.head = &n; - table.tail = &n; - } - else { - (*(table.tail)).next = &n; - table.tail = &n; - } -} - -// returns the pointer to key of the specified node, or null, if it does not exist -void* st_search(st table, void* key) { - return nodeSearch(table.head, key); -} - -void* nodeSearch(node* n, void* key) { - if (n != NULL) { - if ((*n).key == key) { - return (*n).value; - } - else { - return nodeSearch((*n).next, key); - } - } - else { - return NULL; - } -} \ No newline at end of file diff --git a/src/twopassassembly.c b/src/twopassassembly.c index b5dccae..e6899d5 100644 --- a/src/twopassassembly.c +++ b/src/twopassassembly.c @@ -1,32 +1,33 @@ #include "global.h" #include "a64instruction/a64instruction.h" #include "symboltable.c" -//generates assembled code based on two pass assembly method +#include +#include +// Generates assembled code based on the two-pass assembly method -word assembleBranch(a64inst_instruction *instr){ +word assembleBranch(a64inst_instruction *instr) { word binInstr = 0; - binInstr += (5^28); //101 start of branch instr - switch (instr->data.BranchData.BranchType) - { + binInstr += (5 << 28); // 101 start of branch instr + switch (instr->data.BranchData.BranchType) { case a64inst_UNCONDITIONAL: - //000101 - //25-0: sign extended simm26 + // 000101 + // 25-0: sign extended simm26 binInstr += instr->data.BranchData.processOpData.unconditionalData.unconditionalOffset; break; case a64inst_REGISTER: - //10000 - //11111 - //000000 - //9-5: address from register - //0000 - binInstr += ((instr->data.BranchData.processOpData.registerData.src)^5); + // 10000 + // 11111 + // 000000 + // 9-5: address from register + // 0000 + binInstr += ((instr->data.BranchData.processOpData.registerData.src) << 5); break; case a64inst_CONDITIONAL: - // 01010100 + // 01010100 // 25-5: sign extended offset // 4-0: 0{condition} - binInstr += ((instr->data.BranchData.processOpData.conditionalData.offset)^5); + binInstr += ((instr->data.BranchData.processOpData.conditionalData.offset) << 5); binInstr += instr->data.BranchData.processOpData.conditionalData.cond; break; default: @@ -35,43 +36,43 @@ word assembleBranch(a64inst_instruction *instr){ return binInstr; } -st* firstPass(a64inst_instruction instrs[], int numInstrs){ - //TODO: +st* firstPass(a64inst_instruction instrs[], int numInstrs) { + // TODO: // -iterate over instructions, adding to symbol table // create symbol table and map labels to addresses/lines - struct st table; - for(int i=0; i Date: Tue, 11 Jun 2024 23:46:40 +0100 Subject: [PATCH 16/19] Add overall assemble structure --- src/assemble.c | 26 ++++++++++++++++++++++++++ src/fileio.c | 2 ++ src/fileio.h | 4 +++- src/parser.c | 22 ++++++++++++++++------ src/parser.h | 4 ++++ src/twopassassembly.c | 5 +++-- 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/assemble.c b/src/assemble.c index 856a097..967b02e 100755 --- a/src/assemble.c +++ b/src/assemble.c @@ -1,8 +1,34 @@ #include #include +#include "a64instruction/a64instruction.h" #include "parser.h" #include "fileio.h" +#include "parser.h" +#include "twopassassembly.c" int main(int argc, char **argv) { + // Check the arguments + if (argc < 3) { + fprintf(stderr, "Error: A source file and an object output file are required. Syntax: ./assemble "); + return EXIT_FAILURE; + } + + // Load the source file into memory + char **source = readAssemblyFile(argv[1]); + + // Parse the source file + a64inst_instruction *instructions = parse(source); + + // First Pass: Create the symbol table + st *table = firstPass(instructions, 1000); // 1000 is just a temp fix. + + // Second Pass: Assemble the instructions + word *binary = secondPass(instructions, 1000, table); // 1000 is just a temp fix. + + // Write the binary to the output file + writeBinaryFile(binary, argv[2], 1000); // 1000 is just a temp fix. + + /* TODO: FREE MEMORY!! */ + return EXIT_SUCCESS; } diff --git a/src/fileio.c b/src/fileio.c index 85fd8d1..8be2e38 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1,5 +1,7 @@ #include #include +#include "global.h" +#include "fileio.h" #define MAX_ASM_LINE_LENGTH 30 diff --git a/src/fileio.h b/src/fileio.h index a2d4262..88e9cca 100644 --- a/src/fileio.h +++ b/src/fileio.h @@ -5,5 +5,7 @@ #define EXIT_FAILURE 1 -extern byte *fileio_loadBin(const char *filePath, size_t memorySize); +char **readAssemblyFile(char inputFile[]); +int writeBinaryFile(word instrs[], char outputFile[], int numInstrs); + #endif diff --git a/src/parser.c b/src/parser.c index 8cb6609..a66b6f3 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3,7 +3,6 @@ #include #include #include "parser.h" - #include "a64instruction/a64instruction.h" //takes input string, read from asm file and returns @@ -188,16 +187,15 @@ void tokeniseOperands(char* str, int *operandCount, char *operands[], int *numOp //takes inputted assembly line and returns a //pointer to an abstract representation of the instruction -a64inst_instruction *parser(char asmLine[]){ +void parser_instruction(char asmLine[], a64inst_instruction *instr) { int numOperands = 0; - a64inst_instruction *instr = malloc(sizeof(a64inst_instruction)); if (instr == NULL){ exit(EXIT_FAILURE); } if(strcmp(asmLine, HALT_ASM_CMD) == 0){ instr->type = a64inst_HALT; - return(instr); + return; } //"opcode operand1, {operand2}, ..." @@ -252,7 +250,19 @@ a64inst_instruction *parser(char asmLine[]){ } - return(instr); - } +// Takes an array of strings, each string representing an assembly instruction. +// Returns an array of a64inst_instruction pointers, each representing an instruction. +// Note. The array of strings must be NULL-terminated???? +a64inst_instruction *parse(char **asmLines) { + a64inst_instruction *instructions = malloc(sizeof(a64inst_instruction) * 1000); + + int i = 0; + while (asmLines[i] != NULL) { + parser_instruction(asmLines[i], &instructions[i]); + i++; + } + + return instructions; +} diff --git a/src/parser.h b/src/parser.h index e303b58..1f7ab70 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,2 +1,6 @@ +#include "a64instruction/a64instruction.h" + #define OPERAND_DELIMITER ", " #define HALT_ASM_CMD "and x0, x0, x0" + +a64inst_instruction *parse(char **asmLines); diff --git a/src/twopassassembly.c b/src/twopassassembly.c index e6899d5..b4ecdec 100644 --- a/src/twopassassembly.c +++ b/src/twopassassembly.c @@ -178,11 +178,12 @@ word ldl(a64inst_instruction cI) { return out; } -void secondPass(a64inst_instruction instrs[], int numInstrs, st* table, word arr[]) { +word *secondPass(a64inst_instruction instrs[], int numInstrs, st* table) { // TODO: // iterate over instructions again, this time replacing labels // with values from symbol table // after a line has had all the values replaced, assemble it and append + word *arr = (word*)malloc(sizeof(word) * numInstrs); int index = 0; for (int i = 0; i < numInstrs; i++) { a64inst_instruction cI = instrs[i]; @@ -221,5 +222,5 @@ void secondPass(a64inst_instruction instrs[], int numInstrs, st* table, word arr break; } } - return; + return arr; } From 17d31a74e38bc73c860ee858363875b72461e364 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 11 Jun 2024 23:49:40 +0100 Subject: [PATCH 17/19] Add a working Makefile for testing purposes --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 7106e44..2fe219c 100755 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ CFLAGS ?= -std=c17 -g\ all: assemble emulate -assemble: assemble.o +assemble: assemble.o parser.o fileio.o emulate: emulate.o clean: From 269a150926f36b17c60bdb5111288f2c412cee72 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 12 Jun 2024 00:49:25 +0100 Subject: [PATCH 18/19] Fix types, signatures, and arguments. --- src/assemble.c | 11 +- src/execute.c | 448 ------------------------------------------------- src/parser.c | 15 +- src/parser.h | 2 +- 4 files changed, 15 insertions(+), 461 deletions(-) delete mode 100644 src/execute.c diff --git a/src/assemble.c b/src/assemble.c index 967b02e..ef1b06d 100755 --- a/src/assemble.c +++ b/src/assemble.c @@ -14,19 +14,20 @@ int main(int argc, char **argv) { } // Load the source file into memory - char **source = readAssemblyFile(argv[1]); + int lineCount = countLines(argv[1]); + char **source = readAssemblyFile(argv[1], lineCount); // Parse the source file - a64inst_instruction *instructions = parse(source); + a64inst_instruction *instructions = parse(source, lineCount); // First Pass: Create the symbol table - st *table = firstPass(instructions, 1000); // 1000 is just a temp fix. + st *table = firstPass(instructions, lineCount); // Second Pass: Assemble the instructions - word *binary = secondPass(instructions, 1000, table); // 1000 is just a temp fix. + word *binary = secondPass(instructions, lineCount, table); // 1000 is just a temp fix. // Write the binary to the output file - writeBinaryFile(binary, argv[2], 1000); // 1000 is just a temp fix. + writeBinaryFile(binary, argv[2], lineCount); // 1000 is just a temp fix. /* TODO: FREE MEMORY!! */ diff --git a/src/execute.c b/src/execute.c deleted file mode 100644 index fc436af..0000000 --- a/src/execute.c +++ /dev/null @@ -1,448 +0,0 @@ -#include -#include -#include "execute.h" -#include "print.h" - -// Defines the maximum value that can be held in a register -#define MAX_REG_VAL ((1 << DWORD_BITS) - 1) - -// The number of bits to shift the immediate value in an arithmetic immediate data processing -// instruction if the shift flag is enabled. -#define DPI_ARITHM_SHIFT 12 - -// The number of bits to shift the immediate value in a wide move immediate data processing -// instruction if the shift flag is enabled. -#define DPI_WIDEMOV_SHIFT 16 - -// Prototypes -void execute_SDT(Machine *state, a64inst_instruction *inst); -void execute_Branch(Machine *state, a64inst_instruction *inst); -void executeMultiply(Machine *state, a64inst_instruction *inst); - -// Return maximum of two dwords -static dword max(dword a, dword b) { - return a > b ? a : b; -} - -// 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_X) { - return value; - } else { - return (word)value; - //return value & (dword)(((dword)1 << WORD_BITS) - 1); - } -} - -// Sign extend a given value to a 64-bit signed integer given the number of bits -static int64_t signExtend(dword value, unsigned int n) { - if (n == 0 || n >= 64) { - // If n_bits is 0 or greater than or equal to 64, return the value as is - return (int64_t)value; - } - - uint64_t sign_bit_mask = (uint64_t)1 << (n - 1); - - // Mask to isolate the n-bit value - uint64_t n_bit_mask = (sign_bit_mask << 1) - 1; - - // Check if the sign bit is set - if (value & sign_bit_mask) { - // Sign bit is set, extend the sign - return (int64_t)(value | ~n_bit_mask); - } else { - // Sign bit is not set, return the value as is - return (int64_t)(value & n_bit_mask); - } -} - -// 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); - } -} - -// TODO: - -// Write to a 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 void writeRegister(Machine *state, a64inst_regSpecifier reg, a64inst_regType regType, dword value) { - assert(reg <= REGISTER_COUNT); - if (reg != ZERO_REGISTER) { - state->registers[reg] = truncateValue(value, regType); - } -} - -// Returns the position of the MSB of the given register type -inline static dword getMSBPos(a64inst_regType regType) { - return (regType ? DWORD_BITS : WORD_BITS) - 1; -} - -// Returns the MSB of the given value assuming it's of the size stored in the given register type -inline static uint8_t getMSB(dword value, a64inst_regType regType) { - return value >> getMSBPos(regType); -} - -// Updates N and Z condition codes given the machine and a result value -static void updateCondNZ(Machine *state, dword result, a64inst_regType regType) { - state->conditionCodes.Negative = getMSB(result, regType); - state->conditionCodes.Zero = result == 0; -} - -// Execute a data processing immediate instruction -static void executeDPImmediate(Machine *state, a64inst_instruction *inst) { - assert(inst->type == a64inst_DPIMMEDIATE); - - a64inst_regType regType = inst->data.DPImmediateData.regType; - a64inst_regSpecifier dest = inst->data.DPImmediateData.dest; - switch(inst->data.DPImmediateData.DPIOpType) { - - // Execute an arithmetic immediate 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 arithmImm = inst->data.DPImmediateData.processOpData.arithmData.immediate; - dword srcVal = state->registers[inst->data.DPImmediateData.processOpData.arithmData.src]; - if (inst->data.DPImmediateData.processOpData.arithmData.shiftImmediate) { - arithmImm = truncateValue(arithmImm << DPI_ARITHM_SHIFT, regType); - } - - switch(inst->data.DPImmediateData.processOp) { - - dword result; - case(a64inst_ADDS): - result = srcVal + arithmImm; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = max(srcVal, arithmImm) > result; - state->conditionCodes.Carry = state->conditionCodes.Overflow; - break; - - case(a64inst_ADD): - writeRegister(state, dest, regType, srcVal + arithmImm); - break; - - case(a64inst_SUBS): - result = srcVal - arithmImm; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = srcVal < result; - state->conditionCodes.Carry = state->conditionCodes.Overflow; - break; - - case(a64inst_SUB): - writeRegister(state, dest, regType, srcVal - arithmImm); - break; - - // Unknown opcode detected! - default: - fprintf(stderr, "Unknown opcode detected in a DPI arithmetic instruction!\n"); - break; - } - break; - - // Execute a wide move immediate data processing instruction - case a64inst_DPI_WIDEMOV:; - uint8_t shiftScalar = inst->data.DPImmediateData.processOpData.wideMovData.shiftScalar; - dword wideMovImm = inst->data.DPImmediateData.processOpData.wideMovData.immediate; - - // NOTE: Not checking that shiftScalar has valid value for 32bit registers. Possibly add explicit error. - //printf("%x\n", wideMovImm << (shiftScalar * DPI_WIDEMOV_SHIFT) & ); - wideMovImm = truncateValue(wideMovImm << (shiftScalar * DPI_WIDEMOV_SHIFT), regType); - switch(inst->data.DPImmediateData.processOp) { - - case(a64inst_MOVN): - writeRegister(state, dest, regType, ~wideMovImm); - break; - - case(a64inst_MOVZ): - writeRegister(state, dest, regType, wideMovImm); - break; - - case(a64inst_MOVK):; - dword result = readRegister(state, dest, regType); - result = (result & ~(((1lu << DPI_WIDEMOV_SHIFT) - 1) << shiftScalar * DPI_WIDEMOV_SHIFT)) | wideMovImm; - writeRegister(state, dest, regType, result); - break; - - default: - fprintf(stderr, "Unknown opcode detected in a DPI wide move instruction!\n"); - break; - } - break; - - // Unknown instruction detected! - default: - fprintf(stderr, "Attempting to execute instruction with unknown DPI operand type!\n"); - break; - } -} - -// Execute a data processing register instruction -static void executeDPRegister(Machine *state, a64inst_instruction *inst) { - assert(inst->type == a64inst_DPREGISTER); - - a64inst_regType regType = inst->data.DPRegisterData.regType; - a64inst_regSpecifier dest = inst->data.DPRegisterData.dest; - dword src1Val = readRegister(state, inst->data.DPRegisterData.src1, regType); - dword src2Val = readRegister(state, inst->data.DPRegisterData.src2, regType); - - switch(inst->data.DPRegisterData.DPROpType) { - - // Execute an arithmetic or logic register data processing instruction - case a64inst_DPR_ARITHMLOGIC:; - - // Apply shift to value held in second register - a64inst_DPRegister_ArithmLogicData *arithmLogicData = &inst->data.DPRegisterData.processOpData.arithmLogicData; - uint8_t shiftAmount = arithmLogicData->shiftAmount; - switch(arithmLogicData->shiftType) { - - case a64inst_LSL: - src2Val = truncateValue(src2Val << shiftAmount, regType); - break; - - case a64inst_LSR: - src2Val = truncateValue(src2Val >> shiftAmount, regType); - break; - - case a64inst_ASR: - if (regType == a64inst_X) { - src2Val = truncateValue((int64_t)src2Val >> shiftAmount, regType); - } else { - src2Val = truncateValue((int32_t)src2Val >> shiftAmount, regType); - } - break; - - case a64inst_ROR: - if (arithmLogicData->type != a64inst_DPR_LOGIC) { - fprintf(stderr, "Attempting to perform ROR shift on non-logic register data processing instruction!\n"); - } - src2Val = truncateValue(src2Val >> shiftAmount | src2Val << (getMSBPos(regType) - shiftAmount), regType); - break; - - default: - fprintf(stderr, "Attempting to execute arithmetic/logic register data processing instruction with invalid shift type!\n"); - break; - } - - // Negate second operand if negShiftedSrc2 flag is enabled - if (arithmLogicData->negShiftedSrc2) { - src2Val = truncateValue(~src2Val, regType); - } - - dword result; - switch(arithmLogicData->type) { - - case a64inst_DPR_ARITHM: - switch(inst->data.DPRegisterData.processOp) { - - case(a64inst_ADDS): - result = src1Val + src2Val; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = max(src1Val, src2Val) > result; - state->conditionCodes.Carry = state->conditionCodes.Overflow; - break; - - case(a64inst_ADD): - writeRegister(state, dest, regType, src1Val + src2Val); - break; - - case(a64inst_SUBS): - result = src1Val - src2Val; - writeRegister(state, dest, regType, result); - - updateCondNZ(state, result, regType); - state->conditionCodes.Overflow = getMSB(src1Val, regType) != getMSB(src2Val, regType) && getMSB(src1Val, regType) != getMSB(result, regType); - state->conditionCodes.Carry = src1Val >= src2Val; - break; - - case(a64inst_SUB): - writeRegister(state, dest, regType, src1Val - src2Val); - break; - - // Unknown opcode detected! - default: - fprintf(stderr, "Unknown opcode detected in a DPI arithmetic instruction!\n"); - break; - } - break; - - case a64inst_DPR_LOGIC: - switch(inst->data.DPRegisterData.processOp) { - - case a64inst_AND: - writeRegister(state, dest, regType, src1Val & src2Val); - break; - - case a64inst_OR: - writeRegister(state, dest, regType, src1Val | src2Val); - break; - - case a64inst_XOR: - writeRegister(state, dest, regType, src1Val ^ src2Val); - break; - - case a64inst_AND_FLAGGED:; - result = src1Val & src2Val; - writeRegister(state, dest, regType, result); - state->conditionCodes.Overflow = 0; - state->conditionCodes.Carry = 0; - updateCondNZ(state, result, regType); - break; - } - break; - - default: - fprintf(stderr, "Attempting to execute an instruction with an unknown DPR arithmetic or logic subtype!\n"); - break; - } - break; - - // Execute a multiply register data processing instruction - case a64inst_DPR_MULTIPLY: - break; - - // Unknown instruction detected! - default: - fprintf(stderr, "Attempting to execute instruction with unknown DPR operand type!\n"); - break; - } -} - -void execute(Machine *state, a64inst_instruction *inst) { - - switch (inst->type) { - - // Halt the program - case a64inst_HALT: - break; - - // Execute a data processing immediate instruction - case a64inst_DPIMMEDIATE: - executeDPImmediate(state, inst); - break; - - // Execute a branch instruction - case a64inst_BRANCH: - execute_Branch(state, inst); - break; - - // Execute a data processing register instruction - case a64inst_DPREGISTER: - if (inst->data.DPRegisterData.DPROpType == a64inst_DPR_MULTIPLY) - executeMultiply(state, inst); - else - executeDPRegister(state, inst); - break; - - case a64inst_SINGLETRANSFER: - execute_SDT(state, inst); - break; - - // Unknown instruction - default: - break; - } - -} - -void execute_SDT(Machine *state, a64inst_instruction *inst) { - word address; - bool isLoad; - if (inst->data.SingleTransferData.SingleTransferOpType == a64inst_SINGLE_TRANSFER_LOAD_LITERAL) { - // Load Literal - isLoad = true; - address = state->pc + inst->data.SingleTransferData.processOpData.loadLiteralData.offset * 4; - } else { - address = state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.base]; - isLoad = inst->data.SingleTransferData.processOpData.singleDataTransferData.transferType == a64inst_LOAD; - switch (inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode) { - case a64inst_UNSIGNED_OFFSET: - address += inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.unsignedOffset * (inst->data.SingleTransferData.regType == a64inst_W ? 4 : 8); - break; - case a64inst_REGISTER_OFFSET: - address += state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.offsetReg]; - break; - case a64inst_PRE_INDEXED: - address += inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset; - state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.base] = address; - break; - case a64inst_POST_INDEXED: - state->registers[inst->data.SingleTransferData.processOpData.singleDataTransferData.base] = address + inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset; - break; - } - } - - if (isLoad) { - if (inst->data.SingleTransferData.regType == a64inst_W) { - // 32 bit access - state->registers[inst->data.SingleTransferData.target] = readWord(state->memory, address); - } else { - state->registers[inst->data.SingleTransferData.target] = readDoubleWord(state->memory, address); - } - } else { - *(word *)(state->memory + address) = state->registers[inst->data.SingleTransferData.target]; - - // Update base register if post indexed - if (inst->data.SingleTransferData.processOpData.singleDataTransferData.addressingMode == a64inst_POST_INDEXED) { - writeRegister(state, inst->data.SingleTransferData.processOpData.singleDataTransferData.base, inst->data.SingleTransferData.regType == a64inst_W, address + inst->data.SingleTransferData.processOpData.singleDataTransferData.a64inst_addressingModeData.indexedOffset); - } - } - -} - -static bool isConditionMet(Machine* state, a64inst_ConditionType cond) { - switch(cond) { - case EQ: - return state->conditionCodes.Zero; - case NE: - return !state->conditionCodes.Zero; - case GE: - return state->conditionCodes.Negative == state->conditionCodes.Overflow; - case LT: - return state->conditionCodes.Negative != state->conditionCodes.Overflow; - case GT: - return !state->conditionCodes.Zero && (state->conditionCodes.Negative == state->conditionCodes.Overflow); - case LE: - return state->conditionCodes.Zero || (state->conditionCodes.Negative != state->conditionCodes.Overflow); - case AL: - return true; - default: - fprintf(stderr, "Unknown condition specified!\n"); - exit(1); - } -} - -void execute_Branch(Machine *state, a64inst_instruction *inst) { - switch (inst->data.BranchData.BranchType) { - case a64inst_UNCONDITIONAL: - state->pc += signExtend(inst->data.BranchData.processOpData.unconditionalData.unconditionalOffset * 4, 26); - break; - - case a64inst_REGISTER: - state->pc = state->registers[inst->data.BranchData.processOpData.registerData.src]; - break; - - case a64inst_CONDITIONAL: - if (isConditionMet(state, inst->data.BranchData.processOpData.conditionalData.cond)) { - state->pc += signExtend(inst->data.BranchData.processOpData.conditionalData.offset * 4, 19); - } - break; - } -} - -void executeMultiply(Machine *state, a64inst_instruction *inst) { - dword product = state->registers[inst->data.DPRegisterData.src1] * state->registers[inst->data.DPRegisterData.src2]; - dword sum = readRegister(state, inst->data.DPRegisterData.processOpData.multiplydata.summand, inst->data.DPRegisterData.regType) + (inst->data.DPRegisterData.processOpData.multiplydata.negProd ? -product : product); - writeRegister(state, inst->data.DPRegisterData.dest, inst->data.DPRegisterData.regType, sum); -} diff --git a/src/parser.c b/src/parser.c index a66b6f3..31b5ffc 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -172,8 +173,9 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ } void tokeniseOperands(char* str, int *operandCount, char *operands[], int *numOperands){ - char *operandsDupe = NULL; - operandsDupe = strcpy(operandsDupe, str); + assert(str != NULL); + char operandsDupe[strlen(str)+1]; + strcpy(operandsDupe, str); char *operand = strtok(operandsDupe, OPERAND_DELIMITER); operands[0] = operand; @@ -200,8 +202,8 @@ void parser_instruction(char asmLine[], a64inst_instruction *instr) { //"opcode operand1, {operand2}, ..." //duplicated as strtok modifies the input string - char *stringptr = NULL; - stringptr = strcpy(stringptr, asmLine); + char stringptr[strlen(asmLine) + 1]; + strcpy(stringptr, asmLine); char *opcode = strtok(stringptr, " "); char *operands = strtok(NULL, ""); @@ -254,9 +256,8 @@ void parser_instruction(char asmLine[], a64inst_instruction *instr) { // Takes an array of strings, each string representing an assembly instruction. // Returns an array of a64inst_instruction pointers, each representing an instruction. -// Note. The array of strings must be NULL-terminated???? -a64inst_instruction *parse(char **asmLines) { - a64inst_instruction *instructions = malloc(sizeof(a64inst_instruction) * 1000); +a64inst_instruction *parse(char **asmLines, int lineCount) { + a64inst_instruction *instructions = malloc(sizeof(a64inst_instruction) * lineCount); int i = 0; while (asmLines[i] != NULL) { diff --git a/src/parser.h b/src/parser.h index 1f7ab70..2d7f382 100644 --- a/src/parser.h +++ b/src/parser.h @@ -3,4 +3,4 @@ #define OPERAND_DELIMITER ", " #define HALT_ASM_CMD "and x0, x0, x0" -a64inst_instruction *parse(char **asmLines); +a64inst_instruction *parse(char **asmLines, int lineCount); From 53ab6a2bf6e6313dda08822b24aaad40272a57be Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 12 Jun 2024 00:50:00 +0100 Subject: [PATCH 19/19] Update fileio, add countLine, rewrite read and write file funcs --- src/fileio.c | 110 +++++++++++++++++++++++++++------------------------ src/fileio.h | 6 ++- 2 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 8be2e38..f2f47fd 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1,9 +1,8 @@ -#include #include #include "global.h" #include "fileio.h" -#define MAX_ASM_LINE_LENGTH 30 +#define MAX_ASM_LINE_LENGTH 300 int isValidFileFormat(char filename[], char expectedExtension[]){ char *pointLoc = strrchr(filename, '.'); @@ -16,67 +15,76 @@ int isValidFileFormat(char filename[], char expectedExtension[]){ return(0); } -int writeBinaryFile(word instrs[], char outputFile[], int numInstrs){ - - if (!isValidFileFormat(outputFile, "bin")){ - return(-1); +void writeBinaryFile(word instrs[], char outputFile[], int numInstrs) { + FILE *fp = fopen(outputFile, "wb"); + if (fp == NULL) { + fprintf(stderr, "Error: Could not open file %s\n", outputFile); + exit(EXIT_FAILURE); } - - FILE *fp; - fp = fopen(outputFile, "wb"); - - if(fp == NULL){ - return(-1); - } - - fwrite(instrs, 4, sizeof(word) * numInstrs, fp); + fwrite(instrs, sizeof(word), numInstrs, fp); fclose(fp); - - return(0); } -char **readAssemblyFile(char inputFile[]) { - if (!isValidFileFormat(inputFile, "s")){ - return(NULL); +int countLines(char *filename) { + FILE *file = fopen(filename, "r"); + if (file == NULL) { + fprintf(stderr, "Error: Could not read file %s\n", filename); + exit(EXIT_FAILURE); } - FILE *fp = fopen(inputFile, "r"); + int count = 0; + char c; - if (fp == NULL){ - return(NULL); - } - - int lineCount = 0; - char ch; - while ((ch = fgetc(fp)) != EOF) - { - if (ch == '\n' || ch == '\0') - { - lineCount++; + while ((c = fgetc(file)) != EOF) { + if (c == '\n') { + count++; } } - - char **heap = malloc(sizeof(char *) * lineCount); - rewind(fp); - - for( int i=0; i #include #include "global.h" #define EXIT_FAILURE 1 -char **readAssemblyFile(char inputFile[]); -int writeBinaryFile(word instrs[], char outputFile[], int numInstrs); +char **readAssemblyFile(char filename[], int lineCount); +void writeBinaryFile(word instrs[], char outputFile[], int numInstrs); +int countLines(char *filename); #endif