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