base/asm-common.h: Accept condition codes in ARM PIC macros.
[catacomb] / base / asm-common.h
CommitLineData
1a0c09c4
MW
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); \
36F(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///--------------------------------------------------------------------------
0f23f75f
MW
61/// Windows-specific hacking.
62
63#if ABI_WIN
1a0c09c4
MW
64
65#if CPUFAM_X86
0f23f75f
MW
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
1a0c09c4
MW
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
0f23f75f 102#if WANT_PIC && CPUFAM_X86
1a0c09c4
MW
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
0f23f75f 110#if WANT_PIC && CPUFAM_X86
1a0c09c4
MW
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
0f23f75f 121# if CPUFAM_X86
1a0c09c4 122 mov \reg, [\got + \addr@GOT]
0f23f75f
MW
123# endif
124# if CPUFAM_AMD64
125 mov \reg, \addr@GOTPCREL[rip]
126# endif
1a0c09c4 127#else
0f23f75f 128# if CPUFAM_X86
1a0c09c4 129 mov \reg, offset \addr
0f23f75f
MW
130# endif
131# if CPUFAM_AMD64
132 lea \reg, \addr[rip]
133# endif
1a0c09c4
MW
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)
0f23f75f
MW
141#if CPUFAM_AMD64
142# define INTADDR__1(addr, got) addr + rip
143#elif WANT_PIC
1a0c09c4
MW
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///--------------------------------------------------------------------------
61bd904b
MW
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.
2d03a881 176 .macro ldgot cond=, got=GOTREG
61bd904b 177#if WANT_PIC
2d03a881
MW
178 ldr\cond \got, =_GLOBAL_OFFSET_TABLE_ - . - 12
179 add\cond \got, pc, \got
61bd904b
MW
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
2d03a881
MW
186 ldr\cond \reg, =\addr(GOT)
187 ldr\cond \reg, [\got, \reg]
61bd904b 188#else
2d03a881 189 ldr\cond \reg, =\addr
61bd904b
MW
190#endif
191 .endm
192
193#endif
194
195///--------------------------------------------------------------------------
1a0c09c4
MW
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 --------------------------------------------------