rvemu

RISC-V RV32I execution engine
git clone git://mcdim.xyz/revemu.git
Log | Files | Refs

disasm.c (5352B)


      1 #include <stdint.h>
      2 #include <inttypes.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "decode.h"
      8 #include "disasm.h"
      9 
     10 static void disasm_itype(uint32_t inst) {
     11 	itype_t i;
     12 	decode_itype(&i, inst);
     13 
     14 	switch(i.funct3) {
     15 	case 0x0:
     16 		printf("addi");
     17 		break;
     18 	case 0x1:
     19 		if (i.funct7 == 0x00) {
     20 			printf("slli");
     21 		} else {
     22 			printf(".word 0x%08" PRIx32 "\n", inst);
     23 			return;
     24 		}
     25 		break;
     26 	case 0x2:
     27 		printf("slti");
     28 		break;
     29 	case 0x3:
     30 		printf("sltiu");
     31 		break;
     32 	case 0x4:
     33 		printf("xori");
     34 		break;
     35 	case 0x5:
     36 		switch(i.funct7) {
     37 		case 0x00:
     38 			printf("srli");
     39 			break;
     40 		case 0x20:
     41 			printf("srai");
     42 			break;
     43 		default:
     44 			printf(".word 0x%08" PRIx32 "\n", inst);
     45 			return;
     46 		}
     47 		break;
     48 	case 0x6:
     49 		printf("ori");
     50 		break;
     51 	case 0x7:
     52 		printf("andi");
     53 		break;
     54 	default:
     55 		printf(".word 0x%08" PRIx32 "\n", inst);
     56 		return;
     57 	}
     58 	printf(" x%d, x%" PRIu8 ", %" PRId32 "\n", i.rd, i.rs1, i.imm);
     59 }
     60 
     61 static void disasm_rtype(uint32_t inst) {
     62 	rtype_t r;
     63 	decode_rtype(&r, inst);
     64 
     65 	switch(r.funct3) {
     66 	case 0x0:
     67 		switch(r.funct7) {
     68 		case 0x00:
     69 			printf("add x%d, x%d\n", r.rs1, r.rs2);
     70 			break;
     71 		case 0x20:
     72 			printf("sub x%d, x%d\n", r.rs1, r.rs2);
     73 			break;
     74 		default:
     75 			printf(".word 0x%08" PRIx32 "\n", inst);
     76 			return;
     77 		}
     78 		break;
     79 	case 0x1:
     80 		printf("ssl x%d, x%d\n", r.rs1, r.rs2);
     81 		break;
     82 	case 0x2:
     83 		printf("slt x%d, x%d\n", r.rs1, r.rs2);
     84 		break;
     85 	case 0x3:
     86 		printf("sltu x%d, x%d\n", r.rs1, r.rs2);
     87 		break;
     88 	case 0x4:
     89 		printf("xor x%d, x%d\n", r.rs1, r.rs2);
     90 		break;
     91 	case 0x5:
     92 		switch(r.funct7) {
     93 		case 0x00:
     94 			printf("srl x%d, x%d\n", r.rs1, r.rs2);
     95 			break;
     96 		case 0x20:
     97 			printf("sra x%d, x%d\n", r.rs1, r.rs2);
     98 			break;
     99 		default:
    100 			printf(".word 0x%08" PRIx32 "\n", inst);
    101 			return;
    102 		}
    103 		break;
    104 	case 0x6:
    105 		printf("or x%d, x%d\n", r.rs1, r.rs2);
    106 		break;
    107 	case 0x7:
    108 		printf("and x%d, x%d\n", r.rs1, r.rs2);
    109 		break;
    110 	default:
    111 		printf(".word 0x%08" PRIx32 "\n", inst);
    112 		return;
    113 	}
    114 }
    115 
    116 static void disasm_itype_loads(uint32_t inst) {
    117 	itype_t i;
    118 	decode_itype(&i, inst);
    119 
    120 	switch(i.funct3) {
    121 	case 0x0:
    122 		printf("lb");
    123 		break;
    124 	case 0x1:
    125 		printf("lh");
    126 		break;
    127 	case 0x2:
    128 		printf("lw");
    129 		break;
    130 	case 0x4:
    131 		printf("lbu");
    132 		break;
    133 	case 0x5:
    134 		printf("lhu");
    135 		break;
    136 	default:
    137 		printf(".word 0x%08" PRIx32 "\n", inst);
    138 		return;
    139 	}
    140 
    141 	printf(" x%" PRIu32 ", %" PRId32 "(x%" PRIu32 ")\n",
    142 	       i.rd, i.imm, i.rs1);
    143 }
    144 
    145 static void disasm_stype(uint32_t inst) {
    146 	stype_t s;
    147 	decode_stype(&s, inst);
    148 
    149 	switch(s.funct3) {
    150 	case 0x0:
    151 		printf("sb");
    152 		break;
    153 	case 0x1:
    154 		printf("sh");
    155 		break;
    156 	case 0x2:
    157 		printf("sw");
    158 		break;
    159 	default:
    160 		printf(".word 0x%08" PRIx32 "\n", inst);
    161 		return;
    162 	}
    163 
    164 	printf(" x%" PRIu32 ", %" PRId32 "(x%" PRIu32 ")\n",
    165 	       s.rs2, (int32_t)(int16_t)s.imm, s.rs1);
    166 }
    167 
    168 static void disasm_btype(uint32_t inst) {
    169 	btype_t b;
    170 	decode_btype(&b, inst);
    171 
    172 	switch (b.funct3) {
    173 	case 0x0:
    174 		printf("beq");
    175 		break;
    176 	case 0x1:
    177 		printf("bne");
    178 		break;
    179 	case 0x4:
    180 		printf("blt");
    181 		break;
    182 	case 0x5:
    183 		printf("bge");
    184 		break;
    185 	case 0x6:
    186 		printf("bltu");
    187 		break;
    188 	case 0x7:
    189 		printf("bgeu");
    190 		break;
    191 	default:
    192 		printf(".word 0x%08" PRIx32 "\n", inst);
    193 		return;
    194 	}
    195 
    196 	printf(" x%" PRIu32 ", x%" PRIu32 ", %" PRId32 "\n",
    197 	       b.rs1, b.rs2, (int32_t)(int16_t)b.imm);
    198 
    199 
    200 }
    201 
    202 static void disasm_itype_jalr(uint32_t inst) {
    203 	itype_t i;
    204 	decode_itype(&i, inst);
    205 	
    206 	if (i.funct3 != 0x0u) {
    207 		printf(".word 0x%08" PRIx32 "\n", inst);
    208 		return;
    209 	}
    210 	
    211 	printf("x%" PRIu32 ", %" PRId32 "(x%" PRIu32 ")\n",
    212 	       i.rd, i.imm, i.rs1);
    213 
    214 }
    215 
    216 static void disasm_jtype(uint32_t inst) {
    217 	jtype_t j;
    218 	decode_jtype(&j, inst);
    219 
    220 	printf("x%" PRIu32 ", %" PRId32 "\n",
    221 	       j.rd, (int32_t)j.imm);
    222 
    223 }
    224 
    225 static void disasm_utype(uint32_t inst) {
    226 	utype_t u;
    227 	decode_utype(&u, inst);
    228 
    229 	printf("lui x%" PRIu8 ", 0x%05" PRIx32 "\n", u.rd, u.imm);
    230 }
    231 
    232 static void disasm_utype_auipc(uint32_t inst) {
    233 	utype_t u;
    234 	decode_utype(&u, inst);
    235 
    236 	printf("auipc x%" PRIu8 ", 0x%05" PRIx32 "\n", u.rd, u.imm);
    237 }
    238 
    239 static void
    240 disasm_itype_control(uint32_t inst)
    241 {
    242 	itype_t i;
    243 	decode_itype(&i, inst);
    244 
    245 	if (i.funct3 != 0x0) {
    246 		printf(".word 0x%08" PRIx32 "\n", inst);
    247 		return;
    248 	}
    249 
    250 	if (i.imm == 0x0) {
    251 		puts("ecall");
    252 		return;
    253 	} else if (i.imm == 0x1) {
    254 		puts("ebreak");
    255 		return;
    256 	} else {
    257 		printf(".word 0x%08" PRIx32 "\n", inst);
    258 		return;
    259 	}
    260 }
    261 
    262 static void
    263 disasm_itype_fence(uint32_t inst)
    264 {
    265 	itype_t i;
    266 	decode_itype(&i, inst);
    267 
    268 	if (i.funct3 != 0x0) {
    269 		printf(".word 0x%08" PRIx32 "\n", inst);
    270 		return;
    271 	}
    272 
    273 	puts("fence");
    274 	return;
    275 }
    276 
    277 typedef void (*disasm_fn)(uint32_t inst);
    278 
    279 static disasm_fn opcode_table[128];
    280 
    281 static void
    282 init_opcode_table(void)
    283 {
    284         opcode_table[0x33] = disasm_rtype;
    285         opcode_table[0x13] = disasm_itype;
    286         opcode_table[0x03] = disasm_itype_loads;
    287         opcode_table[0x67] = disasm_itype_jalr;
    288         opcode_table[0x73] = disasm_itype_control;
    289         opcode_table[0x0f] = disasm_itype_fence;
    290         opcode_table[0x23] = disasm_stype;
    291         opcode_table[0x63] = disasm_btype;
    292         opcode_table[0x6f] = disasm_jtype;
    293 	opcode_table[0x37] = disasm_utype;
    294 	opcode_table[0x17] = disasm_utype_auipc;
    295 }
    296 
    297 void disassemble_instruction(uint32_t inst) {
    298 	init_opcode_table();
    299 	uint16_t opcode = inst & 0x7f;
    300 	disasm_fn fn = opcode_table[opcode];
    301 	if (!fn) {
    302 		printf(".word 0x%08" PRIx32 "\n", inst);
    303 		return;
    304 	}
    305 	fn(inst);
    306 }