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