Rewrite: Parse C-type jump field
x1phosura x1phosura@x1phosura.zone
Wed, 08 Feb 2023 01:51:58 -0800
1 files changed,
40 insertions(+),
16 deletions(-)
M
projects/06/assembler2/assembler2.c
→
projects/06/assembler2/assembler2.c
@@ -13,7 +13,7 @@
#define is_symbol_char(c) (('0' <= c && c <= '9') || ('A' <= c && c <= 'Z') \ || ('a' <= c && c <= 'z') || c == '_' || c == '.' \ || c == '$' || c == ':') -#define is_whitespace(c) ((c == ' ' || c == '\t')) +#define is_whitespace(c) ((c == ' ' || c == '\t' || c == '\n')) #define is_number(c) (('0' <= c && c <= '9')) #define MAX_LINE_LEN 256 // TODO: in/excludes NULL terminator?@@ -140,18 +140,20 @@
return add_symbol(label_str, (uint16_t)instruction_offset); } -bool parse_c_type_dest(const char *dest_line, uint16_t *dest) +/* returns dest bits 0b00000ddd + */ +bool parse_c_type_dest(const char *line, uint16_t *dest) { size_t i; uint8_t a_dest = 0, d_dest = 0, m_dest = 0; - for (i = 0; dest_line[i] != '='; ++i) { - switch (dest_line[i]) { + for (i = 0; line[i] != '='; ++i) { + switch (line[i]) { case 'A': ++a_dest; break; case 'D': ++d_dest; break; case 'M': ++m_dest; break; - default: return err("error: invalid destination register " - "'%c'\n", dest_line[i]); + default: return err("syntax error: invalid destination " + "register '%c'\n", line[i]); } if (i >= 3)@@ -159,39 +161,61 @@ return err("error: too many destinations\n");
} if (a_dest > 1) - return err("err: multiple 'A's found in destination\n"); + return err("syntax error: multiple 'A's in destination\n"); if (d_dest > 1) - return err("err: multiple 'D's found in destination\n"); + return err("syntax error: multiple 'D's in destination\n"); if (m_dest > 1) - return err("err: multiple 'M's found in destination\n"); + return err("syntax error: multiple 'M's in destination\n"); *dest = (uint16_t)((a_dest << 2) | (d_dest << 1) | (m_dest)); return true; } -bool parse_c_type_comp(const char *comp_line, uint16_t *comp) +/* returns comp bits 0b0acccccc + */ +bool parse_c_type_comp(const char *line, uint16_t *comp) { // also length check here since it's not being done in parse_c_type() *comp = 0x32; return true; } -bool parse_c_type_jump(const char *jump_line, uint16_t *jump) +/* returns jump bits 0b00000jjj + */ +bool parse_c_type_jump(const char *line, uint16_t *jump) { - // also length check here since it's not being done in parse_c_type() - *jump = 3; - return true; + size_t i; + char jump_str[5]; + char *jump_tb[] = {"", "JGT", "JEQ", "JGE", "JLT", "JNE", "JLE", "JMP"}; + + for (i = 0; i < 5 && !is_whitespace(line[i]) && line[i] != '/'; ++i) + jump_str[i] = line[i]; + + jump_str[i] = '\0'; + if (i > 4) + return err("syntax error: invalid jump field '%s'\n", jump_str); + + for (i = 0; i < (sizeof(jump_tb) / sizeof(jump_tb[0])); ++i) { + if (strncmp(jump_tb[i], jump_str, 3) == 0) { + *jump = (uint16_t)i; + return true; + } + } + + return err("syntax error: invalid jump field '%s'\n", jump_str); } +/* instruction format: 0b111accccccdddjjj + */ bool parse_c_type(const char *line, uint16_t *instruction) { size_t i; char c; const char *dest_start = NULL, *comp_start = NULL, *jump_start = NULL; - uint16_t dest = 0, comp = 0, jump = 0; // TODO: remove, just use instruction + uint16_t dest = 0, comp = 0, jump = 0; c = line[0]; - for (i = 0; !is_whitespace(c) && c != '\n' && c != '\0'; ++i) { + for (i = 0; !is_whitespace(c) && c != '\0'; ++i) { c = line[i]; if (c == '=') { dest_start = &line[0];