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 }