8b56b00dbbee462d56c19c9089a64aae9687403a
[mono.git] / mono / arch / arm / arm-vfp-codegen.h
1 //
2 // Copyright 2011 Xamarin Inc
3 //
4
5 #ifndef __MONO_ARM_VFP_CODEGEN_H__
6 #define __MONO_ARM_VFP_CODEGEN_H__
7
8 #include "arm-codegen.h"
9
10 enum {
11         /* VFP registers */
12         ARM_VFP_F0,
13         ARM_VFP_F1,
14         ARM_VFP_F2,
15         ARM_VFP_F3,
16         ARM_VFP_F4,
17         ARM_VFP_F5,
18         ARM_VFP_F6,
19         ARM_VFP_F7,
20         ARM_VFP_F8,
21         ARM_VFP_F9,
22         ARM_VFP_F10,
23         ARM_VFP_F11,
24         ARM_VFP_F12,
25         ARM_VFP_F13,
26         ARM_VFP_F14,
27         ARM_VFP_F15,
28         ARM_VFP_F16,
29         ARM_VFP_F17,
30         ARM_VFP_F18,
31         ARM_VFP_F19,
32         ARM_VFP_F20,
33         ARM_VFP_F21,
34         ARM_VFP_F22,
35         ARM_VFP_F23,
36         ARM_VFP_F24,
37         ARM_VFP_F25,
38         ARM_VFP_F26,
39         ARM_VFP_F27,
40         ARM_VFP_F28,
41         ARM_VFP_F29,
42         ARM_VFP_F30,
43         ARM_VFP_F31,
44
45         ARM_VFP_D0 = ARM_VFP_F0,
46         ARM_VFP_D1 = ARM_VFP_F2,
47         ARM_VFP_D2 = ARM_VFP_F4,
48         ARM_VFP_D3 = ARM_VFP_F6,
49         ARM_VFP_D4 = ARM_VFP_F8,
50         ARM_VFP_D5 = ARM_VFP_F10,
51         ARM_VFP_D6 = ARM_VFP_F12,
52         ARM_VFP_D7 = ARM_VFP_F14,
53         ARM_VFP_D8 = ARM_VFP_F16,
54         ARM_VFP_D9 = ARM_VFP_F18,
55         ARM_VFP_D10 = ARM_VFP_F20,
56         ARM_VFP_D11 = ARM_VFP_F22,
57         ARM_VFP_D12 = ARM_VFP_F24,
58         ARM_VFP_D13 = ARM_VFP_F26,
59         ARM_VFP_D14 = ARM_VFP_F28,
60         ARM_VFP_D15 = ARM_VFP_F30,
61
62         ARM_VFP_COPROC_SINGLE = 10,
63         ARM_VFP_COPROC_DOUBLE = 11,
64
65 #define ARM_VFP_OP(p,q,r,s) (((p) << 23) | ((q) << 21) | ((r) << 20) | ((s) << 6))
66 #define ARM_VFP_OP2(Fn,N) (ARM_VFP_OP (1,1,1,1) | ((Fn) << 16) | ((N) << 7))
67
68         ARM_VFP_MUL = ARM_VFP_OP (0,1,0,0),
69         ARM_VFP_NMUL = ARM_VFP_OP (0,1,0,1),
70         ARM_VFP_ADD = ARM_VFP_OP (0,1,1,0),
71         ARM_VFP_SUB = ARM_VFP_OP (0,1,1,1),
72         ARM_VFP_DIV = ARM_VFP_OP (1,0,0,0),
73
74         ARM_VFP_CPY = ARM_VFP_OP2 (0,0),
75         ARM_VFP_ABS = ARM_VFP_OP2 (0,1),
76         ARM_VFP_NEG = ARM_VFP_OP2 (1,0),
77         ARM_VFP_SQRT = ARM_VFP_OP2 (1,1),
78         ARM_VFP_CMP = ARM_VFP_OP2 (4,0),
79         ARM_VFP_CMPE = ARM_VFP_OP2 (4,1),
80         ARM_VFP_CMPZ = ARM_VFP_OP2 (5,0),
81         ARM_VFP_CMPEZ = ARM_VFP_OP2 (5,1),
82         ARM_VFP_CVT = ARM_VFP_OP2 (7,1),
83         ARM_VFP_UITO = ARM_VFP_OP2 (8,0),
84         ARM_VFP_SITO = ARM_VFP_OP2 (8,1),
85         ARM_VFP_TOUI = ARM_VFP_OP2 (12,0),
86         ARM_VFP_TOSI = ARM_VFP_OP2 (13,0),
87         ARM_VFP_TOUIZ = ARM_VFP_OP2 (12,1),
88         ARM_VFP_TOSIZ = ARM_VFP_OP2 (13,1),
89
90         ARM_VFP_SID = 0,
91         ARM_VFP_SCR = 1 << 1,
92         ARM_VFP_EXC = 8 << 1
93 };
94
95 #define ARM_DEF_VFP_DYADIC(cond,cp,op,Fd,Fn,Fm) \
96         (14 << 24)                              |       \
97         ((cp) << 8)                             |       \
98         (op)                                    |       \
99         (((Fd) >> 1) << 12)                     |       \
100         (((Fd) & 1) << 22)                      |       \
101         (((Fn) >> 1) << 16)                     |       \
102         (((Fn) & 1) << 7)                       |       \
103         (((Fm) >> 1) << 0)                      |       \
104         (((Fm) & 1) << 5)                       |       \
105         ARM_DEF_COND(cond)
106
107 #define ARM_DEF_VFP_MONADIC(cond,cp,op,Fd,Fm)   \
108         (14 << 24)                              |       \
109         ((cp) << 8)                             |       \
110         (op)                                    |       \
111         (((Fd) >> 1) << 12)                     |       \
112         (((Fd) & 1) << 22)                      |       \
113         (((Fm) >> 1) << 0)                      |       \
114         (((Fm) & 1) << 5)                       |       \
115         ARM_DEF_COND(cond)
116
117 #define ARM_DEF_VFP_LSF(cond,cp,post,ls,wback,basereg,Fd,offset)        \
118         ((offset) >= 0? (offset)>>2: -(offset)>>2)      |       \
119         (6 << 25)                                       |       \
120         ((cp) << 8)                                     |       \
121         (((Fd) >> 1) << 12)                             |       \
122         (((Fd) & 1) << 22)                              |       \
123         ((basereg) << 16)                               |       \
124         ((ls) << 20)                                    |       \
125         ((wback) << 21)                                 |       \
126         (((offset) >= 0) << 23)                         |       \
127         ((wback) << 21)                                 |       \
128         ((post) << 24)                                  |       \
129         ARM_DEF_COND(cond)
130
131 #define ARM_DEF_VFP_CPT(cond,cp,op,L,Fn,Rd)     \
132         (14 << 24)                              |       \
133         (1 << 4)                                |       \
134         ((cp) << 8)                             |       \
135         ((op) << 21)                            |       \
136         ((L) << 20)                             |       \
137         ((Rd) << 12)                            |       \
138         (((Fn) >> 1) << 16)                     |       \
139         (((Fn) & 1) << 7)                       |       \
140         ARM_DEF_COND(cond)
141
142 /* FP load and stores */
143 #define ARM_FLDS_COND(p,freg,base,offset,cond)  \
144         ARM_EMIT((p), ARM_DEF_VFP_LSF((cond),ARM_VFP_COPROC_SINGLE,1,ARMOP_LDR,0,(base),(freg),(offset)))
145 #define ARM_FLDS(p,freg,base,offset)    \
146         ARM_FLDS_COND(p,freg,base,offset,ARMCOND_AL)
147
148 #define ARM_FLDD_COND(p,freg,base,offset,cond)  \
149         ARM_EMIT((p), ARM_DEF_VFP_LSF((cond),ARM_VFP_COPROC_DOUBLE,1,ARMOP_LDR,0,(base),(freg),(offset)))
150 #define ARM_FLDD(p,freg,base,offset)    \
151         ARM_FLDD_COND(p,freg,base,offset,ARMCOND_AL)
152
153 #define ARM_FSTS_COND(p,freg,base,offset,cond)  \
154         ARM_EMIT((p), ARM_DEF_VFP_LSF((cond),ARM_VFP_COPROC_SINGLE,1,ARMOP_STR,0,(base),(freg),(offset)))
155 #define ARM_FSTS(p,freg,base,offset)    \
156         ARM_FSTS_COND(p,freg,base,offset,ARMCOND_AL)
157
158 #define ARM_FSTD_COND(p,freg,base,offset,cond)  \
159         ARM_EMIT((p), ARM_DEF_VFP_LSF((cond),ARM_VFP_COPROC_DOUBLE,1,ARMOP_STR,0,(base),(freg),(offset)))
160 #define ARM_FSTD(p,freg,base,offset)    \
161         ARM_FSTD_COND(p,freg,base,offset,ARMCOND_AL)
162
163 #define ARM_FLDMD_COND(p,first_reg,nregs,base,cond)                                                     \
164         ARM_EMIT((p), ARM_DEF_VFP_LSF((cond),ARM_VFP_COPROC_DOUBLE,0,ARMOP_LDR,0,(base),(first_reg),((nregs) * 2) << 2))
165
166 #define ARM_FLDMD(p,first_reg,nregs,base)               \
167         ARM_FLDMD_COND(p,first_reg,nregs,base,ARMCOND_AL)
168
169 #define ARM_FSTMD_COND(p,first_reg,nregs,base,cond)                                                     \
170         ARM_EMIT((p), ARM_DEF_VFP_LSF((cond),ARM_VFP_COPROC_DOUBLE,0,ARMOP_STR,0,(base),(first_reg),((nregs) * 2) << 2))
171
172 #define ARM_FSTMD(p,first_reg,nregs,base)               \
173         ARM_FSTMD_COND(p,first_reg,nregs,base,ARMCOND_AL)
174
175 #include <mono/arch/arm/arm_vfpmacros.h>
176
177 /* coprocessor register transfer */
178 #define ARM_FMSR(p,freg,reg)    \
179         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_SINGLE,0,0,(freg),(reg)))
180 #define ARM_FMRS(p,reg,freg)    \
181         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_SINGLE,0,1,(freg),(reg)))
182
183 #define ARM_FMDLR(p,freg,reg)   \
184         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_DOUBLE,0,0,(freg),(reg)))
185 #define ARM_FMRDL(p,reg,freg)   \
186         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_DOUBLE,0,1,(freg),(reg)))
187 #define ARM_FMDHR(p,freg,reg)   \
188         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_DOUBLE,1,0,(freg),(reg)))
189 #define ARM_FMRDH(p,reg,freg)   \
190         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_DOUBLE,1,1,(freg),(reg)))
191
192 #define ARM_FMXR(p,freg,reg)    \
193         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_SINGLE,7,0,(freg),(reg)))
194 #define ARM_FMRX(p,reg,fcreg)   \
195         ARM_EMIT((p), ARM_DEF_VFP_CPT(ARMCOND_AL,ARM_VFP_COPROC_SINGLE,7,1,(fcreg),(reg)))
196
197 #define ARM_FMSTAT(p)   \
198         ARM_FMRX((p),ARMREG_R15,ARM_VFP_SCR)
199
200 #define ARM_DEF_MCRR(cond,cp,rn,rd,Fm,M) \
201         ((Fm) << 0) |                                      \
202         (1 << 4)   |                                       \
203         ((M) << 5) |                                       \
204         ((cp) << 8) |                                      \
205         ((rd) << 12) |                                     \
206         ((rn) << 16) |                                     \
207         ((2) << 21) |                                      \
208         (12 << 24) |                                       \
209         ARM_DEF_COND(cond)
210
211 #define ARM_FMDRR(p,rd,rn,dm)   \
212         ARM_EMIT((p), ARM_DEF_MCRR(ARMCOND_AL,ARM_VFP_COPROC_DOUBLE,(rn),(rd),(dm) >> 1, (dm) & 1))
213
214 #define ARM_DEF_FMRRD(cond,cp,rn,rd,Dm,D)               \
215         ((Dm) << 0) |                                      \
216         (1 << 4)   |                                       \
217         ((cp) << 8) |                                      \
218         ((rd) << 12) |                                     \
219         ((rn) << 16) |                                     \
220         ((0xc5) << 20) |                                           \
221         ARM_DEF_COND(cond)
222
223 #define ARM_FMRRD(p,rd,rn,dm)   \
224         ARM_EMIT((p), ARM_DEF_FMRRD(ARMCOND_AL,ARM_VFP_COPROC_DOUBLE,(rn),(rd),(dm) >> 1, (dm) & 1))
225
226 #define ARM_DEF_FUITOS(cond,Dd,D,Fm,M) ((cond) << 28) | ((0x1d) << 23) | ((D) << 22) | ((0x3) << 20) | ((8) << 16) | ((Dd) << 12) | ((0xa) << 8) | ((1) << 6) | ((M) << 5) | ((Fm) << 0)
227
228 #define ARM_FUITOS(p,dreg,sreg) \
229         ARM_EMIT((p), ARM_DEF_FUITOS (ARMCOND_AL, (dreg) >> 1, (dreg) & 1, (sreg) >> 1, (sreg) & 1))
230
231 #define ARM_DEF_FUITOD(cond,Dd,D,Fm,M) ((cond) << 28) | ((0x1d) << 23) | ((D) << 22) | ((0x3) << 20) | ((8) << 16) | ((Dd) << 12) | ((0xb) << 8) | ((1) << 6) | ((M) << 5) | ((Fm) << 0)
232
233 #define ARM_FUITOD(p,dreg,sreg) \
234         ARM_EMIT((p), ARM_DEF_FUITOD (ARMCOND_AL, (dreg) >> 1, (dreg) & 1, (sreg) >> 1, (sreg) & 1))
235
236 #define ARM_DEF_FSITOS(cond,Dd,D,Fm,M) ((cond) << 28) | ((0x1d) << 23) | ((D) << 22) | ((0x3) << 20) | ((8) << 16) | ((Dd) << 12) | ((0xa) << 8) | ((1) << 7) | ((1) << 6) | ((M) << 5) | ((Fm) << 0)
237
238 #define ARM_FSITOS(p,dreg,sreg) \
239         ARM_EMIT((p), ARM_DEF_FSITOS (ARMCOND_AL, (dreg) >> 1, (dreg) & 1, (sreg) >> 1, (sreg) & 1))
240
241 #define ARM_DEF_FSITOD(cond,Dd,D,Fm,M) ((cond) << 28) | ((0x1d) << 23) | ((D) << 22) | ((0x3) << 20) | ((8) << 16) | ((Dd) << 12) | ((0xb) << 8) | ((1) << 7) | ((1) << 6) | ((M) << 5) | ((Fm) << 0)
242
243 #define ARM_FSITOD(p,dreg,sreg) \
244         ARM_EMIT((p), ARM_DEF_FSITOD (ARMCOND_AL, (dreg) >> 1, (dreg) & 1, (sreg) >> 1, (sreg) & 1))
245
246 #endif /* __MONO_ARM_VFP_CODEGEN_H__ */
247