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