Skip to content

Commit

Permalink
feat(zicsr): add zicsr instructions (#41)
Browse files Browse the repository at this point in the history
* feat(zicsr): add zicsr instructions + parser stubs

* fix(zicsr): Add csr files to compilation

* feat: add csr parsers + add some const qualifiers

* fix(test): fix failing test

* fix(msvc): fix msvc warning

* fix(msvc): fix msvc warning +1

* fix: simplify get_immediate function

* feat(zicsr): add csr instruction tests
  • Loading branch information
cyuria authored Jun 14, 2024
1 parent 4b62b1b commit 8f82208
Show file tree
Hide file tree
Showing 11 changed files with 616 additions and 68 deletions.
4 changes: 4 additions & 0 deletions h/form/csr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once
#include "form/instructions.h"

extern const struct formation zicsr[];
2 changes: 2 additions & 0 deletions h/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ arg_parser parse_jr;
arg_parser parse_ftso;
arg_parser parse_al;
arg_parser parse_as;
arg_parser parse_csr;
arg_parser parse_csri;

int parse_asm(const char *, struct sectionpos);
2 changes: 2 additions & 0 deletions h/registers.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <stdlib.h>
#include <stdint.h>

extern const char *reg_abi_map[];
extern const char *float_reg_abi_map[];
Expand All @@ -9,3 +10,4 @@ size_t get_register_id(const char *);
size_t get_float_register_id(const char *);

int get_immediate(const char *, size_t *);
uint16_t get_csr(const char *);
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ sources = files(
'src/elf/output.c',
'src/form/atomic.c',
'src/form/base.c',
'src/form/csr.c',
'src/form/generic.c',
'src/form/instructions.c',
'src/generation.c',
Expand Down
16 changes: 16 additions & 0 deletions src/form/csr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

#include "form/csr.h"

#include "form/generic.h"
#include "parse.h"

const struct formation zicsr[] = {
{ "csrrw", &form_itype, &parse_csr, { 4, OP_SYSTEM, 0x1, 0 } },
{ "csrrs", &form_itype, &parse_csr, { 4, OP_SYSTEM, 0x2, 0 } },
{ "csrrc", &form_itype, &parse_csr, { 4, OP_SYSTEM, 0x3, 0 } },
{ "csrrwi", &form_itype, &parse_csri, { 4, OP_SYSTEM, 0x5, 0 } },
{ "csrrsi", &form_itype, &parse_csri, { 4, OP_SYSTEM, 0x6, 0 } },
{ "csrrci", &form_itype, &parse_csri, { 4, OP_SYSTEM, 0x7, 0 } },

END_FORMATION
};
4 changes: 3 additions & 1 deletion src/form/instructions.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#include <string.h>

#include "debug.h"
#include "form/generic.h"
#include "form/atomic.h"
#include "form/base.h"
#include "form/csr.h"
#include "form/generic.h"
#include "macros.h"

struct formation parse_form(const char *instruction)
Expand All @@ -20,6 +21,7 @@ struct formation parse_form(const char *instruction)
rv64i,
rv32a,
rv64a,
zicsr,
};
for (size_t i = 0; i < ARRAY_LENGTH(sets); i++) {
while (sets[i]->name) {
Expand Down
102 changes: 89 additions & 13 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "parse.h"

#include <ctype.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

Expand Down Expand Up @@ -78,6 +79,15 @@ static uint32_t expect_imm(char *arg)
return (uint32_t)imm;
}

static uint16_t expect_csr(char *arg)
{
const uint16_t csr = get_csr(arg);
if (csr == 0xFFFF)
logger(ERROR, error_instruction_other,
"Expected valid control/status register but got %s", arg);
return csr;
}

static int expect_one_arg(char *first)
{
if (strtok(NULL, ",")) {
Expand Down Expand Up @@ -155,8 +165,8 @@ int parse_asm(const char *linestr, struct sectionpos position)
char *instruction = strtok(line, " \t");
char *argstr = strtok(NULL, "");

struct formation formation = parse_form(instruction);
struct args args = formation.arg_handler(argstr);
const struct formation formation = parse_form(instruction);
const struct args args = formation.arg_handler(argstr);

free(line);

Expand Down Expand Up @@ -203,7 +213,7 @@ struct args parse_rtype(char *argstr)
if (expect_three_args(first, second, third))
return empty_args;

struct args args = {
const struct args args = {
.rd = expect_reg(first),
.rs1 = expect_reg(second),
.rs2 = expect_reg(third),
Expand Down Expand Up @@ -232,7 +242,7 @@ struct args parse_itype(char *argstr)
if (expect_three_args(first, second, third))
return empty_args;

struct args args = {
const struct args args = {
.rd = expect_reg(first),
.rs1 = expect_reg(second),
.imm = expect_imm(third),
Expand Down Expand Up @@ -314,7 +324,7 @@ struct args parse_utype(char *argstr)
if (expect_two_args(first, second))
return empty_args;

struct args args = {
const struct args args = {
.rd = expect_reg(first),
.imm = expect_imm(second),
.sym = NULL,
Expand All @@ -340,7 +350,7 @@ struct args parse_btype(char *argstr)
if (expect_three_args(first, second, third))
return empty_args;

struct args args = {
const struct args args = {
.rs1 = expect_reg(first),
.rs2 = expect_reg(second),
.sym = get_or_create_symbol(third, SYMBOL_LABEL),
Expand All @@ -367,7 +377,7 @@ struct args parse_bztype(char *argstr)
if (expect_two_args(first, second))
return empty_args;

struct args args = {
const struct args args = {
.rs1 = expect_reg(first),
.sym = get_or_create_symbol(second, SYMBOL_LABEL),
};
Expand All @@ -392,7 +402,7 @@ struct args parse_pseudo(char *argstr)
if (expect_two_args(first, second))
return empty_args;

struct args args = {
const struct args args = {
.rd = expect_reg(first),
.rs1 = expect_reg(second),
.sym = NULL,
Expand Down Expand Up @@ -532,6 +542,7 @@ struct args parse_jalr(char *argstr)
.rd = 0x1,
.rs1 = rd,
.imm = 0,
.sym = NULL,
};
}

Expand All @@ -551,7 +562,12 @@ struct args parse_jalr(char *argstr)
logger(DEBUG, no_error, "jalr arguments parsed x%d x%d %d", rd, rs1,
imm);

return (struct args){ .rd = rd, .rs1 = rs1, .imm = imm };
return (struct args){
.rd = rd,
.rs1 = rs1,
.imm = imm,
.sym = NULL,
};
}

struct args parse_la(char *argstr)
Expand All @@ -565,7 +581,7 @@ struct args parse_la(char *argstr)
if (expect_two_args(first, second))
return empty_args;

struct args args = {
const struct args args = {
.rd = expect_reg(first),
.sym = get_or_create_symbol(second, SYMBOL_LABEL),
};
Expand All @@ -589,9 +605,10 @@ struct args parse_li(char *argstr)
if (expect_two_args(first, second))
return empty_args;

struct args args = {
const struct args args = {
.rd = expect_reg(first),
.imm = expect_imm(second),
.sym = NULL,
};

free(first);
Expand All @@ -612,7 +629,7 @@ struct args parse_j(char *argstr)
if (expect_one_arg(first))
return empty_args;

struct args args = {
const struct args args = {
.sym = get_or_create_symbol(first, SYMBOL_LABEL),
};

Expand All @@ -631,8 +648,9 @@ struct args parse_jr(char *argstr)
if (expect_one_arg(first))
return empty_args;

struct args args = {
const struct args args = {
.rs1 = expect_reg(first),
.sym = NULL,
};

free(first);
Expand All @@ -651,6 +669,7 @@ struct args parse_ftso(char *argstr)
.rd = 0x0,
.rs1 = 0x0,
.imm = 0x833,
.sym = NULL,
};

if (!argstr)
Expand Down Expand Up @@ -678,6 +697,7 @@ struct args parse_al(char *argstr)
struct args args = {
.rd = expect_reg(first),
.rs2 = 0,
.sym = NULL,
};

expect_offreg(second, &args.imm, &args.rs1);
Expand Down Expand Up @@ -727,3 +747,59 @@ struct args parse_as(char *argstr)

return args;
}

struct args parse_csr(char *argstr)
{
logger(DEBUG, no_error, "Parsing arguments for csr instruction %s",
argstr);

char *first = trim_arg(argstr);
char *second = trim_arg(NULL);
char *third = trim_arg(NULL);

if (expect_three_args(first, second, third))
return empty_args;

struct args args = {
.rd = expect_reg(first),
.imm = expect_csr(second),
.rs1 = expect_reg(third),
};

free(first);
free(second);
free(third);

logger(DEBUG, no_error, "Registers parsed x%d, x%d, 0x%.03X", args.rd,
args.rs1, args.imm);

return args;
}

struct args parse_csri(char *argstr)
{
logger(DEBUG, no_error, "Parsing arguments for csri instruction %s",
argstr);

char *first = trim_arg(argstr);
char *second = trim_arg(NULL);
char *third = trim_arg(NULL);

if (expect_three_args(first, second, third))
return empty_args;

struct args args = {
.rd = expect_reg(first),
.imm = expect_csr(second),
.rs1 = (uint8_t)(expect_imm(third) & 0x1F),
};

free(first);
free(second);
free(third);

logger(DEBUG, no_error, "Registers parsed x%d, 0x%X, 0x%.03X", args.rd,
args.rs1, args.imm);

return args;
}
Loading

0 comments on commit 8f82208

Please sign in to comment.