update generator to support multipe isas, expand grammer syntax
This commit is contained in:
parent
94617351ed
commit
55137aee81
2 changed files with 383 additions and 56 deletions
381
masm/gen.c
381
masm/gen.c
|
@ -1,7 +1,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <merror.h>
|
#include <merror.h>
|
||||||
#include <melf.h>
|
#include <melf.h>
|
||||||
#include <mips32.h>
|
#include <mips.h>
|
||||||
|
#include <mips1.h>
|
||||||
|
#include <mips32r2.h>
|
||||||
#include <mips32r6.h>
|
#include <mips32r6.h>
|
||||||
|
|
||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
|
@ -263,30 +265,6 @@ static int gen_constant(struct generator *gen, struct expr_const *const expr)
|
||||||
return M_ERROR;
|
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)
|
static int parse_register(enum mips32_register *reg, struct string *name)
|
||||||
{
|
{
|
||||||
int len = name->len;
|
int len = name->len;
|
||||||
|
@ -403,6 +381,141 @@ static int parse_register(enum mips32_register *reg, struct string *name)
|
||||||
return M_ERROR;
|
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,
|
static int gen_ins_read_state(struct generator *gen,
|
||||||
struct expr *const expr,
|
struct expr *const expr,
|
||||||
struct gen_ins_state *state,
|
struct gen_ins_state *state,
|
||||||
|
@ -459,6 +572,42 @@ static int gen_ins_read_state(struct generator *gen,
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case GMR_IMMD:
|
||||||
// immd
|
// immd
|
||||||
if (arg->type != EXPR_INS_ARG_IMMEDIATE) {
|
if (arg->type != EXPR_INS_ARG_IMMEDIATE) {
|
||||||
|
@ -468,6 +617,61 @@ static int gen_ins_read_state(struct generator *gen,
|
||||||
}
|
}
|
||||||
state->immd = arg->immd;
|
state->immd = arg->immd;
|
||||||
break;
|
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:
|
case GMR_OFFSET:
|
||||||
// offset
|
// offset
|
||||||
state->offset = 0;
|
state->offset = 0;
|
||||||
|
@ -494,6 +698,19 @@ static int gen_ins_read_state(struct generator *gen,
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case GMR_TARGET:
|
||||||
// target
|
// target
|
||||||
state->target = 0;
|
state->target = 0;
|
||||||
|
@ -521,7 +738,7 @@ static int gen_ins_read_state(struct generator *gen,
|
||||||
} else if (*ptr == '\0') {
|
} else if (*ptr == '\0') {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
ERROR("!! BUG3: invalid splitting char %c !!!", *ptr);
|
BUG("invalid grammer '%s'", grammer);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,27 +753,31 @@ static int gen_ins_write_state(
|
||||||
struct gen_ins_state *state, // the current read state
|
struct gen_ins_state *state, // the current read state
|
||||||
char *grammer) // the gramemr to parse
|
char *grammer) // the gramemr to parse
|
||||||
{
|
{
|
||||||
|
// grammer pointer
|
||||||
char *ptr = grammer;
|
char *ptr = grammer;
|
||||||
|
|
||||||
|
// new reference type if needed
|
||||||
enum reference_type reftype = REF_NONE;
|
enum reference_type reftype = REF_NONE;
|
||||||
|
|
||||||
|
// hardcoded
|
||||||
|
struct gen_ins_override hstate;
|
||||||
|
bool hc = false;
|
||||||
|
|
||||||
// read values into state
|
// read values into state
|
||||||
while (*ptr != '\0') {
|
while (*ptr != '\0') {
|
||||||
|
|
||||||
// parse next dsl entry
|
// parse next dsl entry
|
||||||
size_t skip;
|
size_t skip;
|
||||||
enum grammer_type gmr = get_gmr_type(ptr, &skip);
|
enum grammer_type gmr = get_gmr_type(ptr, &skip);
|
||||||
|
|
||||||
// check for dsl hardcoded register argument
|
// check for dsl hardcoded register argument
|
||||||
bool hardcoded = false;
|
hc = false;
|
||||||
enum mips32_register hard_reg;
|
|
||||||
if (*(ptr + skip) == '=') {
|
if (*(ptr + skip) == '=') {
|
||||||
// parse argument
|
// get value pointer
|
||||||
char *rptr = ptr + skip + 2;
|
char *value = ptr + skip + 1;
|
||||||
hardcoded = true;
|
hc = true;
|
||||||
struct string regname;
|
// parse value
|
||||||
string_bss(®name, rptr);
|
if (get_gmr_hc(state, &hstate, value)) {
|
||||||
if (parse_register(&hard_reg, ®name)) {
|
BUG("invalid grammer: %s", grammer);
|
||||||
ERROR("!!! BUG2: this should never hit !!!");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -568,16 +789,43 @@ static int gen_ins_write_state(
|
||||||
|
|
||||||
switch (gmr) {
|
switch (gmr) {
|
||||||
case GMR_RD:
|
case GMR_RD:
|
||||||
ins.rd = hardcoded ? hard_reg : state->rd;
|
ins.rd = hc ? hstate.reg : state->rd;
|
||||||
break;
|
break;
|
||||||
case GMR_RS:
|
case GMR_RS:
|
||||||
ins.rs = hardcoded ? hard_reg : state->rs;
|
ins.rs = hc ? hstate.reg : state->rs;
|
||||||
break;
|
break;
|
||||||
case GMR_RT:
|
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;
|
break;
|
||||||
case GMR_IMMD:
|
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;
|
break;
|
||||||
case GMR_OFFSET:
|
case GMR_OFFSET:
|
||||||
ins.offset = state->offset;
|
ins.offset = state->offset;
|
||||||
|
@ -588,6 +836,10 @@ static int gen_ins_write_state(
|
||||||
ins.rs = state->base;
|
ins.rs = state->base;
|
||||||
reftype = REF_MIPS_16;
|
reftype = REF_MIPS_16;
|
||||||
break;
|
break;
|
||||||
|
case GMR_INDEX_BASE:
|
||||||
|
ins.rt = state->index;
|
||||||
|
ins.rs = state->base;
|
||||||
|
break;
|
||||||
case GMR_TARGET:
|
case GMR_TARGET:
|
||||||
ins.target = state->target;
|
ins.target = state->target;
|
||||||
reftype = REF_MIPS_26;
|
reftype = REF_MIPS_26;
|
||||||
|
@ -600,8 +852,9 @@ static int gen_ins_write_state(
|
||||||
ins.immd = state->target & 0x0000FFFF;
|
ins.immd = state->target & 0x0000FFFF;
|
||||||
reftype = REF_MIPS_LO16;
|
reftype = REF_MIPS_LO16;
|
||||||
break;
|
break;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get offset for reference (if needed)
|
// get offset for reference (if needed)
|
||||||
uint32_t offset = gen->current->len;
|
uint32_t offset = gen->current->len;
|
||||||
|
@ -721,8 +974,8 @@ static int gen_label(struct generator *gen, struct string *const label)
|
||||||
return M_SUCCESS;
|
return M_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* run codegen */
|
/* run codegen for next expression */
|
||||||
static int generate(struct generator *gen)
|
static int generate_next(struct generator *gen)
|
||||||
{
|
{
|
||||||
struct expr expr;
|
struct expr expr;
|
||||||
int res = M_SUCCESS;
|
int res = M_SUCCESS;
|
||||||
|
@ -771,16 +1024,10 @@ static int generate(struct generator *gen)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* run codegen with the mips32r6 specification */
|
static int generate(struct generator *gen)
|
||||||
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;
|
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
while (res = generate(gen), 1) {
|
while (res = generate_next(gen), 1) {
|
||||||
if (res == M_ERROR)
|
if (res == M_ERROR)
|
||||||
return M_ERROR;
|
return M_ERROR;
|
||||||
if (res == M_EOF)
|
if (res == M_EOF)
|
||||||
|
@ -790,6 +1037,36 @@ int generate_mips32r6(struct generator *gen)
|
||||||
return M_SUCCESS;
|
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)
|
int generator_init(const char *file, struct generator *gen)
|
||||||
{
|
{
|
||||||
if (parser_init(file, &gen->parser))
|
if (parser_init(file, &gen->parser))
|
||||||
|
|
58
masm/gen.h
58
masm/gen.h
|
@ -4,7 +4,7 @@
|
||||||
#define __GEN_H__
|
#define __GEN_H__
|
||||||
|
|
||||||
#include <mlimits.h>
|
#include <mlimits.h>
|
||||||
#include <mips32.h>
|
#include <mips.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
@ -44,16 +44,42 @@ void section_free(struct section *section);
|
||||||
///
|
///
|
||||||
|
|
||||||
struct gen_ins_state {
|
struct gen_ins_state {
|
||||||
// rd,rst,rt
|
// rd,rs,rt
|
||||||
enum mips32_register rd;
|
enum mips32_register rd;
|
||||||
enum mips32_register rs;
|
enum mips32_register rs;
|
||||||
enum mips32_register rt;
|
enum mips32_register rt;
|
||||||
|
|
||||||
|
// fs,ft
|
||||||
|
enum mips32_fp_register fs;
|
||||||
|
enum mips32_fp_register ft;
|
||||||
|
enum mips32_fp_register fd;
|
||||||
|
|
||||||
// immd
|
// 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)
|
// offset(base)
|
||||||
uint16_t offset;
|
uint16_t offset; // 16 bit
|
||||||
enum mips32_register base;
|
enum mips32_register base;
|
||||||
|
|
||||||
// target
|
// target
|
||||||
|
@ -63,15 +89,35 @@ struct gen_ins_state {
|
||||||
struct string *label;
|
struct string *label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gen_ins_override {
|
||||||
|
enum mips32_register reg;
|
||||||
|
enum mips32_fp_register fpreg;
|
||||||
|
uint32_t immd;
|
||||||
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// grammer type
|
/// grammer type
|
||||||
///
|
///
|
||||||
|
|
||||||
enum grammer_type {
|
enum grammer_type {
|
||||||
|
// registers
|
||||||
GMR_RD,
|
GMR_RD,
|
||||||
GMR_RS,
|
GMR_RS,
|
||||||
GMR_RT,
|
GMR_RT,
|
||||||
|
GMR_INDEX_BASE,
|
||||||
|
// fp registers
|
||||||
|
GMR_FS,
|
||||||
|
GMR_FT,
|
||||||
|
GMR_FD,
|
||||||
|
// numeric fields
|
||||||
GMR_IMMD,
|
GMR_IMMD,
|
||||||
|
GMR_CC,
|
||||||
|
GMR_CODE,
|
||||||
|
GMR_POS,
|
||||||
|
GMR_SIZE,
|
||||||
|
GMR_HB,
|
||||||
|
GMR_HINT,
|
||||||
|
// addresses
|
||||||
GMR_OFFSET,
|
GMR_OFFSET,
|
||||||
GMR_OFFSET_BASE,
|
GMR_OFFSET_BASE,
|
||||||
GMR_TARGET,
|
GMR_TARGET,
|
||||||
|
@ -108,6 +154,10 @@ struct generator {
|
||||||
|
|
||||||
/* generate the input as mips32r6 */
|
/* generate the input as mips32r6 */
|
||||||
int generate_mips32r6(struct generator *gen);
|
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 */
|
/* initalize a generator */
|
||||||
int generator_init(const char *file, struct generator *gen);
|
int generator_init(const char *file, struct generator *gen);
|
||||||
|
|
Loading…
Reference in a new issue