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