* Removed all Id tags.
[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 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32
33 #include "vm/types.h"
34
35 #include "arch.h"
36 #include "codegen.h"
37
38 #include "vm/jit/emit-common.h"
39 #include "vm/jit/jit.h"
40 #include "vm/jit/patcher-common.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_patcher_traps **********************************************************
251
252    Generates the code for the patcher traps.
253
254 *******************************************************************************/
255
256 void emit_patcher_traps(jitdata *jd)
257 {
258         codegendata *cd;
259         codeinfo    *code;
260         patchref_t  *pr;
261         u1          *savedmcodeptr;
262         u1          *tmpmcodeptr;
263         uint32_t     mcode;
264
265         /* get required compiler data */
266
267         cd   = jd->cd;
268         code = jd->code;
269
270         /* generate patcher traps code */
271
272         for (pr = list_first_unsynced(code->patchers); pr != NULL; pr = list_next_unsynced(code->patchers, pr)) {
273
274                 /* Calculate the patch position where the original machine
275                    code is located and the trap should be placed. */
276
277                 tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
278
279                 /* Patch in the trap to call the signal handler (done at
280                    compile time). */
281
282                 savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
283                 cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
284
285                 mcode = emit_trap(cd);
286
287                 cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
288
289                 /* Remember the original machine code which is patched
290                    back in later (done at runtime). */
291
292                 pr->mcode = mcode;
293         }
294 }
295
296
297 /* emit_bccz *******************************************************************
298
299    Emit conditional and unconditional branch instructions on integer
300    regiseters.
301
302 *******************************************************************************/
303
304 void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
305 {
306         s4 branchmpc;
307         s4 disp;
308
309         /* Target basic block already has an PC, so we can generate the
310            branch immediately. */
311
312         if ((target->mpc >= 0)) {
313                 STATISTICS(count_branches_resolved++);
314
315                 /* calculate the mpc of the branch instruction */
316
317                 branchmpc = cd->mcodeptr - cd->mcodebase;
318                 disp      = target->mpc - branchmpc;
319
320 #if defined(ENABLE_STATISTICS)
321                 count_emit_branch++;
322                 if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
323                 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
324                 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
325 # if SIZEOF_VOID_P == 8
326                 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
327 # endif
328 #endif
329
330                 emit_branch(cd, disp, condition, reg, options);
331         }
332         else {
333                 /* current mcodeptr is the correct position,
334                    afterwards emit the NOPs */
335
336                 codegen_add_branch_ref(cd, target, condition, reg, options);
337
338                 /* generate NOPs as placeholder for branch code */
339
340                 BRANCH_NOPS;
341         }
342 }
343
344
345 /* emit_bcc ********************************************************************
346
347    Emit conditional and unconditional branch instructions on condition
348    codes.
349
350 *******************************************************************************/
351
352 void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
353 {
354         emit_bccz(cd, target, condition, -1, options);
355 }
356
357
358 /* emit_br *********************************************************************
359
360    Wrapper for unconditional branches.
361
362 *******************************************************************************/
363
364 void emit_br(codegendata *cd, basicblock *target)
365 {
366         emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
367 }
368
369
370 /* emit_bxxz *******************************************************************
371
372    Wrappers for branches on one integer register.
373
374 *******************************************************************************/
375
376 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
377
378 void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
379 {
380         emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
381 }
382
383 void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
384 {
385         emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
386 }
387
388 void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
389 {
390         emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
391 }
392
393 void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
394 {
395         emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
396 }
397
398 void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
399 {
400         emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
401 }
402
403 void emit_blez(codegendata *cd, basicblock *target, s4 reg)
404 {
405         emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
406 }
407
408 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
409
410
411 /* emit_bxx ********************************************************************
412
413    Wrappers for branches on two integer registers.
414
415    We use PACK_REGS here, so we don't have to change the branchref
416    data structure and the emit_bccz function.
417
418 *******************************************************************************/
419
420 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
421
422 void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
423 {
424         emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
425 }
426
427 void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
428 {
429         emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
430 }
431
432 #endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
433
434
435 /* emit_bxx ********************************************************************
436
437    Wrappers for branches on condition codes.
438
439 *******************************************************************************/
440
441 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
442
443 void emit_beq(codegendata *cd, basicblock *target)
444 {
445         emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
446 }
447
448 void emit_bne(codegendata *cd, basicblock *target)
449 {
450         emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
451 }
452
453 void emit_blt(codegendata *cd, basicblock *target)
454 {
455         emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
456 }
457
458 void emit_bge(codegendata *cd, basicblock *target)
459 {
460         emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
461 }
462
463 void emit_bgt(codegendata *cd, basicblock *target)
464 {
465         emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
466 }
467
468 void emit_ble(codegendata *cd, basicblock *target)
469 {
470         emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
471 }
472
473 #if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
474 void emit_bult(codegendata *cd, basicblock *target)
475 {
476         emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
477 }
478
479 void emit_bule(codegendata *cd, basicblock *target)
480 {
481         emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
482 }
483
484 void emit_buge(codegendata *cd, basicblock *target)
485 {
486         emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
487 }
488
489 void emit_bugt(codegendata *cd, basicblock *target)
490 {
491         emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
492 }
493 #endif
494
495 #if defined(__POWERPC__) || defined(__POWERPC64__)
496 void emit_bnan(codegendata *cd, basicblock *target)
497 {
498         emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
499 }
500 #endif
501
502 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
503
504
505 /* emit_label_bccz *************************************************************
506
507    Emit a branch to a label.  Possibly emit the branch, if it is a
508    backward branch.
509
510 *******************************************************************************/
511
512 void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
513 {
514         list_t             *list;
515         branch_label_ref_t *br;
516         s4                  mpc;
517         s4                  disp;
518
519         /* get the label list */
520
521         list = cd->brancheslabel;
522
523         /* search if the label is already in the list */
524
525         for (br = list_first_unsynced(list); br != NULL;
526                  br = list_next_unsynced(list, br)) {
527                 /* is this entry the correct label? */
528
529                 if (br->label == label)
530                         break;
531         }
532
533         /* a branch reference was found */
534
535         if (br != NULL) {
536                 /* calculate the mpc of the branch instruction */
537
538                 mpc  = cd->mcodeptr - cd->mcodebase;
539                 disp = br->mpc - mpc;
540
541 #if defined(ENABLE_STATISTICS)
542                 count_emit_branch++;
543                 if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
544                 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
545                 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
546 # if SIZEOF_VOID_P == 8
547                 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
548 # endif
549 #endif
550
551                 emit_branch(cd, disp, condition, reg, options);
552
553                 /* now remove the branch reference */
554
555                 list_remove_unsynced(list, br);
556         }
557         else {
558                 /* current mcodeptr is the correct position,
559                    afterwards emit the NOPs */
560
561                 codegen_branch_label_add(cd, label, condition, reg, options);
562
563                 /* generate NOPs as placeholder for branch code */
564
565                 BRANCH_NOPS;
566         }
567 }
568
569
570 /* emit_label ******************************************************************
571
572    Emit a label for a branch.  Possibly emit the branch, if it is a
573    forward branch.
574
575 *******************************************************************************/
576
577 void emit_label(codegendata *cd, s4 label)
578 {
579         list_t             *list;
580         branch_label_ref_t *br;
581         s4                  mpc;
582         s4                  disp;
583         u1                 *mcodeptr;
584
585         /* get the label list */
586
587         list = cd->brancheslabel;
588
589         /* search if the label is already in the list */
590
591         for (br = list_first_unsynced(list); br != NULL;
592                  br = list_next_unsynced(list, br)) {
593                 /* is this entry the correct label? */
594
595                 if (br->label == label)
596                         break;
597         }
598
599         /* a branch reference was found */
600
601         if (br != NULL) {
602                 /* calculate the mpc of the branch instruction */
603
604                 mpc  = cd->mcodeptr - cd->mcodebase;
605                 disp = mpc - br->mpc;
606
607                 /* temporary set the mcodeptr */
608
609                 mcodeptr     = cd->mcodeptr;
610                 cd->mcodeptr = cd->mcodebase + br->mpc;
611
612 #if defined(ENABLE_STATISTICS)
613                 count_emit_branch++;
614                 if ((int8_t)disp == disp)  count_emit_branch_8bit++; 
615                 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
616                 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
617 # if SIZEOF_VOID_P == 8
618                 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
619 # endif
620 #endif
621
622                 emit_branch(cd, disp, br->condition, br->reg, br->options);
623
624                 /* restore mcodeptr */
625
626                 cd->mcodeptr = mcodeptr;
627
628                 /* now remove the branch reference */
629
630                 list_remove_unsynced(list, br);
631         }
632         else {
633                 /* add the label to the list (use invalid values for condition
634                    and register) */
635
636                 codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
637         }
638 }
639
640
641 /* emit_label_bcc **************************************************************
642
643    Emit conditional and unconditional label-branch instructions on
644    condition codes.
645
646 *******************************************************************************/
647
648 void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
649 {
650         emit_label_bccz(cd, label, condition, -1, options);
651 }
652
653
654 /* emit_label_br ***************************************************************
655
656    Wrapper for unconditional label-branches.
657
658 *******************************************************************************/
659
660 void emit_label_br(codegendata *cd, s4 label)
661 {
662         emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
663 }
664
665
666 /* emit_label_bxxz *************************************************************
667
668    Wrappers for label-branches on one integer register.
669
670 *******************************************************************************/
671
672 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
673
674 void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
675 {
676         emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
677 }
678
679 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
680
681
682 /* emit_label_bxx **************************************************************
683
684    Wrappers for label-branches on condition codes.
685
686 *******************************************************************************/
687
688 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
689
690 void emit_label_beq(codegendata *cd, s4 label)
691 {
692         emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
693 }
694
695 void emit_label_bne(codegendata *cd, s4 label)
696 {
697         emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
698 }
699
700 void emit_label_blt(codegendata *cd, s4 label)
701 {
702         emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
703 }
704
705 void emit_label_bge(codegendata *cd, s4 label)
706 {
707         emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
708 }
709
710 void emit_label_bgt(codegendata *cd, s4 label)
711 {
712         emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
713 }
714
715 void emit_label_ble(codegendata *cd, s4 label)
716 {
717         emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
718 }
719
720 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
721
722
723 /*
724  * These are local overrides for various environment variables in Emacs.
725  * Please do not remove this and leave it at the end of the file, where
726  * Emacs will automagically detect them.
727  * ---------------------------------------------------------------------
728  * Local variables:
729  * mode: c
730  * indent-tabs-mode: t
731  * c-basic-offset: 4
732  * tab-width: 4
733  * End:
734  * vim:noexpandtab:sw=4:ts=4:
735  */