* src/vm/jit/trace.c: Moved to .cpp.
[cacao.git] / src / vm / jit / arm / emit.c
1 /* src/vm/jit/arm/emit.c - Arm 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 #include <stdint.h>
30
31 #include "vm/types.h"
32
33 #include "md-abi.h"
34
35 #include "vm/jit/arm/codegen.h"
36
37 #include "mm/memory.h"
38
39 #include "threads/lock-common.h"
40
41 #include "vm/exceptions.h"
42 #include "vm/global.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/patcher-common.h"
49 #include "vm/jit/replace.h"
50 #include "vm/jit/trace.hpp"
51 #include "vm/jit/trap.h"
52
53 #include "toolbox/logging.h" /* XXX for debugging only */
54
55
56 /* emit_load *******************************************************************
57
58    Emits a possible load of an operand.
59
60 *******************************************************************************/
61
62 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
63 {
64         codegendata  *cd;
65         s4            disp;
66         s4            reg;
67
68         /* get required compiler data */
69
70         cd = jd->cd;
71
72         if (src->flags & INMEMORY) {
73                 COUNT_SPILLS;
74
75                 disp = src->vv.regoff;
76
77 #if defined(ENABLE_SOFTFLOAT)
78                 switch (src->type) {
79                 case TYPE_INT:
80                 case TYPE_FLT:
81                 case TYPE_ADR:
82                         M_ILD(tempreg, REG_SP, disp);
83                         break;
84                 case TYPE_LNG:
85                 case TYPE_DBL:
86                         M_LLD(tempreg, REG_SP, disp);
87                         break;
88                 default:
89                         vm_abort("emit_load: unknown type %d", src->type);
90                 }
91 #else
92                 switch (src->type) {
93                 case TYPE_INT:
94                 case TYPE_ADR:
95                         M_ILD(tempreg, REG_SP, disp);
96                         break;
97                 case TYPE_LNG:
98                         M_LLD(tempreg, REG_SP, disp);
99                         break;
100                 case TYPE_FLT:
101                         M_FLD(tempreg, REG_SP, disp);
102                         break;
103                 case TYPE_DBL:
104                         M_DLD(tempreg, REG_SP, disp);
105                         break;
106                 default:
107                         vm_abort("emit_load: unknown type %d", src->type);
108                 }
109 #endif
110
111                 reg = tempreg;
112         }
113         else
114                 reg = src->vv.regoff;
115
116         return reg;
117 }
118
119
120 /* emit_load_low ***************************************************************
121
122    Emits a possible load of the low 32-bits of a long source operand.
123
124 *******************************************************************************/
125
126 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
127 {
128         codegendata  *cd;
129         s4            disp;
130         s4            reg;
131
132         assert(src->type == TYPE_LNG);
133
134         /* get required compiler data */
135
136         cd = jd->cd;
137
138         if (src->flags & INMEMORY) {
139                 COUNT_SPILLS;
140
141                 disp = src->vv.regoff;
142
143 #if defined(__ARMEL__)
144                 M_ILD(tempreg, REG_SP, disp);
145 #else
146                 M_ILD(tempreg, REG_SP, disp + 4);
147 #endif
148
149                 reg = tempreg;
150         }
151         else
152                 reg = GET_LOW_REG(src->vv.regoff);
153
154         return reg;
155 }
156
157
158 /* emit_load_high **************************************************************
159
160    Emits a possible load of the high 32-bits of a long source operand.
161
162 *******************************************************************************/
163
164 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
165 {
166         codegendata  *cd;
167         s4            disp;
168         s4            reg;
169
170         assert(src->type == TYPE_LNG);
171
172         /* get required compiler data */
173
174         cd = jd->cd;
175
176         if (src->flags & INMEMORY) {
177                 COUNT_SPILLS;
178
179                 disp = src->vv.regoff;
180
181 #if defined(__ARMEL__)
182                 M_ILD(tempreg, REG_SP, disp + 4);
183 #else
184                 M_ILD(tempreg, REG_SP, disp);
185 #endif
186
187                 reg = tempreg;
188         }
189         else
190                 reg = GET_HIGH_REG(src->vv.regoff);
191
192         return reg;
193 }
194
195
196 /* emit_store ******************************************************************
197
198    Emits a possible store to a variable.
199
200 *******************************************************************************/
201
202 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
203 {
204         codegendata  *cd;
205         s4            disp;
206
207         /* get required compiler data */
208
209         cd = jd->cd;
210
211         if (dst->flags & INMEMORY) {
212                 COUNT_SPILLS;
213
214                 disp = dst->vv.regoff;
215
216 #if defined(ENABLE_SOFTFLOAT)
217                 switch (dst->type) {
218                 case TYPE_INT:
219                 case TYPE_FLT:
220                 case TYPE_ADR:
221                         M_IST(d, REG_SP, disp);
222                         break;
223                 case TYPE_LNG:
224                 case TYPE_DBL:
225                         M_LST(d, REG_SP, disp);
226                         break;
227                 default:
228                         vm_abort("emit_store: unknown type %d", dst->type);
229                 }
230 #else
231                 switch (dst->type) {
232                 case TYPE_INT:
233                 case TYPE_ADR:
234                         M_IST(d, REG_SP, disp);
235                         break;
236                 case TYPE_LNG:
237                         M_LST(d, REG_SP, disp);
238                         break;
239                 case TYPE_FLT:
240                         M_FST(d, REG_SP, disp);
241                         break;
242                 case TYPE_DBL:
243                         M_DST(d, REG_SP, disp);
244                         break;
245                 default:
246                         vm_abort("emit_store: unknown type %d", dst->type);
247                 }
248 #endif
249         }
250 }
251
252
253 /* emit_copy *******************************************************************
254
255    Generates a register/memory to register/memory copy.
256
257 *******************************************************************************/
258
259 void emit_copy(jitdata *jd, instruction *iptr)
260 {
261         codegendata *cd;
262         varinfo     *src;
263         varinfo     *dst;
264         s4           s1, d;
265
266         /* get required compiler data */
267
268         cd = jd->cd;
269
270         /* get source and destination variables */
271
272         src = VAROP(iptr->s1);
273         dst = VAROP(iptr->dst);
274
275         /* XXX dummy call, removed me!!! */
276         d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
277
278         if ((src->vv.regoff != dst->vv.regoff) ||
279                 ((src->flags ^ dst->flags) & INMEMORY)) {
280
281                 if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
282                         /* emit nothing, as the value won't be used anyway */
283                         return;
284                 }
285
286                 /* If one of the variables resides in memory, we can eliminate
287                    the register move from/to the temporary register with the
288                    order of getting the destination register and the load. */
289
290                 if (IS_INMEMORY(src->flags)) {
291 #if !defined(ENABLE_SOFTFLOAT)
292                         if (IS_FLT_DBL_TYPE(src->type))
293                                 d = codegen_reg_of_var(iptr->opc, dst, REG_FTMP1);
294                         else
295 #endif
296                         {
297                                 if (IS_2_WORD_TYPE(src->type))
298                                         d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
299                                 else
300                                         d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
301                         }
302
303                         s1 = emit_load(jd, iptr, src, d);
304                 }
305                 else {
306 #if !defined(ENABLE_SOFTFLOAT)
307                         if (IS_FLT_DBL_TYPE(src->type))
308                                 s1 = emit_load(jd, iptr, src, REG_FTMP1);
309                         else
310 #endif
311                         {
312                                 if (IS_2_WORD_TYPE(src->type))
313                                         s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
314                                 else
315                                         s1 = emit_load(jd, iptr, src, REG_ITMP1);
316                         }
317
318                         d = codegen_reg_of_var(iptr->opc, dst, s1);
319                 }
320
321                 if (s1 != d) {
322 #if defined(ENABLE_SOFTFLOAT)
323                         switch (src->type) {
324                         case TYPE_INT:
325                         case TYPE_FLT:
326                         case TYPE_ADR:
327                                 /* XXX grrrr, wrong direction! */
328                                 M_MOV(d, s1);
329                                 break;
330                         case TYPE_LNG:
331                         case TYPE_DBL:
332                                 /* XXX grrrr, wrong direction! */
333                                 M_MOV(GET_LOW_REG(d), GET_LOW_REG(s1));
334                                 M_MOV(GET_HIGH_REG(d), GET_HIGH_REG(s1));
335                                 break;
336                         default:
337                                 vm_abort("emit_copy: unknown type %d", src->type);
338                         }
339 #else
340                         switch (src->type) {
341                         case TYPE_INT:
342                         case TYPE_ADR:
343                                 /* XXX grrrr, wrong direction! */
344                                 M_MOV(d, s1);
345                                 break;
346                         case TYPE_LNG:
347                                 /* XXX grrrr, wrong direction! */
348                                 M_MOV(GET_LOW_REG(d), GET_LOW_REG(s1));
349                                 M_MOV(GET_HIGH_REG(d), GET_HIGH_REG(s1));
350                                 break;
351                         case TYPE_FLT:
352                                 M_FMOV(s1, d);
353                                 break;
354                         case TYPE_DBL:
355                                 M_DMOV(s1, d);
356                                 break;
357                         default:
358                                 vm_abort("emit_copy: unknown type %d", src->type);
359                         }
360 #endif
361                 }
362
363                 emit_store(jd, iptr, dst, d);
364         }
365 }
366
367
368 /* emit_iconst *****************************************************************
369
370    XXX
371
372 *******************************************************************************/
373
374 void emit_iconst(codegendata *cd, s4 d, s4 value)
375 {
376         s4 disp;
377
378         if (IS_IMM(value))
379                 M_MOV_IMM(d, value);
380         else {
381                 disp = dseg_add_s4(cd, value);
382                 M_DSEG_LOAD(d, disp);
383         }
384 }
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 - 8);
401         branchdisp = (disp - 8) >> 2;
402
403         /* check which branch to generate */
404
405         if (condition == BRANCH_UNCONDITIONAL) {
406                 /* check displacement for overflow */
407
408                 if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
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_B(branchdisp);
420                 }
421         }
422         else {
423                 /* and displacement for overflow */
424
425                 if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
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                         vm_abort("emit_branch: emit conditional long-branch code");
434                 }
435                 else {
436                         switch (condition) {
437                         case BRANCH_EQ:
438                                 M_BEQ(branchdisp);
439                                 break;
440                         case BRANCH_NE:
441                                 M_BNE(branchdisp);
442                                 break;
443                         case BRANCH_LT:
444                                 M_BLT(branchdisp);
445                                 break;
446                         case BRANCH_GE:
447                                 M_BGE(branchdisp);
448                                 break;
449                         case BRANCH_GT:
450                                 M_BGT(branchdisp);
451                                 break;
452                         case BRANCH_LE:
453                                 M_BLE(branchdisp);
454                                 break;
455                         case BRANCH_UGT:
456                                 M_BHI(branchdisp);
457                                 break;
458                         default:
459                                 vm_abort("emit_branch: unknown condition %d", condition);
460                         }
461                 }
462         }
463 }
464
465
466 /* emit_arithmetic_check *******************************************************
467
468    Emit an ArithmeticException check.
469
470 *******************************************************************************/
471
472 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
473 {
474         if (INSTRUCTION_MUST_CHECK(iptr)) {
475                 CHECK_INT_REG(reg);
476                 M_TEQ_IMM(reg, 0);
477                 M_TRAPEQ(0, TRAP_ArithmeticException);
478         }
479 }
480
481
482 /* emit_nullpointer_check ******************************************************
483
484    Emit a NullPointerException check.
485
486 *******************************************************************************/
487
488 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
489 {
490         if (INSTRUCTION_MUST_CHECK(iptr)) {
491                 M_TST(reg, reg);
492                 M_TRAPEQ(0, TRAP_NullPointerException);
493         }
494 }
495
496 void emit_nullpointer_check_force(codegendata *cd, instruction *iptr, s4 reg)
497 {
498         M_TST(reg, reg);
499         M_TRAPEQ(0, TRAP_NullPointerException);
500 }
501
502
503 /* emit_arrayindexoutofbounds_check ********************************************
504
505    Emit a ArrayIndexOutOfBoundsException check.
506
507 *******************************************************************************/
508
509 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
510 {
511         if (INSTRUCTION_MUST_CHECK(iptr)) {
512                 M_ILD_INTERN(REG_ITMP3, s1, OFFSET(java_array_t, size));
513                 M_CMP(s2, REG_ITMP3);
514                 M_TRAPHS(s2, TRAP_ArrayIndexOutOfBoundsException);
515         }
516 }
517
518
519 /* emit_arraystore_check *******************************************************
520
521    Emit an ArrayStoreException check.
522
523 *******************************************************************************/
524
525 void emit_arraystore_check(codegendata *cd, instruction *iptr)
526 {
527         if (INSTRUCTION_MUST_CHECK(iptr)) {
528                 M_TST(REG_RESULT, REG_RESULT);
529                 M_TRAPEQ(0, TRAP_ArrayStoreException);
530         }
531 }
532
533
534 /* emit_classcast_check ********************************************************
535
536    Emit a ClassCastException check.
537
538 *******************************************************************************/
539
540 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
541 {
542         if (INSTRUCTION_MUST_CHECK(iptr)) {
543                 switch (condition) {
544                 case BRANCH_EQ:
545                         M_TRAPEQ(s1, TRAP_ClassCastException);
546                         break;
547
548                 case BRANCH_LE:
549                         M_TRAPLE(s1, TRAP_ClassCastException);
550                         break;
551
552                 case BRANCH_UGT:
553                         M_TRAPHI(s1, TRAP_ClassCastException);
554                         break;
555
556                 default:
557                         vm_abort("emit_classcast_check: unknown condition %d", condition);
558                 }
559         }
560 }
561
562 /* emit_exception_check ********************************************************
563
564    Emit an Exception check.
565
566 *******************************************************************************/
567
568 void emit_exception_check(codegendata *cd, instruction *iptr)
569 {
570         if (INSTRUCTION_MUST_CHECK(iptr)) {
571                 M_TST(REG_RESULT, REG_RESULT);
572                 M_TRAPEQ(0, TRAP_CHECK_EXCEPTION);
573         }
574 }
575
576
577 /* emit_trap *******************************************************************
578
579    Emit a trap instruction and return the original machine code.
580
581 *******************************************************************************/
582
583 uint32_t emit_trap(codegendata *cd)
584 {
585         uint32_t mcode;
586
587         /* Get machine code which is patched back in later. The
588            trap is 1 instruction word long. */
589
590         mcode = *((uint32_t *) cd->mcodeptr);
591
592         M_TRAP(0, TRAP_PATCHER);
593
594         return mcode;
595 }
596
597
598 /* emit_verbosecall_enter ******************************************************
599
600    Generates the code for the call trace.
601
602 *******************************************************************************/
603
604 #if !defined(NDEBUG)
605 void emit_verbosecall_enter(jitdata *jd)
606 {
607         methodinfo   *m;
608         codegendata  *cd;
609         registerdata *rd;
610         methoddesc   *md;
611         s4            disp;
612         s4            i, s;
613
614         /* get required compiler data */
615
616         m  = jd->m;
617         cd = jd->cd;
618         rd = jd->rd;
619
620         md = m->parseddesc;
621
622         /* mark trace code */
623
624         M_NOP;
625
626         /* Keep stack 8-byte aligned. */
627
628         M_STMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
629         M_SUB_IMM(REG_SP, REG_SP, md->paramcount * 8);
630
631         /* save argument registers */
632
633         for (i = 0; i < md->paramcount; i++) {
634                 if (!md->params[i].inmemory) {
635                         s = md->params[i].regoff;
636
637 #if defined(ENABLE_SOFTFLOAT)
638                         switch (md->paramtypes[i].type) {
639                         case TYPE_INT:
640                         case TYPE_FLT:
641                         case TYPE_ADR:
642                                 M_IST(s, REG_SP, i * 8);
643                                 break;
644                         case TYPE_LNG:
645                         case TYPE_DBL:
646                                 M_LST(s, REG_SP, i * 8);
647                                 break;
648                         }
649 #else
650                         switch (md->paramtypes[i].type) {
651                         case TYPE_ADR:
652                         case TYPE_INT:
653                                 M_IST(s, REG_SP, i * 8);
654                                 break;
655                         case TYPE_LNG:
656                                 M_LST(s, REG_SP, i * 8);
657                                 break;
658                         case TYPE_FLT:
659                                 M_FST(s, REG_SP, i * 8);
660                                 break;
661                         case TYPE_DBL:
662                                 M_DST(s, REG_SP, i * 8);
663                                 break;
664                         }
665 #endif
666                 }
667         }
668
669         disp = dseg_add_address(cd, m);
670         M_DSEG_LOAD(REG_A0, disp);
671         M_MOV(REG_A1, REG_SP);
672         M_ADD_IMM(REG_A2, REG_SP, md->paramcount * 8 + 2 * 4 + cd->stackframesize);
673         M_LONGBRANCH(trace_java_call_enter);
674
675         /* restore argument registers */
676
677         for (i = 0; i < md->paramcount; i++) {
678                 if (!md->params[i].inmemory) {
679                         s = md->params[i].regoff;
680
681 #if defined(ENABLE_SOFTFLOAT)
682                         switch (md->paramtypes[i].type) {
683                         case TYPE_INT:
684                         case TYPE_FLT:
685                         case TYPE_ADR:
686                                 M_ILD(s, REG_SP, i * 8);
687                                 break;
688                         case TYPE_LNG:
689                         case TYPE_DBL:
690                                 M_LLD(s, REG_SP, i * 8);
691                                 break;
692                         }
693 #else
694                         switch (md->paramtypes[i].type) {
695                         case TYPE_ADR:
696                         case TYPE_INT:
697                                 M_ILD(s, REG_SP, i * 8);
698                                 break;
699                         case TYPE_LNG:
700                                 M_LLD(s, REG_SP, i * 8);
701                                 break;
702                         case TYPE_FLT:
703                                 M_FLD(s, REG_SP, i * 8);
704                                 break;
705                         case TYPE_DBL:
706                                 M_DLD(s, REG_SP, i * 8);
707                                 break;
708                         }
709 #endif
710                 }
711         }
712
713         /* Keep stack 8-byte aligned. */
714
715         M_ADD_IMM(REG_SP, REG_SP, md->paramcount * 8);
716         M_LDMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
717
718         /* mark trace code */
719
720         M_NOP;
721 }
722 #endif /* !defined(NDEBUG) */
723
724
725 /* emit_verbosecall_exit *******************************************************
726
727    Generates the code for the call trace.
728
729 *******************************************************************************/
730
731 #if !defined(NDEBUG)
732 void emit_verbosecall_exit(jitdata *jd)
733 {
734         methodinfo   *m;
735         codegendata  *cd;
736         registerdata *rd;
737         methoddesc   *md;
738         s4            disp;
739
740         /* get required compiler data */
741
742         m  = jd->m;
743         cd = jd->cd;
744         rd = jd->rd;
745
746         md = m->parseddesc;
747
748         /* mark trace code */
749
750         M_NOP;
751
752         /* Keep stack 8-byte aligned. */
753
754         M_STMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
755         M_SUB_IMM(REG_SP, REG_SP, 1 * 8);
756
757         /* save return value */
758
759         switch (md->returntype.type) {
760         case TYPE_ADR:
761         case TYPE_INT:
762         case TYPE_FLT:
763                 M_IST(REG_RESULT, REG_SP, 0 * 8);
764                 break;
765         case TYPE_LNG:
766         case TYPE_DBL:
767                 M_LST(REG_RESULT_PACKED, REG_SP, 0 * 8);
768                 break;
769         }
770
771         disp = dseg_add_address(cd, m);
772         M_DSEG_LOAD(REG_A0, disp);
773         M_MOV(REG_A1, REG_SP);
774         M_LONGBRANCH(trace_java_call_exit);
775
776         /* restore return value */
777
778         switch (md->returntype.type) {
779         case TYPE_ADR:
780         case TYPE_INT:
781         case TYPE_FLT:
782                 M_ILD(REG_RESULT, REG_SP, 0 * 8);
783                 break;
784         case TYPE_LNG:
785         case TYPE_DBL:
786                 M_LLD(REG_RESULT_PACKED, REG_SP, 0 * 8);
787                 break;
788         }
789
790         /* Keep stack 8-byte aligned. */
791
792         M_ADD_IMM(REG_SP, REG_SP, 1 * 8);
793         M_LDMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
794
795         /* mark trace code */
796
797         M_NOP;
798 }
799 #endif /* !defined(NDEBUG) */
800
801
802 /*
803  * These are local overrides for various environment variables in Emacs.
804  * Please do not remove this and leave it at the end of the file, where
805  * Emacs will automagically detect them.
806  * ---------------------------------------------------------------------
807  * Local variables:
808  * mode: c
809  * indent-tabs-mode: t
810  * c-basic-offset: 4
811  * tab-width: 4
812  * End:
813  * vim:noexpandtab:sw=4:ts=4:
814  */