2007-10-19 Marek Habersack <mhabersack@novell.com>
[mono.git] / mono / mini / inssel-float.brg
1 #if defined(MONO_ARCH_SOFT_FLOAT)
2 #define SOFT_FLOAT_IMPL TRUE
3 #else
4 #define SOFT_FLOAT_IMPL FALSE
5 #endif
6
7 typedef union {
8         guint32 vali [2];
9         double vald;
10 } DVal;
11
12 %%
13
14 #
15 # inssel-float.brg: burg file for floating point instructions
16 #
17 # Author:
18 #   Dietmar Maurer (dietmar@ximian.com)
19 #
20 # (C) 2002 Ximian, Inc.
21 #
22
23 #
24 # load/store
25 #
26
27 freg: CEE_LDIND_R4 (base) {
28         if (SOFT_FLOAT_IMPL) {
29                 g_assert_not_reached ();
30         } else {
31                 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADR4_MEMBASE, state->reg1, 
32                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
33         }
34 }
35
36 freg: CEE_LDIND_R8 (base) {
37         if (SOFT_FLOAT_IMPL) {
38                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, 
39                                        state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_LS_WORD_OFFSET);
40                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg2, 
41                                        state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_MS_WORD_OFFSET);
42         } else {
43                 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADR8_MEMBASE, state->reg1, 
44                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
45         }
46 }
47
48 stmt: CEE_STIND_R4 (base, freg) {
49         if (SOFT_FLOAT_IMPL) {
50                 g_assert_not_reached ();
51         } else {
52                 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORER4_MEMBASE_REG, state->left->tree->inst_basereg,
53                                  state->left->tree->inst_offset, state->right->reg1);
54         }
55 }
56
57 stmt: CEE_STIND_R8 (base, freg) {
58         if (SOFT_FLOAT_IMPL) {
59                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
60                                      state->left->tree->inst_offset + MINI_MS_WORD_OFFSET, state->right->reg2);
61                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
62                                      state->left->tree->inst_offset + MINI_LS_WORD_OFFSET, state->right->reg1);
63         } else {
64                 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORER8_MEMBASE_REG, state->left->tree->inst_basereg,
65                                  state->left->tree->inst_offset, state->right->reg1);
66         }
67 }
68
69 freg: OP_R4CONST {
70         if (SOFT_FLOAT_IMPL) {
71                 DVal d;
72                 /* we load the r8 value */
73                 d.vald = *(float*)tree->inst_p0;
74                 MONO_EMIT_NEW_ICONST (s, state->reg1, d.vali [MINI_LS_WORD_IDX]);
75                 MONO_EMIT_NEW_ICONST (s, state->reg2, d.vali [MINI_MS_WORD_IDX]);
76         } else {
77                 tree->dreg = state->reg1;
78                 mono_bblock_add_inst (s->cbb, tree);
79         }
80 }
81
82 freg: OP_R8CONST {
83         if (SOFT_FLOAT_IMPL) {
84                 DVal d;
85                 d.vald = *(double*)tree->inst_p0;
86                 MONO_EMIT_NEW_ICONST (s, state->reg1, d.vali [MINI_LS_WORD_IDX]);
87                 MONO_EMIT_NEW_ICONST (s, state->reg2, d.vali [MINI_MS_WORD_IDX]);
88         } else {
89                 tree->dreg = state->reg1;
90                 mono_bblock_add_inst (s->cbb, tree);
91         }
92 }
93
94 #
95 # fp alu operations 
96
97
98 freg: OP_FADD (freg, freg) {
99         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
100 }
101
102 freg: OP_FSUB (freg, freg) {
103         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
104 }
105
106 freg: OP_FMUL (freg, freg) {
107         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
108 }
109
110 freg: OP_FDIV (freg, freg) {
111         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
112 }
113
114 freg: OP_FREM (freg, freg) {
115         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
116 }
117
118 freg: OP_FNEG (freg) {
119         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
120 }
121
122 freg: OP_CKFINITE (freg) {
123         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
124 }
125
126 freg: OP_SIN (freg) {
127         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
128 }
129
130 freg: OP_COS (freg) {
131         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
132 }
133
134 freg: OP_ABS (freg) {
135         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
136 }
137
138 freg: OP_TAN (freg) {
139         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
140 }
141
142 freg: OP_ATAN (freg) {
143         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
144 }
145
146 freg: OP_SQRT (freg) {
147         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
148 }
149
150 #
151 # floating point conversions
152 #
153
154 reg: OP_FCONV_TO_I4 (freg) {
155         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
156 }
157
158 reg: OP_FCONV_TO_U4 (freg) {
159         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
160 }
161
162 reg: OP_FCONV_TO_OVF_I4 (freg) {
163         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
164 }
165
166 reg: OP_FCONV_TO_OVF_U4 (freg) {
167         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
168 }
169
170 reg: OP_FCONV_TO_OVF_I8 (freg) {
171         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
172 }
173
174 reg: OP_FCONV_TO_OVF_U8 (freg) {
175         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
176 }
177
178 reg: OP_FCONV_TO_OVF_I (freg) {
179         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
180 }
181
182 reg: OP_FCONV_TO_OVF_U (freg) {
183         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
184 }
185
186 reg: OP_FCONV_TO_I (freg) {
187         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
188 }
189
190 reg: OP_FCONV_TO_U (freg) {
191         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
192 }
193
194 reg: OP_FCONV_TO_I2 (freg) {
195         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
196 }
197
198 reg: OP_FCONV_TO_U2 (freg) {
199         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
200 }
201
202 reg: OP_FCONV_TO_I1 (freg) {
203         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
204 }
205
206 reg: OP_FCONV_TO_U1 (freg) {
207         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
208 }
209
210 freg: OP_FCONV_TO_R8 (freg) {
211         MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->reg1);
212 }
213
214 freg: OP_FCONV_TO_R4 (freg) {
215         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
216 }
217
218 freg: CEE_CONV_R4 (reg) "2" {
219         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
220 }
221
222 freg: CEE_CONV_R8 (reg) "2" {
223         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
224 }
225
226 freg: CEE_CONV_R_UN (reg) "2" {
227         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
228 }
229
230 #
231 # control flow
232 #
233
234 # CPUs using the same condition flags for integers and float
235 # can use the following chain rule:
236 # cflags: fpcflags "0"
237 # that way all branches are handled by inssel.brg
238
239 fpcflags: OP_COMPARE (freg, freg) {
240         tree->opcode = OP_FCOMPARE;
241         tree->sreg1 = state->left->reg1;
242         tree->sreg2 = state->right->reg1;
243         mono_bblock_add_inst (s->cbb, tree);
244 }
245
246 #
247 # miscellaneous fp operations
248 #
249
250 stmt: CEE_POP (freg) {
251         /* do nothing */
252 }     
253
254 %%