be082d70c49bf502eccad0ffd882e6ebecb2483a
[cacao.git] / src / vm / jit / powerpc64 / codegen.c
1 /* src/vm/jit/powerpc64/codegen.c - machine code generator for 64-bit PowerPC
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <signal.h>
32
33 #include "vm/types.h"
34
35 #include "md-abi.h"
36
37 #include "vm/jit/powerpc64/arch.h"
38 #include "vm/jit/powerpc64/codegen.h"
39
40 #include "mm/memory.h"
41
42 #include "native/localref.h"
43 #include "native/native.h"
44
45 #include "threads/lock-common.h"
46
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "vm/global.h"
50 #include "vm/stringlocal.h"
51 #include "vm/vm.h"
52
53 #include "vm/jit/abi.h"
54 #include "vm/jit/abi-asm.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/codegen-common.h"
57 #include "vm/jit/dseg.h"
58 #include "vm/jit/emit-common.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/linenumbertable.h"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher-common.h"
63 #include "vm/jit/reg.h"
64 #include "vm/jit/replace.h"
65 #include "vm/jit/stacktrace.h"
66 #include "vm/jit/trap.h"
67
68 #include "vmcore/loader.h"
69 #include "vmcore/options.h"
70
71 #if defined(ENABLE_LSRA)
72 # include "vm/jit/allocator/lsra.h"
73 #endif
74
75
76 /* codegen_emit ****************************************************************
77
78    Generates machine code.
79
80 *******************************************************************************/
81
82 bool codegen_emit(jitdata *jd)
83 {
84         methodinfo         *m;
85         codeinfo           *code;
86         codegendata        *cd;
87         registerdata       *rd;
88         s4                  len, s1, s2, s3, d, disp;
89         ptrint              a;
90         varinfo            *var;
91         basicblock         *bptr;
92         instruction        *iptr;
93         u2                  currentline;
94         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
95         unresolved_method  *um;
96         builtintable_entry *bte;
97         methoddesc         *md;
98         s4                  fieldtype;
99         s4                  varindex;
100         unresolved_field   *uf;
101         fieldinfo          *fi;
102
103         /* get required compiler data */
104
105         m    = jd->m;
106         code = jd->code;
107         cd   = jd->cd;
108         rd   = jd->rd;
109
110         /* prevent compiler warnings */
111
112         d   = 0;
113         lm  = NULL;
114         um  = NULL;
115         bte = NULL;
116         uf  = NULL;
117
118         {
119         s4 i, p, t, l;
120         s4 savedregs_num;
121
122         savedregs_num = 0;
123
124         /* space to save used callee saved registers */
125
126         savedregs_num += (INT_SAV_CNT - rd->savintreguse);
127         savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
128
129         cd->stackframesize = rd->memuse + savedregs_num;
130
131 #if defined(ENABLE_THREADS)
132         /* space to save argument of monitor_enter and Return Values to survive */
133     /* monitor_exit. The stack position for the argument can not be shared  */
134         /* with place to save the return register on PPC64, since both values     */
135         /* reside in R3 */
136         if (checksync && code_is_synchronized(code)) {
137                 /* reserve 2 slots for long/double return values for monitorexit */
138                 cd->stackframesize += 2;
139         }
140
141 #endif
142
143         /* create method header */
144
145         /* align stack to 16-bytes */
146
147 /* FIXME */
148 /*      if (!m->isleafmethod || opt_verbosecall) */
149 /*              stackframesize = (stackframesize + 3) & ~3;
150 */
151 /*      else if (m->isleafmethod && (stackframesize == LA_WORD_SIZE)) */
152 /*              stackframesize = 0; */
153
154         (void) dseg_add_unique_address(cd, code);                      /* CodeinfoPointer */
155         (void) dseg_add_unique_s4(cd, cd->stackframesize * 8);             /* FrameSize       */
156
157         code->synchronizedoffset = rd->memuse * 8;
158
159         /* REMOVEME: We still need it for exception handling in assembler. */
160
161         if (code_is_leafmethod(code))
162                 (void) dseg_add_unique_s4(cd, 1);
163         else
164                 (void) dseg_add_unique_s4(cd, 0);
165
166         (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave         */
167         (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave         */
168
169         /* create stack frame (if necessary) */
170
171         if (!code_is_leafmethod(code)) {
172                 M_MFLR(REG_ZERO);
173                 M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
174         }
175
176         if (cd->stackframesize)
177                 M_STDU(REG_SP, REG_SP, -cd->stackframesize * 8);
178
179         /* save return address and used callee saved registers */
180
181         p = cd->stackframesize;
182         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
183                 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
184         }
185         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
186                 p --; M_DST(rd->savfltregs[i], REG_SP, p * 8);
187         }
188
189         /* take arguments out of register or stack frame */
190
191         md = m->parseddesc;
192
193         for (p = 0, l = 0; p < md->paramcount; p++) {
194                 t = md->paramtypes[p].type;
195                 varindex = jd->local_map[l*5 + t];
196                 l++;
197                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
198                         l++;
199                 if (varindex == UNUSED)
200                         continue;
201
202                 var = VAR(varindex);
203                 s1  = md->params[p].regoff;
204
205                 if (IS_INT_LNG_TYPE(t)) {
206                         if (!md->params[p].inmemory) {
207                                 if (!IS_INMEMORY(var->flags))
208                                         M_INTMOVE(s1, var->vv.regoff);
209                                 else
210                                         M_LST(s1, REG_SP, var->vv.regoff);
211                         }
212                         else {
213                                 if (!IS_INMEMORY(var->flags))
214                                         M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
215                                 else
216                                         var->vv.regoff = cd->stackframesize * 8 + s1;
217                         }
218                 }
219                 else {
220                         if (!md->params[p].inmemory) {
221                                 if (!IS_INMEMORY(var->flags))
222                                         M_FLTMOVE(s1, var->vv.regoff);
223                                 else
224                                         M_DST(s1, REG_SP, var->vv.regoff);
225                         }
226                         else {
227                                 if (!(var->flags & INMEMORY)) {
228                                         if (IS_2_WORD_TYPE(t))
229                                                 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
230                                         else
231                                                 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
232                                 }
233                                 else
234                                         var->vv.regoff = cd->stackframesize * 8 + s1;
235                         }
236                 }
237         }
238
239         /* save monitorenter argument */
240
241 #if defined(ENABLE_THREADS)
242
243         if (checksync && code_is_synchronized(code)) {
244
245                 /* stackoffset for argument used for LOCK_monitor_exit */
246                 s1 = rd->memuse;
247
248 #if !defined (NDEBUG)
249                 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
250                         M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP);
251
252                         for (p = 0; p < INT_ARG_CNT; p++)
253                                 M_LST(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
254
255                         for (p = 0; p < FLT_ARG_CNT; p++)
256                                 M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
257
258                         /* used for LOCK_monitor_exit, adopt size because we created another stackframe */
259                         s1 += (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT);
260                 }
261 #endif
262
263                 p = dseg_add_functionptr(cd, LOCK_monitor_enter);
264                 M_ALD(REG_ITMP3, REG_PV, p);
265                 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
266                 M_MTCTR(REG_ITMP3);
267
268                 /* get or test the lock object */
269
270                 if (m->flags & ACC_STATIC) {
271                         p = dseg_add_address(cd, &m->clazz->object.header);
272                         M_ALD(REG_A0, REG_PV, p);
273                 }
274                 else {
275                         M_TST(REG_A0);
276                         M_BNE(1);
277                         M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
278                 }
279
280                 M_AST(REG_A0, REG_SP, s1 * 8);                      /* rd->memuse * 8 */
281                 M_JSR;
282
283 #if !defined(NDEBUG)
284                 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
285                         for (p = 0; p < INT_ARG_CNT; p++)
286                                 M_LLD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
287
288                         for (p = 0; p < FLT_ARG_CNT; p++)
289                                 M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
290
291                         M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP);
292                 }
293 #endif
294         }
295 #endif
296
297         /* call trace function */
298 #if !defined (NDEBUG)
299         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
300                 emit_verbosecall_enter(jd);
301 #endif
302
303         }
304
305         /* end of header generation */
306
307         /* create replacement points */
308          
309         REPLACEMENT_POINTS_INIT(cd, jd);
310
311         /* walk through all basic blocks */
312
313         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
314
315                 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
316
317                 if (bptr->flags >= BBREACHED) {
318
319                 /* branch resolving */
320                 codegen_resolve_branchrefs(cd, bptr);
321
322                 /* handle replacement points */
323
324                 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
325
326                 /* copy interface registers to their destination */
327
328                 len = bptr->indepth;
329                 MCODECHECK(128+len);
330
331 #if defined(ENABLE_LSRA)
332                 if (opt_lsra) {
333                         while (len) {
334                                 len--;
335                                 var = VAR(bptr->invars[len]);
336                                 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
337                                         /* d = reg_of_var(m, var, REG_ITMP1); */
338                                         if (!(var->flags & INMEMORY))
339                                                 d = var->vv.regoff;
340                                         else
341                                                 d = REG_ITMP1;
342                                         M_INTMOVE(REG_ITMP1, d);
343                                         emit_store(jd, NULL, var, d);
344                                 }
345                         }
346                 } else {
347 #endif
348                 while (len) {
349                         len--;
350                         var = VAR(bptr->invars[len]);
351                         if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
352                                 d = codegen_reg_of_var(0, var, REG_ITMP1);
353                                 M_INTMOVE(REG_ITMP1, d);
354                                 emit_store(jd, NULL, var, d);
355                         } 
356                         else {
357                                 assert((var->flags & INOUT));
358                         }
359                 }
360
361 #if defined(ENABLE_LSRA)
362                 }
363 #endif
364                 /* walk through all instructions */
365                 
366                 len = bptr->icount;
367                 currentline = 0;
368                         
369                 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
370                         if (iptr->line != currentline) {
371                                 linenumbertable_list_entry_add(cd, iptr->line);
372                                 currentline = iptr->line;
373                         }
374
375                         MCODECHECK(128);   /* an instruction usually needs < 64 words      */
376
377                 switch (iptr->opc) {
378                 case ICMD_NOP:        /* ...  ==> ...                                 */
379                 case ICMD_POP:        /* ..., value  ==> ...                          */
380                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
381                         break;
382
383                 case ICMD_INLINE_START:
384
385                         REPLACEMENT_POINT_INLINE_START(cd, iptr);
386                         break;
387
388                 case ICMD_INLINE_BODY:
389          
390                         REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
391                         linenumbertable_list_entry_add_inline_start(cd, iptr);
392                         linenumbertable_list_entry_add(cd, iptr->line);
393                         break;
394
395                 case ICMD_INLINE_END:
396
397                         linenumbertable_list_entry_add_inline_end(cd, iptr);
398                         linenumbertable_list_entry_add(cd, iptr->line);
399                         break;
400
401                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
402
403                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
404                         M_TST(s1);
405                         M_BEQ(0);
406                         emit_nullpointer_check(cd, iptr, s1);
407                         break;
408
409                 /* constant operations ************************************************/
410
411                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
412
413                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
414                         ICONST(d, iptr->sx.val.i);
415                         emit_store_dst(jd, iptr, d);
416                         break;
417
418                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
419
420                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
421                         LCONST(d, iptr->sx.val.l);
422                         emit_store_dst(jd, iptr, d);
423                         break;
424
425                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
426
427                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
428                         a = dseg_add_float(cd, iptr->sx.val.f);
429                         M_FLD(d, REG_PV, a);
430                         emit_store_dst(jd, iptr, d);
431                         break;
432                         
433                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
434
435                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
436                         a = dseg_add_double(cd, iptr->sx.val.d);
437                         M_DLD(d, REG_PV, a);
438                         emit_store_dst(jd, iptr, d);
439                         break;
440
441                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
442
443                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
444
445                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
446                                 disp = dseg_add_unique_address(cd, iptr->sx.val.c.ref);
447                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
448                                                                         iptr->sx.val.c.ref,
449                                                                     disp);
450                         } else  {
451                                 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
452                         }
453                         M_ALD(d, REG_PV, disp);
454                         emit_store_dst(jd, iptr, d);
455                         break;
456
457
458                 /* load/store/copy/move operations ************************************/
459
460                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
461                 case ICMD_ALOAD:      /* s1.localindex = local variable               */
462                 case ICMD_LLOAD:
463                 case ICMD_FLOAD:
464                 case ICMD_DLOAD:
465                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
466                 case ICMD_LSTORE:
467                 case ICMD_FSTORE:
468                 case ICMD_DSTORE:
469                 case ICMD_COPY:
470                 case ICMD_MOVE:
471
472                         emit_copy(jd, iptr);
473                         break;
474
475                 case ICMD_ASTORE:
476                         if (!(iptr->flags.bits & INS_FLAG_RETADDR))
477                                 emit_copy(jd, iptr);
478                         break;
479
480
481                 /* integer operations *************************************************/
482
483                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
484                         s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
485                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
486                         M_NEG(s1, d);
487                         M_EXTSW(d, d);
488                         emit_store_dst(jd, iptr, d);
489                         break;
490
491                 case ICMD_LNEG:    
492                         s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
493                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
494                         M_NEG(s1, d);
495                         emit_store_dst(jd, iptr, d);
496                         break;
497
498
499                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
500
501                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
502                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
503                         M_INTMOVE(s1, d);
504                         emit_store_dst(jd, iptr, d);
505                         break;
506
507                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
508
509                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
510                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
511                         M_ISEXT(s1, d); 
512                         emit_store_dst(jd, iptr, d);
513                         break;
514
515                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
516
517                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
518                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
519                         M_BSEXT(s1, d);
520                         emit_store_dst(jd, iptr, d);
521                         break;
522
523                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
524
525                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
526                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
527                         M_CZEXT(s1, d);
528                         emit_store_dst(jd, iptr, d);
529                         break;
530
531                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
532
533                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
534                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
535                         M_SSEXT(s1, d);
536                         emit_store_dst(jd, iptr, d);
537                         break;
538
539
540                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
541
542                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
543                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
544                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
545                         M_IADD(s1, s2, d);
546                         M_EXTSW(d,d);
547                         emit_store_dst(jd, iptr, d);
548                         break;
549
550                 case ICMD_IINC:
551                 case ICMD_IADDCONST:
552
553                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
554                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
555                         if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) {
556                                 M_IADD_IMM(s1, iptr->sx.val.i, d);
557                         } else {
558                                 ICONST(REG_ITMP2, iptr->sx.val.i);
559                                 M_IADD(s1, REG_ITMP2, d);
560                         }
561                         M_EXTSW(d,d);
562                         emit_store_dst(jd, iptr, d);
563                         break;
564
565                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
566
567                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
568                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
569                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
570                         M_LADD(s1, s2, d);
571                         emit_store_dst(jd, iptr, d);
572                         break;
573
574                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
575                                       /* sx.val.l = constant                          */
576
577                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
578                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
579                         /* XXX check me */
580                         if ((iptr->sx.val.l >= -32768) && (iptr->sx.val.l <= 32767)) {
581                                 M_LADD_IMM(s1, iptr->sx.val.l, d);
582                         } else {
583                                 LCONST(REG_ITMP2, iptr->sx.val.l);
584                                 M_LADD(s1, REG_ITMP2, d);
585                         }
586                         emit_store_dst(jd, iptr, d);
587                         break;
588
589                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
590
591                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
592                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
593                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
594                         M_SUB(s1, s2, d);
595                         M_EXTSW(d, d);
596                         emit_store_dst(jd, iptr, d);
597                         break;
598
599                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
600                                       /* sx.val.i = constant                          */
601
602                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
603                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
604                         if ((iptr->sx.val.i >= -32767) && (iptr->sx.val.i <= 32768)) {
605                                 M_IADD_IMM(s1, -iptr->sx.val.i, d);
606                         } else {
607                                 ICONST(REG_ITMP2, iptr->sx.val.i);
608                                 M_SUB(s1, REG_ITMP2, d);
609                         }
610                         M_EXTSW(d, d);
611                         emit_store_dst(jd, iptr, d);
612                         break;
613
614                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
615
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                         M_SUB(s1, s2, d);
620                         emit_store_dst(jd, iptr, d);
621                         break;
622
623                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
624                                       /* sx.val.l = constant                          */
625
626                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
627                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
628                         /* XXX check me */
629                         if ((iptr->sx.val.l >= -32767) && (iptr->sx.val.l <= 32767)) {
630                                 M_LADD_IMM(s1, -iptr->sx.val.l, d);
631                         } else {
632                                 LCONST(REG_ITMP2, iptr->sx.val.l);
633                                 M_SUB(s1, REG_ITMP2, d);
634                         }
635                         emit_store_dst(jd, iptr, d);
636                         break;
637
638                 case ICMD_IDIV:
639                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
640                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
641                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
642                         emit_arithmetic_check(cd, iptr, s2);
643
644                         M_DIV(s1, s2, d);
645                         M_EXTSW(d, d);
646                         emit_store_dst(jd, iptr, d);
647                         break;
648
649                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
650
651                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
652                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
653                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
654                         emit_arithmetic_check(cd, iptr, s2);
655
656                         M_DIV(s1, s2, d);
657                         /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
658                         /* we only need to check this if we did a LDIV, not for IDIV */
659                         M_MFXER(REG_ITMP2);
660                         M_ANDIS(REG_ITMP2, 0x4000, REG_ITMP2);  /* test OV */
661                         M_BLE(1);
662                         M_MOV(s1, d);                           /* java specs says result == dividend */
663                         emit_store_dst(jd, iptr, d);
664                         break;
665
666                 case ICMD_IREM:
667                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
668                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
669                         emit_arithmetic_check(cd, iptr, s2);
670
671                         M_DIV(s1, s2,  REG_ITMP3);      
672                         M_MUL(REG_ITMP3, s2, REG_ITMP2);
673                         M_SUB(s1, REG_ITMP2,  REG_ITMP3);
674                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
675
676                         M_MOV(REG_ITMP3, d);
677                         emit_store_dst(jd, iptr, d);
678                         break;
679
680
681                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
682                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
683                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
684                         emit_arithmetic_check(cd, iptr, s2);
685
686                         M_DIV(s1, s2,  REG_ITMP3);      
687                         /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
688                         /* we only need to check this if we did a LDIV, not for IDIV */
689                         M_MFXER(REG_ITMP2);
690                         M_ANDIS(REG_ITMP2, 0x4000, REG_ITMP2);  /* test OV */
691                         M_BLE(2); 
692                         LCONST(REG_ITMP3, 0);                   /* result == 0 in this case */
693                         M_BR(2);
694                         M_MUL(REG_ITMP3, s2, REG_ITMP2);
695                         M_SUB(s1, REG_ITMP2,  REG_ITMP3);
696                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
697
698                         M_MOV(REG_ITMP3, d);
699                         emit_store_dst(jd, iptr, d);
700                         break;
701
702                 
703                 case ICMD_IMUL:       /* ..., 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_ITMP2);
707                         M_MUL(s1, s2, d);
708                         M_EXTSW(d, d);
709                         emit_store_dst(jd, iptr, d);
710                         break;
711
712                 case ICMD_LMUL:
713                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
714                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
715                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
716                         M_MUL(s1, s2, d);
717                         emit_store_dst(jd, iptr, d);
718                         break;
719
720                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
721                                       /* sx.val.i = constant                          */
722
723                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
724                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
725                         if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
726                                 M_MUL_IMM(s1, iptr->sx.val.i, d);
727                         else {
728                                 ICONST(REG_ITMP3, iptr->sx.val.i);
729                                 M_MUL(s1, REG_ITMP3, d);
730                         }
731                         M_EXTSW(d, d);
732                         emit_store_dst(jd, iptr, d);
733                         break;
734                 case ICMD_LMULCONST:
735                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
736                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
737                         if ((iptr->sx.val.l >= -32767) && (iptr->sx.val.l <= 32767))
738                                 M_MUL_IMM(s1, iptr->sx.val.l, d);
739                         else {
740                                 LCONST(REG_ITMP3, iptr->sx.val.l);
741                                 M_MUL(s1, REG_ITMP3, d);
742                         }
743                         emit_store_dst(jd, iptr, d);
744                         break;
745
746                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
747                       
748                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
749                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
750                         M_SRA_IMM(s1, iptr->sx.val.i, d);
751                         M_ADDZE(d, d);
752                         M_EXTSW(d, d);
753                         emit_store_dst(jd, iptr, d);
754                         break;
755
756                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
757
758                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
759                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
760                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
761                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
762                         M_SLL(s1, REG_ITMP3, d);
763                         M_EXTSW(d, d);
764                         emit_store_dst(jd, iptr, d);
765                         break;
766
767                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
768                                       /* sx.val.i = constant                             */
769
770                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
771                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
772                         M_SLL_IMM(s1, iptr->sx.val.i & 0x1f, d);
773                         M_EXTSW(d,d);
774                         emit_store_dst(jd, iptr, d);
775                         break;
776
777                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
778
779                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
780                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
781                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
782                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
783                         M_SRA(s1, REG_ITMP3, d);
784                         emit_store_dst(jd, iptr, d);
785                         break;
786
787                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
788                                       /* sx.val.i = constant                             */
789
790                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
791                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
792                         M_SRA_IMM(s1, iptr->sx.val.i & 0x1f, d);
793                         emit_store_dst(jd, iptr, d);
794                         break;
795
796                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
797
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_AND_IMM(s2, 0x1f, REG_ITMP2);
802                         M_MOV(s1, REG_ITMP1);
803                         M_CLR_HIGH(REG_ITMP1);
804                         M_SRL(REG_ITMP1, REG_ITMP2, d);
805                         M_EXTSW(d,d);   /* for the case it was shift 0 bits */
806                         emit_store_dst(jd, iptr, d);
807                         break;
808
809                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
810                                       /* sx.val.i = constant                             */
811
812                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
813                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
814                         if (iptr->sx.val.i & 0x1f) {
815                                 M_MOV(s1, REG_ITMP1);
816                                 M_CLR_HIGH(REG_ITMP1);
817                                 M_SRA_IMM(REG_ITMP1, iptr->sx.val.i & 0x1f, d);
818                         } else {
819                                 M_INTMOVE(s1, d);
820                         }
821                         emit_store_dst(jd, iptr, d);
822                         break;
823         
824                 case ICMD_LSHLCONST:
825                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
826                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
827                         M_SLL_IMM(s1, iptr->sx.val.i & 0x3f, d);
828                         emit_store_dst(jd, iptr, d);
829                         break;
830                 case ICMD_LSHL:
831                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
832                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
833                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
834                         M_AND_IMM(s2, 0x3f, REG_ITMP2);
835                         M_SLL(s1, REG_ITMP2, d);
836                         emit_store_dst(jd, iptr, d);
837                         break;
838                 case ICMD_LSHRCONST:
839                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
840                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
841                         M_SRA_IMM(s1, iptr->sx.val.i & 0x3f, d);
842                         emit_store_dst(jd, iptr, d);
843                         break;
844                 case ICMD_LSHR:
845                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
846                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
847                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
848                         M_AND_IMM(s2, 0x3f, REG_ITMP2);
849                         M_SRA(s1, REG_ITMP2, d);
850                         emit_store_dst(jd, iptr, d);
851                         break;
852                 case ICMD_LUSHRCONST:
853                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
854                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
855                         M_SRL_IMM(s1, iptr->sx.val.i & 0x3f, d);
856                         emit_store_dst(jd, iptr, d);
857                         break;
858                 case ICMD_LUSHR:
859                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
860                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
861                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
862                         M_AND_IMM(s2, 0x3f, REG_ITMP2);
863                         M_SRL(s1, REG_ITMP2, d);
864                         emit_store_dst(jd, iptr, d);
865                         break;
866
867                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
868                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
869                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
870                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
871                         M_AND(s1, s2, d);
872 /*                      M_EXTSW(d, d);*/
873                         emit_store_dst(jd, iptr, d);
874                         break;
875
876                 case ICMD_LAND:
877                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
878                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
879                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
880                         M_AND(s1, s2, d);
881                         emit_store_dst(jd, iptr, d);
882                         break;
883
884                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
885                                       /* sx.val.i = constant                          */
886
887                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
888                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
889                         if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535)) {
890                                 M_AND_IMM(s1, iptr->sx.val.i, d);
891                                 }
892                         /*
893                         else if (iptr->sx.val.i == 0xffffff) {
894                                 M_RLWINM(s1, 0, 8, 31, d);
895                                 }
896                         */
897                         else {
898                                 ICONST(REG_ITMP3, iptr->sx.val.i);
899                                 M_AND(s1, REG_ITMP3, d);
900                         }
901                         emit_store_dst(jd, iptr, d);
902                         break;
903
904                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
905                                       /* sx.val.l = constant                          */
906
907                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
908                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
909                         if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
910                                 M_AND_IMM(s1, iptr->sx.val.l, d);
911                         /*
912                         else if (iptr->sx.val.l == 0xffffff) {
913                                 M_RLWINM(s1, 0, 8, 31, d);
914                                 }
915                         */
916                         else {
917                                 LCONST(REG_ITMP3, iptr->sx.val.l);
918                                 M_AND(s1, REG_ITMP3, d);
919                         }
920                         emit_store_dst(jd, iptr, d);
921                         break;
922
923                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
924                                       /* sx.val.i = constant                             */
925                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
926                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
927 #if 0
928                         /* fast division, result in REG_ITMP3) */
929                         M_SRA_IMM(s1, iptr->sx.val.i, REG_ITMP3);
930                         M_ADDZE(REG_ITMP3, REG_ITMP3);
931
932                         M_SUB(s1, REG_ITMP3, d);
933                         M_EXTSW(d, d);
934                         emit_store_dst(jd, iptr, d);
935                         break;
936 #else
937                         
938                         M_MOV(s1, REG_ITMP2);
939                         M_CMPI(s1, 0);
940                         M_BGE(1 + 3*(iptr->sx.val.i >= 32768));
941                         if (iptr->sx.val.i >= 32768) {
942                                 M_ADDIS(REG_ZERO, iptr->sx.val.i >> 16, REG_ITMP2);
943                                 M_EXTSW(REG_ITMP2, REG_ITMP2);
944                                 M_OR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2);
945                                 M_IADD(s1, REG_ITMP2, REG_ITMP2);
946                         } else {
947                                 M_IADD_IMM(s1, iptr->sx.val.i, REG_ITMP2);
948                         }
949                         {
950                                 int b=0, m = iptr->sx.val.i;
951                                 while (m >>= 1)
952                                         ++b;
953                                 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
954                         }
955                         M_SUB(s1, REG_ITMP2, d);
956                         M_EXTSW(d, d);
957                         emit_store_dst(jd, iptr, d);
958                         break;
959 #endif
960
961                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
962                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
963                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
964                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
965                         M_OR(s1, s2, d);
966 /*                      M_EXTSW(d,d);*/
967                         emit_store_dst(jd, iptr, d);
968                         break;
969
970                 case ICMD_LOR:
971
972                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
973                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
974                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
975                         M_OR(s1, s2, d);
976                         emit_store_dst(jd, iptr, d);
977                         break;
978
979                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
980                                       /* sx.val.i = constant                          */
981
982                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
983                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
984                         if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
985                                 M_OR_IMM(s1, iptr->sx.val.i, d);
986                         else {
987                                 ICONST(REG_ITMP3, iptr->sx.val.i);
988                                 M_OR(s1, REG_ITMP3, d);
989                         }
990                         emit_store_dst(jd, iptr, d);
991                         break;
992
993                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
994                                       /* sx.val.l = constant                          */
995
996                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
997                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
998                         if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
999                                 M_OR_IMM(s1, iptr->sx.val.l, d);
1000                         else {
1001                                 LCONST(REG_ITMP3, iptr->sx.val.l);
1002                                 M_OR(s1, REG_ITMP3, d);
1003                         }
1004                         emit_store_dst(jd, iptr, d);
1005                         break;
1006
1007
1008                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1009                 case ICMD_LXOR:
1010
1011                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1012                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1013                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1014                         M_XOR(s1, s2, d);
1015                         emit_store_dst(jd, iptr, d);
1016                         break;
1017
1018                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1019                                       /* sx.val.i = constant                          */
1020
1021                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1022                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1023                         if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
1024                                 M_XOR_IMM(s1, iptr->sx.val.i, d);
1025                         else {
1026                                 ICONST(REG_ITMP3, iptr->sx.val.i);
1027                                 M_XOR(s1, REG_ITMP3, d);
1028                         }
1029                         emit_store_dst(jd, iptr, d);
1030                         break;
1031
1032                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1033                                       /* sx.val.l = constant                          */
1034
1035                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1036                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1037                         if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
1038                                 M_XOR_IMM(s1, iptr->sx.val.l, d);
1039                         else {
1040                                 LCONST(REG_ITMP3, iptr->sx.val.l);
1041                                 M_XOR(s1, REG_ITMP3, d);
1042                         }
1043                         emit_store_dst(jd, iptr, d);
1044                         break;
1045
1046                 case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
1047
1048                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1049                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1050                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1051                         /* XXX implement me!!! */
1052                         vm_abort("codegen: implement ICMD_LCMP!");
1053                         emit_store_dst(jd, iptr, d);
1054                         break;
1055                         break;
1056
1057
1058                 /* floating operations ************************************************/
1059
1060                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1061
1062                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1063                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1064                         M_FMOVN(s1, d);
1065                         emit_store_dst(jd, iptr, d);
1066                         break;
1067
1068                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1069
1070                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1071                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1072                         M_FMOVN(s1, d);
1073                         emit_store_dst(jd, iptr, d);
1074                         break;
1075
1076                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1077
1078                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1079                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1080                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1081                         M_FADD(s1, s2, d);
1082                         emit_store_dst(jd, iptr, d);
1083                         break;
1084
1085                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1086
1087                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1088                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1089                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1090                         M_DADD(s1, s2, d);
1091                         emit_store_dst(jd, iptr, d);
1092                         break;
1093
1094                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1095
1096                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1097                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1098                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1099                         M_FSUB(s1, s2, d);
1100                         emit_store_dst(jd, iptr, d);
1101                         break;
1102
1103                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1104
1105                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1106                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1107                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1108                         M_DSUB(s1, s2, d);
1109                         emit_store_dst(jd, iptr, d);
1110                         break;
1111
1112                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1113
1114                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1115                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1116                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1117                         M_FMUL(s1, s2, d);
1118                         emit_store_dst(jd, iptr, d);
1119                         break;
1120
1121                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1122
1123                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1124                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1125                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1126                         M_DMUL(s1, s2, d);
1127                         emit_store_dst(jd, iptr, d);
1128                         break;
1129
1130                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1131
1132                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1133                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1134                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1135                         M_FDIV(s1, s2, d);
1136                         emit_store_dst(jd, iptr, d);
1137                         break;
1138
1139                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1140
1141                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1142                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1143                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1144                         M_DDIV(s1, s2, d);
1145                         emit_store_dst(jd, iptr, d);
1146                         break;
1147                 
1148                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1149                 case ICMD_D2I:
1150
1151                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1152                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1153                         M_CLR(d);
1154                         disp = dseg_add_float(cd, 0.0);
1155                         M_FLD(REG_FTMP2, REG_PV, disp);
1156                         M_FCMPU(s1, REG_FTMP2);
1157                         M_BNAN(4);
1158                         disp = dseg_add_unique_s4(cd, 0);
1159                         M_CVTDL_C(s1, REG_FTMP1);
1160                         M_LDA(REG_ITMP1, REG_PV, disp);
1161                         M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1162                         M_ILD(d, REG_PV, disp);
1163                         emit_store_dst(jd, iptr, d);
1164                         break;
1165                 
1166                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1167
1168                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1169                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1170                         M_FLTMOVE(s1, d);
1171                         emit_store_dst(jd, iptr, d);
1172                         break;
1173                                         
1174                 case ICMD_D2F:       /* ..., value  ==> ..., (double) value           */
1175
1176                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1177                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1178                         M_CVTDF(s1, d);
1179                         emit_store_dst(jd, iptr, d);
1180                         break;
1181                 
1182                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1183                 case ICMD_DCMPL:      /* == => 0, < => 1, > => -1                     */
1184
1185                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1186                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1187                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1188                         M_FCMPU(s2, s1);
1189                         M_IADD_IMM(REG_ZERO, -1, d);
1190                         M_BNAN(4);
1191                         M_BGT(3);
1192                         M_IADD_IMM(REG_ZERO, 0, d);
1193                         M_BGE(1);
1194                         M_IADD_IMM(REG_ZERO, 1, d);
1195                         emit_store_dst(jd, iptr, d);
1196                         break;
1197
1198                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1199                 case ICMD_DCMPG:      /* == => 0, < => 1, > => -1                     */
1200
1201                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1202                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1203                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1204                         M_FCMPU(s1, s2);
1205                         M_IADD_IMM(REG_ZERO, 1, d);
1206                         M_BNAN(4);
1207                         M_BGT(3);
1208                         M_IADD_IMM(REG_ZERO, 0, d);
1209                         M_BGE(1);
1210                         M_IADD_IMM(REG_ZERO, -1, d);
1211                         emit_store_dst(jd, iptr, d);
1212                         break;
1213
1214                         
1215                 /* memory operations **************************************************/
1216
1217                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1218
1219                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1220                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1221                         emit_nullpointer_check(cd, iptr, s1);
1222                         M_ILD(d, s1, OFFSET(java_array_t, size));
1223                         emit_store_dst(jd, iptr, d);
1224                         break;
1225
1226                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1227
1228                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1229                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1230                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1231                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1232                         M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1233                         /* implicit null-pointer check */
1234                         M_LBZX(d, s1, REG_ITMP2);
1235                         M_BSEXT(d, d);
1236                         emit_store_dst(jd, iptr, d);
1237                         break;                  
1238
1239                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1240
1241                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1242                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1243                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1244                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1245                         M_SLL_IMM(s2, 1, REG_ITMP2);
1246                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1247                         /* implicit null-pointer check */
1248                         M_LHZX(d, s1, REG_ITMP2);
1249                         emit_store_dst(jd, iptr, d);
1250                         break;
1251
1252                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1253
1254                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1255                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1256                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1257                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1258                         M_SLL_IMM(s2, 1, REG_ITMP2);
1259                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1260                         /* implicit null-pointer check */
1261                         M_LHAX(d, s1, REG_ITMP2);
1262                         emit_store_dst(jd, iptr, d);
1263                         break;
1264
1265                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1266
1267                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1268                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1269                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1270                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1271                         M_SLL_IMM(s2, 2, REG_ITMP2);
1272                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1273                         /* implicit null-pointer check */
1274                         M_LWAX(d, s1, REG_ITMP2);
1275                         emit_store_dst(jd, iptr, d);
1276                         break;
1277
1278                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1279
1280                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1281                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1282                         d = codegen_reg_of_dst(jd, iptr, PACK_REGS(REG_ITMP2, REG_ITMP1));
1283                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1284                         M_SLL_IMM(s2, 3, REG_ITMP2);
1285                         M_IADD(s1, REG_ITMP2, REG_ITMP2);
1286                         /* implicit null-pointer check */
1287                         M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray_t, data[0]));
1288                         emit_store_dst(jd, iptr, d);
1289                         break;
1290
1291                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1292
1293                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1294                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1295                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1296                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1297                         M_SLL_IMM(s2, 2, REG_ITMP2);
1298                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1299                         /* implicit null-pointer check */
1300                         M_LFSX(d, s1, REG_ITMP2);
1301                         emit_store_dst(jd, iptr, d);
1302                         break;
1303
1304                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1305
1306                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1307                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1308                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1309                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1310                         M_SLL_IMM(s2, 3, REG_ITMP2);
1311                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1312                         /* implicit null-pointer check */
1313                         M_LFDX(d, s1, REG_ITMP2);
1314                         emit_store_dst(jd, iptr, d);
1315                         break;
1316
1317                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1318
1319                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1320                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1321                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1322                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1323                         M_SLL_IMM(s2, 3, REG_ITMP2);
1324                         M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
1325                         /* implicit null-pointer check */
1326                         M_ALDX(d, s1, REG_ITMP2);
1327                         emit_store_dst(jd, iptr, d);
1328                         break;
1329
1330
1331                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1332
1333                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1334                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1335                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1336                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1337                         M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
1338                         /* implicit null-pointer check */
1339                         M_STBX(s3, s1, REG_ITMP2);
1340                         break;
1341
1342                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1343
1344                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1345                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1346                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1347                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1348                         M_SLL_IMM(s2, 1, REG_ITMP2);
1349                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
1350                         /* implicit null-pointer check */
1351                         M_STHX(s3, s1, REG_ITMP2);
1352                         break;
1353
1354                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1355
1356                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1357                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1358                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1359                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1360                         M_SLL_IMM(s2, 1, REG_ITMP2);
1361                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
1362                         M_STHX(s3, s1, REG_ITMP2);
1363                         break;
1364
1365                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1366
1367                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1368                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1369                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1370                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1371                         M_SLL_IMM(s2, 2, REG_ITMP2);
1372                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
1373                         /* implicit null-pointer check */
1374                         M_STWX(s3, s1, REG_ITMP2);
1375                         break;
1376
1377                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1378
1379                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1380                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1381                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1382                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1383                         M_SLL_IMM(s2, 3, REG_ITMP2);
1384                         M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray_t, data[0]), REG_ITMP2);
1385                         /* implicit null-pointer check */
1386                         M_LSTX(s3, s1, REG_ITMP2);
1387                         break;
1388
1389                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1390
1391                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1392                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1393                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1394                         s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1395                         M_SLL_IMM(s2, 2, REG_ITMP2);
1396                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
1397                         /* implicit null-pointer check */
1398                         M_STFSX(s3, s1, REG_ITMP2);
1399                         break;
1400
1401                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1402
1403                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1404                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1405                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1406                         s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1407                         M_SLL_IMM(s2, 3, REG_ITMP2);
1408                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
1409                         /* implicit null-pointer check */
1410                         M_STFDX(s3, s1, REG_ITMP2);
1411                         break;
1412
1413                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1414
1415                         s1 = emit_load_s1(jd, iptr, REG_A0);
1416                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1417                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1418                         s3 = emit_load_s3(jd, iptr, REG_A1);
1419
1420                         disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1421                         M_ALD(REG_ITMP3, REG_PV, disp);
1422                         M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
1423                         M_MTCTR(REG_ITMP3);
1424
1425                         M_INTMOVE(s1, REG_A0);
1426                         M_INTMOVE(s3, REG_A1);
1427
1428                         M_JSR;
1429                         emit_arraystore_check(cd, iptr);
1430
1431                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1432                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1433                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1434                         M_SLL_IMM(s2, 3, REG_ITMP2);
1435                         M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
1436                         /* implicit null-pointer check */
1437                         M_ASTX(s3, s1, REG_ITMP2);
1438                         break;
1439
1440
1441                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1442
1443                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1444                                 uf        = iptr->sx.s23.s3.uf;
1445                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1446                                 disp      = dseg_add_unique_address(cd, NULL);
1447
1448                                 patcher_add_patch_ref(jd, PATCHER_get_putstatic,
1449                                                                         iptr->sx.s23.s3.uf, disp);
1450
1451                         }
1452                         else {
1453                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1454                                 fieldtype = fi->type;
1455                                 disp      = dseg_add_address(cd, fi->value);
1456
1457                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
1458                                         patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
1459                                 }
1460                         }
1461
1462                         M_ALD(REG_ITMP1, REG_PV, disp);
1463                         switch (fieldtype) {
1464                         case TYPE_INT:
1465                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1466                                 M_ILD_INTERN(d, REG_ITMP1, 0);
1467                                 break;
1468                         case TYPE_LNG:
1469                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1470                                 M_LLD(d, REG_ITMP1, 0);
1471                                 break;
1472                         case TYPE_ADR:
1473                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1474                                 M_ALD_INTERN(d, REG_ITMP1, 0);
1475                                 break;
1476                         case TYPE_FLT:
1477                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1478                                 M_FLD_INTERN(d, REG_ITMP1, 0);
1479                                 break;
1480                         case TYPE_DBL:                          
1481                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1482                                 M_DLD_INTERN(d, REG_ITMP1, 0);
1483                                 break;
1484                         }
1485                         emit_store_dst(jd, iptr, d);
1486                         break;
1487
1488                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1489
1490
1491                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1492                                 uf        = iptr->sx.s23.s3.uf;
1493                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1494                                 disp      = dseg_add_unique_address(cd, NULL);
1495
1496                                 patcher_add_patch_ref(jd, PATCHER_get_putstatic,
1497                                                                         iptr->sx.s23.s3.uf, disp);
1498                         }
1499                         else {
1500                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1501                                 fieldtype = fi->type;
1502                                 disp      = dseg_add_address(cd, fi->value);
1503
1504                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
1505                                         patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
1506                                 }
1507                         }
1508
1509                         M_ALD(REG_ITMP1, REG_PV, disp);
1510                         switch (fieldtype) {
1511                         case TYPE_INT:
1512                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1513                                 M_IST_INTERN(s1, REG_ITMP1, 0);
1514                                 break;
1515                         case TYPE_LNG:
1516                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1517                                 M_LST_INTERN(s1, REG_ITMP1, 0);
1518                                 break;
1519                         case TYPE_ADR:
1520                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1521                                 M_AST_INTERN(s1, REG_ITMP1, 0);
1522                                 break;
1523                         case TYPE_FLT:
1524                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1525                                 M_FST_INTERN(s1, REG_ITMP1, 0);
1526                                 break;
1527                         case TYPE_DBL:
1528                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1529                                 M_DST_INTERN(s1, REG_ITMP1, 0);
1530                                 break;
1531                         }
1532                         break;
1533
1534
1535                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1536
1537                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1538
1539                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1540                                 uf        = iptr->sx.s23.s3.uf;
1541                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1542                                 disp      = 0;
1543
1544                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1545                         }
1546                         else {
1547                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1548                                 fieldtype = fi->type;
1549                                 disp      = fi->offset;
1550                         }
1551
1552                         /* implicit null-pointer check */
1553                         switch (fieldtype) {
1554                         case TYPE_INT:
1555                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1556                                 M_ILD(d, s1, disp);
1557                                 break;
1558                         case TYPE_LNG:
1559                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1560                                 M_LLD(d, s1, disp);
1561                                 break;
1562                         case TYPE_ADR:
1563                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1564                                 M_ALD(d, s1, disp);
1565                                 break;
1566                         case TYPE_FLT:
1567                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1568                                 M_FLD(d, s1, disp);
1569                                 break;
1570                         case TYPE_DBL:                          
1571                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1572                                 M_DLD(d, s1, disp);
1573                                 break;
1574                         }
1575                         emit_store_dst(jd, iptr, d);
1576                         break;
1577
1578                 case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
1579
1580                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1581
1582                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1583                                 uf        = iptr->sx.s23.s3.uf;
1584                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1585                                 disp      = 0;
1586                         }
1587                         else {
1588                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1589                                 fieldtype = fi->type;
1590                                 disp      = fi->offset;
1591                         }
1592
1593                         if (IS_INT_LNG_TYPE(fieldtype)) {
1594                                 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1595                         }
1596                         else
1597                                 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1598
1599                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1600                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1601                         }
1602
1603
1604                         /* implicit null-pointer check */
1605                         switch (fieldtype) {
1606                         case TYPE_INT:
1607                                 M_IST(s2, s1, disp);
1608                                 break;
1609                         case TYPE_LNG:
1610                                 M_LST(s2, s1, disp);
1611                                 break;
1612                         case TYPE_ADR:
1613                                 M_AST(s2, s1, disp);
1614                                 break;
1615                         case TYPE_FLT:
1616                                 M_FST(s2, s1, disp);
1617                                 break;
1618                         case TYPE_DBL:
1619                                 M_DST(s2, s1, disp);
1620                                 break;
1621                         }
1622                         break;
1623
1624
1625                 /* branch operations **************************************************/
1626
1627                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1628
1629                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1630                         M_LNGMOVE(s1, REG_ITMP1_XPTR);
1631
1632 #ifdef ENABLE_VERIFIER
1633                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1634                                 patcher_add_patch_ref(jd, PATCHER_resolve_class,
1635                                                                         iptr->sx.s23.s2.uc, 0);
1636                         }
1637 #endif /* ENABLE_VERIFIER */
1638
1639                         disp = dseg_add_functionptr(cd, asm_handle_exception);
1640                         M_ALD(REG_ITMP2, REG_PV, disp);
1641                         M_MTCTR(REG_ITMP2);
1642
1643                         if (code_is_leafmethod(code))
1644                                 M_MFLR(REG_ITMP3);                          /* save LR        */
1645
1646                         M_BL(0);                                        /* get current PC */
1647                         M_MFLR(REG_ITMP2_XPC);
1648
1649                         if (code_is_leafmethod(code))
1650                                 M_MTLR(REG_ITMP3);                          /* restore LR     */
1651
1652                         M_RTS;                                          /* jump to CTR    */
1653                         ALIGNCODENOP;
1654                         break;
1655
1656                 case ICMD_GOTO:         /* ... ==> ...                                */
1657                 case ICMD_RET:          /* ... ==> ...                                */
1658
1659                         emit_br(cd, iptr->dst.block);
1660                         ALIGNCODENOP;
1661                         break;
1662
1663                 case ICMD_JSR:          /* ... ==> ...                                */
1664
1665                         emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1666                         ALIGNCODENOP;
1667                         break;
1668
1669                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
1670
1671                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1672                         M_TST(s1);
1673                         emit_beq(cd, iptr->dst.block);
1674                         break;
1675
1676                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
1677
1678                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1679                         M_TST(s1);
1680                         emit_bne(cd, iptr->dst.block);
1681                         break;
1682
1683                 case ICMD_IFLT:
1684                 case ICMD_IFLE:
1685                 case ICMD_IFNE:
1686                 case ICMD_IFGT:
1687                 case ICMD_IFGE:
1688                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
1689
1690                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1691                         if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
1692                                 M_CMPI(s1, iptr->sx.val.i);
1693                         else {
1694                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1695                                 M_CMP(s1, REG_ITMP2);
1696                         }
1697                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1698                         break;
1699                         
1700                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
1701                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1702                         LCONST(REG_ITMP2, iptr->sx.val.l);
1703                         M_CMP(s1, REG_ITMP2);
1704                         emit_beq(cd, iptr->dst.block);
1705                         break;
1706                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
1707                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1708                         LCONST(REG_ITMP2, iptr->sx.val.l);
1709                         M_CMP(s1, REG_ITMP2);
1710                         emit_blt(cd, iptr->dst.block);
1711                         break;
1712                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
1713                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1714                         LCONST(REG_ITMP2, iptr->sx.val.l);
1715                         M_CMP(s1, REG_ITMP2);
1716                         emit_ble(cd, iptr->dst.block);
1717                         break;
1718
1719                 case ICMD_IF_LNE:       /* ..., value ==> ... */
1720                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1721                         LCONST(REG_ITMP2, iptr->sx.val.l);
1722                         M_CMP(s1, REG_ITMP2);
1723                         emit_bne(cd, iptr->dst.block);
1724                         break;
1725                 case ICMD_IF_LGE:       /* ..., value ==> ... */
1726                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1727                         LCONST(REG_ITMP2, iptr->sx.val.l);
1728                         M_CMP(s1, REG_ITMP2);
1729                         emit_bge(cd, iptr->dst.block);
1730                         break;
1731                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
1732                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1733                         LCONST(REG_ITMP2, iptr->sx.val.l);
1734                         M_CMP(s1, REG_ITMP2);
1735                         emit_bgt(cd, iptr->dst.block);
1736                         break;
1737                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
1738                 case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
1739                 case ICMD_IF_LCMPEQ: 
1740
1741                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1742                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1743                         M_CMP(s1, s2);
1744                         emit_beq(cd, iptr->dst.block);
1745                         break;
1746
1747                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
1748                 case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
1749                 case ICMD_IF_LCMPNE:  
1750
1751                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1752                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1753                         M_CMP(s1, s2);
1754                         emit_bne(cd, iptr->dst.block);
1755                         break;
1756
1757
1758                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
1759                 case ICMD_IF_LCMPLT:
1760
1761                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1762                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1763                         M_CMP(s1, s2);
1764                         emit_blt(cd, iptr->dst.block);
1765                         break;
1766
1767                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
1768                 case ICMD_IF_LCMPGT:
1769
1770                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1771                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1772                         M_CMP(s1, s2);
1773                         emit_bgt(cd, iptr->dst.block);
1774                         break;
1775
1776                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
1777                 case ICMD_IF_LCMPLE:
1778
1779                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1780                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1781                         M_CMP(s1, s2);
1782                         emit_ble(cd, iptr->dst.block);
1783                         break;
1784
1785                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
1786                 case ICMD_IF_LCMPGE:
1787
1788                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1789                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1790                         M_CMP(s1, s2);
1791                         emit_bge(cd, iptr->dst.block);
1792                         break;
1793
1794
1795                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
1796                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
1797
1798                         REPLACEMENT_POINT_RETURN(cd, iptr);
1799                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
1800                         M_LNGMOVE(s1, REG_RESULT);
1801                         goto nowperformreturn;
1802
1803                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
1804
1805                         REPLACEMENT_POINT_RETURN(cd, iptr);
1806                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
1807                         M_LNGMOVE(s1, REG_RESULT);
1808
1809 #ifdef ENABLE_VERIFIER
1810                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1811                                 patcher_add_patch_ref(jd, PATCHER_resolve_class,
1812                                                                         iptr->sx.s23.s2.uc, 0);
1813                         }
1814 #endif /* ENABLE_VERIFIER */
1815
1816                         goto nowperformreturn;
1817
1818                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
1819                 case ICMD_DRETURN:
1820
1821                         REPLACEMENT_POINT_RETURN(cd, iptr);
1822                         s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1823                         M_FLTMOVE(s1, REG_FRESULT);
1824                         goto nowperformreturn;
1825
1826                 case ICMD_RETURN:      /* ...  ==> ...                                */
1827
1828                         REPLACEMENT_POINT_RETURN(cd, iptr);
1829
1830 nowperformreturn:
1831                         {
1832                         s4 i, p;
1833                         
1834                         p = cd->stackframesize;
1835
1836                         /* call trace function */
1837
1838 #if !defined(NDEBUG)
1839                         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
1840                                 emit_verbosecall_exit(jd);
1841 #endif          
1842
1843 #if defined(ENABLE_THREADS)
1844                         if (checksync && code_is_synchronized(code)) {
1845                                 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
1846                                 M_ALD(REG_ITMP3, REG_PV, disp);
1847                                 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
1848                                 M_MTCTR(REG_ITMP3);
1849
1850                                 /* we need to save the proper return value */
1851
1852                                 switch (iptr->opc) {
1853                                 case ICMD_LRETURN:
1854                                 case ICMD_IRETURN:
1855                                 case ICMD_ARETURN:
1856                                         /* fall through */
1857                                         M_LST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1858                                         break;
1859                                 case ICMD_FRETURN:
1860                                         M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1861                                         break;
1862                                 case ICMD_DRETURN:
1863                                         M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1864                                         break;
1865                                 }
1866
1867                                 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
1868                                 M_JSR;
1869
1870                                 /* and now restore the proper return value */
1871
1872                                 switch (iptr->opc) {
1873                                 case ICMD_LRETURN:
1874                                 case ICMD_IRETURN:
1875                                 case ICMD_ARETURN:
1876                                         /* fall through */
1877                                         M_LLD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1878                                         break;
1879                                 case ICMD_FRETURN:
1880                                         M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1881                                         break;
1882                                 case ICMD_DRETURN:
1883                                         M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1884                                         break;
1885                                 }
1886                         }
1887 #endif
1888
1889                         /* restore return address                                         */
1890
1891                         if (!code_is_leafmethod(code)) {
1892                                 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
1893                                    may have a displacement overflow. */
1894
1895                                 M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET);
1896                                 M_MTLR(REG_ITMP1);
1897                         }
1898
1899                         /* restore saved registers                                        */
1900
1901                         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
1902                                 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
1903                         }
1904                         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
1905                                 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
1906                         }
1907
1908                         /* deallocate stack                                               */
1909
1910                         if (cd->stackframesize)
1911                                 M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
1912
1913                         M_RET;
1914                         ALIGNCODENOP;
1915                         }
1916                         break;
1917
1918
1919                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
1920                         {
1921                         s4 i, l;
1922                         branch_target_t *table;
1923
1924                         table = iptr->dst.table;
1925
1926                         l = iptr->sx.s23.s2.tablelow;
1927                         i = iptr->sx.s23.s3.tablehigh;
1928
1929                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1930                         if (l == 0) {
1931                                 M_INTMOVE(s1, REG_ITMP1);
1932                         } else if (l <= 32768) {
1933                                 M_LDA(REG_ITMP1, s1, -l);
1934                         } else {
1935                                 ICONST(REG_ITMP2, l);
1936                                 M_SUB(s1, REG_ITMP2, REG_ITMP1);
1937                         }
1938
1939                         /* number of targets */
1940                         i = i - l + 1;
1941
1942                         /* range check */
1943
1944                         M_CMPUI(REG_ITMP1, i - 1);
1945                         emit_bgt(cd, table[0].block);
1946
1947                         /* build jump table top down and use address of lowest entry */
1948
1949                         table += i;
1950
1951                         while (--i >= 0) {
1952                                 dseg_add_target(cd, table->block); 
1953                                 --table;
1954                         }
1955
1956                         /* length of dataseg after last dseg_add_unique_target is used by load */
1957
1958                         M_SLL_IMM(REG_ITMP1, 3, REG_ITMP1);
1959                         M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
1960                         M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
1961                         M_MTCTR(REG_ITMP2);
1962                         M_RTS;
1963                         ALIGNCODENOP;
1964                         }
1965                         break;
1966
1967
1968                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
1969                         {
1970                         s4 i, val;
1971                         lookup_target_t *lookup;
1972
1973                         lookup = iptr->dst.lookup;
1974
1975                         i = iptr->sx.s23.s2.lookupcount;
1976                         
1977                         MCODECHECK((i<<3)+8);
1978                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1979                         while (--i >= 0) {
1980                                 val = lookup->value;
1981                                 if ((val >= -32768) && (val <= 32767)) {
1982                                         M_CMPI(s1, val);
1983                         
1984                                 } else {
1985                                         a = dseg_add_s4(cd, val);
1986                                         M_ILD(REG_ITMP2, REG_PV, a);
1987                                         M_CMP(s1, REG_ITMP2);
1988                                 }
1989                                 emit_beq(cd, lookup->target.block);
1990                                 ++lookup;
1991                         }
1992
1993                         emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
1994
1995                         ALIGNCODENOP;
1996                         break;
1997                         }
1998
1999
2000                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
2001
2002                         bte = iptr->sx.s23.s3.bte;
2003                         md = bte->md;
2004                         goto gen_method;
2005
2006                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2007                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2008                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2009                 case ICMD_INVOKEINTERFACE:
2010
2011                         REPLACEMENT_POINT_INVOKE(cd, iptr);
2012
2013                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2014                                 lm = NULL;
2015                                 um = iptr->sx.s23.s3.um;
2016                                 md = um->methodref->parseddesc.md;
2017                         }
2018                         else {
2019                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2020                                 um = NULL;
2021                                 md = lm->parseddesc;
2022                         }
2023
2024 gen_method:
2025                         s3 = md->paramcount;
2026
2027                         MCODECHECK((s3 << 2) + 128);
2028
2029                         /* copy arguments to registers or stack location */
2030
2031                         for (s3 = s3 - 1; s3 >= 0; s3--) {
2032                                 var = VAR(iptr->sx.s23.s2.args[s3]);
2033                                 d   = md->params[s3].regoff;
2034
2035                                 if (var->flags & PREALLOC)
2036                                         continue;
2037
2038                                 if (IS_INT_LNG_TYPE(var->type)) {
2039                                         if (!md->params[s3].inmemory) {
2040                                                 s1 = emit_load(jd, iptr, var, d);
2041                                                 M_LNGMOVE(s1, d);
2042                                         }
2043                                         else {
2044                                                 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2045                                                 M_LST(s1, REG_SP, d);
2046                                         }
2047                                 }
2048                                 else {
2049                                         if (!md->params[s3].inmemory) {
2050                                                 s1 = emit_load(jd, iptr, var, d);
2051                                                 M_FLTMOVE(s1, d);
2052                                         }
2053                                         else {
2054                                                 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2055                                                 M_DST(s1, REG_SP, d);
2056                                         }
2057                                 }
2058                         }
2059
2060                         switch (iptr->opc) {
2061                         case ICMD_BUILTIN:
2062                                 if (bte->stub == NULL) {
2063                                         disp = dseg_add_functionptr(cd, bte->fp);
2064                                         M_ALD(REG_PV, REG_PV, disp);
2065                                         M_ALD(REG_PV, REG_PV, 0);       /* TOC */
2066                                 }
2067                                 else {
2068                                         disp = dseg_add_functionptr(cd, bte->stub);
2069                                         M_ALD(REG_PV, REG_PV, disp);
2070                                 }
2071
2072                                 /* generate the actual call */
2073                                 M_MTCTR(REG_PV);
2074                                 M_JSR;
2075                                 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2076                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2077                                 M_MFLR(REG_ITMP1);
2078                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2079                                 break;
2080
2081                         case ICMD_INVOKESPECIAL:
2082                                 emit_nullpointer_check(cd, iptr, REG_A0);
2083                                 /* fall through */
2084
2085                         case ICMD_INVOKESTATIC:
2086                                 if (lm == NULL) {
2087                                         disp = dseg_add_unique_address(cd, um);
2088
2089                                         patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2090                                                                                 um, disp);
2091                                 } else {
2092                                         disp = dseg_add_address(cd, lm->stubroutine);
2093                                 }
2094                                 M_ALD(REG_PV, REG_PV, disp);
2095
2096                                 /* generate the actual call */
2097
2098                                 M_MTCTR(REG_PV);
2099                                 M_JSR;
2100                                 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2101                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2102                                 M_MFLR(REG_ITMP1);
2103                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2104                                 break;
2105
2106                         case ICMD_INVOKEVIRTUAL:
2107                                 if (lm == NULL) {
2108                                         patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2109                                         s1 = 0;
2110                                 } else {
2111                                         s1 = OFFSET(vftbl_t, table[0]) +
2112                                                 sizeof(methodptr) * lm->vftblindex;
2113                                 }
2114
2115                                 /* implicit null-pointer check */
2116                                 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2117                                 M_ALD(REG_PV, REG_METHODPTR, s1);
2118
2119                                 /* generate the actual call */
2120
2121                                 M_MTCTR(REG_PV);
2122                                 M_JSR;
2123                                 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2124                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2125                                 M_MFLR(REG_ITMP1);
2126                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2127                                 break;
2128
2129                         case ICMD_INVOKEINTERFACE:
2130                                 if (lm == NULL) {
2131                                         patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2132
2133                                         s1 = 0;
2134                                         s2 = 0;
2135
2136                                 } else {
2137                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
2138                                                 sizeof(methodptr*) * lm->clazz->index;
2139
2140                                         s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2141                                 }
2142
2143                                 /* implicit null-pointer check */
2144                                 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));    
2145                                 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2146                                 M_ALD(REG_PV, REG_METHODPTR, s2);
2147
2148                                 /* generate the actual call */
2149
2150                                 M_MTCTR(REG_PV);
2151                                 M_JSR;
2152                                 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2153                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2154                                 M_MFLR(REG_ITMP1);
2155                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2156
2157                                 break;
2158                         }
2159                         /* store return value */
2160
2161                         d = md->returntype.type;
2162
2163                         if (d != TYPE_VOID) {
2164                                 if (IS_INT_LNG_TYPE(d)) {
2165                                         s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2166                                         M_MOV(REG_RESULT, s1);
2167                                 }
2168                                 else {
2169                                         s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2170                                         M_FLTMOVE(REG_FRESULT, s1);
2171                                 }
2172                                 emit_store_dst(jd, iptr, s1);
2173                         }
2174                         break;
2175
2176                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2177                                       /* val.a: (classinfo*) superclass               */
2178
2179                         /*  superclass is an interface:
2180                          *
2181                          *  OK if ((sub == NULL) ||
2182                          *         (sub->vftbl->interfacetablelength > super->index) &&
2183                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
2184                          *
2185                          *  superclass is a class:
2186                          *
2187                          *  OK if ((sub == NULL) || (0
2188                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2189                          *         super->vftbl->diffvall));
2190                          */
2191
2192                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2193                                 /* object type cast-check */
2194
2195                                 classinfo *super;
2196                                 s4         superindex;
2197
2198                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2199                                         super      = NULL;
2200                                         superindex = 0;
2201                                 }
2202                                 else {
2203                                         super      = iptr->sx.s23.s3.c.cls;
2204                                         superindex = super->index;
2205                                 }
2206                 
2207                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2208
2209                                 /* if class is not resolved, check which code to call */
2210
2211                                 if (super == NULL) {
2212                                         M_TST(s1);
2213                                         emit_label_beq(cd, BRANCH_LABEL_1);
2214                                         disp = dseg_add_unique_s4(cd, 0);                     /* super->flags */
2215
2216                                         patcher_add_patch_ref(jd,
2217                                                                                 PATCHER_resolve_classref_to_flags,
2218                                                                                 iptr->sx.s23.s3.c.ref,
2219                                                                                 disp);
2220
2221                                         M_ILD(REG_ITMP2, REG_PV, disp);
2222                                         M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2223
2224                                         emit_label_beq(cd, BRANCH_LABEL_2);
2225                                 }
2226
2227                                 /* interface checkcast code */
2228
2229                                 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2230                                         if (super == NULL) {
2231                                                 patcher_add_patch_ref(jd,
2232                                                                                         PATCHER_checkcast_interface,
2233                                                                                         iptr->sx.s23.s3.c.ref,
2234                                                                                         0);
2235                                         } else {
2236                                                 M_TST(s1);
2237                                                 emit_label_beq(cd, BRANCH_LABEL_3);
2238                                         }
2239
2240                                         M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2241                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2242                                         M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2243                                         emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2244                                         M_ALD(REG_ITMP3, REG_ITMP2,
2245                                                   OFFSET(vftbl_t, interfacetable[0]) -
2246                                                   superindex * sizeof(methodptr*));
2247                                         M_TST(REG_ITMP3);
2248                                         emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
2249
2250                                         if (super == NULL)      {
2251                                                 emit_label_br(cd, BRANCH_LABEL_4);
2252                                         } else  {
2253                                                 emit_label(cd, BRANCH_LABEL_3);
2254                                         }
2255                                 }
2256
2257                                 /* class checkcast code */
2258
2259                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2260                                         if (super == NULL) {
2261                                                 emit_label(cd, BRANCH_LABEL_2);
2262
2263                                                 disp = dseg_add_unique_address(cd, NULL);
2264                                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2265                                                                                         iptr->sx.s23.s3.c.ref,
2266                                                                                         disp);
2267                                         } else {
2268                                                 disp = dseg_add_address(cd, super->vftbl);
2269                                                 M_TST(s1);
2270                                                 emit_label_beq(cd, BRANCH_LABEL_5);
2271                                         }
2272
2273                                         M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2274
2275                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2276                                         M_ALD(REG_ITMP2, REG_PV, disp);
2277                                         if (s1 != REG_ITMP1) {
2278                                                 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2279                                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2280
2281                                                 M_SUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2282                                                 M_EXTSW(REG_ITMP3, REG_ITMP3);
2283                                         } else {
2284                                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2285                                                 M_SUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2286                                                 M_EXTSW(REG_ITMP3, REG_ITMP3);
2287                                                 M_ALD(REG_ITMP2, REG_PV, disp);
2288                                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2289                                         }
2290                                         M_CMPU(REG_ITMP3, REG_ITMP2);
2291                                         emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
2292                                         
2293                                         if (super != NULL)
2294                                                 emit_label(cd, BRANCH_LABEL_5);
2295                                 }
2296
2297                                 if (super == NULL) {
2298                                         emit_label(cd, BRANCH_LABEL_1);
2299                                         emit_label(cd, BRANCH_LABEL_4);
2300                                 }
2301                                 d = codegen_reg_of_dst(jd, iptr, s1);
2302
2303                         } else {
2304                                 /* array type cast-check */
2305
2306                                 s1 = emit_load_s1(jd, iptr, REG_A0);
2307                                 M_INTMOVE(s1, REG_A0);
2308
2309
2310                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2311                                         disp = dseg_add_unique_address(cd, NULL);
2312                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2313                                                                                 iptr->sx.s23.s3.c.ref,
2314                                                                                 disp);
2315                                 } else {
2316                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2317                                 }
2318
2319                                 M_ALD(REG_A1, REG_PV, disp);
2320                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2321                                 M_ALD(REG_ITMP2, REG_PV, disp);
2322                                 M_ALD(REG_ITMP2, REG_ITMP2, 0); /* TOC */
2323                                 M_MTCTR(REG_ITMP2);
2324                                 M_JSR;
2325                                 M_TST(REG_RESULT);
2326                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2327
2328                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2329                                 d = codegen_reg_of_dst(jd, iptr, s1);
2330                         }
2331                         M_INTMOVE(s1, d);
2332                         emit_store_dst(jd, iptr, d);
2333                         break;
2334
2335
2336                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2337                                       /* val.a: (classinfo*) superclass               */
2338
2339                         /*  superclass is an interface:
2340                          *
2341                          *  return (sub != NULL) &&
2342                          *         (sub->vftbl->interfacetablelength > super->index) &&
2343                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
2344                          *
2345                          *  superclass is a class:
2346                          *
2347                          *  return ((sub != NULL) && (0
2348                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2349                          *          super->vftbl->diffvall));
2350                          */
2351
2352                         {
2353                         classinfo *super;
2354                         s4         superindex;
2355
2356                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2357                                 super      = NULL;
2358                                 superindex = 0;
2359                         }
2360                         else {
2361                                 super      = iptr->sx.s23.s3.c.cls;
2362                                 superindex = super->index;
2363                         }
2364                         
2365                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2366                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2367                         if (s1 == d) {
2368                                 M_MOV(s1, REG_ITMP1);
2369                                 s1 = REG_ITMP1;
2370                         }
2371
2372                         M_CLR(d);
2373
2374                         /* if class is not resolved, check which code to call */
2375
2376                         if (super == NULL) {
2377                                 M_TST(s1);
2378                                 emit_label_beq(cd, BRANCH_LABEL_1);
2379                                 disp = dseg_add_unique_s4(cd, 0);                     /* super->flags */
2380
2381                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2382                                                                         iptr->sx.s23.s3.c.ref, disp);
2383
2384                                 M_ILD(REG_ITMP3, REG_PV, disp);
2385                                 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2386                                 emit_label_beq(cd, BRANCH_LABEL_2);
2387                         }
2388
2389                         /* interface instanceof code */
2390
2391                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2392                                 if (super == NULL) {
2393                                         patcher_add_patch_ref(jd,
2394                                                                                 PATCHER_instanceof_interface,
2395                                                                                 iptr->sx.s23.s3.c.ref, 0);
2396
2397                                 } else {
2398                                         M_TST(s1);
2399                                         emit_label_beq(cd, BRANCH_LABEL_3);
2400                                 }
2401
2402                                 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2403                                 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2404                                 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2405                                 M_BLE(4);
2406                                 M_ALD(REG_ITMP1, REG_ITMP1,
2407                                           OFFSET(vftbl_t, interfacetable[0]) -
2408                                           superindex * sizeof(methodptr*));
2409                                 M_TST(REG_ITMP1);
2410                                 M_BEQ(1);
2411                                 M_IADD_IMM(REG_ZERO, 1, d);
2412
2413                                 if (super == NULL)      {
2414                                         emit_label_br(cd, BRANCH_LABEL_4);
2415                                 } else  {
2416                                         emit_label(cd, BRANCH_LABEL_3);
2417                                 }
2418                         }
2419
2420                         /* class instanceof code */
2421
2422                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2423
2424                                 if (super == NULL) {
2425                                         emit_label(cd, BRANCH_LABEL_2);
2426
2427                                         disp = dseg_add_unique_address(cd, NULL);
2428                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2429                                                                                 iptr->sx.s23.s3.c.ref,
2430                                                                                 disp);
2431
2432                                 } else {
2433                                         disp = dseg_add_address(cd, super->vftbl);
2434                                         M_TST(s1);
2435                                         emit_label_beq(cd, BRANCH_LABEL_5);
2436                                 }
2437
2438                                 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2439                                 M_ALD(REG_ITMP2, REG_PV, disp);
2440
2441                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2442                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2443                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2444
2445                                 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2446                                 M_EXTSW(REG_ITMP1, REG_ITMP1);
2447                                 M_CMPU(REG_ITMP1, REG_ITMP2);
2448                                 M_CLR(d);
2449                                 M_BGT(1);
2450                                 M_IADD_IMM(REG_ZERO, 1, d);
2451
2452                                 if (super != NULL)
2453                                         emit_label(cd, BRANCH_LABEL_5);
2454                         }
2455
2456                         if (super == NULL) {
2457                                 emit_label(cd, BRANCH_LABEL_1);
2458                                 emit_label(cd, BRANCH_LABEL_4);
2459                         }
2460
2461                         emit_store_dst(jd, iptr, d);
2462                         }
2463                         break;
2464
2465                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2466
2467                         /* check for negative sizes and copy sizes to stack if necessary  */
2468
2469                         MCODECHECK((iptr->s1.argcount << 2) + 128);
2470
2471                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2472
2473                                 var = VAR(iptr->sx.s23.s2.args[s1]);
2474
2475                                 /* copy SAVEDVAR sizes to stack */
2476
2477                                 if (!(var->flags & PREALLOC)) {
2478                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
2479 #if defined(__DARWIN__)
2480                                         M_LST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 8);
2481 #else
2482                                         M_LST(s2, REG_SP, LA_SIZE + (s1 + 3) * 8);
2483 #endif
2484                                 }
2485                         }
2486
2487                         /* a0 = dimension count */
2488
2489                         ICONST(REG_A0, iptr->s1.argcount);
2490
2491                         /* is patcher function set? */
2492
2493                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2494                                 disp = dseg_add_unique_address(cd, NULL);
2495
2496                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2497                                                                         iptr->sx.s23.s3.c.ref, disp);
2498                         } else {
2499                                 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2500                         }
2501
2502                         /* a1 = arraydescriptor */
2503
2504                         M_ALD(REG_A1, REG_PV, disp);
2505
2506                         /* a2 = pointer to dimensions = stack pointer */
2507
2508 #if defined(__DARWIN__)
2509                         M_LDA(REG_A2, REG_SP, LA_SIZE + INT_ARG_CNT * 8);
2510 #else
2511                         M_LDA(REG_A2, REG_SP, LA_SIZE + 3 * 8);
2512 #endif
2513
2514                         disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2515                         M_ALD(REG_ITMP3, REG_PV, disp);
2516                         M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
2517                         M_MTCTR(REG_ITMP3);
2518                         M_JSR;
2519
2520                         /* check for exception before result assignment */
2521                         emit_exception_check(cd, iptr);
2522
2523                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2524                         M_INTMOVE(REG_RESULT, d);
2525                         emit_store_dst(jd, iptr, d);
2526                         break;
2527
2528                 default:
2529                         exceptions_throw_internalerror("Unknown ICMD %d during code generation",
2530                                                                                    iptr->opc);
2531                         return false;
2532         } /* switch */
2533                 
2534         } /* for instruction */
2535                 
2536         } /* if (bptr -> flags >= BBREACHED) */
2537         } /* for basic block */
2538
2539         /* generate traps */
2540
2541         emit_patcher_traps(jd);
2542
2543         /* everything's ok */
2544
2545         return true;
2546 }
2547
2548
2549 /* codegen_emit_stub_native ****************************************************
2550
2551    Emits a stub routine which calls a native method.
2552
2553 *******************************************************************************/
2554
2555 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2556 {
2557         methodinfo  *m;
2558         codeinfo    *code;
2559         codegendata *cd;
2560         methoddesc  *md;
2561         s4           i, j;
2562         s4           t;
2563         int          s1, s2;
2564         int          disp;
2565
2566         /* get required compiler data */
2567
2568         m    = jd->m;
2569         code = jd->code;
2570         cd   = jd->cd;
2571
2572         /* Sanity check. */
2573
2574         assert(!code_is_leafmethod(code));
2575
2576         /* set some variables */
2577
2578         md = m->parseddesc;
2579
2580         /* calculate stackframe size */
2581
2582         cd->stackframesize =
2583                 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
2584                 sizeof(localref_table) / SIZEOF_VOID_P +
2585                 4 +                            /* 4 stackframeinfo arguments (darwin)*/
2586                 nmd->paramcount  + 
2587                 nmd->memuse;
2588
2589 /*      cd->stackframesize = (cd->stackframesize + 3) & ~3;*/ /* keep stack 16-byte aligned */
2590
2591         /* create method header */
2592
2593         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
2594         (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
2595         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
2596         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
2597         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
2598
2599         /* generate code */
2600
2601         M_MFLR(REG_ZERO);
2602         M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
2603         M_STDU(REG_SP, REG_SP, -(cd->stackframesize * 8));
2604
2605         /* save integer and float argument registers */
2606
2607         for (i = 0; i < md->paramcount; i++) {
2608                 if (!md->params[i].inmemory) {
2609                         s1 = md->params[i].regoff;
2610
2611                         switch (md->paramtypes[i].type) {
2612                         case TYPE_INT:
2613                         case TYPE_LNG:
2614                         case TYPE_ADR:
2615                                 M_LST(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2616                                 break;
2617                         case TYPE_FLT:
2618                         case TYPE_DBL:
2619                                 M_DST(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2620                                 break;
2621                         }
2622                 }
2623         }
2624
2625         /* create native stack info */
2626
2627         M_MOV(REG_SP, REG_A0);
2628         M_MOV(REG_PV, REG_A1);
2629         disp = dseg_add_functionptr(cd, codegen_start_native_call);
2630         M_ALD(REG_ITMP1, REG_PV, disp);
2631         M_ALD(REG_ITMP1, REG_ITMP1, 0);         /* TOC */
2632         M_MTCTR(REG_ITMP1);
2633         M_JSR;
2634
2635         /* remember class argument */
2636
2637         if (m->flags & ACC_STATIC)
2638                 M_MOV(REG_RESULT, REG_ITMP3);
2639
2640         /* restore integer and float argument registers */
2641
2642         for (i = 0; i < md->paramcount; i++) {
2643                 if (!md->params[i].inmemory) {
2644                         s1 = md->params[i].regoff;
2645
2646                         switch (md->paramtypes[i].type) {
2647                         case TYPE_INT:
2648                         case TYPE_LNG:
2649                         case TYPE_ADR:
2650                                 M_LLD(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2651                                 break;
2652                         case TYPE_FLT:
2653                         case TYPE_DBL:
2654                                 M_DLD(s1, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + i * 8);
2655                                 break;
2656                         }
2657                 }
2658         }
2659         
2660         /* copy or spill arguments to new locations */
2661
2662         for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2663                 t = md->paramtypes[i].type;
2664
2665                 if (IS_INT_LNG_TYPE(t)) {
2666                         if (!md->params[i].inmemory) {
2667                                 s1 = md->params[i].regoff;
2668                                 s2 = nmd->params[j].regoff;
2669
2670                                 if (!nmd->params[j].inmemory)
2671                                         M_INTMOVE(s1, s2);
2672                                 else
2673                                         M_LST(s1, REG_SP, s2);
2674                         }
2675                         else {
2676                                 s1 = md->params[i].regoff + cd->stackframesize * 8;
2677                                 s2 = nmd->params[j].regoff;
2678
2679                                 M_LLD(REG_ITMP1, REG_SP, s1);
2680                                 M_LST(REG_ITMP1, REG_SP, s2);
2681                         }
2682                 }
2683                 else {
2684                         /* We only copy spilled float arguments, as the float
2685                            argument registers keep unchanged. */
2686
2687                         if (md->params[i].inmemory) {
2688                                 s1 = md->params[i].regoff + cd->stackframesize * 8;
2689                                 s2 = nmd->params[j].regoff;
2690
2691                                 M_DLD(REG_FTMP1, REG_SP, s1);
2692
2693                                 if (IS_2_WORD_TYPE(t))
2694                                         M_DST(REG_FTMP1, REG_SP, s2);
2695                                 else
2696                                         M_FST(REG_FTMP1, REG_SP, s2 + 4);
2697                         }
2698                 }
2699         }
2700
2701         /* Handle native Java methods. */
2702
2703         if (m->flags & ACC_NATIVE) {
2704                 /* put class into second argument register */
2705
2706                 if (m->flags & ACC_STATIC)
2707                         M_MOV(REG_ITMP3, REG_A1);
2708
2709                 /* put env into first argument register */
2710
2711                 disp = dseg_add_unique_address(cd, _Jv_env);
2712                 M_ALD(REG_A0, REG_PV, disp);
2713         }
2714
2715         /* Call the native function. */
2716         /* native functions have a different TOC for sure */
2717
2718         M_AST(REG_TOC, REG_SP, 40);     /* save old TOC */
2719         disp = dseg_add_functionptr(cd, f);
2720         M_ALD(REG_ITMP3, REG_PV, disp);
2721         M_ALD(REG_TOC, REG_ITMP3, 8);   /* load TOC from func. descriptor */
2722         M_ALD(REG_ITMP3, REG_ITMP3, 0);         
2723         M_MTCTR(REG_ITMP3);
2724         M_JSR;
2725         M_ALD(REG_TOC, REG_SP, 40);     /* restore TOC */
2726
2727         /* save return value */
2728
2729         if (md->returntype.type != TYPE_VOID) {
2730                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
2731                         M_LST(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2732                 }
2733                 else {
2734                         M_DST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2735                 }
2736         }
2737
2738         /* remove native stackframe info */
2739
2740         M_MOV(REG_SP, REG_A0);
2741         M_MOV(REG_PV, REG_A1);
2742         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2743         M_ALD(REG_ITMP1, REG_PV, disp);
2744         M_ALD(REG_ITMP1, REG_ITMP1, 0); /* XXX what about TOC? */
2745         M_MTCTR(REG_ITMP1);
2746         M_JSR;
2747         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
2748
2749         /* restore return value */
2750
2751         if (md->returntype.type != TYPE_VOID) {
2752                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
2753                         M_LLD(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2754                 }
2755                 else {
2756                         M_DLD(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 2 * 8);
2757                 }
2758         }
2759
2760         M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
2761         M_MTLR(REG_ITMP2_XPC);
2762         M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); /* remove stackframe           */
2763
2764         /* check for exception */
2765
2766         M_TST(REG_ITMP1_XPTR);
2767         M_BNE(1);                           /* if no exception then return        */
2768
2769         M_RET;
2770
2771         /* handle exception */
2772
2773         M_LADD_IMM(REG_ITMP2_XPC, -4, REG_ITMP2_XPC);  /* exception address       */
2774
2775         disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2776         M_ALD(REG_ITMP3, REG_PV, disp);
2777         M_MTCTR(REG_ITMP3);
2778         M_RTS;
2779 }
2780
2781
2782 /*
2783  * These are local overrides for various environment variables in Emacs.
2784  * Please do not remove this and leave it at the end of the file, where
2785  * Emacs will automagically detect them.
2786  * ---------------------------------------------------------------------
2787  * Local variables:
2788  * mode: c
2789  * indent-tabs-mode: t
2790  * c-basic-offset: 4
2791  * tab-width: 4
2792  * End:
2793  * vim:noexpandtab:sw=4:ts=4:
2794  */