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/parse.h"
59 #include "vm/jit/patcher.h"
60 #include "vm/jit/reg.h"
61 #include "vm/jit/replace.h"
62 #include "vm/jit/stacktrace.h"
63 #include "vm/jit/md.h"
65 #include "vmcore/loader.h"
66 #include "vmcore/options.h"
67 #include "vmcore/utf8.h"
70 bool codegen_emit(jitdata *jd)
76 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 && (m->flags & ACC_SYNCHRONIZED)) {
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 */
142 #if defined(ENABLE_THREADS)
143 if (checksync && (m->flags & ACC_SYNCHRONIZED))
144 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8);/* IsSync */
147 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
148 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
150 /* XXX we use the IntSave a split field for the adr now */
151 (void) dseg_add_unique_s4(cd, (ADR_SAV_CNT - rd->savadrreguse) << 16 | (INT_SAV_CNT - rd->savintreguse)); /* IntSave */
152 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
154 dseg_addlinenumbertablesize(cd);
156 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
158 /* create exception table */
159 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
160 dseg_add_target(cd, ex->start);
161 dseg_add_target(cd, ex->end);
162 dseg_add_target(cd, ex->handler);
163 (void) dseg_add_unique_address(cd, ex->catchtype.any);
166 #if defined(ENABLE_PROFILING)
171 emit_verbosecall_enter(jd);
173 /* create stack frame */
174 M_AADD_IMM(-(cd->stackframesize), REG_SP);
176 /* save used callee saved registers */
177 p = cd->stackframesize;
178 for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
179 p-=8; M_IST(rd->savintregs[i], REG_SP, p);
181 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
182 p-=8; M_AST(rd->savadrregs[i], REG_SP, p);
184 #if !defined(ENABLE_SOFTFLOAT)
185 for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
186 p-=8; M_FSTORE(rd->savfltregs[i], REG_SP, p);
189 assert(FLT_SAV_CNT == 0);
190 assert(rd->savfltreguse == 0);
192 /* take arguments out of stack frame */
194 for (p = 0, l = 0; p < md->paramcount; p++) {
195 t = md->paramtypes[p].type;
196 varindex = jd->local_map[l * 5 + t];
199 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
202 if (varindex == UNUSED)
207 s1 = md->params[p].regoff;
208 assert(md->params[p].inmemory); /* all args are on stack */
211 #if defined(ENABLE_SOFTFLOAT)
217 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
218 if (IS_2_WORD_TYPE(t)) {
219 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
221 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
223 } else { /* stack arg -> spilled */
224 M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4);
225 M_IST(REG_ITMP1, REG_SP, var->vv.regoff);
226 if (IS_2_WORD_TYPE(t)) {
227 M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4 + 4);
228 M_IST(REG_ITMP1, REG_SP, var->vv.regoff + 4);
232 #if !defined(ENABLE_SOFTFLOAT)
235 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
236 if (IS_2_WORD_TYPE(t)) {
237 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
239 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
241 } else { /* stack-arg -> spilled */
242 if (IS_2_WORD_TYPE(t)) {
243 M_DLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
244 M_DST(REG_FTMP1, REG_SP, var->vv.regoff);
246 M_FLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
247 M_FST(REG_FTMP1, REG_SP, var->vv.regoff);
251 #endif /* SOFTFLOAT */
253 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
254 M_ALD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
255 } else { /* stack-arg -> spilled */
256 M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + s1 + 4);
257 M_AST(REG_ATMP1, REG_SP, var->vv.regoff);
262 } /* end for argument out of stack*/
264 #if defined(ENABLE_THREADS)
265 /* call lock_monitor_enter function */
266 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
267 if (m->flags & ACC_STATIC) {
268 M_AMOV_IMM((&m->class->object.header), REG_ATMP1);
270 /* for non-static case the first arg is the object */
271 M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + 4);
274 M_TRAP(M68K_EXCEPTION_HARDWARE_NULLPOINTER);
277 M_AST(REG_ATMP1, REG_SP, rd->memuse * 8);
278 M_AST(REG_ATMP1, REG_SP, 0 * 4);
279 M_JSR_IMM(LOCK_monitor_enter);
285 /* create replacement points */
286 REPLACEMENT_POINTS_INIT(cd, jd);
288 /* foreach basic block */
289 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
291 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
293 if (bptr->flags >= BBREACHED) {
295 /* branch resolving */
296 codegen_resolve_branchrefs(cd, bptr);
298 /* handle replacement points */
299 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
301 #if defined(ENABLE_PROFILING)
304 /* FIXME there are still some constrcuts to copy in here */
306 #if defined(ENABLE_LSRA)
310 /* copy interface registers to their destination */
316 var = VAR(bptr->invars[len]);
317 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
318 d = codegen_reg_of_var(0, var, REG_ATMP1_XPTR);
319 M_ADRMOVE(REG_ATMP1_XPTR, d);
320 emit_store(jd, NULL, var, d);
323 assert((var->flags & INOUT));
327 /* walk through all instructions */
331 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
332 if (iptr->line != currentline) {
333 dseg_addlinenumber(cd, iptr->line);
334 currentline = iptr->line;
337 MCODECHECK(1024); /* 1kB should be enough */
340 case ICMD_NOP: /* ... ==> ... */
341 case ICMD_POP: /* ..., value ==> ... */
342 case ICMD_POP2: /* ..., value, value ==> ... */
345 case ICMD_INLINE_START:
347 REPLACEMENT_POINT_INLINE_START(cd, iptr);
350 case ICMD_INLINE_BODY:
352 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
353 dseg_addlinenumber_inline_start(cd, iptr);
354 dseg_addlinenumber(cd, iptr->line);
357 case ICMD_INLINE_END:
359 dseg_addlinenumber_inline_end(cd, iptr);
360 dseg_addlinenumber(cd, iptr->line);
363 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
365 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
366 assert(VAROP(iptr->s1)->type == TYPE_ADR);
367 emit_nullpointer_check(cd, iptr, s1);
371 /* CONST **************************************************************/
372 case ICMD_ICONST: /* ... ==> ..., constant */
373 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
374 M_IMOV_IMM(iptr->sx.val.i, d);
375 emit_store_dst(jd, iptr, d);
378 case ICMD_LCONST: /* ... ==> ..., constant */
380 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
381 LCONST(iptr->sx.val.l, d);
382 emit_store_dst(jd, iptr, d);
385 case ICMD_FCONST: /* ... ==> ..., constant */
387 #if defined(ENABLE_SOFTFLOAT)
388 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
389 M_IMOV_IMM(iptr->sx.val.i, d);
390 emit_store_dst(jd, iptr, d);
392 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
393 FCONST(iptr->sx.val.i, d);
394 emit_store_dst(jd, iptr, d);
398 case ICMD_DCONST: /* ... ==> ..., constant */
400 #if defined(ENABLE_SOFTFLOAT)
401 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
402 LCONST(iptr->sx.val.l, d);
403 emit_store_dst(jd, iptr, d);
405 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
406 disp = dseg_add_double(cd, iptr->sx.val.d);
407 M_AMOV_IMM(0, REG_ATMP1);
409 M_DLD(d, REG_ATMP1, disp);
410 emit_store_dst(jd, iptr, d);
415 /* some long operations *********************************************/
416 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
417 s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
418 s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
419 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
420 M_INTMOVE(s2, REG_ITMP1);
421 M_IADD(s1, REG_ITMP1); /* low word */
422 s1 = emit_load_s1_high(jd, iptr, REG_ITMP3);
423 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
424 M_INTMOVE(s2, REG_ITMP2);
425 M_IADDX(s1, REG_ITMP2); /* high word */
426 emit_store_dst(jd, iptr, d);
429 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
430 /* sx.val.l = constant */
431 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
432 s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
433 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
435 M_IMOV_IMM(iptr->sx.val.l >> 32, REG_ITMP3);
437 s3 = iptr->sx.val.l & 0xffffffff;
438 M_INTMOVE(s1, REG_ITMP1);
439 M_IADD_IMM(s3, REG_ITMP1); /* lower word in REG_ITMP1 now */
441 M_IADDX(REG_ITMP3, REG_ITMP2); /* high word in REG_ITMP2 now */
442 M_LNGMOVE(REG_ITMP12_PACKED, d);
443 emit_store_dst(jd, iptr, d);
446 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
447 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
448 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
449 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
450 M_INTMOVE(s1, REG_ITMP1);
451 M_ISUB(s2, REG_ITMP1); /* low word */
452 s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
453 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
454 M_INTMOVE(s1, REG_ITMP2);
455 M_ISUBX(s2, REG_ITMP2); /* high word */
456 emit_store_dst(jd, iptr, d);
459 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
460 /* sx.val.l = constant */
461 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
462 s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
463 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
465 M_IMOV_IMM( (-iptr->sx.val.l) >> 32, REG_ITMP3);
467 s3 = (-iptr->sx.val.l) & 0xffffffff;
468 M_INTMOVE(s1, REG_ITMP1);
469 M_IADD_IMM(s3, REG_ITMP1); /* lower word in REG_ITMP1 now */
471 M_IADDX(REG_ITMP3, REG_ITMP2); /* high word in REG_ITMP2 now */
472 M_LNGMOVE(REG_ITMP12_PACKED, d);
473 emit_store_dst(jd, iptr, d);
476 case ICMD_LNEG: /* ..., value ==> ..., - value */
477 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
478 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
479 M_LNGMOVE(s1, REG_ITMP12_PACKED);
480 M_INEG(GET_LOW_REG(REG_ITMP12_PACKED));
481 M_INEGX(GET_HIGH_REG(REG_ITMP12_PACKED));
482 M_LNGMOVE(REG_ITMP12_PACKED, d);
483 emit_store_dst(jd, iptr, d);
486 /* integer operations ************************************************/
487 case ICMD_INEG: /* ..., value ==> ..., - value */
489 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
490 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
491 M_INTMOVE(s1, REG_ITMP1);
493 M_INTMOVE(REG_ITMP1, d);
494 emit_store_dst(jd, iptr, d);
497 case ICMD_I2L: /* ..., value ==> ..., value */
499 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
500 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
501 M_IMOV(s1, GET_LOW_REG(d)); /* sets negativ bit */
503 M_ISET(GET_HIGH_REG(d));
505 M_ICLR(GET_HIGH_REG(d));
507 emit_store_dst(jd, iptr, d);
510 case ICMD_L2I: /* ..., value ==> ..., value */
512 s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
513 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
515 emit_store_dst(jd, iptr, d);
517 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
519 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
520 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
522 emit_store_dst(jd, iptr, d);
525 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
527 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
528 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
530 emit_store_dst(jd, iptr, d);
533 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
535 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
536 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
538 emit_store_dst(jd, iptr, d);
543 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
545 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
546 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
547 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
548 M_INTMOVE(s2, REG_ITMP2);
549 M_IADD(s1, REG_ITMP2);
550 M_INTMOVE(REG_ITMP2, d);
551 emit_store_dst(jd, iptr, d);
554 /* s1.localindex = variable, sx.val.i = constant*/
559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
560 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
561 M_INTMOVE(s1, REG_ITMP1);
562 M_IADD_IMM(iptr->sx.val.i, REG_ITMP1);
563 M_INTMOVE(REG_ITMP1, d);
564 emit_store_dst(jd, iptr, d);
567 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
569 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
570 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
571 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
572 M_INTMOVE(s1, REG_ITMP1);
573 M_ISUB(s2, REG_ITMP1);
574 M_INTMOVE(REG_ITMP1, d);
575 emit_store_dst(jd, iptr, d);
578 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
579 /* sx.val.i = constant */
581 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
582 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
583 M_INTMOVE(s1, REG_ITMP1);
584 M_IADD_IMM(-iptr->sx.val.i, REG_ITMP1);
585 M_INTMOVE(REG_ITMP1, d);
586 emit_store_dst(jd, iptr, d);
589 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
590 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
591 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
592 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
593 emit_arithmetic_check(cd, iptr, s2);
594 M_INTMOVE(s1, REG_ITMP1);
595 M_IDIV(s2, REG_ITMP1);
596 M_INTMOVE(REG_ITMP1, d);
597 emit_store_dst(jd, iptr, d);
600 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
601 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
602 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
603 M_INTMOVE(s1, REG_ITMP1);
607 M_IADD_IMM((1 << iptr->sx.val.i) - 1, REG_ITMP1);
609 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
610 M_ISSR(REG_ITMP2, REG_ITMP1);
611 M_INTMOVE(REG_ITMP1, d);
612 emit_store_dst(jd, iptr, d);
615 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
616 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
617 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
618 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
619 emit_arithmetic_check(cd, iptr, s2);
621 M_ICMP_IMM(0x80000000, s1);
626 M_TPFL; /* hides the next instruction */
627 M_IREM(s2, s1, REG_ITMP3);
629 M_INTMOVE(REG_ITMP3, d);
631 emit_store_dst(jd, iptr, d);
634 case ICMD_IREMPOW2: /* ..., value ==> ..., value << constant */
635 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
636 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
638 M_IMOV(s1, REG_ITMP1);
642 M_IAND_IMM(iptr->sx.val.i, d);
644 M_BGE(2 + 2 + 6 + 2);
645 M_IMOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */
647 M_IAND_IMM(iptr->sx.val.i, d); /* use 32-bit for jump offset */
650 emit_store_dst(jd, iptr, d);
654 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
655 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
657 bte = iptr->sx.s23.s3.bte;
660 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
661 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
662 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
663 /* XXX could be optimized */
664 emit_arithmetic_check(cd, iptr, REG_ITMP3);
666 M_LST(s2, REG_SP, 2 * 4);
667 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
668 M_LST(s1, REG_SP, 0 * 4);
672 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
673 M_LNGMOVE(REG_RESULT_PACKED, d);
674 emit_store_dst(jd, iptr, d);
677 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
679 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
680 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
681 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
682 M_INTMOVE(s2, REG_ITMP2);
683 M_IMUL(s1, REG_ITMP2);
684 M_INTMOVE(REG_ITMP2, d);
685 emit_store_dst(jd, iptr, d);
688 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
689 /* sx.val.i = constant */
690 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
691 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
692 M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
693 M_IMUL(s1, REG_ITMP2);
694 M_INTMOVE(REG_ITMP2, d);
695 emit_store_dst(jd, iptr, d);
698 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
700 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
701 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
702 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
703 M_INTMOVE(s1, REG_ITMP1);
704 M_INTMOVE(s2, REG_ITMP2);
705 M_IAND_IMM(0x1f, REG_ITMP2);
706 M_ISSL(REG_ITMP2, REG_ITMP1);
707 M_INTMOVE(REG_ITMP1, d);
708 emit_store_dst(jd, iptr, d);
711 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
712 /* sx.val.i = constant */
714 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
715 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
716 if (iptr->sx.val.i & 0x1f) {
717 M_INTMOVE(s1, REG_ITMP1)
718 if ((iptr->sx.val.i & 0x1f) <= 7) {
719 M_ISSL_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
721 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
722 M_ISSL(REG_ITMP2, REG_ITMP1);
724 M_INTMOVE(REG_ITMP1, d);
728 emit_store_dst(jd, iptr, d);
731 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
733 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
734 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
735 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
736 M_INTMOVE(s1, REG_ITMP1);
737 M_INTMOVE(s2, REG_ITMP2);
738 M_IAND_IMM(0x1f, REG_ITMP2);
739 M_ISSR(REG_ITMP2, REG_ITMP1);
740 M_INTMOVE(REG_ITMP1, d);
741 emit_store_dst(jd, iptr, d);
744 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
745 /* sx.val.i = constant */
747 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
748 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
749 if (iptr->sx.val.i & 0x1f) {
750 M_INTMOVE(s1, REG_ITMP1)
751 if ((iptr->sx.val.i & 0x1f) <= 7) {
752 M_ISSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
754 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
755 M_ISSR(REG_ITMP2, REG_ITMP1);
757 M_INTMOVE(REG_ITMP1, d);
761 emit_store_dst(jd, iptr, d);
764 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
766 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
767 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
768 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
769 M_INTMOVE(s1, REG_ITMP1);
770 M_INTMOVE(s2, REG_ITMP2);
771 M_IAND_IMM(0x1f, REG_ITMP2);
772 M_IUSR(REG_ITMP2, REG_ITMP1);
773 M_INTMOVE(REG_ITMP1, d);
774 emit_store_dst(jd, iptr, d);
777 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
778 /* sx.val.i = constant */
779 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
780 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
781 if (iptr->sx.val.i & 0x1f) {
782 M_INTMOVE(s1, REG_ITMP1)
783 if ((iptr->sx.val.i & 0x1f) <= 7) {
784 M_IUSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
786 M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
787 M_IUSR(REG_ITMP2, REG_ITMP1);
789 M_INTMOVE(REG_ITMP1, d);
793 emit_store_dst(jd, iptr, d);
796 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
798 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
799 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
800 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
801 M_INTMOVE(s2, REG_ITMP2);
802 M_IAND(s1, REG_ITMP2);
803 M_INTMOVE(REG_ITMP2, d);
804 emit_store_dst(jd, iptr, d);
807 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
808 /* sx.val.i = constant */
810 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
811 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
812 M_INTMOVE(s1, REG_ITMP1);
813 M_IAND_IMM(iptr->sx.val.i, REG_ITMP1);
814 M_INTMOVE(REG_ITMP1, d);
815 emit_store_dst(jd, iptr, d);
818 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
819 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
820 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
821 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
822 M_INTMOVE(s2, REG_ITMP2);
823 M_IOR(s1, REG_ITMP2);
824 M_INTMOVE(REG_ITMP2, d);
825 emit_store_dst(jd, iptr, d);
828 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
829 /* sx.val.i = constant */
830 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
831 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
832 M_INTMOVE(s1, REG_ITMP1);
833 M_IOR_IMM(iptr->sx.val.i, REG_ITMP1);
834 M_INTMOVE(REG_ITMP1, d);
835 emit_store_dst(jd, iptr, d);
838 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 | val2 */
839 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
840 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
841 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
842 M_INTMOVE(s2, REG_ITMP2);
843 M_IXOR(s1, REG_ITMP2);
844 M_INTMOVE(REG_ITMP2, d);
845 emit_store_dst(jd, iptr, d);
848 case ICMD_IXORCONST: /* ..., value ==> ..., value | constant */
849 /* sx.val.i = constant */
850 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
851 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
852 M_INTMOVE(s1, REG_ITMP1);
853 M_IXOR_IMM(iptr->sx.val.i, REG_ITMP1);
854 M_INTMOVE(REG_ITMP1, d);
855 emit_store_dst(jd, iptr, d);
858 /* floating point operations ******************************************/
859 #if !defined(ENABLE_SOFTFLOAT)
860 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
862 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
863 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
864 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
867 M_BFUN(14); /* result is -1, branch to end */
868 M_BFLT(10); /* result is -1, branch to end */
870 M_BFEQ(4) /* result is 0, branch to end */
872 emit_store_dst(jd, iptr, d);
875 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
877 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
878 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
879 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
882 M_BFUN(16); /* result is +1, branch to end */
883 M_BFGT(14); /* result is +1, branch to end */
885 M_BFEQ(8) /* result is 0, branch to end */
887 emit_store_dst(jd, iptr, d);
890 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
891 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
892 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
893 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
894 M_FLTMOVE(s2, REG_FTMP2);
895 M_FMUL(s1, REG_FTMP2);
896 M_FLTMOVE(REG_FTMP2, d);
897 emit_store_dst(jd, iptr, d);
900 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
901 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
902 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
903 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
904 M_DBLMOVE(s2, REG_FTMP2);
905 M_DMUL(s1, REG_FTMP2);
906 M_DBLMOVE(REG_FTMP2, d);
907 emit_store_dst(jd, iptr, d);
910 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
911 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
912 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
913 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
914 M_FLTMOVE(s1, REG_FTMP1);
915 M_FDIV(s2, REG_FTMP1);
916 M_FLTMOVE(REG_FTMP1, d);
917 emit_store_dst(jd, iptr, d);
920 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
921 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
922 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
923 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
924 M_DBLMOVE(s1, REG_FTMP1);
925 M_DDIV(s2, REG_FTMP1);
926 M_DBLMOVE(REG_FTMP1, d);
927 emit_store_dst(jd, iptr, d);
930 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
931 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
932 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
933 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
934 M_FLTMOVE(s2, REG_FTMP2);
935 M_FADD(s1, REG_FTMP2);
936 M_FLTMOVE(REG_FTMP2, d);
937 emit_store_dst(jd, iptr, d);
940 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
941 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
942 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
943 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
944 M_DBLMOVE(s2, REG_FTMP2);
945 M_DADD(s1, REG_FTMP2);
946 M_DBLMOVE(REG_FTMP2, d);
947 emit_store_dst(jd, iptr, d);
950 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
951 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
952 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
953 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
954 M_FLTMOVE(s1, REG_FTMP1);
955 M_FSUB(s2, REG_FTMP1);
956 M_FLTMOVE(REG_FTMP1, d);
957 emit_store_dst(jd, iptr, d);
960 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
961 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
962 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
963 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
964 M_DBLMOVE(s1, REG_FTMP1);
965 M_DSUB(s2, REG_FTMP1);
966 M_DBLMOVE(REG_FTMP1, d);
967 emit_store_dst(jd, iptr, d);
970 case ICMD_F2D: /* ..., value ==> ..., (double) value */
971 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
972 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
974 emit_store_dst(jd, iptr, d);
977 case ICMD_D2F: /* ..., value ==> ..., (float) 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_FNEG: /* ..., value ==> ..., - 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_DNEG: /* ..., 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);
1000 /* load/store/copy/move operations ************************************/
1002 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
1003 case ICMD_ALOAD: /* s1 = local variable */
1007 case ICMD_ISTORE: /* ..., value ==> ... */
1014 emit_copy(jd, iptr);
1019 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
1020 emit_copy(jd, iptr);
1024 case ICMD_ACONST: /* ... ==> ..., constant */
1025 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1027 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1028 constant_classref *cr = iptr->sx.val.c.ref;;
1029 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
1032 M_AMOV_IMM(iptr->sx.val.anyptr, d);
1034 emit_store_dst(jd, iptr, d);
1036 /* BRANCH *************************************************************/
1038 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1040 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1041 M_ADRMOVE(s1, REG_ATMP1_XPTR);
1043 #ifdef ENABLE_VERIFIER
1044 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1045 unresolved_class *uc = iptr->sx.s23.s2.uc;
1047 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1049 #endif /* ENABLE_VERIFIER */
1050 M_JSR_PCREL(2); /* get current PC */
1053 M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
1058 case ICMD_GOTO: /* ... ==> ... */
1059 case ICMD_RET: /* ... ==> ... */
1061 emit_br(cd, iptr->dst.block);
1065 case ICMD_JSR: /* ... ==> ... */
1067 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1073 case ICMD_IFNULL: /* ..., value ==> ... */
1074 case ICMD_IFNONNULL:
1075 assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
1076 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1078 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
1086 case ICMD_IFEQ: /* ..., value ==> ... */
1088 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1089 assert (VAROP(iptr->s1)->type == TYPE_INT);
1090 M_ICMP_IMM(iptr->sx.val.i, s1);
1091 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1094 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1095 case ICMD_IF_ICMPNE:
1096 case ICMD_IF_ICMPLT:
1097 case ICMD_IF_ICMPGT:
1098 case ICMD_IF_ICMPLE:
1099 case ICMD_IF_ICMPGE:
1101 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1102 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1104 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
1107 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
1108 case ICMD_IF_ACMPNE:
1110 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1111 s2 = emit_load_s2(jd, iptr, REG_ATMP2);
1113 emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
1117 /* MEMORY *************************************************************/
1119 case ICMD_GETSTATIC: /* ... ==> ..., value */
1121 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1122 uf = iptr->sx.s23.s3.uf;
1123 fieldtype = uf->fieldref->parseddesc.fd->type;
1126 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1129 fi = iptr->sx.s23.s3.fmiref->p.field;
1130 fieldtype = fi->type;
1131 disp = (intptr_t) fi->value;
1133 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1134 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
1139 M_AMOV_IMM(disp, REG_ATMP1);
1140 switch (fieldtype) {
1141 #if defined(ENABLE_SOFTFLOAT)
1145 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1146 M_ILD(d, REG_ATMP1, 0);
1149 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1150 M_ALD(d, REG_ATMP1, 0);
1152 #if defined(ENABLE_SOFTFLOAT)
1156 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1157 M_LLD(d, REG_ATMP1, 0);
1159 #if !defined(ENABLE_SOFTFLOAT)
1161 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1162 M_FLD(d, REG_ATMP1, 0);
1165 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1166 M_DLD(d, REG_ATMP1, 0);
1170 emit_store_dst(jd, iptr, d);
1173 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1175 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1176 uf = iptr->sx.s23.s3.uf;
1177 fieldtype = uf->fieldref->parseddesc.fd->type;
1180 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
1183 fi = iptr->sx.s23.s3.fmiref->p.field;
1184 fieldtype = fi->type;
1185 disp = (intptr_t) fi->value;
1187 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1188 codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
1192 M_AMOV_IMM(disp, REG_ATMP1);
1193 switch (fieldtype) {
1194 #if defined(ENABLE_SOFTFLOAT)
1198 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1199 M_IST(s1, REG_ATMP1, 0);
1201 #if defined(ENABLE_SOFTFLOAT)
1205 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1206 M_LST(s1, REG_ATMP1, 0);
1209 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1210 M_AST(s1, REG_ATMP1, 0);
1212 #if !defined(ENABLE_SOFTFLOAT)
1214 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1215 M_FST(s1, REG_ATMP1, 0);
1218 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1219 M_DST(s1, REG_ATMP1, 0);
1226 case ICMD_GETFIELD: /* ... ==> ..., value */
1228 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1230 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1231 uf = iptr->sx.s23.s3.uf;
1232 fieldtype = uf->fieldref->parseddesc.fd->type;
1235 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1238 fi = iptr->sx.s23.s3.fmiref->p.field;
1239 fieldtype = fi->type;
1243 /* implicit null-pointer check */
1244 switch (fieldtype) {
1245 #if defined(ENABLE_SOFTFLOAT)
1249 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1252 #if defined(ENABLE_SOFTFLOAT)
1256 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1260 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1263 #if !defined(ENABLE_SOFTFLOAT)
1265 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1269 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1274 emit_store_dst(jd, iptr, d);
1277 case ICMD_PUTFIELD: /* ..., value ==> ... */
1279 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1281 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1282 uf = iptr->sx.s23.s3.uf;
1283 fieldtype = uf->fieldref->parseddesc.fd->type;
1287 fi = iptr->sx.s23.s3.fmiref->p.field;
1288 fieldtype = fi->type;
1292 if (IS_INT_LNG_TYPE(fieldtype)) {
1293 if (IS_2_WORD_TYPE(fieldtype)) {
1294 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1296 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1299 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1302 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1303 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1305 /* implicit null-pointer check */
1306 switch (fieldtype) {
1307 #if defined(ENABLE_SOFTFLOAT)
1311 M_IST(s2, s1, disp);
1314 #if defined(ENABLE_SOFTFLOAT)
1318 M_LST(s2, s1, disp);
1321 M_AST(s2, s1, disp);
1323 #if !defined(ENABLE_SOFTFLOAT)
1325 M_FST(s2, s1, disp);
1328 M_DST(s2, s1, disp);
1334 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1336 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1337 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1338 /* implicit null-pointer check */
1339 M_ILD(d, s1, OFFSET(java_array_t, size));
1340 emit_store_dst(jd, iptr, d);
1343 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1345 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1346 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1347 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1348 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1349 M_INTMOVE(s2, REG_ITMP2);
1350 M_IADD_IMM(OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1351 M_ADRMOVE(s1, REG_ATMP1);
1352 M_AADDINT(REG_ITMP2, REG_ATMP1);
1353 /* implicit null-pointer check */
1354 M_LBZX(REG_ATMP1, d);
1356 emit_store_dst(jd, iptr, d);
1359 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1361 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1362 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1363 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1364 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1365 M_INTMOVE(s2, REG_ITMP2);
1366 M_ISSL_IMM(1, REG_ITMP2);
1367 M_IADD_IMM(OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1368 M_ADRMOVE(s1, REG_ATMP1);
1369 M_AADDINT(REG_ITMP2, REG_ATMP1);
1370 /* implicit null-pointer check */
1371 M_LHZX(REG_ATMP1, d);
1373 emit_store_dst(jd, iptr, d);
1376 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1378 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1379 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1380 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1381 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1382 M_INTMOVE(s2, REG_ITMP2);
1383 M_ISSL_IMM(1, REG_ITMP2);
1384 M_IADD_IMM(OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1385 M_ADRMOVE(s1, REG_ATMP1);
1386 M_AADDINT(REG_ITMP2, REG_ATMP1);
1388 /* implicit null-pointer check */
1389 M_LHZX(REG_ATMP1, d);
1391 emit_store_dst(jd, iptr, d);
1394 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1396 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1397 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1398 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1399 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1400 M_INTMOVE(s2, REG_ITMP2);
1401 M_ISSL_IMM(2, REG_ITMP2);
1402 M_IADD_IMM(OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1403 M_ADRMOVE(s1, REG_ATMP1);
1404 M_AADDINT(REG_ITMP2, REG_ATMP1);
1405 /* implicit null-pointer check */
1406 M_LWZX(REG_ATMP1, d);
1407 emit_store_dst(jd, iptr, d);
1410 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1411 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1412 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1413 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1414 /* implicit null-pointer check */
1415 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1416 M_INTMOVE(s2, REG_ITMP1);
1417 M_ISSL_IMM(3, REG_ITMP1);
1418 M_IADD_IMM(OFFSET(java_longarray_t, data[0]), REG_ITMP1);
1419 M_ADRMOVE(s1, REG_ATMP1);
1420 M_AADDINT(REG_ITMP1, REG_ATMP1);
1421 /* implicit null-pointer check */
1422 M_LLD(d, REG_ATMP1, 0);
1423 emit_store_dst(jd, iptr, d);
1426 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1427 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1428 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1429 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1430 M_INTMOVE(s2, REG_ITMP2);
1431 M_ISSL_IMM(2, REG_ITMP2);
1432 M_IADD_IMM(OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1433 M_ADRMOVE(s1, REG_ATMP1);
1434 M_AADDINT(REG_ITMP2, REG_ATMP1);
1435 /* implicit null-pointer check */
1436 #if !defined(ENABLE_SOFTFLOAT)
1437 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1438 M_FLD(d, REG_ATMP1, 0);
1440 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1441 M_LWZX(REG_ATMP1, d);
1443 emit_store_dst(jd, iptr, d);
1446 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1447 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1448 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1449 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1450 M_INTMOVE(s2, REG_ITMP2);
1451 M_ISSL_IMM(3, REG_ITMP2);
1452 M_IADD_IMM(OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1453 M_ADRMOVE(s1, REG_ATMP1);
1454 M_AADDINT(REG_ITMP2, REG_ATMP1);
1455 /* implicit null-pointer check */
1456 #if !defined(ENABLE_SOFTFLOAT)
1457 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1458 M_DLD(d, REG_ATMP1, 0);
1460 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1461 M_LLD(d, REG_ATMP1, 0);
1463 emit_store_dst(jd, iptr, d);
1466 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1467 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1468 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1469 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1470 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1471 M_INTMOVE(s2, REG_ITMP2);
1472 M_ISSL_IMM(2, REG_ITMP2);
1473 M_IADD_IMM(OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
1474 M_ADRMOVE(s1, REG_ATMP1);
1475 M_AADDINT(REG_ITMP2, REG_ATMP1);
1477 /* implicit null-pointer check */
1478 M_LAX(REG_ATMP1, d);
1479 emit_store_dst(jd, iptr, d);
1483 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1484 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1485 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1486 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1487 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1488 M_INTMOVE(s2, REG_ITMP2);
1489 M_IADD_IMM(OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1490 M_ADRMOVE(s1, REG_ATMP1);
1491 M_AADDINT(REG_ITMP2, REG_ATMP1);
1492 /* implicit null-pointer check */
1493 M_STBX(REG_ATMP1, s3);
1496 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1497 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1498 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1499 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1500 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1501 M_INTMOVE(s2, REG_ITMP2);
1502 M_ISSL_IMM(1, REG_ITMP2);
1503 M_IADD_IMM(OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1504 M_ADRMOVE(s1, REG_ATMP1);
1505 M_AADDINT(REG_ITMP2, REG_ATMP1);
1506 /* implicit null-pointer check */
1507 M_STHX(REG_ATMP1, s3);
1510 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1511 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1512 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1513 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1514 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1515 M_INTMOVE(s2, REG_ITMP2);
1516 M_ISSL_IMM(1, REG_ITMP2);
1517 M_IADD_IMM(OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1518 M_ADRMOVE(s1, REG_ATMP1);
1519 M_AADDINT(REG_ITMP2, REG_ATMP1);
1520 /* implicit null-pointer check */
1521 M_STHX(REG_ATMP1, s3);
1524 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1525 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1526 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1527 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1528 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1529 M_INTMOVE(s2, REG_ITMP2);
1530 M_ISSL_IMM(2, REG_ITMP2);
1531 M_IADD_IMM(OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1532 M_ADRMOVE(s1, REG_ATMP1);
1533 M_AADDINT(REG_ITMP2, REG_ATMP1);
1534 /* implicit null-pointer check */
1535 M_STWX(REG_ATMP1, s3);
1538 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1539 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1540 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1541 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1543 M_INTMOVE(s2, REG_ITMP1);
1544 M_ISSL_IMM(3, REG_ITMP1);
1545 M_IADD_IMM(OFFSET(java_longarray_t, data[0]), REG_ITMP1);
1546 M_ADRMOVE(s1, REG_ATMP1);
1547 M_AADDINT(REG_ITMP1, REG_ATMP1);
1548 /* implicit null-pointer check */
1549 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1550 M_LST(s3, REG_ATMP1, 0);
1553 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1554 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1555 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1556 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1557 M_INTMOVE(s2, REG_ITMP2);
1558 M_ISSL_IMM(2, REG_ITMP2);
1559 M_IADD_IMM(OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1560 M_ADRMOVE(s1, REG_ATMP1);
1561 M_AADDINT(REG_ITMP2, REG_ATMP1);
1562 /* implicit null-pointer check */
1563 #if !defined(ENABLE_SOFTFLOAT)
1564 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1565 M_FST(s3, REG_ATMP1, 0);
1567 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1568 M_STWX(REG_ATMP1, s3);
1572 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1573 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1574 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1575 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1576 M_INTMOVE(s2, REG_ITMP2);
1577 M_ISSL_IMM(3, REG_ITMP2);
1578 M_IADD_IMM(OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1579 M_ADRMOVE(s1, REG_ATMP1);
1580 M_AADDINT(REG_ITMP2, REG_ATMP1);
1581 /* implicit null-pointer check */
1582 #if !defined(ENABLE_SOFTFLOAT)
1583 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1584 M_DST(s3, REG_ATMP1, 0);
1586 s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1587 /* implicit null-pointer check */
1588 M_LST(s3, REG_ATMP1, 0);
1592 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1594 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1595 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1596 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1597 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1599 /* XXX what if array is NULL */
1600 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1602 M_AST(s1, REG_SP, 0*4);
1603 M_AST(s3, REG_SP, 1*4);
1604 M_JSR_IMM(BUILTIN_canstore);
1605 emit_exception_check(cd, iptr);
1607 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1608 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1609 s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1610 M_INTMOVE(s2, REG_ITMP1);
1611 M_ISSL_IMM(2, REG_ITMP1);
1612 M_IADD_IMM(OFFSET(java_objectarray_t, data[0]), REG_ITMP1);
1613 M_ADRMOVE(s1, REG_ATMP1);
1614 M_AADDINT(REG_ITMP1, REG_ATMP1);
1615 /* implicit null-pointer check */
1616 M_STAX(REG_ATMP1, s3);
1621 /* METHOD INVOCATION *********************************************************/
1622 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
1623 bte = iptr->sx.s23.s3.bte;
1627 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1628 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1629 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1630 case ICMD_INVOKEINTERFACE:
1631 REPLACEMENT_POINT_INVOKE(cd, iptr);
1633 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1635 um = iptr->sx.s23.s3.um;
1636 md = um->methodref->parseddesc.md;
1639 lm = iptr->sx.s23.s3.fmiref->p.method;
1641 md = lm->parseddesc;
1644 s3 = md->paramcount;
1646 MCODECHECK((s3 << 1) + 64);
1648 /* copy arguments to stack */
1649 for (s3 = s3 - 1; s3 >= 0; s3--) {
1650 var = VAR(iptr->sx.s23.s2.args[s3]);
1651 /* already preallocated */
1652 if (var->flags & PREALLOC) continue;
1654 if (!md->params[s3].inmemory) assert(0);
1656 switch (var->type) {
1657 #if defined(ENABLE_SOFTFLOAT)
1661 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
1662 M_LST(d, REG_SP, md->params[s3].regoff);
1664 #if defined(ENABLE_SOFTFLOAT)
1668 d = emit_load(jd, iptr, var, REG_ITMP1);
1669 M_IST(d, REG_SP, md->params[s3].regoff);
1672 d = emit_load(jd, iptr, var, REG_ATMP1);
1673 M_AST(d, REG_SP, md->params[s3].regoff);
1675 #if !defined(ENABLE_SOFTFLOAT)
1677 d = emit_load(jd, iptr, var, REG_FTMP1);
1678 M_FST(d, REG_SP, md->params[s3].regoff);
1681 d = emit_load(jd, iptr, var, REG_FTMP1);
1682 M_DST(d, REG_SP, md->params[s3].regoff);
1690 /* arguments in place now */
1693 disp = (ptrint) bte->fp;
1694 d = md->returntype.type;
1697 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1698 emit_exception_check(cd, iptr);
1701 case ICMD_INVOKESPECIAL:
1702 /* adress register for sure */
1703 M_ALD(REG_ATMP1, REG_SP, 0);
1704 emit_nullpointer_check(cd, iptr, REG_ATMP1);
1706 case ICMD_INVOKESTATIC:
1708 codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
1710 M_AMOV_IMM(disp, REG_ATMP1);
1712 disp = lm->stubroutine;
1713 M_AMOV_IMM(disp, REG_ATMP1);
1716 /* generate the actual call */
1718 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1722 case ICMD_INVOKEVIRTUAL:
1724 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
1727 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1729 /* load object pointer (==argument 0) */
1730 M_ALD(REG_ATMP1, REG_SP, 0);
1731 /* implicit null-pointer check */
1732 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
1733 M_ALD(REG_ATMP3, REG_METHODPTR, s1);
1734 /* generate the actual call */
1737 case ICMD_INVOKEINTERFACE:
1739 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
1744 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
1745 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1747 /* load object pointer (==argument 0) */
1748 M_ALD(REG_ATMP1, REG_SP, 0);
1750 /* implicit null-pointer check */
1751 M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
1752 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
1753 M_ALD(REG_ATMP3, REG_METHODPTR, s2);
1755 /* generate the actual call */
1757 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1761 } /* switch (iptr->opc) */
1763 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1765 /* store return value */
1766 d = md->returntype.type;
1769 case TYPE_VOID: break;
1770 #if defined(ENABLE_SOFTFLOAT)
1774 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
1775 M_INTMOVE(REG_RESULT, s1);
1777 #if defined(ENABLE_SOFTFLOAT)
1781 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1782 M_LNGMOVE(REG_RESULT_PACKED, s1);
1785 s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
1786 /* all stuff is returned in %d0 */
1787 M_INT2ADRMOVE(REG_RESULT, s1);
1789 #if !defined(ENABLE_SOFTFLOAT)
1791 * for BUILTINS float values are returned in %d0,%d1
1792 * within cacao we use %fp0 for that.
1795 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1796 if (iptr->opc == ICMD_BUILTIN) {
1797 M_INT2FLTMOVE(REG_FRESULT, s1);
1799 M_FLTMOVE(REG_FRESULT, s1);
1803 s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1804 if (iptr->opc == ICMD_BUILTIN) {
1805 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4 + 4);
1806 M_DLD(s1, REG_SP, rd->memuse * 4 + 4);
1808 M_DBLMOVE(REG_FRESULT, s1);
1815 if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
1816 break; /* ICMD_INVOKE* */
1818 #if defined(ENABLE_SOFTFLOAT)
1821 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1823 REPLACEMENT_POINT_RETURN(cd, iptr);
1824 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1825 M_INTMOVE(s1, REG_RESULT);
1826 goto nowperformreturn;
1828 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1830 REPLACEMENT_POINT_RETURN(cd, iptr);
1831 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1832 assert(VAROP(iptr->s1)->type == TYPE_ADR);
1833 M_ADR2INTMOVE(s1, REG_RESULT);
1835 #ifdef ENABLE_VERIFIER
1836 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1837 unresolved_class *uc = iptr->sx.s23.s2.uc;
1839 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1841 #endif /* ENABLE_VERIFIER */
1842 goto nowperformreturn;
1844 #if defined(ENABLE_SOFTFLOAT)
1847 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1848 REPLACEMENT_POINT_RETURN(cd, iptr);
1849 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
1850 M_LNGMOVE(s1, REG_RESULT_PACKED);
1851 goto nowperformreturn;
1853 #if !defined(ENABLE_SOFTFLOAT)
1854 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1855 REPLACEMENT_POINT_RETURN(cd, iptr);
1856 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1857 M_FLTMOVE(s1, REG_FRESULT);
1858 goto nowperformreturn;
1861 REPLACEMENT_POINT_RETURN(cd, iptr);
1862 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1863 M_DBLMOVE(s1, REG_FRESULT);
1864 goto nowperformreturn;
1868 case ICMD_RETURN: /* ... ==> ... */
1870 REPLACEMENT_POINT_RETURN(cd, iptr);
1876 p = cd->stackframesize;
1878 /* call trace function */
1879 #if !defined(NDEBUG)
1880 emit_verbosecall_exit(jd);
1883 #if defined(ENABLE_THREADS)
1884 /* call lock_monitor_exit */
1885 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1886 M_ILD(REG_ITMP3, REG_SP, rd->memuse * 8);
1888 /* we need to save the proper return value */
1889 /* we do not care for the long -> doubel convert space here */
1890 switch (iptr->opc) {
1891 #if defined(ENABLE_SOFTFLOAT)
1895 M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
1897 #if defined(ENABLE_SOFTFLOAT)
1902 M_IST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1904 #if !defined(ENABLE_SOFTFLOAT)
1906 M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1909 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1914 M_IST(REG_ITMP3, REG_SP, 0 * 4);
1915 M_JSR_IMM(LOCK_monitor_exit);
1917 /* and now restore the proper return value */
1918 switch (iptr->opc) {
1920 #if defined(ENABLE_SOFTFLOAT)
1924 M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
1926 #if defined(ENABLE_SOFTFLOAT)
1931 M_ILD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1933 #if !defined(ENABLE_SOFTFLOAT)
1935 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1938 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1946 /* restore return address */
1948 if (!jd->isleafmethod) {
1949 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
1950 may have a displacement overflow. */
1952 M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
1956 /* restore saved registers */
1958 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
1959 p-=8; M_ILD(rd->savintregs[i], REG_SP, p);
1961 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
1962 p-=8; M_ALD(rd->savadrregs[i], REG_SP, p);
1964 #if !defined(ENABLE_SOFTFLOAT)
1965 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
1966 p-=8; M_FLOAD(rd->savfltregs[i], REG_SP, p);
1969 /* deallocate stack */
1970 M_AADD_IMM(cd->stackframesize, REG_SP);
1976 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1977 /* val.a: (classinfo*) superclass */
1979 /* superclass is an interface:
1981 * return (sub != NULL) &&
1982 * (sub->vftbl->interfacetablelength > super->index) &&
1983 * (sub->vftbl->interfacetable[-super->index] != NULL);
1985 * superclass is a class:
1987 * return ((sub != NULL) && (0
1988 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
1989 * super->vftbl->diffvall));
1996 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2001 super = iptr->sx.s23.s3.c.cls;
2002 superindex = super->index;
2005 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2006 CODEGEN_CRITICAL_SECTION_NEW;
2008 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
2009 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2011 assert(VAROP(iptr->s1 )->type == TYPE_ADR);
2012 assert(VAROP(iptr->dst)->type == TYPE_INT);
2016 /* if class is not resolved, check which code to call */
2018 if (super == NULL) {
2020 emit_label_beq(cd, BRANCH_LABEL_1);
2022 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
2024 M_IMOV_IMM32(0, REG_ITMP3);
2025 M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
2026 emit_label_beq(cd, BRANCH_LABEL_2);
2029 /* interface instanceof code */
2031 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2032 if (super == NULL) {
2033 codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
2036 emit_label_beq(cd, BRANCH_LABEL_3);
2039 M_ALD(REG_ATMP1, s1, OFFSET(java_object_t, vftbl));
2040 M_ILD(REG_ITMP3, REG_ATMP1, OFFSET(vftbl_t, interfacetablelength));
2041 M_IADD_IMM(-superindex, REG_ITMP3); /* -superindex may be patched patched */
2044 M_ALD(REG_ATMP1, REG_ATMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patch here too! */
2050 emit_label_br(cd, BRANCH_LABEL_4);
2052 emit_label(cd, BRANCH_LABEL_3);
2055 /* class instanceof code */
2057 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2058 if (super == NULL) {
2059 emit_label(cd, BRANCH_LABEL_2);
2061 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
2062 M_AMOV_IMM(0, REG_ATMP2);
2064 M_AMOV_IMM(super->vftbl, REG_ATMP2);
2066 emit_label_beq(cd, BRANCH_LABEL_5);
2069 M_ALD(REG_ATMP1, s1, OFFSET(java_object_t, vftbl));
2071 CODEGEN_CRITICAL_SECTION_START;
2073 M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
2074 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
2075 M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
2077 CODEGEN_CRITICAL_SECTION_END;
2079 M_ISUB(REG_ITMP3, REG_ITMP1);
2080 M_ICMP(REG_ITMP2, REG_ITMP1);
2083 M_TPFW; /* overlaps next instruction */
2087 emit_label(cd, BRANCH_LABEL_5);
2090 if (super == NULL) {
2091 emit_label(cd, BRANCH_LABEL_1);
2092 emit_label(cd, BRANCH_LABEL_4);
2095 emit_store_dst(jd, iptr, d);
2099 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2100 /* val.a: (classinfo*) superclass */
2102 /* superclass is an interface:
2104 * OK if ((sub == NULL) ||
2105 * (sub->vftbl->interfacetablelength > super->index) &&
2106 * (sub->vftbl->interfacetable[-super->index] != NULL));
2108 * superclass is a class:
2110 * OK if ((sub == NULL) || (0
2111 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2112 * super->vftbl->diffvall));
2115 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2116 /* object type cast-check */
2121 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2126 super = iptr->sx.s23.s3.c.cls;
2127 superindex = super->index;
2130 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2131 CODEGEN_CRITICAL_SECTION_NEW;
2133 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
2134 assert(VAROP(iptr->s1)->type == TYPE_ADR);
2136 /* if class is not resolved, check which code to call */
2138 if (super == NULL) {
2140 emit_label_beq(cd, BRANCH_LABEL_1);
2142 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
2144 M_IMOV_IMM32(0, REG_ITMP2);
2145 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
2146 emit_label_beq(cd, BRANCH_LABEL_2);
2149 /* interface checkcast code */
2151 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2152 if (super == NULL) {
2153 codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
2156 emit_label_beq(cd, BRANCH_LABEL_3);
2159 M_ALD(REG_ATMP2, s1, OFFSET(java_object_t, vftbl));
2160 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetablelength));
2162 M_IADD_IMM(-superindex, REG_ITMP3); /* superindex patched */
2164 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2166 M_ALD(REG_ATMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); /* patched*/
2168 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ATMP3, s1);
2171 emit_label_br(cd, BRANCH_LABEL_4);
2173 emit_label(cd, BRANCH_LABEL_3);
2176 /* class checkcast code */
2178 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2179 if (super == NULL) {
2180 emit_label(cd, BRANCH_LABEL_2);
2182 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
2183 M_AMOV_IMM(0, REG_ATMP3);
2185 M_AMOV_IMM(super->vftbl, REG_ATMP3);
2187 emit_label_beq(cd, BRANCH_LABEL_5);
2190 M_ALD(REG_ATMP2, s1, OFFSET(java_object_t, vftbl));
2192 CODEGEN_CRITICAL_SECTION_START;
2194 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval)); /* REG_ITMP3 == sub->vftbl->baseval */
2195 M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
2196 M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
2198 CODEGEN_CRITICAL_SECTION_END;
2200 M_ISUB(REG_ITMP1, REG_ITMP3);
2201 M_ICMP(REG_ITMP2, REG_ITMP3); /* XXX was CMPU */
2203 emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); /* XXX was BRANCH_GT */
2206 emit_label(cd, BRANCH_LABEL_5);
2209 if (super == NULL) {
2210 emit_label(cd, BRANCH_LABEL_1);
2211 emit_label(cd, BRANCH_LABEL_4);
2214 d = codegen_reg_of_dst(jd, iptr, s1);
2216 /* array type cast-check */
2218 s1 = emit_load_s1(jd, iptr, REG_ATMP2);
2220 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2221 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2222 M_AMOV_IMM(0, REG_ATMP1);
2224 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2229 M_JSR_IMM(BUILTIN_arraycheckcast);
2230 M_AADD_IMM(2*4, REG_SP); /* pop arguments off stack */
2232 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2234 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2235 d = codegen_reg_of_dst(jd, iptr, s1);
2237 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2239 emit_store_dst(jd, iptr, d);
2242 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2245 branch_target_t *table;
2247 table = iptr->dst.table;
2249 l = iptr->sx.s23.s2.tablelow;
2250 i = iptr->sx.s23.s3.tablehigh;
2252 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2253 M_INTMOVE(s1, REG_ITMP1);
2254 if (l != 0) M_ISUB_IMM(l, REG_ITMP1);
2259 M_ICMP_IMM(i - 1, REG_ITMP1);
2260 emit_bugt(cd, table[0].block);
2262 /* build jump table top down and use address of lowest entry */
2266 dseg_add_target(cd, table->block);
2270 /* length of dataseg after last dseg_add_target is used by load */
2271 M_AMOV_IMM(0, REG_ATMP2);
2274 M_ISSL_IMM(2, REG_ITMP1); /* index * 4 == offset in table */
2275 M_AADDINT(REG_ITMP1, REG_ATMP2); /* offset in table */
2276 M_AADD_IMM(-(cd->dseglen), REG_ATMP2); /* start of table in dseg */
2277 M_ALD(REG_ATMP1, REG_ATMP2, 0);
2284 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2287 lookup_target_t *lookup;
2289 lookup = iptr->dst.lookup;
2291 i = iptr->sx.s23.s2.lookupcount;
2293 MCODECHECK((i<<2)+8);
2294 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2297 M_ICMP_IMM(lookup->value, s1);
2298 emit_beq(cd, lookup->target.block);
2302 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2307 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2309 /* check for negative sizes and copy sizes to stack if necessary */
2310 MCODECHECK((iptr->s1.argcount << 1) + 64);
2312 for (s1 = iptr->s1.argcount; --s1 >= 0;) {
2313 var = VAR(iptr->sx.s23.s2.args[s1]);
2315 /* Already Preallocated? */
2316 if (!(var->flags & PREALLOC)) {
2317 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2318 M_IST(s2, REG_SP, (s1 + 3) * 4);
2322 /* a0 = dimension count */
2323 M_IMOV_IMM(iptr->s1.argcount, REG_ITMP1);
2324 M_IST(REG_ITMP1, REG_SP, 0*4);
2326 /* a1 = arraydescriptor */
2327 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2328 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2329 M_AMOV_IMM(0, REG_ATMP1);
2331 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2333 M_AST(REG_ATMP1, REG_SP, 1*4);
2335 /* a2 = pointer to dimensions = stack pointer */
2336 M_AMOV(REG_SP, REG_ATMP1);
2337 M_AADD_IMM(3*4, REG_ATMP1);
2338 M_AST(REG_ATMP1, REG_SP, 2*4);
2340 M_JSR_IMM(BUILTIN_multianewarray);
2342 /* check for exception before result assignment */
2343 emit_exception_check(cd, iptr);
2345 assert(VAROP(iptr->dst)->type == TYPE_ADR);
2346 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2347 M_INT2ADRMOVE(REG_RESULT, d);
2348 emit_store_dst(jd, iptr, d);
2354 printf("UNKNOWN OPCODE %d\n", iptr->opc);
2355 exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
2358 /* M_TPF; */ /* nop after each ICMD */
2359 } /* for each instruction */
2361 /* At the end of a basic block we may have to append some nops,
2362 because the patcher stub calling code might be longer than the
2363 actual instruction. So codepatching does not change the
2364 following block unintentionally. */
2366 if (cd->mcodeptr < cd->lastmcodeptr) {
2367 while (cd->mcodeptr < cd->lastmcodeptr) {
2373 } /* if (btpre->flags >= BBREACHED) */
2374 } /* for each basic block */
2376 dseg_createlinenumbertable(cd);
2378 /* generate stubs */
2379 emit_patcher_stubs(jd);
2385 /* codegen_emit_stub_compiler **************************************************
2387 Emits a stub routine which calls the compiler.
2389 *******************************************************************************/
2391 void codegen_emit_stub_compiler(jitdata *jd)
2396 /* get required compiler data */
2401 /* code for the stub */
2403 M_AMOV_IMM(m, REG_ATMP1);
2404 M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
2409 /* codegen_emit_stub_native ****************************************************
2411 Emits a stub routine which calls a native method.
2413 *******************************************************************************/
2415 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
2422 s4 nativeparams, i, j, t, s1, s2;
2424 /* get required compiler data */
2432 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
2434 /* calc stackframe size */
2435 cd->stackframesize = sizeof(stackframeinfo) / SIZEOF_VOID_P +
2436 sizeof(localref_table) / SIZEOF_VOID_P +
2438 1 + /* functionptr */
2439 4; /* args for codegen_start_native_call */
2441 /* create method header */
2442 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2443 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
2444 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2445 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2446 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2447 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2448 (void) dseg_addlinenumbertablesize(cd);
2449 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2451 /* print call trace */
2452 #if !defined(NDEBUG)
2453 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2454 emit_verbosecall_enter(jd);
2459 M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
2461 /* get function address (this must happen before the stackframeinfo) */
2462 #if !defined(WITH_STATIC_CLASSPATH)
2464 codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
2467 M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
2469 M_AST(REG_ATMP2, REG_SP, 4 * 4);
2471 /* put arguments for codegen_start_native_call onto stack */
2472 /* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
2474 M_AMOV(REG_SP, REG_ATMP1);
2475 M_AADD_IMM(cd->stackframesize * 4, REG_ATMP1);
2477 M_ALD(REG_ATMP3, REG_ATMP1, 0 * 4);
2478 M_AST(REG_ATMP3, REG_SP, 3 * 4); /* ra */
2480 M_AST(REG_ATMP1, REG_SP, 0 * 4); /* datasp */
2482 M_AADD_IMM(1 * 4 , REG_ATMP1);
2483 M_AST(REG_ATMP1, REG_SP, 2 * 4); /* sp */
2485 M_AMOV_IMM(0, REG_ATMP2); /* 0 needs to patched */
2486 dseg_adddata(cd); /* this patches it */
2488 M_AST(REG_ATMP2, REG_SP, 1 * 4); /* pv */
2490 M_JSR_IMM(codegen_start_native_call);
2492 /* load function pointer */
2493 M_ALD(REG_ATMP2, REG_SP, 4 * 4);
2495 /* copy arguments into stackframe */
2496 for (i = md->paramcount -1, j = i + nativeparams; i >= 0; --i, --j) {
2497 t = md->paramtypes[i].type;
2498 /* all arguments via stack */
2499 assert(md->params[i].inmemory);
2501 s1 = md->params[i].regoff + cd->stackframesize * 4 + 4;
2502 s2 = nmd->params[j].regoff;
2504 /* simply copy argument stack */
2505 M_ILD(REG_ITMP1, REG_SP, s1);
2506 M_IST(REG_ITMP1, REG_SP, s2);
2507 if (IS_2_WORD_TYPE(t)) {
2508 M_ILD(REG_ITMP1, REG_SP, s1 + 4);
2509 M_IST(REG_ITMP1, REG_SP, s2 + 4);
2513 /* for static function class as second arg */
2514 if (m->flags & ACC_STATIC) {
2515 M_AMOV_IMM(m->class, REG_ATMP1);
2516 M_AST(REG_ATMP1, REG_SP, 1 * 4);
2518 /* env ist first argument */
2519 M_AMOV_IMM(_Jv_env, REG_ATMP1);
2520 M_AST(REG_ATMP1, REG_SP, 0 * 4);
2522 /* call the native function */
2525 /* save return value */
2526 switch (md->returntype.type) {
2527 case TYPE_VOID: break;
2529 /* natives return float arguments in %d0, %d1, cacao expects them in %fp0 */
2532 M_IST(REG_D1, REG_SP, 2 * 4);
2538 M_IST(REG_D0, REG_SP, 1 * 4);
2544 /* print call trace */
2545 #if ! defined(NDEBUG)
2546 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2547 emit_verbosecall_exit(jd);
2550 /* remove native stackframe info */
2551 /* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
2553 M_AMOV(REG_SP, REG_ATMP3);
2554 M_AADD_IMM(cd->stackframesize * 4, REG_ATMP3);
2555 M_AST(REG_ATMP3, REG_SP, 0 * 4); /* datasp */
2556 M_JSR_IMM(codegen_finish_native_call);
2558 M_INT2ADRMOVE(REG_RESULT, REG_ATMP1);
2559 /* restore return value */
2560 switch (md->returntype.type) {
2561 case TYPE_VOID: break;
2565 M_ILD(REG_D1, REG_SP, 2 * 4);
2570 M_ILD(REG_D0, REG_SP, 1 * 4);
2575 #if !defined(ENABLE_SOFTFLOAT)
2576 /* additionally load values into floating points registers
2577 * as cacao jit code expects them there */
2578 switch (md->returntype.type) {
2580 M_FLD(REG_D0, REG_SP, 1 * 4);
2583 M_DLD(REG_D0, REG_SP, 1 * 4);
2587 /* restore saved registers */
2589 M_AADD_IMM(cd->stackframesize*4, REG_SP);
2590 /* check for exception */
2595 /* handle exception, REG_ATMP1 already contains exception object, REG_ATMP2 holds address */
2597 M_ALD(REG_ATMP2_XPC, REG_SP, 0); /* take return address as faulting instruction */
2598 M_AADD_IMM(-2, REG_ATMP2_XPC); /* which is off by 2 */
2599 M_JMP_IMM(asm_handle_nat_exception);
2601 /* should never be reached from within jit code*/
2604 /* generate patcher stub call code */
2605 emit_patcher_stubs(jd);
2610 * These are local overrides for various environment variables in Emacs.
2611 * Please do not remove this and leave it at the end of the file, where
2612 * Emacs will automagically detect them.
2613 * ---------------------------------------------------------------------
2616 * indent-tabs-mode: t
2620 * vim:noexpandtab:sw=4:ts=4: