* src/vm/jit/builtin.hpp (builtintable_entry): Added function pointer to
[cacao.git] / src / vm / jit / emit-common.hpp
1 /* src/vm/jit/emit-common.hpp - common code emitter functions
2
3    Copyright (C) 2006, 2007, 2008, 2009
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5    Copyright (C) 2009 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #ifndef _EMIT_COMMON_HPP
28 #define _EMIT_COMMON_HPP
29
30 #include "config.h"
31 #include "vm/types.h"
32
33 #include "arch.h"
34 #include "codegen.h"
35
36 #include "vm/jit/codegen-common.hpp"
37 #include "vm/jit/jit.hpp"
38
39
40 /* branch labels **************************************************************/
41
42 #define BRANCH_LABEL_1    1
43 #define BRANCH_LABEL_2    2
44 #define BRANCH_LABEL_3    3
45 #define BRANCH_LABEL_4    4
46 #define BRANCH_LABEL_5    5
47 #define BRANCH_LABEL_6    6
48 #define BRANCH_LABEL_7    7
49 #define BRANCH_LABEL_8    8
50 #define BRANCH_LABEL_9    9
51 #define BRANCH_LABEL_10  10
52
53
54 /* constant range macros ******************************************************/
55
56 #if SIZEOF_VOID_P == 8
57
58 # define IS_IMM8(c) \
59     (((s8) (c) >= -128) && ((s8) (c) <= 127))
60
61 # define IS_IMM32(c) \
62     (((s8) (c) >= (-2147483647-1)) && ((s8) (c) <= 2147483647))
63
64 #else
65
66 # define IS_IMM8(c) \
67     (((s4) (c) >= -128) && ((s4) (c) <= 127))
68
69 # define IS_IMM16(c) \
70     (((s4) (c) >= -32768) && ((s4) (c) <= 32767))
71
72 #endif
73
74
75 /* code generation functions **************************************************/
76
77 #ifdef __cplusplus
78 extern "C" {
79 #endif
80
81 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
82 s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg);
83 s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg);
84 s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg);
85
86 #if SIZEOF_VOID_P == 4
87 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
88 s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg);
89 s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg);
90 s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg);
91
92 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
93 s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg);
94 s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg);
95 s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg);
96 #endif
97
98 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
99 void emit_store_dst(jitdata *jd, instruction *iptr, s4 d);
100
101 #if SIZEOF_VOID_P == 4
102 void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
103 void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
104 #endif
105
106 void emit_copy(jitdata *jd, instruction *iptr);
107
108 void emit_iconst(codegendata *cd, s4 d, s4 value);
109 void emit_lconst(codegendata *cd, s4 d, s8 value);
110
111 /* compare-emitting functions targeting an integer register */
112
113 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
114 void emit_icmpeq_imm(codegendata* cd, int reg, int32_t value, int d);
115 #endif
116
117 /* compare-emitting functions targeting the condition register */
118
119 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
120 void emit_icmp_imm(codegendata* cd, int reg, int32_t value);
121 #endif
122
123 /* branch-emitting functions */
124 void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
125 void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
126
127 /* wrapper for unconditional branches */
128 void emit_br(codegendata *cd, basicblock *target);
129
130 /* wrappers for branches on one integer register */
131
132 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
133 void emit_beqz(codegendata *cd, basicblock *target, s4 reg);
134 void emit_bnez(codegendata *cd, basicblock *target, s4 reg);
135 void emit_bltz(codegendata *cd, basicblock *target, s4 reg);
136 void emit_bgez(codegendata *cd, basicblock *target, s4 reg);
137 void emit_bgtz(codegendata *cd, basicblock *target, s4 reg);
138 void emit_blez(codegendata *cd, basicblock *target, s4 reg);
139 #endif
140
141 /* wrappers for branches on two integer registers */
142
143 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
144 void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2);
145 void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2);
146 #endif
147
148 /* wrappers for branches on condition codes */
149
150 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
151 void emit_beq(codegendata *cd, basicblock *target);
152 void emit_bne(codegendata *cd, basicblock *target);
153 void emit_blt(codegendata *cd, basicblock *target);
154 void emit_bge(codegendata *cd, basicblock *target);
155 void emit_bgt(codegendata *cd, basicblock *target);
156 void emit_ble(codegendata *cd, basicblock *target);
157 #endif
158
159 #if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
160 void emit_bult(codegendata *cd, basicblock *target);
161 void emit_bule(codegendata *cd, basicblock *target);
162 void emit_buge(codegendata *cd, basicblock *target);
163 void emit_bugt(codegendata *cd, basicblock *target);
164 #endif
165
166 #if defined(__POWERPC__) || defined(__POWERPC64__)
167 void emit_bnan(codegendata *cd, basicblock *target);
168 #endif
169
170 /* label-branches */
171 void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
172 void emit_label(codegendata *cd, s4 label);
173 void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
174
175 void emit_label_br(codegendata *cd, s4 label);
176
177 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
178 void emit_label_beqz(codegendata* cd, int label, int reg);
179 void emit_label_bnez(codegendata* cd, int label, int reg);
180 void emit_label_bltz(codegendata* cd, int label, int reg);
181 void emit_label_bgtz(codegendata* cd, int label, int reg);
182 #endif
183
184 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
185 void emit_label_beq(codegendata* cd, int label, int s1, int s2);
186 void emit_label_bne(codegendata* cd, int label, int s1, int s2);
187 #endif
188
189 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
190 void emit_label_beq(codegendata *cd, s4 label);
191 void emit_label_bne(codegendata *cd, s4 label);
192 void emit_label_blt(codegendata *cd, s4 label);
193 void emit_label_bge(codegendata *cd, s4 label);
194 void emit_label_bgt(codegendata *cd, s4 label);
195 void emit_label_ble(codegendata *cd, s4 label);
196 #endif
197
198 /* machine dependent branch-emitting function */
199 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options);
200
201 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg);
202 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
203 void emit_arraystore_check(codegendata *cd, instruction *iptr);
204 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1);
205 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
206 void emit_exception_check(codegendata *cd, instruction *iptr);
207
208 void emit_trap_compiler(codegendata *cd);
209 void emit_trap_countdown(codegendata *cd, s4 *counter);
210 uint32_t emit_trap(codegendata *cd);
211
212 void emit_patcher_traps(jitdata *jd);
213
214 void emit_recompute_pv(codegendata* cd);
215
216 /* machine dependent faspath-emitting functions */
217 void emit_fastpath_monitor_enter(jitdata* jd, instruction* iptr, int d);
218 void emit_fastpath_monitor_exit(jitdata* jd, instruction* iptr, int d);
219
220 #if defined(ENABLE_THREADS)
221 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset);
222 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset);
223 #endif
224
225 #if defined(ENABLE_PROFILING)
226 void emit_profile_method(codegendata* cd, codeinfo* code);
227 void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr);
228 void emit_profile_cycle_start(codegendata* cd, codeinfo* code);
229 void emit_profile_cycle_stop(codegendata* cd, codeinfo* code);
230 #endif
231
232 void emit_verbosecall_enter(jitdata *jd);
233 void emit_verbosecall_exit(jitdata *jd);
234
235 #ifdef __cplusplus
236 }
237 #endif
238
239
240 /* inline code generation functions *******************************************/
241
242 /**
243  * Generates an integer-move from register s to d. If s and d are
244  * the same registers, no code will be generated.
245  */
246 static inline void emit_imove(codegendata* cd, int s, int d)
247 {
248         if (s != d)
249 #if defined(__ARM__)
250                 // XXX Fix this!!!
251                 M_MOV(d, s);
252 #else
253                 M_MOV(s, d);
254 #endif
255 }
256
257
258 /**
259  * Generates a long-move from register s to d. If s and d are
260  * the same registers, no code will be generated.
261  */
262 static inline void emit_lmove(codegendata* cd, int s, int d)
263 {
264 #if SIZEOF_VOID_P == 8
265         emit_imove(cd, s, d);
266 #else
267         if (GET_HIGH_REG(s) == GET_LOW_REG(d)) {
268                 assert((GET_LOW_REG(s) != GET_HIGH_REG(d)));
269                 emit_imove(cd, GET_HIGH_REG(s), GET_HIGH_REG(d));
270                 emit_imove(cd, GET_LOW_REG(s), GET_LOW_REG(d));
271         } else {
272                 emit_imove(cd, GET_LOW_REG(s), GET_LOW_REG(d));
273                 emit_imove(cd, GET_HIGH_REG(s), GET_HIGH_REG(d));
274         }
275 #endif
276 }
277
278
279 /**
280  * Generates a float-move from register s to d. If s and d are
281  * the same registers, no code will be generated.
282  */
283 static inline void emit_fmove(codegendata* cd, int s, int d)
284 {
285         if (s != d)
286                 M_FMOV(s, d);
287 }
288
289
290 /**
291  * Generates an double-move from register s to d. If s and d are
292  * the same registers, no code will be generated.
293  */
294 static inline void emit_dmove(codegendata* cd, int s, int d)
295 {
296         if (s != d)
297                 M_DMOV(s, d);
298 }
299
300
301 /* preserve compatibility with legacy code ************************************/
302
303 #define M_INTMOVE(a, b)      emit_imove(cd, a, b)
304 #define M_LNGMOVE(a, b)      emit_lmove(cd, a, b)
305 #define M_FLTMOVE(a, b)      emit_fmove(cd, a, b)
306 #define M_DBLMOVE(a, b)      emit_dmove(cd, a, b)
307
308
309 #endif /* _EMIT_COMMON_HPP */
310
311
312 /*
313  * These are local overrides for various environment variables in Emacs.
314  * Please do not remove this and leave it at the end of the file, where
315  * Emacs will automagically detect them.
316  * ---------------------------------------------------------------------
317  * Local variables:
318  * mode: c
319  * indent-tabs-mode: t
320  * c-basic-offset: 4
321  * tab-width: 4
322  * End:
323  * vim:noexpandtab:sw=4:ts=4:
324  */