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: We still need it for exception handling in assembler. */
149 if (code_is_leafmethod(code))
150 (void) dseg_add_unique_s4(cd, 1);
152 (void) dseg_add_unique_s4(cd, 0);
154 /* XXX we use the IntSave a split field for the adr now */
155 (void) dseg_add_unique_s4(cd, (ADR_SAV_CNT - rd->savadrreguse) << 16 | (INT_SAV_CNT - rd->savintreguse)); /* IntSave */
156 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
158 dseg_addlinenumbertablesize(cd);
160 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
162 /* create exception table */
163 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
164 dseg_add_target(cd, ex->start);
165 dseg_add_target(cd, ex->end);
166 dseg_add_target(cd, ex->handler);
167 (void) dseg_add_unique_address(cd, ex->catchtype.any);
170 #if defined(ENABLE_PROFILING)
175 emit_verbosecall_enter(jd);
177 /* create stack frame */
178 M_AADD_IMM(-(cd->stackframesize), REG_SP);
180 /* save used callee saved registers */
181 p = cd->stackframesize;
182 for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
183 p-=8; M_IST(rd->savintregs[i], REG_SP, p);
185 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
186 p-=8; M_AST(rd->savadrregs[i], REG_SP, p);
188 #if !defined(ENABLE_SOFTFLOAT)
189 for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
190 p-=8; M_FSTORE(rd->savfltregs[i], REG_SP, p);
193 assert(FLT_SAV_CNT == 0);
194 assert(rd->savfltreguse == 0);
196 /* take arguments out of stack frame */
198 for (p = 0, l = 0; p < md->paramcount; p++) {
199 t = md->paramtypes[p].type;
200 varindex = jd->local_map[l * 5 + t];
203 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
206 if (varindex == UNUSED)
211 s1 = md->params[p].regoff;
212 assert(md->params[p].inmemory); /* all args are on stack */
215 #if defined(ENABLE_SOFTFLOAT)
221 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
222 if (IS_2_WORD_TYPE(t)) {
223 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
225 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
227 } else { /* stack arg -> spilled */
228 M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4);
229 M_IST(REG_ITMP1, REG_SP, var->vv.regoff);
230 if (IS_2_WORD_TYPE(t)) {
231 M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4 + 4);
232 M_IST(REG_ITMP1, REG_SP, var->vv.regoff + 4);
236 #if !defined(ENABLE_SOFTFLOAT)
239 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
240 if (IS_2_WORD_TYPE(t)) {
241 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
243 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
245 } else { /* stack-arg -> spilled */
246 if (IS_2_WORD_TYPE(t)) {
247 M_DLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
248 M_DST(REG_FTMP1, REG_SP, var->vv.regoff);
250 M_FLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
251 M_FST(REG_FTMP1, REG_SP, var->vv.regoff);
255 #endif /* SOFTFLOAT */
257 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
258 M_ALD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
259 } else { /* stack-arg -> spilled */
260 M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + s1 + 4);
261 M_AST(REG_ATMP1, REG_SP, var->vv.regoff);
266 } /* end for argument out of stack*/
268 #if defined(ENABLE_THREADS)
269 /* call lock_monitor_enter function */
270 if (checksync && code_is_synchronized(code)) {
271 if (m->flags & ACC_STATIC) {
272 M_AMOV_IMM((&m->class->object.header), REG_ATMP1);
274 /* for non-static case the first arg is the object */
275 M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + 4);
278 M_TRAP(M68K_EXCEPTION_HARDWARE_NULLPOINTER);
281 M_AST(REG_ATMP1, REG_SP, rd->memuse * 8);
282 M_AST(REG_ATMP1, REG_SP, 0 * 4);
283 M_JSR_IMM(LOCK_monitor_enter);
289 /* create replacement points */
290 REPLACEMENT_POINTS_INIT(cd, jd);
292 /* foreach basic block */
293 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
295 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
297 if (bptr->flags >= BBREACHED) {
299 /* branch resolving */
300 codegen_resolve_branchrefs(cd, bptr);
302 /* handle replacement points */
303 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
305 #if defined(ENABLE_PROFILING)
308 /* FIXME there are still some constrcuts to copy in here */
310 #if defined(ENABLE_LSRA)
314 /* copy interface registers to their destination */
320 var = VAR(bptr->invars[len]);
321 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
322 d = codegen_reg_of_var(0, var, REG_ATMP1_XPTR);
323 M_ADRMOVE(REG_ATMP1_XPTR, d);
324 emit_store(jd, NULL, var, d);
327 assert((var->flags & INOUT));
331 /* walk through all instructions */
335 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
336 if (iptr->line != currentline) {
337 dseg_addlinenumber(cd, iptr->line);
338 currentline = iptr->line;
341 MCODECHECK(1024); /* 1kB should be enough */
344 case ICMD_NOP: /* ... ==> ... */
345 case ICMD_POP: /* ..., value ==> ... */
346 case ICMD_POP2: /* ..., value, value ==> ... */
349 case ICMD_INLINE_START:
351 REPLACEMENT_POINT_INLINE_START(cd, iptr);
354 case ICMD_INLINE_BODY:
356 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
357 dseg_addlinenumber_inline_start(cd, iptr);
358 dseg_addlinenumber(cd, iptr->line);
361 case ICMD_INLINE_END:
363 dseg_addlinenumber_inline_end(cd, iptr);
364 dseg_addlinenumber(cd, iptr->line);
367 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
369 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
370 assert(VAROP(iptr->s1)->type == TYPE_ADR);
371 emit_nullpointer_check(cd, iptr, s1);
375 /* CONST **************************************************************/
376 case ICMD_ICONST: /* ... ==> ..., constant */
377 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
378 M_IMOV_IMM(iptr->sx.val.i, d);
379 emit_store_dst(jd, iptr, d);
382 case ICMD_LCONST: /* ... ==> ..., constant */
384 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
385 LCONST(iptr->sx.val.l, d);
386 emit_store_dst(jd, iptr, d);
389 case ICMD_FCONST: /* ... ==> ..., constant */
391 #if defined(ENABLE_SOFTFLOAT)
392 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
393 M_IMOV_IMM(iptr->sx.val.i, d);
394 emit_store_dst(jd, iptr, d);
396 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
397 FCONST(iptr->sx.val.i, d);
398 emit_store_dst(jd, iptr, d);
402 case ICMD_DCONST: /* ... ==> ..., constant */
404 #if defined(ENABLE_SOFTFLOAT)
405 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
406 LCONST(iptr->sx.val.l, d);
407 emit_store_dst(jd, iptr, d);
409 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
410 disp = dseg_add_double(cd, iptr->sx.val.d);
411 M_AMOV_IMM(0, REG_ATMP1);
413 M_DLD(d, REG_ATMP1, disp);
414 emit_store_dst(jd, iptr, d);
419 /* some long operations *********************************************/
420 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
421 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
422 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
423 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
424 M_INTMOVE(s2, REG_ITMP1);
425 M_IADD(s1, REG_ITMP1); /* low word */
426 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
427 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
428 M_INTMOVE(s2, REG_ITMP2);
429 M_IADDX(s1, REG_ITMP2); /* high word */
430 emit_store_dst(jd, iptr, d);
433 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
434 /* sx.val.l = constant */
435 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
436 s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
437 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
439 M_IMOV_IMM(iptr->sx.val.l >> 32, REG_ITMP3);
441 s3 = iptr->sx.val.l & 0xffffffff;
442 M_INTMOVE(s1, REG_ITMP1);
443 M_IADD_IMM(s3, REG_ITMP1); /* lower word in REG_ITMP1 now */
445 M_IADDX(REG_ITMP3, REG_ITMP2); /* high word in REG_ITMP2 now */
446 M_LNGMOVE(REG_ITMP12_PACKED, d);
447 emit_store_dst(jd, iptr, d);
450 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
451 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
452 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
453 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
454 M_INTMOVE(s1, REG_ITMP1);
455 M_ISUB(s2, REG_ITMP1); /* low word */
456 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
457 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
458 M_INTMOVE(s1, REG_ITMP2);
459 M_ISUBX(s2, REG_ITMP2); /* high word */
460 emit_store_dst(jd, iptr, d);
463 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
464 /* sx.val.l = constant */
465 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
466 s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
467 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
469 M_IMOV_IMM( (-iptr->sx.val.l) >> 32, REG_ITMP3);
471 s3 = (-iptr->sx.val.l) & 0xffffffff;
472 M_INTMOVE(s1, REG_ITMP1);
473 M_IADD_IMM(s3, REG_ITMP1); /* lower word in REG_ITMP1 now */
475 M_IADDX(REG_ITMP3, REG_ITMP2); /* high word in REG_ITMP2 now */
476 M_LNGMOVE(REG_ITMP12_PACKED, d);
477 emit_store_dst(jd, iptr, d);
480 case ICMD_LNEG: /* ..., value ==> ..., - value */
481 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
482 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
483 M_LNGMOVE(s1, REG_ITMP12_PACKED);
484 M_INEG(GET_LOW_REG(REG_ITMP12_PACKED));
485 M_INEGX(GET_HIGH_REG(REG_ITMP12_PACKED));
486 M_LNGMOVE(REG_ITMP12_PACKED, d);
487 emit_store_dst(jd, iptr, d);
490 /* integer operations ************************************************/
491 case ICMD_INEG: /* ..., value ==> ..., - value */
493 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
494 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
495 M_INTMOVE(s1, REG_ITMP1);
497 M_INTMOVE(REG_ITMP1, d);
498 emit_store_dst(jd, iptr, d);
501 case ICMD_I2L: /* ..., value ==> ..., value */
503 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
504 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
505 M_IMOV(s1, GET_LOW_REG(d)); /* sets negativ bit */
507 M_ISET(GET_HIGH_REG(d));
509 M_ICLR(GET_HIGH_REG(d));
511 emit_store_dst(jd, iptr, d);
514 case ICMD_L2I: /* ..., value ==> ..., value */
516 s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
517 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
519 emit_store_dst(jd, iptr, d);
521 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
523 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
524 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
526 emit_store_dst(jd, iptr, d);
529 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
531 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
532 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
534 emit_store_dst(jd, iptr, d);
537 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
539 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
540 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
542 emit_store_dst(jd, iptr, d);
547 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
549 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
550 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
551 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
552 M_INTMOVE(s2, REG_ITMP2);
553 M_IADD(s1, REG_ITMP2);
554 M_INTMOVE(REG_ITMP2, d);
555 emit_store_dst(jd, iptr, d);
558 /* s1.localindex = variable, sx.val.i = constant*/
563 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
564 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
565 M_INTMOVE(s1, REG_ITMP1);
566 M_IADD_IMM(iptr->sx.val.i, REG_ITMP1);
567 M_INTMOVE(REG_ITMP1, d);
568 emit_store_dst(jd, iptr, d);
571 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
573 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
574 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
575 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
576 M_INTMOVE(s1, REG_ITMP1);
577 M_ISUB(s2, REG_ITMP1);
578 M_INTMOVE(REG_ITMP1, d);
579 emit_store_dst(jd, iptr, d);
582 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
583 /* sx.val.i = constant */
585 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
586 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
587 M_INTMOVE(s1, REG_ITMP1);
588 M_IADD_IMM(-iptr->sx.val.i, REG_ITMP1);
589 M_INTMOVE(REG_ITMP1, d);
590 emit_store_dst(jd, iptr, d);
593 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
594 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
595 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
596 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
597 emit_arithmetic_check(cd, iptr, s2);
598 M_INTMOVE(s1, REG_ITMP1);
599 M_IDIV(s2, REG_ITMP1);
600 M_INTMOVE(REG_ITMP1, d);
601 emit_store_dst(jd, iptr, d);
604 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
605 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
606 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
607 M_INTMOVE(s1, REG_ITMP1);
611 M_IADD_IMM((1 << iptr->sx.val.i) - 1, REG_ITMP1);
613 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
614 M_ISSR(REG_ITMP2, REG_ITMP1);
615 M_INTMOVE(REG_ITMP1, d);
616 emit_store_dst(jd, iptr, d);
619 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
620 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
621 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
622 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
623 emit_arithmetic_check(cd, iptr, s2);
625 M_ICMP_IMM(0x80000000, s1);
630 M_TPFL; /* hides the next instruction */
631 M_IREM(s2, s1, REG_ITMP3);
633 M_INTMOVE(REG_ITMP3, d);
635 emit_store_dst(jd, iptr, d);
638 case ICMD_IREMPOW2: /* ..., value ==> ..., value << constant */
639 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
642 M_IMOV(s1, REG_ITMP1);
646 M_IAND_IMM(iptr->sx.val.i, d);
648 M_BGE(2 + 2 + 6 + 2);
649 M_IMOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */
651 M_IAND_IMM(iptr->sx.val.i, d); /* use 32-bit for jump offset */
654 emit_store_dst(jd, iptr, d);
658 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
659 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
661 bte = iptr->sx.s23.s3.bte;
664 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
665 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
666 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
667 /* XXX could be optimized */
668 emit_arithmetic_check(cd, iptr, REG_ITMP3);
670 M_LST(s2, REG_SP, 2 * 4);
671 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
672 M_LST(s1, REG_SP, 0 * 4);
676 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
677 M_LNGMOVE(REG_RESULT_PACKED, d);
678 emit_store_dst(jd, iptr, d);
681 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
683 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
684 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
685 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
686 M_INTMOVE(s2, REG_ITMP2);
687 M_IMUL(s1, REG_ITMP2);
688 M_INTMOVE(REG_ITMP2, d);
689 emit_store_dst(jd, iptr, d);
692 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
693 /* sx.val.i = constant */
694 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
695 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
696 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
697 M_IMUL(s1, REG_ITMP2);
698 M_INTMOVE(REG_ITMP2, d);
699 emit_store_dst(jd, iptr, d);
702 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
704 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
705 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
706 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
707 M_INTMOVE(s1, REG_ITMP1);
708 M_INTMOVE(s2, REG_ITMP2);
709 M_IAND_IMM(0x1f, REG_ITMP2);
710 M_ISSL(REG_ITMP2, REG_ITMP1);
711 M_INTMOVE(REG_ITMP1, d);
712 emit_store_dst(jd, iptr, d);
715 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
716 /* sx.val.i = constant */
718 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
720 if (iptr->sx.val.i & 0x1f) {
721 M_INTMOVE(s1, REG_ITMP1)
722 if ((iptr->sx.val.i & 0x1f) <= 7) {
723 M_ISSL_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
725 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
726 M_ISSL(REG_ITMP2, REG_ITMP1);
728 M_INTMOVE(REG_ITMP1, d);
732 emit_store_dst(jd, iptr, d);
735 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
737 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
738 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
739 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
740 M_INTMOVE(s1, REG_ITMP1);
741 M_INTMOVE(s2, REG_ITMP2);
742 M_IAND_IMM(0x1f, REG_ITMP2);
743 M_ISSR(REG_ITMP2, REG_ITMP1);
744 M_INTMOVE(REG_ITMP1, d);
745 emit_store_dst(jd, iptr, d);
748 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
749 /* sx.val.i = constant */
751 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
752 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
753 if (iptr->sx.val.i & 0x1f) {
754 M_INTMOVE(s1, REG_ITMP1)
755 if ((iptr->sx.val.i & 0x1f) <= 7) {
756 M_ISSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
758 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
759 M_ISSR(REG_ITMP2, REG_ITMP1);
761 M_INTMOVE(REG_ITMP1, d);
765 emit_store_dst(jd, iptr, d);
768 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
770 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
771 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
772 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
773 M_INTMOVE(s1, REG_ITMP1);
774 M_INTMOVE(s2, REG_ITMP2);
775 M_IAND_IMM(0x1f, REG_ITMP2);
776 M_IUSR(REG_ITMP2, REG_ITMP1);
777 M_INTMOVE(REG_ITMP1, d);
778 emit_store_dst(jd, iptr, d);
781 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
782 /* sx.val.i = constant */
783 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
784 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
785 if (iptr->sx.val.i & 0x1f) {
786 M_INTMOVE(s1, REG_ITMP1)
787 if ((iptr->sx.val.i & 0x1f) <= 7) {
788 M_IUSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
790 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
791 M_IUSR(REG_ITMP2, REG_ITMP1);
793 M_INTMOVE(REG_ITMP1, d);
797 emit_store_dst(jd, iptr, d);
800 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
802 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
803 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
804 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
805 M_INTMOVE(s2, REG_ITMP2);
806 M_IAND(s1, REG_ITMP2);
807 M_INTMOVE(REG_ITMP2, d);
808 emit_store_dst(jd, iptr, d);
811 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
812 /* sx.val.i = constant */
814 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
815 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
816 M_INTMOVE(s1, REG_ITMP1);
817 M_IAND_IMM(iptr->sx.val.i, REG_ITMP1);
818 M_INTMOVE(REG_ITMP1, d);
819 emit_store_dst(jd, iptr, d);
822 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
823 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
824 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
825 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
826 M_INTMOVE(s2, REG_ITMP2);
827 M_IOR(s1, REG_ITMP2);
828 M_INTMOVE(REG_ITMP2, d);
829 emit_store_dst(jd, iptr, d);
832 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
833 /* sx.val.i = constant */
834 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
835 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
836 M_INTMOVE(s1, REG_ITMP1);
837 M_IOR_IMM(iptr->sx.val.i, REG_ITMP1);
838 M_INTMOVE(REG_ITMP1, d);
839 emit_store_dst(jd, iptr, d);
842 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 | val2 */
843 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
844 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
845 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
846 M_INTMOVE(s2, REG_ITMP2);
847 M_IXOR(s1, REG_ITMP2);
848 M_INTMOVE(REG_ITMP2, d);
849 emit_store_dst(jd, iptr, d);
852 case ICMD_IXORCONST: /* ..., value ==> ..., value | constant */
853 /* sx.val.i = constant */
854 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
855 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
856 M_INTMOVE(s1, REG_ITMP1);
857 M_IXOR_IMM(iptr->sx.val.i, REG_ITMP1);
858 M_INTMOVE(REG_ITMP1, d);
859 emit_store_dst(jd, iptr, d);
862 /* floating point operations ******************************************/
863 #if !defined(ENABLE_SOFTFLOAT)
864 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
866 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
867 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
868 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
871 M_BFUN(14); /* result is -1, branch to end */
872 M_BFLT(10); /* result is -1, branch to end */
874 M_BFEQ(4) /* result is 0, branch to end */
876 emit_store_dst(jd, iptr, d);
879 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
881 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
882 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
883 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
886 M_BFUN(16); /* result is +1, branch to end */
887 M_BFGT(14); /* result is +1, branch to end */
889 M_BFEQ(8) /* result is 0, branch to end */
891 emit_store_dst(jd, iptr, d);
894 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
895 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
896 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
897 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
898 M_FLTMOVE(s2, REG_FTMP2);
899 M_FMUL(s1, REG_FTMP2);
900 M_FLTMOVE(REG_FTMP2, d);
901 emit_store_dst(jd, iptr, d);
904 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
905 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
906 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
907 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
908 M_DBLMOVE(s2, REG_FTMP2);
909 M_DMUL(s1, REG_FTMP2);
910 M_DBLMOVE(REG_FTMP2, d);
911 emit_store_dst(jd, iptr, d);
914 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
915 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
916 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
917 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
918 M_FLTMOVE(s1, REG_FTMP1);
919 M_FDIV(s2, REG_FTMP1);
920 M_FLTMOVE(REG_FTMP1, d);
921 emit_store_dst(jd, iptr, d);
924 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
925 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
926 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
927 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
928 M_DBLMOVE(s1, REG_FTMP1);
929 M_DDIV(s2, REG_FTMP1);
930 M_DBLMOVE(REG_FTMP1, d);
931 emit_store_dst(jd, iptr, d);
934 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
935 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
936 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
937 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
938 M_FLTMOVE(s2, REG_FTMP2);
939 M_FADD(s1, REG_FTMP2);
940 M_FLTMOVE(REG_FTMP2, d);
941 emit_store_dst(jd, iptr, d);
944 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
945 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
946 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
947 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
948 M_DBLMOVE(s2, REG_FTMP2);
949 M_DADD(s1, REG_FTMP2);
950 M_DBLMOVE(REG_FTMP2, d);
951 emit_store_dst(jd, iptr, d);
954 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
955 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
956 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
957 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
958 M_FLTMOVE(s1, REG_FTMP1);
959 M_FSUB(s2, REG_FTMP1);
960 M_FLTMOVE(REG_FTMP1, d);
961 emit_store_dst(jd, iptr, d);
964 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
965 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
966 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
967 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
968 M_DBLMOVE(s1, REG_FTMP1);
969 M_DSUB(s2, REG_FTMP1);
970 M_DBLMOVE(REG_FTMP1, d);
971 emit_store_dst(jd, iptr, d);
974 case ICMD_F2D: /* ..., value ==> ..., (double) value */
975 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
976 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
978 emit_store_dst(jd, iptr, d);
981 case ICMD_D2F: /* ..., value ==> ..., (float) value */
982 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
983 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
985 emit_store_dst(jd, iptr, d);
988 case ICMD_FNEG: /* ..., value ==> ..., - value */
989 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
990 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
992 emit_store_dst(jd, iptr, d);
995 case ICMD_DNEG: /* ..., value ==> ..., - value */
996 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
997 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
999 emit_store_dst(jd, iptr, d);
1004 /* load/store/copy/move operations ************************************/
1006 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
1007 case ICMD_ALOAD: /* s1 = local variable */
1011 case ICMD_ISTORE: /* ..., value ==> ... */
1018 emit_copy(jd, iptr);
1023 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
1024 emit_copy(jd, iptr);
1028 case ICMD_ACONST: /* ... ==> ..., constant */
1029 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1031 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1032 constant_classref *cr = iptr->sx.val.c.ref;;
1033 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
1036 M_AMOV_IMM(iptr->sx.val.anyptr, d);
1038 emit_store_dst(jd, iptr, d);
1040 /* BRANCH *************************************************************/
1042 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1044 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1045 M_ADRMOVE(s1, REG_ATMP1_XPTR);
1047 #ifdef ENABLE_VERIFIER
1048 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1049 unresolved_class *uc = iptr->sx.s23.s2.uc;
1051 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1053 #endif /* ENABLE_VERIFIER */
1054 M_JSR_PCREL(2); /* get current PC */
1057 M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
1062 case ICMD_GOTO: /* ... ==> ... */
1063 case ICMD_RET: /* ... ==> ... */
1065 emit_br(cd, iptr->dst.block);
1069 case ICMD_JSR: /* ... ==> ... */
1071 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1077 case ICMD_IFNULL: /* ..., value ==> ... */
1078 case ICMD_IFNONNULL:
1079 assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
1080 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1082 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
1090 case ICMD_IFEQ: /* ..., value ==> ... */
1092 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1093 assert (VAROP(iptr->s1)->type == TYPE_INT);
1094 M_ICMP_IMM(iptr->sx.val.i, s1);
1095 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1098 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1099 case ICMD_IF_ICMPNE:
1100 case ICMD_IF_ICMPLT:
1101 case ICMD_IF_ICMPGT:
1102 case ICMD_IF_ICMPLE:
1103 case ICMD_IF_ICMPGE:
1105 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1106 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1108 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
1111 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
1112 case ICMD_IF_ACMPNE:
1114 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1115 s2 = emit_load_s2(jd, iptr, REG_ATMP2);
1117 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
1121 /* MEMORY *************************************************************/
1123 case ICMD_GETSTATIC: /* ... ==> ..., value */
1125 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1126 uf = iptr->sx.s23.s3.uf;
1127 fieldtype = uf->fieldref->parseddesc.fd->type;
1130 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1133 fi = iptr->sx.s23.s3.fmiref->p.field;
1134 fieldtype = fi->type;
1135 disp = (intptr_t) fi->value;
1137 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1138 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
1143 M_AMOV_IMM(disp, REG_ATMP1);
1144 switch (fieldtype) {
1145 #if defined(ENABLE_SOFTFLOAT)
1149 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1150 M_ILD(d, REG_ATMP1, 0);
1153 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1154 M_ALD(d, REG_ATMP1, 0);
1156 #if defined(ENABLE_SOFTFLOAT)
1160 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1161 M_LLD(d, REG_ATMP1, 0);
1163 #if !defined(ENABLE_SOFTFLOAT)
1165 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1166 M_FLD(d, REG_ATMP1, 0);
1169 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1170 M_DLD(d, REG_ATMP1, 0);
1174 emit_store_dst(jd, iptr, d);
1177 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1179 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1180 uf = iptr->sx.s23.s3.uf;
1181 fieldtype = uf->fieldref->parseddesc.fd->type;
1184 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1187 fi = iptr->sx.s23.s3.fmiref->p.field;
1188 fieldtype = fi->type;
1189 disp = (intptr_t) fi->value;
1191 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1192 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
1196 M_AMOV_IMM(disp, REG_ATMP1);
1197 switch (fieldtype) {
1198 #if defined(ENABLE_SOFTFLOAT)
1202 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1203 M_IST(s1, REG_ATMP1, 0);
1205 #if defined(ENABLE_SOFTFLOAT)
1209 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1210 M_LST(s1, REG_ATMP1, 0);
1213 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1214 M_AST(s1, REG_ATMP1, 0);
1216 #if !defined(ENABLE_SOFTFLOAT)
1218 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1219 M_FST(s1, REG_ATMP1, 0);
1222 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1223 M_DST(s1, REG_ATMP1, 0);
1230 case ICMD_GETFIELD: /* ... ==> ..., value */
1232 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1234 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1235 uf = iptr->sx.s23.s3.uf;
1236 fieldtype = uf->fieldref->parseddesc.fd->type;
1239 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1242 fi = iptr->sx.s23.s3.fmiref->p.field;
1243 fieldtype = fi->type;
1247 /* implicit null-pointer check */
1248 switch (fieldtype) {
1249 #if defined(ENABLE_SOFTFLOAT)
1253 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1256 #if defined(ENABLE_SOFTFLOAT)
1260 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1264 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1267 #if !defined(ENABLE_SOFTFLOAT)
1269 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1273 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1278 emit_store_dst(jd, iptr, d);
1281 case ICMD_PUTFIELD: /* ..., value ==> ... */
1283 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1285 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1286 uf = iptr->sx.s23.s3.uf;
1287 fieldtype = uf->fieldref->parseddesc.fd->type;
1291 fi = iptr->sx.s23.s3.fmiref->p.field;
1292 fieldtype = fi->type;
1296 if (IS_INT_LNG_TYPE(fieldtype)) {
1297 if (IS_2_WORD_TYPE(fieldtype)) {
1298 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1300 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1303 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1306 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1307 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1309 /* implicit null-pointer check */
1310 switch (fieldtype) {
1311 #if defined(ENABLE_SOFTFLOAT)
1315 M_IST(s2, s1, disp);
1318 #if defined(ENABLE_SOFTFLOAT)
1322 M_LST(s2, s1, disp);
1325 M_AST(s2, s1, disp);
1327 #if !defined(ENABLE_SOFTFLOAT)
1329 M_FST(s2, s1, disp);
1332 M_DST(s2, s1, disp);
1338 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1340 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1341 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1342 /* implicit null-pointer check */
1343 M_ILD(d, s1, OFFSET(java_array_t, size));
1344 emit_store_dst(jd, iptr, d);
1347 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1349 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1350 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1351 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1352 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1353 M_INTMOVE(s2, REG_ITMP2);
1354 M_IADD_IMM(OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1355 M_ADRMOVE(s1, REG_ATMP1);
1356 M_AADDINT(REG_ITMP2, REG_ATMP1);
1357 /* implicit null-pointer check */
1358 M_LBZX(REG_ATMP1, d);
1360 emit_store_dst(jd, iptr, d);
1363 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1365 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1366 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1367 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1368 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1369 M_INTMOVE(s2, REG_ITMP2);
1370 M_ISSL_IMM(1, REG_ITMP2);
1371 M_IADD_IMM(OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1372 M_ADRMOVE(s1, REG_ATMP1);
1373 M_AADDINT(REG_ITMP2, REG_ATMP1);
1374 /* implicit null-pointer check */
1375 M_LHZX(REG_ATMP1, d);
1377 emit_store_dst(jd, iptr, d);
1380 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1382 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1383 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1384 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1385 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1386 M_INTMOVE(s2, REG_ITMP2);
1387 M_ISSL_IMM(1, REG_ITMP2);
1388 M_IADD_IMM(OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1389 M_ADRMOVE(s1, REG_ATMP1);
1390 M_AADDINT(REG_ITMP2, REG_ATMP1);
1392 /* implicit null-pointer check */
1393 M_LHZX(REG_ATMP1, d);
1395 emit_store_dst(jd, iptr, d);
1398 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1400 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1401 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1402 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1403 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1404 M_INTMOVE(s2, REG_ITMP2);
1405 M_ISSL_IMM(2, REG_ITMP2);
1406 M_IADD_IMM(OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1407 M_ADRMOVE(s1, REG_ATMP1);
1408 M_AADDINT(REG_ITMP2, REG_ATMP1);
1409 /* implicit null-pointer check */
1410 M_LWZX(REG_ATMP1, d);
1411 emit_store_dst(jd, iptr, d);
1414 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1415 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1416 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1417 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1418 /* implicit null-pointer check */
1419 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1420 M_INTMOVE(s2, REG_ITMP1);
1421 M_ISSL_IMM(3, REG_ITMP1);
1422 M_IADD_IMM(OFFSET(java_longarray_t, data[0]), REG_ITMP1);
1423 M_ADRMOVE(s1, REG_ATMP1);
1424 M_AADDINT(REG_ITMP1, REG_ATMP1);
1425 /* implicit null-pointer check */
1426 M_LLD(d, REG_ATMP1, 0);
1427 emit_store_dst(jd, iptr, d);
1430 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1431 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1432 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1433 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1434 M_INTMOVE(s2, REG_ITMP2);
1435 M_ISSL_IMM(2, REG_ITMP2);
1436 M_IADD_IMM(OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1437 M_ADRMOVE(s1, REG_ATMP1);
1438 M_AADDINT(REG_ITMP2, REG_ATMP1);
1439 /* implicit null-pointer check */
1440 #if !defined(ENABLE_SOFTFLOAT)
1441 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1442 M_FLD(d, REG_ATMP1, 0);
1444 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1445 M_LWZX(REG_ATMP1, d);
1447 emit_store_dst(jd, iptr, d);
1450 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1451 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1452 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1453 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1454 M_INTMOVE(s2, REG_ITMP2);
1455 M_ISSL_IMM(3, REG_ITMP2);
1456 M_IADD_IMM(OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1457 M_ADRMOVE(s1, REG_ATMP1);
1458 M_AADDINT(REG_ITMP2, REG_ATMP1);
1459 /* implicit null-pointer check */
1460 #if !defined(ENABLE_SOFTFLOAT)
1461 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1462 M_DLD(d, REG_ATMP1, 0);
1464 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1465 M_LLD(d, REG_ATMP1, 0);
1467 emit_store_dst(jd, iptr, d);
1470 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1471 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1472 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1473 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1474 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1475 M_INTMOVE(s2, REG_ITMP2);
1476 M_ISSL_IMM(2, REG_ITMP2);
1477 M_IADD_IMM(OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
1478 M_ADRMOVE(s1, REG_ATMP1);
1479 M_AADDINT(REG_ITMP2, REG_ATMP1);
1481 /* implicit null-pointer check */
1482 M_LAX(REG_ATMP1, d);
1483 emit_store_dst(jd, iptr, d);
1487 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1488 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1489 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1490 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1491 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1492 M_INTMOVE(s2, REG_ITMP2);
1493 M_IADD_IMM(OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1494 M_ADRMOVE(s1, REG_ATMP1);
1495 M_AADDINT(REG_ITMP2, REG_ATMP1);
1496 /* implicit null-pointer check */
1497 M_STBX(REG_ATMP1, s3);
1500 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1501 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1502 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1503 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1504 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1505 M_INTMOVE(s2, REG_ITMP2);
1506 M_ISSL_IMM(1, REG_ITMP2);
1507 M_IADD_IMM(OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1508 M_ADRMOVE(s1, REG_ATMP1);
1509 M_AADDINT(REG_ITMP2, REG_ATMP1);
1510 /* implicit null-pointer check */
1511 M_STHX(REG_ATMP1, s3);
1514 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1515 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1516 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1517 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1518 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1519 M_INTMOVE(s2, REG_ITMP2);
1520 M_ISSL_IMM(1, REG_ITMP2);
1521 M_IADD_IMM(OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1522 M_ADRMOVE(s1, REG_ATMP1);
1523 M_AADDINT(REG_ITMP2, REG_ATMP1);
1524 /* implicit null-pointer check */
1525 M_STHX(REG_ATMP1, s3);
1528 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1529 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1530 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1531 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1532 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1533 M_INTMOVE(s2, REG_ITMP2);
1534 M_ISSL_IMM(2, REG_ITMP2);
1535 M_IADD_IMM(OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1536 M_ADRMOVE(s1, REG_ATMP1);
1537 M_AADDINT(REG_ITMP2, REG_ATMP1);
1538 /* implicit null-pointer check */
1539 M_STWX(REG_ATMP1, s3);
1542 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1543 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1544 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1545 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1547 M_INTMOVE(s2, REG_ITMP1);
1548 M_ISSL_IMM(3, REG_ITMP1);
1549 M_IADD_IMM(OFFSET(java_longarray_t, data[0]), REG_ITMP1);
1550 M_ADRMOVE(s1, REG_ATMP1);
1551 M_AADDINT(REG_ITMP1, REG_ATMP1);
1552 /* implicit null-pointer check */
1553 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1554 M_LST(s3, REG_ATMP1, 0);
1557 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1558 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1559 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1560 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1561 M_INTMOVE(s2, REG_ITMP2);
1562 M_ISSL_IMM(2, REG_ITMP2);
1563 M_IADD_IMM(OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1564 M_ADRMOVE(s1, REG_ATMP1);
1565 M_AADDINT(REG_ITMP2, REG_ATMP1);
1566 /* implicit null-pointer check */
1567 #if !defined(ENABLE_SOFTFLOAT)
1568 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1569 M_FST(s3, REG_ATMP1, 0);
1571 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1572 M_STWX(REG_ATMP1, s3);
1576 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1577 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1578 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1579 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1580 M_INTMOVE(s2, REG_ITMP2);
1581 M_ISSL_IMM(3, REG_ITMP2);
1582 M_IADD_IMM(OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1583 M_ADRMOVE(s1, REG_ATMP1);
1584 M_AADDINT(REG_ITMP2, REG_ATMP1);
1585 /* implicit null-pointer check */
1586 #if !defined(ENABLE_SOFTFLOAT)
1587 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1588 M_DST(s3, REG_ATMP1, 0);
1590 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1591 /* implicit null-pointer check */
1592 M_LST(s3, REG_ATMP1, 0);
1596 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1598 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1599 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1600 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1601 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1603 /* XXX what if array is NULL */
1604 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1606 M_AST(s1, REG_SP, 0*4);
1607 M_AST(s3, REG_SP, 1*4);
1608 M_JSR_IMM(BUILTIN_FAST_canstore);
1609 emit_arraystore_check(cd, iptr);
1611 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1612 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1613 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1614 M_INTMOVE(s2, REG_ITMP1);
1615 M_ISSL_IMM(2, REG_ITMP1);
1616 M_IADD_IMM(OFFSET(java_objectarray_t, data[0]), REG_ITMP1);
1617 M_ADRMOVE(s1, REG_ATMP1);
1618 M_AADDINT(REG_ITMP1, REG_ATMP1);
1619 /* implicit null-pointer check */
1620 M_STAX(REG_ATMP1, s3);
1625 /* METHOD INVOCATION *********************************************************/
1626 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
1627 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
1629 bte = iptr->sx.s23.s3.bte;
1633 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1634 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1635 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1636 case ICMD_INVOKEINTERFACE:
1637 REPLACEMENT_POINT_INVOKE(cd, iptr);
1639 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1641 um = iptr->sx.s23.s3.um;
1642 md = um->methodref->parseddesc.md;
1645 lm = iptr->sx.s23.s3.fmiref->p.method;
1647 md = lm->parseddesc;
1650 s3 = md->paramcount;
1652 MCODECHECK((s3 << 1) + 64);
1654 /* copy arguments to stack */
1655 for (s3 = s3 - 1; s3 >= 0; s3--) {
1656 var = VAR(iptr->sx.s23.s2.args[s3]);
1657 /* already preallocated */
1658 if (var->flags & PREALLOC) continue;
1660 if (!md->params[s3].inmemory) assert(0);
1662 switch (var->type) {
1663 #if defined(ENABLE_SOFTFLOAT)
1667 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
1668 M_LST(d, REG_SP, md->params[s3].regoff);
1670 #if defined(ENABLE_SOFTFLOAT)
1674 d = emit_load(jd, iptr, var, REG_ITMP1);
1675 M_IST(d, REG_SP, md->params[s3].regoff);
1678 d = emit_load(jd, iptr, var, REG_ATMP1);
1679 M_AST(d, REG_SP, md->params[s3].regoff);
1681 #if !defined(ENABLE_SOFTFLOAT)
1683 d = emit_load(jd, iptr, var, REG_FTMP1);
1684 M_FST(d, REG_SP, md->params[s3].regoff);
1687 d = emit_load(jd, iptr, var, REG_FTMP1);
1688 M_DST(d, REG_SP, md->params[s3].regoff);
1696 /* arguments in place now */
1699 if (bte->stub == NULL)
1700 disp = (ptrint) bte->fp;
1702 disp = (ptrint) bte->stub;
1703 d = md->returntype.type;
1706 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1709 case ICMD_INVOKESPECIAL:
1710 /* adress register for sure */
1711 M_ALD(REG_ATMP1, REG_SP, 0);
1712 emit_nullpointer_check(cd, iptr, REG_ATMP1);
1714 case ICMD_INVOKESTATIC:
1716 codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
1718 M_AMOV_IMM(disp, REG_ATMP1);
1720 disp = lm->stubroutine;
1721 M_AMOV_IMM(disp, REG_ATMP1);
1724 /* generate the actual call */
1726 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1730 case ICMD_INVOKEVIRTUAL:
1732 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
1735 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1737 /* load object pointer (==argument 0) */
1738 M_ALD(REG_ATMP1, REG_SP, 0);
1739 /* implicit null-pointer check */
1740 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
1741 M_ALD(REG_ATMP3, REG_METHODPTR, s1);
1742 /* generate the actual call */
1745 case ICMD_INVOKEINTERFACE:
1747 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
1752 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
1753 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1755 /* load object pointer (==argument 0) */
1756 M_ALD(REG_ATMP1, REG_SP, 0);
1758 /* implicit null-pointer check */
1759 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
1760 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
1761 M_ALD(REG_ATMP3, REG_METHODPTR, s2);
1763 /* generate the actual call */
1765 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1769 } /* switch (iptr->opc) */
1771 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1772 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
1774 /* store return value */
1775 d = md->returntype.type;
1778 case TYPE_VOID: break;
1779 #if defined(ENABLE_SOFTFLOAT)
1783 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
1784 M_INTMOVE(REG_RESULT, s1);
1786 #if defined(ENABLE_SOFTFLOAT)
1790 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1791 M_LNGMOVE(REG_RESULT_PACKED, s1);
1794 s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
1795 /* all stuff is returned in %d0 */
1796 M_INT2ADRMOVE(REG_RESULT, s1);
1798 #if !defined(ENABLE_SOFTFLOAT)
1800 * for BUILTINS float values are returned in %d0,%d1
1801 * within cacao we use %fp0 for that.
1804 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1805 if (iptr->opc == ICMD_BUILTIN) {
1806 M_INT2FLTMOVE(REG_FRESULT, s1);
1808 M_FLTMOVE(REG_FRESULT, s1);
1812 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1813 if (iptr->opc == ICMD_BUILTIN) {
1814 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4 + 4);
1815 M_DLD(s1, REG_SP, rd->memuse * 4 + 4);
1817 M_DBLMOVE(REG_FRESULT, s1);
1824 if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
1825 break; /* ICMD_INVOKE* */
1827 #if defined(ENABLE_SOFTFLOAT)
1830 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1832 REPLACEMENT_POINT_RETURN(cd, iptr);
1833 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1834 M_INTMOVE(s1, REG_RESULT);
1835 goto nowperformreturn;
1837 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1839 REPLACEMENT_POINT_RETURN(cd, iptr);
1840 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1841 assert(VAROP(iptr->s1)->type == TYPE_ADR);
1842 M_ADR2INTMOVE(s1, REG_RESULT);
1844 #ifdef ENABLE_VERIFIER
1845 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1846 unresolved_class *uc = iptr->sx.s23.s2.uc;
1848 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1850 #endif /* ENABLE_VERIFIER */
1851 goto nowperformreturn;
1853 #if defined(ENABLE_SOFTFLOAT)
1856 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1857 REPLACEMENT_POINT_RETURN(cd, iptr);
1858 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
1859 M_LNGMOVE(s1, REG_RESULT_PACKED);
1860 goto nowperformreturn;
1862 #if !defined(ENABLE_SOFTFLOAT)
1863 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1864 REPLACEMENT_POINT_RETURN(cd, iptr);
1865 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1866 M_FLTMOVE(s1, REG_FRESULT);
1867 goto nowperformreturn;
1870 REPLACEMENT_POINT_RETURN(cd, iptr);
1871 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1872 M_DBLMOVE(s1, REG_FRESULT);
1873 goto nowperformreturn;
1877 case ICMD_RETURN: /* ... ==> ... */
1879 REPLACEMENT_POINT_RETURN(cd, iptr);
1885 p = cd->stackframesize;
1887 /* call trace function */
1888 #if !defined(NDEBUG)
1889 emit_verbosecall_exit(jd);
1892 #if defined(ENABLE_THREADS)
1893 /* call lock_monitor_exit */
1894 if (checksync && code_is_synchronized(code)) {
1895 M_ILD(REG_ITMP3, REG_SP, rd->memuse * 8);
1897 /* we need to save the proper return value */
1898 /* we do not care for the long -> doubel convert space here */
1899 switch (iptr->opc) {
1900 #if defined(ENABLE_SOFTFLOAT)
1904 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
1906 #if defined(ENABLE_SOFTFLOAT)
1911 M_IST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1913 #if !defined(ENABLE_SOFTFLOAT)
1915 M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1918 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1923 M_IST(REG_ITMP3, REG_SP, 0 * 4);
1924 M_JSR_IMM(LOCK_monitor_exit);
1926 /* and now restore the proper return value */
1927 switch (iptr->opc) {
1929 #if defined(ENABLE_SOFTFLOAT)
1933 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
1935 #if defined(ENABLE_SOFTFLOAT)
1940 M_ILD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1942 #if !defined(ENABLE_SOFTFLOAT)
1944 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1947 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1955 /* restore return address */
1957 if (!code_is_leafmethod(code)) {
1958 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
1959 may have a displacement overflow. */
1961 M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
1965 /* restore saved registers */
1967 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
1968 p-=8; M_ILD(rd->savintregs[i], REG_SP, p);
1970 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
1971 p-=8; M_ALD(rd->savadrregs[i], REG_SP, p);
1973 #if !defined(ENABLE_SOFTFLOAT)
1974 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
1975 p-=8; M_FLOAD(rd->savfltregs[i], REG_SP, p);
1978 /* deallocate stack */
1979 M_AADD_IMM(cd->stackframesize, REG_SP);
1985 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1986 /* val.a: (classinfo*) superclass */
1988 /* superclass is an interface:
1990 * return (sub != NULL) &&
1991 * (sub->vftbl->interfacetablelength > super->index) &&
1992 * (sub->vftbl->interfacetable[-super->index] != NULL);
1994 * superclass is a class:
1996 * return ((sub != NULL) && (0
1997 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
1998 * super->vftbl->diffvall));
2005 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2010 super = iptr->sx.s23.s3.c.cls;
2011 superindex = super->index;
2014 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2015 CODEGEN_CRITICAL_SECTION_NEW;
2017 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
2018 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2020 assert(VAROP(iptr->s1 )->type == TYPE_ADR);
2021 assert(VAROP(iptr->dst)->type == TYPE_INT);
2025 /* if class is not resolved, check which code to call */
2027 if (super == NULL) {
2029 emit_label_beq(cd, BRANCH_LABEL_1);
2031 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
2033 M_IMOV_IMM32(0, REG_ITMP3);
2034 M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
2035 emit_label_beq(cd, BRANCH_LABEL_2);
2038 /* interface instanceof code */
2040 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2041 if (super == NULL) {
2042 codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
2045 emit_label_beq(cd, BRANCH_LABEL_3);
2048 M_ALD(REG_ATMP1, s1, OFFSET(java_object_t, vftbl));
2049 M_ILD(REG_ITMP3, REG_ATMP1, OFFSET(vftbl_t, interfacetablelength));
2050 M_IADD_IMM(-superindex, REG_ITMP3); /* -superindex may be patched patched */
2053 M_ALD(REG_ATMP1, REG_ATMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patch here too! */
2059 emit_label_br(cd, BRANCH_LABEL_4);
2061 emit_label(cd, BRANCH_LABEL_3);
2064 /* class instanceof code */
2066 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2067 if (super == NULL) {
2068 emit_label(cd, BRANCH_LABEL_2);
2070 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
2071 M_AMOV_IMM(0, REG_ATMP2);
2073 M_AMOV_IMM(super->vftbl, REG_ATMP2);
2075 emit_label_beq(cd, BRANCH_LABEL_5);
2078 M_ALD(REG_ATMP1, s1, OFFSET(java_object_t, vftbl));
2080 CODEGEN_CRITICAL_SECTION_START;
2082 M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
2083 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
2084 M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
2086 CODEGEN_CRITICAL_SECTION_END;
2088 M_ISUB(REG_ITMP3, REG_ITMP1);
2089 M_ICMP(REG_ITMP2, REG_ITMP1);
2092 M_TPFW; /* overlaps next instruction */
2096 emit_label(cd, BRANCH_LABEL_5);
2099 if (super == NULL) {
2100 emit_label(cd, BRANCH_LABEL_1);
2101 emit_label(cd, BRANCH_LABEL_4);
2104 emit_store_dst(jd, iptr, d);
2108 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2109 /* val.a: (classinfo*) superclass */
2111 /* superclass is an interface:
2113 * OK if ((sub == NULL) ||
2114 * (sub->vftbl->interfacetablelength > super->index) &&
2115 * (sub->vftbl->interfacetable[-super->index] != NULL));
2117 * superclass is a class:
2119 * OK if ((sub == NULL) || (0
2120 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2121 * super->vftbl->diffvall));
2124 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2125 /* object type cast-check */
2130 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2135 super = iptr->sx.s23.s3.c.cls;
2136 superindex = super->index;
2139 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2140 CODEGEN_CRITICAL_SECTION_NEW;
2142 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
2143 assert(VAROP(iptr->s1)->type == TYPE_ADR);
2145 /* if class is not resolved, check which code to call */
2147 if (super == NULL) {
2149 emit_label_beq(cd, BRANCH_LABEL_1);
2151 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
2153 M_IMOV_IMM32(0, REG_ITMP2);
2154 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
2155 emit_label_beq(cd, BRANCH_LABEL_2);
2158 /* interface checkcast code */
2160 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2161 if (super == NULL) {
2162 codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
2165 emit_label_beq(cd, BRANCH_LABEL_3);
2168 M_ALD(REG_ATMP2, s1, OFFSET(java_object_t, vftbl));
2169 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetablelength));
2171 M_IADD_IMM(-superindex, REG_ITMP3); /* superindex patched */
2173 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2175 M_ALD(REG_ATMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patched*/
2177 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ATMP3, s1);
2180 emit_label_br(cd, BRANCH_LABEL_4);
2182 emit_label(cd, BRANCH_LABEL_3);
2185 /* class checkcast code */
2187 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2188 if (super == NULL) {
2189 emit_label(cd, BRANCH_LABEL_2);
2191 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
2192 M_AMOV_IMM(0, REG_ATMP3);
2194 M_AMOV_IMM(super->vftbl, REG_ATMP3);
2196 emit_label_beq(cd, BRANCH_LABEL_5);
2199 M_ALD(REG_ATMP2, s1, OFFSET(java_object_t, vftbl));
2201 CODEGEN_CRITICAL_SECTION_START;
2203 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval)); /* REG_ITMP3 == sub->vftbl->baseval */
2204 M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
2205 M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
2207 CODEGEN_CRITICAL_SECTION_END;
2209 M_ISUB(REG_ITMP1, REG_ITMP3);
2210 M_ICMP(REG_ITMP2, REG_ITMP3); /* XXX was CMPU */
2212 emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); /* XXX was BRANCH_GT */
2215 emit_label(cd, BRANCH_LABEL_5);
2218 if (super == NULL) {
2219 emit_label(cd, BRANCH_LABEL_1);
2220 emit_label(cd, BRANCH_LABEL_4);
2223 d = codegen_reg_of_dst(jd, iptr, s1);
2225 /* array type cast-check */
2227 s1 = emit_load_s1(jd, iptr, REG_ATMP2);
2229 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2230 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2231 M_AMOV_IMM(0, REG_ATMP1);
2233 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2238 M_JSR_IMM(BUILTIN_arraycheckcast);
2239 M_AADD_IMM(2*4, REG_SP); /* pop arguments off stack */
2241 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2243 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2244 d = codegen_reg_of_dst(jd, iptr, s1);
2246 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2248 emit_store_dst(jd, iptr, d);
2251 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2254 branch_target_t *table;
2256 table = iptr->dst.table;
2258 l = iptr->sx.s23.s2.tablelow;
2259 i = iptr->sx.s23.s3.tablehigh;
2261 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2262 M_INTMOVE(s1, REG_ITMP1);
2263 if (l != 0) M_ISUB_IMM(l, REG_ITMP1);
2268 M_ICMP_IMM(i - 1, REG_ITMP1);
2269 emit_bugt(cd, table[0].block);
2271 /* build jump table top down and use address of lowest entry */
2275 dseg_add_target(cd, table->block);
2279 /* length of dataseg after last dseg_add_target is used by load */
2280 M_AMOV_IMM(0, REG_ATMP2);
2283 M_ISSL_IMM(2, REG_ITMP1); /* index * 4 == offset in table */
2284 M_AADDINT(REG_ITMP1, REG_ATMP2); /* offset in table */
2285 M_AADD_IMM(-(cd->dseglen), REG_ATMP2); /* start of table in dseg */
2286 M_ALD(REG_ATMP1, REG_ATMP2, 0);
2293 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2296 lookup_target_t *lookup;
2298 lookup = iptr->dst.lookup;
2300 i = iptr->sx.s23.s2.lookupcount;
2302 MCODECHECK((i<<2)+8);
2303 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2306 M_ICMP_IMM(lookup->value, s1);
2307 emit_beq(cd, lookup->target.block);
2311 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2316 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2318 /* check for negative sizes and copy sizes to stack if necessary */
2319 MCODECHECK((iptr->s1.argcount << 1) + 64);
2321 for (s1 = iptr->s1.argcount; --s1 >= 0;) {
2322 var = VAR(iptr->sx.s23.s2.args[s1]);
2324 /* Already Preallocated? */
2325 if (!(var->flags & PREALLOC)) {
2326 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2327 M_IST(s2, REG_SP, (s1 + 3) * 4);
2331 /* a0 = dimension count */
2332 M_IMOV_IMM(iptr->s1.argcount, REG_ITMP1);
2333 M_IST(REG_ITMP1, REG_SP, 0*4);
2335 /* a1 = arraydescriptor */
2336 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2337 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2338 M_AMOV_IMM(0, REG_ATMP1);
2340 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2342 M_AST(REG_ATMP1, REG_SP, 1*4);
2344 /* a2 = pointer to dimensions = stack pointer */
2345 M_AMOV(REG_SP, REG_ATMP1);
2346 M_AADD_IMM(3*4, REG_ATMP1);
2347 M_AST(REG_ATMP1, REG_SP, 2*4);
2349 M_JSR_IMM(BUILTIN_multianewarray);
2351 /* check for exception before result assignment */
2352 emit_exception_check(cd, iptr);
2354 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2355 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2356 M_INT2ADRMOVE(REG_RESULT, d);
2357 emit_store_dst(jd, iptr, d);
2363 printf("UNKNOWN OPCODE %d\n", iptr->opc);
2364 exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
2367 /* M_TPF; */ /* nop after each ICMD */
2368 } /* for each instruction */
2370 /* At the end of a basic block we may have to append some nops,
2371 because the patcher stub calling code might be longer than the
2372 actual instruction. So codepatching does not change the
2373 following block unintentionally. */
2375 if (cd->mcodeptr < cd->lastmcodeptr) {
2376 while (cd->mcodeptr < cd->lastmcodeptr) {
2382 } /* if (btpre->flags >= BBREACHED) */
2383 } /* for each basic block */
2385 dseg_createlinenumbertable(cd);
2387 /* generate stubs */
2388 emit_patcher_stubs(jd);
2394 /* codegen_emit_stub_compiler **************************************************
2396 Emits a stub routine which calls the compiler.
2398 *******************************************************************************/
2400 void codegen_emit_stub_compiler(jitdata *jd)
2405 /* get required compiler data */
2410 /* code for the stub */
2412 M_AMOV_IMM(m, REG_ATMP1);
2413 M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
2416 /* codegen_emit_stub_native ****************************************************
2418 Emits a stub routine which calls a native method.
2420 *******************************************************************************/
2422 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2431 /* get required compiler data */
2440 /* calc stackframe size */
2441 cd->stackframesize =
2442 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
2443 sizeof(localref_table) / SIZEOF_VOID_P +
2445 1 + /* functionptr */
2446 4; /* args for codegen_start_native_call */
2448 /* create method header */
2449 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2450 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
2451 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2452 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2453 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2454 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2455 (void) dseg_addlinenumbertablesize(cd);
2456 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2458 /* print call trace */
2459 #if !defined(NDEBUG)
2460 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2461 emit_verbosecall_enter(jd);
2466 M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
2468 /* get function address (this must happen before the stackframeinfo) */
2470 codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
2473 M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
2475 M_AST(REG_ATMP2, REG_SP, 4 * 4);
2477 /* put arguments for codegen_start_native_call onto stack */
2478 /* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
2480 M_AMOV(REG_SP, REG_ATMP1);
2481 M_AST(REG_ATMP1, REG_SP, 0 * 4); /* currentsp */
2483 M_AMOV_IMM(0, REG_ATMP2); /* 0 needs to patched */
2484 dseg_adddata(cd); /* this patches it */
2486 M_AST(REG_ATMP2, REG_SP, 1 * 4); /* pv */
2488 M_JSR_IMM(codegen_start_native_call);
2490 /* remember class argument */
2491 if (m->flags & ACC_STATIC)
2492 M_INT2ADRMOVE(REG_RESULT, REG_ATMP3);
2494 /* load function pointer */
2495 M_ALD(REG_ATMP2, REG_SP, 4 * 4);
2497 /* copy arguments into stackframe */
2498 for (i = md->paramcount -1, j = i + skipparams; i >= 0; --i, --j) {
2499 t = md->paramtypes[i].type;
2500 /* all arguments via stack */
2501 assert(md->params[i].inmemory);
2503 s1 = md->params[i].regoff + cd->stackframesize * 4 + 4;
2504 s2 = nmd->params[j].regoff;
2506 /* simply copy argument stack */
2507 M_ILD(REG_ITMP1, REG_SP, s1);
2508 M_IST(REG_ITMP1, REG_SP, s2);
2509 if (IS_2_WORD_TYPE(t)) {
2510 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
2511 M_IST(REG_ITMP1, REG_SP, s2 + 4);
2515 /* for static function class as second arg */
2516 if (m->flags & ACC_STATIC)
2517 M_AST(REG_ATMP3, REG_SP, 1 * 4);
2519 /* env ist first argument */
2520 M_AMOV_IMM(_Jv_env, REG_ATMP1);
2521 M_AST(REG_ATMP1, REG_SP, 0 * 4);
2523 /* call the native function */
2526 /* save return value */
2527 switch (md->returntype.type) {
2528 case TYPE_VOID: break;
2530 /* natives return float arguments in %d0, %d1, cacao expects them in %fp0 */
2533 M_IST(REG_D1, REG_SP, 2 * 4);
2539 M_IST(REG_D0, REG_SP, 2 * 4);
2545 /* print call trace */
2546 #if ! defined(NDEBUG)
2547 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2548 emit_verbosecall_exit(jd);
2551 /* remove native stackframe info */
2552 /* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
2554 M_AMOV(REG_SP, REG_ATMP1);
2555 M_AST(REG_ATMP1, REG_SP, 0 * 4); /* currentsp */
2557 M_AMOV_IMM(0, REG_ATMP2); /* 0 needs to patched */
2558 dseg_adddata(cd); /* this patches it */
2560 M_AST(REG_ATMP2, REG_SP, 1 * 4); /* pv */
2562 M_JSR_IMM(codegen_finish_native_call);
2564 M_INT2ADRMOVE(REG_RESULT, REG_ATMP1);
2565 /* restore return value */
2566 switch (md->returntype.type) {
2567 case TYPE_VOID: break;
2571 M_ILD(REG_D1, REG_SP, 2 * 4);
2576 M_ILD(REG_D0, REG_SP, 2 * 4);
2581 #if !defined(ENABLE_SOFTFLOAT)
2582 /* additionally load values into floating points registers
2583 * as cacao jit code expects them there */
2584 switch (md->returntype.type) {
2586 M_FLD(REG_D0, REG_SP, 2 * 4);
2589 M_DLD(REG_D0, REG_SP, 2 * 4);
2593 /* restore saved registers */
2595 M_AADD_IMM(cd->stackframesize*4, REG_SP);
2596 /* check for exception */
2601 /* handle exception, REG_ATMP1 already contains exception object, REG_ATMP2 holds address */
2603 M_ALD(REG_ATMP2_XPC, REG_SP, 0); /* take return address as faulting instruction */
2604 M_AADD_IMM(-2, REG_ATMP2_XPC); /* which is off by 2 */
2605 M_JMP_IMM(asm_handle_nat_exception);
2607 /* should never be reached from within jit code*/
2610 /* generate patcher stub call code */
2611 emit_patcher_stubs(jd);
2616 * These are local overrides for various environment variables in Emacs.
2617 * Please do not remove this and leave it at the end of the file, where
2618 * Emacs will automagically detect them.
2619 * ---------------------------------------------------------------------
2622 * indent-tabs-mode: t
2626 * vim:noexpandtab:sw=4:ts=4: