diff options
Diffstat (limited to 'masm/gen.c')
| -rw-r--r-- | masm/gen.c | 661 |
1 files changed, 10 insertions, 651 deletions
@@ -11,178 +11,9 @@ #include "parse.h" /// -/// section table -/// - -static void section_get_default_perm(struct section *sec, const char *name) -{ - #define __LEN 7 - static const struct perms { - char *name; - bool read; - bool write; - bool execute; - int alignment; - } defaults[__LEN] = { - {".text", true, false, true, 4}, - {".code", true, false, true, 4}, - {".data", true, true, false, 1}, - {".stack", true, true, false, 1}, - {".rodata", true, false, false, 1}, - {".bss", true, true, false, 1}, - {".robss", true, false, false, 1}, - }; - - for (int i = 0; i < __LEN; i++) { - const struct perms *p = &defaults[i]; - if (strcasecmp(name, p->name) != 0) - continue; - sec->read = p->read; - sec->write = p->write; - sec->execute = p->execute; - sec->align = p->alignment; - break; - } - -} - -static int section_get(struct generator *gen, struct section **res, - const struct string *const name) -{ - /// find the section if it exists - for (size_t i = 0; i < gen->sections_len; i++) { - struct section *sec = &gen->sections[i]; - if (sec->name.len != name->len) - continue; - if (strcmp(sec->name.str, name->str) != 0) - continue; - *res = sec; - return M_SUCCESS; - } - - /// allocate a new one if it doesnt - size_t size = gen->sections_size ? gen->sections_size * 2 : 8; - void *new = realloc(gen->sections, size * sizeof(struct section)); - if (new == NULL) { - PERROR("cannot realloc"); - return M_ERROR; - } - - gen->sections_size = size; - gen->sections = new; - - struct section *sec = &gen->sections[gen->sections_len++]; - - // alloc reftab - if (reftab_init(&sec->reftab)) - return M_ERROR; - - // copy name - if (string_clone(&sec->name, name)) - return M_ERROR; - - // set defaults - sec->len = 0; - sec->size = 0; - sec->align = 1; - sec->data = NULL; - sec->read = true; - sec->write = true; - sec->execute = false; - section_get_default_perm(sec, name->str); - - *res = sec; - return M_SUCCESS; -} - -static int section_extend(struct section *section, size_t space) -{ - size_t newlen = section->len + space; - if (newlen < section->size) - return M_SUCCESS; - - size_t size = section->size ? section->size * 2 + newlen : newlen * 2; - void *new = realloc(section->data, size); - if (new == NULL) { - PERROR("cannot realloc"); - return M_ERROR; - } - section->size = size; - section->data = new; - - return M_SUCCESS; -} - -static int section_push(struct section *section, void *data, size_t len) -{ - size_t newlen = section->len + len; - size_t zeros = newlen % section->align; - if (zeros) - zeros = section->align - zeros; - - if (section_extend(section, len + zeros)) - return M_ERROR; - - memset(section->data + section->len, 0, zeros); - memcpy(section->data + section->len + zeros, data, len); - section->len += len + zeros; - - return M_SUCCESS; -} - -static int section_zero(struct section *section, size_t len) -{ - size_t zeros = section->len % section->align; - if (zeros) - zeros = section->align - zeros; - - if (section_extend(section, len + zeros)) - return M_ERROR; - - memset(section->data + section->len, 0, len + zeros); - section->len += len + zeros; - - return M_SUCCESS; -} - -void section_free(struct section *section) -{ - reftab_free(§ion->reftab); - string_free(§ion->name); - free(section->data); -} - -/// /// generation functions /// -static void print_curr_line(struct generator *gen, - const struct expr *const expr) -{ - int line = expr->line_no, - len = expr->byte_end - expr->byte_start, - nl = true, - c = EOF; - FILE *file = gen->parser.lexer.file; - - fseek(file, expr->byte_start, SEEK_SET); - - while (len--) { - c = getc(file); - if (c == EOF || c == '\0') - break; - if (nl) { - fprintf(stderr, "\t%d | ", line); - line++; - nl = false; - } - if (c == '\n') - nl = true; - putc(c, stderr); - } - -} - static int gen_directive_whb(struct generator *gen, const void *data, uint32_t count, uint32_t len) { @@ -265,488 +96,6 @@ static int gen_constant(struct generator *gen, struct expr_const *const expr) return M_ERROR; } -static int parse_register(enum mips32_register *reg, struct string *name) -{ - int len = name->len; - int c0 = len > 0 ? name->str[0] : '\0', - c1 = len > 1 ? name->str[1] : '\0', - c2 = len > 2 ? name->str[2] : '\0', - c3 = len > 3 ? name->str[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 == 'a') { - *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("unknown register $%.*s", name->len, name->str); - return M_ERROR; -} - -static int parse_fp_register(enum mips32_fp_register *reg, struct string *name) -{ - int len = name->len; - int c0 = len > 0 ? name->str[0] : '\0', - c1 = len > 1 ? name->str[1] : '\0', - c2 = len > 2 ? name->str[2] : '\0'; - - *reg = 0; - - if (c0 != 'f') - goto error; - - if (c1 < '0' || c1 > '9') - goto error; - - *reg += c1 - '0'; - - if (c1 == '\0') - return M_SUCCESS; - - if (c2 < '0' || c2 > '9') - goto error; - - *reg *= 10; - *reg += c2 - '0'; - - return M_SUCCESS; - -error: - ERROR("unknown fp register $%.*s", name->len, name->str); - return M_ERROR; - -} - -static enum grammer_type get_gmr_type(const char *name, size_t *len) -{ - #define CHK(part, str) { \ - if (strncasecmp(str, name, strlen(str)) == 0) { \ - *len = strlen(str); \ - return GMR_ ##part; \ - }} \ - - CHK(RD, "rd") - CHK(RS, "rs") - CHK(RT, "rt") - CHK(FS, "fs") - CHK(FT, "ft") - CHK(FD, "fd") - CHK(IMMD, "immd") - CHK(CC, "cc") - CHK(CODE, "code") - CHK(POS, "pos") - CHK(SIZE, "size") - CHK(HB, "hb") - CHK(HINT, "hint") - CHK(OFFSET_BASE, "offset(base)") - CHK(INDEX_BASE, "index(base)") - CHK(OFFSET, "offset") - CHK(TARGET, "target") - CHK(HI, "hi") - CHK(LO, "lo") - - #undef CHK - - BUG("invalid grammer key: %s", name); - exit(1); -} - -static int get_gmr_hc(struct gen_ins_state *state, - struct gen_ins_override *over, - char *value) -{ - int vlen = 0; - int res = M_SUCCESS; - - /* get length of value */ - for (const char *ptr = value; - *ptr != '\0' && *ptr != ','; - ptr++, vlen++); - - /* must be at least of length 1 */ - if (vlen < 1) - return M_ERROR; - - #define VAL(v) if (strncmp(v, value, vlen) == 0) - /* register to register mapping */ - VAL("rd") - over->reg = state->rd; - else VAL("rs") - over->reg = state->rs; - else VAL("rt") - { - over->reg = state->rt; - } - else VAL("fs") - over->fpreg = state->fs; - else VAL("ft") - over->fpreg = state->ft; - else VAL("fd") - over->fpreg = state->fd; - else VAL("immd") - over->immd = state->immd; - else VAL("-immd") - over->immd = -state->immd; - /* hardcoded register */ - else if (*value == '$') { - // register - if (vlen < 2) - return M_ERROR; - struct string name; - name.str = value + 1; - name.len = vlen - 1; - if (*name.str == 'f') - res = parse_fp_register(&over->fpreg, &name); - else - res = parse_register(&over->reg, &name); - /* hardcoded immediate */ - } else { - // immediate - char c; - int immd = 0; - while (c = *(value++), c != ',' && c != '\0') { - if (c < '0' || c > '9') - return M_ERROR; - immd *= 10; - immd += c - '0'; - } - over->immd = immd; - } - - #undef KEY - - return res; -} - -static int gen_ins_read_state(struct generator *gen, - struct expr *const expr, - struct gen_ins_state *state, - struct mips32_grammer *grammer) -{ - char *ptr = grammer->grammer; - uint32_t argi = 0; - - // read values into state - while (*ptr != '\0') { - - if (argi >= expr->instruction.args_len) { - ERROR("not enough arguments passed"); - print_curr_line(gen, expr); - return M_ERROR; - } - struct expr_ins_arg *arg = &expr->instruction.args[argi++]; - - size_t skip; - switch (get_gmr_type(ptr, &skip)) { - case GMR_RD: - // rd - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_register(&state->rd, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_RS: - // rs - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_register(&state->rs, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_RT: - // rt - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_register(&state->rt, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_FS: - // fs - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_fp_register(&state->fs, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_FT: - // ft - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_fp_register(&state->ft, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_FD: - // fd - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_fp_register(&state->fd, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_IMMD: - // immd - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->immd = arg->immd; - break; - case GMR_CC: - // cc - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->cc = arg->immd; - break; - case GMR_CODE: - // code - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->code = arg->immd; - break; - case GMR_POS: - // pos - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->pos = arg->immd; - break; - case GMR_SIZE: - // size - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - // TODO: check valid size - state->size = arg->immd; - break; - case GMR_HB: - // hb - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->hb = !!(arg->immd); - break; - case GMR_HINT: - // hint - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->hint = arg-> immd; - break; - case GMR_OFFSET: - // offset - state->offset = 0; - if (arg->type == EXPR_INS_ARG_IMMEDIATE) - state->offset = arg->immd; - else if (arg->type == EXPR_INS_ARG_LABEL) - state->label = &arg->label; - else { - ERROR("invalid instruction"); - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_OFFSET_BASE: - // offset(base) - if (arg->type != EXPR_INS_ARG_OFFSET) { - ERROR("expected an offset($base)"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->offset = arg->offset.immd; - if (parse_register(&state->base, &arg->offset.reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_INDEX_BASE: - // index(base) - if (arg->type != EXPR_INS_ARG_OFFSET) { - ERROR("expected an index($base)"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->index = arg->offset.immd; - if (parse_register(&state->base, &arg->offset.reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_TARGET: - // target - state->target = 0; - if (arg->type == EXPR_INS_ARG_IMMEDIATE) - state->target = arg->immd; - else if (arg->type == EXPR_INS_ARG_LABEL) - state->label = &arg->label; - else { - ERROR("invalid instruction"); - print_curr_line(gen, expr); - return M_ERROR; - } - break; - default: - break; - } - - // skip entry - ptr += skip; - - // skip comma - if (*ptr == ',') { - ptr++; - continue; - } else if (*ptr == '\0') { - break; - } else { - BUG("invalid grammer '%s'", grammer); - exit(1); - } - - } - - return M_SUCCESS; -} - static int gen_ins_write_state( struct generator *gen, union mips32_instruction ins, // the instruction to modify @@ -1037,6 +386,12 @@ static int generate(struct generator *gen) return M_SUCCESS; } +// +// the following functions set default generator +// state values for different versions of the mips +// isa +// + /* run codegen with the mips32r6 specification */ int generate_mips32r6(struct generator *gen) { @@ -1067,6 +422,10 @@ int generate_mips1(struct generator *gen) return generate(gen); } +// +// constructors and deconstructors +// + int generator_init(const char *file, struct generator *gen) { if (parser_init(file, &gen->parser)) |