aa64_inline_test.c (3438B)
1 /* Public-API unit test for the aarch64 inline-asm backend. */ 2 3 #include <stdint.h> 4 5 #include "inline_public_test.h" 6 7 #define EXPECTED_MOV_X1_X5 0xaa0503e1u 8 #define EXPECTED_NOP 0xd503201fu 9 #define EXPECTED_ADD_W0_WSP_7 0x11001fe0u 10 /* System-register move (MRS/MSR register form). TPIDR_EL0 is S3_3_C13_C0_2. 11 * MSR TPIDR_EL0, X0 : 0xd51bd040 | Rt (write, L=0) 12 * MRS X1, TPIDR_EL0 : 0xd53bd040 | Rt (read, L=1) */ 13 #define EXPECTED_MSR_TPIDR_X0 0xd51bd040u 14 #define EXPECTED_MRS_X1_TPIDR 0xd53bd041u 15 16 static void put32le(uint8_t out[4], uint32_t v) { 17 out[0] = (uint8_t)v; 18 out[1] = (uint8_t)(v >> 8); 19 out[2] = (uint8_t)(v >> 16); 20 out[3] = (uint8_t)(v >> 24); 21 } 22 23 static void aa64_body(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) { 24 KitCgAsmOperand imm; 25 const char* memory_clobber = "memory"; 26 (void)i64_ty; 27 28 it_inline_asm(c, cg, "mov x1, x5", NULL, 0, NULL, 0, NULL, 0); 29 it_inline_asm(c, cg, "nop ; nop", NULL, 0, NULL, 0, NULL, 0); 30 /* System-register thread-pointer access (used by the freestanding cross 31 * startup stub to seed TPIDR_EL0). */ 32 it_inline_asm(c, cg, "msr tpidr_el0, x0", NULL, 0, NULL, 0, NULL, 0); 33 it_inline_asm(c, cg, "mrs x1, tpidr_el0", NULL, 0, NULL, 0, NULL, 0); 34 35 kit_cg_push_int(cg, 7, i64_ty); 36 imm = it_asm_op(c, "i", "imm", i64_ty, KIT_CG_ASM_IN); 37 it_inline_asm(c, cg, "add w0, wsp, %[imm]", NULL, 0, &imm, 1, &memory_clobber, 38 1); 39 } 40 41 static void aa64_bad_add_zr(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) { 42 (void)i64_ty; 43 it_inline_asm(c, cg, "add w0, wzr, #7", NULL, 0, NULL, 0, NULL, 0); 44 } 45 46 static void aa64_bad_ldr_zr(KitCompiler* c, KitCg* cg, KitCgTypeId i64_ty) { 47 (void)i64_ty; 48 it_inline_asm(c, cg, "ldr w0, [xzr]", NULL, 0, NULL, 0, NULL, 0); 49 } 50 51 int main(void) { 52 InlineTestEnv env; 53 InlineText text; 54 uint8_t pat[12]; 55 56 it_env_init(&env); 57 IT_EXPECT(&env, 58 it_emit_text(&env, KIT_ARCH_ARM_64, "aa64_inline_public", aa64_body, 59 &text), 60 "failed to emit aa64 inline-asm object"); 61 if (text.data) { 62 put32le(pat, EXPECTED_MOV_X1_X5); 63 IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4), 64 "missing mov x1, x5 encoding"); 65 66 put32le(pat, EXPECTED_NOP); 67 put32le(pat + 4, EXPECTED_NOP); 68 IT_EXPECT(&env, it_contains(text.data, text.len, pat, 8), 69 "missing two-nop inline asm encoding"); 70 71 put32le(pat, EXPECTED_ADD_W0_WSP_7); 72 IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4), 73 "missing add w0, wsp, #7 immediate-substitution encoding"); 74 75 put32le(pat, EXPECTED_MSR_TPIDR_X0); 76 IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4), 77 "missing msr tpidr_el0, x0 encoding"); 78 79 put32le(pat, EXPECTED_MRS_X1_TPIDR); 80 IT_EXPECT(&env, it_contains(text.data, text.len, pat, 4), 81 "missing mrs x1, tpidr_el0 encoding"); 82 } 83 it_text_close(&text); 84 85 IT_EXPECT(&env, 86 it_expect_panic(&env, KIT_ARCH_ARM_64, "aa64_bad_add_zr", 87 aa64_bad_add_zr, "zero register"), 88 "expected add w0, wzr, #7 to panic"); 89 IT_EXPECT(&env, 90 it_expect_panic(&env, KIT_ARCH_ARM_64, "aa64_bad_ldr_zr", 91 aa64_bad_ldr_zr, "zero register"), 92 "expected ldr w0, [xzr] to panic"); 93 94 if (env.fails) { 95 fprintf(stderr, "%d failure(s)\n", env.fails); 96 return 1; 97 } 98 printf("aa64_inline_test: ok\n"); 99 return 0; 100 }