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