Write C-type logic, stub C-type field parsers
x1phosura x1phosura@x1phosura.zone
Wed, 21 Dec 2022 02:52:55 -0800
1 files changed,
133 insertions(+),
7 deletions(-)
M
projects/06/assembler1/assembler1.c
→
projects/06/assembler1/assembler1.c
@@ -13,7 +13,7 @@
#define MAX_LINE_LEN 256 -uint32_t myatoi(const char *a_field_str) +static uint32_t myatoi(const char *a_field_str) { size_t i; uint32_t ret = 0;@@ -25,7 +25,7 @@
return ret; } -bool parse_a_type(const char *line, uint16_t *instruction) +static bool parse_a_type(const char *line, uint16_t *instruction) { char c, a_field_str[6]; // TODO: eventually factor out use of array uint32_t a_field = 0;@@ -71,17 +71,143 @@ *instruction = 0x0000 | (uint16_t) a_field;
return true; // STUB, A-type MSB == 0 anyway } -bool parse_c_type(const char *line, uint16_t *instruction) +/* returns dest bits 0b00000ddd + */ +static bool parse_c_type_dest(const char *dest_line, uint8_t *dest) { - // Note: could do 'jump' fields via lookup tables once - // they're extracted from the line - *instruction = 0x8888; // STUB, TODO implement + DEBUG("dest_line: %s\n", dest_line); + + /* if 'A' + * if 'D' + * if 'M' + * else if '=' + * if 'D' + * if 'M' + * else if '=' + * if 'M' + * if '=' + * default: + * "syntax error" + */ + + *dest = 0x03; // 0b00000011 + return true; +} + +/* returns comp bits 0b0acccccc + */ +static bool parse_c_type_comp(const char *comp_line, uint8_t *comp) +{ + DEBUG("comp_line: %s\n", comp_line); + *comp = 0x53; // 0b01010011 + return true; +} + +/* returns jump bits 0b00000jjj + */ +static bool parse_c_type_jump(const char *jump_line, uint8_t *jump) +{ + // Note: can do 'jump' fields via lookup tables once extracted from line + DEBUG("jump_line: %s\n", jump_line); + + /* if 'J' + * if 'G' + * if 'T' + * if 'E' + * if 'E' + * if 'Q' + * if 'L' + * if 'T' + * if 'E' + * if 'N' + * if 'E' + * if 'M' + * if 'P' + * default: + * "syntax error" + */ + + *jump = 0x01; // 0b00000001 + return true; +} + +/* Instruction format: 0b111accccccdddjjj + * Assumes line begins with actual instruction (prepended whitespace stripped) + */ +static bool parse_c_type(const char *line, uint16_t *instruction) +{ + bool ret; + char c; + char *dest_start = NULL; + char *comp_start = NULL; + char *jump_start = NULL; + size_t i = 0; + uint8_t dest = 0; + uint8_t comp = 0; + uint8_t jump = 0; + + c = line[0]; + for (i = 0; c != ' ' && c != '\t' && + c != '\n' && c != '\0'; ++i) { + c = line[i]; + + if (c == '=') { + if (1 <= i && i <= 3) { + dest_start = &line[0]; // start of line + comp_start = &line[i+1]; // after "[dest]=" + } else { + //syntax error + alert("syntax error: destination field in line" + " incorrectly formatted\n"); + return false; + } + } else if (c == ';') { + if (1 <= i && i <= 7) { + jump_start = &line[i+1]; // after "[comp];" + } else { + //syntax error + alert("syntax error: jump field in line" + " incorrectly formatted\n"); + return false; + } + } + } + + // Only the comp field is mandatory for assembly instructions; + // dest and jump fields are optional, and may/may not be present + if (comp_start == NULL) { + comp_start = &line[0]; // start of line (no dest field) + } + + ret = parse_c_type_comp(comp_start, &comp); + if (!ret) { + return false; + } + + if (dest_start != NULL) { + ret = parse_c_type_dest(dest_start, &dest); + if (!ret) { + return false; + } + } + + if (jump_start != NULL) { + ret = parse_c_type_jump(jump_start, &jump); + if (!ret) { + return false; + } + } + + // STUB: DM=D-M;JGT // 0b111 1010011 011 001 + *instruction = 0xe000 | ((uint16_t)comp << 6) + | ((uint16_t)dest << 3) + | ((uint16_t)jump); return true; } // does not care about line line length; exits at first newline or after // relevant portion parsed (allows for syntactically-incorrect lines, I know) -bool parse_next_instruction(const char *line, uint16_t *instruction) +static bool parse_next_instruction(const char *line, uint16_t *instruction) { bool ret; char c;