diff options
Diffstat (limited to '')
-rw-r--r-- | masm/parse_mips32.c | 872 |
1 files changed, 0 insertions, 872 deletions
diff --git a/masm/parse_mips32.c b/masm/parse_mips32.c deleted file mode 100644 index db7f346..0000000 --- a/masm/parse_mips32.c +++ /dev/null @@ -1,872 +0,0 @@ -#include <mips.h> -#include <mips32.h> -#include <merror.h> -#include <stdint.h> -#include <string.h> -#include <strings.h> - -#include "parse_mips32.h" -#include "parse.h" -#include "mlimits.h" -#include "parse.h" -#include "lex.h" - -/* 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, -}; - -#define FORMAT(ins, format) \ - [MIPS32_INS_##ins] = MIPS32_PARSE_##format, \ - -const enum mips32_parse_format mips32_parse_formats[] = { - FORMAT(ADD, R) - FORMAT(ADDI, I) - FORMAT(ADDIU, I) - FORMAT(ADDU, R) - FORMAT(AND, R) - FORMAT(ANDI, I) - FORMAT(BAL, O16) - FORMAT(BALC, O26) - FORMAT(BC, O26) - FORMAT(BEQ, BE) - FORMAT(BEQL, BE) - FORMAT(BGEZ, BZ) - FORMAT(BGEZAL, BZ) - FORMAT(BGEZALL, BZ) - FORMAT(BGEZL, BZ) - FORMAT(BGTZ, BZ) - FORMAT(BGTZL, BZ) - FORMAT(BLEZ, BZ) - FORMAT(BLEZL, BZ) - FORMAT(BLTZ, BZ) - FORMAT(BLTZAL, BZ) - FORMAT(BLTZALL, BZ) - FORMAT(BLTZL, BZ) - FORMAT(BNE, BE) - FORMAT(BNEL, BE) - FORMAT(DDIV, R2) - FORMAT(DDIVU, R2) - FORMAT(DIV, R2) - FORMAT(DIVU, R2) - FORMAT(J, J) - FORMAT(JAL, J) - FORMAT(JALR, JR) // TODO: handle rd - FORMAT(JALX, J) - FORMAT(JR, JR) - FORMAT(LB, SL) - FORMAT(LBU, SL) - FORMAT(LH, SL) - FORMAT(LHU, SL) - FORMAT(LUI, SLI) - 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(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(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) -}; - -#undef FORMAT - -#define MAX5 32 -#define MAX16 65536 -#define MAX26 67108864 - -static int get_reference(struct parser *parser, uint32_t *offset, - enum reference_type type) -{ - struct token token; - - if (next_token(parser, &token)) - return M_ERROR; - - 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; - } - - 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; - - *offset = 0; - - return M_SUCCESS; -} - -static int get_offset(struct parser *parser, uint32_t *offset) -{ - return get_reference(parser, offset, REF_OFFESET); -} - -static int get_target(struct parser *parser, uint32_t *offset) -{ - 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; -} - -static int is_instruction(const char *ident) -{ - 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; - - 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', - c3 = len > 3 ? token.text[3] : '\0'; - - // $zero - if (c0 == 'z') { - if (c1 == 'e' && c2 == 'r' && c3 == 'o') { - *reg = MIPS32_REG_ZERO; - return M_SUCCESS; - } - } - - // $a0-a3 $at - else if (c0 == 'a') { - if (c1 == 't') { - *reg = MIPS32_REG_AT; - return M_SUCCESS; - } - if (c1 >= '0' && c1 <= '3') { - *reg = MIPS32_REG_A0; - *reg += c1 - '0'; - return M_SUCCESS; - } - } - - // $v0-v1 - else if (c0 == 'v') { - if (c1 >= '0' && c1 <= '1') { - *reg = MIPS32_REG_V0; - *reg += c1 - '0'; - return M_SUCCESS; - } - } - - // $t0-t9 - else if (c0 == 't') { - if (c1 >= '0' && c1 <= '7') { - *reg = MIPS32_REG_T0; - *reg += c1 - '0'; - return M_SUCCESS; - } - // reg T8-T9 are not in order with T0-T7 - if (c1 >= '8' && c1 <= '9') { - *reg = MIPS32_REG_T8; - *reg += c1 - '8'; - return M_SUCCESS; - } - } - - // $s0-s7 $sp - else if (c0 == 's') { - if (c1 >= '0' && c1 <= '7') { - *reg = MIPS32_REG_S0; - *reg += c1 - '0'; - return M_SUCCESS; - } - if (c1 == 'p') { - *reg = MIPS32_REG_SP; - return M_SUCCESS; - } - } - - // $k0-k1 - else if (c0 == 'k') { - if (c1 >= '0' && c1 <= '1') { - *reg = MIPS32_REG_K0; - *reg += c1 - '0'; - return M_SUCCESS; - } - } - - // $gp - else if (c0 == 'g') { - if (c1 == 'p') { - *reg = MIPS32_REG_GP; - return M_SUCCESS; - } - } - - // $fp - else if (c0 == 'f') { - if (c1 == 'p') { - *reg = MIPS32_REG_FP; - return M_SUCCESS; - } - } - - // $rp - else if (c0 == 'r') { - if (c1 == 'p') { - *reg = MIPS32_REG_RA; - return M_SUCCESS; - } - } - - // $0-31 (non aliased register names) - else if (c0 >= '0' && c0 <= '9') { - int i = c0 - '0'; - if (c1 >= '0' && c1 <= '9') { - i *= 10; - i += c1 - '0'; - } - if (i <= 31) { - *reg = i; - return M_SUCCESS; - } - } - - ERROR_POS(token, "unknown register $%s", token.text); - return M_ERROR; -} - -static int parse_instruction_r(struct parser *parser, - struct mips32_instruction *ins) -{ - // format: rs, rt, rd - enum mips32_register reg; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; - - return M_SUCCESS; -} - -static int parse_instruction_r2(struct parser *parser, - struct mips32_instruction *ins) -{ - // format: rs, rt - enum mips32_register reg; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; - - return M_SUCCESS; -} - -static int parse_instruction_rs(struct parser *parser, - struct mips32_instruction *ins) -{ - // format: rs - enum mips32_register reg; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; - - return M_SUCCESS; -} - -static int parse_instruction_rd(struct parser *parser, - struct mips32_instruction *ins) -{ - // format: rd - enum mips32_register reg; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; - - return M_SUCCESS; -} - -static int parse_instruction_i(struct parser *parser, - struct mips32_instruction *ins) -{ - // format: rs, rt, immd - enum mips32_register reg; - struct token token; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; - - 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_NUMBER, &token)) - return M_ERROR; - - if (token.number >= MAX16) - return M_ERROR; - ins->I_data.immd = token.number; - - return M_SUCCESS; -} - -static int parse_instruction_offset(struct parser *parser, - uint32_t max, - struct mips32_instruction *ins) -{ - 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; - } - - return M_SUCCESS; -} - -static int parse_instruction_j(struct parser *parser, - struct mips32_instruction *ins) -{ - uint32_t n; - if (get_target(parser, &n) || n > MAX26) - return M_ERROR; - ins->J_data.target = n; - - return M_SUCCESS; -} - -static int parse_instruction_jr(struct parser *parser, - struct mips32_instruction *ins) -{ - uint32_t n; - if (get_target(parser, &n) || n > MAX26) - return M_ERROR; - ins->J_data.target = n; - - return M_SUCCESS; -} - -static int parse_instruction_branch_equal(struct parser *parser, - struct mips32_instruction *ins) -{ - enum mips32_register reg; - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; - - return M_SUCCESS; -} - -static int parse_instruction_branch(struct parser *parser, - struct mips32_instruction *ins) -{ - enum mips32_register reg; - uint32_t n; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->B_data.rs = reg; - - 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; - - return M_SUCCESS; -} - -static int parse_instruction_sl(struct parser *parser, - struct mips32_instruction *ins) -{ - enum mips32_register reg; - uint32_t offset = 0; - struct token token; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rt = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - 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 (peek_token(parser, &token)) - return M_ERROR; - - 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 (parse_register(parser, ®)) - return M_ERROR; - ins->I_data.rs = reg; - - if (assert_token(parser, TOK_RPAREN, NULL)) - return M_ERROR; - - return M_SUCCESS; -} - -static int parse_instruction_sli(struct parser *parser, - struct mips32_instruction *ins) -{ - enum mips32_register reg; - struct token token; - - 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_NUMBER, &token) || token.number > MAX16) - return M_ERROR; - ins->I_data.immd = token.number; - - return M_SUCCESS; -} - -static int parse_instruction_s(struct parser *parser, - struct mips32_instruction *ins) -{ - enum mips32_register reg; - struct token token; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; - - 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_NUMBER, &token) || token.number > MAX5) - return M_ERROR; - ins->R_data.shamt = token.number; - - return M_SUCCESS; -} - -static int parse_instruction_sv(struct parser *parser, - struct mips32_instruction *ins) -{ - enum mips32_register reg; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rd = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rt = reg; - - if (assert_token(parser, TOK_COMMA, NULL)) - return M_ERROR; - - if (parse_register(parser, ®)) - return M_ERROR; - ins->R_data.rs = reg; - - return M_SUCCESS; -} - -static int parse_instruction(struct parser *parser, - union mips_instruction *ins, - struct token ident) -{ - 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; - } - - 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; - } - - if (res == M_SUCCESS && assert_eol(parser)) - return M_ERROR; - - return res; -} - - -static int parse_directive_align(struct parser *parser, - struct mips32_directive *directive) -{ - 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 > MAX16) { - ERROR_POS(token, "cannot align more than 65kb"); - return M_ERROR; - } - - directive->type = MIPS32_DIRECTIVE_ALIGN; - directive->align = token.number; - - return M_SUCCESS; -} - -static int parse_directive_space(struct parser *parser, - struct mips32_directive *directive) -{ - 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 > MAX16) { - ERROR_POS(token, "cannot reserve more than 65kb"); - return M_ERROR; - } - - directive->type = MIPS32_DIRECTIVE_SPACE; - directive->space = token.number; - - return M_SUCCESS; -} - -static int parse_directive_whb(struct parser *parser, - struct mips32_directive *directive, - enum mips32_directive_type type) -{ - 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: - } - - 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; - - break; - case MIPS32_DIRECTIVE_HALF: - directive->halfs[len++] = token.number; - break; - case MIPS32_DIRECTIVE_BYTE: - directive->bytes[len++] = token.number; - break; - default: - } - - if (peek_token(parser, &token)) - return M_ERROR; - - if (token.type == TOK_COMMA) { - next_token(parser, NULL); - continue; - } - - break; - } - - directive->len = len; - - return M_SUCCESS; -} - -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; - - directive->type = MIPS32_DIRECTIVE_EXTERN; - strcpy(directive->name, token.text); - - return M_SUCCESS; -} - -static int parse_directive_globl(struct parser *parser, - struct mips32_directive *directive) -{ - struct token token; - if (assert_token(parser, TOK_IDENT, &token)) - return M_ERROR; - - directive->type = MIPS32_DIRECTIVE_GLOBL; - strcpy(directive->name, token.text); - - return M_SUCCESS; -} - -static int parse_section(struct mips32_directive *directive, - char name[MAX_LEX_LENGTH]) -{ - directive->type = MIPS32_DIRECTIVE_SECTION; - strcpy(directive->name, name); - - return M_SUCCESS; -} - -static int parse_directive(struct parser *parser, - union mips_directive *directive) -{ - 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 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); -} - -void mips32_parser_init(struct parser *parser) -{ - 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); -} |