kit

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

rv64_inline_test.c (2463B)


      1 /* Public-API unit test for the rv64 inline-asm backend. */
      2 
      3 #include <stdint.h>
      4 
      5 #include "inline_public_test.h"
      6 
      7 #define ENC_EBREAK 0x00100073u
      8 #define ENC_ECALL 0x00000073u
      9 #define ENC_NOP 0x00000013u
     10 #define ENC_ADDI_T0_T1_42 0x02a30293u
     11 #define ENC_FENCE_RW_RW 0x0330000fu
     12 
     13 static void put32le(uint8_t out[4], uint32_t v) {
     14   out[0] = (uint8_t)v;
     15   out[1] = (uint8_t)(v >> 8);
     16   out[2] = (uint8_t)(v >> 16);
     17   out[3] = (uint8_t)(v >> 24);
     18 }
     19 
     20 static void rv64_body(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) {
     21   KitCgAsmOperand imm;
     22   const char* memory_clobber = "memory";
     23   (void)i64_ty;
     24 
     25   it_inline_asm(c, cg, "ebreak ; ecall", NULL, 0, NULL, 0, NULL, 0);
     26   it_inline_asm(c, cg, "nop\nnop", NULL, 0, NULL, 0, NULL, 0);
     27 
     28   kit_cg_push_int(cg, 42, i64_ty);
     29   imm = it_asm_op(c, "i", "imm", i64_ty, KIT_CG_ASM_IN);
     30   it_inline_asm(c, cg, "addi t0, t1, %[imm]", NULL, 0, &imm, 1, NULL, 0);
     31 
     32   it_inline_asm(c, cg, "fence rw, rw", NULL, 0, NULL, 0, &memory_clobber, 1);
     33 }
     34 
     35 static void rv64_bad_operand(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) {
     36   (void)i64_ty;
     37   it_inline_asm(c, cg, "mv %9, a0", NULL, 0, NULL, 0, NULL, 0);
     38 }
     39 
     40 int main(void) {
     41   InlineTestEnv env;
     42   InlineText text;
     43   uint8_t pat[12];
     44 
     45   it_env_init(&env);
     46   IT_EXPECT(
     47       &env,
     48       it_emit_text(&env, KIT_ARCH_RV64, "rv64_inline_public", rv64_body, &text),
     49       "failed to emit rv64 inline-asm object");
     50   if (text.data) {
     51     put32le(pat, ENC_EBREAK);
     52     put32le(pat + 4, ENC_ECALL);
     53     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 8),
     54               "missing ebreak/ecall encoding");
     55 
     56     put32le(pat, ENC_NOP);
     57     put32le(pat + 4, ENC_NOP);
     58     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 8),
     59               "missing two-nop inline asm encoding");
     60 
     61     put32le(pat, ENC_ADDI_T0_T1_42);
     62     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4),
     63               "missing addi t0, t1, 42 immediate-substitution encoding");
     64 
     65     put32le(pat, ENC_FENCE_RW_RW);
     66     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4),
     67               "missing fence rw, rw encoding");
     68   }
     69   it_text_close(&text);
     70 
     71   IT_EXPECT(&env,
     72             it_expect_panic(&env, KIT_ARCH_RV64, "rv64_bad_operand",
     73                             rv64_bad_operand, "operand index"),
     74             "expected out-of-range rv64 asm operand to panic");
     75 
     76   if (env.fails) {
     77     fprintf(stderr, "%d failure(s)\n", env.fails);
     78     return 1;
     79   }
     80   printf("rv64_inline_test: ok\n");
     81   return 0;
     82 }