Compare commits

..
10 Commits
Author SHA1 Message Date
Josh Ashton 01d483cf8d fixed input/output of files, parsing needs additional work 2023-10-17 19:42:45 -06:00
Josh Ashton bf8e88a7e8 branching to remove excess to narrow down problem 2023-10-17 18:42:59 -06:00
Josh Ashton e0102289e4 partial success! testParse will parse a file, though not all the hex is correct. primarily this is the case for instructions not yet added however. running from main with cli arguments currently will always result in a seg fault. 2023-10-17 13:08:31 -06:00
Josh Ashton 160cf8d9a0 succesfully parsing and outputing into converter. two main bugs, the converter adds 1 to the end somehow, and for the addi instruction it's registering that there are multiple free() statements 2023-10-13 16:00:22 -06:00
Josh Ashton 233c1ba1d9 moving to nested linked list structure for instructions and arguments. this should allow for better dynamism between instructions and clearer organizational logic. 2023-10-12 17:11:55 -06:00
Josh Ashton 1c2ce3e971 first successful parsing from .asm to notational representationrun testParse 2023-10-10 13:41:32 -06:00
Josh Ashton 87014ffc01 successful removal of whitespace and comments, 1.0 2023-10-10 11:33:58 -06:00
Josh Ashton a5136d917b basic reading functionality added, need to complete parsing implementation 2023-10-09 19:40:47 -06:00
Josh Ashton 6a1fbca018 memory safety & documentation added 2023-10-09 10:58:01 -06:00
Josh Ashton d179bf2a8d toBinary implemented (not yet memory safe), all tests pass 2023-10-09 10:52:07 -06:00
16 changed files with 977 additions and 122 deletions
+40
View File
@@ -0,0 +1,40 @@
.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
+38 -10
View File
@@ -2,8 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include "util/registers.h"
#include "util/functions.h"
#include "util/parse.c"
int help() {
printf(
@@ -13,25 +12,54 @@ int help() {
" mipsToHex --help\n"
" mipsToHex [ file ]\n"
" mipsToHex --asm [ asmFile ]\n"
" mipsToHex -a [ asmFile ]\n"
" mipsToHex --asm [ asmFile ] --hex [ hexFile ]\n"
" mipsToHex -a [ asmFile ] -x [ hexFile ]\n"
);
return 0;
}
int error() {
printf("There must be at least one argument.");
int error(char * msg) {
printf("\n%s\n", msg);
help();
return 1;
}
int main(int argc, char* args[]) {
if(argc < 2) return error();
if(strcmp(args[1], "-h") == 0 || strcmp(args[1], "--help") == 0) return help();
void printHex(struct instruction* current) {
while(current->nextInstruction != NULL) {
printf("0x%s ", convert(current));
initFunctions();
current = current->nextInstruction;
}
}
void writeHex(struct instruction * current) {
char output[25];
printf("What is the output file name (ends in .hex): ");
scanf("%s", output);
FILE * file = fopen(output, "w");
if(file == NULL) printf("error!");
while(current->nextInstruction != NULL) {
fprintf(file, "0x%s ", convert(current));
current = current->nextInstruction;
}
}
int main() {
char * file;
char * output;
printf("Welcome to the MIPS assembly to hexadecimal converter!\nPlease enter the input filename: ");
scanf("%s", file);
printHex(initParse(file));
printf("\n\n");
writeHex(initParse(file));
for(int i = 0; i < 32; i++)
printf("%d: %s\n", i, REGISTER_STRING[i]);
return 0;
}
+1
View File
@@ -0,0 +1 @@
0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000024 0x00000020 0x00000020 0x00000020 0x00000020 0x00000024 0x00000020 0x00000024 0x00000020 0x00000020 0x00000020 0x00000024 0x00000020 0x00000024 0x00000020 0x0000F821 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x012A5820 0x012A5820 0x012A5820 0x01014023 0x01014020 0x01014020 0x01014020 0x0000F821
+1
View File
@@ -0,0 +1 @@
0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000024 0x00000020 0x00000020 0x00000020 0x00000020 0x00000024 0x00000020 0x00000024 0x00000020 0x00000020 0x00000020 0x00000024 0x00000020 0x00000024 0x00000020 0x0000F821 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x0000F820 0x012A5820 0x012A5820 0x012A5820 0x01014023 0x01014020 0x01014020 0x01014020 0x0000F821
+40
View File
@@ -0,0 +1,40 @@
.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
+1
View File
@@ -0,0 +1 @@
0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00400008 0x00801020 0x00000024 0x00000020 0x00000020 0x00000020 0x00400008 0x00000024 0x00000020 0x00000024 0x00000020 0x00400008 0x00801020 0x00000024 0x00400008 0x00000024 0x00000020 0x0000F821 0x0000F820 0x0000F820 0x01000008 0x01200008 0x01400008 0x01600008 0x00005820 0x00005820 0x012A5820 0x012A5820 0x012A5820 0x21080001 0x01014020 0x01014020 0x01014020 0x0000F821
+119 -40
View File
@@ -1,66 +1,136 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../util/formats.h"
#include "../util/formats.c"
int compareIntArray(int * x, int * y, int size) {
for(int i = 0; i < size; i++)
if(x[i] != y[i]) return 0;
return 1;
}
int test_binaryToHex() {
return 1; // TODO
}
// Testing the toBinary function with an input of 0 and a size of 5.
int test_toBinary_0_size5() {
char * binaryString = toBinary(0, 5);
char * expectedOutput = "00000";
int size = 5;
int * binary = toBinary(0, size);
int expectedOutput[] = { 0, 0, 0, 0, 0 };
int cmp = strcmp(binaryString, expectedOutput);
if(cmp < 0 || cmp > 0) return 0;
else return 1;
int cmp = compareIntArray(binary, expectedOutput, size);
return cmp;
}
// Testing the toBinary function with an input of 0 and a size of 6.
int test_toBinary_0_size6() {
char * binaryString = toBinary(0, 6);
char * expectedOutput = "000000";
int size = 6;
int * binary = toBinary(0, size);
int expectedOutput[] = { 0, 0, 0, 0, 0, 0 };
int cmp = strcmp(binaryString, expectedOutput);
if(cmp < 0 || cmp > 0) return 0;
else return 1;
}
int test_toBinary_20_size6() {
char * binaryString = toBinary(20, 6);
char * expectedOutput = "010100";
int cmp = strcmp(binaryString, expectedOutput);
if(cmp < 0 || cmp > 0) return 0;
else return 1;
int cmp = compareIntArray(binary, expectedOutput, size);
return cmp;
}
// Testing the toBinary function with an input of 10 and a size of 6.
int test_toBinary_10_size6() {
char * binaryString = toBinary(10, 6);
char * expectedOutput = "001010";
int size = 6;
int * binary = toBinary(10, size);
int expectedOutput[] = { 0, 0, 1, 0, 1, 0 };
int cmp = strcmp(binaryString, expectedOutput);
if(cmp < 0 || cmp > 0) return 0;
else return 1;
int cmp = compareIntArray(binary, expectedOutput, size);
return cmp;
}
// Testing the toBinary function with an input of 20 and a size of 6.
int test_toBinary_20_size6() {
int size = 6;
int * binary = toBinary(20, size);
int expectedOutput[] = { 0, 1, 0, 1, 0, 0 };
int cmp = compareIntArray(binary, expectedOutput, size);
return cmp;
}
// Testing the toBinary function with an input of 17 and a size of 16.
int test_toBinary_17_size16() {
char * binaryString = toBinary(17, 16);
char * expectedOutput = "0000000000010001";
int size = 16;
int * binary = toBinary(17, size);
int expectedOutput[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1};
int cmp = strcmp(binaryString, expectedOutput);
int cmp = compareIntArray(binary, expectedOutput, size);
return cmp;
}
int test_rToBinary_sll() {
r* rFormat = malloc(sizeof(r));
rFormat->opcode = 0; // Opcode for sll instruction
rFormat->rs = 0; // Register 17.
rFormat->rt = 16; // Register 18.
rFormat->rd = 14; // Register 13.
rFormat->shamt = 2; // Shift amount
rFormat->funct = 0; // Hexadecimal 00, or 0000 0000.
int * binary = rToBinary(rFormat);
int expectedOutput[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
int cmp = compareIntArray(binary, expectedOutput, 32);
return cmp;
}
int test_rToBinary_add() {
r* rFormat = malloc(sizeof(r));
rFormat->opcode = 0; // Opcode for add instruction
rFormat->rs = 17; // Register 17.
rFormat->rt = 18; // Register 18.
rFormat->rd = 13; // Register 13.
rFormat->shamt = 0; // Shift amount is 0
rFormat->funct = 32; // Hexadecimal 20, or 0010 0000.
int * binary = rToBinary(rFormat);
int expectedOutput[] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 };
int cmp = compareIntArray(binary, expectedOutput, 32);
return cmp;
}
int test_rToHex_add() {
r* rFormat = malloc(sizeof(r));
rFormat->opcode = 0; // Opcode for add instruction
rFormat->rs = 17; // Register 17.
rFormat->rt = 18; // Register 18.
rFormat->rd = 13; // Register 13.
rFormat->shamt = 0; // Shift amount is 0
rFormat->funct = 32; // Hexadecimal 20, or 0010 0000.
char * hex = rToHex(rFormat);
char * expectedHex = "02326820";
int cmp = strcmp(hex, expectedHex);
if(cmp < 0 || cmp > 0) return 0;
else return 1;
}
int test_rToBinary() {
int test_rToHex_sll() {
r* rFormat = malloc(sizeof(r));
return 1; // TODO
rFormat->opcode = 0; // Opcode for sll instruction
rFormat->rs = 0; // Register 17.
rFormat->rt = 16; // Register 18.
rFormat->rd = 14; // Register 13.
rFormat->shamt = 2; // Shift amount
rFormat->funct = 0; // Hexadecimal 00, or 0000 0000.
char * hex = rToHex(rFormat);
char * expectedHex = "00107080";
int cmp = strcmp(hex, expectedHex);
if(cmp < 0 || cmp > 0) return 0;
else return 1;
}
int test_iToHex() {
@@ -69,11 +139,20 @@ int test_iToHex() {
}
int main() {
printf("\nTesting formats.h functionality.\n");
printf("\nTesting formats.h functionality. 1 = pass, 0 = fail\n");
printf("\ntoBinary_0_size5: %d\n", test_toBinary_0_size5());
printf("\ntoBinary_0_size6: %d\n", test_toBinary_0_size6());
printf("\ntoBinary_10_size6: %d\n", test_toBinary_10_size6());
printf("\ntoBinary_20_size6: %d\n", test_toBinary_20_size6());
printf("\ntoBinary_17_size16: %d\n", test_toBinary_17_size16());
printf("\nTesting number to binary (with formatted size):\n");
printf("toBinary_0_size5: %d\n", test_toBinary_0_size5());
printf("toBinary_0_size6: %d\n", test_toBinary_0_size6());
printf("toBinary_10_size6: %d\n", test_toBinary_10_size6());
printf("toBinary_20_size6: %d\n", test_toBinary_20_size6());
printf("toBinary_17_size16: %d\n", test_toBinary_17_size16());
printf("\nTesting R Format to Binary:\n");
printf("rToBinary_add: %d\n", test_rToBinary_add());
printf("rToBinary_sll: %d\n", test_rToBinary_sll());
printf("\nTesting R Format to Hex:\n");
printf("rToHex_add: %d\n", test_rToHex_add());
printf("rToHex_sll: %d\n", test_rToHex_sll());
}
+23
View File
@@ -0,0 +1,23 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../util/parse.c"
int traverse(struct instruction* current) {
while(current->nextInstruction != NULL) {
printf("0x%s ", convert(current));
current = current->nextInstruction;
}
return 1; // TODO
}
int main() {
// filepath may be a relative or an absolute filepath
//filepath = "/home/jashton/dev/mipsToHex/src/test/Fibonacci.asm";
char * filepath = "Fibonacci.asm";
return traverse(initParse(filepath));
}
+186
View File
@@ -0,0 +1,186 @@
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);
int * rs = toBinary(format->rs, 5);
fillArray(bin, rs, 6, size);
int * rt = toBinary(format->rt, 5);
fillArray(bin, rt, 11, size);
int * rd = toBinary(format->rd, 5);
fillArray(bin, rd, 16, size);
int * shamt = toBinary(format->shamt, 5);
fillArray(bin, shamt, 21, size);
int * funct = toBinary(format->funct, 6);
fillArray(bin, funct, 26, size);
// Print the binary representation.
/**
for(int i = 0; i < 32; i++) {
printf("%d", bin[i]);
if(i % 4 == 3) printf(" ");
}
printf("\n"); // Separate the bit string from the hex
*/
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);
int * rs = toBinary(format->rs, 5);
fillArray(bin, rs, 6, size);
int * rt = toBinary(format->rt, 5);
fillArray(bin, rt, 11, size);
int * immediate = toBinary(format->immediate, 16);
fillArray(bin, immediate, 16, size);
// Print the binary representation
/**
printf("\n");
for(int i = 0; i < 32; i++) {
printf("%d", bin[i]);
if(i % 4 == 3) printf(" ");
}
printf("\n");
*/
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));
}
+2 -30
View File
@@ -1,15 +1,3 @@
// Utility function to convert any given binary instruction into hexadecimal.
char* binaryToHex(char* bin) {
return "0x00000000";
}
// Utility function to convert a number to binary
char* toBinary(int num, int size) {
char bin[size];
return "000000"; // TODO
}
// Represents the R instruction format.
typedef struct r {
int opcode; // 6 bits
@@ -22,22 +10,10 @@ typedef struct r {
int rd_size;
int shamt; // 5 bits
int shamt_size;
char* functHex; // 6 bits
int funct; // 6 bits
int functHex_size;
} r;
char* rToBinary(r* format) {
char binary[32];
char* opcode = toBinary(format->opcode, format->opcode_size);
if(format->opcode == 0)
for(int i = 0; i < 6; i++) binary[i] = 0;
return binary;
}
// Represents the I instruction format.
typedef struct i {
int opcode; // 6 bits
@@ -46,13 +22,9 @@ typedef struct i {
int immediate; // 16 bits
} i;
// Utility function to convert any given I instruction into hexadecimal.
char* iToHex(i* format) {
return "";
}
// Represents the J instruction format.
typedef struct j {
int opcode; // 6 bits
int address; // 26 bits
} j;
+29
View File
@@ -0,0 +1,29 @@
#define FOREACH_FUNCTION(FUNCTION) \
FUNCTION(add) \
FUNCTION(jr) \
FUNCTION(syscall) \
FUNCTION(addu) \
FUNCTION(and) \
FUNCTION(nor) \
FUNCTION(or) \
FUNCTION(slt) \
FUNCTION(sltu) \
FUNCTION(sll) \
FUNCTION(srl) \
FUNCTION(addi) \
FUNCTION(addiu) \
FUNCTION(li) \
FUNCTION(sub) \
FUNCTION(subu) \
FUNCTION(jal) \
#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_STRING(STRING) #STRING,
enum Function {
FOREACH_FUNCTION(GENERATE_ENUM)
};
static char* FUNCTION_STRING[] = {
FOREACH_FUNCTION(GENERATE_STRING)
};
+337
View File
@@ -0,0 +1,337 @@
#include <stdio.h>
#include <stdlib.h>
#include "formats.c"
#include "registers.h"
#include "functionAssigner.h"
#include "instruction.h"
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 * addFunc(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 * adduFunction(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 * andFunction(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 * jrFunction(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 * norFunction(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 * orFunction(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 * sltFunction(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 * sltuFunction(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 * sllFunction(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 * srlFunction(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 * subFunction(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 * subuFunction(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 * addiFunction(int * args) {
iFormat->opcode = 8;
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
char * addiuFunction(int * args) {
iFormat->opcode = 9;
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
char * andiFunction(int * args) {
iFormat->opcode = 12;
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
char * beqFunction(int * args) {
iFormat->opcode = 4;
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
// -------------------------- J FORMAT INSTRUCTIONS -------------------------- //
int str2int(char * numStr) {
int intVal = 0;
while(* numStr != '\0') {
intVal *= 10;
intVal += * numStr - '0'; //0x30 ascii value of charater 0
numStr++;
}
return intVal;
}
// Helper function to get the number of arguments.
int getArgCount(struct args * a) {
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) {
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 {
// TODO: This is broken. Currently only gets the first digit.
array[index] = str2int(a->arg);
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) {
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 = "";
}
free(rFormat);
free(iFormat);
return hex;
}
// Convert a linked list instruction into hexadecimal
char * convert(struct instruction * i) {
initFunctions();
struct args * remainingArgs;
struct args * a = i->a;
int call = 0;
// 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 < 13; i++) {
if(strcmp(a->arg, FUNCTION_STRING[i]) == 0) {
call = i;
remainingArgs = a->nextArg;
break;
}
}
return funcToCall(call, remainingArgs);
}
-42
View File
@@ -1,42 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#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[4];
rFormat->functHex = "0x20";
return rToBinary(rFormat);
}
char* addi(int * args[]) {
rFormat->opcode = 0;
rFormat->rs = *args[0];
rFormat->rt = *args[1];
rFormat->functHex = "0x8";
return rToBinary(rFormat);
}
char* sub(int * args[]) {
rFormat->opcode = 0;
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
rFormat->shamt = *args[4];
rFormat->functHex = "0x22";
return rToBinary(rFormat);
}
+11
View File
@@ -0,0 +1,11 @@
typedef struct args {
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;
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;
+52
View File
@@ -0,0 +1,52 @@
#include <stdio.h>
#include <stdlib.h>
#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);
}
+97
View File
@@ -0,0 +1,97 @@
#include <bits/types/FILE.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "functions.c"
// 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 != (char *) NULL && !isspace(prior))
if(&after != (char *) NULL && !isspace(after))
return 1;
return 0;
}
// Cleans up the input string to prepare for parsing into command and arguments.
char * removeCommentsAndWhiteSpace(char * line) {
if(line[0] == 10) return "";
int len = strlen(line);
char tmpLine[256];
int parsedIndex = 0;
for(int i = 0; i < len; i++) {
// Check if we've reached a comment and if so, break out of the loop
if(line[i] == '#') break;
// Check if the current character is not a comma or dollar sign.
if(line[i] != ',' && line[i] != '$' && !isspace(line[i])) {
tmpLine[parsedIndex] = line[i];
parsedIndex++;
} else if(isspace(line[i])) {
// Check if we're within bounds of the array to check whitespace
if((i - 1 >= 0) && (i + 1 < len))
if(determineKeepSpace(line[i - 1], line[i + 1]) == 1) {
tmpLine[parsedIndex] = line[i];
parsedIndex++;
}
}
}
// Create a dynamically sized array containing only the valid characters
char * parsed = (char *)calloc(parsedIndex, sizeof(char));
for(int i = 0; i < parsedIndex; i++)
parsed[i] = tmpLine[i];
return parsed;
}
// Parse a line of assembly into numerical representations for the function (eg. add = 0), registers, offset, etc.
void parseIntoNotation(char * bareLine, args * a) {
char * token = strtok(bareLine, " ");
args * current = a;
while (token != NULL) {
current->arg = token;
token = strtok(NULL, " ");
if(token != NULL) {
current->nextArg = (args*) malloc(sizeof(args));
current = current->nextArg;
}
}
}
// Accepts an already verified FILE pointer to parse. Creates a Linked List to contain each instruction, with a sub Linked List
// to contain each argument of each instruction. Formatted into a custom numeric notation.
instruction* initParse(char * filepath) {
FILE * file = fopen(filepath, "r");
if(file == NULL) return NULL;
// Maximum number of characters in a line is 1024.
char lines[256];
int numFunctions = 16; // 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);
parseIntoNotation(line, argsHead);
current->nextInstruction = (instruction*) malloc(sizeof(instruction));
current = current->nextInstruction;
}
return head;
}