asm_03_register_operand.c (1415B)
1 /* GNU local register variables (`register T x __asm__("reg")`) used as inline- 2 * asm operands must occupy the named hard register. Each template below 3 * addresses its registers directly (not via %N operand substitution), so the 4 * result is correct only when a/b/r really land in the pinned registers — a 5 * regression guard for register-variable operand pinning through the native 6 * backends (-O0 direct and the optimizer's tied-hard-reg path). 40 + 2 == 42. 7 * 8 * Arch-guarded; the asm is target-specific. The wasm backend has no native 9 * hard-register file, so this case opts out of W via sidecar. */ 10 11 int test_main(void) { 12 long out = 0; 13 #if defined(__aarch64__) 14 register long a __asm__("x12") = 40; 15 register long b __asm__("x13") = 2; 16 register long r __asm__("x14"); 17 __asm__ volatile("add x14, x12, x13" : "=r"(r) : "r"(a), "r"(b)); 18 out = r; 19 #elif defined(__x86_64__) 20 register long a __asm__("rdi") = 40; 21 register long b __asm__("rsi") = 2; 22 register long r __asm__("rdx"); 23 __asm__ volatile("movq %%rdi, %%rdx\n\taddq %%rsi, %%rdx" 24 : "=r"(r) 25 : "r"(a), "r"(b)); 26 out = r; 27 #elif defined(__riscv) && __riscv_xlen == 64 28 register long a __asm__("a3") = 40; 29 register long b __asm__("a4") = 2; 30 register long r __asm__("a5"); 31 __asm__ volatile("add a5, a3, a4" : "=r"(r) : "r"(a), "r"(b)); 32 out = r; 33 #else 34 out = 42; 35 #endif 36 return (int)out; 37 }