riscv

an RV32I simulator and related experiments
git clone http://frotz.net/git/riscv.git
Log | Files | Refs | README

rvdis.c (2424B)


      1 // Copyright 2019, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 #include <string.h>
      5 #include <stdio.h>
      6 
      7 #include "riscv.h"
      8 
      9 static char *append_str(char *buf, const char *s) {
     10 	while (*s) *buf++ = *s++;
     11 	return buf;
     12 }
     13 
     14 static char *append_i32(char *buf, int32_t n) {
     15 	return buf + sprintf(buf, "%d", n);
     16 }
     17 
     18 static char *append_u32(char *buf, int32_t n) {
     19 	return buf + sprintf(buf, "0x%x", n);
     20 }
     21 
     22 static char *append_csr(char *buf, int32_t n) {
     23 	return buf + sprintf(buf, "0x%03x", n & 0xFFF);
     24 }
     25 
     26 static const char* regname_plain[32] = {
     27 	"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
     28 	"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
     29 	"x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
     30 	"x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
     31 };
     32 static const char* regname_fancy[32] = {
     33 	"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
     34 	"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
     35 	"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
     36 	"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
     37 };
     38 
     39 static const char** regname = regname_plain;
     40 
     41 const char* rvregname(uint32_t n) {
     42 	if (n < 32) {
     43 		return regname[n];
     44 	} else {
     45 		return "??";
     46 	}
     47 }
     48 
     49 
     50 typedef struct {
     51 	uint32_t mask;
     52 	uint32_t bits;
     53 	const char* fmt;
     54 } rvins_t;
     55 
     56 static rvins_t instab[] = {
     57 #include "gen/instab.h"
     58 };
     59 
     60 void rvdis(uint32_t pc, uint32_t ins, char *out) {
     61 	unsigned n = 0;
     62 	while ((ins & instab[n].mask) != instab[n].bits) n++;
     63 	const char* fmt = instab[n].fmt;
     64 	char c;
     65 	while ((c = *fmt++) != 0) {
     66 		if (c != '%') {
     67 			*out++ = c;
     68 			continue;
     69 		}
     70 		switch (*fmt++) {
     71 		case '1': out = append_str(out, regname[get_r1(ins)]); break;
     72 		case '2': out = append_str(out, regname[get_r2(ins)]); break;
     73 		case 'd': out = append_str(out, regname[get_rd(ins)]); break;
     74 		case 'i': out = append_i32(out, get_ii(ins)); break;
     75 		case 'j': out = append_i32(out, get_ij(ins)); break;
     76 		case 'J': out = append_u32(out, pc + get_ij(ins)); break;
     77 		case 'b': out = append_i32(out, get_ib(ins)); break;
     78 		case 'B': out = append_u32(out, pc + get_ib(ins)); break;
     79 		case 's': out = append_i32(out, get_is(ins)); break;
     80 		case 'u': out = append_i32(out, get_iu(ins)); break;
     81 		case 'U': out = append_u32(out, get_iu(ins)); break;
     82 		case 'c': out = append_i32(out, get_ic(ins)); break;
     83 		case 'x': out = append_i32(out, get_r2(ins)); break;
     84 		case 'C': out = append_csr(out, get_ii(ins)); break;
     85 		}
     86 	}
     87 	*out = 0;
     88 }