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