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