kit

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

aa64_inline_test.c (5313B)


      1 /* Public-API unit test for the aarch64 inline-asm backend. */
      2 
      3 #include <stdint.h>
      4 #include <string.h>
      5 
      6 #include "inline_public_test.h"
      7 
      8 #define EXPECTED_MOV_X1_X5 0xaa0503e1u
      9 #define EXPECTED_NOP 0xd503201fu
     10 #define EXPECTED_ADD_W0_WSP_7 0x11001fe0u
     11 /* System-register move (MRS/MSR register form). TPIDR_EL0 is S3_3_C13_C0_2.
     12  *   MSR TPIDR_EL0, X0 : 0xd51bd040 | Rt   (write, L=0)
     13  *   MRS X1, TPIDR_EL0 : 0xd53bd040 | Rt   (read,  L=1) */
     14 #define EXPECTED_MSR_TPIDR_X0 0xd51bd040u
     15 #define EXPECTED_MRS_X1_TPIDR 0xd53bd041u
     16 
     17 static void put32le(uint8_t out[4], uint32_t v) {
     18   out[0] = (uint8_t)v;
     19   out[1] = (uint8_t)(v >> 8);
     20   out[2] = (uint8_t)(v >> 16);
     21   out[3] = (uint8_t)(v >> 24);
     22 }
     23 
     24 static void aa64_body(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) {
     25   KitCgAsmOperand imm;
     26   const char* memory_clobber = "memory";
     27   (void)i64_ty;
     28 
     29   it_inline_asm(c, cg, "mov x1, x5", NULL, 0, NULL, 0, NULL, 0);
     30   it_inline_asm(c, cg, "nop ; nop", NULL, 0, NULL, 0, NULL, 0);
     31   /* System-register thread-pointer access (used by the freestanding cross
     32    * startup stub to seed TPIDR_EL0). */
     33   it_inline_asm(c, cg, "msr tpidr_el0, x0", NULL, 0, NULL, 0, NULL, 0);
     34   it_inline_asm(c, cg, "mrs x1, tpidr_el0", NULL, 0, NULL, 0, NULL, 0);
     35 
     36   kit_cg_push_int(cg, 7, i64_ty);
     37   imm = it_asm_op(c, "i", "imm", i64_ty, KIT_CG_ASM_IN);
     38   it_inline_asm(c, cg, "add w0, wsp, %[imm]", NULL, 0, &imm, 1, &memory_clobber,
     39                 1);
     40 }
     41 
     42 static void aa64_bad_add_zr(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) {
     43   (void)i64_ty;
     44   it_inline_asm(c, cg, "add w0, wzr, #7", NULL, 0, NULL, 0, NULL, 0);
     45 }
     46 
     47 static void aa64_bad_ldr_zr(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) {
     48   (void)i64_ty;
     49   it_inline_asm(c, cg, "ldr w0, [xzr]", NULL, 0, NULL, 0, NULL, 0);
     50 }
     51 
     52 static void aa64_push_local_inputs(KitCompiler* c, KitCg* cg, KitCgTypeId ty,
     53                                    const char* constraint,
     54                                    KitCgAsmOperand* ins, uint32_t n) {
     55   KitCgLocal locals[24];
     56   KitCgLocalAttrs attrs;
     57   KitCgMemAccess mem;
     58   memset(&attrs, 0, sizeof attrs);
     59   memset(&mem, 0, sizeof mem);
     60   mem.type = ty;
     61   mem.align = kit_cg_type_align(c, ty);
     62   for (uint32_t i = 0; i < n; ++i) {
     63     locals[i] = kit_cg_local(cg, ty, attrs);
     64     if (ty == kit_cg_type_builtin(c, KIT_CG_BUILTIN_F64))
     65       kit_cg_push_float(cg, (double)i + 0.5, ty);
     66     else
     67       kit_cg_push_int(cg, i + 1u, ty);
     68     kit_cg_local_write(cg, locals[i], mem);
     69   }
     70   for (uint32_t i = 0; i < n; ++i) {
     71     kit_cg_local_read(cg, locals[i], mem);
     72     ins[i] = it_asm_op(c, constraint, NULL, ty, KIT_CG_ASM_IN);
     73   }
     74 }
     75 
     76 static void aa64_optimized_stage(KitCompiler* c, KitCg* cg,
     77                                  KitCgTypeId i64_ty) {
     78   KitCgTypeId f64_ty = kit_cg_type_builtin(c, KIT_CG_BUILTIN_F64);
     79   KitCgAsmOperand ins[24];
     80   KitCgAsmOperand outs[6];
     81 
     82   aa64_push_local_inputs(c, cg, i64_ty, "r", ins, 20);
     83   it_inline_asm(c, cg, "", NULL, 0, ins, 20, NULL, 0);
     84 
     85   aa64_push_local_inputs(c, cg, f64_ty, "w", ins, 24);
     86   it_inline_asm(c, cg, "", NULL, 0, ins, 24, NULL, 0);
     87 
     88   for (uint32_t i = 0; i < 6u; ++i)
     89     outs[i] = it_asm_op(c, i & 1u ? "=w" : "=r", NULL,
     90                         i & 1u ? f64_ty : i64_ty, KIT_CG_ASM_OUT);
     91   it_inline_asm(c, cg, "", outs, 6, NULL, 0, NULL, 0);
     92   for (uint32_t i = 0; i < 6u; ++i) kit_cg_drop(cg);
     93 }
     94 
     95 int main(void) {
     96   InlineTestEnv env;
     97   InlineText text;
     98   uint8_t pat[12];
     99 
    100   it_env_init(&env);
    101   IT_EXPECT(&env,
    102             it_emit_text(&env, KIT_ARCH_ARM_64, "aa64_inline_public", aa64_body,
    103                          &text),
    104             "failed to emit aa64 inline-asm object");
    105   if (text.data) {
    106     put32le(pat, EXPECTED_MOV_X1_X5);
    107     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4),
    108               "missing mov x1, x5 encoding");
    109 
    110     put32le(pat, EXPECTED_NOP);
    111     put32le(pat + 4, EXPECTED_NOP);
    112     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 8),
    113               "missing two-nop inline asm encoding");
    114 
    115     put32le(pat, EXPECTED_ADD_W0_WSP_7);
    116     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4),
    117               "missing add w0, wsp, #7 immediate-substitution encoding");
    118 
    119     put32le(pat, EXPECTED_MSR_TPIDR_X0);
    120     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4),
    121               "missing msr tpidr_el0, x0 encoding");
    122 
    123     put32le(pat, EXPECTED_MRS_X1_TPIDR);
    124     IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4),
    125               "missing mrs x1, tpidr_el0 encoding");
    126   }
    127   it_text_close(&text);
    128 
    129   IT_EXPECT(&env,
    130             it_expect_panic(&env, KIT_ARCH_ARM_64, "aa64_bad_add_zr",
    131                             aa64_bad_add_zr, "zero register"),
    132             "expected add w0, wzr, #7 to panic");
    133   IT_EXPECT(&env,
    134             it_expect_panic(&env, KIT_ARCH_ARM_64, "aa64_bad_ldr_zr",
    135                             aa64_bad_ldr_zr, "zero register"),
    136             "expected ldr w0, [xzr] to panic");
    137 
    138   {
    139     InlineText opt;
    140     IT_EXPECT(&env,
    141               it_emit_text_opt(&env, KIT_ARCH_ARM_64, "aa64_optimized_stage",
    142                                aa64_optimized_stage, 1, &opt),
    143               "failed to emit optimized aa64 inline-asm staging case");
    144     it_text_close(&opt);
    145   }
    146 
    147   if (env.fails) {
    148     fprintf(stderr, "%d failure(s)\n", env.fails);
    149     return 1;
    150   }
    151   printf("aa64_inline_test: ok\n");
    152   return 0;
    153 }