#include "ASMParser.h"
#include "SymbolTable.h"
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
// On my honor:
//
// - I have not discussed the C language code in my program with
// anyone other than my instructor or the teaching assistants
// assigned to this course.
//
// - I have not used C language code obtained from another student,
// the Internet, or any other unauthorized source, either modified
// or unmodified.
//
// - If any C language code or documentation used in my program
// was obtained from an authorized source, such as a text book or
// course notes, that has been clearly noted with a proper citation
// in the comments of my program.
//
// - I have not designed this program in such a way as to defeat or
// interfere with the normal operation of the grading code.
//
// <Jordan Harrington>
// <jordanha23>
/*** Add include directives for here as needed. ***/
static struct
{
char *mnem;
char *address;
} registers[] = {
{"$at", "00001"},
{"$a0", "00100"},
{"$a1", "00101"},
{"$a2", "00110"},
{"$a3", "00111"},
{"$t0", "01000"},
{"$t1", "01001"},
{"$t2", "01010"},
{"$t3", "01011"},
{"$t4", "01100"},
{"$t5", "01101"},
{"$t6", "01110"},
{"$t7", "01111"},
{"$t8", "11000"},
{"$t9", "11001"},
{"$s0", "10000"},
{"$s1", "10001"},
{"$s2", "10010"},
{"$s3", "10011"},
{"$s4", "10100"},
{"$s5", "10101"},
{"$s6", "10110"},
{"$s7", "10111"},
{"$v0", "00010"},
{"$v1", "00011"},
{"$zero", "00000"},
{"$k0", "11010"},
{"$k1", "11011"},
{NULL, 0}};
static struct
{
char *mnem;
char *opCode;
} op[] = {
{"lw", "100011"},
{"sub", "000000"},
{"add", "000000"},
{"nor", "000000"},
{"mult", "000000"},
{"syscall", "000000"},
{"mul", "011100"},
{"slti", "001010"},
{"lui", "001111"},
{"addi", "001000"},
{"la", "001000"},
{"beq", "000100"},
{"bne", "000101"},
{"sw", "101011"},
{"nop", "000000"},
{"sll", "000000"},
{"sra", "000000"},
{"srav", "000000"},
{"slt", "000000"},
{"blt", "101010"},
{"j", "000010"},
{"addu", "000000"},
{"move", "000000"},
{"addiu", "001001"},
{"li", "001001"},
{"blez", "000110"},
{"bgtz", "000111"},
{NULL, 0}};
static struct
{
char *mnem;
char *funcCode;
} func[] = {
{"sub", "100010"},
{"slt", "101010"},
{"addu", "100001"},
{"move", "100001"},
{"sra", "000011"},
{"srav", "000111"},
{"add", "100000"},
{"mult", "011000"},
{"nor", "100111"},
{"mul", "000010"},
{"syscall", "001100"},
{"sll", "000000"},
{"nop", "000000"},
{NULL, 0}};
static struct
{
char *mnem;
char *mType;
} type[] = {
{"sub", "r"},
{"nor", "r"},
{"add", "r"},
{"syscall", "r"},
{"mul", "r"},
{"mult", "s"},
{"lw", "i"},
{"lui", "i"},
{"addi", "i"},
{"slti", "i"},
{"la", "i"},
{"beq", "i"},
{"bne", "i"},
{"sw", "i"},
{"nop", "r"},
{"sll", "r"},
{"sra", "r"},
{"srav", "r"},
{"slt", "r"},
{"blt", "r"},
{"j", "ju"},
{"addu", "r"},
{"move", "r"},
{"addiu", "i"},
{"li", "i"},
{"blez", "i"},
{"bgtz", "i"},
{NULL, 0}};
#define REG_LENGTH 4
#define OP_FUNC_CODE_LENGTH 7
#define REG_ADD_LENGTH 6
#define TARGET_LENGTH 27
static bool blt = false;
char *findReg(char *inp);
char *findFunc(char *inp);
char *findOp(char *inp);
char *findType(char *inp);
uint8_t binaryToDec(char *addy);
uint16_t findInstructionNum(char *word);
uint16_t findImm(char *word);
char *unDecToBinary(char *word);
ParseResult *parseASM(const char *const pASM, uint16_t instructionNumber)
{
// Create ParseResult
ParseResult *res = calloc(1, sizeof(ParseResult));
res->ASMInstruction = calloc(strlen(pASM) + 1, sizeof(char));
strcpy(res->ASMInstruction, pASM);
res->rd = 0;
res->rs = 0;
res->rt = 0;
char *line = calloc(strlen(pASM) + 1, sizeof(char)),
*str[4];
strcpy(line, pASM);
// Grabs arguments
int i = 0;
str[i] = strtok(line, " ,\t");
while (str[i++])
str[i] = strtok(NULL, " ,\t");
// Sets mnemonic for type checking
res->Mnemonic = calloc(strlen(str[0]) + 1, sizeof(char));
strcpy(res->Mnemonic, (blt) ? "bne" : str[0]);
// Allocates fields of ParseResult based on instruction type
if (!strcmp(findType(res->Mnemonic), "ju"))
res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
else if (!strcmp(findType(res->Mnemonic), "i"))
{
res->RT = calloc(REG_ADD_LENGTH, sizeof(char));
res->RS = calloc(REG_ADD_LENGTH, sizeof(char));
res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
res->rtName = calloc(REG_LENGTH, sizeof(char));
res->rsName = calloc(REG_LENGTH, sizeof(char));
res->IMM = calloc(IMM_LENGTH, sizeof(char));
}
else if (!strcmp(findType(res->Mnemonic), "r"))
{
res->rtName = calloc(REG_LENGTH, sizeof(char));
res->rsName = calloc(REG_LENGTH, sizeof(char));
res->rdName = calloc(REG_LENGTH, sizeof(char));
res->Funct = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
res->RT = calloc(REG_ADD_LENGTH, sizeof(char));
res->RS = calloc(REG_ADD_LENGTH, sizeof(char));
res->RD = calloc(REG_ADD_LENGTH, sizeof(char));
res->shamt = calloc(REG_ADD_LENGTH, sizeof(char));
}
else if (!strcmp(findType(res->Mnemonic), "s"))
{
res->rtName = calloc(REG_LENGTH, sizeof(char));
res->rsName = calloc(REG_LENGTH, sizeof(char));
res->RT = calloc(REG_ADD_LENGTH, sizeof(char));
res->RS = calloc(REG_ADD_LENGTH, sizeof(char));
res->RD = calloc(REG_ADD_LENGTH, sizeof(char));
res->Funct = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
}
// R-type
if (!strcmp(res->Mnemonic, "mul") || !strcmp(str[0], "sub") ||
!strcmp(str[0], "add") || !strcmp(str[0], "nor") ||
!strcmp(str[0], "slt") || !strcmp(str[0], "addu"))
{
strcpy(res->rdName, str[1]);
strcpy(res->rsName, str[2]);
strcpy(res->rtName, str[3]);
strcpy(res->shamt, "00000");
strcpy(res->RD, findReg(str[1]));
strcpy(res->RS, findReg(str[2]));
strcpy(res->RT, findReg(str[3]));
strcpy(res->Funct, findFunc(str[0]));
strcpy(res->Opcode, findOp(str[0]));
res->rd = binaryToDec(res->RD);
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
}
else if (!strcmp(res->Mnemonic, "sll") || !strcmp(res->Mnemonic, "sra"))
{
strcpy(res->rdName, str[1]);
strcpy(res->rtName, str[2]);
strncpy(res->shamt, &decToBinary(str[3])[11], 6);
strcpy(res->RD, findReg(str[1]));
strcpy(res->RT, findReg(str[2]));
strcpy(res->RS, "00000");
strcpy(res->Funct, findFunc(str[0]));
strcpy(res->Opcode, findOp(str[0]));
res->rd = binaryToDec(res->RD);
res->rt = binaryToDec(res->RT);
}
else if (!strcmp(res->Mnemonic, "move"))
{
strcpy(res->rdName, str[1]);
strcpy(res->rtName, str[2]);
strcpy(res->shamt, "00000");
strcpy(res->RD, findReg(str[1]));
strcpy(res->RT, findReg(str[2]));
strcpy(res->RS, findReg("$zero"));
strcpy(res->Funct, findFunc(str[0]));
strcpy(res->Opcode, findOp(str[0]));
res->rd = binaryToDec(res->RD);
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
}
else if (!strcmp(res->Mnemonic, "srav"))
{
strcpy(res->rdName, str[1]);
strcpy(res->rsName, str[3]);
strcpy(res->rtName, str[2]);
strcpy(res->shamt, "00000");
strcpy(res->RD, findReg(str[1]));
strcpy(res->RS, findReg(str[3]));
strcpy(res->RT, findReg(str[2]));
strcpy(res->Funct, findFunc(str[0]));
strcpy(res->Opcode, findOp(str[0]));
res->rd = binaryToDec(res->RD);
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
}
else if (!strcmp(res->Mnemonic, "syscall"))
{
strcpy(res->RD, "00000");
strcpy(res->RS, "00000");
strcpy(res->RT, "00000");
strcpy(res->shamt, "00000");
strcpy(res->Funct, findFunc(str[0]));
strcpy(res->Opcode, findOp(str[0]));
}
else if (!strcmp(res->Mnemonic, "nop"))
{
strcpy(res->shamt, "00000");
strcpy(res->RD, findReg("$zero"));
strcpy(res->RT, findReg("$zero"));
strcpy(res->RS, "00000");
strcpy(res->Funct, findFunc(str[0]));
strcpy(res->Opcode, findOp(str[0]));
res->rd = binaryToDec(res->RD);
res->rt = binaryToDec(res->RT);
}
else if (!strcmp(res->Mnemonic, "blt"))
{
strcpy(res->rdName, "$at");
strcpy(res->rsName, str[1]);
strcpy(res->rtName, str[2]);
strcpy(res->shamt, "00000");
strcpy(res->RD, findReg("$at"));
strcpy(res->RS, findReg(str[1]));
strcpy(res->RT, findReg(str[2]));
strcpy(res->Funct, findFunc("slt"));
strcpy(res->Opcode, findOp("slt"));
res->rd = binaryToDec(res->RD);
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
blt = true;
}
// I-type
else if (!strcmp(res->Mnemonic, "blez") || !strcmp(res->Mnemonic, "bgtz"))
{
strcpy(res->rsName, str[1]);
strcpy(res->RS, findReg(str[1]));
strcpy(res->RT, findReg("$zero"));
strcpy(res->Opcode, findOp(str[0]));
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
int16_t symbolInstructNum = findInstructionNum(str[2]);
int16_t i = (symbolInstructNum - instructionNumber) - 1;
char *imm = calloc(TARGET_LENGTH, sizeof(char));
snprintf(imm, sizeof(char *), "%d", i);
char *bin = decToBinary(imm);
strcpy(res->IMM, bin);
free(bin);
free(imm);
res->Imm = i;
}
else if (!strcmp(res->Mnemonic, "bne") || !strcmp(res->Mnemonic, "beq"))
{
if (blt)
{
strcpy(res->rsName, "$at");
strcpy(res->RS, findReg("$at"));
strcpy(res->RT, findReg("$zero"));
strcpy(res->Opcode, findOp("bne"));
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
int16_t symbolInstructNum = findInstructionNum(str[3]);
int16_t i = (symbolInstructNum - instructionNumber);
if (i < 0)
i--;
char *imm = calloc(TARGET_LENGTH, sizeof(char));
snprintf(imm, sizeof(char *), "%d", i);
char *bin = decToBinary(imm);
strcpy(res->IMM, bin);
free(bin);
free(imm);
res->Imm = i;
blt = false;
}
else
{
strcpy(res->rsName, str[1]);
strcpy(res->rtName, str[2]);
strcpy(res->RS, findReg(str[1]));
strcpy(res->RT, findReg(str[2]));
strcpy(res->Opcode, findOp(str[0]));
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
int16_t symbolInstructNum = findInstructionNum(str[3]);
int16_t i = (symbolInstructNum - instructionNumber) - 1;
char *imm = calloc(TARGET_LENGTH, sizeof(char));
snprintf(imm, sizeof(char *), "%d", i);
char *bin = decToBinary(imm);
strcpy(res->IMM, bin);
free(bin);
free(imm);
res->Imm = i;
}
}
else if (!strcmp(res->Mnemonic, "li"))
{
strcpy(res->rtName, str[1]);
strcpy(res->RT, findReg(str[1]));
strcpy(res->RS, findReg("$zero"));
strcpy(res->Opcode, findOp(str[0]));
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
char *bin = unDecToBinary(str[2]);
strcpy(res->IMM, bin);
free(bin);
res->Imm = strtoul(str[2], NULL, 10);
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
}
else if (!strcmp(res->Mnemonic, "la"))
{
strcpy(res->rtName, str[1]);
strcpy(res->RT, findReg(str[1]));
strcpy(res->RS, findReg("$zero"));
strcpy(res->Opcode, findOp(str[0]));
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
uint16_t i = findImm(str[2]);
char *imm = calloc(TARGET_LENGTH, sizeof(char));
snprintf(imm, sizeof(char *), "%d", i);
char *bin = decToBinary(imm);
strcpy(res->IMM, bin);
free(bin);
free(imm);
res->Imm = i;
}
else if (!strcmp(res->Mnemonic, "addi") || !strcmp(res->Mnemonic, "slti") ||
!strcmp(res->Mnemonic, "addiu"))
{
strcpy(res->rtName, str[1]);
strcpy(res->rsName, str[2]);
strcpy(res->RT, findReg(str[1]));
strcpy(res->RS, findReg(str[2]));
strcpy(res->Opcode, findOp(str[0]));
char *bin;
if (!strcmp(res->Mnemonic, "addiu"))
bin = unDecToBinary(str[3]);
else
bin = decToBinary(str[3]);
strcpy(res->IMM, bin);
free(bin);
if (!strcmp(res->Mnemonic, "addiu"))
res->Imm = strtoul(str[3], NULL, 10);
else
res->Imm = atol(str[3]);
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
}
else if (!strcmp(res->Mnemonic, "lw") || !strcmp(res->Mnemonic, "sw"))
{
uint16_t x = 0;
bool lwLabel = false;
char *trash = calloc(1, sizeof(char)),
offset[50], regi[4];
if (!strcmp(res->Mnemonic, "lw"))
if ((x = findImm(str[2])) != 0)
lwLabel = true;
if (!lwLabel)
{
sscanf(str[2], " %[^(]%c %[^)]", offset, trash, regi);
strcpy(res->rtName, str[1]);
strcpy(res->rsName, regi);
strcpy(res->RT, findReg(str[1]));
strcpy(res->RS, findReg(regi));
strcpy(res->Opcode, findOp(str[0]));
char *bin = decToBinary(offset);
strcpy(res->IMM, bin);
free(bin);
res->Imm = atol(offset);
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
free(trash);
}
else
{
strcpy(res->rtName, str[1]);
strcpy(res->RT, findReg(str[1]));
strcpy(res->Opcode, findOp(str[0]));
strcpy(res->RS, findReg("$zero"));
char *imm = calloc(TARGET_LENGTH, sizeof(char));
snprintf(imm, sizeof(char *), "%d", x);
char *bin = decToBinary(imm);
strcpy(res->IMM, bin);
free(bin);
free(imm);
res->Imm = x;
}
}
else if (!strcmp(res->Mnemonic, "lui"))
{
strcpy(res->rtName, str[1]);
strcpy(res->RT, findReg(str[1]));
strcpy(res->Opcode, findOp(str[0]));
strcpy(res->RS, "00000");
free(res->rsName);
res->rsName = NULL;
char *bin = decToBinary(str[2]);
strcpy(res->IMM, bin);
free(bin);
res->Imm = atol(str[2]);
res->rt = binaryToDec(res->RT);
}
// S-type
else if (!strcmp(res->Mnemonic, "mult"))
{
strcpy(res->rsName, str[1]);
strcpy(res->rtName, str[2]);
strcpy(res->RS, findReg(str[1]));
strcpy(res->RT, findReg(str[2]));
strcpy(res->Funct, findFunc(str[0]));
strcpy(res->Opcode, findOp(str[0]));
strcpy(res->RD, "00000");
res->rs = binaryToDec(res->RS);
res->rt = binaryToDec(res->RT);
}
// J-type
else if (!strcmp(res->Mnemonic, "j"))
{
strcpy(res->Opcode, findOp(str[0]));
int16_t symbolInstructNum = findInstructionNum(str[1]);
if (symbolInstructNum)
symbolInstructNum--;
char *imm = calloc(1, sizeof(char));
snprintf(imm, sizeof(char *), "%d", symbolInstructNum);
char *bin = decToBinary26(imm);
res->Target = bin;
free(imm);
}
free(line);
return res;
}
uint8_t binaryToDec(char *addy)
{
int dec = 0;
while (*addy)
{
dec *= 2;
if (*addy == '1')
dec++;
addy++;
}
return dec;
}
char *findReg(char *inp)
{
int i = -1;
while (registers[++i].mnem)
if (!strcmp(inp, registers[i].mnem))
return registers[i].address;
return NULL;
}
char *findFunc(char *inp)
{
int i = -1;
while (func[++i].mnem)
if (!strcmp(inp, func[i].mnem))
return func[i].funcCode;
return NULL;
}
char *findType(char *inp)
{
int i = -1;
while (type[++i].mnem)
if (!strcmp(inp, type[i].mnem))
return type[i].mType;
return NULL;
}
char *findOp(char *inp)
{
int i = -1;
while (op[++i].mnem)
if (!strcmp(inp, op[i].mnem))
return op[i].opCode;
return NULL;
}
uint16_t findInstructionNum(char *word)
{
int i = -1;
while (textSymbols[++i].key)
if (!strcmp(word, textSymbols[i].key))
return textSymbols[i].instructionNum;
return 0;
}