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