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