kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 }