mips/masm/parse_mips32.c

873 lines
18 KiB
C
Raw Normal View History

#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 {
2024-09-10 00:48:08 +00:00
// 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) \
2024-09-10 00:48:08 +00:00
[MIPS32_INS_##ins] = MIPS32_PARSE_##format, \
const enum mips32_parse_format mips32_parse_formats[] = {
2024-09-10 00:48:08 +00:00
FORMAT(ADD, R)
FORMAT(ADDI, I)
FORMAT(ADDIU, I)
FORMAT(ADDU, R)
2024-09-10 00:48:08 +00:00
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)
2024-09-10 00:48:08 +00:00
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)
2024-09-10 00:48:08 +00:00
FORMAT(SLT, R)
FORMAT(SLTI, I)
FORMAT(SLTIU, I)
FORMAT(SLTU, R)
FORMAT(SRA, S)
FORMAT(SRAV, SV)
FORMAT(SRL, S)
FORMAT(SRLV, SV)
2024-09-10 00:48:08 +00:00
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,
2024-09-10 00:48:08 +00:00
enum reference_type type)
{
2024-09-10 00:48:08 +00:00
struct token token;
2024-09-10 00:48:08 +00:00
if (next_token(parser, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (token.type == TOK_NUMBER) {
*offset = token.number;
return M_SUCCESS;
}
2024-09-10 00:48:08 +00:00
if (token.type != TOK_IDENT) {
ERROR_POS(token, "unexpected token of type '%s'",
token_str(token.type));
return M_ERROR;
}
2024-09-10 00:48:08 +00:00
struct reference reference = {
.section = parser->sec_tbl.current,
.index = parser->sec_tbl.current->count,
.type = type,
};
strcpy(reference.name, token.text);
2024-09-10 00:48:08 +00:00
if (reftbl_push(&parser->ref_tbl, reference))
return M_ERROR;
2024-09-10 00:48:08 +00:00
*offset = 0;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int get_offset(struct parser *parser, uint32_t *offset)
{
2024-09-10 00:48:08 +00:00
return get_reference(parser, offset, REF_OFFESET);
}
static int get_target(struct parser *parser, uint32_t *offset)
{
2024-09-10 00:48:08 +00:00
return get_reference(parser, offset, REF_TARGET);
}
static int get_instruction(const char *ident, struct mips32_instruction *res)
{
2024-09-10 00:48:08 +00:00
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)
{
2024-09-10 00:48:08 +00:00
return get_instruction(ident, NULL);
}
static int parse_register(struct parser *parser, enum mips32_register *reg)
{
2024-09-10 00:48:08 +00:00
struct token token;
if (assert_token(parser, TOK_REG, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
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) {
2024-09-10 00:48:08 +00:00
*reg = i;
return M_SUCCESS;
}
}
2024-09-10 00:48:08 +00:00
ERROR_POS(token, "unknown register $%s", token.text);
return M_ERROR;
}
static int parse_instruction_r(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
// format: rs, rt, rd
enum mips32_register reg;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rd = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rs = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rt = reg;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_r2(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
// format: rs, rt
enum mips32_register reg;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rs = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rt = reg;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_rs(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
// format: rs
enum mips32_register reg;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rs = reg;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_rd(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
// format: rd
enum mips32_register reg;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rd = reg;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_i(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
// format: rs, rt, immd
enum mips32_register reg;
struct token token;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->I_data.rt = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->I_data.rs = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_NUMBER, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (token.number >= MAX16)
return M_ERROR;
ins->I_data.immd = token.number;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_offset(struct parser *parser,
2024-09-10 00:48:08 +00:00
uint32_t max,
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
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,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
uint32_t n;
if (get_target(parser, &n) || n > MAX26)
return M_ERROR;
ins->J_data.target = n;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_jr(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
uint32_t n;
if (get_target(parser, &n) || n > MAX26)
return M_ERROR;
ins->J_data.target = n;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_branch_equal(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
enum mips32_register reg;
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rs = reg;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_branch(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
enum mips32_register reg;
uint32_t n;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->B_data.rs = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (get_offset(parser, &n) || n > MAX16)
return M_ERROR;
ins->B_data.offset = n;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_sl(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
enum mips32_register reg;
uint32_t offset = 0;
struct token token;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->I_data.rt = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (peek_token(parser, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (token.type != TOK_LPAREN)
if (get_offset(parser, &offset))
return M_ERROR;
ins->I_data.immd = offset;
2024-09-10 00:48:08 +00:00
if (peek_token(parser, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (token.type == TOK_NL) {
ins->I_data.rs = MIPS32_REG_ZERO;
return M_SUCCESS;
}
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_LPAREN, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->I_data.rs = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_RPAREN, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_sli(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
enum mips32_register reg;
struct token token;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->I_data.rt = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX16)
return M_ERROR;
ins->I_data.immd = token.number;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_s(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
enum mips32_register reg;
struct token token;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rd = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rt = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_NUMBER, &token) || token.number > MAX5)
return M_ERROR;
ins->R_data.shamt = token.number;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction_sv(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_instruction *ins)
{
2024-09-10 00:48:08 +00:00
enum mips32_register reg;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rd = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rt = reg;
2024-09-10 00:48:08 +00:00
if (assert_token(parser, TOK_COMMA, NULL))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (parse_register(parser, &reg))
return M_ERROR;
ins->R_data.rs = reg;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_instruction(struct parser *parser,
2024-09-10 00:48:08 +00:00
union mips_instruction *ins,
struct token ident)
{
2024-09-10 00:48:08 +00:00
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,
2024-09-10 00:48:08 +00:00
struct mips32_directive *directive)
{
2024-09-10 00:48:08 +00:00
struct token token;
if (assert_token(parser, TOK_NUMBER, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (token.number < 0) {
ERROR_POS(token, "cannot align negative");
return M_ERROR;
}
2024-09-10 00:48:08 +00:00
if (token.number > MAX16) {
ERROR_POS(token, "cannot align more than 65kb");
return M_ERROR;
}
2024-09-10 00:48:08 +00:00
directive->type = MIPS32_DIRECTIVE_ALIGN;
directive->align = token.number;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_directive_space(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_directive *directive)
{
2024-09-10 00:48:08 +00:00
struct token token;
if (assert_token(parser, TOK_NUMBER, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
if (token.number < 0) {
ERROR_POS(token, "cannot reserve negative");
return M_ERROR;
}
2024-09-10 00:48:08 +00:00
if (token.number > MAX16) {
ERROR_POS(token, "cannot reserve more than 65kb");
return M_ERROR;
}
2024-09-10 00:48:08 +00:00
directive->type = MIPS32_DIRECTIVE_SPACE;
directive->space = token.number;
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_directive_whb(struct parser *parser,
2024-09-10 00:48:08 +00:00
struct mips32_directive *directive,
enum mips32_directive_type type)
{
2024-09-10 00:48:08 +00:00
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;
}
2024-09-10 00:48:08 +00:00
static int parse_directive_extern(struct parser *parser,
struct mips32_directive *directive)
{
2024-09-10 00:48:08 +00:00
struct token token;
if (assert_token(parser, TOK_IDENT, &token))
return M_ERROR;
2024-09-10 00:48:08 +00:00
directive->type = MIPS32_DIRECTIVE_EXTERN;
strcpy(directive->name, token.text);
2024-09-10 00:48:08 +00:00
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);
2024-09-10 00:48:08 +00:00
return M_SUCCESS;
}
static int parse_directive(struct parser *parser,
2024-09-10 00:48:08 +00:00
union mips_directive *directive)
{
2024-09-10 00:48:08 +00:00
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);
}
2024-09-10 00:48:08 +00:00
void mips32_parser_init(struct parser *parser)
{
2024-09-10 00:48:08 +00:00
parser->parse_instruction = parse_instruction;
parser->is_instruction = is_instruction;
parser->parse_directive = parse_directive;
}
void mips32_parser_free(struct parser *parser)
{
2024-09-10 00:48:08 +00:00
parser_free(parser);
}