commit c2fa47e26498589e4051971fa648478e4595732a
parent b42785d3f3109b72b2f9162b5721fd820985a39c
Author: Paul Longtine <paul@nanner.co>
Date: Thu, 13 Jun 2019 00:25:48 -0400
Hashing out tiny assembler
Diffstat:
2 files changed, 151 insertions(+), 93 deletions(-)
diff --git a/example_assembly.asm b/example_assembly.asm
@@ -0,0 +1,5 @@
+# we're doing asssembly now
+ li 0x34
+sc: cin GRA GRB
+ sp GRA
+ sb GRB
diff --git a/tisc.c b/tisc.c
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <string.h>
+#define TOT_INSTRUCTIONS 15
#define MAX_SYMBOLS 1000
#define MAX_SYMBOL_LEN 100
#define MAX_LINE_LEN 100
@@ -23,92 +24,129 @@ typedef struct InstructionDefintion
int arguements;
int instructionLength;
uint8_t opcode_mask;
- uint8_t* (*assemble)(struct InstructionDefintion, int, int, int);
+ uint8_t** (*assemble)(struct InstructionDefintion, uint8_t*);
} InstructionDefinition_t;
-uint8_t* assemble_default(InstructionDefinition_t definition, int arg0, int arg1, int arg2)
+uint8_t** assemble_default(
+ InstructionDefinition_t definition,
+ uint8_t* arg)
{
- uint8_t return_value[] = { definition.opcode_mask };
+ uint8_t** return_value = (uint8_t**)malloc(sizeof(uint8_t*) * 1);
+
+ return_value[0] = &definition.opcode_mask;
+
return return_value;
}
-InstructionDefinition_t instruction_definitions[1] =
+InstructionDefinition_t definitions[TOT_INSTRUCTIONS] =
{
- { "push", 0, 1, 0x93, assemble_default }
+ { "push", 0, 1, 0x93, assemble_default },
+ { "pop", 0, 1, 0x53, assemble_default },
+ { "pcr", 0, 1, 0xA3, assemble_default },
+ { "li", 1, 2, 0x00, assemble_default },
+ { "lli", 1, 1, 0x03, assemble_default },
+ { "lui", 1, 1, 0x43, assemble_default },
+ { "jmp", 1, 2, 0x83, assemble_default },
+ { "lb", 1, 1, 0x87, assemble_default },
+ { "sb", 1, 1, 0x8B, assemble_default },
+ { "sp", 1, 1, 0x8F, assemble_default },
+ { "cin", 2, 1, 0x02, assemble_default },
+ { "cmp", 2, 1, 0xC3, assemble_default },
+ { "or", 2, 1, 0x00, assemble_default },
+ { "nand", 2, 1, 0x01, assemble_default },
+ { "add", 2, 1, 0x02, assemble_default },
};
int validSymbols = 0;
int addresses[MAX_SYMBOLS];
char symbols[MAX_SYMBOLS][MAX_SYMBOL_LEN];
-char *formats[MAX_INSTYPES][8] =
-{
- // 0 arg instructions
- {
- "push",
- "pop",
- "pcr",
- NULL
- },
- // 1 arg instructions
- {
- "lli",
- "lui",
- "jmp",
- "lb",
- "sb",
- "sp",
- ".fill",
- NULL
- },
- // 2 arg instructions
- {
- "cmp",
- "cin",
- NULL
- },
- // 3 arg instructions
- {
- "add",
- "nand",
- "or",
- NULL
- }
-};
-
-
/* char *parse -> parses file and sets label, opcode, and args
accordingly */
-char *parse(FILE *file, char *line, char **label, char **opcode,
- char **arg0, char **arg1, char **arg2)
+int parse(FILE *file, char *line, char **label, char **opcode,
+ char *arg[3])
{
+ int success = 0;
+
char *str, *first;
str = fgets(line, MAX_LINE_LEN, file);
+
if (str != NULL)
{
first = strtok(line, " \t\n");
if (first == NULL || first[0] == '#')
{
- return parse(file, line, label, opcode, arg0, arg1, arg2);
+ return parse(file, line, label, opcode, arg);
}
else if (first[strlen(first) - 1] == ':')
{
*label = first;
*opcode = strtok(NULL, " \t\n");
first[strlen(first) - 1] = '\0';
+
+ success = 1;
}
else
{
*label = NULL;
*opcode = first;
+
+ success = 1;
+ }
+
+ if (success)
+ {
+ arg[0] = strtok(NULL, " \t\n");
+ arg[1] = strtok(NULL, " \t\n");
+ arg[2] = strtok(NULL, " \t\n");
}
- *arg0 = strtok(NULL, " \t\n");
- *arg1 = strtok(NULL, " \t\n");
- *arg2 = strtok(NULL, " \t\n");
}
- return(str);
+ return success;
+}
+
+int validins(const char *opcode, char *arg[])
+{
+ int status = 0;
+
+ for (int i = 0; i < TOT_INSTRUCTIONS; i++)
+ {
+ // does that instruction label match what we're looking for?
+ if (strcmp(definitions[i].instructionLabel, opcode) == 0)
+ {
+ int supp_args;
+ for (supp_args = 0; supp_args < 3; supp_args++)
+ {
+ if (arg[supp_args] == NULL)
+ {
+ break;
+ }
+ }
+
+ if (definitions[i].arguements > supp_args)
+ {
+ status = 2; // Too few args, fail
+ }
+ else
+ if (definitions[i].arguements < supp_args)
+ {
+ status = 3; // Too many args, fail
+ }
+ else
+ {
+ status = 1; // Success!
+ }
+ break;
+ }
+ }
+
+ return status;
+}
+
+int processins(int op, const char *opcode, char* arg[])
+{
+ return 0;
}
int labelexists(const char *label)
@@ -116,25 +154,43 @@ int labelexists(const char *label)
int i, status = 0;
for (i = 0; i < validSymbols; i++)
- if (strcmp(symbols[i], label) == 0) status = 1;
+ {
+ if (strcmp(symbols[i], label) == 0)
+ {
+ status = 1;
+ }
+ }
return status;
}
-int validins(int op, int format, const char *opcode, char *arg[])
+int process_label(char *label, int address)
{
int status = 0;
- if (strcmp(formats[format][op], opcode) == 0)
+
+ if (label != NULL)
{
- status = 1;
- if (!(format == 0 && arg[0] == NULL && arg[1] == NULL && arg[2] == NULL ||
- format == 1 && arg[0] != NULL && arg[1] == NULL && arg[2] == NULL ||
- format == 2 && arg[0] != NULL && arg[1] != NULL && arg[2] == NULL ||
- format == 3 && arg[0] != NULL && arg[1] != NULL && arg[2] != NULL ))
+ //duplicate label check
+ if (labelexists(label) == 1)
{
- status = 2;
+ printf(
+ "Error:%i: re-use of existing label '%s'\n",
+ address, label );
+ }
+ else
+ {
+ //add label to table 'o' label
+ strcpy(symbols[validSymbols], label);
+ addresses[validSymbols] = address;
+ validSymbols++;
+
+ status = 1;
}
}
+ else
+ {
+ status = 1;
+ }
return status;
}
@@ -142,46 +198,36 @@ int validins(int op, int format, const char *opcode, char *arg[])
/* int preprocess -> 1st pass over file, links symbols to address
and reports syntax errors, fails if returns -1 */
int preprocess(int address, char *label, char *opcode,
- char *arg0, char *arg1, char *arg2)
+ char *arg[3])
{
+
int i,op;
int status = 0;
- // arguement check
- for (i = 0; (i < MAX_INSTYPES) && status == 0; i++)
- {
- for (op = 0; (formats[i][op] != NULL) && status == 0; op++)
- {
- char *args[3] = {arg0, arg1, arg2};
- status = validins(op, i, opcode, args);
- }
- }
+ status = validins(opcode, arg);
switch (status)
{
case 0:
- printf("Error:%i: instruction '%s' does not exist\n",address, opcode);
- status = 1;
+ printf("Error:%i: instruction '%s' does not exist\n",
+ address, opcode);
+ status = 0;
break;
case 2:
- printf("Error:%i: not enough arguements for '%s'\n",address, opcode);
- status = 1;
+ printf("Error:%i: too few arguements for '%s'\n",
+ address, opcode);
+ status = 0;
+ break;
+ case 3:
+ printf("Error:%i: too many arguements for '%s'\n",
+ address, opcode);
+ status = 0;
break;
}
- //duplicate label check
- if (label != NULL)
+ if (status == 1)
{
- if (labelexists(label) == 1)
- {
- printf("Error:%i: label exists '%s'\n",address, label);
- }
- else
- {
- strcpy(symbols[validSymbols], label);
- addresses[validSymbols] = address;
- validSymbols++;
- }
+ status = process_label(label, address);
}
return status;
@@ -191,7 +237,7 @@ int preprocess(int address, char *label, char *opcode,
machine code with symbols filled in as adresses,
fails if returns -1 */
int process(int address, FILE *outfile, char *label, char *opcode,
- char *arg0, char *arg1, char *arg2)
+ char *arg[3])
{
return 0;
}
@@ -201,20 +247,20 @@ int main(int argc, char *argv[])
if (argc != 3)
{
fprintf(stderr,
- "error useage: %s <assembly-code-file> <machine-code-file> \n", argv[0]);
+ "do: %s <assembly-code-file> <machine-code-file> \n",
+ argv[0]);
+
exit(1);
}
char *input, *output;
FILE *inputf, *outputf;
- char *labels, *opcodes, *args0, *args1, *args2;
- char lines[MAX_LINE_LEN + 1];
+ char *labels, *opcodes, *args[3];
+ char line[MAX_LINE_LEN + 1];
int address = 0;
input = argv[1];
- output = argv[2];
inputf = fopen(input, "r");
- outputf = fopen(output, "w");
if (inputf == NULL)
{
@@ -222,26 +268,33 @@ int main(int argc, char *argv[])
exit(1);
}
+ output = argv[2];
+ outputf = fopen(output, "w");
+
if (outputf == NULL)
{
fprintf(stderr, "Error opening file '%s'", output);
exit(1);
}
- while (parse(inputf, lines, &labels, &opcodes, &args0, &args1, &args2) != NULL)
+ while (parse(inputf, line, &labels, &opcodes, args) == 1)
{
- if (preprocess(address, labels, opcodes, args0, args1, args2) == 0)
+ if (preprocess(address, labels, opcodes, args) == 0)
+ {
exit(1);
+ }
address++;
}
rewind(inputf);
address = 0;
- while (parse(inputf, lines, &labels, &opcodes, &args0, &args1, &args2) != NULL)
+ while (parse(inputf, line, &labels, &opcodes, args) == 1)
{
- if (process(address, outputf, labels, opcodes, args0, args1, args2) == 0)
+ if (process(address, outputf, labels, opcodes, args) == 0)
+ {
exit(1);
+ }
address++;
}