diff --git a/src/main.c b/src/main.c index e7cb514..99e6f5c 100644 --- a/src/main.c +++ b/src/main.c @@ -3,7 +3,7 @@ #include #include "util/registers.h" -#include "util/functions.h" +#include "util/functions.c" int help() { printf( diff --git a/src/test/testFormats.c b/src/test/testFormats.c index ba272d5..09fec03 100644 --- a/src/test/testFormats.c +++ b/src/test/testFormats.c @@ -3,7 +3,7 @@ #include #include -#include "../util/formats.h" +#include "../util/formats.c" int compareIntArray(int * x, int * y, int size) { for(int i = 0; i < size; i++) diff --git a/src/test/testParse.c b/src/test/testParse.c index f58f127..90054f8 100644 --- a/src/test/testParse.c +++ b/src/test/testParse.c @@ -2,7 +2,7 @@ #include #include -#include "../util/parse.h" +#include "../util/parse.c" char * filepath; diff --git a/src/util/formats.c b/src/util/formats.c new file mode 100644 index 0000000..3459ded --- /dev/null +++ b/src/util/formats.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include + +#include "formats.h" + +char subBinaryToHex(int * bin) { + int sum = 0; + for(int i = 0; i < 4; i++) { + switch (i) { + case 0: + if(bin[i] == 1) sum += 8; + break; + case 1: + if(bin[i] == 1) sum += 4; + break; + case 2: + if(bin[i] == 1) sum += 2; + break; + case 3: + if(bin[i] == 1) sum += 1; + break; + }; + } + + if(sum < 10) return sum + '0'; + else { + switch (sum) { + case 10: + return 'A'; + case 11: + return 'B'; + case 12: + return 'C'; + case 13: + return 'D'; + case 14: + return 'E'; + case 15: + return 'F'; + default: + return 'G'; + }; + } +} + +// Utility function to convert any given binary instruction into hexadecimal. +// Expected input is an int array containing 32 bits. +char * binaryToHex(int * bin) { + char * hex = (char *)calloc(8, sizeof(char)); + + int j = 0; + for(int i = 0; i < 8; i++) { + int * tmp[4]; + int c = j + 4; + for(; j < c; j++) tmp[j % 4] = &bin[j]; + + hex[i] = subBinaryToHex(* tmp); + } + + return hex; +} + +// Utility function to convert a number to binary +int * toBinary(int num, int size) { + // Dynamically allows for different sized arrays. Need to manually release from memory. + int * bin = (int*)calloc(size, sizeof(int)); + + // Fill up the array with default values. + for(int i = 0; i < size; i++) + bin[i] = 0; + + if(num == 0) return bin; + + // Since the binary values are calculated in reverse order, entering the values into the array + // in reverse order will negate this, and leave us with an array in the correct order. + int i = size - 1; + while(num > 0) { + bin[i] = num % 2; + num = num / 2; + i--; + } + + return bin; +} + +// Utility function to copy an existing array into a destination array, starting at a specified index of the existing array. +// This allows for multiple existing arrays to be added in sequence to a destination array. +void fillArray(int * destArray, int * arrayToAdd, int startIndex, int destArraySize) { + int j = 0; + for(int i = startIndex; i < destArraySize; i++) { + destArray[i] = arrayToAdd[j]; + j++; + } +} + +int * rToBinary(r* format) { + int size = 32; // R-Format instructions when decoded into their bit strings are 32 bits. + + // Dynamically allows for different sized arrays. Need to manually release from memory. + int * bin = (int*)calloc(size, sizeof(int)); + + // Fill up the array with default values. + for(int i = 0; i < size; i++) + bin[i] = 0; + + // Create the binary form of the field, fill the instruction array with those values, and once complete, free from memory the original array. + + int * opcode = toBinary(format->opcode, 6); + fillArray(bin, opcode, 0, size); + free(opcode); + + int * rs = toBinary(format->rs, 5); + fillArray(bin, rs, 6, size); + free(rs); + + int * rt = toBinary(format->rt, 5); + fillArray(bin, rt, 11, size); + free(rt); + + int * rd = toBinary(format->rd, 5); + fillArray(bin, rd, 16, size); + free(rd); + + int * shamt = toBinary(format->shamt, 5); + fillArray(bin, shamt, 21, size); + free(shamt); + + int * funct = toBinary(format->funct, 6); + fillArray(bin, funct, 26, size); + free(funct); + + return bin; +} + +int * iToBinary(i* format) { + int size = 32; // R-Format instructions when decoded into their bit strings are 32 bits. + + // Dynamically allows for different sized arrays. Need to manually release from memory. + int * bin = (int*)calloc(size, sizeof(int)); + + // Fill up the array with default values. + for(int i = 0; i < size; i++) + bin[i] = 0; + + // Create the binary form of the field, fill the instruction array with those values, and once complete, free from memory the original array. + + int * opcode = toBinary(format->opcode, 6); + fillArray(bin, opcode, 0, size); + free(opcode); + + int * rs = toBinary(format->rs, 5); + fillArray(bin, rs, 6, size); + free(rs); + + int * rt = toBinary(format->rt, 5); + fillArray(bin, rt, 11, size); + free(rt); + + int * immediate = toBinary(format->immediate, 16); + fillArray(bin, immediate, 16, size); + free(immediate); + + return bin; +} + +char * rToHex(r* format) { + return binaryToHex(rToBinary(format)); +} + +// Utility function to convert any given I instruction into hexadecimal. +char* iToHex(i* format) { + return binaryToHex(iToBinary(format)); +} diff --git a/src/util/formats.h b/src/util/formats.h index 33d04d7..582e78e 100644 --- a/src/util/formats.h +++ b/src/util/formats.h @@ -1,8 +1,3 @@ -#include -#include -#include -#include - // Represents the R instruction format. typedef struct r { int opcode; // 6 bits @@ -33,141 +28,3 @@ typedef struct j { int address; // 26 bits } j; -char subBinaryToHex(int * bin) { - int sum = 0; - for(int i = 0; i < 4; i++) { - switch (i) { - case 0: - if(bin[i] == 1) sum += 8; - break; - case 1: - if(bin[i] == 1) sum += 4; - break; - case 2: - if(bin[i] == 1) sum += 2; - break; - case 3: - if(bin[i] == 1) sum += 1; - break; - }; - } - - if(sum < 10) return sum + '0'; - else { - switch (sum) { - case 10: - return 'A'; - case 11: - return 'B'; - case 12: - return 'C'; - case 13: - return 'D'; - case 14: - return 'E'; - case 15: - return 'F'; - default: - return 'G'; - }; - } -} - -// Utility function to convert any given binary instruction into hexadecimal. -// Expected input is an int array containing 32 bits. -char* binaryToHex(int * bin) { - char * hex = (char *)calloc(8, sizeof(char)); - - int j = 0; - for(int i = 0; i < 8; i++) { - int * tmp[4]; - int c = j + 4; - for(; j < c; j++) tmp[j % 4] = &bin[j]; - - hex[i] = subBinaryToHex(* tmp); - } - - return hex; -} - -// Utility function to convert a number to binary -int* toBinary(int num, int size) { - // Dynamically allows for different sized arrays. Need to manually release from memory. - int * bin = (int*)calloc(size, sizeof(int)); - - // Fill up the array with default values. - for(int i = 0; i < size; i++) - bin[i] = 0; - - if(num == 0) return bin; - - // Since the binary values are calculated in reverse order, entering the values into the array - // in reverse order will negate this, and leave us with an array in the correct order. - int i = size - 1; - while(num > 0) { - bin[i] = num % 2; - num = num / 2; - i--; - } - - return bin; -} - -// Utility function to copy an existing array into a destination array, starting at a specified index of the existing array. -// This allows for multiple existing arrays to be added in sequence to a destination array. -void fillArray(int * destArray, int * arrayToAdd, int startIndex, int destArraySize) { - int j = 0; - for(int i = startIndex; i < destArraySize; i++) { - destArray[i] = arrayToAdd[j]; - j++; - } -} - -int * rToBinary(r* format) { - int size = 32; // R-Format instructions when decoded into their bit strings are 32 bits. - - // Dynamically allows for different sized arrays. Need to manually release from memory. - int * bin = (int*)calloc(size, sizeof(int)); - - // Fill up the array with default values. - for(int i = 0; i < size; i++) - bin[i] = 0; - - // Create the binary form of the field, fill the instruction array with those values, and once complete, free from memory the original array. - - int * opcode = toBinary(format->opcode, 6); - fillArray(bin, opcode, 0, size); - free(opcode); - - int * rs = toBinary(format->rs, 5); - fillArray(bin, rs, 6, size); - free(rs); - - int * rt = toBinary(format->rt, 5); - fillArray(bin, rt, 11, size); - free(rt); - - int * rd = toBinary(format->rd, 5); - fillArray(bin, rd, 16, size); - free(rd); - - int * shamt = toBinary(format->shamt, 5); - fillArray(bin, shamt, 21, size); - free(shamt); - - int * funct = toBinary(format->funct, 6); - fillArray(bin, funct, 26, size); - free(funct); - - return bin; -} - -char * rToHex(r* format) { - int * bin = rToBinary(format); - return binaryToHex(bin); -} - -// Utility function to convert any given I instruction into hexadecimal. -char* iToHex(i* format) { - return ""; -} diff --git a/src/util/functionAssigner.h b/src/util/functionAssigner.h index aef2ac2..4f6bcbf 100644 --- a/src/util/functionAssigner.h +++ b/src/util/functionAssigner.h @@ -1,6 +1,20 @@ #define FOREACH_FUNCTION(FUNCTION) \ - FUNCTION(add) \ - FUNCTION(li) \ + FUNCTION(add) \ + FUNCTION(jr) \ + FUNCTION(syscall) \ + FUNCTION(li) \ + FUNCTION(addu) \ + FUNCTION(and) \ + FUNCTION(nor) \ + FUNCTION(or) \ + FUNCTION(slt) \ + FUNCTION(sltu) \ + FUNCTION(sll) \ + FUNCTION(srl) \ + FUNCTION(sub) \ + FUNCTION(subu) \ + FUNCTION(addi) \ + FUNCTION(jal) \ #define GENERATE_ENUM(ENUM) ENUM, #define GENERATE_STRING(STRING) #STRING, diff --git a/src/util/functions.c b/src/util/functions.c new file mode 100644 index 0000000..8e3a16c --- /dev/null +++ b/src/util/functions.c @@ -0,0 +1,197 @@ +#include +#include +#include "formats.c" + +r* rFormat; +i* iFormat; + +void initFunctions() { + rFormat = (r*)malloc(sizeof(r)); + iFormat = (i*)malloc(sizeof(i)); + + rFormat->opcode = 0; + iFormat->opcode = 0; +} + +// -------------------------- R FORMAT INSTRUCTIONS -------------------------- // +char * add(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 32; + + // Unused in add instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +char * addu(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 33; + + // Unused in addu instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +char * and(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 36; + + // Unused in and instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +char * jr(int * args[]) { + rFormat->rs = *args[0]; + rFormat->funct = 8; + + // Unused in jr instruction. + rFormat->shamt = 0; + rFormat->rd = 0; + rFormat->rt = 0; + + return rToHex(rFormat); +} + +char * nor(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 39; + + // Unused in nor instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +char * or(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 37; + + // Unused in or instruction. + rFormat->shamt = 0; + return rToHex(rFormat); +} + +char * slt(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 42; + + // Unused in slt instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +char * sltu(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 43; + + // Unused in sltu instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +char * sll(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rt = *args[1]; + rFormat->shamt = *args[2]; + rFormat->funct = 0; + + // Unused in sll instruction. + rFormat->rs = 0; + + return rToHex(rFormat); +} + +char * srl(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rt = *args[1]; + rFormat->shamt = *args[2]; + rFormat->funct = 2; + + // Unused in sll instruction. + rFormat->rs = 0; + + return rToHex(rFormat); +} + +char * sub(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 34; + + // Unused in sll instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +char * subu(int * args[]) { + rFormat->rd = *args[0]; + rFormat->rs = *args[1]; + rFormat->rt = *args[2]; + rFormat->funct = 35; + + // Unused in sll instruction. + rFormat->shamt = 0; + + return rToHex(rFormat); +} + +// -------------------------- I FORMAT INSTRUCTIONS -------------------------- // +char * addi(int * args[]) { + iFormat->opcode = 8; + iFormat->rt = *args[0]; + iFormat->rs = *args[1]; + iFormat->immediate = *args[2]; + + return iToHex(iFormat); +} + +char * addiu(int * args[]) { + iFormat->opcode = 9; + iFormat->rt = *args[0]; + iFormat->rs = *args[1]; + iFormat->immediate = *args[2]; + + return iToHex(iFormat); +} + +char * andi(int * args[]) { + iFormat->opcode = 12; + iFormat->rt = *args[0]; + iFormat->rs = *args[1]; + iFormat->immediate = *args[2]; + + return iToHex(iFormat); +} + +char * beq(int * args[]) { + iFormat->opcode = 4; + iFormat->rt = *args[0]; + iFormat->rs = *args[1]; + iFormat->immediate = *args[2]; + + return iToHex(iFormat); +} + +// -------------------------- J FORMAT INSTRUCTIONS -------------------------- // diff --git a/src/util/functions.h b/src/util/functions.h deleted file mode 100644 index 22bce48..0000000 --- a/src/util/functions.h +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include "formats.h" - -r* rFormat; -i* iFormat; - -void initFunctions() { - rFormat = (r*)malloc(sizeof(r)); - iFormat = (i*)malloc(sizeof(i)); -} - -char * add(int * args[]) { - rFormat->opcode = 0; - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; - rFormat->shamt = *args[3]; - rFormat->funct = 20; - - return rToHex(rFormat); -} - -char * sub(int * args[]) { - rFormat->opcode = 0; - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; - rFormat->shamt = *args[3]; - rFormat->funct = 22; - - return rToHex(rFormat); -} diff --git a/src/util/instruction.h b/src/util/instruction.h new file mode 100644 index 0000000..fd9b650 --- /dev/null +++ b/src/util/instruction.h @@ -0,0 +1,11 @@ +typedef struct args { + int arg; + struct args *nextArg; // Allows dynamically sized lists of arguments. For eg. syscall will just be 1 element, but add has 4 elements. +} args; + +typedef struct instruction { + int formatType; // 0 = R, 1 = I, 2 = J + struct instruction* nextInstruction; + struct args* a; // A linked list of each argument of the instruction. + +} instruction; diff --git a/src/util/list.c b/src/util/list.c new file mode 100644 index 0000000..4cf01b8 --- /dev/null +++ b/src/util/list.c @@ -0,0 +1,52 @@ +#include +#include + +#include "instruction.h" + +int traverse(struct instruction* current) { + while(current->nextInstruction != NULL) { + + struct args* currentArgs = current->a; + + while(currentArgs != NULL) { + printf("%d ", currentArgs->arg); + + currentArgs = currentArgs->nextArg; + } + + printf("\n"); + current = current->nextInstruction; + } + + return 1; // TODO +} + +// Test driver for nested linked list functionality. +int main() { + struct instruction* head = (instruction*) malloc(sizeof(instruction)); + struct instruction* current = head; + + for(int i = 0; i < 20; i++) { + + // Get a pseudo random formatType between 0 and 2 inclusive + current->formatType = i % 3; + + // Create the head and current pointers for the inner linked list. + struct args* argsHead = (args*) malloc(sizeof(args)); + current->a = argsHead; + struct args* argsCurrent = argsHead; + + for(int j = 0; j < (i % 4 + 1); j++) { + argsCurrent->arg = j; + + argsCurrent->nextArg = (args*) malloc(sizeof(args)); + argsCurrent = argsCurrent->nextArg; + } + + // Move to the next instruction. + current->nextInstruction = (instruction*) malloc(sizeof(instruction)); + current = current->nextInstruction; + } + + traverse(head); +} diff --git a/src/util/parse.h b/src/util/parse.c similarity index 78% rename from src/util/parse.h rename to src/util/parse.c index 3d42270..eac0a58 100644 --- a/src/util/parse.h +++ b/src/util/parse.c @@ -4,7 +4,7 @@ #include #include -#include "formats.h" +#include "formats.c" #include "registers.h" #include "functionAssigner.h" @@ -12,8 +12,8 @@ FILE * file; // Determines if the parser should keep a space, based upon if the space is surrounded by two non-space characters. int determineKeepSpace(char prior, char after) { - if(prior != NULL && !isspace(prior)) - if(after != NULL && !isspace(after)) + if(&prior != (char *) NULL && !isspace(prior)) + if(&after != (char *) NULL && !isspace(after)) return 1; return 0; @@ -57,37 +57,38 @@ char * removeCommentsAndWhiteSpace(char * line) { // Parse a line of assembly into numerical representations for the function (eg. add = 0), registers, offset, etc. int * parseIntoNotation(char * bareLine) { - int numFunctions = 2; // TODO: Need to obtain dynamically. - int * notation = (int *)calloc(4, sizeof(int)); + int numFunctions = 20; // TODO: Need to obtain dynamically. //char * tokens = strtok(bareLine, " "); char * token = strtok(bareLine, " "); - - int counter = 0; + + int cmd; + for(int i = 0; i < numFunctions; i++) + if(strcmp(token, FUNCTION_STRING[i]) == 0) cmd = i; + + int * notation = (int *)calloc(4, sizeof(int)); + int counter = 1; while (token != NULL) { - for(int i = 0; i < numFunctions; i++) { - if(strcmp(token, FUNCTION_STRING[i]) == 0) { - printf("found a match between %s and %s, value is %d\n", token, FUNCTION_STRING[i], i); - notation[counter] = i; - counter++; - continue; - } + // Compare only the first token to all available functions. + if(counter == 0) { } if(counter == 0) break; + // Compare subsequent tokens to available registers. for(int i = 0; i < 32; i++) { if(strcmp(token, REGISTER_STRING[i]) == 0) { - printf("found a match between %s and %s, value is %d\n", token, REGISTER_STRING[i], i); notation[counter] = i; counter++; continue; } } + printf("%s ", token); token = strtok(NULL, " "); } + return notation; } @@ -96,7 +97,7 @@ int initParse(char * filepath) { file = fopen(filepath, "r"); // Maximum number of characters in a line is 1024. - char lines[1024]; + char lines[256]; // Catch if the file does not exist/cannot be opened. if(file == NULL) { @@ -104,13 +105,11 @@ int initParse(char * filepath) { return 0; } + // Get each line of the file, remove comments and whitespace, and attempt to parse while(fgets(lines, sizeof(lines), file)) { char * line = removeCommentsAndWhiteSpace(lines); int * notation = parseIntoNotation(line); - - printf("notation: %d %d %d %d\n", notation[0], notation[1], notation[2], notation[3]); - free(notation); } fclose(file);