* src/vm/jit/emit-common.c: Moved to .cpp.
[cacao.git] / src / vm / jit / powerpc / emit.c
1 /* src/vm/jit/powerpc/emit.c - PowerPC code emitter functions
2
3    Copyright (C) 1996-2005, 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 "md-abi.h"
34
35 #include "vm/jit/powerpc/codegen.h"
36
37 #include "mm/memory.h"
38
39 #include "threads/lock-common.h"
40
41 #include "vm/options.h"
42
43 #include "vm/jit/abi.h"
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/codegen-common.h"
46 #include "vm/jit/dseg.h"
47 #include "vm/jit/emit-common.hpp"
48 #include "vm/jit/jit.hpp"
49 #include "vm/jit/replace.hpp"
50 #include "vm/jit/trace.hpp"
51 #include "vm/jit/trap.h"
52
53
54 /* emit_load *******************************************************************
55
56    Emits a possible load of an operand.
57
58 *******************************************************************************/
59
60 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
61 {
62         codegendata *cd;
63         s4           disp;
64         s4           reg;
65
66         /* get required compiler data */
67
68         cd = jd->cd;
69
70         if (IS_INMEMORY(src->flags)) {
71                 COUNT_SPILLS;
72
73                 disp = src->vv.regoff;
74
75                 switch (src->type) {
76                 case TYPE_INT:
77                 case TYPE_ADR:
78                         M_ILD(tempreg, REG_SP, disp);
79                         break;
80                 case TYPE_LNG:
81                         M_LLD(tempreg, REG_SP, disp);
82                         break;
83                 case TYPE_FLT:
84                 case TYPE_DBL:
85                         M_DLD(tempreg, REG_SP, disp);
86                         break;
87                 default:
88                         vm_abort("emit_load: unknown type %d", src->type);
89                 }
90
91                 reg = tempreg;
92         }
93         else
94                 reg = src->vv.regoff;
95
96         return reg;
97 }
98
99
100 /* emit_load_low ***************************************************************
101
102    Emits a possible load of the low 32-bits of an operand.
103
104 *******************************************************************************/
105
106 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
107 {
108         codegendata  *cd;
109         s4            disp;
110         s4            reg;
111
112         assert(src->type == TYPE_LNG);
113
114         /* get required compiler data */
115
116         cd = jd->cd;
117
118         if (IS_INMEMORY(src->flags)) {
119                 COUNT_SPILLS;
120
121                 disp = src->vv.regoff;
122
123                 M_ILD(tempreg, REG_SP, disp + 4);
124
125                 reg = tempreg;
126         }
127         else
128                 reg = GET_LOW_REG(src->vv.regoff);
129
130         return reg;
131 }
132
133
134 /* emit_load_high **************************************************************
135
136    Emits a possible load of the high 32-bits of an operand.
137
138 *******************************************************************************/
139
140 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
141 {
142         codegendata  *cd;
143         s4            disp;
144         s4            reg;
145
146         assert(src->type == TYPE_LNG);
147
148         /* get required compiler data */
149
150         cd = jd->cd;
151
152         if (IS_INMEMORY(src->flags)) {
153                 COUNT_SPILLS;
154
155                 disp = src->vv.regoff;
156
157                 M_ILD(tempreg, REG_SP, disp);
158
159                 reg = tempreg;
160         }
161         else
162                 reg = GET_HIGH_REG(src->vv.regoff);
163
164         return reg;
165 }
166
167
168 /* emit_store ******************************************************************
169
170    Emit a possible store for the given variable.
171
172 *******************************************************************************/
173
174 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
175 {
176         codegendata *cd;
177         s4           disp;
178
179         /* get required compiler data */
180
181         cd = jd->cd;
182
183         if (IS_INMEMORY(dst->flags)) {
184                 COUNT_SPILLS;
185
186                 disp = dst->vv.regoff;
187
188                 switch (dst->type) {
189                 case TYPE_INT:
190                 case TYPE_ADR:
191                         M_IST(d, REG_SP, disp);
192                         break;
193                 case TYPE_LNG:
194                         M_LST(d, REG_SP, disp);
195                         break;
196                 case TYPE_FLT:
197                 case TYPE_DBL:
198                         M_DST(d, REG_SP, disp);
199                         break;
200                 default:
201                         vm_abort("emit_store: unknown type %d", dst->type);
202                 }
203         }
204 }
205
206
207 /* emit_copy *******************************************************************
208
209    Generates a register/memory to register/memory copy.
210
211 *******************************************************************************/
212
213 void emit_copy(jitdata *jd, instruction *iptr)
214 {
215         codegendata *cd;
216         varinfo     *src;
217         varinfo     *dst;
218         s4           s1, d;
219
220         /* get required compiler data */
221
222         cd = jd->cd;
223
224         /* get source and destination variables */
225
226         src = VAROP(iptr->s1);
227         dst = VAROP(iptr->dst);
228
229         if ((src->vv.regoff != dst->vv.regoff) ||
230                 (IS_INMEMORY(src->flags ^ dst->flags))) {
231
232                 if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
233                         /* emit nothing, as the value won't be used anyway */
234                         return;
235                 }
236
237                 /* If one of the variables resides in memory, we can eliminate
238                    the register move from/to the temporary register with the
239                    order of getting the destination register and the load. */
240
241                 if (IS_INMEMORY(src->flags)) {
242                         if (IS_LNG_TYPE(src->type))
243                                 d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
244                         else
245                                 d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
246
247                         s1 = emit_load(jd, iptr, src, d);
248                 }
249                 else {
250                         if (IS_LNG_TYPE(src->type))
251                                 s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
252                         else
253                                 s1 = emit_load(jd, iptr, src, REG_IFTMP);
254
255                         d = codegen_reg_of_var(iptr->opc, dst, s1);
256                 }
257
258                 if (s1 != d) {
259                         switch (src->type) {
260                         case TYPE_INT:
261                         case TYPE_ADR:
262                                 M_MOV(s1, d);
263                                 break;
264                         case TYPE_LNG:
265                                 M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
266                                 M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d));
267                                 break;
268                         case TYPE_FLT:
269                         case TYPE_DBL:
270                                 M_FMOV(s1, d);
271                                 break;
272                         default:
273                                 vm_abort("emit_copy: unknown type %d", src->type);
274                         }
275                 }
276
277                 emit_store(jd, iptr, dst, d);
278         }
279 }
280
281
282 /* emit_iconst *****************************************************************
283
284    XXX
285
286 *******************************************************************************/
287
288 void emit_iconst(codegendata *cd, s4 d, s4 value)
289 {
290         s4 disp;
291
292         if ((value >= -32768) && (value <= 32767))
293                 M_LDA_INTERN(d, REG_ZERO, value);
294         else {
295                 disp = dseg_add_s4(cd, value);
296                 M_ILD(d, REG_PV, disp);
297         }
298 }
299
300
301 /* emit_branch *****************************************************************
302
303    Emits the code for conditional and unconditional branchs.
304
305 *******************************************************************************/
306
307 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
308 {
309         s4 checkdisp;
310         s4 branchdisp;
311
312         /* calculate the different displacements */
313
314         checkdisp  =  disp + 4;
315         branchdisp = (disp - 4) >> 2;
316
317         /* check which branch to generate */
318
319         if (condition == BRANCH_UNCONDITIONAL) {
320                 /* check displacement for overflow */
321
322                 if ((checkdisp < (s4) 0xfe000000) || (checkdisp > (s4) 0x01fffffc)) {
323                         /* if the long-branches flag isn't set yet, do it */
324
325                         if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
326                                 cd->flags |= (CODEGENDATA_FLAG_ERROR |
327                                                           CODEGENDATA_FLAG_LONGBRANCHES);
328                         }
329
330                         vm_abort("emit_branch: emit unconditional long-branch code");
331                 }
332                 else {
333                         M_BR(branchdisp);
334                 }
335         }
336         else {
337                 /* and displacement for overflow */
338
339                 if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
340                         /* if the long-branches flag isn't set yet, do it */
341
342                         if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
343                                 cd->flags |= (CODEGENDATA_FLAG_ERROR |
344                                                           CODEGENDATA_FLAG_LONGBRANCHES);
345                         }
346
347                         switch (condition) {
348                         case BRANCH_EQ:
349                                 M_BNE(1);
350                                 M_BR(branchdisp);
351                                 break;
352                         case BRANCH_NE:
353                                 M_BEQ(1);
354                                 M_BR(branchdisp);
355                                 break;
356                         case BRANCH_LT:
357                                 M_BGE(1);
358                                 M_BR(branchdisp);
359                                 break;
360                         case BRANCH_GE:
361                                 M_BLT(1);
362                                 M_BR(branchdisp);
363                                 break;
364                         case BRANCH_GT:
365                                 M_BLE(1);
366                                 M_BR(branchdisp);
367                                 break;
368                         case BRANCH_LE:
369                                 M_BGT(1);
370                                 M_BR(branchdisp);
371                                 break;
372                         case BRANCH_NAN:
373                                 vm_abort("emit_branch: long BRANCH_NAN");
374                                 break;
375                         default:
376                                 vm_abort("emit_branch: unknown condition %d", condition);
377                         }
378                 }
379                 else {
380                         switch (condition) {
381                         case BRANCH_EQ:
382                                 M_BEQ(branchdisp);
383                                 break;
384                         case BRANCH_NE:
385                                 M_BNE(branchdisp);
386                                 break;
387                         case BRANCH_LT:
388                                 M_BLT(branchdisp);
389                                 break;
390                         case BRANCH_GE:
391                                 M_BGE(branchdisp);
392                                 break;
393                         case BRANCH_GT:
394                                 M_BGT(branchdisp);
395                                 break;
396                         case BRANCH_LE:
397                                 M_BLE(branchdisp);
398                                 break;
399                         case BRANCH_NAN:
400                                 M_BNAN(branchdisp);
401                                 break;
402                         default:
403                                 vm_abort("emit_branch: unknown condition %d", condition);
404                         }
405                 }
406         }
407 }
408
409
410 /* emit_arithmetic_check *******************************************************
411
412    Emit an ArithmeticException check.
413
414 *******************************************************************************/
415
416 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
417 {
418         if (INSTRUCTION_MUST_CHECK(iptr)) {
419                 M_TST(reg);
420                 M_BNE(1);
421                 M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_ArithmeticException);
422         }
423 }
424
425
426 /* emit_arrayindexoutofbounds_check ********************************************
427
428    Emit a ArrayIndexOutOfBoundsException check.
429
430 *******************************************************************************/
431
432 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
433 {
434         if (INSTRUCTION_MUST_CHECK(iptr)) {
435                 M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
436                 M_TRAPGEU(s2, REG_ITMP3);
437         }
438 }
439
440
441 /* emit_arraystore_check *******************************************************
442
443    Emit an ArrayStoreException check.
444
445 *******************************************************************************/
446
447 void emit_arraystore_check(codegendata *cd, instruction *iptr)
448 {
449         if (INSTRUCTION_MUST_CHECK(iptr)) {
450                 M_TST(REG_RESULT);
451                 M_BNE(1);
452                 M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_ArrayStoreException);
453         }
454 }
455
456
457 /* emit_classcast_check ********************************************************
458
459    Emit a ClassCastException check.
460
461 *******************************************************************************/
462
463 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
464 {
465         if (INSTRUCTION_MUST_CHECK(iptr)) {
466                 switch (condition) {
467                 case BRANCH_LE:
468                         M_BGT(1);
469                         break;
470                 case BRANCH_EQ:
471                         M_BNE(1);
472                         break;
473                 case BRANCH_GT:
474                         M_BLE(1);
475                         break;
476                 default:
477                         vm_abort("emit_classcast_check: unknown condition %d", condition);
478                 }
479                 M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
480         }
481 }
482
483
484 /* emit_nullpointer_check ******************************************************
485
486    Emit a NullPointerException check.
487
488 *******************************************************************************/
489
490 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
491 {
492         if (INSTRUCTION_MUST_CHECK(iptr)) {
493                 M_TST(reg);
494                 M_BNE(1);
495                 M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
496         }
497 }
498
499
500 /* emit_exception_check ********************************************************
501
502    Emit an Exception check.
503
504 *******************************************************************************/
505
506 void emit_exception_check(codegendata *cd, instruction *iptr)
507 {
508         if (INSTRUCTION_MUST_CHECK(iptr)) {
509                 M_TST(REG_RESULT);
510                 M_BNE(1);
511                 M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_CHECK_EXCEPTION);
512         }
513 }
514
515
516 /* emit_trap_compiler **********************************************************
517
518    Emit a trap instruction which calls the JIT compiler.
519
520 *******************************************************************************/
521
522 void emit_trap_compiler(codegendata *cd)
523 {
524         M_ALD_INTERN(REG_METHODPTR, REG_ZERO, TRAP_COMPILER);
525 }
526
527
528 /* emit_trap *******************************************************************
529
530    Emit a trap instruction and return the original machine code.
531
532 *******************************************************************************/
533
534 uint32_t emit_trap(codegendata *cd)
535 {
536         uint32_t mcode;
537
538         /* Get machine code which is patched back in later. The
539            trap is 1 instruction word long. */
540
541         mcode = *((uint32_t *) cd->mcodeptr);
542
543         M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
544
545         return mcode;
546 }
547
548
549 /* emit_verbosecall_enter ******************************************************
550
551    Generates the code for the call trace.
552
553 *******************************************************************************/
554
555 void emit_verbosecall_enter(jitdata *jd)
556 {
557 #if !defined(NDEBUG)
558         methodinfo   *m;
559         codegendata  *cd;
560         registerdata *rd;
561         methoddesc   *md;
562         int32_t       disp;
563         int32_t       i;
564         int32_t       s, d;
565
566         if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
567                 return;
568
569         /* get required compiler data */
570
571         m  = jd->m;
572         cd = jd->cd;
573         rd = jd->rd;
574
575         md = m->parseddesc;
576
577         /* mark trace code */
578
579         M_NOP;
580
581         /* On Darwin we need to allocate an additional 3*4 bytes of stack
582            for the arguments to trace_java_call_enter, we make it 2*8. */
583
584         M_MFLR(REG_ZERO);
585         M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
586         M_STWU(REG_SP, REG_SP, -(LA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8));
587
588         /* save argument registers */
589
590         for (i = 0; i < md->paramcount; i++) {
591                 if (!md->params[i].inmemory) {
592                         s = md->params[i].regoff;
593                         d = LA_SIZE + (i + 2) * 8;
594
595                         switch (md->paramtypes[i].type) {
596                         case TYPE_INT:
597                         case TYPE_ADR:
598                                 M_IST(s, REG_SP, d);
599                                 break;
600                         case TYPE_LNG:
601                                 M_LST(s, REG_SP, d);
602                                 break;
603                         case TYPE_FLT:
604                                 M_FST(s, REG_SP, d);
605                                 break;
606                         case TYPE_DBL:
607                                 M_DST(s, REG_SP, d);
608                                 break;
609                         }
610                 }
611         }
612
613         /* pass methodinfo and pointers to the tracer function */
614
615         disp = dseg_add_address(cd, m);
616         M_ALD(REG_A0, REG_PV, disp);
617         M_AADD_IMM(REG_SP, LA_SIZE + 2 * 8, REG_A1);
618         M_AADD_IMM(REG_SP, LA_SIZE + (2 + ARG_CNT + TMP_CNT + cd->stackframesize) * 8, REG_A2);
619         
620         disp = dseg_add_functionptr(cd, trace_java_call_enter);
621         M_ALD(REG_ITMP2, REG_PV, disp);
622         M_MTCTR(REG_ITMP2);
623         M_JSR;
624
625         /* restore argument registers */
626
627         for (i = 0; i < md->paramcount; i++) {
628                 if (!md->params[i].inmemory) {
629                         s = LA_SIZE + (i + 2) * 8;
630                         d = md->params[i].regoff;
631
632                         switch (md->paramtypes[i].type) {
633                         case TYPE_INT:
634                         case TYPE_ADR:
635                                 M_ILD(d, REG_SP, s);
636                                 break;
637                         case TYPE_LNG:
638                                 M_LLD(d, REG_SP, s);
639                                 break;
640                         case TYPE_FLT:
641                                 M_FLD(d, REG_SP, s);
642                                 break;
643                         case TYPE_DBL:
644                                 M_DLD(d, REG_SP, s);
645                                 break;
646                         }
647                 }
648         }
649
650         M_ALD(REG_ZERO, REG_SP, LA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8 + LA_LR_OFFSET);
651         M_MTLR(REG_ZERO);
652         M_LDA(REG_SP, REG_SP, LA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8);
653
654         /* mark trace code */
655
656         M_NOP;
657 #endif /* !defined(NDEBUG) */
658 }
659
660
661 /* emit_verbosecall_exit *******************************************************
662
663    Generates the code for the call trace.
664
665 *******************************************************************************/
666
667 void emit_verbosecall_exit(jitdata *jd)
668 {
669 #if !defined(NDEBUG)
670         methodinfo   *m;
671         codegendata  *cd;
672         registerdata *rd;
673         methoddesc   *md;
674         s4            disp;
675
676         if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
677                 return;
678
679         /* get required compiler data */
680
681         m  = jd->m;
682         cd = jd->cd;
683         rd = jd->rd;
684
685         md = m->parseddesc;
686         
687         /* mark trace code */
688
689         M_NOP;
690
691         /* On Darwin we need to allocate an additional 2*4 bytes of stack
692            for the arguments to trace_java_call_exit, we make it 1*8. */
693
694         M_MFLR(REG_ZERO);
695         M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
696         M_STWU(REG_SP, REG_SP, -(LA_SIZE + (1 + 1) * 8));
697
698         /* save return value */
699
700         switch (md->returntype.type) {
701         case TYPE_INT:
702         case TYPE_ADR:
703                 M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
704                 break;
705         case TYPE_LNG:
706                 M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
707                 break;
708         case TYPE_FLT:
709                 M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
710                 break;
711         case TYPE_DBL:
712                 M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
713                 break;
714         case TYPE_VOID:
715                 break;
716         }
717
718         disp = dseg_add_address(cd, m);
719         M_ALD(REG_A0, REG_PV, disp);
720         M_AADD_IMM(REG_SP, LA_SIZE + 1 * 8, REG_A1);
721
722         disp = dseg_add_functionptr(cd, trace_java_call_exit);
723         M_ALD(REG_ITMP2, REG_PV, disp);
724         M_MTCTR(REG_ITMP2);
725         M_JSR;
726
727         /* restore return value */
728
729         switch (md->returntype.type) {
730         case TYPE_INT:
731         case TYPE_ADR:
732                 M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
733                 break;
734         case TYPE_LNG:
735                 M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
736                 break;
737         case TYPE_FLT:
738                 M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
739                 break;
740         case TYPE_DBL:
741                 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
742                 break;
743         case TYPE_VOID:
744                 break;
745         }
746
747         M_ALD(REG_ZERO, REG_SP, LA_SIZE + (1 + 1) * 8 + LA_LR_OFFSET);
748         M_MTLR(REG_ZERO);
749         M_LDA(REG_SP, REG_SP, LA_SIZE + (1 + 1) * 8);
750
751         /* mark trace code */
752
753         M_NOP;
754 #endif /* !defined(NDEBUG) */
755 }
756
757
758 /*
759  * These are local overrides for various environment variables in Emacs.
760  * Please do not remove this and leave it at the end of the file, where
761  * Emacs will automagically detect them.
762  * ---------------------------------------------------------------------
763  * Local variables:
764  * mode: c
765  * indent-tabs-mode: t
766  * c-basic-offset: 4
767  * tab-width: 4
768  * End:
769  * vim:noexpandtab:sw=4:ts=4:
770  */