asm_04_register_callee_saved.c (1864B)
1 /* A hard-register inline-asm operand may name a callee-saved register. The 2 * callee must preserve the caller's register value even though it loads the asm 3 * operand through that hard register internally. */ 4 5 #if defined(__aarch64__) 6 __asm__( 7 ".text\n" 8 ".globl write_saved_reg\n" 9 "write_saved_reg:\n" 10 "mov x19, x0\n" 11 "ret\n" 12 ".globl read_saved_reg\n" 13 "read_saved_reg:\n" 14 "mov x0, x19\n" 15 "ret\n"); 16 extern void write_saved_reg(long); 17 extern long read_saved_reg(void); 18 #elif defined(__x86_64__) 19 __asm__( 20 ".text\n" 21 ".globl write_saved_reg\n" 22 "write_saved_reg:\n" 23 "movq %rdi, %r13\n" 24 "retq\n" 25 ".globl read_saved_reg\n" 26 "read_saved_reg:\n" 27 "movq %r13, %rax\n" 28 "retq\n"); 29 extern void write_saved_reg(long); 30 extern long read_saved_reg(void); 31 #elif defined(__riscv) && __riscv_xlen == 64 32 __asm__( 33 ".text\n" 34 ".globl write_saved_reg\n" 35 "write_saved_reg:\n" 36 "mv s1, a0\n" 37 "ret\n" 38 ".globl read_saved_reg\n" 39 "read_saved_reg:\n" 40 "mv a0, s1\n" 41 "ret\n"); 42 extern void write_saved_reg(long); 43 extern long read_saved_reg(void); 44 #else 45 static long saved_fallback; 46 static void write_saved_reg(long v) { saved_fallback = v; } 47 static long read_saved_reg(void) { return saved_fallback; } 48 #endif 49 50 __attribute__((noinline)) static void touch_callee_saved(void) { 51 #if defined(__aarch64__) 52 register long v __asm__("x19") = 123; 53 __asm__ volatile("" : "+r"(v)); 54 #elif defined(__x86_64__) 55 register long v __asm__("r13") = 123; 56 __asm__ volatile("" : "+r"(v)); 57 #elif defined(__riscv) && __riscv_xlen == 64 58 register long v __asm__("s1") = 123; 59 __asm__ volatile("" : "+r"(v)); 60 #endif 61 } 62 63 int test_main(void) { 64 long saved = read_saved_reg(); 65 long after; 66 write_saved_reg(77); 67 touch_callee_saved(); 68 after = read_saved_reg(); 69 write_saved_reg(saved); 70 return (int)after; 71 }