rv64_decode_test.c (7117B)
1 /* RV64 structured decode test. 2 * 3 * Pins the ArchDecodeOps path used by the emu lifter bring-up: bytes decode 4 * into KitDecodedInsn records, and the formatter renders those same 5 * records for disassembly without parsing text back into operands. */ 6 7 #include <kit/compile.h> 8 #include <kit/core.h> 9 #include <stdarg.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include "arch/arch.h" 15 #include "arch/riscv/isa.h" 16 #include "lib/kit_unit.h" 17 18 /* Shared test context replaces the per-file heap/diag/counter globals; 19 * EXPECT aliases CU_EXPECT so the call sites are unchanged. */ 20 static KitUnit g_u; 21 #define EXPECT(cond, ...) CU_EXPECT(&g_u, cond, __VA_ARGS__) 22 23 static KitCompiler* new_compiler(void) { 24 KitTargetSpec t = kit_unit_target(KIT_ARCH_RV64, KIT_OS_LINUX, KIT_OBJ_ELF); 25 KitCompiler* c = NULL; 26 if (kit_unit_compiler_new(&g_u, t, &c) != KIT_OK || !c) { 27 fprintf(stderr, "compiler_new failed\n"); 28 exit(2); 29 } 30 return c; 31 } 32 33 static void put32(unsigned char* b, size_t off, unsigned v) { 34 b[off + 0] = (unsigned char)v; 35 b[off + 1] = (unsigned char)(v >> 8); 36 b[off + 2] = (unsigned char)(v >> 16); 37 b[off + 3] = (unsigned char)(v >> 24); 38 } 39 40 static void decode_addi(KitCompiler* pub) { 41 Compiler* c = (Compiler*)pub; 42 unsigned char bytes[4]; 43 KitDecodedInsn insn; 44 KitStatus st; 45 46 put32(bytes, 0, rv_addi(RV_A0, RV_ZERO, 42)); 47 memset(&insn, 0, sizeof(insn)); 48 st = arch_decode_one(c, bytes, sizeof(bytes), 0x1000, &insn); 49 EXPECT(st == KIT_OK, "decode_one(addi) status %d", (int)st); 50 EXPECT(insn.pc == 0x1000, "pc = 0x%llx", (unsigned long long)insn.pc); 51 EXPECT(insn.nbytes == 4, "nbytes = %u", (unsigned)insn.nbytes); 52 EXPECT(insn.opcode == RV64_DEC_ADDI, "opcode = %u, want ADDI", 53 (unsigned)insn.opcode); 54 EXPECT((insn.flags & KIT_DECODE_TERMINATOR) == 0, 55 "addi should not be a terminator"); 56 EXPECT(insn.noperands == 3, "addi operand count = %u", 57 (unsigned)insn.noperands); 58 EXPECT( 59 insn.operands[0].kind == KIT_DECOP_REG && insn.operands[0].reg == RV_A0, 60 "addi rd operand wrong"); 61 EXPECT( 62 insn.operands[1].kind == KIT_DECOP_REG && insn.operands[1].reg == RV_ZERO, 63 "addi rs1 operand wrong"); 64 EXPECT(insn.operands[2].kind == KIT_DECOP_IMM && insn.operands[2].imm == 42, 65 "addi imm operand wrong"); 66 } 67 68 static void decode_block_stops_at_ecall(KitCompiler* pub) { 69 Compiler* c = (Compiler*)pub; 70 unsigned char bytes[16]; 71 KitDecodedInsn insts[4]; 72 u32 n = 0; 73 KitStatus st; 74 75 put32(bytes, 0, rv_addi(RV_A0, RV_ZERO, 42)); 76 put32(bytes, 4, rv_addi(RV_A7, RV_ZERO, 93)); 77 put32(bytes, 8, rv_ecall()); 78 put32(bytes, 12, rv_addi(RV_A0, RV_ZERO, 7)); 79 80 memset(insts, 0, sizeof(insts)); 81 st = arch_decode_block(c, bytes, sizeof(bytes), 0x2000, insts, 4, &n); 82 EXPECT(st == KIT_OK, "decode_block status %d", (int)st); 83 EXPECT(n == 3, "decode_block count = %u", (unsigned)n); 84 EXPECT(insts[2].nbytes == 4, "ecall nbytes = %u", (unsigned)insts[2].nbytes); 85 EXPECT(insts[2].opcode == RV64_DEC_ECALL, "ecall opcode = %u", 86 (unsigned)insts[2].opcode); 87 EXPECT((insts[2].flags & KIT_DECODE_TERMINATOR) != 0, 88 "ecall should terminate block"); 89 EXPECT((insts[2].flags & KIT_DECODE_TRAP) != 0, 90 "ecall should be marked trap"); 91 } 92 93 static void format_decoded_record(KitCompiler* pub) { 94 Compiler* c = (Compiler*)pub; 95 unsigned char bytes[4]; 96 KitDecodedInsn insn; 97 ArchInsnFormatter* fmt; 98 KitInsn text; 99 KitStatus st; 100 101 put32(bytes, 0, rv_addi(RV_A0, RV_ZERO, 42)); 102 st = arch_decode_one(c, bytes, sizeof(bytes), 0x3000, &insn); 103 EXPECT(st == KIT_OK, "decode_one for format status %d", (int)st); 104 fmt = arch_insn_formatter_new(c); 105 EXPECT(fmt != NULL, "formatter_new returned NULL"); 106 if (!fmt) return; 107 memset(&text, 0, sizeof(text)); 108 st = arch_format_insn(fmt, &insn, &text); 109 EXPECT(st == KIT_OK, "format status %d", (int)st); 110 EXPECT(kit_slice_eq_cstr(text.mnemonic, "li"), "mnemonic = %.*s", 111 KIT_SLICE_ARG(text.mnemonic)); 112 EXPECT(text.operands.s && strstr(text.operands.s, "a0"), 113 "operands missing a0: %.*s", KIT_SLICE_ARG(text.operands)); 114 EXPECT(text.operands.s && strstr(text.operands.s, "42"), 115 "operands missing 42: %.*s", KIT_SLICE_ARG(text.operands)); 116 arch_insn_formatter_free(fmt); 117 } 118 119 /* CSR pseudo-ops expand to the matching full-form csrr* instruction. Confirm 120 * the bytes the 2-operand pseudo forms build (via enc_i, supplying x0 for the 121 * dropped operand) are bit-identical to the full-form encodings and decode / 122 * format as those full forms. CSR numbers come from the shared name table 123 * (mstatus=0x300, mcause=0x342, mtvec=0x305, mscratch=0x340). */ 124 static void expect_csr_bytes(KitCompiler* pub, u32 word, const char* mnem, 125 const char* op_needle, u32 pc) { 126 Compiler* c = (Compiler*)pub; 127 unsigned char bytes[4]; 128 KitDecodedInsn insn; 129 ArchInsnFormatter* fmt; 130 KitInsn text; 131 KitStatus st; 132 133 put32(bytes, 0, word); 134 memset(&insn, 0, sizeof(insn)); 135 st = arch_decode_one(c, bytes, sizeof(bytes), pc, &insn); 136 EXPECT(st == KIT_OK, "decode_one(%s) status %d", mnem, (int)st); 137 EXPECT(insn.nbytes == 4, "%s nbytes = %u", mnem, (unsigned)insn.nbytes); 138 fmt = arch_insn_formatter_new(c); 139 if (!fmt) return; 140 memset(&text, 0, sizeof(text)); 141 st = arch_format_insn(fmt, &insn, &text); 142 EXPECT(st == KIT_OK, "format(%s) status %d", mnem, (int)st); 143 EXPECT(kit_slice_eq_cstr(text.mnemonic, mnem), "%s mnemonic = %.*s", mnem, 144 KIT_SLICE_ARG(text.mnemonic)); 145 EXPECT(text.operands.s && strstr(text.operands.s, op_needle), 146 "%s operands missing '%s': %.*s", mnem, op_needle, 147 KIT_SLICE_ARG(text.operands)); 148 arch_insn_formatter_free(fmt); 149 } 150 151 static void csr_pseudos_match_full_form(KitCompiler* pub) { 152 /* csrs mstatus, t0 == csrrs x0, 0x300, t0 */ 153 expect_csr_bytes(pub, rv_csrrs(RV_ZERO, 0x300, RV_T0), "csrrs", "t0", 0x6000); 154 /* csrr a0, mcause == csrrs a0, 0x342, x0 */ 155 expect_csr_bytes(pub, rv_csrrs(RV_A0, 0x342, RV_ZERO), "csrrs", "a0", 0x6004); 156 /* csrw mtvec, a1 == csrrw x0, 0x305, a1 */ 157 expect_csr_bytes(pub, rv_csrrw(RV_ZERO, 0x305, RV_A1), "csrrw", "a1", 0x6008); 158 /* csrwi mscratch, 5 == csrrwi x0, 0x340, 5 */ 159 expect_csr_bytes(pub, rv_csrrwi(RV_ZERO, 0x340, 5), "csrrwi", "5", 0x600c); 160 161 /* Round-trip the CSR-name table. */ 162 for (u32 i = 0; i < rv64_csr_names_n; ++i) { 163 u16 num = 0; 164 EXPECT(rv64_csr_num_from_name(kit_slice_cstr(rv64_csr_names[i].name), 165 &num) && 166 num == rv64_csr_names[i].num, 167 "csr name lookup '%s' -> 0x%x", rv64_csr_names[i].name, 168 (unsigned)rv64_csr_names[i].num); 169 EXPECT(rv64_csr_name_from_num(rv64_csr_names[i].num) != NULL, 170 "csr num 0x%x has no name", (unsigned)rv64_csr_names[i].num); 171 } 172 } 173 174 int main(void) { 175 KitCompiler* c; 176 kit_unit_init(&g_u); 177 c = new_compiler(); 178 decode_addi(c); 179 decode_block_stops_at_ecall(c); 180 format_decoded_record(c); 181 csr_pseudos_match_full_form(c); 182 kit_compiler_free(c); 183 kit_unit_summary(&g_u, "rv64_decode_test"); 184 return kit_unit_status(&g_u); 185 }