base/asm-common.h, */*.S: New macros for making stack-unwinding tables.
[catacomb] / base / asm-common.h
index fdd7fad..22bb44d 100644 (file)
@@ -66,6 +66,7 @@
 #define INTFUNC(name)                                                  \
        TYPE_FUNC(name);                                                \
        .macro ENDFUNC; _ENDFUNC(name); .endm;                          \
+       .L$_prologue_p = 0; .L$_frameptr_p = 0;                         \
        FUNC_PREHOOK(name);                                             \
 name:                                                                  \
        FUNC_POSTHOOK(name)
@@ -77,6 +78,8 @@ INTFUNC(F(name))
 
 // Marking the end of a function.
 #define _ENDFUNC(name)                                                 \
+       .if ~ .L$_prologue_p; .error "Missing `endprologue'"; .endif;   \
+       .if .L$_frameptr_p; .purgem dropfp; .endif;                     \
        .purgem ENDFUNC;                                                \
        SIZE_OBJ(name);                                                 \
        ENDFUNC_HOOK(name);                                             \
@@ -147,6 +150,11 @@ name:
 // `.seh_pushreg' and friends, and `.seh_endprologue'.
 #endif
 
+#if __ELF__
+#  define FUNC_POSTHOOK(_) .cfi_startproc
+#  define ENDFUNC_HOOK(_) .cfi_endproc
+#endif
+
 // Don't use the wretched AT&T syntax.  It's festooned with pointless
 // punctuation, and all of the data movement is backwards.  Ugh!
        .intel_syntax noprefix
@@ -427,6 +435,101 @@ name:
 #endif
 #define WHOLE(reg) _REGFORM(reg, r)
 
+// Stack management and unwinding.
+.macro setfp   fp, offset = 0
+  .if \offset == 0
+       mov     \fp, R_sp(r)
+#if __ELF__
+         .cfi_def_cfa_register \fp
+#endif
+#if ABI_WIN && CPUFAM_AMD64
+         .seh_setframe \fp, 0
+#endif
+  .else
+       lea     \fp, [R_sp(r) + \offset]
+#if __ELF__
+         .cfi_def_cfa_register \fp
+         .cfi_adjust_cfa_offset -\offset
+#endif
+#if ABI_WIN && CPUFAM_AMD64
+         .seh_setframe \fp, \offset
+#endif
+  .endif
+       .L$_frameptr_p = -1
+       .macro dropfp; _dropfp  \fp, \offset; .endm
+.endm
+
+.macro _dropfp fp, offset = 0
+  .if \offset == 0
+       mov     R_sp(r), \fp
+#if __ELF__
+         .cfi_def_cfa_register R_sp(r)
+#endif
+  .else
+       lea     R_sp(r), [\fp - \offset]
+#if __ELF__
+         .cfi_def_cfa_register R_sp(r)
+         .cfi_adjust_cfa_offset +\offset
+#endif
+  .endif
+       .L$_frameptr_p = 0
+       .purgem dropfp
+.endm
+
+.macro stalloc n
+       sub     R_sp(r), \n
+#if __ELF__
+         .cfi_adjust_cfa_offset +\n
+#endif
+#if ABI_WIN && CPUFAM_AMD64
+         .seh_stackalloc \n
+#endif
+.endm
+
+.macro stfree  n
+       add     R_sp(r), \n
+#if __ELF__
+         .cfi_adjust_cfa_offset -\n
+#endif
+.endm
+
+.macro pushreg r
+       push    \r
+#if __ELF__
+         .cfi_adjust_cfa_offset +WORDSZ
+         .cfi_rel_offset \r, 0
+#endif
+#if ABI_WIN && CPUFAM_AMD64
+         .seh_pushreg \r
+#endif
+.endm
+
+.macro popreg  r
+       pop     \r
+#if __ELF__
+         .cfi_adjust_cfa_offset -WORDSZ
+         .cfi_restore \r
+#endif
+.endm
+
+.macro savexmm r, offset
+       movdqa  [R_sp(r) + \offset], \r
+#if ABI_WIN && CPUFAM_AMD64
+         .seh_savexmm \r, \offset
+#endif
+.endm
+
+.macro rstrxmm r, offset
+       movdqa  \r, [R_sp(r) + \offset]
+.endm
+
+.macro endprologue
+#if ABI_WIN && CPUFAM_AMD64
+         .seh_endprologue
+#endif
+       .L$_prologue_p = -1
+.endm
+
 #endif
 
 #if CPUFAM_X86
@@ -551,8 +654,8 @@ name:
        ARM
 
 // Set the function hooks.
-#define FUNC_PREHOOK(_) .balign 4
-#define ENDFUNC_HOOK(name) .ltorg
+#define FUNC_PREHOOK(_) .balign 4; .fnstart
+#define ENDFUNC_HOOK(_) .fnend; .ltorg
 
 // Call external subroutine at ADDR, possibly via PLT.
 .macro callext addr, cond=
@@ -868,6 +971,63 @@ name:
 // Macros for converting vldm/vstm ranges.
 #define QQ(qlo, qhi) D0(qlo)-D1(qhi)
 
+// Stack management and unwinding.
+.macro setfp   fp, offset = 0
+  .if \offset == 0
+       mov     \fp, sp
+         .setfp \fp, sp
+  .else
+       add     \fp, sp, #\offset
+         .setfp \fp, sp, #\offset
+  .endif
+       .macro dropfp; _dropfp  \fp, \offset; .endm
+       .L$_frameptr_p = -1
+.endm
+
+.macro _dropfp fp, offset = 0
+  .if \offset == 0
+       mov     sp, \fp
+  .else
+       sub     sp, \fp, #\offset
+  .endif
+       .purgem dropfp
+       .L$_frameptr_p = 0
+.endm
+
+.macro stalloc n
+       sub     sp, sp, #\n
+         .pad #\n
+.endm
+
+.macro stfree  n
+       add     sp, sp, #\n
+         .pad #-\n
+.endm
+
+.macro pushreg rr:vararg
+       stmfd   sp!, {\rr}
+         .save {\rr}
+.endm
+
+.macro popreg  rr:vararg
+       ldmfd   sp!, {\rr}
+.endm
+
+.macro pushvfp rr:vararg
+       vstmdb  sp!, {\rr}
+         .vsave {\rr}
+.endm
+
+.macro popvfp rr:vararg
+       vldmia  sp!, {\rr}
+.endm
+
+.macro endprologue
+.endm
+
+// No need for prologue markers on ARM.
+#define FUNC_POSTHOOK(_) .L$_prologue_p = -1
+
 #endif
 
 ///--------------------------------------------------------------------------