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