Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01d483cf8d | ||
|
|
bf8e88a7e8 | ||
|
|
e0102289e4 | ||
|
|
160cf8d9a0 | ||
|
|
233c1ba1d9 | ||
|
|
1c2ce3e971 | ||
|
|
87014ffc01 | ||
|
|
a5136d917b | ||
|
|
6a1fbca018 | ||
|
|
d179bf2a8d |
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user