remove C implementation of riscv

This commit is contained in:
2026-03-08 18:21:43 +01:00
parent 1705cbceeb
commit 31b11028b8
2 changed files with 0 additions and 919 deletions

545
riscv64.c
View File

@@ -1,545 +0,0 @@
// https://docs.riscv.org/reference/isa/unpriv/rv-32-64g.html
// https://riscv.org/wp-content/uploads/2024/12/riscv-calling.pdf
#include "riscv64_dis.h"
#include <gelf.h>
#include <libelf.h>
#define MEMORY_SIZE 20 * 1024 * 1024 // should be enough
const char *const REGS[32] = {
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1", "a0",
"a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5",
"s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"};
Section riscv64_get_code_section(Elf *elf, GElf_Ehdr ehdr) {
size_t str_table_index;
if (elf_getshdrstrndx(elf, &str_table_index) != 0) {
fprintf(stderr, "elf_getshdrstrndx failed: %s\n", elf_errmsg(-1));
exit(1);
}
Elf_Scn *section = NULL;
while ((section = elf_nextscn(elf, section)) != NULL) {
GElf_Shdr header;
if (gelf_getshdr(section, &header) != &header)
continue;
const char *name = elf_strptr(elf, str_table_index, header.sh_name);
if (name && strcmp(name, ".text") == 0) {
return (Section){.offset = header.sh_addr,
.size = header.sh_size,
.entrypoint = ehdr.e_entry};
}
}
fprintf(stderr, "Failed to locate .text\n");
exit(1);
}
RISCV64 riscv64_load(uint8_t *exe_bytes, size_t exe_size) {
uint8_t *memory = calloc(MEMORY_SIZE, 1);
Elf *elf = elf_memory((char *)exe_bytes, exe_size);
GElf_Ehdr ehdr;
gelf_getehdr(elf, &ehdr);
Section text_section = riscv64_get_code_section(elf, ehdr);
for (size_t i = 0; i < ehdr.e_phnum; i++) {
GElf_Phdr phdr;
gelf_getphdr(elf, i, &phdr);
if (phdr.p_type == PT_LOAD) {
memcpy(memory + phdr.p_vaddr, exe_bytes + phdr.p_offset, phdr.p_filesz);
}
}
elf_end(elf);
return (RISCV64){
.memory = memory,
.pc = text_section.offset,
.regs = {0},
.code_section = text_section,
};
}
void riscv64_dump(const RISCV64 *r) {
printf("REGS:");
for (size_t i = 0; i < 32; i++) {
printf(" %lu", r->regs[i]);
}
printf("\n");
}
void riscv64_execute(RISCV64 *r) {
r->pc = r->code_section.entrypoint;
r->regs[2] = MEMORY_SIZE - 1024; // set the stack pointer
while (r->pc < r->code_section.offset + r->code_section.size) {
r->regs[0] = 0; // clear the zero register
uint32_t ins;
memcpy(&ins, r->memory + r->pc, 4);
uint16_t opcode = ins & 0b1111111;
// https://stackoverflow.com/questions/62939410/how-can-i-find-out-the-instruction-format-of-a-risc-v-instruction
switch (opcode) {
case 0b1100011: {
PARSE_B_INS(ins);
if (funct3 == 0b000) { // beq
if (r->regs[rs1] == r->regs[rs2]) {
r->pc += imm;
continue;
}
} else if (funct3 == 0b001) { // bne
if (r->regs[rs1] != r->regs[rs2]) {
r->pc += imm;
continue;
}
} else if (funct3 == 0b101) { // bge
if (r->regs[rs1] >= r->regs[rs2]) {
r->pc += imm;
continue;
}
} else if (funct3 == 0b100) { // blt
if (r->regs[rs1] < r->regs[rs2]) {
r->pc += imm;
continue;
}
} else if (funct3 == 0b110) { // bltu
if ((uint64_t)r->regs[rs1] < (uint64_t)r->regs[rs2]) {
r->pc += imm;
continue;
}
} else {
fprintf(stderr, "B-type: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0010011: {
PARSE_I_INS(ins);
if (funct3 == 0b000) { // addi
r->regs[rd] = r->regs[rs1] + imm;
} else if (funct3 == 0b001) { // slli
uint32_t shamt = (ins >> 20) & 0b111111;
uint32_t funct6 = (ins >> 26) & 0b111111;
if (funct6 == 0b000000) {
r->regs[rd] = r->regs[rs1] << shamt;
} else {
fprintf(stderr, "I-type 1: funct3=001: unrecognized funct6: %b\n",
funct6);
exit(1);
}
} else if (funct3 == 0b011) { // sltiu
r->regs[rd] = ((uint64_t)r->regs[rs1] < (uint64_t)(int64_t)imm) ? 1 : 0;
} else if (funct3 == 0b100) { // xori
r->regs[rd] = r->regs[rs1] ^ imm;
} else if (funct3 == 0b101) {
// of course this one just has to be different
uint32_t shamt = (ins >> 20) & 0b111111;
uint32_t funct6 = (ins >> 26) & 0b111111;
if (funct6 == 0b000000) { // srli
r->regs[rd] = (uint64_t)r->regs[rs1] >> shamt;
} else if (funct6 == 0b010000) { // srai
r->regs[rd] = (int64_t)r->regs[rs1] >> shamt;
} else {
fprintf(stderr, "I-type 1: funct3=101: unrecognized funct6: %b\n",
funct6);
exit(1);
}
} else if (funct3 == 0b111) {
r->regs[rd] = r->regs[rs1] & imm;
} else {
fprintf(stderr, "I-type 1: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0000011: {
PARSE_I_INS(ins);
if (funct3 == 0b000) { // lb
r->regs[rd] = (int8_t)r->memory[r->regs[rs1] + imm];
} else if (funct3 == 0b001) { // lh
r->regs[rd] = *(int16_t *)&r->memory[r->regs[rs1] + imm];
} else if (funct3 == 0b010) { // lw
r->regs[rd] = *(int32_t *)&r->memory[r->regs[rs1] + imm];
} else if (funct3 == 0b011) { // ld
r->regs[rd] = *(uint64_t *)&r->memory[r->regs[rs1] + imm];
} else if (funct3 == 0b100) { // lbu
r->regs[rd] = r->memory[r->regs[rs1] + imm];
} else {
fprintf(stderr, "I-type 2: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b1100111: { // jalr
PARSE_I_INS(ins);
size_t target = (r->regs[rs1] + imm) & ~(size_t)1;
r->regs[rd] = r->pc + 4;
r->pc = target;
continue;
}; break;
case 0b1110011: {
PARSE_I_INS(ins);
if (funct3 == 0b000) {
if (imm == 0) { // ecall
// https://jborza.com/post/2021-05-11-riscv-linux-syscalls/
switch (r->regs[17]) {
case 63: { // read
if (r->regs[10] != 0) {
fprintf(stderr, "read syscall implemented only for stdin.\n");
exit(1);
}
size_t start = r->regs[11];
size_t count = r->regs[12];
size_t bytes_read = 0;
for (size_t i = 0; i < count; i++) {
int c = getchar();
if (c == EOF)
break;
r->memory[start + i] = (uint8_t)c;
bytes_read++;
if (c == '\n')
break;
}
r->regs[10] = bytes_read;
}; break;
case 64: { // write
if (r->regs[10] != 1) {
fprintf(stderr, "write syscall implemented only for stdout.\n");
exit(1);
}
size_t start = r->regs[11];
size_t end = r->regs[11] + r->regs[12];
for (size_t i = start; i < end; i++) {
putchar(r->memory[i]);
}
}; break;
case 93: { // exit
printf("Program exited with code %lu.\n", r->regs[10]);
return;
}; break;
case 169: { // gettimeofday
// TODO: actually return the time
int64_t tv_addr = r->regs[10];
int64_t tz_addr = r->regs[11];
uint8_t tv_buf[16] = {
0xD2, 0x02, 0x96, 0x49,
0x00, 0x00, 0x00, 0x00, // tv_sec = 1234567890
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // tv_usec = 0
};
memcpy(&r->memory[tv_addr], tv_buf, 16);
memset(&r->memory[tz_addr], 0, 8);
r->regs[10] = 0;
}; break;
default:
fprintf(stderr, "Unimplemented syscall: %lu\n", r->regs[17]);
exit(1);
}
break;
} else {
fprintf(stderr, "I-type 4: funct3=000 unrecognized imm: %b\n", imm);
exit(1);
};
break;
} else {
fprintf(stderr, "I-type 4: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b1101111: { // jal
PARSE_J_INS(ins);
r->regs[rd] = r->pc + 4;
r->pc += imm;
continue;
}; break;
case 0b0110011: {
PARSE_R_INS(ins);
if (funct3 == 0b000) {
if (funct7 == 0b0000000) { // add
r->regs[rd] = r->regs[rs1] + r->regs[rs2];
} else if (funct7 == 0b0100000) { // sub
r->regs[rd] = r->regs[rs1] - r->regs[rs2];
} else if (funct7 == 0b0000001) { // mul
r->regs[rd] = r->regs[rs1] * r->regs[rs2];
} else {
fprintf(stderr, "R-type 1: funct3=0b000: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b001) {
if (funct7 == 0b0000001) { // mulh
int64_t a_hi = r->regs[rs1] >> 32;
int64_t b_hi = r->regs[rs2] >> 32;
uint64_t a_lo = (uint32_t)r->regs[rs1];
uint64_t b_lo = (uint32_t)r->regs[rs2];
uint64_t p0 = a_lo * b_lo;
int64_t p1 = a_hi * b_lo;
int64_t p2 = b_hi * a_lo;
int64_t p3 = a_hi * b_hi;
int64_t carry = (p0 >> 32);
int64_t mid = p1 + p2 + carry;
r->regs[rd] = p3 + (mid >> 32);
} else {
fprintf(stderr, "R-type 1: funct3=0b001: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b010) {
if (funct7 == 0b0000000) { // slt
r->regs[rd] = (r->regs[rs1] < r->regs[rs2]) ? 1 : 0;
} else {
fprintf(stderr, "R-type 1: funct3=0b010: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b011) {
if (funct7 == 0b0000000) { // sltu
r->regs[rd] =
((uint64_t)r->regs[rs1] < (uint64_t)r->regs[rs2]) ? 1 : 0;
} else if (funct7 == 0b0000001) { // mulhu
uint64_t a = r->regs[rs1];
uint64_t b = r->regs[rs2];
uint64_t a_lo = a & 0xffffffff;
uint64_t a_hi = a >> 32;
uint64_t b_lo = b & 0xffffffff;
uint64_t b_hi = b >> 32;
uint64_t lo_lo = a_lo * b_lo;
uint64_t hi_lo = a_hi * b_lo;
uint64_t lo_hi = a_lo * b_hi;
uint64_t hi_hi = a_hi * b_hi;
uint64_t mid =
(lo_lo >> 32) + (hi_lo & 0xffffffff) + (lo_hi & 0xffffffff);
r->regs[rd] = hi_hi + (hi_lo >> 32) + (lo_hi >> 32) + (mid >> 32);
} else {
fprintf(stderr, "R-type 1: funct3=0b011: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b100) {
if (funct7 == 0b0000000) { // xor
r->regs[rd] = r->regs[rs1] ^ r->regs[rs2];
} else if (funct7 == 0b0000001) { // div
if (r->regs[rs2] == 0) {
r->regs[rd] = -1;
} else {
r->regs[rd] = r->regs[rs1] / r->regs[rs2];
}
} else {
fprintf(stderr, "R-type 1: funct3=0b100: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b110) {
if (funct7 == 0b0000001) { // rem
if (r->regs[rs2] == 0) {
r->regs[rd] = r->regs[rs1];
} else {
r->regs[rd] = r->regs[rs1] % r->regs[rs2];
}
} else if (funct7 == 0b0000000) { // or
r->regs[rd] = r->regs[rs1] | r->regs[rs2];
} else {
fprintf(stderr, "R-type 1: funct3=0b110: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b111) {
if (funct7 == 0b000) { // and
r->regs[rd] = r->regs[rs1] & r->regs[rs2];
} else if (funct7 == 0b001) { // remu
if (r->regs[rs2] == 0) {
r->regs[rd] = r->regs[rs1];
} else {
r->regs[rd] = (uint64_t)r->regs[rs1] % (uint64_t)r->regs[rs2];
}
} else {
fprintf(stderr, "R-type 1: funct3=0b111: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else {
fprintf(stderr, "R-type 1: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0101111: {
fprintf(stderr, "A extension not implemented yet.\n");
exit(1);
}; break;
case 0b0111011: {
PARSE_R_INS(ins);
if (funct3 == 0b000) {
if (funct7 == 0b0000000) { // addw
r->regs[rd] = (int32_t)(r->regs[rs1] + r->regs[rs2]);
} else if (funct7 == 0b0100000) { // subw
r->regs[rd] = (int32_t)(r->regs[rs1] - r->regs[rs2]);
} else if (funct7 == 0b0000001) { // mulw
r->regs[rd] = (int32_t)(r->regs[rs1] * r->regs[rs2]);
} else {
fprintf(stderr, "R-type 3: funct3=000: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b001) {
if (funct7 == 0b0000000) { // sllw
r->regs[rd] =
(int32_t)(uint32_t)((uint32_t)r->regs[rs1]
<< ((uint32_t)r->regs[rs2] & 0b11111));
} else {
fprintf(stderr, "R-type 3: funct3=001: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b100) { // divw
int32_t a = r->regs[rs1];
int32_t b = r->regs[rs2];
if (b == 0) {
r->regs[rd] = (uint64_t)(int64_t)(-1);
} else {
r->regs[rd] = (int64_t)(a / b);
}
} else if (funct3 == 0b101) {
if (funct7 == 0b0000000) { // srlw
r->regs[rd] = (int32_t)((uint32_t)r->regs[rs1] >>
((uint32_t)r->regs[rs2] & 0b11111));
} else if (funct7 == 0b0100000) { // sraw
r->regs[rd] =
((int32_t)r->regs[rs1]) >> ((uint32_t)r->regs[rs2] & 0b11111);
} else if (funct7 == 0b0000001) { // divuw
if (r->regs[rs2] == 0) {
r->regs[rd] = -1LL;
} else {
r->regs[rd] =
(int32_t)((uint32_t)r->regs[rs1] / (uint32_t)r->regs[rs2]);
}
} else {
fprintf(stderr, "R-type 3: funct3=101: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b111) { // remuw
if (r->regs[rs2] == 0) {
r->regs[rd] = (int32_t)r->regs[rs1];
} else {
r->regs[rd] =
(int32_t)((uint32_t)r->regs[rs1] % (uint32_t)r->regs[rs2]);
}
} else {
fprintf(stderr, "R-type 3: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0011011: {
PARSE_I_INS(ins);
if (funct3 == 0b000) { // addiw
r->regs[rd] = (int32_t)r->regs[rs1] + (int32_t)imm;
} else if (funct3 == 0b001) {
uint32_t shamt = (ins >> 20) & 0b11111;
r->regs[rd] = (int32_t)r->regs[rs1] << shamt;
} else if (funct3 == 0b101) {
PARSE_R_INS(ins);
if (funct7 == 0b0000000) { // srliw
r->regs[rd] = (int32_t)((uint32_t)r->regs[rs1] >> rs2);
} else if (funct7 == 0b0100000) { // sraiw
r->regs[rd] = (int32_t)r->regs[rs1] >> rs2;
} else {
fprintf(stderr, "R-type 4: funct3=101: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else {
fprintf(stderr, "R-type 4: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0100011: {
PARSE_S_INS(ins);
if (funct3 == 0b000) { // sb
size_t addr = r->regs[rs1] + imm;
r->memory[addr] = r->regs[rs2];
} else if (funct3 == 0b001) { // sh
size_t addr = r->regs[rs1] + imm;
*(uint16_t *)(&r->memory[addr]) = r->regs[rs2];
} else if (funct3 == 0b010) { // sw
size_t addr = r->regs[rs1] + imm;
*(uint32_t *)(&r->memory[addr]) = r->regs[rs2];
} else if (funct3 == 0b011) { // sd
size_t addr = r->regs[rs1] + imm;
// take this rust
*(uint64_t *)(&r->memory[addr]) = r->regs[rs2];
} else {
fprintf(stderr, "S-type: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0110111: { // lui
PARSE_U_INS(ins);
r->regs[rd] = (int64_t)(int32_t)(imm << 12);
}; break;
case 0b0010111: { // auipc
PARSE_U_INS(ins);
r->regs[rd] = r->pc + ((int64_t)imm << 12);
}; break;
default:
fprintf(stderr, "Unrecognized opcode: %07b\n", opcode);
exit(1);
}
r->pc += 4;
}
}
int main(int argc, char *argv[]) {
if (elf_version(EV_CURRENT) == EV_NONE) {
fprintf(stderr, "Failed to initialize libelf: %s\n", elf_errmsg(-1));
return 1;
}
const char *path = NULL;
for (int i = 1; i < argc; i++) {
path = argv[i];
}
if (path == NULL) {
fprintf(stderr, "Usage: %s <path>\n", argv[0]);
return 1;
}
FILE *file = fopen(path, "rb");
if (!file) {
fprintf(stderr, "Failed to open %s\n", path);
return 1;
}
uint8_t *exe_bytes = malloc(MEMORY_SIZE);
size_t exe_size = fread(exe_bytes, 1, MEMORY_SIZE, file);
fclose(file);
RISCV64 r = riscv64_load(exe_bytes, exe_size);
free(exe_bytes);
for (r.pc = r.code_section.offset;
r.pc < r.code_section.offset + r.code_section.size; r.pc += 4) {
riscv64_disassemble_one(&r);
}
printf("END DISASSEMBLY\n");
riscv64_execute(&r);
}

View File

@@ -1,374 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PARSE_I_INS(ins) \
uint8_t rd = (ins >> 7) & 0b11111; \
uint8_t funct3 = (ins >> 12) & 0b111; \
uint8_t rs1 = (ins >> 15) & 0b11111; \
int32_t imm = ((int32_t)ins) >> 20
#define PARSE_R_INS(ins) \
uint8_t rd = (ins >> 7) & 0b11111; \
uint8_t funct3 = (ins >> 12) & 0b111; \
uint8_t rs1 = (ins >> 15) & 0b11111; \
uint8_t rs2 = (ins >> 20) & 0b11111; \
int32_t funct7 = ((int32_t)ins) >> 25
#define PARSE_B_INS(ins) \
uint8_t funct3 = (ins >> 12) & 0b111; \
uint8_t rs1 = (ins >> 15) & 0b11111; \
uint8_t rs2 = (ins >> 20) & 0b11111; \
int32_t imm_12 = (ins >> 31) & 0b1; \
int32_t imm_10_5 = (ins >> 25) & 0b111111; \
int32_t imm_4_1 = (ins >> 8) & 0b1111; \
int32_t imm_11 = (ins >> 7) & 0b1; \
int32_t imm = \
(imm_12 << 12) | (imm_11 << 11) | (imm_10_5 << 5) | (imm_4_1 << 1); \
imm = (imm << 19) >> 19
#define PARSE_S_INS(ins) \
uint8_t funct3 = (ins >> 12) & 0b111; \
uint8_t rs1 = (ins >> 15) & 0b11111; \
uint8_t rs2 = (ins >> 20) & 0b11111; \
int32_t imm_11_5 = (ins >> 25) & 0b1111111; \
int32_t imm_4_0 = (ins >> 7) & 0b11111; \
int32_t imm = (imm_11_5 << 5) | imm_4_0; \
imm = (imm << 20) >> 20
#define PARSE_J_INS(ins) \
uint8_t rd = (ins >> 7) & 0b11111; \
int32_t imm_20 = (ins >> 31) & 0b1; \
int32_t imm_10_1 = (ins >> 21) & 0b1111111111; \
int32_t imm_11 = (ins >> 20) & 0b1; \
int32_t imm_19_12 = (ins >> 12) & 0b11111111; \
int32_t imm = \
(imm_20 << 20) | (imm_19_12 << 12) | (imm_11 << 11) | (imm_10_1 << 1); \
imm = (imm << 11) >> 11
#define PARSE_U_INS(ins) \
uint8_t rd = (ins >> 7) & 0b11111; \
int32_t imm = ins >> 12
typedef struct {
size_t offset;
size_t size;
size_t entrypoint;
} Section;
typedef struct {
uint8_t *memory;
size_t pc;
int64_t regs[32];
Section code_section;
} RISCV64;
extern const char *const REGS[32];
void riscv64_disassemble_one(const RISCV64 *r) { // NOLINT
uint32_t ins;
memcpy(&ins, r->memory + r->pc, 4);
uint16_t opcode = ins & 0b1111111;
// https://stackoverflow.com/questions/62939410/how-can-i-find-out-the-instruction-format-of-a-risc-v-instruction
switch (opcode) {
case 0b1100011: {
PARSE_B_INS(ins);
if (funct3 == 0b000) {
printf("beq %s, %s, %d\n", REGS[rs1], REGS[rs2], imm);
} else if (funct3 == 0b001) {
printf("bne %s, %s, %d\n", REGS[rs1], REGS[rs2], imm);
} else if (funct3 == 0b100) {
printf("blt %s, %s, %d\n", REGS[rs1], REGS[rs2], imm);
} else if (funct3 == 0b101) {
printf("bge %s, %s, %d\n", REGS[rs1], REGS[rs2], imm);
} else if (funct3 == 0b110) {
printf("bltu %s, %s, %d\n", REGS[rs1], REGS[rs2], imm);
} else if (funct3 == 0b111) {
printf("bgeu %s, %s, %d\n", REGS[rs1], REGS[rs2], imm);
} else {
fprintf(stderr, "B-type: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0010011: {
PARSE_I_INS(ins);
if (funct3 == 0b000) {
printf("addi %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
} else if (funct3 == 0b001) {
uint32_t shamt = (ins >> 20) & 0b111111;
uint32_t funct6 = (ins >> 26) & 0b111111;
if (funct6 == 0b000000) {
printf("slli %s, %s, %d\n", REGS[rd], REGS[rs1], shamt);
} else {
fprintf(stderr, "I-type 1: funct3=001: unrecognized funct6: %b\n",
funct6);
exit(1);
}
} else if (funct3 == 0b010) {
printf("slti %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
} else if (funct3 == 0b011) {
printf("sltiu %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
} else if (funct3 == 0b100) {
printf("xori %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
} else if (funct3 == 0b101) {
// of course this one just has to be different
uint32_t shamt = (ins >> 20) & 0b111111;
uint32_t funct6 = (ins >> 26) & 0b111111;
if (funct6 == 0b000000) {
printf("srli %s, %s, %d\n", REGS[rd], REGS[rs1], shamt);
} else if (funct6 == 0b010000) {
printf("srai %s, %s, %d\n", REGS[rd], REGS[rs1], shamt);
} else {
fprintf(stderr, "I-type 1: funct3=101: unrecognized funct6: %b\n",
funct6);
exit(1);
}
} else if (funct3 == 0b110) {
printf("ori %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
} else if (funct3 == 0b111) {
printf("andi %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
} else {
fprintf(stderr, "I-type 1: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0000011: {
PARSE_I_INS(ins);
if (funct3 == 0b000) {
printf("lb %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]);
} else if (funct3 == 0b001) {
printf("lh %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]);
} else if (funct3 == 0b010) {
printf("lw %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]);
} else if (funct3 == 0b011) {
printf("ld %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]);
} else if (funct3 == 0b100) {
printf("lbu %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]);
} else if (funct3 == 0b101) {
printf("lhu %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]);
} else if (funct3 == 0b110) {
printf("lwu %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]);
} else {
fprintf(stderr, "I-type 2: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b1100111: {
PARSE_I_INS(ins);
printf("jalr %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
}; break;
case 0b1110011: {
PARSE_I_INS(ins);
if (funct3 == 0b000) {
if (imm == 0) {
printf("ecall\n");
} else {
fprintf(stderr, "I-type 4: funct3=000 unrecognized imm: %b\n", imm);
exit(1);
}
} else {
fprintf(stderr, "I-type 4: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b1101111: {
PARSE_J_INS(ins);
printf("jal %s, %d\n", REGS[rd], imm);
}; break;
case 0b0110011: {
PARSE_R_INS(ins);
if (funct3 == 0b000) {
if (funct7 == 0b0000000) {
printf("add %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0100000) {
printf("sub %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000001) {
printf("mul %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b000: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b001) {
if (funct7 == 0b0000000) {
printf("sll %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000001) {
printf("mulh %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b001: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b010) {
if (funct7 == 0b0000000) {
printf("slt %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b010: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b011) {
if (funct7 == 0b0000000) {
printf("sltu %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000001) {
printf("mulhu %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b011: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b100) {
if (funct7 == 0b0000000) {
printf("xor %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000001) {
printf("div %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b100: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b101) {
if (funct7 == 0b0000000) {
printf("srl %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000001) {
printf("divu %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0100000) {
printf("sra %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b101: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b110) {
if (funct7 == 0b0000001) {
printf("rem %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000000) {
printf("or %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b110: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b111) {
if (funct7 == 0b000) {
printf("and %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b001) {
printf("remu %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 1: funct3=0b111: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else {
fprintf(stderr, "R-type 1: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0101111:
fprintf(stderr, "A extension not implemented yet.\n");
exit(1);
case 0b0111011: {
PARSE_R_INS(ins);
if (funct3 == 0b000) {
if (funct7 == 0b0000000) {
printf("addw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0100000) {
printf("subw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000001) {
printf("mulw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 3: funct3=000: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b001) {
printf("sllw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct3 == 0b100) {
printf("divw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct3 == 0b101) {
if (funct7 == 0b0000000) {
printf("srlw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0100000) {
printf("sraw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b0000001) {
printf("divuw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 3: funct3=101: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else if (funct3 == 0b110) {
printf("remw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct3 == 0b111) {
printf("remuw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else {
fprintf(stderr, "R-type 3: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0011011: {
uint8_t funct3 = (ins >> 12) & 0b111;
if (funct3 == 0b000) {
PARSE_I_INS(ins);
printf("addiw %s, %s, %d\n", REGS[rd], REGS[rs1], imm);
} else if (funct3 == 0b001) {
PARSE_R_INS(ins);
printf("slliw %s, %s, %d\n", REGS[rd], REGS[rs1], rs2);
} else if (funct3 == 0b101) {
PARSE_R_INS(ins);
if (funct7 == 0b0000000) {
printf("srliw %s, %s, %d\n", REGS[rd], REGS[rs1], rs2);
} else if (funct7 == 0b0100000) {
printf("sraiw %s, %s, %d\n", REGS[rd], REGS[rs1], rs2);
} else {
fprintf(stderr, "R-type 4: funct3=101: unrecognized funct7: %b\n",
funct7);
exit(1);
}
} else {
fprintf(stderr, "R-type 4: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0100111: {
fprintf(stderr, "F extension not implemented yet.\n");
exit(1);
}; break;
case 0b0100011: {
PARSE_S_INS(ins);
if (funct3 == 0b000) {
printf("sb %s, %d(%s)\n", REGS[rs2], imm, REGS[rs1]);
} else if (funct3 == 0b001) {
printf("sh %s, %d(%s)\n", REGS[rs2], imm, REGS[rs1]);
} else if (funct3 == 0b010) {
printf("sw %s, %d(%s)\n", REGS[rs2], imm, REGS[rs1]);
} else if (funct3 == 0b011) {
printf("sd %s, %d(%s)\n", REGS[rs2], imm, REGS[rs1]);
} else {
fprintf(stderr, "S-type: unrecognized funct3: %03b\n", funct3);
exit(1);
}
}; break;
case 0b0110111: {
PARSE_U_INS(ins);
printf("lui %s, %d\n", REGS[rd], imm);
}; break;
case 0b0010111: {
PARSE_U_INS(ins);
printf("auipc %s, %d\n", REGS[rd], imm);
}; break;
default:
fprintf(stderr, "Unrecognized opcode: %07b\n", opcode);
exit(1);
}
}