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