chiark / gitweb /
4d0d9a60d280aa1e07d235e8358acdc70c96fef9
[catacomb] / base / asm-common.h
1 /// -*- mode: asm; asm-comment-char: ?/ -*-
2 ///
3 /// Fancy SIMD implementation of Salsa20
4 ///
5 /// (c) 2015 Straylight/Edgeware
6 ///
7
8 ///----- Licensing notice ---------------------------------------------------
9 ///
10 /// This file is part of Catacomb.
11 ///
12 /// Catacomb is free software; you can redistribute it and/or modify
13 /// it under the terms of the GNU Library General Public License as
14 /// published by the Free Software Foundation; either version 2 of the
15 /// License, or (at your option) any later version.
16 ///
17 /// Catacomb is distributed in the hope that it will be useful,
18 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 /// GNU Library General Public License for more details.
21 ///
22 /// You should have received a copy of the GNU Library General Public
23 /// License along with Catacomb; if not, write to the Free
24 /// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 /// MA 02111-1307, USA.
26
27 ///--------------------------------------------------------------------------
28 /// General definitions.
29
30 // Announcing an external function.
31 #define FUNC(name)                                                      \
32         .globl  F(name);                                                \
33         TYPE_FUNC(name);                                                \
34         .macro  ENDFUNC; _ENDFUNC(name); .endm;                         \
35         FUNC_PREHOOK(name);                                             \
36 F(name):                                                                \
37         FUNC_POSTHOOK(name)
38
39 // Marking the end of a function.
40 #define _ENDFUNC(name)                                                  \
41         .purgem ENDFUNC;                                                \
42         SIZE_OBJ(name);                                                 \
43         ENDFUNC_HOOK(name)
44
45 ///--------------------------------------------------------------------------
46 /// ELF-specific hacking.
47
48 #if __ELF__
49
50 #if __PIC__ || __PIE__
51 #  define WANT_PIC 1
52 #endif
53
54 #define TYPE_FUNC(name) .type name, STT_FUNC
55
56 #define SIZE_OBJ(name) .size name, . - name
57
58 #endif
59
60 ///--------------------------------------------------------------------------
61 /// Windows-specific hacking.
62
63 #if ABI_WIN
64
65 #if CPUFAM_X86
66 #  define F(name) _##name
67 #endif
68
69 #endif
70
71 ///--------------------------------------------------------------------------
72 /// x86- and amd64-specific hacking.
73 ///
74 /// It's (slightly) easier to deal with both of these in one go.
75
76 #if CPUFAM_X86 || CPUFAM_AMD64
77
78 // Set the function hooks.
79 #define FUNC_PREHOOK(_) .balign 16
80
81 // Don't use the wretched AT&T syntax.  It's festooned with pointless
82 // punctuation, and all of the data movement is backwards.  Ugh!
83         .intel_syntax noprefix
84
85 // Call external subroutine at ADDR, possibly via PLT.
86         .macro  callext addr
87 #if WANT_PIC
88         call    \addr@PLT
89 #else
90         call    \addr
91 #endif
92         .endm
93
94 // Do I need to arrange a spare GOT register?
95 #if WANT_PIC && CPUFAM_X86
96 #  define NEED_GOT 1
97 #endif
98 #define GOTREG ebx                      // Not needed in AMD64 so don't care.
99
100 // Maybe load GOT address into GOT.
101         .macro  ldgot got=GOTREG
102 #if WANT_PIC && CPUFAM_X86
103         call    _where_am_i.\got
104         add     \got, offset _GLOBAL_OFFSET_TABLE_
105 #endif
106         .endm
107
108 // Maybe build a helper subroutine for `ldgot GOT'.
109         .macro  gotaux got=GOTREG
110 #if WANT_PIC && CPUFAM_X86
111         .align  16
112 _where_am_i.\got :
113         mov     \got, [esp]
114         ret
115 #endif
116         .endm
117
118 // Load address of external symbol ADDR into REG, maybe using GOT.
119         .macro  leaext reg, addr, got=GOTREG
120 #if WANT_PIC
121 #  if CPUFAM_X86
122         mov     \reg, [\got + \addr@GOT]
123 #  endif
124 #  if CPUFAM_AMD64
125         mov     \reg, \addr@GOTPCREL[rip]
126 #  endif
127 #else
128 #  if CPUFAM_X86
129         mov     \reg, offset \addr
130 #  endif
131 #  if CPUFAM_AMD64
132         lea     \reg, \addr[rip]
133 #  endif
134 #endif
135         .endm
136
137 // Address expression (possibly using a base register, and a displacement)
138 // referring to ADDR, which is within our module, maybe using GOT.
139 #define INTADDR(...) INTADDR__0(__VA_ARGS__, GOTREG, dummy)
140 #define INTADDR__0(addr, got, ...) INTADDR__1(addr, got)
141 #if CPUFAM_AMD64
142 #  define INTADDR__1(addr, got) addr + rip
143 #elif WANT_PIC
144 #  define INTADDR__1(addr, got) got + addr@GOTOFF
145 #else
146 #  define INTADDR__1(addr, got) addr
147 #endif
148
149 #endif
150
151 ///--------------------------------------------------------------------------
152 /// ARM-specific hacking.
153
154 #if CPUFAM_ARM
155
156 // Set the function hooks.
157 #define FUNC_PREHOOK(_) .balign 4
158 #define ENDFUNC_HOOK(name) .ltorg
159
160 // Call external subroutine at ADDR, possibly via PLT.
161         .macro  callext addr, cond=
162 #if WANT_PIC
163         bl\cond \addr(PLT)
164 #else
165         bl\cond \addr
166 #endif
167         .endm
168
169 // Do I need to arrange a spare GOT register?
170 #if WANT_PIC
171 #  define NEED_GOT 1
172 #endif
173 #define GOTREG r9
174
175 // Maybe load GOT address into GOT.
176         .macro  ldgot   got=GOTREG
177 #if WANT_PIC
178         ldr     \got, =_GLOBAL_OFFSET_TABLE_ - . - 12
179         add     \got, pc, \got
180 #endif
181         .endm
182
183 // Load address of external symbol ADDR into REG, maybe using GOT.
184         .macro  leaext  reg, addr, cond=, got=GOTREG
185 #if WANT_PIC
186         ldr     \reg, =\addr(GOT)
187         ldr     \reg, [\got, \reg]
188 #else
189         ldr     \reg, =\addr
190 #endif
191         .endm
192
193 #endif
194
195 ///--------------------------------------------------------------------------
196 /// Final stuff.
197
198 // Default values for the various hooks.
199 #ifndef FUNC_PREHOOK
200 #  define FUNC_PREHOOK(name)
201 #endif
202 #ifndef FUNC_POSTHOOK
203 #  define FUNC_POSTHOOK(name)
204 #endif
205 #ifndef ENDFUNC_HOOK
206 #  define ENDFUNC_HOOK(name)
207 #endif
208
209 #ifndef F
210 #  define F(name) name
211 #endif
212
213 #ifndef TYPE_FUNC
214 #  define TYPE_FUNC(name)
215 #endif
216
217 #ifndef SIZE_OBJ
218 #  define SIZE_OBJ(name)
219 #endif
220
221 ///----- That's all, folks --------------------------------------------------