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