* src/vm/jit/trace.c: Moved to .cpp.
[cacao.git] / src / vm / jit / m68k / emit.c
1 /* src/vm/jit/m68k/emit.c
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29
30 #include "vm/jit/m68k/codegen.h"
31 #include "vm/jit/m68k/emit.h"
32
33 #include "mm/memory.h"
34
35 #include "vm/builtin.h"
36 #include "vm/exceptions.h"
37
38 #include "vm/jit/asmpart.h"
39 #include "vm/jit/emit-common.h"
40 #include "vm/jit/trace.hpp"
41 #include "vm/jit/trap.h"
42
43
44 /* emit_mov_imm_reg **************************************************************************
45  *
46  *      Loads an immededat operand into an integer data register
47  *
48  ********************************************************************************************/
49 void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg)
50 {
51         /* FIXME: -1 can be used as byte form 0xff, but this ifs cascade is plain wrong it seems */
52
53         if ( (imm & 0x0000007F) == imm) {
54                 /* use byte form */
55                 *((s2*)cd->mcodeptr) = 0x7000 | (dreg << 9) | imm;      /* MOVEQ.L */
56                 cd->mcodeptr += 2;
57         } else if ((imm  & 0x00007FFF) == imm)  {
58                 /* use word form */
59                 OPWORD( ((7<<6) | (dreg << 3) | 5), 7, 4);                      /* MVS.W */
60                 *((s2*)cd->mcodeptr) = (s2)imm;
61                 cd->mcodeptr += 2;
62         } else {
63                 /* use long form */
64                 OPWORD( ((2<<6) | (dreg << 3) | 0), 7, 4);
65                 *((s4*)cd->mcodeptr) = (s4)imm;
66                 cd->mcodeptr += 4;
67
68         }
69 }
70
71 /* emit_copy *******************************************************************
72
73    Generates a register/memory to register/memory copy.
74
75 *******************************************************************************/
76
77 void emit_copy(jitdata *jd, instruction *iptr)
78 {
79         codegendata *cd;
80         varinfo     *src;
81         varinfo     *dst;
82         s4           s1, d;
83
84         /* get required compiler data */
85
86         cd = jd->cd;
87
88         /* get source and destination variables */
89
90         src = VAROP(iptr->s1);
91         dst = VAROP(iptr->dst);
92
93         if ((src->vv.regoff != dst->vv.regoff) ||
94                 (IS_INMEMORY(src->flags ^ dst->flags))) {
95
96                 if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
97                         /* emit nothing, as the value won't be used anyway */
98                         return;
99                 }
100
101                 /* If one of the variables resides in memory, we can eliminate
102                    the register move from/to the temporary register with the
103                    order of getting the destination register and the load. */
104
105                 if (IS_INMEMORY(src->flags)) {
106                         if (IS_LNG_TYPE(src->type))
107                                 d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
108                         else
109                                 d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
110
111                         s1 = emit_load(jd, iptr, src, d);
112                 }
113                 else {
114                         if (IS_LNG_TYPE(src->type))
115                                 s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
116                         else
117                                 s1 = emit_load(jd, iptr, src, REG_IFTMP);
118
119                         d = codegen_reg_of_var(iptr->opc, dst, s1);
120                 }
121
122                 if (s1 != d) {
123                         switch(src->type)       {
124                         case TYPE_INT: M_INTMOVE(s1, d); break;
125                         case TYPE_ADR: M_ADRMOVE(s1, d); break;
126                         case TYPE_LNG: M_LNGMOVE(s1, d); break;
127 #if !defined(ENABLE_SOFTFLOAT)
128                         case TYPE_FLT: M_FLTMOVE(s1, d); break;
129                         case TYPE_DBL: M_DBLMOVE(s1, d); break;
130 #else
131                         case TYPE_FLT: M_INTMOVE(s1, d); break;
132                         case TYPE_DBL: M_LNGMOVE(s1, d); break;
133 #endif
134                         default:
135                                 vm_abort("emit_copy: unknown type %d", src->type);
136                         }
137                 }
138
139                 emit_store(jd, iptr, dst, d);
140         }
141 }
142
143
144 /* emit_store ******************************************************************
145
146    Emits a possible store of the destination operand.
147
148 *******************************************************************************/
149
150 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
151 {
152         codegendata  *cd;
153
154         /* get required compiler data */
155
156         cd = jd->cd;
157
158         if (IS_INMEMORY(dst->flags)) {
159                 COUNT_SPILLS;
160         
161                 switch(dst->type)       {
162 #if defined(ENABLE_SOFTFLOAT)
163                         case TYPE_DBL:
164 #endif
165                         case TYPE_LNG:
166                                 M_LST(d, REG_SP, dst->vv.regoff);
167                                 break;
168 #if defined(ENABLE_SOFTFLOAT)
169                         case TYPE_FLT:
170 #endif
171                         case TYPE_INT:
172                                 M_IST(d, REG_SP, dst->vv.regoff);
173                                 break;
174                         case TYPE_ADR:
175                                 M_AST(d, REG_SP, dst->vv.regoff);
176                                 break;
177 #if !defined(ENABLE_SOFTFLOAT)
178                         case TYPE_DBL:
179                                 M_DST(d, REG_SP, dst->vv.regoff);
180                                 break;
181                         case TYPE_FLT:
182                                 M_FST(d, REG_SP, dst->vv.regoff);
183                                 break;
184 #endif
185                         default:
186                                 vm_abort("emit_store: unknown type %d", dst->type);
187                 }
188         }
189 }
190
191
192 /* emit_load *******************************************************************
193
194    Emits a possible load of an operand.
195
196 *******************************************************************************/
197
198 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
199 {
200         codegendata *cd;
201         s4           disp;
202         s4           reg;
203
204         /* get required compiler data */
205
206         cd = jd->cd;
207
208         if (IS_INMEMORY(src->flags)) {
209                 COUNT_SPILLS;
210
211                 disp = src->vv.regoff;
212         
213                 switch (src->type)      {
214 #if defined(ENABLE_SOFTFLOAT)
215                         case TYPE_FLT:
216 #endif
217                         case TYPE_INT: 
218                                 M_ILD(tempreg, REG_SP, disp);
219                                 break;
220 #if defined(ENABLE_SOFTFLOAT)
221                         case TYPE_DBL:
222 #endif
223                         case TYPE_LNG:
224                                 M_LLD(tempreg, REG_SP, disp);
225                                 break;
226                         case TYPE_ADR:
227                                 M_ALD(tempreg, REG_SP, disp);
228                                 break;
229 #if !defined(ENABLE_SOFTFLOAT)
230                         case TYPE_FLT:
231                                 M_FLD(tempreg, REG_SP, disp);
232                                 break;
233                         case TYPE_DBL:
234                                 M_DLD(tempreg, REG_SP, disp);
235                                 break;
236 #endif
237                         default:
238                                 vm_abort("emit_load: unknown type %d", src->type);
239                 }
240                 #if 0
241                 if (IS_FLT_DBL_TYPE(src->type)) {
242                         if (IS_2_WORD_TYPE(src->type)) {
243                                 M_DLD(tempreg, REG_SP, disp);
244                          } else {
245                                 M_FLD(tempreg, REG_SP, disp);
246                         }
247                 } else {
248                         if (IS_2_WORD_TYPE(src->type)) {
249                                 M_LLD(tempreg, REG_SP, disp);
250                         } else {
251                                 M_ILD(tempreg, REG_SP, disp);
252                         }
253                 }
254                 #endif
255
256                 reg = tempreg;
257         }
258         else
259                 reg = src->vv.regoff;
260
261         return reg;
262 }
263
264 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) 
265 {
266         codegendata  *cd;
267         s4            disp;
268         s4            reg;
269
270 #if !defined(ENABLE_SOFTFLOAT)
271         assert(src->type == TYPE_LNG);
272 #else
273         assert(src->type == TYPE_LNG || src->type == TYPE_DBL);
274 #endif
275
276         /* get required compiler data */
277         cd = jd->cd;
278
279         if (IS_INMEMORY(src->flags)) {
280                 COUNT_SPILLS;
281
282                 disp = src->vv.regoff;
283                 M_ILD(tempreg, REG_SP, disp + 4);
284                 reg = tempreg;
285         } else {
286                 reg = GET_LOW_REG(src->vv.regoff);
287         }
288         return reg;
289 }
290 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
291 {
292         codegendata  *cd;
293         s4            disp;
294         s4            reg;
295
296 #if !defined(ENABLE_SOFTFLOAT)
297         assert(src->type == TYPE_LNG);
298 #else
299         assert(src->type == TYPE_LNG || src->type == TYPE_DBL);
300 #endif
301         /* get required compiler data */
302         cd = jd->cd;
303
304         if (IS_INMEMORY(src->flags)) {
305                 COUNT_SPILLS;
306                 disp = src->vv.regoff;
307                 M_ILD(tempreg, REG_SP, disp);
308                 reg = tempreg;
309         } else {
310                 reg = GET_HIGH_REG(src->vv.regoff);
311         }
312         return reg;
313 }
314 /* emit_branch *****************************************************************
315
316    Emits the code for conditional and unconditional branchs.
317
318 *******************************************************************************/
319 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) 
320
321         /* calculate the different displacements */
322         /* PC is a at branch instruction + 2 */
323         /* coditional and uncondition branching work the same way */
324         /* short branches have signed 16 bit offset */
325         /* long branches are signed 32 bit */
326         /* the 8 bit offset branching instructions are not used */
327
328         disp  =  disp - 2;
329
330         /* check displacement for overflow */
331         if ((disp & 0x0000FFFF) != disp)        {
332                 if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
333                         cd->flags |= (CODEGENDATA_FLAG_ERROR | CODEGENDATA_FLAG_LONGBRANCHES);
334                 }
335         }
336
337         /* check which branch to generate */
338
339         if (condition == BRANCH_UNCONDITIONAL) {
340                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd))      {
341                         M_BR_32(disp);
342                 } else  {
343                         M_BR_16(disp);
344                 }
345         } else {
346                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
347                         switch (condition) {
348                         case BRANCH_EQ:
349                                 M_BEQ_32(disp);
350                                 break;
351                         case BRANCH_NE:
352                                 M_BNE_32(disp);
353                                 break;
354                         case BRANCH_LT:
355                                 M_BLT_32(disp);
356                                 break;
357                         case BRANCH_GE:
358                                 M_BGE_32(disp);
359                                 break;
360                         case BRANCH_GT:
361                                 M_BGT_32(disp);
362                                 break;
363                         case BRANCH_LE:
364                                 M_BLE_32(disp);
365                                 break;
366                         case BRANCH_NAN:
367                                 M_BNAN_32(disp);
368                                 break;
369                         case BRANCH_UGT:
370                                 M_BHI_32(disp);
371                                 break;
372
373                         default:
374                                 vm_abort("emit_branch: unknown condition %d", condition);
375                         }
376                 } else {
377                         switch (condition) {
378                         case BRANCH_EQ:
379                                 M_BEQ_16(disp);
380                                 break;
381                         case BRANCH_NE:
382                                 M_BNE_16(disp);
383                                 break;
384                         case BRANCH_LT:
385                                 M_BLT_16(disp);
386                                 break;
387                         case BRANCH_GE:
388                                 M_BGE_16(disp);
389                                 break;
390                         case BRANCH_GT:
391                                 M_BGT_16(disp);
392                                 break;
393                         case BRANCH_LE:
394                                 M_BLE_16(disp);
395                                 break;
396                         case BRANCH_NAN:
397                                 M_BNAN_16(disp);
398                                 break;
399                         case BRANCH_UGT:
400                                 M_BHI_16(disp);
401                                 break;
402                         default:
403                                 vm_abort("emit_branch: unknown condition %d", condition);
404                         }
405                 }
406         }
407 }
408
409
410 #if !defined(NDEBUG)
411 /*
412  *      Trace functions. Implement -verbose:call flag
413  *      code marked by real NOP, but performance is no matter when using -verbose:call :)
414  */
415 void emit_verbosecall_enter(jitdata* jd) 
416
417         methodinfo   *m;
418         codegendata  *cd;
419         registerdata *rd;
420         methoddesc   *md;
421
422         if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
423                 return;
424         
425         /* get required compiler data */
426         m  = jd->m;
427         cd = jd->cd;
428         rd = jd->rd;
429         md = m->parseddesc;
430
431         /* mark trace code */
432         M_NOP;
433
434         M_IPUSH(REG_D0);
435         M_IPUSH(REG_D1);
436         M_APUSH(REG_A0);
437         M_APUSH(REG_A1);
438         M_AMOV(REG_SP, REG_A0); /* simpyfy stack offset calculation */
439
440 #if !defined(ENABLE_SOFTFLOAT)
441         M_AADD_IMM(-8*2, REG_SP);
442         M_FSTORE(REG_F0, REG_SP, 8);
443         M_FSTORE(REG_F1, REG_SP, 0);
444 #endif
445         
446         M_AADD_IMM(4*4 + 4, REG_A0);
447         M_APUSH(REG_A0);                /* third arg is original argument stack */
448         M_IPUSH_IMM(0);                 /* second arg is number of argument registers (=0) */
449         M_IPUSH_IMM(m);                 /* first arg is methodpointer */
450         
451         M_JSR_IMM(trace_java_call_enter);
452         /* pop arguments off stack */
453         M_AADD_IMM(3*4, REG_SP);
454
455 #if !defined(ENABLE_SOFTFLOAT)
456         M_FSTORE(REG_F1, REG_SP, 0);
457         M_FSTORE(REG_F0, REG_SP, 8);
458         M_AADD_IMM(8*2, REG_SP);
459 #endif
460
461         M_APOP(REG_A1);
462         M_APOP(REG_A0);
463         M_IPOP(REG_D1);
464         M_IPOP(REG_D0);
465
466         M_NOP;
467 }
468 void emit_verbosecall_exit(jitdata* jd) 
469
470         methodinfo   *m;
471         codegendata  *cd;
472         registerdata *rd;
473         methoddesc   *md;
474
475         if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
476                 return;
477
478         /* get required compiler data */
479         m  = jd->m;
480         cd = jd->cd;
481         rd = jd->rd;
482         md = m->parseddesc;
483
484         /* void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m); */
485
486     /* void trace_java_call_exit(methodinfo *m, uint64_t *return_regs) */
487
488         /* mark trace code */
489         M_NOP;
490
491         /* to store result on stack */
492         M_AADD_IMM(-8, REG_SP);                 /* create space for array */
493
494         switch (md->returntype.type)    {
495                 case TYPE_ADR:
496                 case TYPE_INT:
497         #if defined(ENABLE_SOFTFLOAT)
498                 case TYPE_FLT:
499         #endif
500                         M_IST(REG_D0, REG_SP, 0);
501                         break;
502
503                 case TYPE_LNG:
504         #if defined(ENABLE_SOFTFLOAT)
505                 case TYPE_DBL:
506         #endif
507                         M_LST(REG_D1, REG_SP, 0);
508                         break;
509
510         #if !defined(ENABLE_SOFTFLOAT)
511                 case TYPE_FLT:  /* FIXME */
512                 case TYPE_DBL:  /* FIXME */
513         #endif
514
515                 case TYPE_VOID: /* nothing */
516                         break;
517
518                 default:
519                         assert(0);
520         }
521
522         M_APUSH(REG_SP);                                /* push address of array */
523         M_IPUSH_IMM(m);                                 /* push methodinfo */
524         M_JSR_IMM(trace_java_call_exit);
525
526         M_AADD_IMM(8, REG_SP);                  /* remove args */
527         /* poping result registers from stack */
528         switch (md->returntype.type)    {
529                 case TYPE_ADR:
530                 case TYPE_INT:
531         #if defined(ENABLE_SOFTFLOAT)
532                 case TYPE_FLT:
533         #endif
534                         M_ILD(REG_D0, REG_SP, 0);
535                         break;
536
537                 case TYPE_LNG:
538         #if defined(ENABLE_SOFTFLOAT)
539                 case TYPE_DBL:
540         #endif
541                         M_LLD(REG_D1, REG_SP, 0);
542                         break;
543
544         #if !defined(ENABLE_SOFTFLOAT)
545                 case TYPE_FLT:  /* FIXME */
546                 case TYPE_DBL:  /* FIXME */
547         #endif
548
549                 case TYPE_VOID: /* nothing */
550                         break;
551
552                 default:
553                         assert(0);
554         }
555
556         M_AADD_IMM(8, REG_SP);                  /* remove space for array */
557
558         M_NOP;
559 }
560 #endif
561
562 /* emit_classcast_check ********************************************************
563
564    Emit a ClassCastException check.
565
566 *******************************************************************************/
567
568 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
569 {
570         if (INSTRUCTION_MUST_CHECK(iptr)) {
571                 switch (condition) {
572                 case BRANCH_LE:
573                         M_BGT(4);
574                         break;
575                 case BRANCH_EQ:
576                         M_BNE(4);
577                         break;
578                 case BRANCH_GT:
579                         M_BLE(4);
580                         break;
581                 case BRANCH_UGT:
582                         M_BLS(4);
583                         break;
584                 default:
585                         vm_abort("emit_classcast_check: unknown condition %d", condition);
586                 }
587                 M_TRAP_SETREGISTER(s1);
588                 M_TRAP(TRAP_ClassCastException);
589         }
590 }
591
592 /* emit_arrayindexoutofbounds_check ********************************************
593
594    Emit a ArrayIndexOutOfBoundsException check.
595
596 *******************************************************************************/
597 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
598 {
599         if (INSTRUCTION_MUST_CHECK(iptr)) {
600                 M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
601                 M_ICMP(s2, REG_ITMP3);
602                 M_BHI(4);
603                 M_TRAP_SETREGISTER(s2);
604                 M_TRAP(TRAP_ArrayIndexOutOfBoundsException);
605         }
606 }
607
608
609 /* emit_arraystore_check *******************************************************
610
611    Emit an ArrayStoreException check.
612
613 *******************************************************************************/
614
615 void emit_arraystore_check(codegendata *cd, instruction *iptr)
616 {
617         if (INSTRUCTION_MUST_CHECK(iptr)) {
618                 M_ITST(REG_RESULT);
619                 M_BNE(2);
620                 M_TRAP(TRAP_ArrayStoreException);
621         }
622 }
623
624
625 /* emit_nullpointer_check ******************************************************
626
627    Emit a NullPointerException check.
628
629 *******************************************************************************/
630
631 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
632 {
633         if (INSTRUCTION_MUST_CHECK(iptr)) {
634                 /* XXX: this check is copied to call monitor_enter 
635                  * invocation at the beginning of codegen.c */
636                 M_ATST(reg);
637                 M_BNE(2);
638                 M_TRAP(TRAP_NullPointerException);
639         }
640 }
641
642 /* emit_arithmetic_check *******************************************************
643
644    Emit an ArithmeticException check.
645
646 *******************************************************************************/
647
648 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
649 {
650         if (INSTRUCTION_MUST_CHECK(iptr)) {
651                 M_ITST(reg);
652                 M_BNE(2);
653                 M_TRAP(TRAP_ArithmeticException);
654         }
655 }
656
657 /* emit_exception_check_ireg **************************************************
658
659    Emit an Exception check. Teste register is integer REG_RESULT
660
661 *******************************************************************************/
662 void emit_exception_check(codegendata *cd, instruction *iptr)
663 {
664         if (INSTRUCTION_MUST_CHECK(iptr)) {
665                 M_ITST(REG_RESULT);
666                 M_BNE(2);
667                 M_TRAP(TRAP_CHECK_EXCEPTION);
668         }
669 }
670
671 /* emit_trap_compiler **********************************************************
672
673    Emit a trap instruction which calls the JIT compiler.
674
675 *******************************************************************************/
676
677 void emit_trap_compiler(codegendata *cd)
678 {
679         M_TRAP_SETREGISTER(REG_METHODPTR);
680         M_TRAP(TRAP_COMPILER);
681 }
682
683
684 /* emit_trap *******************************************************************
685
686    Emit a trap instruction and return the original machine code.
687
688 *******************************************************************************/
689
690 uint32_t emit_trap(codegendata *cd)
691 {
692         uint32_t mcode;
693
694         /* Get machine code which is patched back in later. The
695            trap is 2 bytes long. */
696
697         mcode = *((uint32_t *) cd->mcodeptr);
698
699         M_TRAP(TRAP_PATCHER);
700
701         return mcode;
702 }
703
704
705
706 /*
707  * These are local overrides for various environment variables in Emacs.
708  * Please do not remove this and leave it at the end of the file, where
709  * Emacs will automagically detect them.
710  * ---------------------------------------------------------------------
711  * Local variables:
712  * mode: c
713  * indent-tabs-mode: t
714  * c-basic-offset: 4
715  * tab-width: 4
716  * End:
717  * vim:noexpandtab:sw=4:ts=4:
718  */