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