217 lines
4.5 KiB
C
217 lines
4.5 KiB
C
/* Copyright (c) 2024 Freya Murphy */
|
|
|
|
#ifndef __GEN_H__
|
|
#define __GEN_H__
|
|
|
|
#include <mlimits.h>
|
|
#include <mips.h>
|
|
#include <stdint.h>
|
|
|
|
#include "parse.h"
|
|
#include "tab.h"
|
|
|
|
// predefine
|
|
struct generator;
|
|
|
|
///
|
|
/// a section
|
|
///
|
|
struct section {
|
|
// name
|
|
struct string name;
|
|
|
|
// alignment
|
|
size_t align;
|
|
|
|
// data
|
|
char *data;
|
|
size_t len;
|
|
size_t size;
|
|
|
|
// permissions
|
|
bool read;
|
|
bool write;
|
|
bool execute;
|
|
|
|
/// reference table
|
|
struct reference_table reftab;
|
|
};
|
|
|
|
/* get a section from the generator by name, and return it into res. if the
|
|
* section does not exist, one will be created. */
|
|
int gen_get_section(struct generator *gen, struct section **res,
|
|
struct string *name);
|
|
|
|
/* initalize a section */
|
|
int section_init(struct section *section, struct string *name);
|
|
|
|
/* free a section */
|
|
void section_free(struct section *section);
|
|
|
|
/* extend a section by space bytes plus alignment */
|
|
int section_extend(struct section *section, size_t space);
|
|
|
|
/* push data into a section */
|
|
int section_push(struct section *section, void *data, size_t len);
|
|
|
|
/* push zeros (empty space) to a section */
|
|
int section_zero(struct section *section, size_t len);
|
|
|
|
///
|
|
/// instruction generation state
|
|
///
|
|
|
|
struct gen_ins_state {
|
|
// 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;
|
|
|
|
// cc
|
|
uint16_t cc;
|
|
|
|
// code
|
|
uint32_t code;
|
|
|
|
// pos
|
|
uint32_t pos;
|
|
|
|
// size
|
|
uint32_t size;
|
|
|
|
// hint
|
|
uint32_t hint;
|
|
|
|
// hazard barrier
|
|
bool hb; // 1 bit - 1
|
|
|
|
// target
|
|
uint32_t target;
|
|
|
|
// index(base)
|
|
// offset(base)
|
|
uint32_t index;
|
|
uint16_t offset;
|
|
enum mips32_register base;
|
|
|
|
// current referencd label
|
|
struct string *label;
|
|
};
|
|
|
|
struct gen_ins_override {
|
|
enum mips32_register reg;
|
|
enum mips32_fp_register fpreg;
|
|
uint32_t immd;
|
|
};
|
|
|
|
enum grammer_type {
|
|
// registers
|
|
GMR_RD,
|
|
GMR_RS,
|
|
GMR_RT,
|
|
// 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_HI,
|
|
GMR_LO,
|
|
GMR_TARGET,
|
|
GMR_OFFSET,
|
|
GMR_INDEX_BASE,
|
|
GMR_OFFSET_BASE,
|
|
// len
|
|
__GMR_LEN
|
|
};
|
|
|
|
/* Parses the input string and matches it to a grammer type. Returns
|
|
* the number of characters consumed, or -1 on error.
|
|
*/
|
|
int gen_parse_grammer_type(const char *name, enum grammer_type *res);
|
|
|
|
/* Parses a register name, returing 0 on success, 1 on error*/
|
|
int gen_parse_register(enum mips32_register *reg, struct string *name);
|
|
|
|
/* Parses a floating point register name, returing 0 on success, 1 on error*/
|
|
int gen_parse_fp_register(enum mips32_fp_register *reg, struct string *name);
|
|
|
|
/* Parses the overide expression (after the =) in the dsl for the grammer.
|
|
* returns the number of characters consumed, or -1 on error. */
|
|
int gen_parse_grammer_overide(struct gen_ins_state *state,
|
|
struct gen_ins_override *over, char *value);
|
|
|
|
/* Given a grammer for an instruction, read all args as values into the
|
|
* instruction generator state. */
|
|
int gen_read_grammer_state(struct generator *gen,
|
|
struct expr *const expr,
|
|
struct gen_ins_state *state,
|
|
struct mips32_grammer *grammer);
|
|
|
|
/* Given a grammer for an instruction, and a read state, output multiple
|
|
* instructions into the current section in the generator. note:
|
|
* this write_grammer is different from the read grammer such that
|
|
* it supports paramater reassignment and overides. */
|
|
int gen_write_grammer_state(struct generator *gen,
|
|
struct gen_ins_state *state,
|
|
char *write_grammer);
|
|
|
|
///
|
|
/// generates assembley
|
|
/// from a parser stream
|
|
///
|
|
struct generator {
|
|
struct parser parser;
|
|
|
|
// current instruction table
|
|
size_t instructions_len;
|
|
union mips32_instruction *instructions;
|
|
|
|
// current grammer table
|
|
size_t grammers_len;
|
|
struct mips32_grammer *grammers;
|
|
|
|
// segments
|
|
size_t sections_len;
|
|
size_t sections_size;
|
|
struct section *sections;
|
|
|
|
// current section
|
|
struct section *current;
|
|
|
|
// symbol table
|
|
struct symbol_table symtab;
|
|
};
|
|
|
|
/* output the source code lines for a provided expression */
|
|
void gen_output_expr(struct generator *gen, struct expr *expr);
|
|
|
|
/* 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);
|
|
|
|
/* free a generator */
|
|
void generator_free(struct generator *gen);
|
|
|
|
#endif /* __GEN_H__ */
|