diff options
Diffstat (limited to 'masm/parse_mips32.c')
-rw-r--r-- | masm/parse_mips32.c | 955 |
1 files changed, 487 insertions, 468 deletions
diff --git a/masm/parse_mips32.c b/masm/parse_mips32.c index 032f115..db7f346 100644 --- a/masm/parse_mips32.c +++ b/masm/parse_mips32.c @@ -14,50 +14,50 @@ /* each instruction has a given parse format * internal to the parser */ enum mips32_parse_format { - // register type: rs, rt, td - MIPS32_PARSE_R, - // register type: rs, rt - MIPS32_PARSE_R2, - // register type: rd - MIPS32_PARSE_RD, - // register type: rs - MIPS32_PARSE_RS, - // imeediate type: rs, rt, immd - MIPS32_PARSE_I, - // jump type: offset - MIPS32_PARSE_J, - // jump type: register - MIPS32_PARSE_JR, - // offset 16b type: offset - MIPS32_PARSE_O16, - // offset 26b type: offset - MIPS32_PARSE_O26, - // breanch equal type: rs, rt, offset - MIPS32_PARSE_BE, - // branch zero type: rs, offset - MIPS32_PARSE_BZ, - // store and load: rt, offset(base) - MIPS32_PARSE_SL, - // store and load immediate: rt, immediate - MIPS32_PARSE_SLI, - // shift: rd, rt, sa - MIPS32_PARSE_S, - // shift variable: rd, rt, rs - MIPS32_PARSE_SV, - // none: - MIPS32_PARSE_NONE, + // register type: rs, rt, td + MIPS32_PARSE_R, + // register type: rs, rt + MIPS32_PARSE_R2, + // register type: rd + MIPS32_PARSE_RD, + // register type: rs + MIPS32_PARSE_RS, + // imeediate type: rs, rt, immd + MIPS32_PARSE_I, + // jump type: offset + MIPS32_PARSE_J, + // jump type: register + MIPS32_PARSE_JR, + // offset 16b type: offset + MIPS32_PARSE_O16, + // offset 26b type: offset + MIPS32_PARSE_O26, + // breanch equal type: rs, rt, offset + MIPS32_PARSE_BE, + // branch zero type: rs, offset + MIPS32_PARSE_BZ, + // store and load: rt, offset(base) + MIPS32_PARSE_SL, + // store and load immediate: rt, immediate + MIPS32_PARSE_SLI, + // shift: rd, rt, sa + MIPS32_PARSE_S, + // shift variable: rd, rt, rs + MIPS32_PARSE_SV, + // none: + MIPS32_PARSE_NONE, }; #define FORMAT(ins, format) \ - [MIPS32_INS_##ins] = MIPS32_PARSE_##format, \ + [MIPS32_INS_##ins] = MIPS32_PARSE_##format, \ const enum mips32_parse_format mips32_parse_formats[] = { - FORMAT(ADD, R) - FORMAT(ADDI, I) + FORMAT(ADD, R) + FORMAT(ADDI, I) FORMAT(ADDIU, I) FORMAT(ADDU, R) - FORMAT(AND, R) - FORMAT(ANDI, I) + FORMAT(AND, R) + FORMAT(ANDI, I) FORMAT(BAL, O16) FORMAT(BALC, O26) FORMAT(BC, O26) @@ -94,34 +94,34 @@ const enum mips32_parse_format mips32_parse_formats[] = { FORMAT(LW, SL) FORMAT(LWL, SL) FORMAT(LWR, SL) - FORMAT(MFHI, RD) - FORMAT(MFLO, RD) - FORMAT(MTHI, RS) - FORMAT(MTLO, RS) - FORMAT(MULT, R2) - FORMAT(MULTU, R2) + FORMAT(MFHI, RD) + FORMAT(MFLO, RD) + FORMAT(MTHI, RS) + FORMAT(MTLO, RS) + FORMAT(MULT, R2) + FORMAT(MULTU, R2) FORMAT(SB, SL) FORMAT(SH, SL) FORMAT(SW, SL) FORMAT(SWL, SL) FORMAT(SLL, S) FORMAT(SLLV, SV) - FORMAT(SLT, R) - FORMAT(SLTI, I) - FORMAT(SLTIU, I) - FORMAT(SLTU, R) + FORMAT(SLT, R) + FORMAT(SLTI, I) + FORMAT(SLTIU, I) + FORMAT(SLTU, R) FORMAT(SRA, S) FORMAT(SRAV, SV) FORMAT(SRL, S) FORMAT(SRLV, SV) - FORMAT(SYSCALL, NONE) - FORMAT(OR, R) - FORMAT(ORI, I) - FORMAT(NOR, R) - FORMAT(SUB, R) - FORMAT(SUBU, R) - FORMAT(XOR, R) - FORMAT(XORI, I) + FORMAT(SYSCALL, NONE) + FORMAT(OR, R) + FORMAT(ORI, I) + FORMAT(NOR, R) + FORMAT(SUB, R) + FORMAT(SUBU, R) + FORMAT(XOR, R) + FORMAT(XORI, I) }; #undef FORMAT @@ -131,75 +131,75 @@ const enum mips32_parse_format mips32_parse_formats[] = { #define MAX26 67108864 static int get_reference(struct parser *parser, uint32_t *offset, - enum reference_type type) + enum reference_type type) { - struct token token; + struct token token; - if (next_token(parser, &token)) - return M_ERROR; + if (next_token(parser, &token)) + return M_ERROR; - if (token.type == TOK_NUMBER) { - *offset = token.number; - return M_SUCCESS; - } + if (token.type == TOK_NUMBER) { + *offset = token.number; + return M_SUCCESS; + } - if (token.type != TOK_IDENT) { - ERROR_POS(token, "unexpected token of type '%s'", - token_str(token.type)); - return M_ERROR; - } + if (token.type != TOK_IDENT) { + ERROR_POS(token, "unexpected token of type '%s'", + token_str(token.type)); + return M_ERROR; + } - struct reference reference = { - .section = parser->sec_tbl.current, - .index = parser->sec_tbl.current->count, - .type = type, - }; - strcpy(reference.name, token.text); + struct reference reference = { + .section = parser->sec_tbl.current, + .index = parser->sec_tbl.current->count, + .type = type, + }; + strcpy(reference.name, token.text); - if (reftbl_push(&parser->ref_tbl, reference)) - return M_ERROR; + if (reftbl_push(&parser->ref_tbl, reference)) + return M_ERROR; - *offset = 0; + *offset = 0; - return M_SUCCESS; + return M_SUCCESS; } static int get_offset(struct parser *parser, uint32_t *offset) { - return get_reference(parser, offset, REF_OFFESET); + return get_reference(parser, offset, REF_OFFESET); } static int get_target(struct parser *parser, uint32_t *offset) { - return get_reference(parser, offset, REF_TARGET); + return get_reference(parser, offset, REF_TARGET); } static int get_instruction(const char *ident, struct mips32_instruction *res) { - for (int i = 0; i < __MIPS32_INS_LEN; i++) { - struct mips32_instruction ins = - mips32_instructions[i]; - if (strcasecmp(ident, ins.name) == 0) { - if (res != NULL) - *res = ins; - return M_SUCCESS; - } - } - return M_ERROR; + for (int i = 0; i < __MIPS32_INS_LEN; i++) { + struct mips32_instruction ins = + mips32_instructions[i]; + if (strcasecmp(ident, ins.name) == 0) { + if (res != NULL) + *res = ins; + return M_SUCCESS; + } + } + return M_ERROR; } static int is_instruction(const char *ident) { - return get_instruction(ident, NULL); + return get_instruction(ident, NULL); } static int parse_register(struct parser *parser, enum mips32_register *reg) { - struct token token; - if (assert_token(parser, TOK_REG, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_REG, &token)) + return M_ERROR; - int len = strlen(token.text); + int len = strlen(token.text); int c0 = len > 0 ? token.text[0] : '\0', c1 = len > 1 ? token.text[1] : '\0', c2 = len > 2 ? token.text[2] : '\0', @@ -304,550 +304,569 @@ static int parse_register(struct parser *parser, enum mips32_register *reg) i += c1 - '0'; } if (i <= 31) { - *reg = i; - return M_SUCCESS; - } + *reg = i; + return M_SUCCESS; + } } - ERROR_POS(token, "unknown register $%s", token.text); + ERROR_POS(token, "unknown register $%s", token.text); return M_ERROR; } static int parse_instruction_r(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs, rt, rd - enum mips32_register reg; + // format: rs, rt, rd + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_r2(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs, rt - enum mips32_register reg; + // format: rs, rt + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_rs(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs - enum mips32_register reg; + // format: rs + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_rd(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rd - enum mips32_register reg; + // format: rd + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_i(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - // format: rs, rt, immd - enum mips32_register reg; - struct token token; + // format: rs, rt, immd + enum mips32_register reg; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; - if (token.number >= MAX16) - return M_ERROR; - ins->I_data.immd = token.number; + if (token.number >= MAX16) + return M_ERROR; + ins->I_data.immd = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_offset(struct parser *parser, - uint32_t max, - struct mips32_instruction *ins) + uint32_t max, + struct mips32_instruction *ins) { - uint32_t n; - if (get_offset(parser, &n) || n > max) - return M_ERROR; + uint32_t n; + if (get_offset(parser, &n) || n > max) + return M_ERROR; - switch (max) { - case MAX26: - ins->J_data.target = n; - break; - case MAX16: - ins->B_data.offset = n; - break; - } + switch (max) { + case MAX26: + ins->J_data.target = n; + break; + case MAX16: + ins->B_data.offset = n; + break; + } - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_j(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - uint32_t n; - if (get_target(parser, &n) || n > MAX26) - return M_ERROR; - ins->J_data.target = n; + uint32_t n; + if (get_target(parser, &n) || n > MAX26) + return M_ERROR; + ins->J_data.target = n; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_jr(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - uint32_t n; - if (get_target(parser, &n) || n > MAX26) - return M_ERROR; - ins->J_data.target = n; + uint32_t n; + if (get_target(parser, &n) || n > MAX26) + return M_ERROR; + ins->J_data.target = n; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_branch_equal(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + enum mips32_register reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_branch(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - uint32_t n; + enum mips32_register reg; + uint32_t n; - if (parse_register(parser, ®)) - return M_ERROR; - ins->B_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->B_data.rs = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (get_offset(parser, &n) || n > MAX16) - return M_ERROR; - ins->B_data.offset = n; + if (get_offset(parser, &n) || n > MAX16) + return M_ERROR; + ins->B_data.offset = n; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_sl(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - uint32_t offset = 0; - struct token token; + enum mips32_register reg; + uint32_t offset = 0; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (peek_token(parser, &token)) - return M_ERROR; + if (peek_token(parser, &token)) + return M_ERROR; - if (token.type != TOK_LPAREN) - if (get_offset(parser, &offset)) - return M_ERROR; - ins->I_data.immd = offset; + if (token.type != TOK_LPAREN) + if (get_offset(parser, &offset)) + return M_ERROR; + ins->I_data.immd = offset; - if (peek_token(parser, &token)) - return M_ERROR; + if (peek_token(parser, &token)) + return M_ERROR; - if (token.type == TOK_NL) { - ins->I_data.rs = MIPS32_REG_ZERO; - return M_SUCCESS; - } + if (token.type == TOK_NL) { + ins->I_data.rs = MIPS32_REG_ZERO; + return M_SUCCESS; + } - if (assert_token(parser, TOK_LPAREN, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_LPAREN, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rs = reg; - if (assert_token(parser, TOK_RPAREN, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_RPAREN, NULL)) + return M_ERROR; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_sli(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - struct token token; + enum mips32_register reg; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->I_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX16) - return M_ERROR; - ins->I_data.immd = token.number; + if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX16) + return M_ERROR; + ins->I_data.immd = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_s(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; - struct token token; + enum mips32_register reg; + struct token token; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX5) - return M_ERROR; - ins->R_data.shamt = token.number; + if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX5) + return M_ERROR; + ins->R_data.shamt = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction_sv(struct parser *parser, - struct mips32_instruction *ins) + struct mips32_instruction *ins) { - enum mips32_register reg; + enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rd = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rt = reg; - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; + if (assert_token(parser, TOK_COMMA, NULL)) + return M_ERROR; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; + if (parse_register(parser, ®)) + return M_ERROR; + ins->R_data.rs = reg; - return M_SUCCESS; + return M_SUCCESS; } static int parse_instruction(struct parser *parser, - union mips_instruction *ins, - struct token ident) + union mips_instruction *ins, + struct token ident) { - struct mips32_instruction instruction; - enum mips32_parse_format format; - int res = M_SUCCESS; + struct mips32_instruction instruction; + enum mips32_parse_format format; + int res = M_SUCCESS; - if (get_instruction(ident.text, &instruction)) { - ERROR_POS(ident, "unknown instruction '%s'", ident.text); - return M_ERROR; - } + if (get_instruction(ident.text, &instruction)) { + ERROR_POS(ident, "unknown instruction '%s'", ident.text); + return M_ERROR; + } - ins->mips32 = instruction; - format = mips32_parse_formats[instruction.type]; + ins->mips32 = instruction; + format = mips32_parse_formats[instruction.type]; - switch (format) { - case MIPS32_PARSE_R: - res = parse_instruction_r(parser, &ins->mips32); - break; - case MIPS32_PARSE_R2: - res = parse_instruction_r2(parser, &ins->mips32); - break; - case MIPS32_PARSE_RS: - res = parse_instruction_rs(parser, &ins->mips32); - break; - case MIPS32_PARSE_RD: - res = parse_instruction_rd(parser, &ins->mips32); - break; - case MIPS32_PARSE_I: - res = parse_instruction_i(parser, &ins->mips32); - break; - case MIPS32_PARSE_J: - res = parse_instruction_j(parser, &ins->mips32); - break; - case MIPS32_PARSE_JR: - res = parse_instruction_jr(parser, &ins->mips32); - break; - case MIPS32_PARSE_O16: - res = parse_instruction_offset(parser, MAX16, &ins->mips32); - break; - case MIPS32_PARSE_O26: - res = parse_instruction_offset(parser, MAX26, &ins->mips32); - break; - case MIPS32_PARSE_BE: - res = parse_instruction_branch_equal(parser, &ins->mips32); - break; - case MIPS32_PARSE_BZ: - res = parse_instruction_branch(parser, &ins->mips32); - break; - case MIPS32_PARSE_SL: - res = parse_instruction_sl(parser, &ins->mips32); - break; - case MIPS32_PARSE_SLI: - res = parse_instruction_sli(parser, &ins->mips32); - break; - case MIPS32_PARSE_S: - res = parse_instruction_s(parser, &ins->mips32); - break; - case MIPS32_PARSE_SV: - res = parse_instruction_sv(parser, &ins->mips32); - break; - case MIPS32_PARSE_NONE: - res = M_SUCCESS; - break; - } + switch (format) { + case MIPS32_PARSE_R: + res = parse_instruction_r(parser, &ins->mips32); + break; + case MIPS32_PARSE_R2: + res = parse_instruction_r2(parser, &ins->mips32); + break; + case MIPS32_PARSE_RS: + res = parse_instruction_rs(parser, &ins->mips32); + break; + case MIPS32_PARSE_RD: + res = parse_instruction_rd(parser, &ins->mips32); + break; + case MIPS32_PARSE_I: + res = parse_instruction_i(parser, &ins->mips32); + break; + case MIPS32_PARSE_J: + res = parse_instruction_j(parser, &ins->mips32); + break; + case MIPS32_PARSE_JR: + res = parse_instruction_jr(parser, &ins->mips32); + break; + case MIPS32_PARSE_O16: + res = parse_instruction_offset(parser, MAX16, &ins->mips32); + break; + case MIPS32_PARSE_O26: + res = parse_instruction_offset(parser, MAX26, &ins->mips32); + break; + case MIPS32_PARSE_BE: + res = parse_instruction_branch_equal(parser, &ins->mips32); + break; + case MIPS32_PARSE_BZ: + res = parse_instruction_branch(parser, &ins->mips32); + break; + case MIPS32_PARSE_SL: + res = parse_instruction_sl(parser, &ins->mips32); + break; + case MIPS32_PARSE_SLI: + res = parse_instruction_sli(parser, &ins->mips32); + break; + case MIPS32_PARSE_S: + res = parse_instruction_s(parser, &ins->mips32); + break; + case MIPS32_PARSE_SV: + res = parse_instruction_sv(parser, &ins->mips32); + break; + case MIPS32_PARSE_NONE: + res = M_SUCCESS; + break; + } - if (res == M_SUCCESS && assert_eol(parser)) - return M_ERROR; + if (res == M_SUCCESS && assert_eol(parser)) + return M_ERROR; - return res; + return res; } static int parse_directive_align(struct parser *parser, - struct mips32_directive *directive) + struct mips32_directive *directive) { - struct token token; - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; - if (token.number < 0) { - ERROR_POS(token, "cannot align negative"); - return M_ERROR; - } + if (token.number < 0) { + ERROR_POS(token, "cannot align negative"); + return M_ERROR; + } - if (token.number > MAX16) { - ERROR_POS(token, "cannot align more than 65kb"); - return M_ERROR; - } + if (token.number > MAX16) { + ERROR_POS(token, "cannot align more than 65kb"); + return M_ERROR; + } - directive->type = MIPS32_DIRECTIVE_ALIGN; - directive->align = token.number; + directive->type = MIPS32_DIRECTIVE_ALIGN; + directive->align = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_directive_space(struct parser *parser, - struct mips32_directive *directive) + struct mips32_directive *directive) { - struct token token; - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; - if (token.number < 0) { - ERROR_POS(token, "cannot reserve negative"); - return M_ERROR; - } + if (token.number < 0) { + ERROR_POS(token, "cannot reserve negative"); + return M_ERROR; + } - if (token.number > MAX16) { - ERROR_POS(token, "cannot reserve more than 65kb"); - return M_ERROR; - } + if (token.number > MAX16) { + ERROR_POS(token, "cannot reserve more than 65kb"); + return M_ERROR; + } - directive->type = MIPS32_DIRECTIVE_SPACE; - directive->space = token.number; + directive->type = MIPS32_DIRECTIVE_SPACE; + directive->space = token.number; - return M_SUCCESS; + return M_SUCCESS; } static int parse_directive_whb(struct parser *parser, - struct mips32_directive *directive, - enum mips32_directive_type type) + struct mips32_directive *directive, + enum mips32_directive_type type) { - struct token token; - uint32_t size = 0; - uint32_t len = 0; + struct token token; + uint32_t size = 0; + uint32_t len = 0; - switch (type) { - case MIPS32_DIRECTIVE_WORD: - size = UINT32_MAX; - break; - case MIPS32_DIRECTIVE_HALF: - size = UINT16_MAX; - break; - case MIPS32_DIRECTIVE_BYTE: - size = UINT8_MAX; - break; - default: - } + switch (type) { + case MIPS32_DIRECTIVE_WORD: + size = UINT32_MAX; + break; + case MIPS32_DIRECTIVE_HALF: + size = UINT16_MAX; + break; + case MIPS32_DIRECTIVE_BYTE: + size = UINT8_MAX; + break; + default: + } + + directive->type = type; + + while (1) { + if (assert_token(parser, TOK_NUMBER, &token)) + return M_ERROR; + + if (len >= MAX_ARG_LENGTH) { + ERROR_POS(token, "directives cannot be longer than " + "%d arguments", MAX_ARG_LENGTH); + return M_ERROR; + } + + if (token.number > size) { + ERROR_POS(token, "number cannot execede max size of: " + "%d", size); + return M_ERROR; + } + + switch (type) { + case MIPS32_DIRECTIVE_WORD: + directive->words[len++] = token.number; - directive->type = type; + break; + case MIPS32_DIRECTIVE_HALF: + directive->halfs[len++] = token.number; + break; + case MIPS32_DIRECTIVE_BYTE: + directive->bytes[len++] = token.number; + break; + default: + } - while (1) { - if (assert_token(parser, TOK_NUMBER, &token)) - return M_ERROR; + if (peek_token(parser, &token)) + return M_ERROR; - if (len >= MAX_ARG_LENGTH) { - ERROR_POS(token, "directives cannot be longer than " - "%d arguments", MAX_ARG_LENGTH); - return M_ERROR; - } + if (token.type == TOK_COMMA) { + next_token(parser, NULL); + continue; + } - if (token.number > size) { - ERROR_POS(token, "number cannot execede max size of: " - "%d", size); - return M_ERROR; - } + break; + } - switch (type) { - case MIPS32_DIRECTIVE_WORD: - directive->words[len++] = token.number; - break; - case MIPS32_DIRECTIVE_HALF: - directive->halfs[len++] = token.number; - break; - case MIPS32_DIRECTIVE_BYTE: - directive->bytes[len++] = token.number; - break; - default: - } + directive->len = len; - if (peek_token(parser, &token)) - return M_ERROR; + return M_SUCCESS; +} - if (token.type == TOK_COMMA) { - next_token(parser, NULL); - continue; - } +static int parse_directive_extern(struct parser *parser, + struct mips32_directive *directive) +{ + struct token token; + if (assert_token(parser, TOK_IDENT, &token)) + return M_ERROR; - break; - } + directive->type = MIPS32_DIRECTIVE_EXTERN; + strcpy(directive->name, token.text); - return M_SUCCESS; + return M_SUCCESS; } -static int parse_section(struct parser *parser, - struct mips32_directive *directive, - char name[MAX_LEX_LENGTH]) +static int parse_directive_globl(struct parser *parser, + struct mips32_directive *directive) { - directive->type = MIPS32_DIRECTIVE_SECTION; - strcpy(directive->name, name); + struct token token; + if (assert_token(parser, TOK_IDENT, &token)) + return M_ERROR; + + directive->type = MIPS32_DIRECTIVE_GLOBL; + strcpy(directive->name, token.text); - struct section *sec; - if (sectbl_get(&parser->sec_tbl, &sec, name) == M_SUCCESS) { - parser->sec_tbl.current = sec; - return M_SUCCESS; - } + return M_SUCCESS; +} - if (sectbl_alloc(&parser->sec_tbl, &sec, name)) - return M_ERROR; +static int parse_section(struct mips32_directive *directive, + char name[MAX_LEX_LENGTH]) +{ + directive->type = MIPS32_DIRECTIVE_SECTION; + strcpy(directive->name, name); - parser->sec_tbl.current = sec; - return M_SUCCESS; + return M_SUCCESS; } static int parse_directive(struct parser *parser, - union mips_directive *directive) + union mips_directive *directive) { - struct token token; - if (assert_token(parser, TOK_DIRECTIVE, &token)) - return M_ERROR; + struct token token; + if (assert_token(parser, TOK_DIRECTIVE, &token)) + return M_ERROR; - // .align n - if (strcmp(token.text, "align") == 0) - return parse_directive_align(parser, &directive->mips32); - else if (strcmp(token.text, "space") == 0) - return parse_directive_space(parser, &directive->mips32); - else if (strcmp(token.text, "word") == 0) - return parse_directive_whb(parser, &directive->mips32, - MIPS32_DIRECTIVE_WORD); - else if (strcmp(token.text, "half") == 0) - return parse_directive_whb(parser, &directive->mips32, - MIPS32_DIRECTIVE_HALF); - else if (strcmp(token.text, "byte") == 0) - return parse_directive_whb(parser, &directive->mips32, - MIPS32_DIRECTIVE_BYTE); - else - return parse_section(parser, &directive->mips32, token.text); + // .align n + if (strcmp(token.text, "align") == 0) + return parse_directive_align(parser, &directive->mips32); + else if (strcmp(token.text, "space") == 0) + return parse_directive_space(parser, &directive->mips32); + else if (strcmp(token.text, "word") == 0) + return parse_directive_whb(parser, &directive->mips32, + MIPS32_DIRECTIVE_WORD); + else if (strcmp(token.text, "half") == 0) + return parse_directive_whb(parser, &directive->mips32, + MIPS32_DIRECTIVE_HALF); + else if (strcmp(token.text, "byte") == 0) + return parse_directive_whb(parser, &directive->mips32, + MIPS32_DIRECTIVE_BYTE); + else if (strcmp(token.text, "extern") == 0) + return parse_directive_extern(parser, &directive->mips32); + else if (strcmp(token.text, "globl") == 0) + return parse_directive_globl(parser, &directive->mips32); + else + return parse_section(&directive->mips32, token.text); } -int mips32_parser_init(struct lexer *lexer, struct parser *parser) +void mips32_parser_init(struct parser *parser) { - if (parser_init(lexer, parser)) - return M_ERROR; - parser->parse_instruction = parse_instruction; - parser->is_instruction = is_instruction; - parser->parse_directive = parse_directive; - return M_SUCCESS; + parser->parse_instruction = parse_instruction; + parser->is_instruction = is_instruction; + parser->parse_directive = parse_directive; } void mips32_parser_free(struct parser *parser) { - parser_free(parser); + parser_free(parser); } |