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