summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-10-09 12:07:27 -0400
committerFreya Murphy <freya@freyacat.org>2024-10-09 12:07:27 -0400
commit55137aee817fb97aefabbe2a69930d968533458c (patch)
tree2426bf94154c6a4a2847db5c3f216c70a96b21fb
parentadd bug logging fn (diff)
downloadmips-55137aee817fb97aefabbe2a69930d968533458c.tar.gz
mips-55137aee817fb97aefabbe2a69930d968533458c.tar.bz2
mips-55137aee817fb97aefabbe2a69930d968533458c.zip
update generator to support multipe isas, expand grammer syntax
-rw-r--r--masm/gen.c381
-rw-r--r--masm/gen.h58
2 files changed, 383 insertions, 56 deletions
diff --git a/masm/gen.c b/masm/gen.c
index ba6960b..c4a15a0 100644
--- a/masm/gen.c
+++ b/masm/gen.c
@@ -1,7 +1,9 @@
#include <stdlib.h>
#include <merror.h>
#include <melf.h>
-#include <mips32.h>
+#include <mips.h>
+#include <mips1.h>
+#include <mips32r2.h>
#include <mips32r6.h>
#include "tab.h"
@@ -263,30 +265,6 @@ static int gen_constant(struct generator *gen, struct expr_const *const expr)
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(IMMD, "immd")
- CHK(OFFSET_BASE, "offset(base)")
- CHK(OFFSET, "offset")
- CHK(TARGET, "target")
- CHK(HI, "hi")
- CHK(LO, "lo")
-
- #undef CHK
-
- ERROR("!!! BUG: this should never hit !!!");
- exit(1);
-}
-
static int parse_register(enum mips32_register *reg, struct string *name)
{
int len = name->len;
@@ -403,6 +381,141 @@ static int parse_register(enum mips32_register *reg, struct string *name)
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,
@@ -459,6 +572,42 @@ static int gen_ins_read_state(struct generator *gen,
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) {
@@ -468,6 +617,61 @@ static int gen_ins_read_state(struct generator *gen,
}
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;
@@ -494,6 +698,19 @@ static int gen_ins_read_state(struct generator *gen,
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;
@@ -521,7 +738,7 @@ static int gen_ins_read_state(struct generator *gen,
} else if (*ptr == '\0') {
break;
} else {
- ERROR("!! BUG3: invalid splitting char %c !!!", *ptr);
+ BUG("invalid grammer '%s'", grammer);
exit(1);
}
@@ -536,27 +753,31 @@ static int gen_ins_write_state(
struct gen_ins_state *state, // the current read state
char *grammer) // the gramemr to parse
{
+ // grammer pointer
char *ptr = grammer;
+
+ // new reference type if needed
enum reference_type reftype = REF_NONE;
+ // hardcoded
+ struct gen_ins_override hstate;
+ bool hc = false;
+
// read values into state
while (*ptr != '\0') {
-
// parse next dsl entry
size_t skip;
enum grammer_type gmr = get_gmr_type(ptr, &skip);
// check for dsl hardcoded register argument
- bool hardcoded = false;
- enum mips32_register hard_reg;
+ hc = false;
if (*(ptr + skip) == '=') {
- // parse argument
- char *rptr = ptr + skip + 2;
- hardcoded = true;
- struct string regname;
- string_bss(&regname, rptr);
- if (parse_register(&hard_reg, &regname)) {
- ERROR("!!! BUG2: this should never hit !!!");
+ // get value pointer
+ char *value = ptr + skip + 1;
+ hc = true;
+ // parse value
+ if (get_gmr_hc(state, &hstate, value)) {
+ BUG("invalid grammer: %s", grammer);
exit(1);
}
}
@@ -568,16 +789,43 @@ static int gen_ins_write_state(
switch (gmr) {
case GMR_RD:
- ins.rd = hardcoded ? hard_reg : state->rd;
+ ins.rd = hc ? hstate.reg : state->rd;
break;
case GMR_RS:
- ins.rs = hardcoded ? hard_reg : state->rs;
+ ins.rs = hc ? hstate.reg : state->rs;
break;
case GMR_RT:
- ins.rt = hardcoded ? hard_reg : state->rt;
+ ins.rt = hc ? hstate.reg : state->rt;
+ break;
+ case GMR_FS:
+ ins.fs = hc ? hstate.fpreg : state->fs;
+ break;
+ case GMR_FT:
+ ins.ft = hc ? hstate.fpreg : state->ft;
+ break;
+ case GMR_FD:
+ ins.fd = hc ? hstate.fpreg : state->fd;
break;
case GMR_IMMD:
- ins.immd = state->immd;
+ ins.immd = hc ? hstate.immd : state->immd;
+ break;
+ case GMR_CC:
+ ins.cc = state->cc;
+ break;
+ case GMR_CODE:
+ ins.code = state->code;
+ break;
+ case GMR_POS:
+ ins.shamt = state->pos;
+ break;
+ case GMR_SIZE:
+ ins.rd = state->size ? state->size - 1 : 0;
+ break;
+ case GMR_HB:
+ ins.hb = hc ? hstate.immd : state->hb;
+ break;
+ case GMR_HINT:
+ ins.rt = state->hint;
break;
case GMR_OFFSET:
ins.offset = state->offset;
@@ -588,6 +836,10 @@ static int gen_ins_write_state(
ins.rs = state->base;
reftype = REF_MIPS_16;
break;
+ case GMR_INDEX_BASE:
+ ins.rt = state->index;
+ ins.rs = state->base;
+ break;
case GMR_TARGET:
ins.target = state->target;
reftype = REF_MIPS_26;
@@ -600,8 +852,9 @@ static int gen_ins_write_state(
ins.immd = state->target & 0x0000FFFF;
reftype = REF_MIPS_LO16;
break;
- }
- }
+ break;
+ }
+ }
// get offset for reference (if needed)
uint32_t offset = gen->current->len;
@@ -721,8 +974,8 @@ static int gen_label(struct generator *gen, struct string *const label)
return M_SUCCESS;
}
-/* run codegen */
-static int generate(struct generator *gen)
+/* run codegen for next expression */
+static int generate_next(struct generator *gen)
{
struct expr expr;
int res = M_SUCCESS;
@@ -771,16 +1024,10 @@ static int generate(struct generator *gen)
return res;
}
-/* run codegen with the mips32r6 specification */
-int generate_mips32r6(struct generator *gen)
+static int generate(struct generator *gen)
{
- gen->instructions_len = __MIPS32R6_INS_LEN;
- gen->instructions = mips32r6_instructions;
- gen->grammers_len = __MIPS32R6_GRAMMER_LEN;
- gen->grammers = mips32r6_grammers;
-
int res;
- while (res = generate(gen), 1) {
+ while (res = generate_next(gen), 1) {
if (res == M_ERROR)
return M_ERROR;
if (res == M_EOF)
@@ -790,6 +1037,36 @@ int generate_mips32r6(struct generator *gen)
return M_SUCCESS;
}
+/* run codegen with the mips32r6 specification */
+int generate_mips32r6(struct generator *gen)
+{
+ gen->instructions_len = __MIPS32R6_INS_LEN;
+ gen->instructions = mips32r6_instructions;
+ gen->grammers_len = __MIPS32R6_GRAMMER_LEN;
+ gen->grammers = mips32r6_grammers;
+ return generate(gen);
+}
+
+/* run codegen with the mips32r2 specification */
+int generate_mips32r2(struct generator *gen)
+{
+ gen->instructions_len = __MIPS32R2_INS_LEN;
+ gen->instructions = mips32r2_instructions;
+ gen->grammers_len = __MIPS32R2_GRAMMER_LEN;
+ gen->grammers = mips32r2_grammers;
+ return generate(gen);
+}
+
+/* run codegen with the mips32r6 specification */
+int generate_mips1(struct generator *gen)
+{
+ gen->instructions_len = __MIPS1_INS_LEN;
+ gen->instructions = mips1_instructions;
+ gen->grammers_len = __MIPS1_GRAMMER_LEN;
+ gen->grammers = mips1_grammers;
+ return generate(gen);
+}
+
int generator_init(const char *file, struct generator *gen)
{
if (parser_init(file, &gen->parser))
diff --git a/masm/gen.h b/masm/gen.h
index 19f575c..42fbf50 100644
--- a/masm/gen.h
+++ b/masm/gen.h
@@ -4,7 +4,7 @@
#define __GEN_H__
#include <mlimits.h>
-#include <mips32.h>
+#include <mips.h>
#include <stdint.h>
#include "parse.h"
@@ -44,16 +44,42 @@ void section_free(struct section *section);
///
struct gen_ins_state {
- // rd,rst,rt
+ // rd,rs,rt
enum mips32_register rd;
enum mips32_register rs;
enum mips32_register rt;
+ // fs,ft
+ enum mips32_fp_register fs;
+ enum mips32_fp_register ft;
+ enum mips32_fp_register fd;
+
// immd
- uint16_t immd;
+ uint16_t immd; // 16 bit
+
+ // cc
+ uint16_t cc; // 3 bit
+
+ // code
+ uint32_t code; // 5 bit
+
+ // pos
+ uint32_t pos; // 5 bit
+
+ // size
+ uint32_t size; // 5 bit - 1
+
+ // hb
+ bool hb; // 1 bit - 1
+
+ // index
+ uint32_t index;
+
+ // hint
+ uint32_t hint;
// offset(base)
- uint16_t offset;
+ uint16_t offset; // 16 bit
enum mips32_register base;
// target
@@ -63,15 +89,35 @@ struct gen_ins_state {
struct string *label;
};
+struct gen_ins_override {
+ enum mips32_register reg;
+ enum mips32_fp_register fpreg;
+ uint32_t immd;
+};
+
///
/// grammer type
///
enum grammer_type {
+ // registers
GMR_RD,
GMR_RS,
GMR_RT,
+ GMR_INDEX_BASE,
+ // fp registers
+ GMR_FS,
+ GMR_FT,
+ GMR_FD,
+ // numeric fields
GMR_IMMD,
+ GMR_CC,
+ GMR_CODE,
+ GMR_POS,
+ GMR_SIZE,
+ GMR_HB,
+ GMR_HINT,
+ // addresses
GMR_OFFSET,
GMR_OFFSET_BASE,
GMR_TARGET,
@@ -108,6 +154,10 @@ struct generator {
/* generate the input as mips32r6 */
int generate_mips32r6(struct generator *gen);
+/* run codegen with the mips32r2 specification */
+int generate_mips32r2(struct generator *gen);
+/* run codegen with the mips32r6 specification */
+int generate_mips1(struct generator *gen);
/* initalize a generator */
int generator_init(const char *file, struct generator *gen);