- compilation fixes
[cacao.git] / src / vm / jit / powerpc / codegen.c
1 /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28             Stefan Ring
29
30    Changes: Christian Thalinger
31
32    $Id: codegen.c 2525 2005-05-24 10:28:20Z twisti $
33
34 */
35
36
37 #include <assert.h>
38 #include <stdio.h>
39 #include <signal.h>
40
41 #include "config.h"
42 #include "cacao/cacao.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/global.h"
46 #include "vm/loader.h"
47 #include "vm/stringlocal.h"
48 #include "vm/tables.h"
49 #include "vm/jit/asmpart.h"
50 #include "vm/jit/jit.h"
51 #include "vm/jit/parse.h"
52 #include "vm/jit/patcher.h"
53 #include "vm/jit/reg.h"
54 #include "vm/jit/powerpc/arch.h"
55 #include "vm/jit/powerpc/codegen.h"
56 #include "vm/jit/powerpc/types.h"
57
58
59 /* register descripton - array ************************************************/
60
61 /* #define REG_RES   0         reserved register for OS or code generator     */
62 /* #define REG_RET   1         return value register                          */
63 /* #define REG_EXC   2         exception value register (only old jit)        */
64 /* #define REG_SAV   3         (callee) saved register                        */
65 /* #define REG_TMP   4         scratch temporary register (caller saved)      */
66 /* #define REG_ARG   5         argument register (caller saved)               */
67
68 /* #define REG_END   -1        last entry in tables */
69  
70 static int nregdescint[] = {
71         REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, 
72         REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV, 
73         REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
74         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
75         REG_END };
76
77 /* for use of reserved registers, see comment above */
78         
79 static int nregdescfloat[] = {
80         REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
81         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV, 
82         REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
83         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
84         REG_END };
85
86
87 /* Include independent code generation stuff -- include after register        */
88 /* descriptions to avoid extern definitions.                                  */
89
90 #include "vm/jit/codegen.inc"
91 #include "vm/jit/reg.inc"
92 #ifdef LSRA
93 #include "vm/jit/lsra.inc"
94 #endif
95
96
97 void asm_cacheflush(void *, long);
98
99 /* #include <architecture/ppc/cframe.h> */
100
101 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
102 void thread_restartcriticalsection(void *u)
103 {
104         /* XXX set pc to restart address */
105 }
106 #endif
107
108 #if defined(__DARWIN__)
109 #include <mach/message.h>
110
111 int cacao_catch_Handler(mach_port_t thread)
112 {
113 #if defined(USE_THREADS)
114         unsigned int *regs;
115         unsigned int crashpc;
116         s4 instr, reg;
117         java_objectheader *xptr;
118
119         /* Mach stuff */
120         thread_state_flavor_t flavor = PPC_THREAD_STATE;
121         mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
122         ppc_thread_state_t thread_state;
123         kern_return_t r;
124         
125         if (checknull)
126                 return 0;
127
128         r = thread_get_state(thread, flavor,
129                 (natural_t*)&thread_state, &thread_state_count);
130         if (r != KERN_SUCCESS) {
131                 log_text("thread_get_state failed");
132                 assert(0);
133         }
134
135         regs = &thread_state.r0;
136         crashpc = thread_state.srr0;
137
138         instr = *(s4*) crashpc;
139         reg = (instr >> 16) & 31;
140
141         if (!regs[reg]) {
142 /*      This is now handled in asmpart because it needs to run in the throwing
143  *      thread */
144 /*              xptr = new_nullpointerexception(); */
145
146                 regs[REG_ITMP2_XPC] = crashpc;
147 /*              regs[REG_ITMP1_XPTR] = (u4) xptr; */
148                 thread_state.srr0 = (u4) asm_handle_nullptr_exception;
149
150                 r = thread_set_state(thread, flavor,
151                         (natural_t*)&thread_state, thread_state_count);
152                 if (r != KERN_SUCCESS) {
153                         log_text("thread_set_state failed");
154                         assert(0);
155                 }
156
157                 return 1;
158         }
159
160         throw_cacao_exception_exit(string_java_lang_InternalError,
161                                    "Segmentation fault at %p", regs[reg]);
162 #endif
163
164         return 0;
165 }
166 #endif /* __DARWIN__ */
167
168
169 void init_exceptions(void)
170 {
171         GC_dirty_init(1);
172
173 #if !defined(__DARWIN__)
174         nregdescint[2] = REG_RES;
175 #endif
176 }
177
178 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
179 {
180         if (!d) {
181                 *fa = 0; *ia = 0;
182                 return;
183         }
184         adjust_argvars(s->prev, d-1, fa, ia);
185         if (s->varkind == ARGVAR)
186                 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
187         *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
188         *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
189 }
190
191
192 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
193
194 void preregpass(methodinfo *m, registerdata *rd)
195 {
196         int paramsize;
197         stackptr    src;
198         basicblock  *bptr;
199         instruction *iptr;
200         int s3, len;
201
202         rd->ifmemuse = 0;
203
204         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
205                 len = bptr->icount;
206                 for (iptr = bptr->iinstr, src = bptr->instack;
207                     len > 0;
208                     src = iptr->dst, len--, iptr++)
209                 {
210                         if (bptr->flags < BBREACHED)
211                                 continue;
212                         switch (iptr->opc) {
213                                 case ICMD_BUILTIN1:
214                                         s3 = 1;
215                                         goto countparams;
216                                 case ICMD_BUILTIN2:
217                                         s3 = 2;
218                                         goto countparams;
219                                 case ICMD_BUILTIN3:
220                                         s3 = 3;
221                                         goto countparams;
222
223                                 case ICMD_INVOKEVIRTUAL:
224                                 case ICMD_INVOKESPECIAL:
225                                 case ICMD_INVOKESTATIC:
226                                 case ICMD_INVOKEINTERFACE:
227                                         s3 = iptr->op1;
228 countparams:
229                                         {
230                                                 int ia, fa;
231                                                 adjust_argvars(src, s3, &fa, &ia);
232                                         }
233                                         paramsize = 0;
234                                         for (; --s3 >= 0; src = src->prev) {
235                                                 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
236                                         }
237                                         rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
238                                         break;
239
240                                 case ICMD_MULTIANEWARRAY:
241                                         s3 = iptr->op1;
242                                         paramsize = rd->intreg_argnum + s3;
243                                         rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
244                                         break;
245                         }
246                 }
247         }
248
249         rd->ifmemuse += 6;
250         rd->maxmemuse = rd->ifmemuse;
251 }
252
253
254 /* function gen_mcode **********************************************************
255
256         generates machine code
257
258 *******************************************************************************/
259
260 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
261 {
262         s4 len, s1, s2, s3, d;
263         s4 a;
264         s4 parentargs_base;
265         s4          *mcodeptr;
266         stackptr    src;
267         varinfo     *var;
268         basicblock  *bptr;
269         instruction *iptr;
270         exceptiontable *ex;
271
272         {
273         s4 i, p, pa, t, l;
274         s4 savedregs_num;
275
276         savedregs_num = 0;
277
278         /* space to save used callee saved registers */
279
280         savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
281         savedregs_num += 2 * (rd->savfltregcnt - rd->maxsavfltreguse);
282
283         parentargs_base = rd->maxmemuse + savedregs_num;
284
285 #ifdef USE_THREADS                 /* space to save argument of monitor_enter   */
286                                        /* and Return Values to survive monitor_exit */
287         if (checksync && (m->flags & ACC_SYNCHRONIZED))
288                 parentargs_base+=3;
289
290 #endif
291
292         /* create method header */
293
294         parentargs_base = (parentargs_base + 3) & ~3;
295
296 #if POINTERSIZE == 4
297         (void) dseg_addaddress(cd, m);                          /* Filler         */
298 #endif
299         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
300         (void) dseg_adds4(cd, parentargs_base * 4);             /* FrameSize      */
301
302 #ifdef USE_THREADS
303
304         /* IsSync contains the offset relative to the stack pointer for the
305            argument of monitor_exit used in the exception handler. Since the
306            offset could be zero and give a wrong meaning of the flag it is
307            offset by one.
308         */
309
310         if (checksync && (m->flags & ACC_SYNCHRONIZED))
311                 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 4);     /* IsSync         */
312         else
313
314 #endif
315
316                 (void) dseg_adds4(cd, 0);                           /* IsSync         */
317                                                
318         (void) dseg_adds4(cd, m->isleafmethod);                 /* IsLeaf         */
319         (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
320         (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
321         (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
322
323         /* create exception table */
324
325         for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
326                 dseg_addtarget(cd, ex->start);
327                 dseg_addtarget(cd, ex->end);
328                 dseg_addtarget(cd, ex->handler);
329                 (void) dseg_addaddress(cd, ex->catchtype.cls);
330         }
331         
332         /* initialize mcode variables */
333         
334         mcodeptr = (s4 *) cd->mcodebase;
335         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
336         MCODECHECK(128 + m->paramcount);
337
338         /* create stack frame (if necessary) */
339
340         if (!m->isleafmethod) {
341                 M_MFLR(REG_ITMP3);
342                 M_AST(REG_ITMP3, REG_SP, 8);
343         }
344
345         if (parentargs_base) {
346                 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
347         }
348
349         /* save return address and used callee saved registers */
350
351         p = parentargs_base;
352         for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
353                 p--; M_IST(rd->savintregs[i], REG_SP, 4 * p);
354         }
355         for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
356                 p-=2; M_DST(rd->savfltregs[i], REG_SP, 4 * p);
357         }
358         /* take arguments out of register or stack frame */
359
360         {
361                 int narg=0, niarg=0;
362                 int arg, iarg;
363
364         for (p = 0, l = 0; p < m->paramcount; p++) {
365                 arg = narg; iarg = niarg;
366                 t = m->paramtypes[p];
367                 var = &(rd->locals[l][t]);
368                 l++, niarg++;
369                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
370                         l++, niarg++;
371                 if (var->type < 0)
372                         continue;
373                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
374                         if (iarg < INT_ARG_CNT -
375                                         (IS_2_WORD_TYPE(t)!=0)) {        /* register arguments    */
376                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
377                                         M_TINTMOVE(t, rd->argintregs[iarg], var->regoff);
378
379                                 } else {                             /* reg arg -> spilled    */
380                                         M_IST(rd->argintregs[iarg], REG_SP, 4 * var->regoff);
381                                         if (IS_2_WORD_TYPE(t))
382                                                 M_IST(rd->secondregs[rd->argintregs[iarg]], REG_SP, 4 * var->regoff + 4);
383                                 }
384
385                         } else {                                 /* stack arguments       */
386                                 pa = iarg + 6;
387                                 if (!(var->flags & INMEMORY)) {      /* stack arg -> register */
388                                         M_ILD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
389                                         if (IS_2_WORD_TYPE(t))
390                                                 M_ILD(rd->secondregs[var->regoff], REG_SP, 4 * (parentargs_base + pa) + 4);
391
392                                 } else {                             /* stack arg -> spilled  */
393                                         M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
394                                         M_IST(REG_ITMP1, REG_SP, 4 * var->regoff);
395                                         if (IS_2_WORD_TYPE(t)) {
396                                                 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
397                                                 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff + 4);
398                                         }
399                                 }
400                         }
401
402                 } else {                                     /* floating args         */
403                         ++narg;
404                         if (arg < FLT_ARG_CNT) {                 /* register arguments    */
405                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
406                                         M_FLTMOVE(rd->argfltregs[arg], var->regoff);
407
408                                 } else {                                         /* reg arg -> spilled    */
409                                         if (IS_2_WORD_TYPE(t))
410                                                 M_DST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
411                                         else
412                                                 M_FST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
413                                 }
414
415                         } else {                                 /* stack arguments       */
416                                 pa = iarg + 6;
417                                 if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
418                                         if (IS_2_WORD_TYPE(t))
419                                                 M_DLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
420
421                                         else
422                                                 M_FLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
423
424                                 } else {                             /* stack-arg -> spilled  */
425                                         if (IS_2_WORD_TYPE(t)) {
426                                                 M_DLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
427                                                 M_DST(REG_FTMP1, REG_SP, 4 * var->regoff);
428
429                                         } else {
430                                                 M_FLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
431                                                 M_FST(REG_FTMP1, REG_SP, 4 * var->regoff);
432                                         }
433                         }
434                         }
435                 }
436         } /* end for */
437         }
438
439         /* save monitorenter argument */
440
441 #if defined(USE_THREADS)
442         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
443                 if (m->flags & ACC_STATIC) {
444                         p = dseg_addaddress(cd, m->class);
445                         M_ALD(REG_ITMP1, REG_PV, p);
446                         M_AST(REG_ITMP1, REG_SP, 4 * rd->maxmemuse);
447
448                 } else {
449                         M_AST(rd->argintregs[0], REG_SP, 4 * rd->maxmemuse);
450                 }
451         }                       
452
453         /* call monitorenter function */
454
455         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
456                 s4 func_enter = (m->flags & ACC_STATIC) ?
457                         (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
458                 p = dseg_addaddress(cd, (void *) func_enter);
459                 M_ALD(REG_ITMP3, REG_PV, p);
460                 M_MTCTR(REG_ITMP3);
461                 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
462                 M_JSR;
463         }
464 #endif
465
466
467         /* copy argument registers to stack and call trace function with pointer
468            to arguments on stack.
469         */
470
471         if (runverbose) {
472                 s4 longargs = 0;
473                 s4 fltargs = 0;
474                 s4 dblargs = 0;
475
476                 M_MFLR(REG_ITMP3);
477                 /* XXX must be a multiple of 16 */
478                 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
479
480                 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
481
482                 M_CLR(REG_ITMP1);    /* clear help register */
483
484                 /* save all arguments into the reserved stack space */
485                 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
486                         t = m->paramtypes[p];
487
488                         if (IS_INT_LNG_TYPE(t)) {
489                                 /* overlapping u8's are on the stack */
490                                 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
491                                         s1 = rd->argintregs[p + longargs + dblargs];
492
493                                         if (!IS_2_WORD_TYPE(t)) {
494                                                 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
495                                                 M_IST(s1, REG_SP, 24 + p * 8 + 4);
496
497                                         } else {
498                                                 M_IST(s1, REG_SP, 24 + p  * 8);
499                                                 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
500                                                 longargs++;
501                                         }
502
503                                 } else {
504                     a = dseg_adds4(cd, 0xdeadbeef);
505                     M_ILD(REG_ITMP1, REG_PV, a);
506                     M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
507                     M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
508                                 }
509
510                         } else {
511                                 if ((fltargs + dblargs) < FLT_ARG_CNT) {
512                                         s1 = rd->argfltregs[fltargs + dblargs];
513
514                                         if (!IS_2_WORD_TYPE(t)) {
515                                                 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
516                                                 M_FST(s1, REG_SP, 24 + p * 8 + 4);
517                                                 fltargs++;
518                                                 
519                                         } else {
520                                                 M_DST(s1, REG_SP, 24 + p * 8);
521                                                 dblargs++;
522                                         }
523
524                                 } else {
525                                         /* this should not happen */
526                                 }
527                         }
528                 }
529
530                 /* TODO: save remaining integer and flaot argument registers */
531
532                 /* load first 4 arguments into integer argument registers */
533                 for (p = 0; p < 8; p++) {
534                         d = rd->argintregs[p];
535                         M_ILD(d, REG_SP, 24 + p * 4);
536                 }
537
538                 p = dseg_addaddress(cd, m);
539                 M_ALD(REG_ITMP1, REG_PV, p);
540                 M_AST(REG_ITMP1, REG_SP, 11 * 8);    /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
541                 p = dseg_addaddress(cd, (void *) builtin_trace_args);
542                 M_ALD(REG_ITMP2, REG_PV, p);
543                 M_MTCTR(REG_ITMP2);
544                 M_JSR;
545
546                 longargs = 0;
547                 fltargs = 0;
548                 dblargs = 0;
549
550         /* restore arguments into the reserved stack space */
551         for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
552             t = m->paramtypes[p];
553
554             if (IS_INT_LNG_TYPE(t)) {
555                 if ((p + longargs + dblargs) < INT_ARG_CNT) {
556                     s1 = rd->argintregs[p + longargs + dblargs];
557
558                                         if (!IS_2_WORD_TYPE(t)) {
559                                                 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
560
561                                         } else {
562                                                 M_ILD(s1, REG_SP, 24 + p  * 8);
563                                                 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
564                                                 longargs++;
565                                         }
566                                 }
567
568             } else {
569                 if ((fltargs + dblargs) < FLT_ARG_CNT) {
570                     s1 = rd->argfltregs[fltargs + dblargs];
571
572                                         if (!IS_2_WORD_TYPE(t)) {
573                                                 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
574                                                 fltargs++;
575
576                                         } else {
577                                                 M_DLD(s1, REG_SP, 24 + p * 8);
578                                                 dblargs++;
579                                         }
580                                 }
581             }
582         }
583
584                 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
585
586                 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
587                 M_MTLR(REG_ITMP3);
588         }
589
590
591
592
593         }
594
595         /* end of header generation */
596
597         /* walk through all basic blocks */
598         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
599
600                 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
601
602                 if (bptr->flags >= BBREACHED) {
603
604                 /* branch resolving */
605
606                 {
607                 branchref *brefs;
608                 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
609                         gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos, 
610                                           brefs->branchpos,
611                                                           bptr->mpc);
612                         }
613                 }
614
615                 /* copy interface registers to their destination */
616
617                 src = bptr->instack;
618                 len = bptr->indepth;
619                 MCODECHECK(64+len);
620
621 #ifdef LSRA
622                 if (opt_lsra) {
623                         while (src != NULL) {
624                                 len--;
625                                 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
626                                         /*                                                      d = reg_of_var(m, src, REG_ITMP1); */
627                                         if (!(src->flags & INMEMORY))
628                                                 d= src->regoff;
629                                         else
630                                                 d=REG_ITMP1;
631                                         M_INTMOVE(REG_ITMP1, d);
632                                         store_reg_to_var_int(src, d);
633                                 }
634                                 src = src->prev;
635                         }
636                 } else {
637 #endif
638                 while (src != NULL) {
639                         len--;
640                         if ((len == 0) && (bptr->type != BBTYPE_STD)) {
641                                 d = reg_of_var(rd, src, REG_ITMP1);
642                                 M_INTMOVE(REG_ITMP1, d);
643                                 store_reg_to_var_int(src, d);
644
645                         } else {
646                                 d = reg_of_var(rd, src, REG_IFTMP);
647                                 if ((src->varkind != STACKVAR)) {
648                                         s2 = src->type;
649                                         if (IS_FLT_DBL_TYPE(s2)) {
650                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
651                                                         s1 = rd->interfaces[len][s2].regoff;
652                                                         M_FLTMOVE(s1,d);
653
654                                                 } else {
655                                                         if (IS_2_WORD_TYPE(s2)) {
656                                                                 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
657
658                                                         } else {
659                                                                 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
660                                                         }
661                                                 }
662                                                 store_reg_to_var_flt(src, d);
663
664                                         } else {
665                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
666                                                         s1 = rd->interfaces[len][s2].regoff;
667                                                         M_TINTMOVE(s2,s1,d);
668
669                                                 } else {
670                                                         M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
671                                                         if (IS_2_WORD_TYPE(s2))
672                                                                 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
673                                                 }
674                                                 store_reg_to_var_int(src, d);
675                                         }
676                                 }
677                         }
678                         src = src->prev;
679                 }
680
681 #ifdef LSRA
682                 }
683 #endif
684                 /* walk through all instructions */
685                 
686                 src = bptr->instack;
687                 len = bptr->icount;
688                 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
689
690         MCODECHECK(64);           /* an instruction usually needs < 64 words      */
691         switch (iptr->opc) {
692                 case ICMD_NOP:        /* ...  ==> ...                                 */
693         case ICMD_INLINE_START:
694         case ICMD_INLINE_END:
695                         break;
696
697                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
698
699                         var_to_reg_int(s1, src, REG_ITMP1);
700                         M_TST(s1);
701                         M_BEQ(0);
702                         codegen_addxnullrefs(cd, mcodeptr);
703                         break;
704
705                 /* constant operations ************************************************/
706
707                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
708                                       /* op1 = 0, val.i = constant                    */
709
710                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
711                         ICONST(d, iptr->val.i);
712                         store_reg_to_var_int(iptr->dst, d);
713                         break;
714
715                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
716                                       /* op1 = 0, val.l = constant                    */
717
718                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
719                         LCONST(d, iptr->val.l);
720                         store_reg_to_var_int(iptr->dst, d);
721                         break;
722
723                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
724                                       /* op1 = 0, val.f = constant                    */
725
726                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
727                         a = dseg_addfloat(cd, iptr->val.f);
728                         M_FLD(d, REG_PV, a);
729                         store_reg_to_var_flt(iptr->dst, d);
730                         break;
731                         
732                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
733                                       /* op1 = 0, val.d = constant                    */
734
735                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
736                         a = dseg_adddouble(cd, iptr->val.d);
737                         M_DLD(d, REG_PV, a);
738                         store_reg_to_var_flt(iptr->dst, d);
739                         break;
740
741                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
742                                       /* op1 = 0, val.a = constant                    */
743
744                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
745                         ICONST(d, (u4) iptr->val.a);
746                         store_reg_to_var_int(iptr->dst, d);
747                         break;
748
749
750                 /* load/store operations **********************************************/
751
752                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
753                 case ICMD_LLOAD:      /* op1 = local variable                         */
754                 case ICMD_ALOAD:
755
756                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
757                         if ((iptr->dst->varkind == LOCALVAR) &&
758                             (iptr->dst->varnum == iptr->op1))
759                                 break;
760                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
761                         if (var->flags & INMEMORY) {
762                                 M_ILD(d, REG_SP, 4 * var->regoff);
763                                 if (IS_2_WORD_TYPE(var->type))
764                                         M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
765                         } else {
766                                 M_TINTMOVE(var->type, var->regoff, d);
767                         }
768                         store_reg_to_var_int(iptr->dst, d);
769                         break;
770
771                 case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
772                 case ICMD_DLOAD:      /* op1 = local variable                         */
773
774                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
775                         if ((iptr->dst->varkind == LOCALVAR) &&
776                             (iptr->dst->varnum == iptr->op1))
777                                 break;
778                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
779                         if (var->flags & INMEMORY)
780                                 if (IS_2_WORD_TYPE(var->type))
781                                         M_DLD(d, REG_SP, 4 * var->regoff);
782                                 else
783                                         M_FLD(d, REG_SP, 4 * var->regoff);
784                         else {
785                                 M_FLTMOVE(var->regoff, d);
786                         }
787                         store_reg_to_var_flt(iptr->dst, d);
788                         break;
789
790
791                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
792                 case ICMD_LSTORE:     /* op1 = local variable                         */
793                 case ICMD_ASTORE:
794
795                         if ((src->varkind == LOCALVAR) &&
796                             (src->varnum == iptr->op1))
797                                 break;
798                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
799                         if (var->flags & INMEMORY) {
800                                 var_to_reg_int(s1, src, REG_ITMP1);
801                                 M_IST(s1, REG_SP, 4 * var->regoff);
802                                 if (IS_2_WORD_TYPE(var->type))
803                                         M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
804                         } else {
805                                 var_to_reg_int(s1, src, var->regoff);
806                                 M_TINTMOVE(var->type, s1, var->regoff);
807                         }
808                         break;
809
810                 case ICMD_FSTORE:     /* ..., value  ==> ...                          */
811                 case ICMD_DSTORE:     /* op1 = local variable                         */
812
813                         if ((src->varkind == LOCALVAR) &&
814                             (src->varnum == iptr->op1))
815                                 break;
816                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
817                         if (var->flags & INMEMORY) {
818                                 var_to_reg_flt(s1, src, REG_FTMP1);
819                                 if (var->type == TYPE_DBL)
820                                         M_DST(s1, REG_SP, 4 * var->regoff);
821                                 else
822                                         M_FST(s1, REG_SP, 4 * var->regoff);
823                         } else {
824                                 var_to_reg_flt(s1, src, var->regoff);
825                                 M_FLTMOVE(s1, var->regoff);
826                         }
827                         break;
828
829
830                 /* pop/dup/swap operations ********************************************/
831
832                 /* attention: double and longs are only one entry in CACAO ICMDs      */
833
834                 case ICMD_POP:        /* ..., value  ==> ...                          */
835                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
836                         break;
837
838                 case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
839                         M_COPY(src, iptr->dst);
840                         break;
841
842                 case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
843
844                         M_COPY(src,       iptr->dst);
845                         M_COPY(src->prev, iptr->dst->prev);
846                         M_COPY(iptr->dst, iptr->dst->prev->prev);
847                         break;
848
849                 case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
850
851                         M_COPY(src,             iptr->dst);
852                         M_COPY(src->prev,       iptr->dst->prev);
853                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
854                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
855                         break;
856
857                 case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
858
859                         M_COPY(src,       iptr->dst);
860                         M_COPY(src->prev, iptr->dst->prev);
861                         break;
862
863                 case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
864
865                         M_COPY(src,             iptr->dst);
866                         M_COPY(src->prev,       iptr->dst->prev);
867                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
868                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
869                         M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
870                         break;
871
872                 case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
873
874                         M_COPY(src,                   iptr->dst);
875                         M_COPY(src->prev,             iptr->dst->prev);
876                         M_COPY(src->prev->prev,       iptr->dst->prev->prev);
877                         M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
878                         M_COPY(iptr->dst,             iptr->dst->prev->prev->prev->prev);
879                         M_COPY(iptr->dst->prev,       iptr->dst->prev->prev->prev->prev->prev);
880                         break;
881
882                 case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
883
884                         M_COPY(src,       iptr->dst->prev);
885                         M_COPY(src->prev, iptr->dst);
886                         break;
887
888
889                 /* integer operations *************************************************/
890
891                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
892
893                         var_to_reg_int(s1, src, REG_ITMP1); 
894                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
895                         M_NEG(s1, d);
896                         store_reg_to_var_int(iptr->dst, d);
897                         break;
898
899         case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
900
901             var_to_reg_int(s1, src, REG_ITMP1);
902             d = reg_of_var(rd, iptr->dst, REG_ITMP3);
903             M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
904             M_SUBFZE(s1, d);
905             store_reg_to_var_int(iptr->dst, d);
906             break;
907
908                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
909
910                         var_to_reg_int(s1, src, REG_ITMP2);
911                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
912                         M_INTMOVE(s1, rd->secondregs[d]);
913                         M_SRA_IMM(rd->secondregs[d], 31, d);
914                         store_reg_to_var_int(iptr->dst, d);
915                         break;
916
917                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
918
919                         var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
920                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
921                         M_INTMOVE(s1, d );
922                         store_reg_to_var_int(iptr->dst, d);
923                         break;
924
925                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
926
927                         var_to_reg_int(s1, src, REG_ITMP1);
928                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
929                         M_BSEXT(s1, d);
930                         store_reg_to_var_int(iptr->dst, d);
931                         break;
932
933                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
934
935                         var_to_reg_int(s1, src, REG_ITMP1);
936                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
937             M_CZEXT(s1, d);
938                         store_reg_to_var_int(iptr->dst, d);
939                         break;
940
941                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
942
943                         var_to_reg_int(s1, src, REG_ITMP1);
944                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
945                         M_SSEXT(s1, d);
946                         store_reg_to_var_int(iptr->dst, d);
947                         break;
948
949
950                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
951
952                         var_to_reg_int(s1, src->prev, REG_ITMP1);
953                         var_to_reg_int(s2, src, REG_ITMP2);
954                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
955                         M_IADD(s1, s2, d);
956                         store_reg_to_var_int(iptr->dst, d);
957                         break;
958
959                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
960                                       /* val.i = constant                             */
961
962                         var_to_reg_int(s1, src, REG_ITMP1);
963                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
964                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
965                                 M_IADD_IMM(s1, iptr->val.i, d);
966                                 }
967                         else {
968                                 ICONST(REG_ITMP2, iptr->val.i);
969                                 M_IADD(s1, REG_ITMP2, d);
970                                 }
971                         store_reg_to_var_int(iptr->dst, d);
972                         break;
973
974         case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
975
976             var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
977             var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
978             d = reg_of_var(rd, iptr->dst, REG_ITMP3);
979             M_ADDC(s1, s2, rd->secondregs[d]);
980             var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
981             var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
982             M_ADDE(s1, s2, d);
983             store_reg_to_var_int(iptr->dst, d);
984             break;
985
986                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
987                                       /* val.l = constant                             */
988
989                         s3 = iptr->val.l & 0xffffffff;
990                         var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
991                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
992                         if ((s3 >= -32768) && (s3 <= 32767)) {
993                                 M_ADDIC(s1, s3, rd->secondregs[d]);
994                                 }
995                         else {
996                                 ICONST(REG_ITMP2, s3);
997                                 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
998                                 }
999                         var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1000                         s3 = iptr->val.l >> 32;
1001                         if (s3 == -1)
1002                                 M_ADDME(s1, d);
1003                         else if (s3 == 0)
1004                                 M_ADDZE(s1, d);
1005                         else {
1006                                 ICONST(REG_ITMP3, s3);
1007                                 M_ADDE(s1, REG_ITMP3, d);
1008                         }
1009                         store_reg_to_var_int(iptr->dst, d);
1010                         break;
1011
1012                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1013
1014                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1015                         var_to_reg_int(s2, src, REG_ITMP2);
1016                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1017                         M_ISUB(s1, s2, d);
1018                         store_reg_to_var_int(iptr->dst, d);
1019                         break;
1020
1021                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
1022                                       /* val.i = constant                             */
1023
1024                         var_to_reg_int(s1, src, REG_ITMP1);
1025                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1026                         if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1027                                 M_IADD_IMM(s1, -iptr->val.i, d);
1028                                 }
1029                         else {
1030                                 ICONST(REG_ITMP2, -iptr->val.i);
1031                                 M_IADD(s1, REG_ITMP2, d);
1032                                 }
1033                         store_reg_to_var_int(iptr->dst, d);
1034                         break;
1035
1036         case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1037
1038             var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1039             var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1040             d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1041             M_SUBC(s1, s2, rd->secondregs[d]);
1042             var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1043             var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1044             M_SUBE(s1, s2, d);
1045             store_reg_to_var_int(iptr->dst, d);
1046             break;
1047
1048                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
1049                                       /* val.l = constant                             */
1050
1051                         s3 = (-iptr->val.l) & 0xffffffff;
1052                         var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1053                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1054                         if ((s3 >= -32768) && (s3 <= 32767)) {
1055                                 M_ADDIC(s1, s3, rd->secondregs[d]);
1056                                 }
1057                         else {
1058                                 ICONST(REG_ITMP2, s3);
1059                                 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
1060                                 }
1061                         var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1062                         s3 = (-iptr->val.l) >> 32;
1063                         if (s3 == -1)
1064                                 M_ADDME(s1, d);
1065                         else if (s3 == 0)
1066                                 M_ADDZE(s1, d);
1067                         else {
1068                                 ICONST(REG_ITMP3, s3);
1069                                 M_ADDE(s1, REG_ITMP3, d);
1070                         }
1071                         store_reg_to_var_int(iptr->dst, d);
1072                         break;
1073
1074                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1075                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1076                         var_to_reg_int(s2, src, REG_ITMP2);
1077                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1078                         M_IDIV(s1, s2, d);
1079                         store_reg_to_var_int(iptr->dst, d);
1080                         break;
1081
1082                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
1083                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1084                         var_to_reg_int(s2, src, REG_ITMP2);
1085                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1086                         M_IDIV(s1, s2, d);
1087                         M_IMUL(d, s2, d);
1088                         M_ISUB(s1, d, d);
1089                         store_reg_to_var_int(iptr->dst, d);
1090                         break;
1091
1092                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1093
1094                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1095                         var_to_reg_int(s2, src, REG_ITMP2);
1096                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1097                         M_IMUL(s1, s2, d);
1098                         store_reg_to_var_int(iptr->dst, d);
1099                         break;
1100
1101                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
1102                                       /* val.i = constant                             */
1103
1104                         var_to_reg_int(s1, src, REG_ITMP1);
1105                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1106                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1107                                 M_IMUL_IMM(s1, iptr->val.i, d);
1108                                 }
1109                         else {
1110                                 ICONST(REG_ITMP2, iptr->val.i);
1111                                 M_IMUL(s1, REG_ITMP2, d);
1112                                 }
1113                         store_reg_to_var_int(iptr->dst, d);
1114                         break;
1115
1116                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
1117                                       
1118                         var_to_reg_int(s1, src, REG_ITMP1);
1119                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1120                         M_SRA_IMM(s1, iptr->val.i, d);
1121                         M_ADDZE(d, d);
1122                         store_reg_to_var_int(iptr->dst, d);
1123                         break;
1124
1125                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
1126
1127                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1128                         var_to_reg_int(s2, src, REG_ITMP2);
1129                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1130                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
1131                         M_SLL(s1, REG_ITMP3, d);
1132                         store_reg_to_var_int(iptr->dst, d);
1133                         break;
1134
1135                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
1136                                       /* val.i = constant                             */
1137
1138                         var_to_reg_int(s1, src, REG_ITMP1);
1139                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1140                         M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1141                         store_reg_to_var_int(iptr->dst, d);
1142                         break;
1143
1144                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1145
1146                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1147                         var_to_reg_int(s2, src, REG_ITMP2);
1148                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1149                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
1150                         M_SRA(s1, REG_ITMP3, d);
1151                         store_reg_to_var_int(iptr->dst, d);
1152                         break;
1153
1154                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
1155                                       /* val.i = constant                             */
1156
1157                         var_to_reg_int(s1, src, REG_ITMP1);
1158                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1159                         M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1160                         store_reg_to_var_int(iptr->dst, d);
1161                         break;
1162
1163                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1164
1165                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1166                         var_to_reg_int(s2, src, REG_ITMP2);
1167                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1168                         M_AND_IMM(s2, 0x1f, REG_ITMP2);
1169                         M_SRL(s1, REG_ITMP2, d);
1170                         store_reg_to_var_int(iptr->dst, d);
1171                         break;
1172
1173                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1174                                       /* val.i = constant                             */
1175
1176                         var_to_reg_int(s1, src, REG_ITMP1);
1177                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1178                         if (iptr->val.i & 0x1f)
1179                                 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1180                         else
1181                                 M_INTMOVE(s1, d);
1182                         store_reg_to_var_int(iptr->dst, d);
1183                         break;
1184
1185                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1186
1187                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1188                         var_to_reg_int(s2, src, REG_ITMP2);
1189                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1190                         M_AND(s1, s2, d);
1191                         store_reg_to_var_int(iptr->dst, d);
1192                         break;
1193
1194                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
1195                                       /* val.i = constant                             */
1196
1197                         var_to_reg_int(s1, src, REG_ITMP1);
1198                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1199                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1200                                 M_AND_IMM(s1, iptr->val.i, d);
1201                                 }
1202                         /*
1203                         else if (iptr->val.i == 0xffffff) {
1204                                 M_RLWINM(s1, 0, 8, 31, d);
1205                                 }
1206                         */
1207                         else {
1208                                 ICONST(REG_ITMP2, iptr->val.i);
1209                                 M_AND(s1, REG_ITMP2, d);
1210                                 }
1211                         store_reg_to_var_int(iptr->dst, d);
1212                         break;
1213
1214                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1215
1216                         var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1217             var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1218             d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1219             M_AND(s1, s2, rd->secondregs[d]);
1220             var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1221             var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1222             M_AND(s1, s2, d);
1223             store_reg_to_var_int(iptr->dst, d);
1224             break;
1225
1226                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1227                                       /* val.l = constant                             */
1228
1229                         s3 = iptr->val.l & 0xffffffff;
1230                         var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1231                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1232                         if ((s3 >= 0) && (s3 <= 65535)) {
1233                                 M_AND_IMM(s1, s3, rd->secondregs[d]);
1234                                 }
1235                         else {
1236                                 ICONST(REG_ITMP2, s3);
1237                                 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1238                                 }
1239                         var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1240                         s3 = iptr->val.l >> 32;
1241                         if ((s3 >= 0) && (s3 <= 65535)) {
1242                                 M_AND_IMM(s1, s3, d);
1243                                 }
1244                         else {
1245                                 ICONST(REG_ITMP3, s3);
1246                                 M_AND(s1, REG_ITMP3, d);
1247                                 }
1248                         store_reg_to_var_int(iptr->dst, d);
1249                         break;
1250
1251                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
1252                                       /* val.i = constant                             */
1253
1254                         var_to_reg_int(s1, src, REG_ITMP1);
1255                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1256                         M_MOV(s1, REG_ITMP2);
1257                         M_CMPI(s1, 0);
1258                         M_BGE(1 + 2*(iptr->val.i >= 32768));
1259                         if (iptr->val.i >= 32768) {
1260                                 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1261                                 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1262                                 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1263                                 } 
1264                         else
1265                                 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1266                         {
1267                                 int b=0, m = iptr->val.i;
1268                                 while (m >>= 1)
1269                                         ++b;
1270                                 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1271                         }
1272                         M_ISUB(s1, REG_ITMP2, d);
1273                         store_reg_to_var_int(iptr->dst, d);
1274                         break;
1275
1276                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1277
1278                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1279                         var_to_reg_int(s2, src, REG_ITMP2);
1280                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1281                         M_OR(s1, s2, d);
1282                         store_reg_to_var_int(iptr->dst, d);
1283                         break;
1284
1285                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
1286                                       /* val.i = constant                             */
1287
1288                         var_to_reg_int(s1, src, REG_ITMP1);
1289                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1290                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1291                                 M_OR_IMM(s1, iptr->val.i, d);
1292                                 }
1293                         else {
1294                                 ICONST(REG_ITMP2, iptr->val.i);
1295                                 M_OR(s1, REG_ITMP2, d);
1296                                 }
1297                         store_reg_to_var_int(iptr->dst, d);
1298                         break;
1299
1300                 case ICMD_LOR:       /* ..., val1, val2  ==> ..., val1 | val2        */
1301
1302                         var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1303             var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1304             d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1305             M_OR(s1, s2, rd->secondregs[d]);
1306             var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1307             var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1308             M_OR(s1, s2, d);
1309             store_reg_to_var_int(iptr->dst, d);
1310             break;
1311
1312                 case ICMD_LORCONST:  /* ..., value  ==> ..., value | constant        */
1313                                       /* val.l = constant                             */
1314
1315                         s3 = iptr->val.l & 0xffffffff;
1316                         var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1317                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1318                         if ((s3 >= 0) && (s3 <= 65535)) {
1319                                 M_OR_IMM(s1, s3, rd->secondregs[d]);
1320                                 }
1321                         else {
1322                                 ICONST(REG_ITMP2, s3);
1323                                 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1324                                 }
1325                         var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1326                         s3 = iptr->val.l >> 32;
1327                         if ((s3 >= 0) && (s3 <= 65535)) {
1328                                 M_OR_IMM(s1, s3, d);
1329                                 }
1330                         else {
1331                                 ICONST(REG_ITMP3, s3);
1332                                 M_OR(s1, REG_ITMP3, d);
1333                                 }
1334                         store_reg_to_var_int(iptr->dst, d);
1335                         break;
1336
1337                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1338
1339                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1340                         var_to_reg_int(s2, src, REG_ITMP2);
1341                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1342                         M_XOR(s1, s2, d);
1343                         store_reg_to_var_int(iptr->dst, d);
1344                         break;
1345
1346                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1347                                       /* val.i = constant                             */
1348
1349                         var_to_reg_int(s1, src, REG_ITMP1);
1350                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1351                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1352                                 M_XOR_IMM(s1, iptr->val.i, d);
1353                                 }
1354                         else {
1355                                 ICONST(REG_ITMP2, iptr->val.i);
1356                                 M_XOR(s1, REG_ITMP2, d);
1357                                 }
1358                         store_reg_to_var_int(iptr->dst, d);
1359                         break;
1360
1361                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1362
1363                         var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1364             var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1365             d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1366             M_XOR(s1, s2, rd->secondregs[d]);
1367             var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1368             var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1369             M_XOR(s1, s2, d);
1370             store_reg_to_var_int(iptr->dst, d);
1371             break;
1372
1373                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1374                                       /* val.l = constant                             */
1375
1376                         s3 = iptr->val.l & 0xffffffff;
1377                         var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1378                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1379                         if ((s3 >= 0) && (s3 <= 65535)) {
1380                                 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1381                                 }
1382                         else {
1383                                 ICONST(REG_ITMP2, s3);
1384                                 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1385                                 }
1386                         var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1387                         s3 = iptr->val.l >> 32;
1388                         if ((s3 >= 0) && (s3 <= 65535)) {
1389                                 M_XOR_IMM(s1, s3, d);
1390                                 }
1391                         else {
1392                                 ICONST(REG_ITMP3, s3);
1393                                 M_XOR(s1, REG_ITMP3, d);
1394                                 }
1395                         store_reg_to_var_int(iptr->dst, d);
1396                         break;
1397
1398                 case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
1399
1400                         var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1401                         var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1402                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1403                         {
1404                                 int tempreg =
1405                                         (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1406                                 int dreg = tempreg ? REG_ITMP1 : d;
1407                                 s4 *br1;
1408                                 M_IADD_IMM(REG_ZERO, 1, dreg);
1409                                 M_CMP(s1, s2);
1410                                 M_BGT(0);
1411                                 br1 = mcodeptr;
1412                                 M_BLT(0);
1413                                 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1414                                 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1415                                 M_CMPU(s1, s2);
1416                                 M_BGT(3);
1417                                 M_BEQ(1);
1418                                 M_IADD_IMM(dreg, -1, dreg);
1419                                 M_IADD_IMM(dreg, -1, dreg);
1420                                 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1421                                 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1422                                 M_INTMOVE(dreg, d);
1423                         }
1424                         store_reg_to_var_int(iptr->dst, d);
1425                         break;
1426
1427                 case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
1428                                       /* op1 = variable, val.i = constant             */
1429
1430             var = &(rd->locals[iptr->op1][TYPE_INT]);
1431             if (var->flags & INMEMORY) {
1432                 s1 = REG_ITMP1;
1433                 M_ILD(s1, REG_SP, 4 * var->regoff);
1434                 }
1435             else
1436                 s1 = var->regoff;
1437                         {
1438                                 u4 m = iptr->val.i;
1439                                 if (m&0x8000)
1440                                         m += 65536;
1441                                 if (m&0xffff0000)
1442                                         M_ADDIS(s1, m>>16, s1);
1443                                 if (m&0xffff)
1444                                         M_IADD_IMM(s1, m&0xffff, s1);
1445                         }
1446             if (var->flags & INMEMORY)
1447                                 M_IST(s1, REG_SP, 4 * var->regoff);
1448                         break;
1449
1450
1451                 /* floating operations ************************************************/
1452
1453                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1454
1455                         var_to_reg_flt(s1, src, REG_FTMP1);
1456                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1457                         M_FMOVN(s1, d);
1458                         store_reg_to_var_flt(iptr->dst, d);
1459                         break;
1460
1461                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1462
1463                         var_to_reg_flt(s1, src, REG_FTMP1);
1464                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1465                         M_FMOVN(s1, d);
1466                         store_reg_to_var_flt(iptr->dst, d);
1467                         break;
1468
1469                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1470
1471                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1472                         var_to_reg_flt(s2, src, REG_FTMP2);
1473                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1474                         M_FADD(s1, s2, d);
1475                         store_reg_to_var_flt(iptr->dst, d);
1476                         break;
1477
1478                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1479
1480                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1481                         var_to_reg_flt(s2, src, REG_FTMP2);
1482                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1483                         M_DADD(s1, s2, d);
1484                         store_reg_to_var_flt(iptr->dst, d);
1485                         break;
1486
1487                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1488
1489                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1490                         var_to_reg_flt(s2, src, REG_FTMP2);
1491                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1492                         M_FSUB(s1, s2, d);
1493                         store_reg_to_var_flt(iptr->dst, d);
1494                         break;
1495
1496                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1497
1498                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1499                         var_to_reg_flt(s2, src, REG_FTMP2);
1500                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1501                         M_DSUB(s1, s2, d);
1502                         store_reg_to_var_flt(iptr->dst, d);
1503                         break;
1504
1505                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1506
1507                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1508                         var_to_reg_flt(s2, src, REG_FTMP2);
1509                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1510                         M_FMUL(s1, s2, d);
1511                         store_reg_to_var_flt(iptr->dst, d);
1512                         break;
1513
1514                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 *** val2        */
1515
1516                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1517                         var_to_reg_flt(s2, src, REG_FTMP2);
1518                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1519                         M_DMUL(s1, s2, d);
1520                         store_reg_to_var_flt(iptr->dst, d);
1521                         break;
1522
1523                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1524
1525                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1526                         var_to_reg_flt(s2, src, REG_FTMP2);
1527                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1528                         M_FDIV(s1, s2, d);
1529                         store_reg_to_var_flt(iptr->dst, d);
1530                         break;
1531
1532                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1533
1534                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1535                         var_to_reg_flt(s2, src, REG_FTMP2);
1536                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1537                         M_DDIV(s1, s2, d);
1538                         store_reg_to_var_flt(iptr->dst, d);
1539                         break;
1540                 
1541                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1542                 case ICMD_D2I:
1543                         var_to_reg_flt(s1, src, REG_FTMP1);
1544                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1545                         M_CLR(d);
1546                         a = dseg_addfloat(cd, 0.0);
1547                         M_FLD(REG_FTMP2, REG_PV, a);
1548                         M_FCMPU(s1, REG_FTMP2);
1549                         M_BNAN(4);
1550                         a = dseg_adds4(cd, 0);
1551                         M_CVTDL_C(s1, REG_FTMP1);
1552                         M_LDA (REG_ITMP1, REG_PV, a);
1553                         M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1554                         M_ILD (d, REG_PV, a);
1555                         store_reg_to_var_int(iptr->dst, d);
1556                         break;
1557                 
1558                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1559
1560                         var_to_reg_flt(s1, src, REG_FTMP1);
1561                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1562                         M_FLTMOVE(s1, d);
1563                         store_reg_to_var_flt(iptr->dst, d);
1564                         break;
1565                                         
1566                 case ICMD_D2F:       /* ..., value  ==> ..., (double) value           */
1567
1568                         var_to_reg_flt(s1, src, REG_FTMP1);
1569                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1570                         M_CVTDF(s1, d);
1571                         store_reg_to_var_flt(iptr->dst, d);
1572                         break;
1573                 
1574                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1575                 case ICMD_DCMPL:
1576                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1577                         var_to_reg_flt(s2, src, REG_FTMP2);
1578                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1579                         M_FCMPU(s2, s1);
1580                         M_IADD_IMM(0, -1, d);
1581                         M_BNAN(4);
1582                         M_BGT(3);
1583                         M_IADD_IMM(0, 0, d);
1584                         M_BGE(1);
1585                         M_IADD_IMM(0, 1, d);
1586                         store_reg_to_var_int(iptr->dst, d);
1587                         break;
1588
1589                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1590                 case ICMD_DCMPG:
1591                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1592                         var_to_reg_flt(s2, src, REG_FTMP2);
1593                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1594                         M_FCMPU(s1, s2);
1595                         M_IADD_IMM(0, 1, d);
1596                         M_BNAN(4);
1597                         M_BGT(3);
1598                         M_IADD_IMM(0, 0, d);
1599                         M_BGE(1);
1600                         M_IADD_IMM(0, -1, d);
1601                         store_reg_to_var_int(iptr->dst, d);
1602                         break;
1603                         
1604
1605                 /* memory operations **************************************************/
1606
1607                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1608
1609                         var_to_reg_int(s1, src, REG_ITMP1);
1610                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1611                         gen_nullptr_check(s1);
1612                         M_ILD(d, s1, OFFSET(java_arrayheader, size));
1613                         store_reg_to_var_int(iptr->dst, d);
1614                         break;
1615
1616                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1617
1618                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1619                         var_to_reg_int(s2, src, REG_ITMP2);
1620                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1621                         if (iptr->op1 == 0) {
1622                                 gen_nullptr_check(s1);
1623                                 gen_bound_check;
1624                                 }
1625                         M_SLL_IMM(s2, 2, REG_ITMP2);
1626                         M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1627                         M_LWZX(d, s1, REG_ITMP2);
1628                         store_reg_to_var_int(iptr->dst, d);
1629                         break;
1630
1631                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1632
1633                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1634                         var_to_reg_int(s2, src, REG_ITMP2);
1635                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1636                         if (iptr->op1 == 0) {
1637                                 gen_nullptr_check(s1);
1638                                 gen_bound_check;
1639                                 }
1640                         M_SLL_IMM(s2, 3, REG_ITMP2);
1641                         M_IADD(s1, REG_ITMP2, REG_ITMP2);
1642                         M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1643                         M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1644                         store_reg_to_var_int(iptr->dst, d);
1645                         break;
1646
1647                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1648
1649                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1650                         var_to_reg_int(s2, src, REG_ITMP2);
1651                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1652                         if (iptr->op1 == 0) {
1653                                 gen_nullptr_check(s1);
1654                                 gen_bound_check;
1655                                 }
1656                         M_SLL_IMM(s2, 2, REG_ITMP2);
1657                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1658                         M_LWZX(d, s1, REG_ITMP2);
1659                         store_reg_to_var_int(iptr->dst, d);
1660                         break;
1661
1662                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1663
1664                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1665                         var_to_reg_int(s2, src, REG_ITMP2);
1666                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1667                         if (iptr->op1 == 0) {
1668                                 gen_nullptr_check(s1);
1669                                 gen_bound_check;
1670                                 }
1671                         M_SLL_IMM(s2, 2, REG_ITMP2);
1672                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1673                         M_LFSX(d, s1, REG_ITMP2);
1674                         store_reg_to_var_flt(iptr->dst, d);
1675                         break;
1676
1677                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1678
1679                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1680                         var_to_reg_int(s2, src, REG_ITMP2);
1681                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1682                         if (iptr->op1 == 0) {
1683                                 gen_nullptr_check(s1);
1684                                 gen_bound_check;
1685                                 }
1686                         M_SLL_IMM(s2, 3, REG_ITMP2);
1687                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1688                         M_LFDX(d, s1, REG_ITMP2);
1689                         store_reg_to_var_flt(iptr->dst, d);
1690                         break;
1691
1692                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1693
1694                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1695                         var_to_reg_int(s2, src, REG_ITMP2);
1696                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1697                         if (iptr->op1 == 0) {
1698                                 gen_nullptr_check(s1);
1699                                 gen_bound_check;
1700                                 }
1701                         M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1702                         M_LBZX(d, s1, REG_ITMP2);
1703                         M_BSEXT(d, d);
1704                         store_reg_to_var_int(iptr->dst, d);
1705                         break;                  
1706
1707                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1708
1709                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1710                         var_to_reg_int(s2, src, REG_ITMP2);
1711                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1712                         if (iptr->op1 == 0) {
1713                                 gen_nullptr_check(s1);
1714                                 gen_bound_check;
1715                                 }
1716                         M_SLL_IMM(s2, 1, REG_ITMP2);
1717                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1718                         M_LHAX(d, s1, REG_ITMP2);
1719                         store_reg_to_var_int(iptr->dst, d);
1720                         break;
1721
1722                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1723
1724                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1725                         var_to_reg_int(s2, src, REG_ITMP2);
1726                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1727                         if (iptr->op1 == 0) {
1728                                 gen_nullptr_check(s1);
1729                                 gen_bound_check;
1730                                 }
1731                         M_SLL_IMM(s2, 1, REG_ITMP2);
1732                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1733                         M_LHZX(d, s1, REG_ITMP2);
1734                         store_reg_to_var_int(iptr->dst, d);
1735                         break;
1736
1737                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1738
1739                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1740                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1741                         if (iptr->op1 == 0) {
1742                                 gen_nullptr_check(s1);
1743                                 gen_bound_check;
1744                                 }
1745                         var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1746                         M_SLL_IMM(s2, 3, REG_ITMP2);
1747                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1748                         M_STWX(s3, s1, REG_ITMP2);
1749                         M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1750                         var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1751                         M_STWX(s3, s1, REG_ITMP2);
1752                         break;
1753
1754                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1755
1756                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1757                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1758                         if (iptr->op1 == 0) {
1759                                 gen_nullptr_check(s1);
1760                                 gen_bound_check;
1761                                 }
1762                         var_to_reg_int(s3, src, REG_ITMP3);
1763                         M_SLL_IMM(s2, 2, REG_ITMP2);
1764                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1765                         M_STWX(s3, s1, REG_ITMP2);
1766                         break;
1767
1768                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1769
1770                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1771                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1772                         if (iptr->op1 == 0) {
1773                                 gen_nullptr_check(s1);
1774                                 gen_bound_check;
1775                                 }
1776                         var_to_reg_flt(s3, src, REG_FTMP3);
1777                         M_SLL_IMM(s2, 2, REG_ITMP2);
1778                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1779                         M_STFSX(s3, s1, REG_ITMP2);
1780                         break;
1781
1782                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1783
1784                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1785                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1786                         if (iptr->op1 == 0) {
1787                                 gen_nullptr_check(s1);
1788                                 gen_bound_check;
1789                                 }
1790                         var_to_reg_flt(s3, src, REG_FTMP3);
1791                         M_SLL_IMM(s2, 3, REG_ITMP2);
1792                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1793                         M_STFDX(s3, s1, REG_ITMP2);
1794                         break;
1795
1796                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1797
1798                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1799                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1800                         if (iptr->op1 == 0) {
1801                                 gen_nullptr_check(s1);
1802                                 gen_bound_check;
1803                                 }
1804                         var_to_reg_int(s3, src, REG_ITMP3);
1805                         M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1806                         M_STBX(s3, s1, REG_ITMP2);
1807                         break;
1808
1809                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1810
1811                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1812                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1813                         if (iptr->op1 == 0) {
1814                                 gen_nullptr_check(s1);
1815                                 gen_bound_check;
1816                                 }
1817                         var_to_reg_int(s3, src, REG_ITMP3);
1818                         M_SLL_IMM(s2, 1, REG_ITMP2);
1819                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1820                         M_STHX(s3, s1, REG_ITMP2);
1821                         break;
1822
1823                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1824
1825                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1826                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1827                         if (iptr->op1 == 0) {
1828                                 gen_nullptr_check(s1);
1829                                 gen_bound_check;
1830                                 }
1831                         var_to_reg_int(s3, src, REG_ITMP3);
1832                         M_SLL_IMM(s2, 1, REG_ITMP2);
1833                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1834                         M_STHX(s3, s1, REG_ITMP2);
1835                         break;
1836
1837
1838                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1839                                       /* op1 = type, val.a = field address            */
1840
1841
1842                         if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1843                                 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1844
1845                                 M_ALD(REG_ITMP1, REG_PV, a);
1846                                 a = dseg_addaddress(cd, asm_wrapper_patcher);
1847                                 M_ALD(REG_ITMP2, REG_PV, a);
1848                                 M_MTCTR(REG_ITMP2);
1849                                 M_JSR;
1850
1851 #if 0
1852                                 /* recompute pv */
1853                                 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1854                                 M_MFLR(REG_ITMP1);
1855                                 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1856                                 else {
1857                                         s4 ml = -s1, mh = 0;
1858                                         while (ml < -32768) { ml += 65536; mh--; }
1859                                         M_LDA(REG_PV, REG_ITMP1, ml);
1860                                         M_LDAH(REG_PV, REG_PV, mh);
1861                                 }
1862 #endif
1863                         }
1864
1865                         a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1866                         M_ALD(REG_ITMP1, REG_PV, a);
1867                         switch (iptr->op1) {
1868                         case TYPE_INT:
1869                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1870                                 M_ILD(d, REG_ITMP1, 0);
1871                                 store_reg_to_var_int(iptr->dst, d);
1872                                 break;
1873                         case TYPE_LNG:
1874                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1875                                 M_ILD(d, REG_ITMP1, 0);
1876                                 M_ILD(rd->secondregs[d], REG_ITMP1, 4);
1877                                 store_reg_to_var_int(iptr->dst, d);
1878                                 break;
1879                         case TYPE_ADR:
1880                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1881                                 M_ALD(d, REG_ITMP1, 0);
1882                                 store_reg_to_var_int(iptr->dst, d);
1883                                 break;
1884                         case TYPE_FLT:
1885                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1886                                 M_FLD(d, REG_ITMP1, 0);
1887                                 store_reg_to_var_flt(iptr->dst, d);
1888                                 break;
1889                         case TYPE_DBL:                          
1890                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1891                                 M_DLD(d, REG_ITMP1, 0);
1892                                 store_reg_to_var_flt(iptr->dst, d);
1893                                 break;
1894                         }
1895                         break;
1896
1897                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1898                                       /* op1 = type, val.a = field address            */
1899 #if 1
1900                         if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1901                                 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1902                                 M_ALD(REG_ITMP1, REG_PV, a);
1903                                 a = dseg_addaddress(cd, asm_wrapper_patcher);
1904                                 M_ALD(REG_ITMP2, REG_PV, a);
1905                                 M_MTCTR(REG_ITMP2);
1906                                 M_JSR;
1907
1908 #if 0
1909                                 /* recompute pv */
1910                                 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1911                                 M_MFLR(REG_ITMP1);
1912                                 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1913                                 else {
1914                                         s4 ml = -s1, mh = 0;
1915                                         while (ml < -32768) { ml += 65536; mh--; }
1916                                         M_LDA(REG_PV, REG_ITMP1, ml);
1917                                         M_LDAH(REG_PV, REG_PV, mh);
1918                                 }
1919 #endif
1920                         }
1921 #else
1922                         {
1923                                 fieldinfo *fi = iptr->val.a;
1924
1925                                 if (!fi->class->initialized) {
1926                                         codegen_addpatchref(cd, mcodeptr,
1927 /*                                                                              PATCHER_clinit, fi->class);*/
1928                                                                                 NULL, fi->class);
1929
1930                                         if (showdisassemble)
1931                                                 M_NOP;
1932                                 }
1933
1934                                 a = (ptrint) &(fi->value);
1935                         }
1936
1937                         a = dseg_addaddress(cd, a);
1938 #endif
1939                         a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1940                         M_ALD(REG_ITMP1, REG_PV, a);
1941                         switch (iptr->op1) {
1942                         case TYPE_INT:
1943                                 var_to_reg_int(s2, src, REG_ITMP2);
1944                                 M_IST(s2, REG_ITMP1, 0);
1945                                 break;
1946                         case TYPE_LNG:
1947                                 var_to_reg_int(s2, src, REG_ITMP3);
1948                                 M_IST(s2, REG_ITMP1, 0);
1949                                 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1950                                 break;
1951                         case TYPE_ADR:
1952                                 var_to_reg_int(s2, src, REG_ITMP2);
1953                                 M_AST(s2, REG_ITMP1, 0);
1954                                 break;
1955                         case TYPE_FLT:
1956                                 var_to_reg_flt(s2, src, REG_FTMP2);
1957                                 M_FST(s2, REG_ITMP1, 0);
1958                                 break;
1959                         case TYPE_DBL:
1960                                 var_to_reg_flt(s2, src, REG_FTMP2);
1961                                 M_DST(s2, REG_ITMP1, 0);
1962                                 break;
1963                         }
1964                         break;
1965
1966
1967                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1968                                       /* op1 = type, val.i = field offset             */
1969
1970                         a = ((fieldinfo *)(iptr->val.a))->offset;
1971                         switch (iptr->op1) {
1972                         case TYPE_INT:
1973                                 var_to_reg_int(s1, src, REG_ITMP1);
1974                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1975                                 gen_nullptr_check(s1);
1976                                 M_ILD(d, s1, a);
1977                                 store_reg_to_var_int(iptr->dst, d);
1978                                 break;
1979                         case TYPE_LNG:
1980                                 var_to_reg_int(s1, src, REG_ITMP1);
1981                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1982                                 gen_nullptr_check(s1);
1983                                 M_ILD(d, s1, a);
1984                                 M_ILD(rd->secondregs[d], s1, a+4);
1985                                 store_reg_to_var_int(iptr->dst, d);
1986                                 break;
1987                         case TYPE_ADR:
1988                                 var_to_reg_int(s1, src, REG_ITMP1);
1989                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1990                                 gen_nullptr_check(s1);
1991                                 M_ALD(d, s1, a);
1992                                 store_reg_to_var_int(iptr->dst, d);
1993                                 break;
1994                         case TYPE_FLT:
1995                                 var_to_reg_int(s1, src, REG_ITMP1);
1996                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1997                                 gen_nullptr_check(s1);
1998                                 M_FLD(d, s1, a);
1999                                 store_reg_to_var_flt(iptr->dst, d);
2000                                 break;
2001                         case TYPE_DBL:                          
2002                                 var_to_reg_int(s1, src, REG_ITMP1);
2003                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2004                                 gen_nullptr_check(s1);
2005                                 M_DLD(d, s1, a);
2006                                 store_reg_to_var_flt(iptr->dst, d);
2007                                 break;
2008                         }
2009                         break;
2010
2011                 case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
2012                                       /* op1 = type, val.i = field offset             */
2013
2014                         a = ((fieldinfo *)(iptr->val.a))->offset;
2015                         switch (iptr->op1) {
2016                         case TYPE_INT:
2017                                 var_to_reg_int(s1, src->prev, REG_ITMP1);
2018                                 var_to_reg_int(s2, src, REG_ITMP2);
2019                                 gen_nullptr_check(s1);
2020                                 M_IST(s2, s1, a);
2021                                 break;
2022                         case TYPE_LNG:
2023                                 var_to_reg_int(s1, src->prev, REG_ITMP1);
2024                                 var_to_reg_int(s2, src, REG_ITMP3);
2025                                 gen_nullptr_check(s1);
2026                                 M_IST(s2, s1, a);
2027                                 M_IST(rd->secondregs[s2], s1, a+4);
2028                                 break;
2029                         case TYPE_ADR:
2030                                 var_to_reg_int(s1, src->prev, REG_ITMP1);
2031                                 var_to_reg_int(s2, src, REG_ITMP2);
2032                                 gen_nullptr_check(s1);
2033                                 M_AST(s2, s1, a);
2034                                 break;
2035                         case TYPE_FLT:
2036                                 var_to_reg_int(s1, src->prev, REG_ITMP1);
2037                                 var_to_reg_flt(s2, src, REG_FTMP2);
2038                                 gen_nullptr_check(s1);
2039                                 M_FST(s2, s1, a);
2040                                 break;
2041                         case TYPE_DBL:
2042                                 var_to_reg_int(s1, src->prev, REG_ITMP1);
2043                                 var_to_reg_flt(s2, src, REG_FTMP2);
2044                                 gen_nullptr_check(s1);
2045                                 M_DST(s2, s1, a);
2046                                 break;
2047                         }
2048                         break;
2049
2050
2051                 /* branch operations **************************************************/
2052
2053                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
2054
2055                         a = dseg_addaddress(cd, asm_handle_exception);
2056                         M_ALD(REG_ITMP2, REG_PV, a);
2057                         M_MTCTR(REG_ITMP2);
2058                         var_to_reg_int(s1, src, REG_ITMP1);
2059                         M_INTMOVE(s1, REG_ITMP1_XPTR);
2060
2061                         if (m->isleafmethod) M_MFLR(REG_ITMP3);  /* save LR */
2062                         M_BL(0);            /* get current PC */
2063                         M_MFLR(REG_ITMP2_XPC);
2064                         if (m->isleafmethod) M_MTLR(REG_ITMP3);  /* restore LR */
2065                         M_RTS;              /* jump to CTR */
2066
2067                         ALIGNCODENOP;
2068                         break;
2069
2070                 case ICMD_GOTO:         /* ... ==> ...                                */
2071                                         /* op1 = target JavaVM pc                     */
2072                         M_BR(0);
2073                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2074                         ALIGNCODENOP;
2075                         break;
2076
2077                 case ICMD_JSR:          /* ... ==> ...                                */
2078                                         /* op1 = target JavaVM pc                     */
2079
2080                         if (m->isleafmethod) M_MFLR(REG_ITMP2);
2081                         M_BL(0);
2082                         M_MFLR(REG_ITMP1);
2083                         M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2084                         if (m->isleafmethod) M_MTLR(REG_ITMP2);
2085                         M_BR(0);
2086                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2087                         break;
2088                         
2089                 case ICMD_RET:          /* ... ==> ...                                */
2090                                         /* op1 = local variable                       */
2091
2092                         var = &(rd->locals[iptr->op1][TYPE_ADR]);
2093                         if (var->flags & INMEMORY) {
2094                                 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2095                                 M_MTCTR(REG_ITMP1);
2096                                 }
2097                         else
2098                                 M_MTCTR(var->regoff);
2099                         M_RTS;
2100                         ALIGNCODENOP;
2101                         break;
2102
2103                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
2104                                         /* op1 = target JavaVM pc                     */
2105
2106                         var_to_reg_int(s1, src, REG_ITMP1);
2107                         M_TST(s1);
2108                         M_BEQ(0);
2109                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2110                         break;
2111
2112                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
2113                                         /* op1 = target JavaVM pc                     */
2114
2115                         var_to_reg_int(s1, src, REG_ITMP1);
2116                         M_TST(s1);
2117                         M_BNE(0);
2118                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2119                         break;
2120
2121                 case ICMD_IFLT:
2122                 case ICMD_IFLE:
2123                 case ICMD_IFNE:
2124                 case ICMD_IFGT:
2125                 case ICMD_IFGE:
2126                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
2127                                         /* op1 = target JavaVM pc, val.i = constant   */
2128
2129                         var_to_reg_int(s1, src, REG_ITMP1);
2130                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2131                                 M_CMPI(s1, iptr->val.i);
2132                                 }
2133                         else {
2134                                 ICONST(REG_ITMP2, iptr->val.i);
2135                                 M_CMP(s1, REG_ITMP2);
2136                                 }
2137                         switch (iptr->opc)
2138                         {
2139                                 case ICMD_IFLT:
2140                                         M_BLT(0);
2141                                         break;
2142                                 case ICMD_IFLE:
2143                                         M_BLE(0);
2144                                         break;
2145                                 case ICMD_IFNE:
2146                                         M_BNE(0);
2147                                         break;
2148                                 case ICMD_IFGT:
2149                                         M_BGT(0);
2150                                         break;
2151                                 case ICMD_IFGE:
2152                                         M_BGE(0);
2153                                         break;
2154                                 case ICMD_IFEQ:
2155                                         M_BEQ(0);
2156                                         break;
2157                                 }
2158                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2159                         break;
2160
2161
2162                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
2163                                         /* op1 = target JavaVM pc, val.l = constant   */
2164
2165             var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2166             var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2167                         if (iptr->val.l == 0) {
2168                                 M_OR(s1, s2, REG_ITMP3);
2169                                 M_CMPI(REG_ITMP3, 0);
2170
2171                         } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2172                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2173                                 M_BNE(2);
2174                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2175
2176                         } else {
2177                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2178                                 M_CMP(s2, REG_ITMP3);
2179                                 M_BNE(3);
2180                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2181                                 M_CMP(s1, REG_ITMP3)
2182                         }
2183                         M_BEQ(0);
2184                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2185                         break;
2186                         
2187                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
2188                                         /* op1 = target JavaVM pc, val.l = constant   */
2189             var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2190             var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2191 /*                      if (iptr->val.l == 0) { */
2192 /*                              M_OR(s1, s2, REG_ITMP3); */
2193 /*                              M_CMPI(REG_ITMP3, 0); */
2194
2195 /*                      } else  */
2196                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2197                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2198                                 M_BLT(0);
2199                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2200                                 M_BGT(2);
2201                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2202
2203                         } else {
2204                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2205                                 M_CMP(s2, REG_ITMP3);
2206                                 M_BLT(0);
2207                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2208                                 M_BGT(3);
2209                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2210                                 M_CMP(s1, REG_ITMP3)
2211                         }
2212                         M_BLT(0);
2213                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2214                         break;
2215                         
2216                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
2217                                         /* op1 = target JavaVM pc, val.l = constant   */
2218
2219             var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2220             var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2221 /*                      if (iptr->val.l == 0) { */
2222 /*                              M_OR(s1, s2, REG_ITMP3); */
2223 /*                              M_CMPI(REG_ITMP3, 0); */
2224
2225 /*                      } else  */
2226                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2227                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2228                                 M_BLT(0);
2229                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2230                                 M_BGT(2);
2231                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2232
2233                         } else {
2234                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2235                                 M_CMP(s2, REG_ITMP3);
2236                                 M_BLT(0);
2237                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2238                                 M_BGT(3);
2239                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2240                                 M_CMP(s1, REG_ITMP3)
2241                         }
2242                         M_BLE(0);
2243                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2244                         break;
2245                         
2246                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
2247                                         /* op1 = target JavaVM pc, val.l = constant   */
2248
2249             var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2250             var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2251                         if (iptr->val.l == 0) {
2252                                 M_OR(s1, s2, REG_ITMP3);
2253                                 M_CMPI(REG_ITMP3, 0);
2254
2255                         } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2256                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2257                                 M_BEQ(2);
2258                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2259
2260                         } else {
2261                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2262                                 M_CMP(s2, REG_ITMP3);
2263                                 M_BEQ(3);
2264                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2265                                 M_CMP(s1, REG_ITMP3)
2266                         }
2267                         M_BNE(0);
2268                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2269                         break;
2270                         
2271                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
2272                                         /* op1 = target JavaVM pc, val.l = constant   */
2273
2274             var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2275             var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2276 /*                      if (iptr->val.l == 0) { */
2277 /*                              M_OR(s1, s2, REG_ITMP3); */
2278 /*                              M_CMPI(REG_ITMP3, 0); */
2279
2280 /*                      } else  */
2281                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2282                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2283                                 M_BGT(0);
2284                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2285                                 M_BLT(2);
2286                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2287
2288                         } else {
2289                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2290                                 M_CMP(s2, REG_ITMP3);
2291                                 M_BGT(0);
2292                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2293                                 M_BLT(3);
2294                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2295                                 M_CMP(s1, REG_ITMP3)
2296                         }
2297                         M_BGT(0);
2298                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2299                         break;
2300                         
2301                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
2302                                         /* op1 = target JavaVM pc, val.l = constant   */
2303             var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2304             var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2305 /*                      if (iptr->val.l == 0) { */
2306 /*                              M_OR(s1, s2, REG_ITMP3); */
2307 /*                              M_CMPI(REG_ITMP3, 0); */
2308
2309 /*                      } else  */
2310                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2311                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2312                                 M_BGT(0);
2313                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2314                                 M_BLT(2);
2315                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2316
2317                         } else {
2318                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2319                                 M_CMP(s2, REG_ITMP3);
2320                                 M_BGT(0);
2321                                 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2322                                 M_BLT(3);
2323                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2324                                 M_CMP(s1, REG_ITMP3)
2325                         }
2326                         M_BGE(0);
2327                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2328                         break;
2329
2330                         /* CUT: alle _L */
2331                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
2332                 case ICMD_IF_LCMPEQ:    /* op1 = target JavaVM pc                     */
2333                 case ICMD_IF_ACMPEQ:
2334
2335                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2336                         var_to_reg_int(s2, src, REG_ITMP2);
2337                         M_CMP(s1, s2);
2338                         M_BEQ(0);
2339                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2340                         break;
2341
2342                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
2343                 case ICMD_IF_LCMPNE:    /* op1 = target JavaVM pc                     */
2344                 case ICMD_IF_ACMPNE:
2345
2346                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2347                         var_to_reg_int(s2, src, REG_ITMP2);
2348                         M_CMP(s1, s2);
2349                         M_BNE(0);
2350                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2351                         break;
2352
2353                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
2354                 case ICMD_IF_LCMPLT:    /* op1 = target JavaVM pc                     */
2355
2356                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2357                         var_to_reg_int(s2, src, REG_ITMP2);
2358                         M_CMP(s1, s2);
2359                         M_BLT(0);
2360                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2361                         break;
2362
2363                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
2364                 case ICMD_IF_LCMPGT:    /* op1 = target JavaVM pc                     */
2365
2366                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2367                         var_to_reg_int(s2, src, REG_ITMP2);
2368                         M_CMP(s1, s2);
2369                         M_BGT(0);
2370                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2371                         break;
2372
2373                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
2374                 case ICMD_IF_LCMPLE:    /* op1 = target JavaVM pc                     */
2375
2376                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2377                         var_to_reg_int(s2, src, REG_ITMP2);
2378                         M_CMP(s1, s2);
2379                         M_BLE(0);
2380                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2381                         break;
2382
2383                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
2384                 case ICMD_IF_LCMPGE:    /* op1 = target JavaVM pc                     */
2385
2386                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2387                         var_to_reg_int(s2, src, REG_ITMP2);
2388                         M_CMP(s1, s2);
2389                         M_BGE(0);
2390                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2391                         break;
2392
2393                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2394                 case ICMD_LRETURN:
2395                 case ICMD_ARETURN:
2396                                 var_to_reg_int(s1, src, REG_RESULT);
2397                                 M_TINTMOVE(src->type, s1, REG_RESULT);
2398                                 goto nowperformreturn;
2399
2400                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2401                 case ICMD_DRETURN:
2402                                 var_to_reg_flt(s1, src, REG_FRESULT);
2403                                 M_FLTMOVE(s1, REG_FRESULT);
2404                                 goto nowperformreturn;
2405
2406                 case ICMD_RETURN:      /* ...  ==> ...                                */
2407
2408
2409
2410 nowperformreturn:
2411                         {
2412                         s4 i, p;
2413                         
2414                         p = parentargs_base;
2415                         /* call trace function */
2416
2417                         if (runverbose) {
2418                                 M_MFLR(REG_ITMP3);
2419                                 M_LDA(REG_SP, REG_SP, -10 * 8);
2420                                 M_DST(REG_FRESULT, REG_SP, 48+0);
2421                                 M_IST(REG_RESULT, REG_SP, 48+8);
2422                                 M_AST(REG_ITMP3, REG_SP, 48+12);
2423                                 M_IST(REG_RESULT2, REG_SP, 48+16);
2424                                 a = dseg_addaddress(cd, m);
2425
2426                                 /* keep this order */
2427                                 switch (iptr->opc) {
2428                                 case ICMD_IRETURN:
2429                                 case ICMD_ARETURN:
2430                                         M_MOV(REG_RESULT, rd->argintregs[2]);
2431                                         M_CLR(rd->argintregs[1]);
2432                                         break;
2433
2434                                 case ICMD_LRETURN:
2435                                         M_MOV(REG_RESULT2, rd->argintregs[2]);
2436                                         M_MOV(REG_RESULT, rd->argintregs[1]);
2437                                         break;
2438                                 }
2439                                 M_ALD(rd->argintregs[0], REG_PV, a);
2440
2441                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2442                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2443                                 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2444                                 M_ALD(REG_ITMP2, REG_PV, a);
2445                                 M_MTCTR(REG_ITMP2);
2446                                 M_JSR;
2447                                 M_DLD(REG_FRESULT, REG_SP, 48+0);
2448                                 M_ILD(REG_RESULT, REG_SP, 48+8);
2449                                 M_ALD(REG_ITMP3, REG_SP, 48+12);
2450                                 M_ILD(REG_RESULT2, REG_SP, 48+16);
2451                                 M_LDA(REG_SP, REG_SP, 10 * 8);
2452                                 M_MTLR(REG_ITMP3);
2453                         }
2454                         
2455 #if defined(USE_THREADS)
2456                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2457                                 /* we need to save the proper return value */
2458                                 switch (iptr->opc) {
2459                                 case ICMD_IRETURN:
2460                                 case ICMD_ARETURN:
2461                                         M_IST(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2462                                 case ICMD_LRETURN:
2463                                         M_IST(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2464                                         break;
2465                                 case ICMD_FRETURN:
2466                                         M_FST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2467                                         break;
2468                                 case ICMD_DRETURN:
2469                                         M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2470                                         break;
2471                                 }
2472
2473                                 a = dseg_addaddress(cd, (void *) (builtin_monitorexit));
2474                                 M_ALD(REG_ITMP3, REG_PV, a);
2475                                 M_MTCTR(REG_ITMP3);
2476                                 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2477                                 M_JSR;
2478
2479                                 /* and now restore the proper return value */
2480                                 switch (iptr->opc) {
2481                                 case ICMD_IRETURN:
2482                                 case ICMD_ARETURN:
2483                                         M_ILD(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2484                                 case ICMD_LRETURN:
2485                                         M_ILD(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2486                                         break;
2487                                 case ICMD_FRETURN:
2488                                         M_FLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2489                                         break;
2490                                 case ICMD_DRETURN:
2491                                         M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2492                                         break;
2493                                 }
2494                         }
2495 #endif
2496
2497                         /* restore return address                                         */
2498
2499                         if (!m->isleafmethod) {
2500                                 M_ALD(REG_ITMP3, REG_SP, 4 * p + 8);
2501                                 M_MTLR(REG_ITMP3);
2502                         }
2503
2504                         /* restore saved registers                                        */
2505
2506                         for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2507                                 p--; M_ILD(rd->savintregs[i], REG_SP, 4 * p);
2508                         }
2509                         for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2510                                 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, 4 * p);
2511                         }
2512
2513                         /* deallocate stack                                               */
2514
2515                         if (parentargs_base) {
2516                                 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2517                         }
2518
2519
2520
2521                         M_RET;
2522                         ALIGNCODENOP;
2523                         }
2524                         break;
2525
2526
2527                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2528                         {
2529                         s4 i, l, *s4ptr;
2530                         void **tptr;
2531
2532                         tptr = (void **) iptr->target;
2533
2534                         s4ptr = iptr->val.a;
2535                         l = s4ptr[1];                          /* low     */
2536                         i = s4ptr[2];                          /* high    */
2537                         
2538                         var_to_reg_int(s1, src, REG_ITMP1);
2539                         if (l == 0) {
2540                                 M_INTMOVE(s1, REG_ITMP1);
2541                         } else if (l <= 32768) {
2542                                 M_LDA(REG_ITMP1, s1, -l);
2543                         } else {
2544                                 ICONST(REG_ITMP2, l);
2545                                 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2546                         }
2547                         i = i - l + 1;
2548
2549                         /* range check */
2550
2551                         M_CMPUI(REG_ITMP1, i - 1);
2552                         M_BGT(0);
2553
2554                         /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2555                         codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2556
2557                         /* build jump table top down and use address of lowest entry */
2558
2559                         /* s4ptr += 3 + i; */
2560                         tptr += i;
2561
2562                         while (--i >= 0) {
2563                                 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2564                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
2565                                 --tptr;
2566                                 }
2567                         }
2568
2569                         /* length of dataseg after last dseg_addtarget is used by load */
2570
2571                         M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2572                         M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2573                         M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2574                         M_MTCTR(REG_ITMP2);
2575                         M_RTS;
2576                         ALIGNCODENOP;
2577                         break;
2578
2579
2580                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2581                         {
2582                         s4 i, l, val, *s4ptr;
2583                         void **tptr;
2584
2585                         tptr = (void **) iptr->target;
2586
2587                         s4ptr = iptr->val.a;
2588                         l = s4ptr[0];                          /* default  */
2589                         i = s4ptr[1];                          /* count    */
2590                         
2591                         MCODECHECK((i<<2)+8);
2592                         var_to_reg_int(s1, src, REG_ITMP1);
2593                         while (--i >= 0) {
2594                                 s4ptr += 2;
2595                                 ++tptr;
2596
2597                                 val = s4ptr[0];
2598                                 if ((val >= -32768) && (val <= 32767)) {
2599                                         M_CMPI(s1, val);
2600                                         } 
2601                                 else {
2602                                         a = dseg_adds4(cd, val);
2603                                         M_ILD(REG_ITMP2, REG_PV, a);
2604                                         M_CMP(s1, REG_ITMP2);
2605                                         }
2606                                 M_BEQ(0);
2607                                 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2608                                 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr); 
2609                                 }
2610
2611                         M_BR(0);
2612                         /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2613                         
2614                         tptr = (void **) iptr->target;
2615                         codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2616
2617                         ALIGNCODENOP;
2618                         break;
2619                         }
2620
2621
2622                 case ICMD_BUILTIN3:     /* ..., arg1, arg2, arg3 ==> ...              */
2623                                         /* op1 = return type, val.a = function pointer*/
2624                         s3 = 3;
2625                         goto gen_method;
2626
2627                 case ICMD_BUILTIN2:     /* ..., arg1, arg2 ==> ...                    */
2628                                         /* op1 = return type, val.a = function pointer*/
2629                         s3 = 2;
2630                         goto gen_method;
2631
2632                 case ICMD_BUILTIN1:     /* ..., arg1 ==> ...                          */
2633                                         /* op1 = return type, val.a = function pointer*/
2634                         s3 = 1;
2635                         goto gen_method;
2636
2637                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2638                                         /* op1 = arg count, val.a = method pointer    */
2639
2640                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2641                                         /* op1 = arg count, val.a = method pointer    */
2642
2643                 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2644                                         /* op1 = arg count, val.a = method pointer    */
2645
2646                 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2647                                         /* op1 = arg count, val.a = method pointer    */
2648
2649                         s3 = iptr->op1;
2650
2651 gen_method: {
2652                         methodinfo *lm;
2653                         classinfo  *ci;
2654
2655                         MCODECHECK((s3 << 1) + 64);
2656
2657                         {
2658                         /* copy arguments to registers or stack location                  */
2659
2660                                 stackptr srcsave = src;
2661                                 int s3save = s3;
2662                                 int fltcnt = 0;
2663                                 int argsize = 0;
2664                         for (; --s3 >= 0; src = src->prev) {
2665                                 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2666                                 if (IS_FLT_DBL_TYPE(src->type))
2667                                         ++fltcnt;
2668                                 }
2669
2670                         for (s3 = s3save, src = srcsave; --s3 >= 0; src = src->prev) {
2671                                 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2672                                 if (IS_FLT_DBL_TYPE(src->type))
2673                                         --fltcnt;
2674                                 if (src->varkind == ARGVAR)
2675                                         continue;
2676                                 if (IS_INT_LNG_TYPE(src->type)) {
2677                                         if (argsize < INT_ARG_CNT) {
2678                                                 s1 = rd->argintregs[argsize];
2679                                                 var_to_reg_int(d, src, s1);
2680                                                 if (argsize < INT_ARG_CNT-1) {
2681                                                         M_TINTMOVE(src->type, d, s1);
2682
2683                                                 } else {
2684                                                         M_INTMOVE(d, s1);
2685                                                         if (IS_2_WORD_TYPE(src->type))
2686                                                                 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2687                                                 }
2688
2689                                         } else {
2690                                                 var_to_reg_int(d, src, REG_ITMP1);
2691                                                 M_IST(d, REG_SP, 4 * (argsize + 6));
2692                                                 if (IS_2_WORD_TYPE(src->type))
2693                                                         M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2694                                         }
2695
2696                                 } else {
2697                                         if (fltcnt < FLT_ARG_CNT) {
2698                                                 s1 = rd->argfltregs[fltcnt];
2699                                                 var_to_reg_flt(d, src, s1);
2700                                                 M_FLTMOVE(d, s1);
2701
2702                                         } else {
2703                                                 var_to_reg_flt(d, src, REG_FTMP1);
2704                                                 if (IS_2_WORD_TYPE(src->type))
2705                                                         M_DST(d, REG_SP, 4 * (argsize + 6));
2706                                                 else
2707                                                         M_FST(d, REG_SP, 4 * (argsize + 6));
2708                                         }
2709                                 }
2710                         } /* end of for */
2711                         }
2712
2713                         lm = iptr->val.a;
2714                         switch (iptr->opc) {
2715                                 case ICMD_BUILTIN3:
2716                                 case ICMD_BUILTIN2:
2717                                 case ICMD_BUILTIN1:
2718                                         a = dseg_addaddress(cd, (void *) lm);
2719
2720                                         M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2721                                         d = iptr->op1;
2722                                         goto makeactualcall;
2723
2724                                 case ICMD_INVOKESTATIC:
2725                                 case ICMD_INVOKESPECIAL:
2726                                         a = dseg_addaddress(cd, lm->stubroutine);
2727
2728                                         M_ALD(REG_PV, REG_PV, a);       /* method pointer in r27 */
2729
2730                                         d = lm->returntype;
2731                                         goto makeactualcall;
2732
2733                                 case ICMD_INVOKEVIRTUAL:
2734
2735                                         gen_nullptr_check(rd->argintregs[0]);
2736                                         M_ALD(REG_METHODPTR, rd->argintregs[0],
2737                                                   OFFSET(java_objectheader, vftbl));
2738                                         M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2739                                                   sizeof(methodptr) * lm->vftblindex);
2740
2741                                         d = lm->returntype;
2742                                         goto makeactualcall;
2743
2744                                 case ICMD_INVOKEINTERFACE:
2745                                         ci = lm->class;
2746                                         
2747                                         gen_nullptr_check(rd->argintregs[0]);
2748                                         M_ALD(REG_METHODPTR, rd->argintregs[0],
2749                                                   OFFSET(java_objectheader, vftbl));    
2750                                         M_ALD(REG_METHODPTR, REG_METHODPTR,
2751                                               OFFSET(vftbl_t, interfacetable[0]) -
2752                                               sizeof(methodptr*) * ci->index);
2753                                         M_ALD(REG_PV, REG_METHODPTR,
2754                                                   sizeof(methodptr) * (lm - ci->methods));
2755
2756                                         d = lm->returntype;
2757                                         goto makeactualcall;
2758                                 }
2759
2760 makeactualcall:
2761                         M_MTCTR(REG_PV);
2762                         M_JSR;
2763
2764                         /* recompute pv */
2765
2766                         s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2767                         M_MFLR(REG_ITMP1);
2768                         if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2769                         else {
2770                                 s4 ml = -s1, mh = 0;
2771                                 while (ml < -32768) { ml += 65536; mh--; }
2772                                 M_LDA(REG_PV, REG_ITMP1, ml);
2773                                 M_LDAH(REG_PV, REG_PV, mh);
2774                         }
2775
2776                         /* d contains return type */
2777
2778                         if (d != TYPE_VOID) {
2779                                 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2780                                         s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2781                                         M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2782                                         store_reg_to_var_int(iptr->dst, s1);
2783
2784                                 } else {
2785                                         s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2786                                         M_FLTMOVE(REG_FRESULT, s1);
2787                                         store_reg_to_var_flt(iptr->dst, s1);
2788                                 }
2789                         }
2790                         }
2791                         break;
2792
2793
2794                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2795
2796                                       /* op1:   0 == array, 1 == class                */
2797                                       /* val.a: (classinfo*) superclass               */
2798
2799 /*          superclass is an interface:
2800  *
2801  *          return (sub != NULL) &&
2802  *                 (sub->vftbl->interfacetablelength > super->index) &&
2803  *                 (sub->vftbl->interfacetable[-super->index] != NULL);
2804  *
2805  *          superclass is a class:
2806  *
2807  *          return ((sub != NULL) && (0
2808  *                  <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2809  *                  super->vftbl->diffvall));
2810  */
2811
2812                         {
2813                         classinfo *super = (classinfo*) iptr->val.a;
2814                         
2815 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2816             codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2817 #endif
2818                         var_to_reg_int(s1, src, REG_ITMP1);
2819                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2820                         if (s1 == d) {
2821                                 M_MOV(s1, REG_ITMP1);
2822                                 s1 = REG_ITMP1;
2823                                 }
2824                         M_CLR(d);
2825                         if (iptr->op1) {                               /* class/interface */
2826                                 M_TST(s1);
2827                                 if (super->flags & ACC_INTERFACE) {        /* interface       */
2828                                         M_BEQ(9);
2829                                         M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2830                                         M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2831                                         M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2832                                         M_BLE(5);
2833                                         M_ALD(REG_ITMP1, REG_ITMP1,
2834                                               OFFSET(vftbl_t, interfacetable[0]) -
2835                                               super->index * sizeof(methodptr*));
2836                                         M_TST(REG_ITMP1);
2837                                         M_CLR(d);
2838                                         M_BEQ(1);
2839                                         M_IADD_IMM(REG_ZERO, 1, d);
2840                                         }
2841                                 else {                                     /* class           */
2842                                         M_BEQ(10);
2843                                         M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2844                                         a = dseg_addaddress(cd, (void*) super->vftbl);
2845                                         M_ALD(REG_ITMP2, REG_PV, a);
2846 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2847                                         codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2848 #endif
2849                                         M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2850                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2851                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2852 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2853                                         codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2854 #endif
2855                                         M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2856                                         M_CMPU(REG_ITMP1, REG_ITMP2);
2857                                         M_CLR(d);
2858                                         M_BGT(1);
2859                                         M_IADD_IMM(REG_ZERO, 1, d);
2860                                         }
2861                                 }
2862                         }
2863                         store_reg_to_var_int(iptr->dst, d);
2864                         break;
2865
2866                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2867
2868                                       /* op1:   0 == array, 1 == class                */
2869                                       /* val.a: (classinfo*) superclass               */
2870
2871 /*          superclass is an interface:
2872  *
2873  *          OK if ((sub == NULL) ||
2874  *                 (sub->vftbl->interfacetablelength > super->index) &&
2875  *                 (sub->vftbl->interfacetable[-super->index] != NULL));
2876  *
2877  *          superclass is a class:
2878  *
2879  *          OK if ((sub == NULL) || (0
2880  *                 <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2881  *                 super->vftbl->diffvall));
2882  */
2883
2884                         {
2885                         classinfo *super = (classinfo*) iptr->val.a;
2886                         
2887 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2888                         codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2889 #endif
2890                         var_to_reg_int(s1, src, REG_ITMP1);
2891                         if (iptr->op1) {                               /* class/interface */
2892                                 M_TST(s1);
2893                                 if (super->flags & ACC_INTERFACE) {        /* interface       */
2894                                         M_BEQ(7);
2895                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2896                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2897                                         M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2898                                         M_BLE(0);
2899                                         codegen_addxcastrefs(cd, mcodeptr);
2900                                         M_ALD(REG_ITMP3, REG_ITMP2,
2901                                               OFFSET(vftbl_t, interfacetable[0]) -
2902                                               super->index * sizeof(methodptr*));
2903                                         M_TST(REG_ITMP3);
2904                                         M_BEQ(0);
2905                                         codegen_addxcastrefs(cd, mcodeptr);
2906                                         }
2907                                 else {                                     /* class           */
2908                     M_BEQ(8 + (s1 == REG_ITMP1));
2909                     M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2910 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2911                                         codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2912 #endif
2913                     M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2914                     a = dseg_addaddress(cd, (void*) super->vftbl);
2915                     M_ALD(REG_ITMP2, REG_PV, a);
2916                     if (s1 != REG_ITMP1) {
2917                         M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2918                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2919 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2920                                                 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2921 #endif
2922                         M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2923                         }
2924                     else {
2925                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2926                         M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2927                         M_ALD(REG_ITMP2, REG_PV, a);
2928                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2929 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2930                                                 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2931 #endif
2932                         }
2933                     M_CMPU(REG_ITMP3, REG_ITMP2);
2934                     M_BGT(0);
2935                     codegen_addxcastrefs(cd, mcodeptr);
2936                     }
2937                                 }
2938                         }
2939                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2940                         M_INTMOVE(s1, d);
2941                         store_reg_to_var_int(iptr->dst, d);
2942                         break;
2943
2944                 case ICMD_CHECKASIZE:  /* ..., size ==> ..., size                     */
2945
2946                         var_to_reg_int(s1, src, REG_ITMP1);
2947                         M_CMPI(s1, 0);
2948                         M_BLT(0);
2949                         codegen_addxcheckarefs(cd, mcodeptr);
2950                         break;
2951
2952                 case ICMD_CHECKEXCEPTION:   /* ... ==> ...                            */
2953
2954                         M_CMPI(REG_RESULT, 0);
2955                         M_BEQ(0);
2956                         codegen_addxexceptionrefs(cd, mcodeptr);
2957                         break;
2958
2959                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2960                                       /* op1 = dimension, val.a = array descriptor    */
2961
2962                         /* check for negative sizes and copy sizes to stack if necessary  */
2963
2964                         MCODECHECK((iptr->op1 << 1) + 64);
2965
2966                         for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2967                                 var_to_reg_int(s2, src, REG_ITMP1);
2968                                 M_CMPI(s2, 0);
2969                                 M_BLT(0);
2970                                 codegen_addxcheckarefs(cd, mcodeptr);
2971
2972                                 /* copy SAVEDVAR sizes to stack */
2973
2974                                 if (src->varkind != ARGVAR) {
2975                                         M_IST(s2, REG_SP, (s1 + INT_ARG_CNT + 6) * 4);
2976                                 }
2977                         }
2978
2979                         /* a0 = dimension count */
2980
2981                         ICONST(rd->argintregs[0], iptr->op1);
2982
2983                         /* a1 = arraydescriptor */
2984
2985                         a = dseg_addaddress(cd, iptr->val.a);
2986                         M_ALD(rd->argintregs[1], REG_PV, a);
2987
2988                         /* a2 = pointer to dimensions = stack pointer */
2989
2990                         M_LDA(rd->argintregs[2], REG_SP, (INT_ARG_CNT + 6) * 4);
2991
2992                         a = dseg_addaddress(cd, BUILTIN_multianewarray);
2993                         M_ALD(REG_PV, REG_PV, a);
2994                         M_MTCTR(REG_PV);
2995                         M_JSR;
2996                         s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2997                         M_MFLR(REG_ITMP1);
2998                         if (s1 <= 32768)
2999                                 M_LDA (REG_PV, REG_ITMP1, -s1);
3000                         else {
3001                                 s4 ml = -s1, mh = 0;
3002                                 while (ml < -32768) {ml += 65536; mh--;}
3003                                 M_LDA(REG_PV, REG_ITMP1, ml);
3004                                 M_LDAH(REG_PV, REG_PV, mh);
3005                             }
3006                         s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3007                         M_INTMOVE(REG_RESULT, s1);
3008                         store_reg_to_var_int(iptr->dst, s1);
3009                         break;
3010
3011
3012                 default:
3013                         throw_cacao_exception_exit(string_java_lang_InternalError,
3014                                                                            "Unknown ICMD %d", iptr->opc);
3015         } /* switch */
3016                 
3017         } /* for instruction */
3018                 
3019         /* copy values to interface registers */
3020
3021         src = bptr->outstack;
3022         len = bptr->outdepth;
3023         MCODECHECK(64 + len);
3024 #ifdef LSRA
3025         if (!opt_lsra)
3026 #endif
3027         while (src) {
3028                 len--;
3029                 if ((src->varkind != STACKVAR)) {
3030                         s2 = src->type;
3031                         if (IS_FLT_DBL_TYPE(s2)) {
3032                                 var_to_reg_flt(s1, src, REG_FTMP1);
3033                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3034                                         M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3035
3036                                 } else {
3037                                         M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3038                                 }
3039
3040                         } else {
3041                                 var_to_reg_int(s1, src, REG_ITMP1);
3042                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3043                                         M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3044
3045                                 } else {
3046                                         M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3047                                         if (IS_2_WORD_TYPE(s2))
3048                                                 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
3049                                 }
3050                         }
3051                 }
3052                 src = src->prev;
3053         }
3054         } /* if (bptr -> flags >= BBREACHED) */
3055         } /* for basic block */
3056
3057         /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3058
3059         {
3060         /* generate bound check stubs */
3061
3062         s4 *xcodeptr = NULL;
3063         branchref *bref;
3064
3065         for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3066                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3067                                   bref->branchpos,
3068                                                   (u1 *) mcodeptr - cd->mcodebase);
3069
3070                 MCODECHECK(14);
3071
3072                 /* move index register into REG_ITMP1 */
3073                 M_MOV(bref->reg, REG_ITMP1);
3074                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3075
3076                 if (xcodeptr != NULL) {
3077                         M_BR(xcodeptr - mcodeptr - 1);
3078
3079                 } else {
3080                         xcodeptr = mcodeptr;
3081
3082                         M_STWU(REG_SP, REG_SP, -(24 + 2 * 4));
3083                         M_IST(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3084
3085                         M_MOV(REG_ITMP1, rd->argintregs[0]);
3086
3087                         a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3088                         M_ALD(REG_ITMP2, REG_PV, a);
3089                         M_MTCTR(REG_ITMP2);
3090                         M_JSR;
3091                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3092
3093                         M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3094                         M_IADD_IMM(REG_SP, 24 + 2 * 4, REG_SP);
3095
3096                         a = dseg_addaddress(cd, asm_handle_exception);
3097                         M_ALD(REG_ITMP3, REG_PV, a);
3098
3099                         M_MTCTR(REG_ITMP3);
3100                         M_RTS;
3101                 }
3102         }
3103
3104         /* generate negative array size check stubs */
3105
3106         xcodeptr = NULL;
3107         
3108         for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3109                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3110                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3111                                                           bref->branchpos,
3112                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3113                         continue;
3114                 }
3115
3116                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3117                                   bref->branchpos,
3118                                                   (u1 *) mcodeptr - cd->mcodebase);
3119
3120                 MCODECHECK(12);
3121
3122                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3123
3124                 if (xcodeptr != NULL) {
3125                         M_BR(xcodeptr - mcodeptr - 1);
3126
3127                 } else {
3128                         xcodeptr = mcodeptr;
3129
3130                         M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3131                         M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3132
3133             a = dseg_addaddress(cd, new_negativearraysizeexception);
3134             M_ALD(REG_ITMP2, REG_PV, a);
3135             M_MTCTR(REG_ITMP2);
3136             M_JSR;
3137             M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3138
3139                         M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3140                         M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3141
3142                         a = dseg_addaddress(cd, asm_handle_exception);
3143                         M_ALD(REG_ITMP3, REG_PV, a);
3144
3145                         M_MTCTR(REG_ITMP3);
3146                         M_RTS;
3147                 }
3148         }
3149
3150         /* generate cast check stubs */
3151
3152         xcodeptr = NULL;
3153         
3154         for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3155                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3156                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3157                                                           bref->branchpos,
3158                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3159                         continue;
3160                 }
3161
3162                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3163                                   bref->branchpos,
3164                                                   (u1 *) mcodeptr - cd->mcodebase);
3165
3166                 MCODECHECK(12);
3167
3168                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3169
3170                 if (xcodeptr != NULL) {
3171                         M_BR(xcodeptr - mcodeptr - 1);
3172
3173                 } else {
3174                         xcodeptr = mcodeptr;
3175
3176                         M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3177             M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3178
3179             a = dseg_addaddress(cd, new_classcastexception);
3180             M_ALD(REG_ITMP2, REG_PV, a);
3181             M_MTCTR(REG_ITMP2);
3182             M_JSR;
3183             M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3184
3185                         M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3186                         M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3187
3188                         a = dseg_addaddress(cd, asm_handle_exception);
3189                         M_ALD(REG_ITMP3, REG_PV, a);
3190
3191                         M_MTCTR(REG_ITMP3);
3192                         M_RTS;
3193                 }
3194         }
3195
3196         /* generate exception check stubs */
3197
3198         xcodeptr = NULL;
3199
3200         for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3201                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3202                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3203                                                           bref->branchpos,
3204                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3205                         continue;
3206                 }
3207
3208                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3209                                   bref->branchpos,
3210                                                   (u1 *) mcodeptr - cd->mcodebase);
3211
3212                 MCODECHECK(14);
3213
3214                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3215
3216                 if (xcodeptr != NULL) {
3217                         M_BR(xcodeptr - mcodeptr - 1);
3218
3219                 } else {
3220                         xcodeptr = mcodeptr;
3221
3222                         M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3223                         M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3224
3225 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3226             a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3227             M_ALD(REG_ITMP2, REG_PV, a);
3228             M_MTCTR(REG_ITMP2);
3229             M_JSR;
3230
3231                         /* get the exceptionptr from the ptrprt and clear it */
3232             M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3233                         M_CLR(REG_ITMP3);
3234                         M_AST(REG_ITMP3, REG_RESULT, 0);
3235 #else
3236                         a = dseg_addaddress(cd, &_exceptionptr);
3237                         M_ALD(REG_ITMP2, REG_PV, a);
3238
3239                         M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3240                         M_CLR(REG_ITMP3);
3241                         M_AST(REG_ITMP3, REG_ITMP2, 0);
3242 #endif
3243
3244             M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3245             M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3246
3247                         a = dseg_addaddress(cd, asm_handle_exception);
3248                         M_ALD(REG_ITMP3, REG_PV, a);
3249                         M_MTCTR(REG_ITMP3);
3250                         M_RTS;
3251                 }
3252         }
3253
3254         /* generate null pointer check stubs */
3255
3256         xcodeptr = NULL;
3257
3258         for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3259                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3260                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3261                                                           bref->branchpos,
3262                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3263                         continue;
3264                 }
3265
3266                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3267                                   bref->branchpos,
3268                                                   (u1 *) mcodeptr - cd->mcodebase);
3269
3270                 MCODECHECK(12);
3271
3272                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3273
3274                 if (xcodeptr != NULL) {
3275                         M_BR(xcodeptr - mcodeptr - 1);
3276
3277                 } else {
3278                         xcodeptr = mcodeptr;
3279
3280                         M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3281                         M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3282
3283                         a = dseg_addaddress(cd, new_nullpointerexception);
3284                         M_ALD(REG_ITMP2, REG_PV, a);
3285                         M_MTCTR(REG_ITMP2);
3286                         M_JSR;
3287                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3288
3289                         M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3290                         M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3291
3292                         a = dseg_addaddress(cd, asm_handle_exception);
3293                         M_ALD(REG_ITMP3, REG_PV, a);
3294                         M_MTCTR(REG_ITMP3);
3295                         M_RTS;
3296                 }
3297         }
3298
3299         /* generate patcher stub call code */
3300
3301         {
3302                 patchref *pref;
3303                 u4        mcode;
3304                 s4       *tmpmcodeptr;
3305
3306                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3307                         /* check code segment size */
3308
3309                         MCODECHECK(13 + 4 + 1);
3310
3311                         /* Get machine code which is patched back in later. The call is   */
3312                         /* 1 instruction word long.                                       */
3313
3314                         xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3315                         mcode = *xcodeptr;
3316
3317 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3318                         /* create a virtual java_objectheader */
3319
3320                         /* align data structure to 8-byte */
3321
3322                         ALIGNCODENOP;
3323
3324                         *((ptrint *) (mcodeptr + 0)) = 0;                        /* vftbl */
3325                         *((ptrint *) (mcodeptr + 1)) = (ptrint) get_dummyLR(); /* monitorPtr */
3326
3327                         mcodeptr += 2 * 1;                 /* mcodeptr is a `u4*' pointer */
3328 #endif
3329
3330                         /* patch in the call to call the following code (done at compile  */
3331                         /* time)                                                          */
3332
3333                         tmpmcodeptr = mcodeptr;         /* save current mcodeptr          */
3334                         mcodeptr = xcodeptr;            /* set mcodeptr to patch position */
3335
3336                         M_BL(tmpmcodeptr - (xcodeptr + 1));
3337
3338                         mcodeptr = tmpmcodeptr;         /* restore the current mcodeptr   */
3339
3340 #if 0
3341                         /* create stack frame */
3342
3343                         M_IADD_IMM(REG_SP, -5 * 4, REG_SP);
3344
3345                         /* move return address onto stack */
3346
3347                         M_AST(REG_ITMP3, REG_SP, 4 * 4);
3348
3349                         /* move pointer to java_objectheader onto stack */
3350
3351 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3352                         M_BL(0);
3353                         M_MFLR(REG_ITMP3);
3354                         M_IADD_IMM(REG_ITMP3, -(3 * 4 + 2 * 4), REG_ITMP3);
3355                         M_AST(REG_ITMP3, REG_SP, 3 * 4);
3356 #else
3357                         M_AST(REG_ZERO, REG_SP, 3 * 4);
3358 #endif
3359
3360                         /* move machine code onto stack */
3361
3362                         a = dseg_adds4(cd, mcode);
3363                         M_ILD(REG_ITMP3, REG_PV, a);
3364                         M_IST(REG_ITMP3, REG_SP, 2 * 4);
3365
3366                         /* move class/method/field reference onto stack */
3367
3368                         a = dseg_addaddress(cd, pref->ref);
3369                         M_ALD(REG_ITMP3, REG_PV, a);
3370                         M_AST(REG_ITMP3, REG_SP, 1 * 4);
3371
3372                         /* move patcher function pointer onto stack */
3373
3374                         a = dseg_addaddress(cd, pref->patcher);
3375                         M_ALD(REG_ITMP3, REG_PV, a);
3376                         M_AST(REG_ITMP3, REG_SP, 0 * 4);
3377
3378                         a = dseg_addaddress(cd, asm_wrapper_patcher);
3379                         M_ALD(REG_ITMP3, REG_PV, a);
3380                         M_MTCTR(REG_ITMP3);
3381                         M_RTS;
3382 #endif
3383                 }
3384         }
3385
3386         }
3387
3388         codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3389
3390         asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3391 }
3392
3393
3394 /* function createcompilerstub *************************************************
3395
3396         creates a stub routine which calls the compiler
3397         
3398 *******************************************************************************/
3399
3400 #define COMPSTUBSIZE 6
3401
3402 u1 *createcompilerstub(methodinfo *m)
3403 {
3404         s4 *s = CNEW (s4, COMPSTUBSIZE);    /* memory to hold the stub            */
3405         s4 *mcodeptr = s;                   /* code generation pointer            */
3406
3407         M_LDA(REG_ITMP1, REG_PV, 4*4);
3408         M_ALD(REG_PV, REG_PV, 5*4);
3409         M_MTCTR(REG_PV);
3410         M_RTS;
3411
3412         s[4] = (s4) m;                      /* literals to be adressed            */
3413         s[5] = (s4) asm_call_jit_compiler;  /* jump directly via PV from above    */
3414
3415     asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3416
3417 #if defined(STATISTICS)
3418         if (opt_stat)
3419                 count_cstub_len += COMPSTUBSIZE * 4;
3420 #endif
3421
3422         return (u1*) s;
3423 }
3424
3425
3426 /* function removecompilerstub *************************************************
3427
3428      deletes a compilerstub from memory  (simply by freeing it)
3429
3430 *******************************************************************************/
3431
3432 void removecompilerstub(u1 *stub) 
3433 {
3434         CFREE(stub, COMPSTUBSIZE * 4);
3435 }
3436
3437
3438 /* function: createnativestub **************************************************
3439
3440         creates a stub routine which calls a native method
3441
3442 *******************************************************************************/
3443
3444 #define NATIVESTUB_SIZE      200
3445 #define NATIVESTUB_OFFSET    9
3446
3447
3448 u1 *createnativestub(functionptr f, methodinfo *m)
3449 {
3450         s4 *s;                              /* memory to hold the stub            */
3451         s4 *cs;
3452         s4 stubsize;
3453         s4 *mcodeptr;                       /* code generation pointer            */
3454         s4 stackframesize = 0;              /* size of stackframe if needed       */
3455         s4 disp;
3456         registerdata *rd;
3457         t_inlining_globals *id;
3458         s4 dumpsize;
3459         s4 i;
3460
3461         /* mark start of dump memory area */
3462
3463         dumpsize = dump_size();
3464
3465         /* setup registers before using it */
3466         
3467         rd = DNEW(registerdata);
3468         id = DNEW(t_inlining_globals);
3469
3470         inlining_setup(m, id);
3471         reg_setup(m, rd, id);
3472
3473         method_descriptor2types(m);                /* set paramcount and paramtypes      */
3474
3475         stubsize = NATIVESTUB_SIZE;         /* calculate nativestub size          */
3476
3477         s = CNEW(s4, stubsize);
3478         cs = s + NATIVESTUB_OFFSET;
3479         mcodeptr = cs;
3480
3481         *(cs-1) = (u4) f;                   /* address of native method           */
3482 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3483         *(cs-2) = (u4) builtin_get_exceptionptrptr;
3484 #else
3485         *(cs-2) = (u4) (&_exceptionptr);    /* address of exceptionptr            */
3486 #endif
3487         *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3488         *(cs-4) = (u4) (&env);              /* addr of jni_environement           */
3489         *(cs-5) = (u4) builtin_trace_args;
3490         *(cs-6) = (u4) m;
3491         *(cs-7) = (u4) builtin_displaymethodstop;
3492         *(cs-8) = (u4) m->class;
3493         *(cs-9) = (u4) asm_wrapper_patcher;
3494
3495         M_MFLR(REG_ITMP1);
3496         M_AST(REG_ITMP1, REG_SP, 8);        /* store return address               */
3497         /* Build up new Stackframe for native call */
3498         stackframesize = 24; /* 24 Bytes Linkage Area */
3499         stackframesize += (m->flags & ACC_STATIC) ? 8 : 4; /*1 or 2 additional int parameters */
3500         for (i = 0; i < m->paramcount; i++) {
3501                 stackframesize += IS_2_WORD_TYPE(m->paramtypes[i]) ? 8 : 4;
3502         }
3503
3504         if (stackframesize < (24+32)) { /* 24 Byte Linkage Area + 32 Bytes minimum Argument area */
3505                 stackframesize = 24+32;
3506         }
3507         stackframesize = stackframesize + 8; /* Reserve Space to store Result registers */
3508         stackframesize = (stackframesize + 3) & ~3; /* Keep Stack 16 Byte aligned */
3509         M_STWU(REG_SP, REG_SP, -stackframesize);      /* build up stackframe                */
3510
3511         /* if function is static, check for initialized */
3512
3513         if (m->flags & ACC_STATIC) {
3514                 /* if class isn't yet initialized, do it */
3515                 if (!m->class->initialized) {
3516                         /* call helper function which patches this code */
3517                         M_ALD(REG_ITMP1, REG_PV, -8 * 4);     /* class                    */
3518                         M_ALD(REG_PV, REG_PV, -9 * 4);        /* asm_wrapper_patcher      */
3519                         M_MTCTR(REG_PV);
3520                         M_JSR;
3521                         disp = -(s4) (mcodeptr - cs) * 4;
3522                         M_MFLR(REG_ITMP1);
3523                         M_LDA(REG_PV, REG_ITMP1, disp);       /* recompute pv from ra     */
3524                 }
3525         }
3526
3527         if (runverbose) {
3528                 s4 p, t, s1, d, a;
3529         s4 longargs = 0;
3530         s4 fltargs = 0;
3531                 s4 dblargs = 0;
3532
3533 /*          M_MFLR(REG_ITMP3); */
3534                 /* XXX must be a multiple of 16 */
3535         M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3536
3537 /*          M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3538
3539                 M_CLR(REG_ITMP1);
3540
3541         /* save all arguments into the reserved stack space */
3542         for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3543             t = m->paramtypes[p];
3544
3545             if (IS_INT_LNG_TYPE(t)) {
3546                 /* overlapping u8's are on the stack */
3547                 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3548                     s1 = rd->argintregs[p + longargs + dblargs];
3549
3550                     if (!IS_2_WORD_TYPE(t)) {
3551                         M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3552                         M_IST(s1, REG_SP, 24 + p * 8 + 4);
3553
3554                     } else {
3555                         M_IST(s1, REG_SP, 24 + p  * 8);
3556                         M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3557                         longargs++;
3558                     }
3559
3560                 } else {
3561                                         /* we do not have a data segment here */
3562                     /* a = dseg_adds4(cd, 0xdeadbeef);
3563                                            M_ILD(REG_ITMP1, REG_PV, a); */
3564                                         M_LDA(REG_ITMP1, REG_ZERO, -1);
3565                     M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3566                     M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3567                 }
3568
3569             } else {
3570                 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3571                     s1 = rd->argfltregs[fltargs + dblargs];
3572
3573                     if (!IS_2_WORD_TYPE(t)) {
3574                         M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3575                         M_FST(s1, REG_SP, 24 + p * 8 + 4);
3576                         fltargs++;
3577
3578                     } else {
3579                         M_DST(s1, REG_SP, 24 + p * 8);
3580                         dblargs++;
3581                     }
3582
3583                 } else {
3584                     /* this should not happen */
3585                 }
3586             }
3587         }
3588
3589         /* TODO: save remaining integer and flaot argument registers */
3590
3591         /* load first 4 arguments into integer argument registers */
3592         for (p = 0; p < 8; p++) {
3593             d = rd->argintregs[p];
3594             M_ILD(d, REG_SP, 24 + p * 4);
3595         }
3596
3597         M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3598         M_AST(REG_ITMP1, REG_SP, 11 * 8);    /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3599                 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3600         M_MTCTR(REG_ITMP2);
3601         M_JSR;
3602
3603         longargs = 0;
3604         fltargs = 0;
3605         dblargs = 0;
3606
3607         /* restore arguments into the reserved stack space */
3608         for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3609             t = m->paramtypes[p];
3610
3611             if (IS_INT_LNG_TYPE(t)) {
3612                 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3613                     s1 = rd->argintregs[p + longargs + dblargs];
3614
3615                     if (!IS_2_WORD_TYPE(t)) {
3616                         M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3617
3618                     } else {
3619                         M_ILD(s1, REG_SP, 24 + p  * 8);
3620                         M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3621                         longargs++;
3622                     }
3623                 }
3624
3625             } else {
3626                 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3627                     s1 = rd->argfltregs[fltargs + dblargs];
3628
3629                     if (!IS_2_WORD_TYPE(t)) {
3630                         M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3631                         fltargs++;
3632
3633                     } else {
3634                         M_DLD(s1, REG_SP, 24 + p * 8);
3635                         dblargs++;
3636                     }
3637                 }
3638             }
3639         }
3640
3641 /*          M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3642
3643         M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3644 /*          M_MTLR(REG_ITMP3); */
3645         }
3646
3647         /* save argument registers on stack -- if we have to            */
3648         /* and copy spilled argument regs from old stack to the new one */
3649         {
3650                 s4 farg = 0;
3651                 s4 iarg;
3652                 s4 paramsize;
3653                 s4 stack_off;
3654                 s4 shift;
3655
3656                 stack_off = 0;
3657                 shift = (m->flags & ACC_STATIC) ? 2 : 1;
3658                 for (i = 0; i < m->paramcount; i++) {
3659                         paramsize = IS_2_WORD_TYPE(m->paramtypes[i]) ? 2 : 1;
3660                         if (IS_FLT_DBL_TYPE(m->paramtypes[i])) {
3661                                 farg++;
3662                                 if (farg >= FLT_ARG_CNT) { /* spilled float arg -> copy from old stack */
3663                                         if (paramsize == 1) { /* float arg */
3664                                                 M_FLD(REG_FTMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3665                                                 M_FST(REG_FTMP1, REG_SP, 24 + 4*(shift + stack_off));
3666                                         } else { /* double arg */
3667                                                 M_DLD(REG_FTMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3668                                                 M_DST(REG_FTMP1, REG_SP, 24 + 4*(shift + stack_off));
3669                                         }
3670                                 }
3671                         } else { /* int arg */
3672                                 iarg = stack_off; /* int register are not consecutive like the float*/
3673                                 if (iarg + paramsize -1 < INT_ARG_CNT) {
3674                                         if ( iarg + paramsize -1 == INT_ARG_CNT - shift ) {
3675                                                 /* int arg reg(s) spilled through shift to stack */
3676                                                 M_IST( rd->argintregs[iarg], REG_SP, 24 + 4 * (shift + stack_off));
3677                                                 if (paramsize == 2) /* spill secondreg, too */
3678                                                         M_IST( rd->argintregs[iarg+1], REG_SP, 24 + 4 * (shift + stack_off) + 4);
3679                                         }
3680                                 } else { /* already spilled int arg -> copy from old stack */
3681                                         M_ILD(REG_ITMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3682                                         M_IST(REG_ITMP1, REG_SP, 24 + 4 * (shift + stack_off));
3683                                         if (paramsize == 2) { /* long arg -> copy second half, too */
3684                                                 M_ILD(REG_ITMP1, REG_SP, stackframesize + 24 + 4 * stack_off + 4);
3685                                                 M_IST(REG_ITMP1, REG_SP, 24 + 4*(shift + stack_off) + 4);
3686                                         }
3687                                 }
3688                         }
3689                         stack_off += paramsize;
3690                 }
3691
3692                 /* now shift integer argument registers */
3693                 for (i = m->paramcount - 1; i >=0; i--) {
3694                         paramsize = IS_2_WORD_TYPE(m->paramtypes[i]) ? 2 : 1;
3695                         stack_off -= paramsize;
3696                         if (IS_INT_LNG_TYPE(m->paramtypes[i])) {
3697                                 iarg = stack_off;
3698                                 if ( iarg + paramsize -1 < INT_ARG_CNT - shift ) {
3699                                         /* shift integer arg */
3700                                         if (paramsize == 2)
3701                                                 M_MOV(rd->argintregs[iarg+1], rd->argintregs[iarg + shift + 1]);
3702                                         M_MOV(rd->argintregs[iarg], rd->argintregs[iarg + shift]);
3703                                 } /* else are already spilled to memory */
3704                         }
3705                 }
3706         }
3707
3708         if (m->flags & ACC_STATIC)
3709                 /* put class into second argument register */
3710                 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3711
3712         /* put env into first argument register */
3713         M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3714
3715         M_ALD(REG_PV, REG_PV, -1 * 4);      /* load adress of native method       */
3716         M_MTCTR(REG_PV);
3717         M_JSR;
3718         disp = -(s4) (mcodeptr - cs) * 4;
3719         M_MFLR(REG_ITMP1);
3720         M_LDA(REG_PV, REG_ITMP1, disp);     /* recompute pv from ra               */
3721
3722         /* 20 instructions */
3723         if (runverbose) {
3724                 M_MFLR(REG_ITMP3);
3725                 M_LDA(REG_SP, REG_SP, -10 * 8);
3726                 M_DST(REG_FRESULT, REG_SP, 48+0);
3727                 M_IST(REG_RESULT, REG_SP, 48+8);
3728                 M_AST(REG_ITMP3, REG_SP, 48+12);
3729                 M_IST(REG_RESULT2, REG_SP, 48+16);
3730
3731                 /* keep this order */
3732                 switch (m->returntype) {
3733                 case TYPE_INT:
3734                 case TYPE_ADDRESS:
3735                         M_MOV(REG_RESULT, rd->argintregs[2]);
3736                         M_CLR(rd->argintregs[1]);
3737                         break;
3738
3739                 case TYPE_LONG:
3740                         M_MOV(REG_RESULT2, rd->argintregs[2]);
3741                         M_MOV(REG_RESULT, rd->argintregs[1]);
3742                         break;
3743                 }
3744                 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3745
3746                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3747                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3748                 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop         */
3749                 M_MTCTR(REG_ITMP2);
3750                 M_JSR;
3751                 M_DLD(REG_FRESULT, REG_SP, 48+0);
3752                 M_ILD(REG_RESULT, REG_SP, 48+8);
3753                 M_ALD(REG_ITMP3, REG_SP, 48+12);
3754                 M_ILD(REG_RESULT2, REG_SP, 48+16);
3755                 M_LDA(REG_SP, REG_SP, 10 * 8);
3756                 M_MTLR(REG_ITMP3);
3757         }
3758
3759 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3760         if (IS_FLT_DBL_TYPE(m->returntype))
3761                 if (IS_2_WORD_TYPE(m->returntype))
3762                         M_DST(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3763                 else
3764                         M_FST(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3765         else {
3766                 M_IST(REG_RESULT, REG_SP, stackframesize-8 /*56*/);
3767                 if (IS_2_WORD_TYPE(m->returntype))
3768                         M_IST(REG_RESULT2, REG_SP, stackframesize-4 /* 60*/);
3769         }
3770
3771         M_ALD(REG_ITMP2, REG_PV, -2 * 4);   /* builtin_get_exceptionptrptr        */
3772         M_MTCTR(REG_ITMP2);
3773         M_JSR;
3774         disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3775         M_MFLR(REG_ITMP1);
3776         M_LDA(REG_PV, REG_ITMP1, disp);
3777         M_MOV(REG_RESULT, REG_ITMP2);
3778
3779         if (IS_FLT_DBL_TYPE(m->returntype))
3780                 if (IS_2_WORD_TYPE(m->returntype))
3781                         M_DLD(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3782                 else
3783                         M_FLD(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3784         else {
3785                 M_ILD(REG_RESULT, REG_SP, stackframesize-8 /*56*/);
3786                 if (IS_2_WORD_TYPE(m->returntype))
3787                         M_ILD(REG_RESULT2, REG_SP, stackframesize-4 /*60*/);
3788         }
3789 #else
3790         M_ALD(REG_ITMP2, REG_PV, -2 * 4);   /* get address of exceptionptr        */
3791 #endif
3792         M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1     */
3793         M_TST(REG_ITMP1_XPTR);
3794         M_BNE(4);                           /* if no exception then return        */
3795
3796         M_ALD(REG_ITMP1, REG_SP, stackframesize + 8);   /* load return address                */
3797         M_MTLR(REG_ITMP1);
3798         M_LDA(REG_SP, REG_SP, stackframesize);          /* remove stackframe                  */
3799
3800         M_RET;
3801
3802         M_CLR(REG_ITMP3);
3803         M_AST(REG_ITMP3, REG_ITMP2, 0);     /* store NULL into exceptionptr       */
3804
3805         M_ALD(REG_ITMP2, REG_SP, stackframesize + 8);   /* load return address                */
3806         M_MTLR(REG_ITMP2);
3807
3808         M_LDA(REG_SP, REG_SP, stackframesize);          /* remove stackframe                  */
3809
3810         M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address                */
3811
3812         M_ALD(REG_ITMP3, REG_PV, -3 * 4);   /* load asm exception handler address */
3813         M_MTCTR(REG_ITMP3);
3814         M_RTS;
3815
3816         /* Check if the stub size is big enough to hold the whole stub generated. */
3817         /* If not, this can lead into unpredictable crashes, because of heap      */
3818         /* corruption.                                                            */
3819         if ((s4) (mcodeptr - s) > stubsize) {
3820                 throw_cacao_exception_exit(string_java_lang_InternalError,
3821                                    "Native stub size %d is to small for current stub size %d",
3822                                    stubsize, (s4) (mcodeptr - s));
3823         }
3824
3825         asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3826
3827 #if defined(STATISTICS)
3828         if (opt_stat)
3829                 count_nstub_len += NATIVESTUB_SIZE * 4;
3830 #endif
3831
3832         /* release dump area */
3833
3834         dump_release(dumpsize);
3835
3836         return (u1*) (s + NATIVESTUB_OFFSET);
3837 }
3838
3839
3840 /* function: removenativestub **************************************************
3841
3842     removes a previously created native-stub from memory
3843     
3844 *******************************************************************************/
3845
3846 void removenativestub(u1 *stub)
3847 {
3848         CFREE((s4 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 4);
3849 }
3850
3851
3852 /*
3853  * These are local overrides for various environment variables in Emacs.
3854  * Please do not remove this and leave it at the end of the file, where
3855  * Emacs will automagically detect them.
3856  * ---------------------------------------------------------------------
3857  * Local variables:
3858  * mode: c
3859  * indent-tabs-mode: t
3860  * c-basic-offset: 4
3861  * tab-width: 4
3862  * End:
3863  */