configure.ac: Quote `$ac_cv_search_clock_gettime' properly.
[catacomb] / base / asm-common.h
index 7e62eb5..bcfa735 100644 (file)
 ///--------------------------------------------------------------------------
 /// General definitions.
 
+// Some useful variables.
+       .L$_subsec = 0
+
+// Literal pools done the hard way.
+#define _LIT .text .L$_subsec + 1
+#define _ENDLIT .text .L$_subsec
+
 // Announcing an external function.
 #define FUNC(name)                                                     \
        .globl  F(name);                                                \
@@ -40,7 +47,9 @@ F(name):                                                              \
 #define _ENDFUNC(name)                                                 \
        .purgem ENDFUNC;                                                \
        SIZE_OBJ(name);                                                 \
-       ENDFUNC_HOOK(name)
+       ENDFUNC_HOOK(name);                                             \
+       .L$_subsec = .L$_subsec + 2;                                    \
+       .text .L$_subsec
 
 ///--------------------------------------------------------------------------
 /// ELF-specific hacking.
@@ -58,9 +67,22 @@ F(name):                                                             \
 #endif
 
 ///--------------------------------------------------------------------------
-/// x86-specific hacking.
+/// Windows-specific hacking.
+
+#if ABI_WIN
 
 #if CPUFAM_X86
+#  define F(name) _##name
+#endif
+
+#endif
+
+///--------------------------------------------------------------------------
+/// x86- and amd64-specific hacking.
+///
+/// It's (slightly) easier to deal with both of these in one go.
+
+#if CPUFAM_X86 || CPUFAM_AMD64
 
 // Set the function hooks.
 #define FUNC_PREHOOK(_) .balign 16
@@ -86,7 +108,7 @@ F(name):                                                             \
 
 // Maybe load GOT address into GOT.
        .macro  ldgot got=GOTREG
-#if WANT_PIC
+#if WANT_PIC && CPUFAM_X86
        call    _where_am_i.\got
        add     \got, offset _GLOBAL_OFFSET_TABLE_
 #endif
@@ -94,7 +116,7 @@ F(name):                                                             \
 
 // Maybe build a helper subroutine for `ldgot GOT'.
        .macro  gotaux got=GOTREG
-#if WANT_PIC
+#if WANT_PIC && CPUFAM_X86
        .align  16
 _where_am_i.\got :
        mov     \got, [esp]
@@ -105,9 +127,19 @@ _where_am_i.\got :
 // Load address of external symbol ADDR into REG, maybe using GOT.
        .macro  leaext reg, addr, got=GOTREG
 #if WANT_PIC
+#  if CPUFAM_X86
        mov     \reg, [\got + \addr@GOT]
+#  endif
+#  if CPUFAM_AMD64
+       mov     \reg, \addr@GOTPCREL[rip]
+#  endif
 #else
+#  if CPUFAM_X86
        mov     \reg, offset \addr
+#  endif
+#  if CPUFAM_AMD64
+       lea     \reg, \addr[rip]
+#  endif
 #endif
        .endm
 
@@ -115,7 +147,9 @@ _where_am_i.\got :
 // referring to ADDR, which is within our module, maybe using GOT.
 #define INTADDR(...) INTADDR__0(__VA_ARGS__, GOTREG, dummy)
 #define INTADDR__0(addr, got, ...) INTADDR__1(addr, got)
-#if WANT_PIC
+#if CPUFAM_AMD64
+#  define INTADDR__1(addr, got) addr + rip
+#elif WANT_PIC
 #  define INTADDR__1(addr, got) got + addr@GOTOFF
 #else
 #  define INTADDR__1(addr, got) addr
@@ -124,6 +158,87 @@ _where_am_i.\got :
 #endif
 
 ///--------------------------------------------------------------------------
+/// ARM-specific hacking.
+
+#if CPUFAM_ARM
+
+// ARM/Thumb mode things.  Use ARM by default.
+#define ARM .arm; .L$_pcoff = 8
+#define THUMB .thumb; .L$_pcoff = 4
+       ARM
+
+// Set the function hooks.
+#define FUNC_PREHOOK(_) .balign 4
+#define ENDFUNC_HOOK(name) .ltorg
+
+// Call external subroutine at ADDR, possibly via PLT.
+       .macro  callext addr, cond=
+#if WANT_PIC
+       bl\cond \addr(PLT)
+#else
+       bl\cond \addr
+#endif
+       .endm
+
+// Do I need to arrange a spare GOT register?
+#if WANT_PIC
+#  define NEED_GOT 1
+#endif
+#define GOTREG r9
+
+// Maybe load GOT address into GOT.
+       .macro  ldgot   cond=, got=GOTREG
+#if WANT_PIC
+       ldr\cond \got, .L$_ldgot$\@
+.L$_ldgot_pc$\@:
+       add\cond \got, pc, \got
+       _LIT
+       .balign 4
+.L$_ldgot$\@:
+       .word   _GLOBAL_OFFSET_TABLE_ - .L$_ldgot_pc$\@ - .L$_pcoff
+       _ENDLIT
+#endif
+       .endm
+
+// Load address of external symbol ADDR into REG, maybe using GOT.
+       .macro  leaext  reg, addr, cond=, got=GOTREG
+#if WANT_PIC
+       ldr\cond \reg, .L$_leaext$\@
+       ldr\cond \reg, [\got, \reg]
+       _LIT
+       .balign 4
+.L$_leaext$\@:
+       .word   \addr(GOT)
+       _ENDLIT
+#else
+       ldr\cond \reg, =\addr
+#endif
+       .endm
+
+// Load address of external symbol ADDR into REG directly.
+       .macro  leaextq reg, addr, cond=
+#if WANT_PIC
+       ldr\cond \reg, .L$_leaextq$\@
+.L$_leaextq_pc$\@:
+       .if     .L$_pcoff == 8
+       ldr\cond \reg, [pc, \reg]
+       .else
+       add\cond \reg, pc
+       ldr\cond \reg, [\reg]
+       .endif
+       _LIT
+       .balign 4
+.L$_leaextq$\@:
+       .word   \addr(GOT_PREL) + (. - .L$_leaextq_pc$\@ - .L$_pcoff)
+       _ENDLIT
+#else
+       ldr\cond \reg, =\addr
+#endif
+       .endm
+
+#endif
+
+///--------------------------------------------------------------------------
 /// Final stuff.
 
 // Default values for the various hooks.