1 /* src/vm/jit/m68k/codegen.c
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
37 #include "vm/jit/m68k/codegen.h"
38 #include "vm/jit/m68k/emit.h"
40 #include "mm/memory.h"
41 #include "native/jni.h"
42 #include "native/localref.h"
43 #include "native/native.h"
45 #include "threads/lock-common.h"
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "vm/global.h"
50 #include "vm/stringlocal.h"
53 #include "vm/jit/asmpart.h"
54 #include "vm/jit/codegen-common.h"
55 #include "vm/jit/dseg.h"
56 #include "vm/jit/emit-common.h"
57 #include "vm/jit/jit.h"
58 #include "vm/jit/abi.h"
59 #include "vm/jit/parse.h"
60 #include "vm/jit/patcher.h"
61 #include "vm/jit/reg.h"
62 #include "vm/jit/replace.h"
63 #include "vm/jit/stacktrace.h"
64 #include "vm/jit/md.h"
66 #include "vmcore/loader.h"
67 #include "vmcore/options.h"
68 #include "vmcore/utf8.h"
71 bool codegen_emit(jitdata *jd)
77 s4 len, s1, s2, s3, d, disp;
83 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
84 unresolved_method *um;
85 builtintable_entry *bte;
92 /* get required compiler data */
99 /* prevent compiler warnings */
107 /* save calle saved registers */
108 s4 savedregs_num = 0;
110 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
111 savedregs_num += (ADR_SAV_CNT - rd->savadrreguse);
112 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
114 cd->stackframesize = rd->memuse + savedregs_num;
116 /* we always add 2 stack slots.
117 * 1 word the lock word, which may be unused and resides @ rd->memuse * 8
118 * + 2 words to either save the return value for LOCK_monitor_exit @ rd->memuse * 8 + 8
119 * on the other hand we could use 2 words when a builtin returns a doulbe which are
120 * returned in %d0, %d1 and need to be stored onto the stack and read in used a fmovemd
121 * so we always _need_ at least 2 slots, and this keeps the code simple */
122 cd->stackframesize += 2;
124 cd->stackframesize *= 8; /* we use 8 byte stack slots */
127 #if defined(ENABLE_THREADS)
128 /* we need additional space to save argument of monitor_enter */
129 if (checksync && code_is_synchronized(code)) {
130 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) {
131 cd->stackframesize += 2;
133 cd->stackframesize += 1;
139 /* create method header */
140 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
141 (void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
143 /* XXX Remove this "offset by one". */
145 code->synchronizedoffset = (rd->memuse + 1) * 8;
147 /* REMOVEME dummy IsSync */
148 (void) dseg_add_unique_s4(cd, 0);
150 /* REMOVEME: We still need it for exception handling in assembler. */
152 if (code_is_leafmethod(code))
153 (void) dseg_add_unique_s4(cd, 1);
155 (void) dseg_add_unique_s4(cd, 0);
157 /* XXX we use the IntSave a split field for the adr now */
158 (void) dseg_add_unique_s4(cd, (ADR_SAV_CNT - rd->savadrreguse) << 16 | (INT_SAV_CNT - rd->savintreguse)); /* IntSave */
159 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
161 dseg_addlinenumbertablesize(cd);
163 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
165 /* create exception table */
166 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
167 dseg_add_target(cd, ex->start);
168 dseg_add_target(cd, ex->end);
169 dseg_add_target(cd, ex->handler);
170 (void) dseg_add_unique_address(cd, ex->catchtype.any);
173 #if defined(ENABLE_PROFILING)
178 emit_verbosecall_enter(jd);
180 /* create stack frame */
181 M_AADD_IMM(-(cd->stackframesize), REG_SP);
183 /* save used callee saved registers */
184 p = cd->stackframesize;
185 for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
186 p-=8; M_IST(rd->savintregs[i], REG_SP, p);
188 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
189 p-=8; M_AST(rd->savadrregs[i], REG_SP, p);
191 #if !defined(ENABLE_SOFTFLOAT)
192 for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
193 p-=8; M_FSTORE(rd->savfltregs[i], REG_SP, p);
196 assert(FLT_SAV_CNT == 0);
197 assert(rd->savfltreguse == 0);
199 /* take arguments out of stack frame */
201 for (p = 0, l = 0; p < md->paramcount; p++) {
202 t = md->paramtypes[p].type;
203 varindex = jd->local_map[l * 5 + t];
206 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
209 if (varindex == UNUSED)
214 s1 = md->params[p].regoff;
215 assert(md->params[p].inmemory); /* all args are on stack */
218 #if defined(ENABLE_SOFTFLOAT)
224 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
225 if (IS_2_WORD_TYPE(t)) {
226 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
228 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
230 } else { /* stack arg -> spilled */
231 M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4);
232 M_IST(REG_ITMP1, REG_SP, var->vv.regoff);
233 if (IS_2_WORD_TYPE(t)) {
234 M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4 + 4);
235 M_IST(REG_ITMP1, REG_SP, var->vv.regoff + 4);
239 #if !defined(ENABLE_SOFTFLOAT)
242 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
243 if (IS_2_WORD_TYPE(t)) {
244 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
246 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
248 } else { /* stack-arg -> spilled */
249 if (IS_2_WORD_TYPE(t)) {
250 M_DLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
251 M_DST(REG_FTMP1, REG_SP, var->vv.regoff);
253 M_FLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
254 M_FST(REG_FTMP1, REG_SP, var->vv.regoff);
258 #endif /* SOFTFLOAT */
260 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
261 M_ALD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
262 } else { /* stack-arg -> spilled */
263 M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + s1 + 4);
264 M_AST(REG_ATMP1, REG_SP, var->vv.regoff);
269 } /* end for argument out of stack*/
271 #if defined(ENABLE_THREADS)
272 /* call lock_monitor_enter function */
273 if (checksync && code_is_synchronized(code)) {
274 if (m->flags & ACC_STATIC) {
275 M_AMOV_IMM((&m->class->object.header), REG_ATMP1);
277 /* for non-static case the first arg is the object */
278 M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + 4);
281 M_TRAP(M68K_EXCEPTION_HARDWARE_NULLPOINTER);
284 M_AST(REG_ATMP1, REG_SP, rd->memuse * 8);
285 M_AST(REG_ATMP1, REG_SP, 0 * 4);
286 M_JSR_IMM(LOCK_monitor_enter);
292 /* create replacement points */
293 REPLACEMENT_POINTS_INIT(cd, jd);
295 /* foreach basic block */
296 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
298 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
300 if (bptr->flags >= BBREACHED) {
302 /* branch resolving */
303 codegen_resolve_branchrefs(cd, bptr);
305 /* handle replacement points */
306 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
308 #if defined(ENABLE_PROFILING)
311 /* FIXME there are still some constrcuts to copy in here */
313 #if defined(ENABLE_LSRA)
317 /* copy interface registers to their destination */
323 var = VAR(bptr->invars[len]);
324 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
325 d = codegen_reg_of_var(0, var, REG_ATMP1_XPTR);
326 M_ADRMOVE(REG_ATMP1_XPTR, d);
327 emit_store(jd, NULL, var, d);
330 assert((var->flags & INOUT));
334 /* walk through all instructions */
338 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
339 if (iptr->line != currentline) {
340 dseg_addlinenumber(cd, iptr->line);
341 currentline = iptr->line;
344 MCODECHECK(1024); /* 1kB should be enough */
347 case ICMD_NOP: /* ... ==> ... */
348 case ICMD_POP: /* ..., value ==> ... */
349 case ICMD_POP2: /* ..., value, value ==> ... */
352 case ICMD_INLINE_START:
354 REPLACEMENT_POINT_INLINE_START(cd, iptr);
357 case ICMD_INLINE_BODY:
359 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
360 dseg_addlinenumber_inline_start(cd, iptr);
361 dseg_addlinenumber(cd, iptr->line);
364 case ICMD_INLINE_END:
366 dseg_addlinenumber_inline_end(cd, iptr);
367 dseg_addlinenumber(cd, iptr->line);
370 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
372 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
373 assert(VAROP(iptr->s1)->type == TYPE_ADR);
374 emit_nullpointer_check(cd, iptr, s1);
378 /* CONST **************************************************************/
379 case ICMD_ICONST: /* ... ==> ..., constant */
380 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
381 M_IMOV_IMM(iptr->sx.val.i, d);
382 emit_store_dst(jd, iptr, d);
385 case ICMD_LCONST: /* ... ==> ..., constant */
387 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
388 LCONST(iptr->sx.val.l, d);
389 emit_store_dst(jd, iptr, d);
392 case ICMD_FCONST: /* ... ==> ..., constant */
394 #if defined(ENABLE_SOFTFLOAT)
395 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
396 M_IMOV_IMM(iptr->sx.val.i, d);
397 emit_store_dst(jd, iptr, d);
399 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
400 FCONST(iptr->sx.val.i, d);
401 emit_store_dst(jd, iptr, d);
405 case ICMD_DCONST: /* ... ==> ..., constant */
407 #if defined(ENABLE_SOFTFLOAT)
408 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
409 LCONST(iptr->sx.val.l, d);
410 emit_store_dst(jd, iptr, d);
412 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
413 disp = dseg_add_double(cd, iptr->sx.val.d);
414 M_AMOV_IMM(0, REG_ATMP1);
416 M_DLD(d, REG_ATMP1, disp);
417 emit_store_dst(jd, iptr, d);
422 /* some long operations *********************************************/
423 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
424 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
425 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
426 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
427 M_INTMOVE(s2, REG_ITMP1);
428 M_IADD(s1, REG_ITMP1); /* low word */
429 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
430 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
431 M_INTMOVE(s2, REG_ITMP2);
432 M_IADDX(s1, REG_ITMP2); /* high word */
433 emit_store_dst(jd, iptr, d);
436 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
437 /* sx.val.l = constant */
438 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
439 s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
440 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
442 M_IMOV_IMM(iptr->sx.val.l >> 32, REG_ITMP3);
444 s3 = iptr->sx.val.l & 0xffffffff;
445 M_INTMOVE(s1, REG_ITMP1);
446 M_IADD_IMM(s3, REG_ITMP1); /* lower word in REG_ITMP1 now */
448 M_IADDX(REG_ITMP3, REG_ITMP2); /* high word in REG_ITMP2 now */
449 M_LNGMOVE(REG_ITMP12_PACKED, d);
450 emit_store_dst(jd, iptr, d);
453 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
454 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
455 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
456 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
457 M_INTMOVE(s1, REG_ITMP1);
458 M_ISUB(s2, REG_ITMP1); /* low word */
459 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
460 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
461 M_INTMOVE(s1, REG_ITMP2);
462 M_ISUBX(s2, REG_ITMP2); /* high word */
463 emit_store_dst(jd, iptr, d);
466 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
467 /* sx.val.l = constant */
468 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
469 s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
470 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
472 M_IMOV_IMM( (-iptr->sx.val.l) >> 32, REG_ITMP3);
474 s3 = (-iptr->sx.val.l) & 0xffffffff;
475 M_INTMOVE(s1, REG_ITMP1);
476 M_IADD_IMM(s3, REG_ITMP1); /* lower word in REG_ITMP1 now */
478 M_IADDX(REG_ITMP3, REG_ITMP2); /* high word in REG_ITMP2 now */
479 M_LNGMOVE(REG_ITMP12_PACKED, d);
480 emit_store_dst(jd, iptr, d);
483 case ICMD_LNEG: /* ..., value ==> ..., - value */
484 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
485 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
486 M_LNGMOVE(s1, REG_ITMP12_PACKED);
487 M_INEG(GET_LOW_REG(REG_ITMP12_PACKED));
488 M_INEGX(GET_HIGH_REG(REG_ITMP12_PACKED));
489 M_LNGMOVE(REG_ITMP12_PACKED, d);
490 emit_store_dst(jd, iptr, d);
493 /* integer operations ************************************************/
494 case ICMD_INEG: /* ..., value ==> ..., - value */
496 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
497 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
498 M_INTMOVE(s1, REG_ITMP1);
500 M_INTMOVE(REG_ITMP1, d);
501 emit_store_dst(jd, iptr, d);
504 case ICMD_I2L: /* ..., value ==> ..., value */
506 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
507 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
508 M_IMOV(s1, GET_LOW_REG(d)); /* sets negativ bit */
510 M_ISET(GET_HIGH_REG(d));
512 M_ICLR(GET_HIGH_REG(d));
514 emit_store_dst(jd, iptr, d);
517 case ICMD_L2I: /* ..., value ==> ..., value */
519 s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
520 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
522 emit_store_dst(jd, iptr, d);
524 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
526 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
527 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
529 emit_store_dst(jd, iptr, d);
532 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
534 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
535 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
537 emit_store_dst(jd, iptr, d);
540 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
542 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
543 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
545 emit_store_dst(jd, iptr, d);
550 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
552 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
553 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
554 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
555 M_INTMOVE(s2, REG_ITMP2);
556 M_IADD(s1, REG_ITMP2);
557 M_INTMOVE(REG_ITMP2, d);
558 emit_store_dst(jd, iptr, d);
561 /* s1.localindex = variable, sx.val.i = constant*/
566 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
567 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
568 M_INTMOVE(s1, REG_ITMP1);
569 M_IADD_IMM(iptr->sx.val.i, REG_ITMP1);
570 M_INTMOVE(REG_ITMP1, d);
571 emit_store_dst(jd, iptr, d);
574 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
576 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
577 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
578 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
579 M_INTMOVE(s1, REG_ITMP1);
580 M_ISUB(s2, REG_ITMP1);
581 M_INTMOVE(REG_ITMP1, d);
582 emit_store_dst(jd, iptr, d);
585 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
586 /* sx.val.i = constant */
588 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
589 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
590 M_INTMOVE(s1, REG_ITMP1);
591 M_IADD_IMM(-iptr->sx.val.i, REG_ITMP1);
592 M_INTMOVE(REG_ITMP1, d);
593 emit_store_dst(jd, iptr, d);
596 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
597 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
598 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
599 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
600 emit_arithmetic_check(cd, iptr, s2);
601 M_INTMOVE(s1, REG_ITMP1);
602 M_IDIV(s2, REG_ITMP1);
603 M_INTMOVE(REG_ITMP1, d);
604 emit_store_dst(jd, iptr, d);
607 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
608 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
609 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
610 M_INTMOVE(s1, REG_ITMP1);
614 M_IADD_IMM((1 << iptr->sx.val.i) - 1, REG_ITMP1);
616 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
617 M_ISSR(REG_ITMP2, REG_ITMP1);
618 M_INTMOVE(REG_ITMP1, d);
619 emit_store_dst(jd, iptr, d);
622 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
623 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
624 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
625 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
626 emit_arithmetic_check(cd, iptr, s2);
628 M_ICMP_IMM(0x80000000, s1);
633 M_TPFL; /* hides the next instruction */
634 M_IREM(s2, s1, REG_ITMP3);
636 M_INTMOVE(REG_ITMP3, d);
638 emit_store_dst(jd, iptr, d);
641 case ICMD_IREMPOW2: /* ..., value ==> ..., value << constant */
642 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
643 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
645 M_IMOV(s1, REG_ITMP1);
649 M_IAND_IMM(iptr->sx.val.i, d);
651 M_BGE(2 + 2 + 6 + 2);
652 M_IMOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */
654 M_IAND_IMM(iptr->sx.val.i, d); /* use 32-bit for jump offset */
657 emit_store_dst(jd, iptr, d);
661 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
662 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
664 bte = iptr->sx.s23.s3.bte;
667 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
668 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
669 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
670 /* XXX could be optimized */
671 emit_arithmetic_check(cd, iptr, REG_ITMP3);
673 M_LST(s2, REG_SP, 2 * 4);
674 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
675 M_LST(s1, REG_SP, 0 * 4);
679 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
680 M_LNGMOVE(REG_RESULT_PACKED, d);
681 emit_store_dst(jd, iptr, d);
684 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
686 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
687 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
688 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
689 M_INTMOVE(s2, REG_ITMP2);
690 M_IMUL(s1, REG_ITMP2);
691 M_INTMOVE(REG_ITMP2, d);
692 emit_store_dst(jd, iptr, d);
695 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
696 /* sx.val.i = constant */
697 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
698 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
699 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
700 M_IMUL(s1, REG_ITMP2);
701 M_INTMOVE(REG_ITMP2, d);
702 emit_store_dst(jd, iptr, d);
705 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
707 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
708 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
709 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
710 M_INTMOVE(s1, REG_ITMP1);
711 M_INTMOVE(s2, REG_ITMP2);
712 M_IAND_IMM(0x1f, REG_ITMP2);
713 M_ISSL(REG_ITMP2, REG_ITMP1);
714 M_INTMOVE(REG_ITMP1, d);
715 emit_store_dst(jd, iptr, d);
718 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
719 /* sx.val.i = constant */
721 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
722 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
723 if (iptr->sx.val.i & 0x1f) {
724 M_INTMOVE(s1, REG_ITMP1)
725 if ((iptr->sx.val.i & 0x1f) <= 7) {
726 M_ISSL_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
728 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
729 M_ISSL(REG_ITMP2, REG_ITMP1);
731 M_INTMOVE(REG_ITMP1, d);
735 emit_store_dst(jd, iptr, d);
738 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
740 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
741 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
742 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
743 M_INTMOVE(s1, REG_ITMP1);
744 M_INTMOVE(s2, REG_ITMP2);
745 M_IAND_IMM(0x1f, REG_ITMP2);
746 M_ISSR(REG_ITMP2, REG_ITMP1);
747 M_INTMOVE(REG_ITMP1, d);
748 emit_store_dst(jd, iptr, d);
751 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
752 /* sx.val.i = constant */
754 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
755 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
756 if (iptr->sx.val.i & 0x1f) {
757 M_INTMOVE(s1, REG_ITMP1)
758 if ((iptr->sx.val.i & 0x1f) <= 7) {
759 M_ISSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
761 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
762 M_ISSR(REG_ITMP2, REG_ITMP1);
764 M_INTMOVE(REG_ITMP1, d);
768 emit_store_dst(jd, iptr, d);
771 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
773 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
774 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
775 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
776 M_INTMOVE(s1, REG_ITMP1);
777 M_INTMOVE(s2, REG_ITMP2);
778 M_IAND_IMM(0x1f, REG_ITMP2);
779 M_IUSR(REG_ITMP2, REG_ITMP1);
780 M_INTMOVE(REG_ITMP1, d);
781 emit_store_dst(jd, iptr, d);
784 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
785 /* sx.val.i = constant */
786 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
787 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
788 if (iptr->sx.val.i & 0x1f) {
789 M_INTMOVE(s1, REG_ITMP1)
790 if ((iptr->sx.val.i & 0x1f) <= 7) {
791 M_IUSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
793 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
794 M_IUSR(REG_ITMP2, REG_ITMP1);
796 M_INTMOVE(REG_ITMP1, d);
800 emit_store_dst(jd, iptr, d);
803 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
805 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
806 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
807 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
808 M_INTMOVE(s2, REG_ITMP2);
809 M_IAND(s1, REG_ITMP2);
810 M_INTMOVE(REG_ITMP2, d);
811 emit_store_dst(jd, iptr, d);
814 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
815 /* sx.val.i = constant */
817 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
818 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
819 M_INTMOVE(s1, REG_ITMP1);
820 M_IAND_IMM(iptr->sx.val.i, REG_ITMP1);
821 M_INTMOVE(REG_ITMP1, d);
822 emit_store_dst(jd, iptr, d);
825 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
826 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
827 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
828 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
829 M_INTMOVE(s2, REG_ITMP2);
830 M_IOR(s1, REG_ITMP2);
831 M_INTMOVE(REG_ITMP2, d);
832 emit_store_dst(jd, iptr, d);
835 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
836 /* sx.val.i = constant */
837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
839 M_INTMOVE(s1, REG_ITMP1);
840 M_IOR_IMM(iptr->sx.val.i, REG_ITMP1);
841 M_INTMOVE(REG_ITMP1, d);
842 emit_store_dst(jd, iptr, d);
845 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 | val2 */
846 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
847 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
848 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
849 M_INTMOVE(s2, REG_ITMP2);
850 M_IXOR(s1, REG_ITMP2);
851 M_INTMOVE(REG_ITMP2, d);
852 emit_store_dst(jd, iptr, d);
855 case ICMD_IXORCONST: /* ..., value ==> ..., value | constant */
856 /* sx.val.i = constant */
857 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
858 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
859 M_INTMOVE(s1, REG_ITMP1);
860 M_IXOR_IMM(iptr->sx.val.i, REG_ITMP1);
861 M_INTMOVE(REG_ITMP1, d);
862 emit_store_dst(jd, iptr, d);
865 /* floating point operations ******************************************/
866 #if !defined(ENABLE_SOFTFLOAT)
867 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
869 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
870 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
871 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
874 M_BFUN(14); /* result is -1, branch to end */
875 M_BFLT(10); /* result is -1, branch to end */
877 M_BFEQ(4) /* result is 0, branch to end */
879 emit_store_dst(jd, iptr, d);
882 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
884 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
885 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
886 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
889 M_BFUN(16); /* result is +1, branch to end */
890 M_BFGT(14); /* result is +1, branch to end */
892 M_BFEQ(8) /* result is 0, branch to end */
894 emit_store_dst(jd, iptr, d);
897 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
898 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
899 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
900 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
901 M_FLTMOVE(s2, REG_FTMP2);
902 M_FMUL(s1, REG_FTMP2);
903 M_FLTMOVE(REG_FTMP2, d);
904 emit_store_dst(jd, iptr, d);
907 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
908 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
909 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
910 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
911 M_DBLMOVE(s2, REG_FTMP2);
912 M_DMUL(s1, REG_FTMP2);
913 M_DBLMOVE(REG_FTMP2, d);
914 emit_store_dst(jd, iptr, d);
917 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
918 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
919 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
920 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
921 M_FLTMOVE(s1, REG_FTMP1);
922 M_FDIV(s2, REG_FTMP1);
923 M_FLTMOVE(REG_FTMP1, d);
924 emit_store_dst(jd, iptr, d);
927 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
928 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
929 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
930 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
931 M_DBLMOVE(s1, REG_FTMP1);
932 M_DDIV(s2, REG_FTMP1);
933 M_DBLMOVE(REG_FTMP1, d);
934 emit_store_dst(jd, iptr, d);
937 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
938 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
939 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
940 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
941 M_FLTMOVE(s2, REG_FTMP2);
942 M_FADD(s1, REG_FTMP2);
943 M_FLTMOVE(REG_FTMP2, d);
944 emit_store_dst(jd, iptr, d);
947 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
948 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
949 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
950 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
951 M_DBLMOVE(s2, REG_FTMP2);
952 M_DADD(s1, REG_FTMP2);
953 M_DBLMOVE(REG_FTMP2, d);
954 emit_store_dst(jd, iptr, d);
957 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
958 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
959 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
960 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
961 M_FLTMOVE(s1, REG_FTMP1);
962 M_FSUB(s2, REG_FTMP1);
963 M_FLTMOVE(REG_FTMP1, d);
964 emit_store_dst(jd, iptr, d);
967 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
968 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
969 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
970 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
971 M_DBLMOVE(s1, REG_FTMP1);
972 M_DSUB(s2, REG_FTMP1);
973 M_DBLMOVE(REG_FTMP1, d);
974 emit_store_dst(jd, iptr, d);
977 case ICMD_F2D: /* ..., value ==> ..., (double) value */
978 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
979 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
981 emit_store_dst(jd, iptr, d);
984 case ICMD_D2F: /* ..., value ==> ..., (float) value */
985 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
986 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
988 emit_store_dst(jd, iptr, d);
991 case ICMD_FNEG: /* ..., value ==> ..., - value */
992 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
993 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
995 emit_store_dst(jd, iptr, d);
998 case ICMD_DNEG: /* ..., value ==> ..., - value */
999 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1000 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1002 emit_store_dst(jd, iptr, d);
1007 /* load/store/copy/move operations ************************************/
1009 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
1010 case ICMD_ALOAD: /* s1 = local variable */
1014 case ICMD_ISTORE: /* ..., value ==> ... */
1021 emit_copy(jd, iptr);
1026 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
1027 emit_copy(jd, iptr);
1031 case ICMD_ACONST: /* ... ==> ..., constant */
1032 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1034 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1035 constant_classref *cr = iptr->sx.val.c.ref;;
1036 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
1039 M_AMOV_IMM(iptr->sx.val.anyptr, d);
1041 emit_store_dst(jd, iptr, d);
1043 /* BRANCH *************************************************************/
1045 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1047 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1048 M_ADRMOVE(s1, REG_ATMP1_XPTR);
1050 #ifdef ENABLE_VERIFIER
1051 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1052 unresolved_class *uc = iptr->sx.s23.s2.uc;
1054 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1056 #endif /* ENABLE_VERIFIER */
1057 M_JSR_PCREL(2); /* get current PC */
1060 M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
1065 case ICMD_GOTO: /* ... ==> ... */
1066 case ICMD_RET: /* ... ==> ... */
1068 emit_br(cd, iptr->dst.block);
1072 case ICMD_JSR: /* ... ==> ... */
1074 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1080 case ICMD_IFNULL: /* ..., value ==> ... */
1081 case ICMD_IFNONNULL:
1082 assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
1083 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1085 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
1093 case ICMD_IFEQ: /* ..., value ==> ... */
1095 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1096 assert (VAROP(iptr->s1)->type == TYPE_INT);
1097 M_ICMP_IMM(iptr->sx.val.i, s1);
1098 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1101 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1102 case ICMD_IF_ICMPNE:
1103 case ICMD_IF_ICMPLT:
1104 case ICMD_IF_ICMPGT:
1105 case ICMD_IF_ICMPLE:
1106 case ICMD_IF_ICMPGE:
1108 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1109 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1111 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
1114 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
1115 case ICMD_IF_ACMPNE:
1117 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1118 s2 = emit_load_s2(jd, iptr, REG_ATMP2);
1120 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
1124 /* MEMORY *************************************************************/
1126 case ICMD_GETSTATIC: /* ... ==> ..., value */
1128 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1129 uf = iptr->sx.s23.s3.uf;
1130 fieldtype = uf->fieldref->parseddesc.fd->type;
1133 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1136 fi = iptr->sx.s23.s3.fmiref->p.field;
1137 fieldtype = fi->type;
1138 disp = (intptr_t) fi->value;
1140 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1141 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
1146 M_AMOV_IMM(disp, REG_ATMP1);
1147 switch (fieldtype) {
1148 #if defined(ENABLE_SOFTFLOAT)
1152 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1153 M_ILD(d, REG_ATMP1, 0);
1156 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1157 M_ALD(d, REG_ATMP1, 0);
1159 #if defined(ENABLE_SOFTFLOAT)
1163 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1164 M_LLD(d, REG_ATMP1, 0);
1166 #if !defined(ENABLE_SOFTFLOAT)
1168 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1169 M_FLD(d, REG_ATMP1, 0);
1172 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1173 M_DLD(d, REG_ATMP1, 0);
1177 emit_store_dst(jd, iptr, d);
1180 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1182 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1183 uf = iptr->sx.s23.s3.uf;
1184 fieldtype = uf->fieldref->parseddesc.fd->type;
1187 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1190 fi = iptr->sx.s23.s3.fmiref->p.field;
1191 fieldtype = fi->type;
1192 disp = (intptr_t) fi->value;
1194 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1195 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
1199 M_AMOV_IMM(disp, REG_ATMP1);
1200 switch (fieldtype) {
1201 #if defined(ENABLE_SOFTFLOAT)
1205 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1206 M_IST(s1, REG_ATMP1, 0);
1208 #if defined(ENABLE_SOFTFLOAT)
1212 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1213 M_LST(s1, REG_ATMP1, 0);
1216 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1217 M_AST(s1, REG_ATMP1, 0);
1219 #if !defined(ENABLE_SOFTFLOAT)
1221 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1222 M_FST(s1, REG_ATMP1, 0);
1225 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1226 M_DST(s1, REG_ATMP1, 0);
1233 case ICMD_GETFIELD: /* ... ==> ..., value */
1235 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1237 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1238 uf = iptr->sx.s23.s3.uf;
1239 fieldtype = uf->fieldref->parseddesc.fd->type;
1242 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1245 fi = iptr->sx.s23.s3.fmiref->p.field;
1246 fieldtype = fi->type;
1250 /* implicit null-pointer check */
1251 switch (fieldtype) {
1252 #if defined(ENABLE_SOFTFLOAT)
1256 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1259 #if defined(ENABLE_SOFTFLOAT)
1263 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1267 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1270 #if !defined(ENABLE_SOFTFLOAT)
1272 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1276 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1281 emit_store_dst(jd, iptr, d);
1284 case ICMD_PUTFIELD: /* ..., value ==> ... */
1286 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1288 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1289 uf = iptr->sx.s23.s3.uf;
1290 fieldtype = uf->fieldref->parseddesc.fd->type;
1294 fi = iptr->sx.s23.s3.fmiref->p.field;
1295 fieldtype = fi->type;
1299 if (IS_INT_LNG_TYPE(fieldtype)) {
1300 if (IS_2_WORD_TYPE(fieldtype)) {
1301 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1303 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1306 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1309 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1310 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1312 /* implicit null-pointer check */
1313 switch (fieldtype) {
1314 #if defined(ENABLE_SOFTFLOAT)
1318 M_IST(s2, s1, disp);
1321 #if defined(ENABLE_SOFTFLOAT)
1325 M_LST(s2, s1, disp);
1328 M_AST(s2, s1, disp);
1330 #if !defined(ENABLE_SOFTFLOAT)
1332 M_FST(s2, s1, disp);
1335 M_DST(s2, s1, disp);
1341 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1343 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1344 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1345 /* implicit null-pointer check */
1346 M_ILD(d, s1, OFFSET(java_array_t, size));
1347 emit_store_dst(jd, iptr, d);
1350 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1352 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1353 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1354 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1355 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1356 M_INTMOVE(s2, REG_ITMP2);
1357 M_IADD_IMM(OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1358 M_ADRMOVE(s1, REG_ATMP1);
1359 M_AADDINT(REG_ITMP2, REG_ATMP1);
1360 /* implicit null-pointer check */
1361 M_LBZX(REG_ATMP1, d);
1363 emit_store_dst(jd, iptr, d);
1366 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1368 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1369 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1370 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1371 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1372 M_INTMOVE(s2, REG_ITMP2);
1373 M_ISSL_IMM(1, REG_ITMP2);
1374 M_IADD_IMM(OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1375 M_ADRMOVE(s1, REG_ATMP1);
1376 M_AADDINT(REG_ITMP2, REG_ATMP1);
1377 /* implicit null-pointer check */
1378 M_LHZX(REG_ATMP1, d);
1380 emit_store_dst(jd, iptr, d);
1383 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1385 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1386 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1387 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1388 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1389 M_INTMOVE(s2, REG_ITMP2);
1390 M_ISSL_IMM(1, REG_ITMP2);
1391 M_IADD_IMM(OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1392 M_ADRMOVE(s1, REG_ATMP1);
1393 M_AADDINT(REG_ITMP2, REG_ATMP1);
1395 /* implicit null-pointer check */
1396 M_LHZX(REG_ATMP1, d);
1398 emit_store_dst(jd, iptr, d);
1401 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1403 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1404 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1405 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1406 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1407 M_INTMOVE(s2, REG_ITMP2);
1408 M_ISSL_IMM(2, REG_ITMP2);
1409 M_IADD_IMM(OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1410 M_ADRMOVE(s1, REG_ATMP1);
1411 M_AADDINT(REG_ITMP2, REG_ATMP1);
1412 /* implicit null-pointer check */
1413 M_LWZX(REG_ATMP1, d);
1414 emit_store_dst(jd, iptr, d);
1417 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1418 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1419 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1420 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1421 /* implicit null-pointer check */
1422 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1423 M_INTMOVE(s2, REG_ITMP1);
1424 M_ISSL_IMM(3, REG_ITMP1);
1425 M_IADD_IMM(OFFSET(java_longarray_t, data[0]), REG_ITMP1);
1426 M_ADRMOVE(s1, REG_ATMP1);
1427 M_AADDINT(REG_ITMP1, REG_ATMP1);
1428 /* implicit null-pointer check */
1429 M_LLD(d, REG_ATMP1, 0);
1430 emit_store_dst(jd, iptr, d);
1433 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1434 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1435 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1436 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1437 M_INTMOVE(s2, REG_ITMP2);
1438 M_ISSL_IMM(2, REG_ITMP2);
1439 M_IADD_IMM(OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1440 M_ADRMOVE(s1, REG_ATMP1);
1441 M_AADDINT(REG_ITMP2, REG_ATMP1);
1442 /* implicit null-pointer check */
1443 #if !defined(ENABLE_SOFTFLOAT)
1444 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1445 M_FLD(d, REG_ATMP1, 0);
1447 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1448 M_LWZX(REG_ATMP1, d);
1450 emit_store_dst(jd, iptr, d);
1453 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1454 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1455 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1456 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1457 M_INTMOVE(s2, REG_ITMP2);
1458 M_ISSL_IMM(3, REG_ITMP2);
1459 M_IADD_IMM(OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1460 M_ADRMOVE(s1, REG_ATMP1);
1461 M_AADDINT(REG_ITMP2, REG_ATMP1);
1462 /* implicit null-pointer check */
1463 #if !defined(ENABLE_SOFTFLOAT)
1464 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1465 M_DLD(d, REG_ATMP1, 0);
1467 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1468 M_LLD(d, REG_ATMP1, 0);
1470 emit_store_dst(jd, iptr, d);
1473 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1474 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1475 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1476 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1477 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1478 M_INTMOVE(s2, REG_ITMP2);
1479 M_ISSL_IMM(2, REG_ITMP2);
1480 M_IADD_IMM(OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
1481 M_ADRMOVE(s1, REG_ATMP1);
1482 M_AADDINT(REG_ITMP2, REG_ATMP1);
1484 /* implicit null-pointer check */
1485 M_LAX(REG_ATMP1, d);
1486 emit_store_dst(jd, iptr, d);
1490 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1491 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1492 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1493 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1494 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1495 M_INTMOVE(s2, REG_ITMP2);
1496 M_IADD_IMM(OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1497 M_ADRMOVE(s1, REG_ATMP1);
1498 M_AADDINT(REG_ITMP2, REG_ATMP1);
1499 /* implicit null-pointer check */
1500 M_STBX(REG_ATMP1, s3);
1503 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1504 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1505 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1506 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1507 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1508 M_INTMOVE(s2, REG_ITMP2);
1509 M_ISSL_IMM(1, REG_ITMP2);
1510 M_IADD_IMM(OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1511 M_ADRMOVE(s1, REG_ATMP1);
1512 M_AADDINT(REG_ITMP2, REG_ATMP1);
1513 /* implicit null-pointer check */
1514 M_STHX(REG_ATMP1, s3);
1517 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1518 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1519 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1520 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1521 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1522 M_INTMOVE(s2, REG_ITMP2);
1523 M_ISSL_IMM(1, REG_ITMP2);
1524 M_IADD_IMM(OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1525 M_ADRMOVE(s1, REG_ATMP1);
1526 M_AADDINT(REG_ITMP2, REG_ATMP1);
1527 /* implicit null-pointer check */
1528 M_STHX(REG_ATMP1, s3);
1531 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1532 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1533 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1534 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1535 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1536 M_INTMOVE(s2, REG_ITMP2);
1537 M_ISSL_IMM(2, REG_ITMP2);
1538 M_IADD_IMM(OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1539 M_ADRMOVE(s1, REG_ATMP1);
1540 M_AADDINT(REG_ITMP2, REG_ATMP1);
1541 /* implicit null-pointer check */
1542 M_STWX(REG_ATMP1, s3);
1545 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1546 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1547 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1548 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1550 M_INTMOVE(s2, REG_ITMP1);
1551 M_ISSL_IMM(3, REG_ITMP1);
1552 M_IADD_IMM(OFFSET(java_longarray_t, data[0]), REG_ITMP1);
1553 M_ADRMOVE(s1, REG_ATMP1);
1554 M_AADDINT(REG_ITMP1, REG_ATMP1);
1555 /* implicit null-pointer check */
1556 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1557 M_LST(s3, REG_ATMP1, 0);
1560 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1561 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1562 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1563 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1564 M_INTMOVE(s2, REG_ITMP2);
1565 M_ISSL_IMM(2, REG_ITMP2);
1566 M_IADD_IMM(OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1567 M_ADRMOVE(s1, REG_ATMP1);
1568 M_AADDINT(REG_ITMP2, REG_ATMP1);
1569 /* implicit null-pointer check */
1570 #if !defined(ENABLE_SOFTFLOAT)
1571 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1572 M_FST(s3, REG_ATMP1, 0);
1574 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1575 M_STWX(REG_ATMP1, s3);
1579 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1580 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1581 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1582 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1583 M_INTMOVE(s2, REG_ITMP2);
1584 M_ISSL_IMM(3, REG_ITMP2);
1585 M_IADD_IMM(OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1586 M_ADRMOVE(s1, REG_ATMP1);
1587 M_AADDINT(REG_ITMP2, REG_ATMP1);
1588 /* implicit null-pointer check */
1589 #if !defined(ENABLE_SOFTFLOAT)
1590 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1591 M_DST(s3, REG_ATMP1, 0);
1593 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1594 /* implicit null-pointer check */
1595 M_LST(s3, REG_ATMP1, 0);
1599 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1601 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1602 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1603 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1604 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1606 /* XXX what if array is NULL */
1607 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1609 M_AST(s1, REG_SP, 0*4);
1610 M_AST(s3, REG_SP, 1*4);
1611 M_JSR_IMM(BUILTIN_FAST_canstore);
1612 emit_arraystore_check(cd, iptr);
1614 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1615 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1616 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1617 M_INTMOVE(s2, REG_ITMP1);
1618 M_ISSL_IMM(2, REG_ITMP1);
1619 M_IADD_IMM(OFFSET(java_objectarray_t, data[0]), REG_ITMP1);
1620 M_ADRMOVE(s1, REG_ATMP1);
1621 M_AADDINT(REG_ITMP1, REG_ATMP1);
1622 /* implicit null-pointer check */
1623 M_STAX(REG_ATMP1, s3);
1628 /* METHOD INVOCATION *********************************************************/
1629 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
1630 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
1632 bte = iptr->sx.s23.s3.bte;
1636 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1637 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1638 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1639 case ICMD_INVOKEINTERFACE:
1640 REPLACEMENT_POINT_INVOKE(cd, iptr);
1642 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1644 um = iptr->sx.s23.s3.um;
1645 md = um->methodref->parseddesc.md;
1648 lm = iptr->sx.s23.s3.fmiref->p.method;
1650 md = lm->parseddesc;
1653 s3 = md->paramcount;
1655 MCODECHECK((s3 << 1) + 64);
1657 /* copy arguments to stack */
1658 for (s3 = s3 - 1; s3 >= 0; s3--) {
1659 var = VAR(iptr->sx.s23.s2.args[s3]);
1660 /* already preallocated */
1661 if (var->flags & PREALLOC) continue;
1663 if (!md->params[s3].inmemory) assert(0);
1665 switch (var->type) {
1666 #if defined(ENABLE_SOFTFLOAT)
1670 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
1671 M_LST(d, REG_SP, md->params[s3].regoff);
1673 #if defined(ENABLE_SOFTFLOAT)
1677 d = emit_load(jd, iptr, var, REG_ITMP1);
1678 M_IST(d, REG_SP, md->params[s3].regoff);
1681 d = emit_load(jd, iptr, var, REG_ATMP1);
1682 M_AST(d, REG_SP, md->params[s3].regoff);
1684 #if !defined(ENABLE_SOFTFLOAT)
1686 d = emit_load(jd, iptr, var, REG_FTMP1);
1687 M_FST(d, REG_SP, md->params[s3].regoff);
1690 d = emit_load(jd, iptr, var, REG_FTMP1);
1691 M_DST(d, REG_SP, md->params[s3].regoff);
1699 /* arguments in place now */
1702 if (bte->stub == NULL)
1703 disp = (ptrint) bte->fp;
1705 disp = (ptrint) bte->stub;
1706 d = md->returntype.type;
1709 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1712 case ICMD_INVOKESPECIAL:
1713 /* adress register for sure */
1714 M_ALD(REG_ATMP1, REG_SP, 0);
1715 emit_nullpointer_check(cd, iptr, REG_ATMP1);
1717 case ICMD_INVOKESTATIC:
1719 codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
1721 M_AMOV_IMM(disp, REG_ATMP1);
1723 disp = lm->stubroutine;
1724 M_AMOV_IMM(disp, REG_ATMP1);
1727 /* generate the actual call */
1729 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1733 case ICMD_INVOKEVIRTUAL:
1735 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
1738 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1740 /* load object pointer (==argument 0) */
1741 M_ALD(REG_ATMP1, REG_SP, 0);
1742 /* implicit null-pointer check */
1743 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
1744 M_ALD(REG_ATMP3, REG_METHODPTR, s1);
1745 /* generate the actual call */
1748 case ICMD_INVOKEINTERFACE:
1750 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
1755 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
1756 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1758 /* load object pointer (==argument 0) */
1759 M_ALD(REG_ATMP1, REG_SP, 0);
1761 /* implicit null-pointer check */
1762 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
1763 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
1764 M_ALD(REG_ATMP3, REG_METHODPTR, s2);
1766 /* generate the actual call */
1768 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1772 } /* switch (iptr->opc) */
1774 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1775 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
1777 /* store return value */
1778 d = md->returntype.type;
1781 case TYPE_VOID: break;
1782 #if defined(ENABLE_SOFTFLOAT)
1786 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
1787 M_INTMOVE(REG_RESULT, s1);
1789 #if defined(ENABLE_SOFTFLOAT)
1793 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1794 M_LNGMOVE(REG_RESULT_PACKED, s1);
1797 s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
1798 /* all stuff is returned in %d0 */
1799 M_INT2ADRMOVE(REG_RESULT, s1);
1801 #if !defined(ENABLE_SOFTFLOAT)
1803 * for BUILTINS float values are returned in %d0,%d1
1804 * within cacao we use %fp0 for that.
1807 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1808 if (iptr->opc == ICMD_BUILTIN) {
1809 M_INT2FLTMOVE(REG_FRESULT, s1);
1811 M_FLTMOVE(REG_FRESULT, s1);
1815 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1816 if (iptr->opc == ICMD_BUILTIN) {
1817 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4 + 4);
1818 M_DLD(s1, REG_SP, rd->memuse * 4 + 4);
1820 M_DBLMOVE(REG_FRESULT, s1);
1827 if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
1828 break; /* ICMD_INVOKE* */
1830 #if defined(ENABLE_SOFTFLOAT)
1833 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1835 REPLACEMENT_POINT_RETURN(cd, iptr);
1836 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1837 M_INTMOVE(s1, REG_RESULT);
1838 goto nowperformreturn;
1840 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1842 REPLACEMENT_POINT_RETURN(cd, iptr);
1843 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1844 assert(VAROP(iptr->s1)->type == TYPE_ADR);
1845 M_ADR2INTMOVE(s1, REG_RESULT);
1847 #ifdef ENABLE_VERIFIER
1848 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1849 unresolved_class *uc = iptr->sx.s23.s2.uc;
1851 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1853 #endif /* ENABLE_VERIFIER */
1854 goto nowperformreturn;
1856 #if defined(ENABLE_SOFTFLOAT)
1859 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1860 REPLACEMENT_POINT_RETURN(cd, iptr);
1861 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
1862 M_LNGMOVE(s1, REG_RESULT_PACKED);
1863 goto nowperformreturn;
1865 #if !defined(ENABLE_SOFTFLOAT)
1866 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1867 REPLACEMENT_POINT_RETURN(cd, iptr);
1868 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1869 M_FLTMOVE(s1, REG_FRESULT);
1870 goto nowperformreturn;
1873 REPLACEMENT_POINT_RETURN(cd, iptr);
1874 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1875 M_DBLMOVE(s1, REG_FRESULT);
1876 goto nowperformreturn;
1880 case ICMD_RETURN: /* ... ==> ... */
1882 REPLACEMENT_POINT_RETURN(cd, iptr);
1888 p = cd->stackframesize;
1890 /* call trace function */
1891 #if !defined(NDEBUG)
1892 emit_verbosecall_exit(jd);
1895 #if defined(ENABLE_THREADS)
1896 /* call lock_monitor_exit */
1897 if (checksync && code_is_synchronized(code)) {
1898 M_ILD(REG_ITMP3, REG_SP, rd->memuse * 8);
1900 /* we need to save the proper return value */
1901 /* we do not care for the long -> doubel convert space here */
1902 switch (iptr->opc) {
1903 #if defined(ENABLE_SOFTFLOAT)
1907 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
1909 #if defined(ENABLE_SOFTFLOAT)
1914 M_IST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1916 #if !defined(ENABLE_SOFTFLOAT)
1918 M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1921 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1926 M_IST(REG_ITMP3, REG_SP, 0 * 4);
1927 M_JSR_IMM(LOCK_monitor_exit);
1929 /* and now restore the proper return value */
1930 switch (iptr->opc) {
1932 #if defined(ENABLE_SOFTFLOAT)
1936 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
1938 #if defined(ENABLE_SOFTFLOAT)
1943 M_ILD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1945 #if !defined(ENABLE_SOFTFLOAT)
1947 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1950 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1958 /* restore return address */
1960 if (!code_is_leafmethod(code)) {
1961 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
1962 may have a displacement overflow. */
1964 M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
1968 /* restore saved registers */
1970 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
1971 p-=8; M_ILD(rd->savintregs[i], REG_SP, p);
1973 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
1974 p-=8; M_ALD(rd->savadrregs[i], REG_SP, p);
1976 #if !defined(ENABLE_SOFTFLOAT)
1977 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
1978 p-=8; M_FLOAD(rd->savfltregs[i], REG_SP, p);
1981 /* deallocate stack */
1982 M_AADD_IMM(cd->stackframesize, REG_SP);
1988 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1989 /* val.a: (classinfo*) superclass */
1991 /* superclass is an interface:
1993 * return (sub != NULL) &&
1994 * (sub->vftbl->interfacetablelength > super->index) &&
1995 * (sub->vftbl->interfacetable[-super->index] != NULL);
1997 * superclass is a class:
1999 * return ((sub != NULL) && (0
2000 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2001 * super->vftbl->diffvall));
2008 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2013 super = iptr->sx.s23.s3.c.cls;
2014 superindex = super->index;
2017 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2018 CODEGEN_CRITICAL_SECTION_NEW;
2020 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
2021 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2023 assert(VAROP(iptr->s1 )->type == TYPE_ADR);
2024 assert(VAROP(iptr->dst)->type == TYPE_INT);
2028 /* if class is not resolved, check which code to call */
2030 if (super == NULL) {
2032 emit_label_beq(cd, BRANCH_LABEL_1);
2034 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
2036 M_IMOV_IMM32(0, REG_ITMP3);
2037 M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
2038 emit_label_beq(cd, BRANCH_LABEL_2);
2041 /* interface instanceof code */
2043 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2044 if (super == NULL) {
2045 codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
2048 emit_label_beq(cd, BRANCH_LABEL_3);
2051 M_ALD(REG_ATMP1, s1, OFFSET(java_object_t, vftbl));
2052 M_ILD(REG_ITMP3, REG_ATMP1, OFFSET(vftbl_t, interfacetablelength));
2053 M_IADD_IMM(-superindex, REG_ITMP3); /* -superindex may be patched patched */
2056 M_ALD(REG_ATMP1, REG_ATMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patch here too! */
2062 emit_label_br(cd, BRANCH_LABEL_4);
2064 emit_label(cd, BRANCH_LABEL_3);
2067 /* class instanceof code */
2069 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2070 if (super == NULL) {
2071 emit_label(cd, BRANCH_LABEL_2);
2073 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
2074 M_AMOV_IMM(0, REG_ATMP2);
2076 M_AMOV_IMM(super->vftbl, REG_ATMP2);
2078 emit_label_beq(cd, BRANCH_LABEL_5);
2081 M_ALD(REG_ATMP1, s1, OFFSET(java_object_t, vftbl));
2083 CODEGEN_CRITICAL_SECTION_START;
2085 M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
2086 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
2087 M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
2089 CODEGEN_CRITICAL_SECTION_END;
2091 M_ISUB(REG_ITMP3, REG_ITMP1);
2092 M_ICMP(REG_ITMP2, REG_ITMP1);
2095 M_TPFW; /* overlaps next instruction */
2099 emit_label(cd, BRANCH_LABEL_5);
2102 if (super == NULL) {
2103 emit_label(cd, BRANCH_LABEL_1);
2104 emit_label(cd, BRANCH_LABEL_4);
2107 emit_store_dst(jd, iptr, d);
2111 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2112 /* val.a: (classinfo*) superclass */
2114 /* superclass is an interface:
2116 * OK if ((sub == NULL) ||
2117 * (sub->vftbl->interfacetablelength > super->index) &&
2118 * (sub->vftbl->interfacetable[-super->index] != NULL));
2120 * superclass is a class:
2122 * OK if ((sub == NULL) || (0
2123 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2124 * super->vftbl->diffvall));
2127 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2128 /* object type cast-check */
2133 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2138 super = iptr->sx.s23.s3.c.cls;
2139 superindex = super->index;
2142 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2143 CODEGEN_CRITICAL_SECTION_NEW;
2145 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
2146 assert(VAROP(iptr->s1)->type == TYPE_ADR);
2148 /* if class is not resolved, check which code to call */
2150 if (super == NULL) {
2152 emit_label_beq(cd, BRANCH_LABEL_1);
2154 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
2156 M_IMOV_IMM32(0, REG_ITMP2);
2157 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
2158 emit_label_beq(cd, BRANCH_LABEL_2);
2161 /* interface checkcast code */
2163 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2164 if (super == NULL) {
2165 codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
2168 emit_label_beq(cd, BRANCH_LABEL_3);
2171 M_ALD(REG_ATMP2, s1, OFFSET(java_object_t, vftbl));
2172 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetablelength));
2174 M_IADD_IMM(-superindex, REG_ITMP3); /* superindex patched */
2176 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2178 M_ALD(REG_ATMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patched*/
2180 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ATMP3, s1);
2183 emit_label_br(cd, BRANCH_LABEL_4);
2185 emit_label(cd, BRANCH_LABEL_3);
2188 /* class checkcast code */
2190 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2191 if (super == NULL) {
2192 emit_label(cd, BRANCH_LABEL_2);
2194 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
2195 M_AMOV_IMM(0, REG_ATMP3);
2197 M_AMOV_IMM(super->vftbl, REG_ATMP3);
2199 emit_label_beq(cd, BRANCH_LABEL_5);
2202 M_ALD(REG_ATMP2, s1, OFFSET(java_object_t, vftbl));
2204 CODEGEN_CRITICAL_SECTION_START;
2206 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval)); /* REG_ITMP3 == sub->vftbl->baseval */
2207 M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
2208 M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
2210 CODEGEN_CRITICAL_SECTION_END;
2212 M_ISUB(REG_ITMP1, REG_ITMP3);
2213 M_ICMP(REG_ITMP2, REG_ITMP3); /* XXX was CMPU */
2215 emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); /* XXX was BRANCH_GT */
2218 emit_label(cd, BRANCH_LABEL_5);
2221 if (super == NULL) {
2222 emit_label(cd, BRANCH_LABEL_1);
2223 emit_label(cd, BRANCH_LABEL_4);
2226 d = codegen_reg_of_dst(jd, iptr, s1);
2228 /* array type cast-check */
2230 s1 = emit_load_s1(jd, iptr, REG_ATMP2);
2232 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2233 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2234 M_AMOV_IMM(0, REG_ATMP1);
2236 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2241 M_JSR_IMM(BUILTIN_arraycheckcast);
2242 M_AADD_IMM(2*4, REG_SP); /* pop arguments off stack */
2244 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2246 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2247 d = codegen_reg_of_dst(jd, iptr, s1);
2249 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2251 emit_store_dst(jd, iptr, d);
2254 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2257 branch_target_t *table;
2259 table = iptr->dst.table;
2261 l = iptr->sx.s23.s2.tablelow;
2262 i = iptr->sx.s23.s3.tablehigh;
2264 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2265 M_INTMOVE(s1, REG_ITMP1);
2266 if (l != 0) M_ISUB_IMM(l, REG_ITMP1);
2271 M_ICMP_IMM(i - 1, REG_ITMP1);
2272 emit_bugt(cd, table[0].block);
2274 /* build jump table top down and use address of lowest entry */
2278 dseg_add_target(cd, table->block);
2282 /* length of dataseg after last dseg_add_target is used by load */
2283 M_AMOV_IMM(0, REG_ATMP2);
2286 M_ISSL_IMM(2, REG_ITMP1); /* index * 4 == offset in table */
2287 M_AADDINT(REG_ITMP1, REG_ATMP2); /* offset in table */
2288 M_AADD_IMM(-(cd->dseglen), REG_ATMP2); /* start of table in dseg */
2289 M_ALD(REG_ATMP1, REG_ATMP2, 0);
2296 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2299 lookup_target_t *lookup;
2301 lookup = iptr->dst.lookup;
2303 i = iptr->sx.s23.s2.lookupcount;
2305 MCODECHECK((i<<2)+8);
2306 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2309 M_ICMP_IMM(lookup->value, s1);
2310 emit_beq(cd, lookup->target.block);
2314 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2319 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2321 /* check for negative sizes and copy sizes to stack if necessary */
2322 MCODECHECK((iptr->s1.argcount << 1) + 64);
2324 for (s1 = iptr->s1.argcount; --s1 >= 0;) {
2325 var = VAR(iptr->sx.s23.s2.args[s1]);
2327 /* Already Preallocated? */
2328 if (!(var->flags & PREALLOC)) {
2329 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2330 M_IST(s2, REG_SP, (s1 + 3) * 4);
2334 /* a0 = dimension count */
2335 M_IMOV_IMM(iptr->s1.argcount, REG_ITMP1);
2336 M_IST(REG_ITMP1, REG_SP, 0*4);
2338 /* a1 = arraydescriptor */
2339 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2340 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2341 M_AMOV_IMM(0, REG_ATMP1);
2343 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2345 M_AST(REG_ATMP1, REG_SP, 1*4);
2347 /* a2 = pointer to dimensions = stack pointer */
2348 M_AMOV(REG_SP, REG_ATMP1);
2349 M_AADD_IMM(3*4, REG_ATMP1);
2350 M_AST(REG_ATMP1, REG_SP, 2*4);
2352 M_JSR_IMM(BUILTIN_multianewarray);
2354 /* check for exception before result assignment */
2355 emit_exception_check(cd, iptr);
2357 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2358 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2359 M_INT2ADRMOVE(REG_RESULT, d);
2360 emit_store_dst(jd, iptr, d);
2366 printf("UNKNOWN OPCODE %d\n", iptr->opc);
2367 exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
2370 /* M_TPF; */ /* nop after each ICMD */
2371 } /* for each instruction */
2373 /* At the end of a basic block we may have to append some nops,
2374 because the patcher stub calling code might be longer than the
2375 actual instruction. So codepatching does not change the
2376 following block unintentionally. */
2378 if (cd->mcodeptr < cd->lastmcodeptr) {
2379 while (cd->mcodeptr < cd->lastmcodeptr) {
2385 } /* if (btpre->flags >= BBREACHED) */
2386 } /* for each basic block */
2388 dseg_createlinenumbertable(cd);
2390 /* generate stubs */
2391 emit_patcher_stubs(jd);
2397 /* codegen_emit_stub_compiler **************************************************
2399 Emits a stub routine which calls the compiler.
2401 *******************************************************************************/
2403 void codegen_emit_stub_compiler(jitdata *jd)
2408 /* get required compiler data */
2413 /* code for the stub */
2415 M_AMOV_IMM(m, REG_ATMP1);
2416 M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
2419 /* codegen_emit_stub_native ****************************************************
2421 Emits a stub routine which calls a native method.
2423 *******************************************************************************/
2425 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2434 /* get required compiler data */
2443 /* calc stackframe size */
2444 cd->stackframesize =
2445 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
2446 sizeof(localref_table) / SIZEOF_VOID_P +
2448 1 + /* functionptr */
2449 4; /* args for codegen_start_native_call */
2451 /* create method header */
2452 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2453 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
2454 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2455 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2456 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2457 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2458 (void) dseg_addlinenumbertablesize(cd);
2459 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2461 /* print call trace */
2462 #if !defined(NDEBUG)
2463 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2464 emit_verbosecall_enter(jd);
2469 M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
2471 /* get function address (this must happen before the stackframeinfo) */
2473 codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
2476 M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
2478 M_AST(REG_ATMP2, REG_SP, 4 * 4);
2480 /* put arguments for codegen_start_native_call onto stack */
2481 /* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
2483 M_AMOV(REG_SP, REG_ATMP1);
2484 M_AST(REG_ATMP1, REG_SP, 0 * 4); /* currentsp */
2486 M_AMOV_IMM(0, REG_ATMP2); /* 0 needs to patched */
2487 dseg_adddata(cd); /* this patches it */
2489 M_AST(REG_ATMP2, REG_SP, 1 * 4); /* pv */
2491 M_JSR_IMM(codegen_start_native_call);
2493 /* remember class argument */
2494 if (m->flags & ACC_STATIC)
2495 M_INT2ADRMOVE(REG_RESULT, REG_ATMP3);
2497 /* load function pointer */
2498 M_ALD(REG_ATMP2, REG_SP, 4 * 4);
2500 /* copy arguments into stackframe */
2501 for (i = md->paramcount -1, j = i + skipparams; i >= 0; --i, --j) {
2502 t = md->paramtypes[i].type;
2503 /* all arguments via stack */
2504 assert(md->params[i].inmemory);
2506 s1 = md->params[i].regoff + cd->stackframesize * 4 + 4;
2507 s2 = nmd->params[j].regoff;
2509 /* simply copy argument stack */
2510 M_ILD(REG_ITMP1, REG_SP, s1);
2511 M_IST(REG_ITMP1, REG_SP, s2);
2512 if (IS_2_WORD_TYPE(t)) {
2513 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
2514 M_IST(REG_ITMP1, REG_SP, s2 + 4);
2518 /* for static function class as second arg */
2519 if (m->flags & ACC_STATIC)
2520 M_AST(REG_ATMP3, REG_SP, 1 * 4);
2522 /* env ist first argument */
2523 M_AMOV_IMM(_Jv_env, REG_ATMP1);
2524 M_AST(REG_ATMP1, REG_SP, 0 * 4);
2526 /* call the native function */
2529 /* save return value */
2530 switch (md->returntype.type) {
2531 case TYPE_VOID: break;
2533 /* natives return float arguments in %d0, %d1, cacao expects them in %fp0 */
2536 M_IST(REG_D1, REG_SP, 2 * 4);
2542 M_IST(REG_D0, REG_SP, 2 * 4);
2548 /* print call trace */
2549 #if ! defined(NDEBUG)
2550 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2551 emit_verbosecall_exit(jd);
2554 /* remove native stackframe info */
2555 /* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
2557 M_AMOV(REG_SP, REG_ATMP1);
2558 M_AST(REG_ATMP1, REG_SP, 0 * 4); /* currentsp */
2560 M_AMOV_IMM(0, REG_ATMP2); /* 0 needs to patched */
2561 dseg_adddata(cd); /* this patches it */
2563 M_AST(REG_ATMP2, REG_SP, 1 * 4); /* pv */
2565 M_JSR_IMM(codegen_finish_native_call);
2567 M_INT2ADRMOVE(REG_RESULT, REG_ATMP1);
2568 /* restore return value */
2569 switch (md->returntype.type) {
2570 case TYPE_VOID: break;
2574 M_ILD(REG_D1, REG_SP, 2 * 4);
2579 M_ILD(REG_D0, REG_SP, 2 * 4);
2584 #if !defined(ENABLE_SOFTFLOAT)
2585 /* additionally load values into floating points registers
2586 * as cacao jit code expects them there */
2587 switch (md->returntype.type) {
2589 M_FLD(REG_D0, REG_SP, 2 * 4);
2592 M_DLD(REG_D0, REG_SP, 2 * 4);
2596 /* restore saved registers */
2598 M_AADD_IMM(cd->stackframesize*4, REG_SP);
2599 /* check for exception */
2604 /* handle exception, REG_ATMP1 already contains exception object, REG_ATMP2 holds address */
2606 M_ALD(REG_ATMP2_XPC, REG_SP, 0); /* take return address as faulting instruction */
2607 M_AADD_IMM(-2, REG_ATMP2_XPC); /* which is off by 2 */
2608 M_JMP_IMM(asm_handle_nat_exception);
2610 /* should never be reached from within jit code*/
2613 /* generate patcher stub call code */
2614 emit_patcher_stubs(jd);
2619 * These are local overrides for various environment variables in Emacs.
2620 * Please do not remove this and leave it at the end of the file, where
2621 * Emacs will automagically detect them.
2622 * ---------------------------------------------------------------------
2625 * indent-tabs-mode: t
2629 * vim:noexpandtab:sw=4:ts=4: