chiark / gitweb /
0b5f2238a2b658373f0b4715f01ab4e5ac78f989
[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 // Some useful variables.
31         .L$_subsec = 0
32
33 // Literal pools done the hard way.
34 #define _LIT .text .L$_subsec + 1
35 #define _ENDLIT .text .L$_subsec
36 #define _LTORG .L$_subsec = .L$_subsec + 2; .text .L$_subsec
37
38 // Announcing an external function.
39 #define FUNC(name)                                                      \
40         .globl  F(name);                                                \
41         TYPE_FUNC(name);                                                \
42         .macro ENDFUNC; _ENDFUNC(name); .endm;                          \
43         FUNC_PREHOOK(name);                                             \
44 F(name):                                                                \
45         FUNC_POSTHOOK(name)
46
47 // Marking the end of a function.
48 #define _ENDFUNC(name)                                                  \
49         .purgem ENDFUNC;                                                \
50         SIZE_OBJ(name);                                                 \
51         ENDFUNC_HOOK(name);                                             \
52         _LTORG
53
54 // Make a helper function, if necessary.
55 #define AUXFN(name)                                                     \
56   .ifndef .L$_auxfn_def.name;                                           \
57         .text 7128;                                                     \
58         .macro _ENDAUXFN; _ENDAUXFN_TAIL(name); .endm;                  \
59         FUNC_PREHOOK(name);                                             \
60 name:
61 #define _ENDAUXFN_TAIL(name)                                            \
62         .purgem _ENDAUXFN;                                              \
63         .text .L$_subsec;                                               \
64         .L$_auxfn_def.name = 1
65 #define ENDAUXFN _ENDAUXFN; .endif
66
67 ///--------------------------------------------------------------------------
68 /// ELF-specific hacking.
69
70 #if __ELF__
71
72 #if __PIC__ || __PIE__
73 #  define WANT_PIC 1
74 #endif
75
76 #define TYPE_FUNC(name) .type name, STT_FUNC
77
78 #define SIZE_OBJ(name) .size name, . - name
79
80 #endif
81
82 ///--------------------------------------------------------------------------
83 /// Windows-specific hacking.
84
85 #if ABI_WIN
86
87 #if CPUFAM_X86
88 #  define F(name) _##name
89 #endif
90
91 #endif
92
93 ///--------------------------------------------------------------------------
94 /// x86- and amd64-specific hacking.
95 ///
96 /// It's (slightly) easier to deal with both of these in one go.
97
98 #if CPUFAM_X86 || CPUFAM_AMD64
99
100 // Set the function hooks.
101 #define FUNC_PREHOOK(_) .balign 16
102
103 // Don't use the wretched AT&T syntax.  It's festooned with pointless
104 // punctuation, and all of the data movement is backwards.  Ugh!
105         .intel_syntax noprefix
106
107 // Call external subroutine at ADDR, possibly via PLT.
108 .macro  callext addr
109 #if WANT_PIC
110         call    \addr@PLT
111 #else
112         call    \addr
113 #endif
114 .endm
115
116 // Do I need to arrange a spare GOT register?
117 #if WANT_PIC && CPUFAM_X86
118 #  define NEED_GOT 1
119 #endif
120 #define GOTREG ebx                      // Not needed in AMD64 so don't care.
121
122 // Maybe load GOT address into GOT.
123 .macro  ldgot got=GOTREG
124 #if WANT_PIC && CPUFAM_X86
125   AUXFN(_ldgot.\got)
126         mov     \got, [esp]
127         ret
128   ENDAUXFN
129         call    _ldgot.\got
130         add     \got, offset _GLOBAL_OFFSET_TABLE_
131 #endif
132 .endm
133
134 // Load address of external symbol ADDR into REG, maybe using GOT.
135 .macro  leaext reg, addr, got=GOTREG
136 #if WANT_PIC
137 #  if CPUFAM_X86
138         mov     \reg, [\got + \addr@GOT]
139 #  endif
140 #  if CPUFAM_AMD64
141         mov     \reg, \addr@GOTPCREL[rip]
142 #  endif
143 #else
144 #  if CPUFAM_X86
145         mov     \reg, offset \addr
146 #  endif
147 #  if CPUFAM_AMD64
148         lea     \reg, \addr[rip]
149 #  endif
150 #endif
151 .endm
152
153 // Address expression (possibly using a base register, and a displacement)
154 // referring to ADDR, which is within our module, maybe using GOT.
155 #define INTADDR(...) INTADDR__0(__VA_ARGS__, GOTREG, dummy)
156 #define INTADDR__0(addr, got, ...) INTADDR__1(addr, got)
157 #if CPUFAM_AMD64
158 #  define INTADDR__1(addr, got) addr + rip
159 #elif WANT_PIC
160 #  define INTADDR__1(addr, got) got + addr@GOTOFF
161 #else
162 #  define INTADDR__1(addr, got) addr
163 #endif
164
165 #endif
166
167 ///--------------------------------------------------------------------------
168 /// ARM-specific hacking.
169
170 #if CPUFAM_ARMEL
171
172 // ARM/Thumb mode things.  Use ARM by default.
173 #define ARM .arm; .L$_pcoff = 8
174 #define THUMB .thumb; .L$_pcoff = 4
175         ARM
176
177 // Set the function hooks.
178 #define FUNC_PREHOOK(_) .balign 4
179 #define ENDFUNC_HOOK(name) .ltorg
180
181 // Call external subroutine at ADDR, possibly via PLT.
182 .macro  callext addr, cond=
183 #if WANT_PIC
184         bl\cond \addr(PLT)
185 #else
186         bl\cond \addr
187 #endif
188 .endm
189
190 // Do I need to arrange a spare GOT register?
191 #if WANT_PIC
192 #  define NEED_GOT 1
193 #endif
194 #define GOTREG r9
195
196 // Maybe load GOT address into GOT.
197 .macro  ldgot   cond=, got=GOTREG
198 #if WANT_PIC
199         ldr\cond \got, .L$_ldgot$\@
200 .L$_ldgot_pc$\@:
201         add\cond \got, pc, \got
202   _LIT
203         .balign 4
204 .L$_ldgot$\@:
205         .word   _GLOBAL_OFFSET_TABLE_ - .L$_ldgot_pc$\@ - .L$_pcoff
206   _ENDLIT
207 #endif
208 .endm
209
210 // Load address of external symbol ADDR into REG, maybe using GOT.
211 .macro  leaext  reg, addr, cond=, got=GOTREG
212 #if WANT_PIC
213         ldr\cond \reg, .L$_leaext$\@
214         ldr\cond \reg, [\got, \reg]
215   _LIT
216         .balign 4
217 .L$_leaext$\@:
218         .word   \addr(GOT)
219   _ENDLIT
220 #else
221         ldr\cond \reg, =\addr
222 #endif
223 .endm
224
225 // Load address of external symbol ADDR into REG directly.
226 .macro  leaextq reg, addr, cond=
227 #if WANT_PIC
228         ldr\cond \reg, .L$_leaextq$\@
229 .L$_leaextq_pc$\@:
230         .if     .L$_pcoff == 8
231         ldr\cond \reg, [pc, \reg]
232         .else
233         add\cond \reg, pc
234         ldr\cond \reg, [\reg]
235         .endif
236   _LIT
237         .balign 4
238 .L$_leaextq$\@:
239         .word   \addr(GOT_PREL) + (. - .L$_leaextq_pc$\@ - .L$_pcoff)
240   _ENDLIT
241 #else
242         ldr\cond \reg, =\addr
243 #endif
244 .endm
245
246 #endif
247
248 ///--------------------------------------------------------------------------
249 /// Final stuff.
250
251 // Default values for the various hooks.
252 #ifndef FUNC_PREHOOK
253 #  define FUNC_PREHOOK(name)
254 #endif
255 #ifndef FUNC_POSTHOOK
256 #  define FUNC_POSTHOOK(name)
257 #endif
258 #ifndef ENDFUNC_HOOK
259 #  define ENDFUNC_HOOK(name)
260 #endif
261
262 #ifndef F
263 #  define F(name) name
264 #endif
265
266 #ifndef TYPE_FUNC
267 #  define TYPE_FUNC(name)
268 #endif
269
270 #ifndef SIZE_OBJ
271 #  define SIZE_OBJ(name)
272 #endif
273
274 ///----- That's all, folks --------------------------------------------------