Created
April 27, 2017 15:13
-
-
Save crcx/7b491b8e83bd7e78ce7cc3da4d156ff5 to your computer and use it in GitHub Desktop.
Muri: An Alternative Assembler for Nga
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <ctype.h> | |
| #define KiB * 1024 | |
| #define MAX_NAMES 1024 | |
| #define STRING_LEN 64 | |
| int32_t target[128 KiB]; | |
| int32_t here; | |
| char Labels[MAX_NAMES][STRING_LEN]; | |
| int32_t Pointers[MAX_NAMES]; | |
| int32_t np; | |
| void save() { | |
| FILE *fp; | |
| if ((fp = fopen("muri.image", "wb")) == NULL) { | |
| printf("Unable to save the image!\n"); | |
| exit(2); | |
| } | |
| fwrite(&target, sizeof(int32_t), here, fp); | |
| fclose(fp); | |
| } | |
| int32_t lookup(char *name) { | |
| int32_t slice = -1; | |
| int32_t n = np; | |
| while (n > 0) { | |
| n--; | |
| if (strcmp(Labels[n], name) == 0) | |
| slice = Pointers[n]; | |
| } | |
| return slice; | |
| } | |
| void add_label(char *name, int32_t slice) { | |
| if (lookup(name) == -1) { | |
| strcpy(Labels[np], name); | |
| Pointers[np] = slice; | |
| np++; | |
| } else { | |
| printf("Fatal error: %s already defined\n", name); | |
| exit(0); | |
| } | |
| } | |
| void read_line(FILE *file, char *line_buffer) { | |
| if (file == NULL || line_buffer == NULL) | |
| { | |
| printf("Error: file or line buffer pointer is null."); | |
| exit(1); | |
| } | |
| int ch = getc(file); | |
| int count = 0; | |
| while ((ch != '\n') && (ch != EOF)) { | |
| line_buffer[count] = ch; | |
| count++; | |
| ch = getc(file); | |
| } | |
| line_buffer[count] = '\0'; | |
| } | |
| char source[16 KiB]; | |
| int32_t opcode_for(char *s) { | |
| if (strcmp(s, "..") == 0) return 0; if (strcmp(s, "li") == 0) return 1; | |
| if (strcmp(s, "du") == 0) return 2; if (strcmp(s, "dr") == 0) return 3; | |
| if (strcmp(s, "sw") == 0) return 4; if (strcmp(s, "pu") == 0) return 5; | |
| if (strcmp(s, "po") == 0) return 6; if (strcmp(s, "ju") == 0) return 7; | |
| if (strcmp(s, "ca") == 0) return 8; if (strcmp(s, "cc") == 0) return 9; | |
| if (strcmp(s, "re") == 0) return 10; if (strcmp(s, "eq") == 0) return 11; | |
| if (strcmp(s, "ne") == 0) return 12; if (strcmp(s, "lt") == 0) return 13; | |
| if (strcmp(s, "gt") == 0) return 14; if (strcmp(s, "fe") == 0) return 15; | |
| if (strcmp(s, "st") == 0) return 16; if (strcmp(s, "ad") == 0) return 17; | |
| if (strcmp(s, "su") == 0) return 18; if (strcmp(s, "mu") == 0) return 19; | |
| if (strcmp(s, "di") == 0) return 20; if (strcmp(s, "an") == 0) return 21; | |
| if (strcmp(s, "or") == 0) return 22; if (strcmp(s, "xo") == 0) return 23; | |
| if (strcmp(s, "sh") == 0) return 24; if (strcmp(s, "zr") == 0) return 25; | |
| if (strcmp(s, "en") == 0) return 26; | |
| return 0; | |
| } | |
| void pass1(char *fname) { | |
| char *buffer = (char *)source; | |
| char command; | |
| unsigned int opcode; | |
| char inst[3]; | |
| inst[2] = '\0'; | |
| FILE *fp; | |
| here = 0; | |
| fp = fopen(fname, "r"); | |
| if (fp == NULL) | |
| return; | |
| while (!feof(fp)) { | |
| read_line(fp, buffer); | |
| if (buffer[1] != '\t') { | |
| printf("ERROR: Invalid line\n"); | |
| exit(2); | |
| } | |
| command = buffer[0]; | |
| opcode = 0; | |
| switch (command) { | |
| case 'i': memcpy(inst, buffer + 8, 2); | |
| opcode = opcode_for(inst); | |
| opcode = opcode << 8; | |
| memcpy(inst, buffer + 6, 2); | |
| opcode += opcode_for(inst); | |
| opcode = opcode << 8; | |
| memcpy(inst, buffer + 4, 2); | |
| opcode += opcode_for(inst); | |
| opcode = opcode << 8; | |
| memcpy(inst, buffer + 2, 2); | |
| opcode += opcode_for(inst); | |
| target[here++] = opcode; | |
| break; | |
| case 'r': target[here++] = 9999; | |
| break; | |
| case 'd': target[here++] = atoi(buffer+2); | |
| break; | |
| case 'c': target[here++] = buffer[2]; | |
| break; | |
| case 's': printf("String\n"); | |
| break; | |
| case ':': add_label(buffer+2, here); | |
| break; | |
| } | |
| } | |
| fclose(fp); | |
| } | |
| void pass2(char *fname) { | |
| char *buffer = (char *)source; | |
| char command; | |
| FILE *fp; | |
| here = 0; | |
| fp = fopen(fname, "r"); | |
| if (fp == NULL) | |
| return; | |
| while (!feof(fp)) { | |
| read_line(fp, buffer); | |
| if (buffer[1] != '\t') { | |
| printf("ERROR: Invalid line\n"); | |
| exit(2); | |
| } | |
| command = buffer[0]; | |
| switch (command) { | |
| case 'i': here++; | |
| break; | |
| case 'r': target[here++] = lookup(buffer+2); | |
| break; | |
| case 'd': here++; | |
| break; | |
| case 'c': here++; | |
| break; | |
| case 's': break; | |
| case ':': break; | |
| } | |
| } | |
| fclose(fp); | |
| } | |
| int main(int argc, char **argv) { | |
| np = 0; | |
| int i = 1; | |
| if (argc > 1) { | |
| pass1(argv[1]); | |
| pass2(argv[1]); | |
| for(int i = 0; i < here; i++) | |
| printf("%d,", target[i]); | |
| printf("\n"); | |
| for(int i = 0; i < np; i++) | |
| printf("%s,", Labels[i]); | |
| printf("\n"); | |
| save(); | |
| } | |
| else | |
| printf("muri\n(c) 2017 charles childers\n\nTry:\n %s filename\n", argv[0]); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment