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