diff --git a/src/main.c b/src/main.c index 99e6f5c..7b23b8f 100644 --- a/src/main.c +++ b/src/main.c @@ -2,9 +2,6 @@ #include #include -#include "util/registers.h" -#include "util/functions.c" - int help() { printf( "\nA CLI-based tool to convert MIPS assembly instructions in a .asm file into hexadecimal instructions in a .hex file.\n" @@ -29,9 +26,5 @@ int main(int argc, char* args[]) { if(argc < 2) return error(); if(strcmp(args[1], "-h") == 0 || strcmp(args[1], "--help") == 0) return help(); - initFunctions(); - - for(int i = 0; i < 32; i++) - printf("%d: %s\n", i, REGISTER_STRING[i]); return 0; } diff --git a/src/test/Fibonacci.asm b/src/test/Fibonacci.asm index 470e5ee..e1358cb 100644 --- a/src/test/Fibonacci.asm +++ b/src/test/Fibonacci.asm @@ -1,53 +1,2 @@ -.data - welcomeMessage: .asciiz "Welcome to a MIPS assembly Fibonacci Sequence calculator!\nThis will calculate the nth term of the Fibonacci Sequence.\n" - prompt: .asciiz "Enter a number (n, input n > 2) to find the nth term:" - foundTerm: .asciiz "The nth term is: " - -.text - -main: - li $v0, 4 # syscall 4 is to print a string - la $a0, welcomeMessage # store the ascii string in register a0 - syscall # print - - jal getInput # get the user input - - jal fibonacci # calculate the nth fibonacci term - move $a0, $v0 # move the returned term to register a0 - li $v0, 1 # syscall 1 is to print an int - syscall # print - - ori $v0, $0, 10 # system call code 10 for exit - syscall # exit the program - -getInput: - li $v0, 4 # syscall 4 is to print a string - la $a0, prompt # store the ascii string in register a0 - syscall # print - - li $v0, 5 # syscall 5 is for reading an int - syscall # read an int from the user - move $a0, $v0 # load input into register a0 - - jr $ra # return to caller - -fibonacci: - move $s1, $a0 # Copy the nth term - li $t0, 2 # Counter - li $t1, 0 # Prev value - li $t2, 1 # Current value - li $t3, 0 # Next value - - while: - bge $t0, $s1, done # While the counter is less than n add $t3, $t1, $t2 # Sum the previous and current values and save in register t3 - move $t1, $t2 # Shift current value to previous value - - move $t2, $t3 # Shift next value to current value addi $t0, $t0, 1 # Increment counter - - b while # Jump back to start of while loop - - done: - move $v0, $t2 # Move current value to register v0 - jr $ra # Return to caller diff --git a/src/test/a.out b/src/test/a.out new file mode 100755 index 0000000..2d27402 Binary files /dev/null and b/src/test/a.out differ diff --git a/src/test/testParse.c b/src/test/testParse.c index 90054f8..b9d5036 100644 --- a/src/test/testParse.c +++ b/src/test/testParse.c @@ -6,8 +6,26 @@ char * filepath; +int traverse(struct instruction* current) { + while(current->nextInstruction != NULL) { + struct args* currentArgs = current->a; + while(currentArgs != NULL) { + printf("%s ", currentArgs->arg); + currentArgs = currentArgs->nextArg; + } + printf("\n"); + + printf("%s\n", convert(current)); + + current = current->nextInstruction; + } + + return 1; // TODO +} + int test_readFile() { - initParse(filepath); + struct instruction * head = initParse(filepath); + traverse(head); return 1; } diff --git a/src/util/functionAssigner.h b/src/util/functionAssigner.h index 4f6bcbf..ff2fcaf 100644 --- a/src/util/functionAssigner.h +++ b/src/util/functionAssigner.h @@ -1,4 +1,5 @@ #define FOREACH_FUNCTION(FUNCTION) \ + FUNCTION(addi) \ FUNCTION(add) \ FUNCTION(jr) \ FUNCTION(syscall) \ @@ -13,7 +14,6 @@ FUNCTION(srl) \ FUNCTION(sub) \ FUNCTION(subu) \ - FUNCTION(addi) \ FUNCTION(jal) \ #define GENERATE_ENUM(ENUM) ENUM, diff --git a/src/util/functions.c b/src/util/functions.c index 8e3a16c..37db0d8 100644 --- a/src/util/functions.c +++ b/src/util/functions.c @@ -2,6 +2,10 @@ #include #include "formats.c" +#include "registers.h" +#include "functionAssigner.h" +#include "instruction.h" + r* rFormat; i* iFormat; @@ -14,10 +18,11 @@ void initFunctions() { } // -------------------------- R FORMAT INSTRUCTIONS -------------------------- // -char * add(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * addFunc(int * args) { + r* rFormat = (r*)malloc(sizeof(r)); + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 32; // Unused in add instruction. @@ -26,10 +31,10 @@ char * add(int * args[]) { return rToHex(rFormat); } -char * addu(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * adduFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 33; // Unused in addu instruction. @@ -38,10 +43,10 @@ char * addu(int * args[]) { return rToHex(rFormat); } -char * and(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * andFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 36; // Unused in and instruction. @@ -50,8 +55,8 @@ char * and(int * args[]) { return rToHex(rFormat); } -char * jr(int * args[]) { - rFormat->rs = *args[0]; +char * jrFunction(int * args) { + rFormat->rs = args[0]; rFormat->funct = 8; // Unused in jr instruction. @@ -62,10 +67,10 @@ char * jr(int * args[]) { return rToHex(rFormat); } -char * nor(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * norFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 39; // Unused in nor instruction. @@ -74,10 +79,10 @@ char * nor(int * args[]) { return rToHex(rFormat); } -char * or(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * orFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 37; // Unused in or instruction. @@ -85,10 +90,10 @@ char * or(int * args[]) { return rToHex(rFormat); } -char * slt(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * sltFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 42; // Unused in slt instruction. @@ -97,10 +102,10 @@ char * slt(int * args[]) { return rToHex(rFormat); } -char * sltu(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * sltuFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 43; // Unused in sltu instruction. @@ -109,10 +114,10 @@ char * sltu(int * args[]) { return rToHex(rFormat); } -char * sll(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rt = *args[1]; - rFormat->shamt = *args[2]; +char * sllFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rt = args[1]; + rFormat->shamt = args[2]; rFormat->funct = 0; // Unused in sll instruction. @@ -121,10 +126,10 @@ char * sll(int * args[]) { return rToHex(rFormat); } -char * srl(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rt = *args[1]; - rFormat->shamt = *args[2]; +char * srlFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rt = args[1]; + rFormat->shamt = args[2]; rFormat->funct = 2; // Unused in sll instruction. @@ -133,10 +138,10 @@ char * srl(int * args[]) { return rToHex(rFormat); } -char * sub(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * subFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 34; // Unused in sll instruction. @@ -145,10 +150,10 @@ char * sub(int * args[]) { return rToHex(rFormat); } -char * subu(int * args[]) { - rFormat->rd = *args[0]; - rFormat->rs = *args[1]; - rFormat->rt = *args[2]; +char * subuFunction(int * args) { + rFormat->rd = args[0]; + rFormat->rs = args[1]; + rFormat->rt = args[2]; rFormat->funct = 35; // Unused in sll instruction. @@ -158,40 +163,169 @@ char * subu(int * args[]) { } // -------------------------- I FORMAT INSTRUCTIONS -------------------------- // -char * addi(int * args[]) { +char * addiFunction(int * args) { iFormat->opcode = 8; - iFormat->rt = *args[0]; - iFormat->rs = *args[1]; - iFormat->immediate = *args[2]; + iFormat->rt = args[0]; + iFormat->rs = args[1]; + iFormat->immediate = args[2]; return iToHex(iFormat); } -char * addiu(int * args[]) { +char * addiuFunction(int * args) { iFormat->opcode = 9; - iFormat->rt = *args[0]; - iFormat->rs = *args[1]; - iFormat->immediate = *args[2]; + iFormat->rt = args[0]; + iFormat->rs = args[1]; + iFormat->immediate = args[2]; return iToHex(iFormat); } -char * andi(int * args[]) { +char * andiFunction(int * args) { iFormat->opcode = 12; - iFormat->rt = *args[0]; - iFormat->rs = *args[1]; - iFormat->immediate = *args[2]; + iFormat->rt = args[0]; + iFormat->rs = args[1]; + iFormat->immediate = args[2]; return iToHex(iFormat); } -char * beq(int * args[]) { +char * beqFunction(int * args) { iFormat->opcode = 4; - iFormat->rt = *args[0]; - iFormat->rs = *args[1]; - iFormat->immediate = *args[2]; + iFormat->rt = args[0]; + iFormat->rs = args[1]; + iFormat->immediate = args[2]; return iToHex(iFormat); } // -------------------------- J FORMAT INSTRUCTIONS -------------------------- // + +// Helper function to get the number of arguments. +int getArgCount(struct args * a) { + printf("getArgCount "); + int count = 0; + + while(a != NULL) { + count++; + a = a->nextArg; + } + + return count; +} + +// Converts a linked list of arguments into an int array of arguments. +int * getArgs(struct args * a) { + printf("getArgs "); + + int * array = (int *) calloc(getArgCount(a), sizeof(int)); + int index = 0; + int update = 0; + while(a != NULL) { + + // check for valid register + for(int i = 0; i < 32; i++) { + if(strcmp(a->arg, REGISTER_STRING[i]) == 0) { + array[index] = i; + index++; + update = 1; + } + } + + // if we found a register, reset the update value to detect a register in the next argument. + if(update == 1) update = 0; + + // otherwise, we have found a constant. + else { + array[index] = (int) a->arg[0]; + printf("%d", array[index]); + index++; + } + + + // move to the next argument. + a = a->nextArg; + } + return array; +} + +// Helper function to determine what function to call given an input int +char * funcToCall(int i, struct args * remainingArgs) { + printf("funcToCall "); + int * args = getArgs(remainingArgs); + char * hex; + switch (i) { + case 0: + hex = addFunc(args); + break; + case 1: + hex = adduFunction(args); + break; + case 2: + hex = andFunction(args); + break; + case 3: + hex = jrFunction(args); + break; + case 4: + hex = norFunction(args); + break; + case 5: + hex = orFunction(args); + break; + case 6: + hex = sltFunction(args); + break; + case 7: + hex = sltuFunction(args); + break; + case 8: + hex = sllFunction(args); + break; + case 9: + hex = srlFunction(args); + break; + case 10: + hex = subFunction(args); + break; + case 11: + hex = subuFunction(args); + break; + case 12: + hex = addiFunction(args); + break; + case 13: + hex = addiuFunction(args); + break; + case 14: + hex = andiFunction(args); + break; + case 15: + hex = beqFunction(args); + break; + default: + hex = ""; + } + + return hex; +} + +// Convert a linked list instruction into hexadecimal +char * convert(struct instruction * i) { + printf("convert "); + initFunctions(); + struct args * a = i->a; + int call = 0; + struct args * remainingArgs; + + // Go through each of the available functions and find a match for the first argument, and get the remaining args + for(int i = 0; i < 4; i++) { + if(strcmp(a->arg, FUNCTION_STRING[i]) == 0) { + call = i; + remainingArgs = a->nextArg; + break; + } + } + + return funcToCall(call, remainingArgs); +} diff --git a/src/util/instruction.h b/src/util/instruction.h index fd9b650..23840ac 100644 --- a/src/util/instruction.h +++ b/src/util/instruction.h @@ -1,5 +1,5 @@ typedef struct args { - int arg; + char * arg; struct args *nextArg; // Allows dynamically sized lists of arguments. For eg. syscall will just be 1 element, but add has 4 elements. } args; diff --git a/src/util/parse.c b/src/util/parse.c index eac0a58..155704c 100644 --- a/src/util/parse.c +++ b/src/util/parse.c @@ -4,9 +4,7 @@ #include #include -#include "formats.c" -#include "registers.h" -#include "functionAssigner.h" +#include "functions.c" FILE * file; @@ -56,63 +54,50 @@ 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 = 20; // TODO: Need to obtain dynamically. - //char * tokens = strtok(bareLine, " "); - +void parseIntoNotation(char * bareLine, args * a) { char * token = strtok(bareLine, " "); + args * current = a; + + while (token != NULL) { + current->arg = token; + token = strtok(NULL, " "); - 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) - { - // Compare only the first token to all available functions. - if(counter == 0) { + if(token != NULL) { + current->nextArg = (args*) malloc(sizeof(args)); + current = current->nextArg; } - - if(counter == 0) break; - - // Compare subsequent tokens to available registers. - for(int i = 0; i < 32; i++) { - if(strcmp(token, REGISTER_STRING[i]) == 0) { - notation[counter] = i; - counter++; - continue; - } - } - - printf("%s ", token); - token = strtok(NULL, " "); } - - return notation; } -int initParse(char * filepath) { +instruction* initParse(char * filepath) { // Open and read a file. file = fopen(filepath, "r"); // Maximum number of characters in a line is 1024. - char lines[256]; + char lines[1024]; // Catch if the file does not exist/cannot be opened. if(file == NULL) { printf("%s cannot be opened.\n", filepath); - return 0; + return NULL; } + int numFunctions = 4; // TODO: Need to obtain dynamically. + struct instruction* head = (instruction*) malloc(sizeof(instruction)); + struct instruction* current = head; // Get each line of the file, remove comments and whitespace, and attempt to parse while(fgets(lines, sizeof(lines), file)) { + struct args* argsHead = (args*) malloc(sizeof(args)); + current->a = argsHead; + char * line = removeCommentsAndWhiteSpace(lines); - int * notation = parseIntoNotation(line); + parseIntoNotation(line, argsHead); + + current->nextInstruction = (instruction*) malloc(sizeof(instruction)); + current = current->nextInstruction; } fclose(file); - - return 1; + return head; }