* src/vm/jit/emit-common.c: Fixed warning related to STATISTICS.
[cacao.git] / src / vm / jit / emit-common.c
1 /* src/vm/jit/emit-common.c - common code emitter functions
2
3    Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "arch.h"
37 #include "codegen.h"
38
39 #include "vm/jit/emit-common.h"
40 #include "vm/jit/jit.h"
41
42 #include "vmcore/options.h"
43 #include "vmcore/statistics.h"
44
45
46 /* emit_load_s1 ****************************************************************
47
48    Emits a possible load of the first source operand.
49
50 *******************************************************************************/
51
52 s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
53 {
54         varinfo *src;
55         s4       reg;
56
57         src = VAROP(iptr->s1);
58
59         reg = emit_load(jd, iptr, src, tempreg);
60
61         return reg;
62 }
63
64
65 /* emit_load_s2 ****************************************************************
66
67    Emits a possible load of the second source operand.
68
69 *******************************************************************************/
70
71 s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
72 {
73         varinfo *src;
74         s4       reg;
75
76         src = VAROP(iptr->sx.s23.s2);
77
78         reg = emit_load(jd, iptr, src, tempreg);
79
80         return reg;
81 }
82
83
84 /* emit_load_s3 ****************************************************************
85
86    Emits a possible load of the third source operand.
87
88 *******************************************************************************/
89
90 s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
91 {
92         varinfo *src;
93         s4       reg;
94
95         src = VAROP(iptr->sx.s23.s3);
96
97         reg = emit_load(jd, iptr, src, tempreg);
98
99         return reg;
100 }
101
102
103 /* emit_load_s1_low ************************************************************
104
105    Emits a possible load of the low 32-bits of the first long source
106    operand.
107
108 *******************************************************************************/
109
110 #if SIZEOF_VOID_P == 4
111 s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg)
112 {
113         varinfo *src;
114         s4       reg;
115
116         src = VAROP(iptr->s1);
117
118         reg = emit_load_low(jd, iptr, src, tempreg);
119
120         return reg;
121 }
122 #endif
123
124
125 /* emit_load_s2_low ************************************************************
126
127    Emits a possible load of the low 32-bits of the second long source
128    operand.
129
130 *******************************************************************************/
131
132 #if SIZEOF_VOID_P == 4
133 s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg)
134 {
135         varinfo *src;
136         s4       reg;
137
138         src = VAROP(iptr->sx.s23.s2);
139
140         reg = emit_load_low(jd, iptr, src, tempreg);
141
142         return reg;
143 }
144 #endif
145
146
147 /* emit_load_s3_low ************************************************************
148
149    Emits a possible load of the low 32-bits of the third long source
150    operand.
151
152 *******************************************************************************/
153
154 #if SIZEOF_VOID_P == 4
155 s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg)
156 {
157         varinfo *src;
158         s4       reg;
159
160         src = VAROP(iptr->sx.s23.s3);
161
162         reg = emit_load_low(jd, iptr, src, tempreg);
163
164         return reg;
165 }
166 #endif
167
168
169 /* emit_load_s1_high ***********************************************************
170
171    Emits a possible load of the high 32-bits of the first long source
172    operand.
173
174 *******************************************************************************/
175
176 #if SIZEOF_VOID_P == 4
177 s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg)
178 {
179         varinfo *src;
180         s4       reg;
181
182         src = VAROP(iptr->s1);
183
184         reg = emit_load_high(jd, iptr, src, tempreg);
185
186         return reg;
187 }
188 #endif
189
190
191 /* emit_load_s2_high ***********************************************************
192
193    Emits a possible load of the high 32-bits of the second long source
194    operand.
195
196 *******************************************************************************/
197
198 #if SIZEOF_VOID_P == 4
199 s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg)
200 {
201         varinfo *src;
202         s4       reg;
203
204         src = VAROP(iptr->sx.s23.s2);
205
206         reg = emit_load_high(jd, iptr, src, tempreg);
207
208         return reg;
209 }
210 #endif
211
212
213 /* emit_load_s3_high ***********************************************************
214
215    Emits a possible load of the high 32-bits of the third long source
216    operand.
217
218 *******************************************************************************/
219
220 #if SIZEOF_VOID_P == 4
221 s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg)
222 {
223         varinfo *src;
224         s4       reg;
225
226         src = VAROP(iptr->sx.s23.s3);
227
228         reg = emit_load_high(jd, iptr, src, tempreg);
229
230         return reg;
231 }
232 #endif
233
234
235 /* emit_store_dst **************************************************************
236
237    This function generates the code to store the result of an
238    operation back into a spilled pseudo-variable.  If the
239    pseudo-variable has not been spilled in the first place, this
240    function will generate nothing.
241     
242 *******************************************************************************/
243
244 void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
245 {
246         emit_store(jd, iptr, VAROP(iptr->dst), d);
247 }
248
249
250 /* emit_bccz *******************************************************************
251
252    Emit conditional and unconditional branch instructions on integer
253    regiseters.
254
255 *******************************************************************************/
256
257 void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
258 {
259         s4 branchmpc;
260         s4 disp;
261
262         /* Target basic block already has an PC, so we can generate the
263            branch immediately. */
264
265         if ((target->mpc >= 0)) {
266                 STATISTICS(count_branches_resolved++);
267
268                 /* calculate the mpc of the branch instruction */
269
270                 branchmpc = cd->mcodeptr - cd->mcodebase;
271                 disp      = target->mpc - branchmpc;
272
273                 #if defined(STATISTICS)
274                         count_emit_branch++;
275                         if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
276                         else if ((int16_t)disp == disp) count_emit_branch_16bit++;
277                         else if ((int32_t)disp == disp) count_emit_branch_32bit++;
278                         #if (SIZEOF_VOID_P == 8)
279                         else if ((int64_t)disp == disp) count_emit_branch_64bit++;
280                         #endif
281                 #endif
282                 emit_branch(cd, disp, condition, reg, options);
283         }
284         else {
285                 /* current mcodeptr is the correct position,
286                    afterwards emit the NOPs */
287
288                 codegen_add_branch_ref(cd, target, condition, reg, options);
289
290                 /* generate NOPs as placeholder for branch code */
291
292                 BRANCH_NOPS;
293         }
294 }
295
296
297 /* emit_bcc ********************************************************************
298
299    Emit conditional and unconditional branch instructions on condition
300    codes.
301
302 *******************************************************************************/
303
304 void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
305 {
306         emit_bccz(cd, target, condition, -1, options);
307 }
308
309
310 /* emit_br *********************************************************************
311
312    Wrapper for unconditional branches.
313
314 *******************************************************************************/
315
316 void emit_br(codegendata *cd, basicblock *target)
317 {
318         emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
319 }
320
321
322 /* emit_bxxz *******************************************************************
323
324    Wrappers for branches on one integer register.
325
326 *******************************************************************************/
327
328 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
329
330 void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
331 {
332         emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
333 }
334
335 void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
336 {
337         emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
338 }
339
340 void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
341 {
342         emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
343 }
344
345 void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
346 {
347         emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
348 }
349
350 void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
351 {
352         emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
353 }
354
355 void emit_blez(codegendata *cd, basicblock *target, s4 reg)
356 {
357         emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
358 }
359
360 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
361
362
363 /* emit_bxx ********************************************************************
364
365    Wrappers for branches on two integer registers.
366
367    We use PACK_REGS here, so we don't have to change the branchref
368    data structure and the emit_bccz function.
369
370 *******************************************************************************/
371
372 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
373
374 void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
375 {
376         emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
377 }
378
379 void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
380 {
381         emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
382 }
383
384 #endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
385
386
387 /* emit_bxx ********************************************************************
388
389    Wrappers for branches on condition codes.
390
391 *******************************************************************************/
392
393 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
394
395 void emit_beq(codegendata *cd, basicblock *target)
396 {
397         emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
398 }
399
400 void emit_bne(codegendata *cd, basicblock *target)
401 {
402         emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
403 }
404
405 void emit_blt(codegendata *cd, basicblock *target)
406 {
407         emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
408 }
409
410 void emit_bge(codegendata *cd, basicblock *target)
411 {
412         emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
413 }
414
415 void emit_bgt(codegendata *cd, basicblock *target)
416 {
417         emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
418 }
419
420 void emit_ble(codegendata *cd, basicblock *target)
421 {
422         emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
423 }
424
425 #if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
426 void emit_bult(codegendata *cd, basicblock *target)
427 {
428         emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
429 }
430
431 void emit_bule(codegendata *cd, basicblock *target)
432 {
433         emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
434 }
435
436 void emit_buge(codegendata *cd, basicblock *target)
437 {
438         emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
439 }
440
441 void emit_bugt(codegendata *cd, basicblock *target)
442 {
443         emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
444 }
445 #endif
446
447 #if defined(__POWERPC__) || defined(__POWERPC64__)
448 void emit_bnan(codegendata *cd, basicblock *target)
449 {
450         emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
451 }
452 #endif
453
454 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
455
456
457 /* emit_label_bccz *************************************************************
458
459    Emit a branch to a label.  Possibly emit the branch, if it is a
460    backward branch.
461
462 *******************************************************************************/
463
464 void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
465 {
466         list_t             *list;
467         branch_label_ref_t *br;
468         s4                  mpc;
469         s4                  disp;
470
471         /* get the label list */
472
473         list = cd->brancheslabel;
474
475         /* search if the label is already in the list */
476
477         for (br = list_first_unsynced(list); br != NULL;
478                  br = list_next_unsynced(list, br)) {
479                 /* is this entry the correct label? */
480
481                 if (br->label == label)
482                         break;
483         }
484
485         /* a branch reference was found */
486
487         if (br != NULL) {
488                 /* calculate the mpc of the branch instruction */
489
490                 mpc  = cd->mcodeptr - cd->mcodebase;
491                 disp = br->mpc - mpc;
492
493                 #if defined(STATISTICS)
494                         count_emit_branch++;
495                         if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
496                         else if ((int16_t)disp == disp) count_emit_branch_16bit++;
497                         else if ((int32_t)disp == disp) count_emit_branch_32bit++;
498                         #if (SIZEOF_VOID_P == 8)
499                         else if ((int64_t)disp == disp) count_emit_branch_64bit++;
500                         #endif
501                 #endif
502                 emit_branch(cd, disp, condition, reg, options);
503
504                 /* now remove the branch reference */
505
506                 list_remove_unsynced(list, br);
507         }
508         else {
509                 /* current mcodeptr is the correct position,
510                    afterwards emit the NOPs */
511
512                 codegen_branch_label_add(cd, label, condition, reg, options);
513
514                 /* generate NOPs as placeholder for branch code */
515
516                 BRANCH_NOPS;
517         }
518 }
519
520
521 /* emit_label ******************************************************************
522
523    Emit a label for a branch.  Possibly emit the branch, if it is a
524    forward branch.
525
526 *******************************************************************************/
527
528 void emit_label(codegendata *cd, s4 label)
529 {
530         list_t             *list;
531         branch_label_ref_t *br;
532         s4                  mpc;
533         s4                  disp;
534         u1                 *mcodeptr;
535
536         /* get the label list */
537
538         list = cd->brancheslabel;
539
540         /* search if the label is already in the list */
541
542         for (br = list_first_unsynced(list); br != NULL;
543                  br = list_next_unsynced(list, br)) {
544                 /* is this entry the correct label? */
545
546                 if (br->label == label)
547                         break;
548         }
549
550         /* a branch reference was found */
551
552         if (br != NULL) {
553                 /* calculate the mpc of the branch instruction */
554
555                 mpc  = cd->mcodeptr - cd->mcodebase;
556                 disp = mpc - br->mpc;
557
558                 /* temporary set the mcodeptr */
559
560                 mcodeptr     = cd->mcodeptr;
561                 cd->mcodeptr = cd->mcodebase + br->mpc;
562
563                 #if defined(STATISTICS)
564                         count_emit_branch++;
565                         if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
566                         else if ((int16_t)disp == disp) count_emit_branch_16bit++;
567                         else if ((int32_t)disp == disp) count_emit_branch_32bit++;
568                         #if (SIZEOF_VOID_P == 8)
569                         else if ((int64_t)disp == disp) count_emit_branch_64bit++;
570                         #endif
571                 #endif
572                 emit_branch(cd, disp, br->condition, br->reg, br->options);
573
574                 /* restore mcodeptr */
575
576                 cd->mcodeptr = mcodeptr;
577
578                 /* now remove the branch reference */
579
580                 list_remove_unsynced(list, br);
581         }
582         else {
583                 /* add the label to the list (use invalid values for condition
584                    and register) */
585
586                 codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
587         }
588 }
589
590
591 /* emit_label_bcc **************************************************************
592
593    Emit conditional and unconditional label-branch instructions on
594    condition codes.
595
596 *******************************************************************************/
597
598 void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
599 {
600         emit_label_bccz(cd, label, condition, -1, options);
601 }
602
603
604 /* emit_label_br ***************************************************************
605
606    Wrapper for unconditional label-branches.
607
608 *******************************************************************************/
609
610 void emit_label_br(codegendata *cd, s4 label)
611 {
612         emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
613 }
614
615
616 /* emit_label_bxxz *************************************************************
617
618    Wrappers for label-branches on one integer register.
619
620 *******************************************************************************/
621
622 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
623
624 void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
625 {
626         emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
627 }
628
629 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
630
631
632 /* emit_label_bxx **************************************************************
633
634    Wrappers for label-branches on condition codes.
635
636 *******************************************************************************/
637
638 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
639
640 void emit_label_beq(codegendata *cd, s4 label)
641 {
642         emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
643 }
644
645 void emit_label_bne(codegendata *cd, s4 label)
646 {
647         emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
648 }
649
650 void emit_label_blt(codegendata *cd, s4 label)
651 {
652         emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
653 }
654
655 void emit_label_bge(codegendata *cd, s4 label)
656 {
657         emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
658 }
659
660 void emit_label_bgt(codegendata *cd, s4 label)
661 {
662         emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
663 }
664
665 void emit_label_ble(codegendata *cd, s4 label)
666 {
667         emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
668 }
669
670 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
671
672
673 /*
674  * These are local overrides for various environment variables in Emacs.
675  * Please do not remove this and leave it at the end of the file, where
676  * Emacs will automagically detect them.
677  * ---------------------------------------------------------------------
678  * Local variables:
679  * mode: c
680  * indent-tabs-mode: t
681  * c-basic-offset: 4
682  * tab-width: 4
683  * End:
684  * vim:noexpandtab:sw=4:ts=4:
685  */