d8fa8ee57da8bb84fade6919b5ac4439dab6d5c9
[cacao.git] / src / vm / jit / powerpc / codegen.c
1 /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28             Stefan Ring
29
30    Changes: Christian Thalinger
31             Christian Ullrich
32
33    $Id: codegen.c 3037 2005-07-13 16:12:20Z twisti $
34
35 */
36
37
38 #include <assert.h>
39 #include <stdio.h>
40 #include <signal.h>
41
42 #include "config.h"
43
44 #include "md-abi.h"
45 #include "md-abi.inc"
46
47 #include "vm/jit/powerpc/arch.h"
48 #include "vm/jit/powerpc/codegen.h"
49 #include "vm/jit/powerpc/types.h"
50
51 #include "cacao/cacao.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/global.h"
55 #include "vm/loader.h"
56 #include "vm/stringlocal.h"
57 #include "vm/tables.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen.inc"
60 #include "vm/jit/jit.h"
61
62 #if defined(LSRA)
63 # include "vm/jit/lsra.inc"
64 #endif
65
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/reg.inc"
70 #include "disass.h"
71
72
73 void asm_cacheflush(void *, long);
74
75 /* #include <architecture/ppc/cframe.h> */
76
77 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
78 void thread_restartcriticalsection(void *u)
79 {
80         /* XXX set pc to restart address */
81 }
82 #endif
83
84 s4 *codegen_trace_args( methodinfo *m, codegendata *cd, registerdata *rd,
85                                                 s4 *mcodeptr, s4 parentargs_base, bool nativestub);
86
87 /* codegen *********************************************************************
88
89    Generates machine code.
90
91 *******************************************************************************/
92
93 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
94 {
95         s4                  len, s1, s2, s3, d, disp;
96         ptrint              a;
97         s4                  parentargs_base;
98         s4                 *mcodeptr;
99         stackptr            src;
100         varinfo            *var;
101         basicblock         *bptr;
102         instruction        *iptr;
103         exceptiontable     *ex;
104         u2                  currentline;
105         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
106         builtintable_entry *bte;
107         methoddesc         *md;
108
109         /* prevent compiler warnings */
110
111         d = 0;
112         currentline = 0;
113         lm = NULL;
114         bte = NULL;
115
116         {
117         s4 i, p, t, l;
118         s4 savedregs_num;
119
120         savedregs_num = 0;
121
122         /* space to save used callee saved registers */
123
124         savedregs_num += (INT_SAV_CNT - rd->savintreguse);
125         savedregs_num += 2 * (FLT_SAV_CNT - rd->savfltreguse);
126
127         parentargs_base = rd->memuse + savedregs_num;
128
129 #if defined(USE_THREADS)
130         /* space to save argument of monitor_enter and Return Values to survive */
131     /* monitor_exit. The stack position for the argument can not be shared  */
132         /* with place to save the return register on PPC, since both values     */
133         /* reside in R3 */
134         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
135                 /* reserve 2 slots for long/double return values for monitorexit */
136
137                 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
138                         parentargs_base += 3;
139                 else
140                         parentargs_base += 2;
141         }
142
143 #endif
144
145         /* create method header */
146
147         parentargs_base = (parentargs_base + 3) & ~3;
148
149         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
150         (void) dseg_adds4(cd, parentargs_base * 4);             /* FrameSize      */
151
152 #if defined(USE_THREADS)
153         /* IsSync contains the offset relative to the stack pointer for the
154            argument of monitor_exit used in the exception handler. Since the
155            offset could be zero and give a wrong meaning of the flag it is
156            offset by one.
157         */
158
159         if (checksync && (m->flags & ACC_SYNCHRONIZED))
160                 (void) dseg_adds4(cd, (rd->memuse + 1) * 4);        /* IsSync         */
161         else
162 #endif
163                 (void) dseg_adds4(cd, 0);                           /* IsSync         */
164                                                
165         (void) dseg_adds4(cd, m->isleafmethod);                 /* IsLeaf         */
166         (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse);  /* IntSave        */
167         (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse);  /* FltSave        */
168
169         dseg_addlinenumbertablesize(cd);
170
171         (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
172
173         /* create exception table */
174
175         for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
176                 dseg_addtarget(cd, ex->start);
177                 dseg_addtarget(cd, ex->end);
178                 dseg_addtarget(cd, ex->handler);
179                 (void) dseg_addaddress(cd, ex->catchtype.cls);
180         }
181         
182         /* initialize mcode variables */
183         
184         mcodeptr = (s4 *) cd->mcodebase;
185         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
186         MCODECHECK(128 + m->paramcount);
187
188         /* create stack frame (if necessary) */
189
190         if (!m->isleafmethod) {
191                 M_MFLR(REG_ITMP3);
192                 M_AST(REG_ITMP3, REG_SP, LA_LR_OFFSET);
193         }
194
195         if (parentargs_base) {
196                 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
197         }
198
199         /* save return address and used callee saved registers */
200
201         p = parentargs_base;
202         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
203                 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
204         }
205         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
206                 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
207         }
208
209         /* take arguments out of register or stack frame */
210
211         md = m->parseddesc;
212
213         for (p = 0, l = 0; p < md->paramcount; p++) {
214                 t = md->paramtypes[p].type;
215                 var = &(rd->locals[l][t]);
216                 l++;
217                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
218                         l++;
219                 if (var->type < 0)
220                         continue;
221                 s1 = md->params[p].regoff;
222                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
223                         if (IS_2_WORD_TYPE(t))
224                                 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
225                                                            rd->argintregs[GET_HIGH_REG(s1)]);
226                         else
227                                 s2 = rd->argintregs[s1];
228                         if (!md->params[p].inmemory) {           /* register arguments    */
229                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
230                                         M_TINTMOVE(t, s2, var->regoff);
231
232                                 } else {                             /* reg arg -> spilled    */
233                                         if (IS_2_WORD_TYPE(t)) {
234                                                 M_IST(GET_HIGH_REG(s2), REG_SP, var->regoff * 4);
235                                                 M_IST(GET_LOW_REG(s2), REG_SP, var->regoff * 4 + 4);
236                                         } else {
237                                                 M_IST(s2, REG_SP, var->regoff * 4);
238                                         }
239                                 }
240
241                         } else {                                 /* stack arguments       */
242                                 if (!(var->flags & INMEMORY)) {      /* stack arg -> register */
243                                         if (IS_2_WORD_TYPE(t)) {
244                                                 M_ILD(GET_HIGH_REG(var->regoff), REG_SP,
245                                                           (parentargs_base + s1) * 4);
246                                                 M_ILD(GET_LOW_REG(var->regoff), REG_SP,
247                                                           (parentargs_base + s1) * 4 + 4);
248                                         } else {
249                                                 M_ILD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
250                                         }
251
252                                 } else {                             /* stack arg -> spilled  */
253 #if 1
254                                         M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4);
255                                         M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
256                                         if (IS_2_WORD_TYPE(t)) {
257                                                 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4 +4);
258                                                 M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
259                                         }
260 #else
261                                         /* Reuse Memory Position on Caller Stack */
262                                         var->regoff = parentargs_base + s1;
263 #endif
264                                 }
265                         }
266
267                 } else {                                     /* floating args         */
268                         if (!md->params[p].inmemory) {           /* register arguments    */
269                                 s2 = rd->argfltregs[s1];
270                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
271                                         M_FLTMOVE(s2, var->regoff);
272
273                                 } else {                                         /* reg arg -> spilled    */
274                                         if (IS_2_WORD_TYPE(t))
275                                                 M_DST(s2, REG_SP, var->regoff * 4);
276                                         else
277                                                 M_FST(s2, REG_SP, var->regoff * 4);
278                                 }
279
280                         } else {                                 /* stack arguments       */
281                                 if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
282                                         if (IS_2_WORD_TYPE(t))
283                                                 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
284
285                                         else
286                                                 M_FLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
287
288                                 } else {                             /* stack-arg -> spilled  */
289 #if 1
290                                         if (IS_2_WORD_TYPE(t)) {
291                                                 M_DLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
292                                                 M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
293                                                 var->regoff = parentargs_base + s1;
294
295                                         } else {
296                                                 M_FLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
297                                                 M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
298                                         }
299 #else
300                                         /* Reuse Memory Position on Caller Stack */
301                                         var->regoff = parentargs_base + s1;
302 #endif
303                                 }
304                         }
305                 }
306         } /* end for */
307
308         /* save monitorenter argument */
309
310 #if defined(USE_THREADS)
311         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
312                 /* stack offset for monitor argument */
313
314                 s1 = rd->memuse;
315
316 #if 0
317                 if (runverbose) {
318                         M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
319
320                         for (p = 0; p < INT_ARG_CNT; p++)
321                                 M_IST(rd->argintregs[p], REG_SP, p * 4);
322
323                         for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
324                                 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
325
326                         s1 += INT_ARG_CNT + FLT_ARG_CNT;
327                 }
328 #endif
329
330                 /* decide which monitor enter function to call */
331
332                 if (m->flags & ACC_STATIC) {
333                         p = dseg_addaddress(cd, m->class);
334                         M_ALD(REG_ITMP1, REG_PV, p);
335                         M_AST(REG_ITMP1, REG_SP, s1 * 4);
336                         M_MOV(REG_ITMP1, rd->argintregs[0]);
337                         p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
338                         M_ALD(REG_ITMP3, REG_PV, p);
339                         M_MTCTR(REG_ITMP3);
340                         M_JSR;
341
342                 } else {
343                         M_TST(rd->argintregs[0]);
344                         M_BEQ(0);
345                         codegen_addxnullrefs(cd, mcodeptr);
346                         M_AST(rd->argintregs[0], REG_SP, s1 * 4);
347                         p = dseg_addaddress(cd, BUILTIN_monitorenter);
348                         M_ALD(REG_ITMP3, REG_PV, p);
349                         M_MTCTR(REG_ITMP3);
350                         M_JSR;
351                 }
352
353 #if 0
354                 if (runverbose) {
355                         for (p = 0; p < INT_ARG_CNT; p++)
356                                 M_ILD(rd->argintregs[p], REG_SP, p * 4);
357
358                         for (p = 0; p < FLT_ARG_CNT; p++)
359                                 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
360
361
362                         M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
363                 }
364 #endif
365         }
366 #endif
367
368         /* call trace function */
369
370         if (runverbose) {
371                 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, parentargs_base, false);
372
373         } /* if (runverbose) */
374         }
375
376         /* end of header generation */
377
378         /* walk through all basic blocks */
379         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
380
381                 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
382
383                 if (bptr->flags >= BBREACHED) {
384
385                 /* branch resolving */
386
387                 {
388                 branchref *brefs;
389                 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
390                         gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos, 
391                                           brefs->branchpos,
392                                                           bptr->mpc);
393                         }
394                 }
395
396                 /* copy interface registers to their destination */
397
398                 src = bptr->instack;
399                 len = bptr->indepth;
400                 MCODECHECK(64+len);
401
402 #ifdef LSRA
403                 if (opt_lsra) {
404                         while (src != NULL) {
405                                 len--;
406                                 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
407                                         /* d = reg_of_var(m, src, REG_ITMP1); */
408                                         if (!(src->flags & INMEMORY))
409                                                 d= src->regoff;
410                                         else
411                                                 d=REG_ITMP1;
412                                         M_INTMOVE(REG_ITMP1, d);
413                                         store_reg_to_var_int(src, d);
414                                 }
415                                 src = src->prev;
416                         }
417                 } else {
418 #endif
419                 while (src != NULL) {
420                         len--;
421                         if ((len == 0) && (bptr->type != BBTYPE_STD)) {
422                                 d = reg_of_var(rd, src, REG_ITMP1);
423                                 M_INTMOVE(REG_ITMP1, d);
424                                 store_reg_to_var_int(src, d);
425                         } else {
426                                 if (src->type == TYPE_LNG)
427                                         d = reg_of_var(rd, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
428                                 else
429                                         d = reg_of_var(rd, src, REG_IFTMP);
430                                 if ((src->varkind != STACKVAR)) {
431                                         s2 = src->type;
432                                         if (IS_FLT_DBL_TYPE(s2)) {
433                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
434                                                         s1 = rd->interfaces[len][s2].regoff;
435                                                         M_FLTMOVE(s1,d);
436                                                 } else {
437                                                         if (IS_2_WORD_TYPE(s2)) {
438                                                                 M_DLD(d, REG_SP,
439                                                                           4 * rd->interfaces[len][s2].regoff);
440                                                         } else {
441                                                                 M_FLD(d, REG_SP,
442                                                                           4 * rd->interfaces[len][s2].regoff);
443                                                         }       
444                                                 }
445                                                 store_reg_to_var_flt(src, d);
446                                         } else {
447                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
448                                                         s1 = rd->interfaces[len][s2].regoff;
449                                                         M_TINTMOVE(s2,s1,d);
450                                                 } else {
451                                                         if (IS_2_WORD_TYPE(s2)) {
452                                                                 M_ILD(GET_HIGH_REG(d), REG_SP,
453                                                                           4 * rd->interfaces[len][s2].regoff);
454                                                                 M_ILD(GET_LOW_REG(d), REG_SP,
455                                                                           4 * rd->interfaces[len][s2].regoff + 4);
456                                                         } else {
457                                                                 M_ILD(d, REG_SP,
458                                                                           4 * rd->interfaces[len][s2].regoff);
459                                                         }
460                                                 }
461                                                 store_reg_to_var_int(src, d);
462                                         }
463                                 }
464                         }
465                         src = src->prev;
466                 }
467
468 #ifdef LSRA
469                 }
470 #endif
471                 /* walk through all instructions */
472                 
473                 src = bptr->instack;
474                 len = bptr->icount;
475
476                 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
477                         if (iptr->line != currentline) {
478                                 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
479                                 currentline = iptr->line;
480                         }
481
482                         MCODECHECK(64);   /* an instruction usually needs < 64 words      */
483
484                         switch (iptr->opc) {
485                         case ICMD_NOP:    /* ...  ==> ...                                 */
486                         case ICMD_INLINE_START:
487                         case ICMD_INLINE_END:
488                                 break;
489
490                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
491
492                         var_to_reg_int(s1, src, REG_ITMP1);
493                         M_TST(s1);
494                         M_BEQ(0);
495                         codegen_addxnullrefs(cd, mcodeptr);
496                         break;
497
498                 /* constant operations ************************************************/
499
500                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
501                                       /* op1 = 0, val.i = constant                    */
502
503                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
504                         ICONST(d, iptr->val.i);
505                         store_reg_to_var_int(iptr->dst, d);
506                         break;
507
508                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
509                                       /* op1 = 0, val.l = constant                    */
510
511                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
512                         LCONST(d, iptr->val.l);
513                         store_reg_to_var_int(iptr->dst, d);
514                         break;
515
516                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
517                                       /* op1 = 0, val.f = constant                    */
518
519                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
520                         a = dseg_addfloat(cd, iptr->val.f);
521                         M_FLD(d, REG_PV, a);
522                         store_reg_to_var_flt(iptr->dst, d);
523                         break;
524                         
525                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
526                                       /* op1 = 0, val.d = constant                    */
527
528                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
529                         a = dseg_adddouble(cd, iptr->val.d);
530                         M_DLD(d, REG_PV, a);
531                         store_reg_to_var_flt(iptr->dst, d);
532                         break;
533
534                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
535                                       /* op1 = 0, val.a = constant                    */
536
537                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
538                         ICONST(d, (u4) iptr->val.a);
539                         store_reg_to_var_int(iptr->dst, d);
540                         break;
541
542
543                 /* load/store operations **********************************************/
544
545                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
546                 case ICMD_LLOAD:      /* op1 = local variable                         */
547                 case ICMD_ALOAD:
548
549                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
550                         if (IS_2_WORD_TYPE(var->type)) /* TYPE_LNG */
551                                 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
552                         else
553                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
554                         if ((iptr->dst->varkind == LOCALVAR) &&
555                             (iptr->dst->varnum == iptr->op1))
556                                 break;
557
558                         if (var->flags & INMEMORY) {
559                                 if (IS_2_WORD_TYPE(var->type)) {
560                                         M_ILD(GET_HIGH_REG(d), REG_SP, var->regoff * 4);
561                                         M_ILD(GET_LOW_REG(d), REG_SP, var->regoff * 4 + 4);
562                                 } else {
563                                         M_ILD(d, REG_SP, var->regoff * 4);
564                                 }
565                         } else {
566                                 M_TINTMOVE(var->type, var->regoff, d);
567                         }
568                         store_reg_to_var_int(iptr->dst, d);
569                         break;
570
571                 case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
572                 case ICMD_DLOAD:      /* op1 = local variable                         */
573
574                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
575                         if ((iptr->dst->varkind == LOCALVAR) &&
576                             (iptr->dst->varnum == iptr->op1))
577                                 break;
578                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
579                         if (var->flags & INMEMORY)
580                                 if (IS_2_WORD_TYPE(var->type))
581                                         M_DLD(d, REG_SP, 4 * var->regoff);
582                                 else
583                                         M_FLD(d, REG_SP, 4 * var->regoff);
584                         else {
585                                 M_FLTMOVE(var->regoff, d);
586                         }
587                         store_reg_to_var_flt(iptr->dst, d);
588                         break;
589
590
591                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
592                 case ICMD_LSTORE:     /* op1 = local variable                         */
593                 case ICMD_ASTORE:
594
595                         if ((src->varkind == LOCALVAR) &&
596                             (src->varnum == iptr->op1))
597                                 break;
598                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
599                         if (var->flags & INMEMORY) {
600                                 if (IS_2_WORD_TYPE(var->type)) {
601                                         var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
602                                         M_IST(GET_HIGH_REG(s1), REG_SP, var->regoff * 4);
603                                         M_IST(GET_LOW_REG(s1), REG_SP, var->regoff * 4 + 4);
604                                 } else {
605                                         var_to_reg_int(s1, src, REG_ITMP1);
606                                         M_IST(s1, REG_SP, var->regoff * 4);
607                                 }
608
609                         } else {
610                                 var_to_reg_int(s1, src, var->regoff);
611                                 M_TINTMOVE(var->type, s1, var->regoff);
612                         }
613                         break;
614
615                 case ICMD_FSTORE:     /* ..., value  ==> ...                          */
616                 case ICMD_DSTORE:     /* op1 = local variable                         */
617
618                         if ((src->varkind == LOCALVAR) &&
619                             (src->varnum == iptr->op1))
620                                 break;
621                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
622                         if (var->flags & INMEMORY) {
623                                 var_to_reg_flt(s1, src, REG_FTMP1);
624                                 if (var->type == TYPE_DBL)
625                                         M_DST(s1, REG_SP, 4 * var->regoff);
626                                 else
627                                         M_FST(s1, REG_SP, 4 * var->regoff);
628                         } else {
629                                 var_to_reg_flt(s1, src, var->regoff);
630                                 M_FLTMOVE(s1, var->regoff);
631                         }
632                         break;
633
634
635                 /* pop/dup/swap operations ********************************************/
636
637                 /* attention: double and longs are only one entry in CACAO ICMDs      */
638
639                 case ICMD_POP:        /* ..., value  ==> ...                          */
640                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
641                         break;
642
643                 case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
644                         M_COPY(src, iptr->dst);
645                         break;
646
647                 case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
648
649                         M_COPY(src,       iptr->dst);
650                         M_COPY(src->prev, iptr->dst->prev);
651                         M_COPY(iptr->dst, iptr->dst->prev->prev);
652                         break;
653
654                 case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
655
656                         M_COPY(src,             iptr->dst);
657                         M_COPY(src->prev,       iptr->dst->prev);
658                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
659                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
660                         break;
661
662                 case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
663
664                         M_COPY(src,       iptr->dst);
665                         M_COPY(src->prev, iptr->dst->prev);
666                         break;
667
668                 case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
669
670                         M_COPY(src,             iptr->dst);
671                         M_COPY(src->prev,       iptr->dst->prev);
672                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
673                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
674                         M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
675                         break;
676
677                 case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
678
679                         M_COPY(src,                   iptr->dst);
680                         M_COPY(src->prev,             iptr->dst->prev);
681                         M_COPY(src->prev->prev,       iptr->dst->prev->prev);
682                         M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
683                         M_COPY(iptr->dst,             iptr->dst->prev->prev->prev->prev);
684                         M_COPY(iptr->dst->prev,       iptr->dst->prev->prev->prev->prev->prev);
685                         break;
686
687                 case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
688
689                         M_COPY(src,       iptr->dst->prev);
690                         M_COPY(src->prev, iptr->dst);
691                         break;
692
693
694                 /* integer operations *************************************************/
695
696                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
697
698                         var_to_reg_int(s1, src, REG_ITMP1); 
699                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
700                         M_NEG(s1, d);
701                         store_reg_to_var_int(iptr->dst, d);
702                         break;
703
704                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
705
706                         var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
707                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
708                         M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
709                         M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
710                         store_reg_to_var_int(iptr->dst, d);
711                         break;
712
713                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
714
715                         var_to_reg_int(s1, src, REG_ITMP2);
716                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
717                         M_INTMOVE(s1, GET_LOW_REG(d));
718                         M_SRA_IMM(GET_LOW_REG(d), 31, GET_HIGH_REG(d));
719                         store_reg_to_var_int(iptr->dst, d);
720                         break;
721
722                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
723
724                         var_to_reg_int_low(s1, src, REG_ITMP2);
725                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
726                         M_INTMOVE(s1, d );
727                         store_reg_to_var_int(iptr->dst, d);
728                         break;
729
730                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
731
732                         var_to_reg_int(s1, src, REG_ITMP1);
733                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
734                         M_BSEXT(s1, d);
735                         store_reg_to_var_int(iptr->dst, d);
736                         break;
737
738                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
739
740                         var_to_reg_int(s1, src, REG_ITMP1);
741                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
742                         M_CZEXT(s1, d);
743                         store_reg_to_var_int(iptr->dst, d);
744                         break;
745
746                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
747
748                         var_to_reg_int(s1, src, REG_ITMP1);
749                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
750                         M_SSEXT(s1, d);
751                         store_reg_to_var_int(iptr->dst, d);
752                         break;
753
754
755                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
756
757                         var_to_reg_int(s1, src->prev, REG_ITMP1);
758                         var_to_reg_int(s2, src, REG_ITMP2);
759                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
760                         M_IADD(s1, s2, d);
761                         store_reg_to_var_int(iptr->dst, d);
762                         break;
763
764                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
765                                       /* val.i = constant                             */
766
767                         var_to_reg_int(s1, src, REG_ITMP1);
768                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
769                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
770                                 M_IADD_IMM(s1, iptr->val.i, d);
771                         } else {
772                                 ICONST(REG_ITMP2, iptr->val.i);
773                                 M_IADD(s1, REG_ITMP2, d);
774                         }
775                         store_reg_to_var_int(iptr->dst, d);
776                         break;
777
778                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
779
780                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
781                         var_to_reg_int_low(s2, src, REG_ITMP2);
782                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
783                         M_ADDC(s1, s2, GET_LOW_REG(d));
784                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
785                         var_to_reg_int_high(s2, src, REG_ITMP3);
786                         M_ADDE(s1, s2, GET_HIGH_REG(d));
787                         store_reg_to_var_int(iptr->dst, d);
788                         break;
789
790                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
791                                       /* val.l = constant                             */
792
793                         s3 = iptr->val.l & 0xffffffff;
794                         var_to_reg_int_low(s1, src, REG_ITMP1);
795                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
796                         if ((s3 >= -32768) && (s3 <= 32767)) {
797                                 M_ADDIC(s1, s3, GET_LOW_REG(d));
798
799                         } else {
800                                 ICONST(REG_ITMP2, s3);
801                                 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
802
803                         }
804                         var_to_reg_int_high(s1, src, REG_ITMP1);
805                         s3 = iptr->val.l >> 32;
806                         if (s3 == -1)
807                                 M_ADDME(s1, GET_HIGH_REG(d));
808                         else if (s3 == 0)
809                                 M_ADDZE(s1, GET_HIGH_REG(d));
810                         else {
811                                 ICONST(REG_ITMP3, s3);
812                                 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
813                         }
814                         store_reg_to_var_int(iptr->dst, d);
815                         break;
816
817                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
818
819                         var_to_reg_int(s1, src->prev, REG_ITMP1);
820                         var_to_reg_int(s2, src, REG_ITMP2);
821                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
822                         M_ISUB(s1, s2, d);
823                         store_reg_to_var_int(iptr->dst, d);
824                         break;
825
826                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
827                                       /* val.i = constant                             */
828
829                         var_to_reg_int(s1, src, REG_ITMP1);
830                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
831                         if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
832                                 M_IADD_IMM(s1, -iptr->val.i, d);
833                         } else {
834                                 ICONST(REG_ITMP2, -iptr->val.i);
835                                 M_IADD(s1, REG_ITMP2, d);
836                         }
837                         store_reg_to_var_int(iptr->dst, d);
838                         break;
839
840                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
841
842                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
843                         var_to_reg_int_low(s2, src, REG_ITMP2);
844                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
845                         M_SUBC(s1, s2, GET_LOW_REG(d));
846                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
847                         var_to_reg_int_high(s2, src, REG_ITMP3);
848                         M_SUBE(s1, s2, GET_HIGH_REG(d));
849                         store_reg_to_var_int(iptr->dst, d);
850                         break;
851
852                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
853                                       /* val.l = constant                             */
854
855                         s3 = (-iptr->val.l) & 0xffffffff;
856                         var_to_reg_int_low(s1, src, REG_ITMP1);
857                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
858                         if ((s3 >= -32768) && (s3 <= 32767)) {
859                                 M_ADDIC(s1, s3, GET_LOW_REG(d));
860                         } else {
861                                 ICONST(REG_ITMP2, s3);
862                                 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
863                         }
864                         var_to_reg_int_high(s1, src, REG_ITMP1);
865                         s3 = (-iptr->val.l) >> 32;
866                         if (s3 == -1)
867                                 M_ADDME(s1, GET_HIGH_REG(d));
868                         else if (s3 == 0)
869                                 M_ADDZE(s1, GET_HIGH_REG(d));
870                         else {
871                                 ICONST(REG_ITMP3, s3);
872                                 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
873                         }
874                         store_reg_to_var_int(iptr->dst, d);
875                         break;
876
877                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
878
879                         var_to_reg_int(s1, src->prev, REG_ITMP1);
880                         var_to_reg_int(s2, src, REG_ITMP2);
881                         M_TST(s2);
882                         M_BEQ(0);
883                         codegen_addxdivrefs(cd, mcodeptr);
884                         M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
885                         M_CMP(REG_ITMP3, s1);
886                         d = reg_of_var(rd, iptr->dst, REG_ITMP3); /* does not change flags*/
887                         M_BNE(3 + (s1 != d));
888                         M_CMPI(s2, -1);
889                         M_BNE(1 + (s1 != d));
890                         M_INTMOVE(s1, d);
891                         M_BR(1);
892                         M_IDIV(s1, s2, d);
893                         store_reg_to_var_int(iptr->dst, d);
894                         break;
895
896                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
897
898                         var_to_reg_int(s1, src->prev, REG_ITMP1);
899                         var_to_reg_int(s2, src, REG_ITMP2);
900                         M_TST(s2);
901                         M_BEQ(0);
902                         codegen_addxdivrefs(cd, mcodeptr);
903                         M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
904                         M_CMP(REG_ITMP3, s1);
905                         d = reg_of_var(rd, iptr->dst, REG_ITMP3); /* does not change flags*/
906                         M_BNE(4);
907                         M_CMPI(s2, -1);
908                         M_BNE(2);
909                         M_CLR(d);
910                         M_BR(3);
911                         M_IDIV(s1, s2, REG_ITMP3);
912                         M_IMUL(REG_ITMP3, s2, REG_ITMP3);
913                         M_ISUB(s1, REG_ITMP3, d);
914                         store_reg_to_var_int(iptr->dst, d);
915                         break;
916
917                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
918                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
919
920                         bte = iptr->val.a;
921                         md = bte->md;
922
923                         var_to_reg_int(s2, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
924                         M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
925                         M_BEQ(0);
926                         codegen_addxdivrefs(cd, mcodeptr);
927
928                         s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[1].regoff)],
929                                                    rd->argintregs[GET_HIGH_REG(md->params[1].regoff)]);
930                         M_TINTMOVE(TYPE_LNG, s2, s3);
931
932                         var_to_reg_int(s1, src->prev, PACK_REGS(REG_ITMP1, REG_ITMP2));
933                         s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[0].regoff)],
934                                                    rd->argintregs[GET_HIGH_REG(md->params[0].regoff)]);
935                         M_TINTMOVE(TYPE_LNG, s1, s3);
936
937                         disp = dseg_addaddress(cd, bte->fp);
938                         M_ALD(REG_ITMP1, REG_PV, disp);
939                         M_MTCTR(REG_ITMP1);
940                         M_JSR;
941
942                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_RESULT2, REG_RESULT));
943                         M_TINTMOVE(TYPE_LNG, PACK_REGS(REG_RESULT2, REG_RESULT), d);
944                         store_reg_to_var_int(iptr->dst, d);
945                         break;
946
947                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
948
949                         var_to_reg_int(s1, src->prev, REG_ITMP1);
950                         var_to_reg_int(s2, src, REG_ITMP2);
951                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
952                         M_IMUL(s1, s2, d);
953                         store_reg_to_var_int(iptr->dst, d);
954                         break;
955
956                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
957                                       /* val.i = constant                             */
958
959                         var_to_reg_int(s1, src, REG_ITMP1);
960                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
961                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
962                                 M_IMUL_IMM(s1, iptr->val.i, d);
963                                 }
964                         else {
965                                 ICONST(REG_ITMP2, iptr->val.i);
966                                 M_IMUL(s1, REG_ITMP2, d);
967                                 }
968                         store_reg_to_var_int(iptr->dst, d);
969                         break;
970
971                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
972                                       
973                         var_to_reg_int(s1, src, REG_ITMP1);
974                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
975                         M_SRA_IMM(s1, iptr->val.i, d);
976                         M_ADDZE(d, d);
977                         store_reg_to_var_int(iptr->dst, d);
978                         break;
979
980                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
981
982                         var_to_reg_int(s1, src->prev, REG_ITMP1);
983                         var_to_reg_int(s2, src, REG_ITMP2);
984                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
985                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
986                         M_SLL(s1, REG_ITMP3, d);
987                         store_reg_to_var_int(iptr->dst, d);
988                         break;
989
990                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
991                                       /* val.i = constant                             */
992
993                         var_to_reg_int(s1, src, REG_ITMP1);
994                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
995                         M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
996                         store_reg_to_var_int(iptr->dst, d);
997                         break;
998
999                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1000
1001                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1002                         var_to_reg_int(s2, src, REG_ITMP2);
1003                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1004                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
1005                         M_SRA(s1, REG_ITMP3, d);
1006                         store_reg_to_var_int(iptr->dst, d);
1007                         break;
1008
1009                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
1010                                       /* val.i = constant                             */
1011
1012                         var_to_reg_int(s1, src, REG_ITMP1);
1013                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1014                         M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1015                         store_reg_to_var_int(iptr->dst, d);
1016                         break;
1017
1018                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1019
1020                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1021                         var_to_reg_int(s2, src, REG_ITMP2);
1022                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1023                         M_AND_IMM(s2, 0x1f, REG_ITMP2);
1024                         M_SRL(s1, REG_ITMP2, d);
1025                         store_reg_to_var_int(iptr->dst, d);
1026                         break;
1027
1028                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1029                                       /* val.i = constant                             */
1030
1031                         var_to_reg_int(s1, src, REG_ITMP1);
1032                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1033                         if (iptr->val.i & 0x1f)
1034                                 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1035                         else
1036                                 M_INTMOVE(s1, d);
1037                         store_reg_to_var_int(iptr->dst, d);
1038                         break;
1039
1040                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1041
1042                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1043                         var_to_reg_int(s2, src, REG_ITMP2);
1044                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1045                         M_AND(s1, s2, d);
1046                         store_reg_to_var_int(iptr->dst, d);
1047                         break;
1048
1049                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
1050                                       /* val.i = constant                             */
1051
1052                         var_to_reg_int(s1, src, REG_ITMP1);
1053                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1054                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1055                                 M_AND_IMM(s1, iptr->val.i, d);
1056                                 }
1057                         /*
1058                         else if (iptr->val.i == 0xffffff) {
1059                                 M_RLWINM(s1, 0, 8, 31, d);
1060                                 }
1061                         */
1062                         else {
1063                                 ICONST(REG_ITMP2, iptr->val.i);
1064                                 M_AND(s1, REG_ITMP2, d);
1065                                 }
1066                         store_reg_to_var_int(iptr->dst, d);
1067                         break;
1068
1069                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1070
1071                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1072                         var_to_reg_int_low(s2, src, REG_ITMP2);
1073                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1074                         M_AND(s1, s2, GET_LOW_REG(d));
1075                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1076                         var_to_reg_int_high(s2, src, REG_ITMP3);
1077                         M_AND(s1, s2, GET_HIGH_REG(d));
1078                         store_reg_to_var_int(iptr->dst, d);
1079                         break;
1080
1081                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1082                                       /* val.l = constant                             */
1083
1084                         s3 = iptr->val.l & 0xffffffff;
1085                         var_to_reg_int_low(s1, src, REG_ITMP1);
1086                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1087                         if ((s3 >= 0) && (s3 <= 65535)) {
1088                                 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1089                         } else {
1090                                 ICONST(REG_ITMP2, s3);
1091                                 M_AND(s1, REG_ITMP2, GET_LOW_REG(d));
1092                         }
1093                         var_to_reg_int_high(s1, src, REG_ITMP1);
1094                         s3 = iptr->val.l >> 32;
1095                         if ((s3 >= 0) && (s3 <= 65535)) {
1096                                 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1097
1098                         } else {
1099                                 ICONST(REG_ITMP3, s3);
1100                                 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1101                         }
1102                         store_reg_to_var_int(iptr->dst, d);
1103                         break;
1104
1105                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
1106                                       /* val.i = constant                             */
1107
1108                         var_to_reg_int(s1, src, REG_ITMP1);
1109                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1110                         M_MOV(s1, REG_ITMP2);
1111                         M_CMPI(s1, 0);
1112                         M_BGE(1 + 2*(iptr->val.i >= 32768));
1113                         if (iptr->val.i >= 32768) {
1114                                 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1115                                 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1116                                 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1117                         } else
1118                                 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1119                         {
1120                                 int b=0, m = iptr->val.i;
1121                                 while (m >>= 1)
1122                                         ++b;
1123                                 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1124                         }
1125                         M_ISUB(s1, REG_ITMP2, d);
1126                         store_reg_to_var_int(iptr->dst, d);
1127                         break;
1128
1129                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1130
1131                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1132                         var_to_reg_int(s2, src, REG_ITMP2);
1133                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1134                         M_OR(s1, s2, d);
1135                         store_reg_to_var_int(iptr->dst, d);
1136                         break;
1137
1138                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
1139                                       /* val.i = constant                             */
1140
1141                         var_to_reg_int(s1, src, REG_ITMP1);
1142                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1143                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1144                                 M_OR_IMM(s1, iptr->val.i, d);
1145                                 }
1146                         else {
1147                                 ICONST(REG_ITMP2, iptr->val.i);
1148                                 M_OR(s1, REG_ITMP2, d);
1149                                 }
1150                         store_reg_to_var_int(iptr->dst, d);
1151                         break;
1152
1153                 case ICMD_LOR:       /* ..., val1, val2  ==> ..., val1 | val2        */
1154
1155                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1156                         var_to_reg_int_low(s2, src, REG_ITMP2);
1157                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1158                         M_OR(s1, s2, GET_LOW_REG(d));
1159                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1160                         var_to_reg_int_high(s2, src, REG_ITMP3);
1161                         M_OR(s1, s2, GET_HIGH_REG(d));
1162                         store_reg_to_var_int(iptr->dst, d);
1163                         break;
1164
1165                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1166                                       /* val.l = constant                             */
1167
1168                         s3 = iptr->val.l & 0xffffffff;
1169                         var_to_reg_int_low(s1, src, REG_ITMP1);
1170                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1171                         if ((s3 >= 0) && (s3 <= 65535)) {
1172                                 M_OR_IMM(s1, s3, GET_LOW_REG(d));
1173                         } else {
1174                                 ICONST(REG_ITMP2, s3);
1175                                 M_OR(s1, REG_ITMP2, GET_LOW_REG(d));
1176                         }
1177                         var_to_reg_int_high(s1, src, REG_ITMP1);
1178                         s3 = iptr->val.l >> 32;
1179                         if ((s3 >= 0) && (s3 <= 65535)) {
1180                                 M_OR_IMM(s1, s3, GET_HIGH_REG(d));
1181                         } else {
1182                                 ICONST(REG_ITMP3, s3);
1183                                 M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
1184                         }
1185                         store_reg_to_var_int(iptr->dst, d);
1186                         break;
1187
1188                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1189
1190                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1191                         var_to_reg_int(s2, src, REG_ITMP2);
1192                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1193                         M_XOR(s1, s2, d);
1194                         store_reg_to_var_int(iptr->dst, d);
1195                         break;
1196
1197                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1198                                       /* val.i = constant                             */
1199
1200                         var_to_reg_int(s1, src, REG_ITMP1);
1201                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1202                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1203                                 M_XOR_IMM(s1, iptr->val.i, d);
1204                                 }
1205                         else {
1206                                 ICONST(REG_ITMP2, iptr->val.i);
1207                                 M_XOR(s1, REG_ITMP2, d);
1208                                 }
1209                         store_reg_to_var_int(iptr->dst, d);
1210                         break;
1211
1212                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1213
1214                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1215                         var_to_reg_int_low(s2, src, REG_ITMP2);
1216                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1217                         M_XOR(s1, s2, GET_LOW_REG(d));
1218                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1219                         var_to_reg_int_high(s2, src, REG_ITMP3);
1220                         M_XOR(s1, s2, GET_HIGH_REG(d));
1221                         store_reg_to_var_int(iptr->dst, d);
1222                         break;
1223
1224                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1225                                       /* val.l = constant                             */
1226
1227                         s3 = iptr->val.l & 0xffffffff;
1228                         var_to_reg_int_low(s1, src, REG_ITMP1);
1229                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1230                         if ((s3 >= 0) && (s3 <= 65535)) {
1231                                 M_XOR_IMM(s1, s3, GET_LOW_REG(d));
1232                         } else {
1233                                 ICONST(REG_ITMP2, s3);
1234                                 M_XOR(s1, REG_ITMP2, GET_LOW_REG(d));
1235                         }
1236                         var_to_reg_int_high(s1, src, REG_ITMP1);
1237                         s3 = iptr->val.l >> 32;
1238                         if ((s3 >= 0) && (s3 <= 65535)) {
1239                                 M_XOR_IMM(s1, s3, GET_HIGH_REG(d));
1240                         } else {
1241                                 ICONST(REG_ITMP3, s3);
1242                                 M_XOR(s1, REG_ITMP3, GET_HIGH_REG(d));
1243                         }
1244                         store_reg_to_var_int(iptr->dst, d);
1245                         break;
1246
1247                 case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
1248                         /*******************************************************************
1249                 TODO: CHANGE THIS TO A VERSION THAT WORKS !!!
1250                         *******************************************************************/
1251                         var_to_reg_int_high(s1, src->prev, REG_ITMP3);
1252                         var_to_reg_int_high(s2, src, REG_ITMP2);
1253                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1254                         {
1255                                 int tempreg = false;
1256                                 int dreg;
1257                                 s4  *br1;
1258
1259                                 if (src->prev->flags & INMEMORY) {
1260                                         tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1261                                 } else {
1262                                         tempreg = tempreg || (d == GET_HIGH_REG(src->prev->regoff))
1263                                                         || (d == GET_LOW_REG(src->prev->regoff));
1264                                 }
1265                                 if (src->flags & INMEMORY) {
1266                                         tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1267                                 } else {
1268                                         tempreg = tempreg || (d == GET_HIGH_REG(src->regoff))
1269                                  || (d == GET_LOW_REG(src->regoff));
1270                                 }
1271
1272                                 dreg = tempreg ? REG_ITMP1 : d;
1273                                 M_IADD_IMM(REG_ZERO, 1, dreg);
1274                                 M_CMP(s1, s2);
1275                                 M_BGT(0);
1276                                 br1 = mcodeptr;
1277                                 M_BLT(0);
1278                                 var_to_reg_int_low(s1, src->prev, REG_ITMP3);
1279                                 var_to_reg_int_low(s2, src, REG_ITMP2);
1280                                 M_CMPU(s1, s2);
1281                                 M_BGT(3);
1282                                 M_BEQ(1);
1283                                 M_IADD_IMM(dreg, -1, dreg);
1284                                 M_IADD_IMM(dreg, -1, dreg);
1285                                 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1286                                 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1287                                 M_INTMOVE(dreg, d);
1288                         }
1289                         store_reg_to_var_int(iptr->dst, d);
1290                         break;
1291
1292                 case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
1293                                       /* op1 = variable, val.i = constant             */
1294
1295                         var = &(rd->locals[iptr->op1][TYPE_INT]);
1296                         if (var->flags & INMEMORY) {
1297                                 s1 = REG_ITMP1;
1298                                 M_ILD(s1, REG_SP, var->regoff * 4);
1299                         } else
1300                                 s1 = var->regoff;
1301                         {
1302                                 u4 m = iptr->val.i;
1303                                 if (m&0x8000)
1304                                         m += 65536;
1305                                 if (m&0xffff0000)
1306                                         M_ADDIS(s1, m>>16, s1);
1307                                 if (m&0xffff)
1308                                         M_IADD_IMM(s1, m&0xffff, s1);
1309                         }
1310                         if (var->flags & INMEMORY)
1311                                 M_IST(s1, REG_SP, var->regoff * 4);
1312                         break;
1313
1314
1315                 /* floating operations ************************************************/
1316
1317                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1318
1319                         var_to_reg_flt(s1, src, REG_FTMP1);
1320                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1321                         M_FMOVN(s1, d);
1322                         store_reg_to_var_flt(iptr->dst, d);
1323                         break;
1324
1325                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1326
1327                         var_to_reg_flt(s1, src, REG_FTMP1);
1328                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1329                         M_FMOVN(s1, d);
1330                         store_reg_to_var_flt(iptr->dst, d);
1331                         break;
1332
1333                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1334
1335                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1336                         var_to_reg_flt(s2, src, REG_FTMP2);
1337                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1338                         M_FADD(s1, s2, d);
1339                         store_reg_to_var_flt(iptr->dst, d);
1340                         break;
1341
1342                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1343
1344                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1345                         var_to_reg_flt(s2, src, REG_FTMP2);
1346                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1347                         M_DADD(s1, s2, d);
1348                         store_reg_to_var_flt(iptr->dst, d);
1349                         break;
1350
1351                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1352
1353                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1354                         var_to_reg_flt(s2, src, REG_FTMP2);
1355                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1356                         M_FSUB(s1, s2, d);
1357                         store_reg_to_var_flt(iptr->dst, d);
1358                         break;
1359
1360                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1361
1362                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1363                         var_to_reg_flt(s2, src, REG_FTMP2);
1364                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1365                         M_DSUB(s1, s2, d);
1366                         store_reg_to_var_flt(iptr->dst, d);
1367                         break;
1368
1369                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1370
1371                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1372                         var_to_reg_flt(s2, src, REG_FTMP2);
1373                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1374                         M_FMUL(s1, s2, d);
1375                         store_reg_to_var_flt(iptr->dst, d);
1376                         break;
1377
1378                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1379
1380                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1381                         var_to_reg_flt(s2, src, REG_FTMP2);
1382                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1383                         M_DMUL(s1, s2, d);
1384                         store_reg_to_var_flt(iptr->dst, d);
1385                         break;
1386
1387                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1388
1389                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1390                         var_to_reg_flt(s2, src, REG_FTMP2);
1391                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1392                         M_FDIV(s1, s2, d);
1393                         store_reg_to_var_flt(iptr->dst, d);
1394                         break;
1395
1396                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1397
1398                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1399                         var_to_reg_flt(s2, src, REG_FTMP2);
1400                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1401                         M_DDIV(s1, s2, d);
1402                         store_reg_to_var_flt(iptr->dst, d);
1403                         break;
1404                 
1405                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1406                 case ICMD_D2I:
1407                         var_to_reg_flt(s1, src, REG_FTMP1);
1408                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1409                         M_CLR(d);
1410                         a = dseg_addfloat(cd, 0.0);
1411                         M_FLD(REG_FTMP2, REG_PV, a);
1412                         M_FCMPU(s1, REG_FTMP2);
1413                         M_BNAN(4);
1414                         a = dseg_adds4(cd, 0);
1415                         M_CVTDL_C(s1, REG_FTMP1);
1416                         M_LDA (REG_ITMP1, REG_PV, a);
1417                         M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1418                         M_ILD (d, REG_PV, a);
1419                         store_reg_to_var_int(iptr->dst, d);
1420                         break;
1421                 
1422                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1423
1424                         var_to_reg_flt(s1, src, REG_FTMP1);
1425                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1426                         M_FLTMOVE(s1, d);
1427                         store_reg_to_var_flt(iptr->dst, d);
1428                         break;
1429                                         
1430                 case ICMD_D2F:       /* ..., value  ==> ..., (double) value           */
1431
1432                         var_to_reg_flt(s1, src, REG_FTMP1);
1433                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1434                         M_CVTDF(s1, d);
1435                         store_reg_to_var_flt(iptr->dst, d);
1436                         break;
1437                 
1438                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1439                 case ICMD_DCMPL:
1440                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1441                         var_to_reg_flt(s2, src, REG_FTMP2);
1442                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1443                         M_FCMPU(s2, s1);
1444                         M_IADD_IMM(0, -1, d);
1445                         M_BNAN(4);
1446                         M_BGT(3);
1447                         M_IADD_IMM(0, 0, d);
1448                         M_BGE(1);
1449                         M_IADD_IMM(0, 1, d);
1450                         store_reg_to_var_int(iptr->dst, d);
1451                         break;
1452
1453                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1454                 case ICMD_DCMPG:
1455                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1456                         var_to_reg_flt(s2, src, REG_FTMP2);
1457                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1458                         M_FCMPU(s1, s2);
1459                         M_IADD_IMM(0, 1, d);
1460                         M_BNAN(4);
1461                         M_BGT(3);
1462                         M_IADD_IMM(0, 0, d);
1463                         M_BGE(1);
1464                         M_IADD_IMM(0, -1, d);
1465                         store_reg_to_var_int(iptr->dst, d);
1466                         break;
1467                         
1468
1469                 /* memory operations **************************************************/
1470
1471                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1472
1473                         var_to_reg_int(s1, src, REG_ITMP1);
1474                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1475                         gen_nullptr_check(s1);
1476                         M_ILD(d, s1, OFFSET(java_arrayheader, size));
1477                         store_reg_to_var_int(iptr->dst, d);
1478                         break;
1479
1480                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1481
1482                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1483                         var_to_reg_int(s2, src, REG_ITMP2);
1484                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1485                         if (iptr->op1 == 0) {
1486                                 gen_nullptr_check(s1);
1487                                 gen_bound_check;
1488                         }
1489                         M_SLL_IMM(s2, 2, REG_ITMP2);
1490                         M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1491                         M_LWZX(d, s1, REG_ITMP2);
1492                         store_reg_to_var_int(iptr->dst, d);
1493                         break;
1494
1495                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1496
1497                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1498                         var_to_reg_int(s2, src, REG_ITMP2);
1499                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1500                         if (iptr->op1 == 0) {
1501                                 gen_nullptr_check(s1);
1502                                 gen_bound_check;
1503                         }
1504                         M_SLL_IMM(s2, 3, REG_ITMP2);
1505                         M_IADD(s1, REG_ITMP2, REG_ITMP2);
1506                         M_ILD(GET_HIGH_REG(d), REG_ITMP2, OFFSET(java_longarray, data[0]));
1507                         M_ILD(GET_LOW_REG(d), REG_ITMP2, OFFSET(java_longarray,
1508                             data[0]) + 4);
1509                         store_reg_to_var_int(iptr->dst, d);
1510                         break;
1511
1512                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1513
1514                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1515                         var_to_reg_int(s2, src, REG_ITMP2);
1516                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1517                         if (iptr->op1 == 0) {
1518                                 gen_nullptr_check(s1);
1519                                 gen_bound_check;
1520                         }
1521                         M_SLL_IMM(s2, 2, REG_ITMP2);
1522                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1523                         M_LWZX(d, s1, REG_ITMP2);
1524                         store_reg_to_var_int(iptr->dst, d);
1525                         break;
1526
1527                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1528
1529                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1530                         var_to_reg_int(s2, src, REG_ITMP2);
1531                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1532                         if (iptr->op1 == 0) {
1533                                 gen_nullptr_check(s1);
1534                                 gen_bound_check;
1535                         }
1536                         M_SLL_IMM(s2, 2, REG_ITMP2);
1537                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1538                         M_LFSX(d, s1, REG_ITMP2);
1539                         store_reg_to_var_flt(iptr->dst, d);
1540                         break;
1541
1542                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1543
1544                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1545                         var_to_reg_int(s2, src, REG_ITMP2);
1546                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1547                         if (iptr->op1 == 0) {
1548                                 gen_nullptr_check(s1);
1549                                 gen_bound_check;
1550                         }
1551                         M_SLL_IMM(s2, 3, REG_ITMP2);
1552                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1553                         M_LFDX(d, s1, REG_ITMP2);
1554                         store_reg_to_var_flt(iptr->dst, d);
1555                         break;
1556
1557                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1558
1559                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1560                         var_to_reg_int(s2, src, REG_ITMP2);
1561                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1562                         if (iptr->op1 == 0) {
1563                                 gen_nullptr_check(s1);
1564                                 gen_bound_check;
1565                         }
1566                         M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1567                         M_LBZX(d, s1, REG_ITMP2);
1568                         M_BSEXT(d, d);
1569                         store_reg_to_var_int(iptr->dst, d);
1570                         break;                  
1571
1572                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1573
1574                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1575                         var_to_reg_int(s2, src, REG_ITMP2);
1576                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1577                         if (iptr->op1 == 0) {
1578                                 gen_nullptr_check(s1);
1579                                 gen_bound_check;
1580                         }
1581                         M_SLL_IMM(s2, 1, REG_ITMP2);
1582                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1583                         M_LHAX(d, s1, REG_ITMP2);
1584                         store_reg_to_var_int(iptr->dst, d);
1585                         break;
1586
1587                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1588
1589                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1590                         var_to_reg_int(s2, src, REG_ITMP2);
1591                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1592                         if (iptr->op1 == 0) {
1593                                 gen_nullptr_check(s1);
1594                                 gen_bound_check;
1595                         }
1596                         M_SLL_IMM(s2, 1, REG_ITMP2);
1597                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1598                         M_LHZX(d, s1, REG_ITMP2);
1599                         store_reg_to_var_int(iptr->dst, d);
1600                         break;
1601
1602                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1603
1604                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1605                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1606                         if (iptr->op1 == 0) {
1607                                 gen_nullptr_check(s1);
1608                                 gen_bound_check;
1609                         }
1610                         var_to_reg_int_high(s3, src, REG_ITMP3);
1611                         M_SLL_IMM(s2, 3, REG_ITMP2);
1612                         M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1613                         M_STWX(s3, s1, REG_ITMP2);
1614                         M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1615                         var_to_reg_int_low(s3, src, REG_ITMP3);
1616                         M_STWX(s3, s1, REG_ITMP2);
1617                         break;
1618
1619                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1620
1621                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1622                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1623                         if (iptr->op1 == 0) {
1624                                 gen_nullptr_check(s1);
1625                                 gen_bound_check;
1626                         }
1627                         var_to_reg_int(s3, src, REG_ITMP3);
1628                         M_SLL_IMM(s2, 2, REG_ITMP2);
1629                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1630                         M_STWX(s3, s1, REG_ITMP2);
1631                         break;
1632
1633                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1634
1635                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1636                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1637                         if (iptr->op1 == 0) {
1638                                 gen_nullptr_check(s1);
1639                                 gen_bound_check;
1640                         }
1641                         var_to_reg_flt(s3, src, REG_FTMP3);
1642                         M_SLL_IMM(s2, 2, REG_ITMP2);
1643                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1644                         M_STFSX(s3, s1, REG_ITMP2);
1645                         break;
1646
1647                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1648
1649                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1650                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1651                         if (iptr->op1 == 0) {
1652                                 gen_nullptr_check(s1);
1653                                 gen_bound_check;
1654                         }
1655                         var_to_reg_flt(s3, src, REG_FTMP3);
1656                         M_SLL_IMM(s2, 3, REG_ITMP2);
1657                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1658                         M_STFDX(s3, s1, REG_ITMP2);
1659                         break;
1660
1661                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1662
1663                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1664                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1665                         if (iptr->op1 == 0) {
1666                                 gen_nullptr_check(s1);
1667                                 gen_bound_check;
1668                         }
1669                         var_to_reg_int(s3, src, REG_ITMP3);
1670                         M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1671                         M_STBX(s3, s1, REG_ITMP2);
1672                         break;
1673
1674                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1675
1676                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1677                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1678                         if (iptr->op1 == 0) {
1679                                 gen_nullptr_check(s1);
1680                                 gen_bound_check;
1681                         }
1682                         var_to_reg_int(s3, src, REG_ITMP3);
1683                         M_SLL_IMM(s2, 1, REG_ITMP2);
1684                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1685                         M_STHX(s3, s1, REG_ITMP2);
1686                         break;
1687
1688                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1689
1690                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1691                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1692                         if (iptr->op1 == 0) {
1693                                 gen_nullptr_check(s1);
1694                                 gen_bound_check;
1695                         }
1696                         var_to_reg_int(s3, src, REG_ITMP3);
1697                         M_SLL_IMM(s2, 1, REG_ITMP2);
1698                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1699                         M_STHX(s3, s1, REG_ITMP2);
1700                         break;
1701
1702
1703                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1704
1705                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1706                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1707 /*                      if (iptr->op1 == 0) { */
1708                                 gen_nullptr_check(s1);
1709                                 gen_bound_check;
1710 /*                      } */
1711                         var_to_reg_int(s3, src, REG_ITMP3);
1712
1713                         M_MOV(s1, rd->argintregs[0]);
1714                         M_MOV(s3, rd->argintregs[1]);
1715                         bte = iptr->val.a;
1716                         disp = dseg_addaddress(cd, bte->fp);
1717                         M_ALD(REG_ITMP1, REG_PV, disp);
1718                         M_MTCTR(REG_ITMP1);
1719                         M_JSR;
1720                         M_TST(REG_RESULT);
1721                         M_BEQ(0);
1722                         codegen_addxstorerefs(cd, mcodeptr);
1723
1724                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1725                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1726                         var_to_reg_int(s3, src, REG_ITMP3);
1727                         M_SLL_IMM(s2, 2, REG_ITMP2);
1728                         M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1729                         M_STWX(s3, s1, REG_ITMP2);
1730                         break;
1731
1732
1733                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1734                                       /* op1 = type, val.a = field address            */
1735
1736                         if (!iptr->val.a) {
1737                                 codegen_addpatchref(cd, mcodeptr,
1738                                                                         PATCHER_get_putstatic,
1739                                                                         (unresolved_field *) iptr->target);
1740
1741                                 if (opt_showdisassemble)
1742                                         M_NOP;
1743
1744                                 a = 0;
1745
1746                         } else {
1747                                 fieldinfo *fi = iptr->val.a;
1748
1749                                 if (!fi->class->initialized) {
1750                                         codegen_addpatchref(cd, mcodeptr,
1751                                                                                 PATCHER_clinit, fi->class);
1752
1753                                         if (opt_showdisassemble)
1754                                                 M_NOP;
1755                                 }
1756
1757                                 a = (ptrint) &(fi->value);
1758                         }
1759
1760                         a = dseg_addaddress(cd, a);
1761                         M_ALD(REG_ITMP1, REG_PV, a);
1762                         switch (iptr->op1) {
1763                         case TYPE_INT:
1764                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1765                                 M_ILD(d, REG_ITMP1, 0);
1766                                 store_reg_to_var_int(iptr->dst, d);
1767                                 break;
1768                         case TYPE_LNG:
1769                                 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1770                                 M_ILD(GET_HIGH_REG(d), REG_ITMP1, 0);
1771                                 M_ILD(GET_LOW_REG(d), REG_ITMP1, 4);
1772                                 store_reg_to_var_int(iptr->dst, d);
1773                                 break;
1774                         case TYPE_ADR:
1775                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1776                                 M_ALD(d, REG_ITMP1, 0);
1777                                 store_reg_to_var_int(iptr->dst, d);
1778                                 break;
1779                         case TYPE_FLT:
1780                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1781                                 M_FLD(d, REG_ITMP1, 0);
1782                                 store_reg_to_var_flt(iptr->dst, d);
1783                                 break;
1784                         case TYPE_DBL:                          
1785                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1786                                 M_DLD(d, REG_ITMP1, 0);
1787                                 store_reg_to_var_flt(iptr->dst, d);
1788                                 break;
1789                         }
1790                         break;
1791
1792                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1793                                       /* op1 = type, val.a = field address            */
1794
1795
1796                         if (!iptr->val.a) {
1797                                 codegen_addpatchref(cd, mcodeptr,
1798                                                                         PATCHER_get_putstatic,
1799                                                                         (unresolved_field *) iptr->target);
1800
1801                                 if (opt_showdisassemble)
1802                                         M_NOP;
1803
1804                                 a = 0;
1805
1806                         } else {
1807                                 fieldinfo *fi = iptr->val.a;
1808
1809                                 if (!fi->class->initialized) {
1810                                         codegen_addpatchref(cd, mcodeptr,
1811                                                                                 PATCHER_clinit, fi->class);
1812
1813                                         if (opt_showdisassemble)
1814                                                 M_NOP;
1815                                 }
1816
1817                                 a = (ptrint) &(fi->value);
1818                         }
1819
1820                         disp = dseg_addaddress(cd, a);
1821                         M_ALD(REG_ITMP1, REG_PV, disp);
1822                         switch (iptr->op1) {
1823                         case TYPE_INT:
1824                                 var_to_reg_int(s2, src, REG_ITMP2);
1825                                 M_IST(s2, REG_ITMP1, 0);
1826                                 break;
1827                         case TYPE_LNG:
1828                                 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1829                                 M_IST(GET_HIGH_REG(s2), REG_ITMP1, 0);
1830                                 M_IST(GET_LOW_REG(s2), REG_ITMP1, 4);
1831                                 break;
1832                         case TYPE_ADR:
1833                                 var_to_reg_int(s2, src, REG_ITMP2);
1834                                 M_AST(s2, REG_ITMP1, 0);
1835                                 break;
1836                         case TYPE_FLT:
1837                                 var_to_reg_flt(s2, src, REG_FTMP2);
1838                                 M_FST(s2, REG_ITMP1, 0);
1839                                 break;
1840                         case TYPE_DBL:
1841                                 var_to_reg_flt(s2, src, REG_FTMP2);
1842                                 M_DST(s2, REG_ITMP1, 0);
1843                                 break;
1844                         }
1845                         break;
1846
1847
1848                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1849                                       /* op1 = type, val.i = field offset             */
1850
1851                         var_to_reg_int(s1, src, REG_ITMP1);
1852                         gen_nullptr_check(s1);
1853
1854                         if (!iptr->val.a) {
1855                                 codegen_addpatchref(cd, mcodeptr,
1856                                                                         PATCHER_get_putfield,
1857                                                                         (unresolved_field *) iptr->target);
1858
1859                                 if (opt_showdisassemble)
1860                                         M_NOP;
1861
1862                                 a = 0;
1863
1864                         } else {
1865                                 a = ((fieldinfo *) (iptr->val.a))->offset;
1866                         }
1867
1868                         switch (iptr->op1) {
1869                         case TYPE_INT:
1870                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1871                                 M_ILD(d, s1, a);
1872                                 store_reg_to_var_int(iptr->dst, d);
1873                                 break;
1874                         case TYPE_LNG:
1875                                 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1876                                 M_ILD(GET_HIGH_REG(d), s1, a);
1877                                 M_ILD(GET_LOW_REG(d), s1, a + 4);
1878                                 store_reg_to_var_int(iptr->dst, d);
1879                                 break;
1880                         case TYPE_ADR:
1881                                 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1882                                 M_ALD(d, s1, a);
1883                                 store_reg_to_var_int(iptr->dst, d);
1884                                 break;
1885                         case TYPE_FLT:
1886                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1887                                 M_FLD(d, s1, a);
1888                                 store_reg_to_var_flt(iptr->dst, d);
1889                                 break;
1890                         case TYPE_DBL:                          
1891                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1892                                 M_DLD(d, s1, a);
1893                                 store_reg_to_var_flt(iptr->dst, d);
1894                                 break;
1895                         }
1896                         break;
1897
1898                 case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
1899                                       /* op1 = type, val.i = field offset             */
1900
1901                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1902                         gen_nullptr_check(s1);
1903
1904                         if (!IS_FLT_DBL_TYPE(iptr->op1)) {
1905                                 if (IS_2_WORD_TYPE(iptr->op1)) {
1906                                         var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1907                                 } else {
1908                                         var_to_reg_int(s2, src, REG_ITMP2);
1909                                 }
1910                         } else {
1911                                 var_to_reg_flt(s2, src, REG_FTMP2);
1912                         }
1913
1914                         if (!iptr->val.a) {
1915                                 codegen_addpatchref(cd, mcodeptr,
1916                                                                         PATCHER_get_putfield,
1917                                                                         (unresolved_field *) iptr->target);
1918
1919                                 if (opt_showdisassemble)
1920                                         M_NOP;
1921
1922                                 a = 0;
1923
1924                         } else {
1925                                 a = ((fieldinfo *) (iptr->val.a))->offset;
1926                         }
1927
1928                         switch (iptr->op1) {
1929                         case TYPE_INT:
1930                                 M_IST(s2, s1, a);
1931                                 break;
1932                         case TYPE_LNG:
1933                                 M_IST(GET_HIGH_REG(s2), s1, a);
1934                                 M_IST(GET_LOW_REG(s2), s1, a + 4);
1935                                 break;
1936                         case TYPE_ADR:
1937                                 M_AST(s2, s1, a);
1938                                 break;
1939                         case TYPE_FLT:
1940                                 M_FST(s2, s1, a);
1941                                 break;
1942                         case TYPE_DBL:
1943                                 M_DST(s2, s1, a);
1944                                 break;
1945                         }
1946                         break;
1947
1948
1949                 /* branch operations **************************************************/
1950
1951                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1952
1953                         disp = dseg_addaddress(cd, asm_handle_exception);
1954                         M_ALD(REG_ITMP2, REG_PV, disp);
1955                         M_MTCTR(REG_ITMP2);
1956                         var_to_reg_int(s1, src, REG_ITMP1);
1957                         M_INTMOVE(s1, REG_ITMP1_XPTR);
1958
1959                         if (m->isleafmethod) M_MFLR(REG_ITMP3);  /* save LR */
1960                         M_BL(0);            /* get current PC */
1961                         M_MFLR(REG_ITMP2_XPC);
1962                         if (m->isleafmethod) M_MTLR(REG_ITMP3);  /* restore LR */
1963                         M_RTS;              /* jump to CTR */
1964
1965                         ALIGNCODENOP;
1966                         break;
1967
1968                 case ICMD_GOTO:         /* ... ==> ...                                */
1969                                         /* op1 = target JavaVM pc                     */
1970                         M_BR(0);
1971                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1972                         ALIGNCODENOP;
1973                         break;
1974
1975                 case ICMD_JSR:          /* ... ==> ...                                */
1976                                         /* op1 = target JavaVM pc                     */
1977
1978                         if (m->isleafmethod) M_MFLR(REG_ITMP2);
1979                         M_BL(0);
1980                         M_MFLR(REG_ITMP1);
1981                         M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
1982                         if (m->isleafmethod) M_MTLR(REG_ITMP2);
1983                         M_BR(0);
1984                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1985                         break;
1986                         
1987                 case ICMD_RET:          /* ... ==> ...                                */
1988                                         /* op1 = local variable                       */
1989
1990                         var = &(rd->locals[iptr->op1][TYPE_ADR]);
1991                         if (var->flags & INMEMORY) {
1992                                 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
1993                                 M_MTCTR(REG_ITMP1);
1994                         } else
1995                                 M_MTCTR(var->regoff);
1996                         M_RTS;
1997                         ALIGNCODENOP;
1998                         break;
1999
2000                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
2001                                         /* op1 = target JavaVM pc                     */
2002
2003                         var_to_reg_int(s1, src, REG_ITMP1);
2004                         M_TST(s1);
2005                         M_BEQ(0);
2006                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2007                         break;
2008
2009                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
2010                                         /* op1 = target JavaVM pc                     */
2011
2012                         var_to_reg_int(s1, src, REG_ITMP1);
2013                         M_TST(s1);
2014                         M_BNE(0);
2015                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2016                         break;
2017
2018                 case ICMD_IFLT:
2019                 case ICMD_IFLE:
2020                 case ICMD_IFNE:
2021                 case ICMD_IFGT:
2022                 case ICMD_IFGE:
2023                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
2024                                         /* op1 = target JavaVM pc, val.i = constant   */
2025
2026                         var_to_reg_int(s1, src, REG_ITMP1);
2027                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2028                                 M_CMPI(s1, iptr->val.i);
2029                                 }
2030                         else {
2031                                 ICONST(REG_ITMP2, iptr->val.i);
2032                                 M_CMP(s1, REG_ITMP2);
2033                                 }
2034                         switch (iptr->opc)
2035                         {
2036                                 case ICMD_IFLT:
2037                                         M_BLT(0);
2038                                         break;
2039                                 case ICMD_IFLE:
2040                                         M_BLE(0);
2041                                         break;
2042                                 case ICMD_IFNE:
2043                                         M_BNE(0);
2044                                         break;
2045                                 case ICMD_IFGT:
2046                                         M_BGT(0);
2047                                         break;
2048                                 case ICMD_IFGE:
2049                                         M_BGE(0);
2050                                         break;
2051                                 case ICMD_IFEQ:
2052                                         M_BEQ(0);
2053                                         break;
2054                                 }
2055                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2056                         break;
2057
2058
2059                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
2060                                         /* op1 = target JavaVM pc, val.l = constant   */
2061
2062                         var_to_reg_int_low(s1, src, REG_ITMP1);
2063                         var_to_reg_int_high(s2, src, REG_ITMP2);
2064                         if (iptr->val.l == 0) {
2065                                 M_OR(s1, s2, REG_ITMP3);
2066                                 M_CMPI(REG_ITMP3, 0);
2067
2068                         } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2069                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2070                                 M_BNE(2);
2071                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2072
2073                         } else {
2074                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2075                                 M_CMP(s2, REG_ITMP3);
2076                                 M_BNE(3);
2077                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2078                                 M_CMP(s1, REG_ITMP3)
2079                         }
2080                         M_BEQ(0);
2081                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2082                         break;
2083                         
2084                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
2085                                         /* op1 = target JavaVM pc, val.l = constant   */
2086                         var_to_reg_int_low(s1, src, REG_ITMP1);
2087                         var_to_reg_int_high(s2, src, REG_ITMP2);
2088 /*                      if (iptr->val.l == 0) { */
2089 /*                              M_OR(s1, s2, REG_ITMP3); */
2090 /*                              M_CMPI(REG_ITMP3, 0); */
2091
2092 /*                      } else  */
2093                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2094                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2095                                 M_BLT(0);
2096                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2097                                 M_BGT(2);
2098                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2099
2100                         } else {
2101                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2102                                 M_CMP(s2, REG_ITMP3);
2103                                 M_BLT(0);
2104                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2105                                 M_BGT(3);
2106                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2107                                 M_CMP(s1, REG_ITMP3)
2108                         }
2109                         M_BLT(0);
2110                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2111                         break;
2112                         
2113                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
2114                                         /* op1 = target JavaVM pc, val.l = constant   */
2115
2116                         var_to_reg_int_low(s1, src, REG_ITMP1);
2117                         var_to_reg_int_high(s2, src, REG_ITMP2);
2118 /*                      if (iptr->val.l == 0) { */
2119 /*                              M_OR(s1, s2, REG_ITMP3); */
2120 /*                              M_CMPI(REG_ITMP3, 0); */
2121
2122 /*                      } else  */
2123                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2124                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2125                                 M_BLT(0);
2126                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2127                                 M_BGT(2);
2128                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2129
2130                         } else {
2131                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2132                                 M_CMP(s2, REG_ITMP3);
2133                                 M_BLT(0);
2134                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2135                                 M_BGT(3);
2136                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2137                                 M_CMP(s1, REG_ITMP3)
2138                         }
2139                         M_BLE(0);
2140                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2141                         break;
2142                         
2143                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
2144                                         /* op1 = target JavaVM pc, val.l = constant   */
2145
2146                         var_to_reg_int_low(s1, src, REG_ITMP1);
2147                         var_to_reg_int_high(s2, src, REG_ITMP2);
2148                         if (iptr->val.l == 0) {
2149                                 M_OR(s1, s2, REG_ITMP3);
2150                                 M_CMPI(REG_ITMP3, 0);
2151
2152                         } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2153                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2154                                 M_BEQ(2);
2155                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2156
2157                         } else {
2158                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2159                                 M_CMP(s2, REG_ITMP3);
2160                                 M_BEQ(3);
2161                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2162                                 M_CMP(s1, REG_ITMP3)
2163                         }
2164                         M_BNE(0);
2165                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2166                         break;
2167                         
2168                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
2169                                         /* op1 = target JavaVM pc, val.l = constant   */
2170
2171                         var_to_reg_int_low(s1, src, REG_ITMP1);
2172                         var_to_reg_int_high(s2, src, REG_ITMP2);
2173 /*                      if (iptr->val.l == 0) { */
2174 /*                              M_OR(s1, s2, REG_ITMP3); */
2175 /*                              M_CMPI(REG_ITMP3, 0); */
2176
2177 /*                      } else  */
2178                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2179                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2180                                 M_BGT(0);
2181                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2182                                 M_BLT(2);
2183                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2184
2185                         } else {
2186                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2187                                 M_CMP(s2, REG_ITMP3);
2188                                 M_BGT(0);
2189                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2190                                 M_BLT(3);
2191                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2192                                 M_CMP(s1, REG_ITMP3)
2193                         }
2194                         M_BGT(0);
2195                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2196                         break;
2197                         
2198                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
2199                                         /* op1 = target JavaVM pc, val.l = constant   */
2200                         var_to_reg_int_low(s1, src, REG_ITMP1);
2201                         var_to_reg_int_high(s2, src, REG_ITMP2);
2202 /*                      if (iptr->val.l == 0) { */
2203 /*                              M_OR(s1, s2, REG_ITMP3); */
2204 /*                              M_CMPI(REG_ITMP3, 0); */
2205
2206 /*                      } else  */
2207                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2208                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2209                                 M_BGT(0);
2210                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2211                                 M_BLT(2);
2212                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2213
2214                         } else {
2215                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2216                                 M_CMP(s2, REG_ITMP3);
2217                                 M_BGT(0);
2218                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2219                                 M_BLT(3);
2220                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2221                                 M_CMP(s1, REG_ITMP3)
2222                         }
2223                         M_BGE(0);
2224                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2225                         break;
2226
2227                         /* CUT: alle _L */
2228                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
2229                 case ICMD_IF_LCMPEQ:    /* op1 = target JavaVM pc                     */
2230                         /******************************************************************
2231             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2232                         *******************************************************************/
2233                 case ICMD_IF_ACMPEQ:
2234
2235                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2236                         var_to_reg_int(s2, src, REG_ITMP2);
2237                         M_CMP(s1, s2);
2238                         M_BEQ(0);
2239                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2240                         break;
2241
2242                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
2243                 case ICMD_IF_LCMPNE:    /* op1 = target JavaVM pc                     */
2244                         /******************************************************************
2245             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2246                         *******************************************************************/
2247                 case ICMD_IF_ACMPNE:
2248
2249                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2250                         var_to_reg_int(s2, src, REG_ITMP2);
2251                         M_CMP(s1, s2);
2252                         M_BNE(0);
2253                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2254                         break;
2255
2256                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
2257                 case ICMD_IF_LCMPLT:    /* op1 = target JavaVM pc                     */
2258                         /******************************************************************
2259             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2260                         *******************************************************************/
2261
2262                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2263                         var_to_reg_int(s2, src, REG_ITMP2);
2264                         M_CMP(s1, s2);
2265                         M_BLT(0);
2266                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2267                         break;
2268
2269                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
2270                 case ICMD_IF_LCMPGT:    /* op1 = target JavaVM pc                     */
2271                         /******************************************************************
2272             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2273                         *******************************************************************/
2274
2275                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2276                         var_to_reg_int(s2, src, REG_ITMP2);
2277                         M_CMP(s1, s2);
2278                         M_BGT(0);
2279                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2280                         break;
2281
2282                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
2283                 case ICMD_IF_LCMPLE:    /* op1 = target JavaVM pc                     */
2284                         /******************************************************************
2285             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2286                         *******************************************************************/
2287
2288                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2289                         var_to_reg_int(s2, src, REG_ITMP2);
2290                         M_CMP(s1, s2);
2291                         M_BLE(0);
2292                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2293                         break;
2294
2295                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
2296                 case ICMD_IF_LCMPGE:    /* op1 = target JavaVM pc                     */
2297                         /******************************************************************
2298             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2299                         *******************************************************************/
2300
2301                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2302                         var_to_reg_int(s2, src, REG_ITMP2);
2303                         M_CMP(s1, s2);
2304                         M_BGE(0);
2305                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2306                         break;
2307
2308                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2309                 case ICMD_ARETURN:
2310                         var_to_reg_int(s1, src, REG_RESULT);
2311                         M_TINTMOVE(src->type, s1, REG_RESULT);
2312                         goto nowperformreturn;
2313                 case ICMD_LRETURN:
2314                         var_to_reg_int(s1, src, PACK_REGS(REG_RESULT2, REG_RESULT));
2315                         M_TINTMOVE(src->type, s1, PACK_REGS(REG_RESULT2, REG_RESULT));
2316                         goto nowperformreturn;
2317
2318                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2319                 case ICMD_DRETURN:
2320                         var_to_reg_flt(s1, src, REG_FRESULT);
2321                         M_FLTMOVE(s1, REG_FRESULT);
2322                         goto nowperformreturn;
2323
2324                 case ICMD_RETURN:      /* ...  ==> ...                                */
2325
2326 nowperformreturn:
2327                         {
2328                         s4 i, p;
2329                         
2330                         p = parentargs_base;
2331
2332                         /* call trace function */
2333
2334                         if (runverbose) {
2335                                 M_MFLR(REG_ITMP3);
2336                                 M_LDA(REG_SP, REG_SP, -10 * 8);
2337                                 M_DST(REG_FRESULT, REG_SP, 48+0);
2338                                 M_IST(REG_RESULT, REG_SP, 48+8);
2339                                 M_AST(REG_ITMP3, REG_SP, 48+12);
2340                                 M_IST(REG_RESULT2, REG_SP, 48+16);
2341
2342                                 /* keep this order */
2343                                 switch (iptr->opc) {
2344                                 case ICMD_IRETURN:
2345                                 case ICMD_ARETURN:
2346 #if defined(__DARWIN__)
2347                                         M_MOV(REG_RESULT, rd->argintregs[2]);
2348                                         M_CLR(rd->argintregs[1]);
2349 #else
2350                                         M_MOV(REG_RESULT, rd->argintregs[3]);
2351                                         M_CLR(rd->argintregs[2]);
2352 #endif
2353                                         break;
2354
2355                                 case ICMD_LRETURN:
2356 #if defined(__DARWIN__)
2357                                         M_MOV(REG_RESULT2, rd->argintregs[2]);
2358                                         M_MOV(REG_RESULT, rd->argintregs[1]);
2359 #else
2360                                         M_MOV(REG_RESULT2, rd->argintregs[3]);
2361                                         M_MOV(REG_RESULT, rd->argintregs[2]);
2362 #endif
2363                                         break;
2364                                 }
2365
2366                                 a = dseg_addaddress(cd, m);
2367                                 M_ALD(rd->argintregs[0], REG_PV, a);
2368
2369                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2370                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2371                                 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2372                                 M_ALD(REG_ITMP2, REG_PV, a);
2373                                 M_MTCTR(REG_ITMP2);
2374                                 M_JSR;
2375                                 M_DLD(REG_FRESULT, REG_SP, 48+0);
2376                                 M_ILD(REG_RESULT, REG_SP, 48+8);
2377                                 M_ALD(REG_ITMP3, REG_SP, 48+12);
2378                                 M_ILD(REG_RESULT2, REG_SP, 48+16);
2379                                 M_LDA(REG_SP, REG_SP, 10 * 8);
2380                                 M_MTLR(REG_ITMP3);
2381                         }
2382                         
2383 #if defined(USE_THREADS)
2384                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2385                                 /* we need to save the proper return value */
2386                                 switch (iptr->opc) {
2387                                 case ICMD_LRETURN:
2388                                         M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2389                                         /* fall through */
2390                                 case ICMD_IRETURN:
2391                                 case ICMD_ARETURN:
2392                                         M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2393                                         break;
2394                                 case ICMD_FRETURN:
2395                                         M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2396                                         break;
2397                                 case ICMD_DRETURN:
2398                                         M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2399                                         break;
2400                                 }
2401
2402                                 a = dseg_addaddress(cd, BUILTIN_monitorexit);
2403                                 M_ALD(REG_ITMP3, REG_PV, a);
2404                                 M_MTCTR(REG_ITMP3);
2405                                 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
2406                                 M_JSR;
2407
2408                                 /* and now restore the proper return value */
2409                                 switch (iptr->opc) {
2410                                 case ICMD_LRETURN:
2411                                         M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2412                                         /* fall through */
2413                                 case ICMD_IRETURN:
2414                                 case ICMD_ARETURN:
2415                                         M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2416                                         break;
2417                                 case ICMD_FRETURN:
2418                                         M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2419                                         break;
2420                                 case ICMD_DRETURN:
2421                                         M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2422                                         break;
2423                                 }
2424                         }
2425 #endif
2426
2427                         /* restore return address                                         */
2428
2429                         if (!m->isleafmethod) {
2430                                 M_ALD(REG_ITMP3, REG_SP, p * 4 + LA_LR_OFFSET);
2431                                 M_MTLR(REG_ITMP3);
2432                         }
2433
2434                         /* restore saved registers                                        */
2435
2436                         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2437                                 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2438                         }
2439                         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2440                                 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2441                         }
2442
2443                         /* deallocate stack                                               */
2444
2445                         if (parentargs_base)
2446                                 M_LDA(REG_SP, REG_SP, parentargs_base * 4);
2447
2448                         M_RET;
2449                         ALIGNCODENOP;
2450                         }
2451                         break;
2452
2453
2454                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2455                         {
2456                         s4 i, l, *s4ptr;
2457                         void **tptr;
2458
2459                         tptr = (void **) iptr->target;
2460
2461                         s4ptr = iptr->val.a;
2462                         l = s4ptr[1];                          /* low     */
2463                         i = s4ptr[2];                          /* high    */
2464                         
2465                         var_to_reg_int(s1, src, REG_ITMP1);
2466                         if (l == 0) {
2467                                 M_INTMOVE(s1, REG_ITMP1);
2468                         } else if (l <= 32768) {
2469                                 M_LDA(REG_ITMP1, s1, -l);
2470                         } else {
2471                                 ICONST(REG_ITMP2, l);
2472                                 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2473                         }
2474                         i = i - l + 1;
2475
2476                         /* range check */
2477
2478                         M_CMPUI(REG_ITMP1, i - 1);
2479                         M_BGT(0);
2480
2481                         /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2482                         codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2483
2484                         /* build jump table top down and use address of lowest entry */
2485
2486                         /* s4ptr += 3 + i; */
2487                         tptr += i;
2488
2489                         while (--i >= 0) {
2490                                 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2491                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
2492                                 --tptr;
2493                                 }
2494                         }
2495
2496                         /* length of dataseg after last dseg_addtarget is used by load */
2497
2498                         M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2499                         M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2500                         M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2501                         M_MTCTR(REG_ITMP2);
2502                         M_RTS;
2503                         ALIGNCODENOP;
2504                         break;
2505
2506
2507                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2508                         {
2509                         s4 i, l, val, *s4ptr;
2510                         void **tptr;
2511
2512                         tptr = (void **) iptr->target;
2513
2514                         s4ptr = iptr->val.a;
2515                         l = s4ptr[0];                          /* default  */
2516                         i = s4ptr[1];                          /* count    */
2517                         
2518                         MCODECHECK((i<<2)+8);
2519                         var_to_reg_int(s1, src, REG_ITMP1);
2520                         while (--i >= 0) {
2521                                 s4ptr += 2;
2522                                 ++tptr;
2523
2524                                 val = s4ptr[0];
2525                                 if ((val >= -32768) && (val <= 32767)) {
2526                                         M_CMPI(s1, val);
2527                                         } 
2528                                 else {
2529                                         a = dseg_adds4(cd, val);
2530                                         M_ILD(REG_ITMP2, REG_PV, a);
2531                                         M_CMP(s1, REG_ITMP2);
2532                                         }
2533                                 M_BEQ(0);
2534                                 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2535                                 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr); 
2536                                 }
2537
2538                         M_BR(0);
2539                         /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2540                         
2541                         tptr = (void **) iptr->target;
2542                         codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2543
2544                         ALIGNCODENOP;
2545                         break;
2546                         }
2547
2548
2549                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
2550                                         /* op1 = arg count val.a = builtintable entry */
2551
2552                         bte = iptr->val.a;
2553                         md = bte->md;
2554                         goto gen_method;
2555
2556                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2557                                         /* op1 = arg count, val.a = method pointer    */
2558
2559                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2560                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2561                 case ICMD_INVOKEINTERFACE:
2562
2563                         lm = iptr->val.a;
2564
2565                         if (lm)
2566                                 md = lm->parseddesc;
2567                         else {
2568                                 unresolved_method *um = iptr->target;
2569                                 md = um->methodref->parseddesc.md;
2570                         }
2571
2572 gen_method:
2573                         s3 = iptr->op1;
2574
2575                         MCODECHECK((s3 << 1) + 64);
2576
2577                         /* copy arguments to registers or stack location */
2578
2579                         for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2580                                 if (src->varkind == ARGVAR)
2581                                         continue;
2582                                 if (IS_INT_LNG_TYPE(src->type)) {
2583                                         if (!md->params[s3].inmemory) {
2584                                                 if (IS_2_WORD_TYPE(src->type))
2585                                                         s1 = PACK_REGS(
2586                                                    rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2587                                                    rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
2588                                                 else
2589                                                         s1 = rd->argintregs[md->params[s3].regoff];
2590                                                 var_to_reg_int(d, src, s1);
2591                                                 M_TINTMOVE(src->type, d, s1);
2592                                         } else {
2593                                                 var_to_reg_int(d, src, PACK_REGS(REG_ITMP3, REG_ITMP1));
2594                                                 M_IST(GET_HIGH_REG(d), REG_SP,
2595                                                           md->params[s3].regoff * 4);
2596                                                 if (IS_2_WORD_TYPE(src->type))
2597                                                         M_IST(GET_LOW_REG(d), 
2598                                                                   REG_SP, md->params[s3].regoff * 4 + 4);
2599                                         }
2600                                                 
2601                                 } else {
2602                                         if (!md->params[s3].inmemory) {
2603                                                 s1 = rd->argfltregs[md->params[s3].regoff];
2604                                                 var_to_reg_flt(d, src, s1);
2605                                                 M_FLTMOVE(d, s1);
2606                                         } else {
2607                                                 var_to_reg_flt(d, src, REG_FTMP1);
2608                                                 if (IS_2_WORD_TYPE(src->type))
2609                                                         M_DST(d, REG_SP, md->params[s3].regoff * 4);
2610                                                 else
2611                                                         M_FST(d, REG_SP, md->params[s3].regoff * 4);
2612                                         }
2613                                 }
2614                         } /* end of for */
2615
2616                         switch (iptr->opc) {
2617                         case ICMD_BUILTIN:
2618                                 if (iptr->target) {
2619                                         codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2620
2621                                         if (opt_showdisassemble)
2622                                                 M_NOP;
2623
2624                                         a = 0;
2625
2626                                 } else {
2627                                         a = (ptrint) bte->fp;
2628                                 }
2629
2630                                 a = dseg_addaddress(cd, a);
2631                                 d = md->returntype.type;
2632
2633                                 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2634                                 break;
2635
2636                         case ICMD_INVOKESPECIAL:
2637                                 gen_nullptr_check(rd->argintregs[0]);
2638                                 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr   */
2639                                 /* fall through */
2640
2641                         case ICMD_INVOKESTATIC:
2642                                 if (!lm) {
2643                                         unresolved_method *um = iptr->target;
2644
2645                                         codegen_addpatchref(cd, mcodeptr,
2646                                                                                 PATCHER_invokestatic_special, um);
2647
2648                                         if (opt_showdisassemble)
2649                                                 M_NOP;
2650
2651                                         a = 0;
2652                                         d = md->returntype.type;
2653
2654                                 } else {
2655                                         a = (ptrint) lm->stubroutine;
2656                                         d = md->returntype.type;
2657                                 }
2658
2659                                 a = dseg_addaddress(cd, a);
2660                                 M_ALD(REG_PV, REG_PV, a);       /* method pointer in r27 */
2661                                 break;
2662
2663                         case ICMD_INVOKEVIRTUAL:
2664                                 gen_nullptr_check(rd->argintregs[0]);
2665
2666                                 if (!lm) {
2667                                         unresolved_method *um = iptr->target;
2668
2669                                         codegen_addpatchref(cd, mcodeptr,
2670                                                                                 PATCHER_invokevirtual, um);
2671
2672                                         if (opt_showdisassemble)
2673                                                 M_NOP;
2674
2675                                         s1 = 0;
2676                                         d = md->returntype.type;
2677
2678                                 } else {
2679                                         s1 = OFFSET(vftbl_t, table[0]) +
2680                                                 sizeof(methodptr) * lm->vftblindex;
2681                                         d = md->returntype.type;
2682                                 }
2683
2684                                 M_ALD(REG_METHODPTR, rd->argintregs[0],
2685                                           OFFSET(java_objectheader, vftbl));
2686                                 M_ALD(REG_PV, REG_METHODPTR, s1);
2687                                 break;
2688
2689                         case ICMD_INVOKEINTERFACE:
2690                                 gen_nullptr_check(rd->argintregs[0]);
2691
2692                                 if (!lm) {
2693                                         unresolved_method *um = iptr->target;
2694
2695                                         codegen_addpatchref(cd, mcodeptr,
2696                                                                                 PATCHER_invokeinterface, um);
2697
2698                                         if (opt_showdisassemble)
2699                                                 M_NOP;
2700
2701                                         s1 = 0;
2702                                         s2 = 0;
2703                                         d = md->returntype.type;
2704
2705                                 } else {
2706                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
2707                                                 sizeof(methodptr*) * lm->class->index;
2708
2709                                         s2 = sizeof(methodptr) * (lm - lm->class->methods);
2710
2711                                         d = md->returntype.type;
2712                                 }
2713
2714                                 M_ALD(REG_METHODPTR, rd->argintregs[0],
2715                                           OFFSET(java_objectheader, vftbl));    
2716                                 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2717                                 M_ALD(REG_PV, REG_METHODPTR, s2);
2718                                 break;
2719                         }
2720
2721                         M_MTCTR(REG_PV);
2722                         M_JSR;
2723
2724                         /* recompute pv */
2725
2726                         s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2727                         M_MFLR(REG_ITMP1);
2728                         if (s1 <= 32768)
2729                                  M_LDA(REG_PV, REG_ITMP1, -s1);
2730                         else {
2731                                 s4 ml = -s1, mh = 0;
2732                                 while (ml < -32768) { ml += 65536; mh--; }
2733                                 M_LDA(REG_PV, REG_ITMP1, ml);
2734                                 M_LDAH(REG_PV, REG_PV, mh);
2735                         }
2736
2737                         /* d contains return type */
2738
2739                         if (d != TYPE_VOID) {
2740                                 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2741                                         if (IS_2_WORD_TYPE(iptr->dst->type)) {
2742                                                 s1 = reg_of_var(rd, iptr->dst,
2743                                                                                 PACK_REGS(REG_RESULT2, REG_RESULT));
2744                                                 M_TINTMOVE(iptr->dst->type,
2745                                                                    PACK_REGS(REG_RESULT2, REG_RESULT), s1);
2746                                         } else {
2747                                                 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2748                                                 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2749                                         }
2750                                         store_reg_to_var_int(iptr->dst, s1);
2751
2752                                 } else {
2753                                         s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2754                                         M_FLTMOVE(REG_FRESULT, s1);
2755                                         store_reg_to_var_flt(iptr->dst, s1);
2756                                 }
2757                         }
2758                         break;
2759
2760
2761                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2762                                       /* val.a: (classinfo*) superclass               */
2763
2764                         /*  superclass is an interface:
2765                          *
2766                          *  OK if ((sub == NULL) ||
2767                          *         (sub->vftbl->interfacetablelength > super->index) &&
2768                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
2769                          *
2770                          *  superclass is a class:
2771                          *
2772                          *  OK if ((sub == NULL) || (0
2773                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2774                          *         super->vftbl->diffvall));
2775                          */
2776
2777                         {
2778                         classinfo *super;
2779                         vftbl_t   *supervftbl;
2780                         s4         superindex;
2781
2782                         super = (classinfo *) iptr->val.a;
2783
2784                         if (!super) {
2785                                 superindex = 0;
2786                                 supervftbl = NULL;
2787
2788                         } else {
2789                                 superindex = super->index;
2790                                 supervftbl = super->vftbl;
2791                         }
2792                         
2793 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2794                         codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2795 #endif
2796                         var_to_reg_int(s1, src, REG_ITMP1);
2797
2798                         /* calculate interface checkcast code size */
2799
2800                         s2 = 7;
2801                         if (!super)
2802                                 s2 += (opt_showdisassemble ? 1 : 0);
2803
2804                         /* calculate class checkcast code size */
2805
2806                         s3 = 8 + (s1 == REG_ITMP1);
2807                         if (!super)
2808                                 s3 += (opt_showdisassemble ? 1 : 0);
2809
2810                         /* if class is not resolved, check which code to call */
2811
2812                         if (!super) {
2813                                 M_TST(s1);
2814                                 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
2815
2816                                 codegen_addpatchref(cd, mcodeptr,
2817                                                                         PATCHER_checkcast_instanceof_flags,
2818                                                                         (constant_classref *) iptr->target);
2819
2820                                 if (opt_showdisassemble)
2821                                         M_NOP;
2822
2823                                 a = dseg_adds4(cd, 0); /* super->flags */
2824                                 M_ILD(REG_ITMP2, REG_PV, a);
2825                                 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2826                                 M_BEQ(s2 + 1);
2827                         }
2828
2829                         /* interface checkcast code */
2830
2831                         if (!super || (super->flags & ACC_INTERFACE)) {
2832                                 if (super) {
2833                                         M_TST(s1);
2834                                         M_BEQ(s2);
2835
2836                                 } else {
2837                                         codegen_addpatchref(cd, mcodeptr,
2838                                                                                 PATCHER_checkcast_instanceof_interface,
2839                                                                                 (constant_classref *) iptr->target);
2840
2841                                         if (opt_showdisassemble)
2842                                                 M_NOP;
2843                                 }
2844
2845                                 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2846                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2847                                 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2848                                 M_BLE(0);
2849                                 codegen_addxcastrefs(cd, mcodeptr);
2850                                 M_ALD(REG_ITMP3, REG_ITMP2,
2851                                         OFFSET(vftbl_t, interfacetable[0]) -
2852                                         superindex * sizeof(methodptr*));
2853                                 M_TST(REG_ITMP3);
2854                                 M_BEQ(0);
2855                                 codegen_addxcastrefs(cd, mcodeptr);
2856
2857                                 if (!super)
2858                                         M_BR(s3);
2859                         }
2860
2861                         /* class checkcast code */
2862
2863                         if (!super || !(super->flags & ACC_INTERFACE)) {
2864                                 if (super) {
2865                                         M_TST(s1);
2866                                         M_BEQ(s3);
2867
2868                                 } else {
2869                                         codegen_addpatchref(cd, mcodeptr,
2870                                                                                 PATCHER_checkcast_class,
2871                                                                                 (constant_classref *) iptr->target);
2872
2873                                         if (opt_showdisassemble)
2874                                                 M_NOP;
2875                                 }
2876
2877                                 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2878 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2879                                 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2880 #endif
2881                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2882                                 a = dseg_addaddress(cd, supervftbl);
2883                                 M_ALD(REG_ITMP2, REG_PV, a);
2884                                 if (s1 != REG_ITMP1) {
2885                                         M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2886                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2887 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2888                                         codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2889 #endif
2890                                         M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2891                                 } else {
2892                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2893                                         M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2894                                         M_ALD(REG_ITMP2, REG_PV, a);
2895                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2896 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2897                                         codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2898 #endif
2899                                 }
2900                                 M_CMPU(REG_ITMP3, REG_ITMP2);
2901                                 M_BGT(0);
2902                                 codegen_addxcastrefs(cd, mcodeptr);
2903                         }
2904                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2905                         M_INTMOVE(s1, d);
2906                         store_reg_to_var_int(iptr->dst, d);
2907                         }
2908                         break;
2909
2910                 case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref        */
2911                                           /* op1: 1... resolved, 0... not resolved    */
2912
2913                         var_to_reg_int(s1, src, REG_ITMP1);
2914                         M_INTMOVE(s1, rd->argintregs[0]);
2915
2916                         bte = iptr->val.a;
2917
2918                         if (!iptr->op1) {
2919                                 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2920
2921                                 if (opt_showdisassemble)
2922                                         M_NOP;
2923
2924                                 a = 0;
2925
2926                         } else {
2927                                 a = (ptrint) bte->fp;
2928                         }
2929
2930                         disp = dseg_addaddress(cd, iptr->target);
2931                         M_ALD(rd->argintregs[1], REG_PV, disp);
2932                         disp = dseg_addaddress(cd, a);
2933                         M_ALD(REG_ITMP2, REG_PV, disp);
2934                         M_MTCTR(REG_ITMP2);
2935                         M_JSR;
2936                         M_TST(REG_RESULT);
2937                         M_BEQ(0);
2938                         codegen_addxcastrefs(cd, mcodeptr);
2939
2940                         var_to_reg_int(s1, src, REG_ITMP1);
2941                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2942                         M_INTMOVE(s1, d);
2943                         store_reg_to_var_int(iptr->dst, d);
2944                         break;
2945
2946
2947                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2948                                       /* val.a: (classinfo*) superclass               */
2949
2950                         /*  superclass is an interface:
2951                          *
2952                          *  return (sub != NULL) &&
2953                          *         (sub->vftbl->interfacetablelength > super->index) &&
2954                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
2955                          *
2956                          *  superclass is a class:
2957                          *
2958                          *  return ((sub != NULL) && (0
2959                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2960                          *          super->vftbl->diffvall));
2961                          */
2962
2963                         {
2964                         classinfo *super;
2965                         vftbl_t   *supervftbl;
2966                         s4         superindex;
2967
2968                         super = (classinfo *) iptr->val.a;
2969
2970                         if (!super) {
2971                                 superindex = 0;
2972                                 supervftbl = NULL;
2973
2974                         } else {
2975                                 superindex = super->index;
2976                                 supervftbl = super->vftbl;
2977                         }
2978                         
2979 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2980             codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2981 #endif
2982                         var_to_reg_int(s1, src, REG_ITMP1);
2983                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2984                         if (s1 == d) {
2985                                 M_MOV(s1, REG_ITMP1);
2986                                 s1 = REG_ITMP1;
2987                         }
2988
2989                         /* calculate interface instanceof code size */
2990
2991                         s2 = 9;
2992                         if (!super)
2993                                 s2 += (opt_showdisassemble ? 1 : 0);
2994
2995                         /* calculate class instanceof code size */
2996
2997                         s3 = 10;
2998                         if (!super)
2999                                 s3 += (opt_showdisassemble ? 1 : 0);
3000
3001                         M_CLR(d);
3002
3003                         /* if class is not resolved, check which code to call */
3004
3005                         if (!super) {
3006                                 M_TST(s1);
3007                                 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3008
3009                                 codegen_addpatchref(cd, mcodeptr,
3010                                                                         PATCHER_checkcast_instanceof_flags,
3011                                                                         (constant_classref *) iptr->target);
3012
3013                                 if (opt_showdisassemble)
3014                                         M_NOP;
3015
3016                                 a = dseg_adds4(cd, 0); /* super->flags */
3017                                 M_ILD(REG_ITMP2, REG_PV, a);
3018                                 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3019                                 M_BEQ(s2 + 1);
3020                         }
3021
3022                         /* interface instanceof code */
3023
3024                         if (!super || (super->flags & ACC_INTERFACE)) {
3025                                 if (super) {
3026                                         M_TST(s1);
3027                                         M_BEQ(9);
3028
3029                                 } else {
3030                                         codegen_addpatchref(cd, mcodeptr,
3031                                                                                 PATCHER_checkcast_instanceof_interface,
3032                                                                                 (constant_classref *) iptr->target);
3033
3034                                         if (opt_showdisassemble)
3035                                                 M_NOP;
3036                                 }
3037
3038                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3039                                 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3040                                 M_LDATST(REG_ITMP2, REG_ITMP2, -superindex);
3041                                 M_BLE(5);
3042                                 M_ALD(REG_ITMP1, REG_ITMP1,
3043                                         OFFSET(vftbl_t, interfacetable[0]) -
3044                                         superindex * sizeof(methodptr*));
3045                                 M_TST(REG_ITMP1);
3046                                 M_CLR(d);
3047                                 M_BEQ(1);
3048                                 M_IADD_IMM(REG_ZERO, 1, d);
3049
3050                                 if (!super)
3051                                         M_BR(s3);
3052                         }
3053
3054                         /* class instanceof code */
3055
3056                         if (!super || !(super->flags & ACC_INTERFACE)) {
3057                                 if (super) {
3058                                         M_TST(s1);
3059                                         M_BEQ(s3);
3060
3061                                 } else {
3062                                         codegen_addpatchref(cd, mcodeptr,
3063                                                                                 PATCHER_instanceof_class,
3064                                                                                 (constant_classref *) iptr->target);
3065
3066                                         if (opt_showdisassemble) {
3067                                                 M_NOP;
3068                                         }
3069                                 }
3070
3071                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3072                                 a = dseg_addaddress(cd, supervftbl);
3073                                 M_ALD(REG_ITMP2, REG_PV, a);
3074 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3075                                 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3076 #endif
3077                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3078                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3079                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3080 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3081                                 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3082 #endif
3083                                 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3084                                 M_CMPU(REG_ITMP1, REG_ITMP2);
3085                                 M_CLR(d);
3086                                 M_BGT(1);
3087                                 M_IADD_IMM(REG_ZERO, 1, d);
3088                         }
3089                         store_reg_to_var_int(iptr->dst, d);
3090                         }
3091                         break;
3092
3093                 case ICMD_CHECKASIZE:  /* ..., size ==> ..., size                     */
3094
3095                         var_to_reg_int(s1, src, REG_ITMP1);
3096                         M_CMPI(s1, 0);
3097                         M_BLT(0);
3098                         codegen_addxcheckarefs(cd, mcodeptr);
3099                         break;
3100
3101                 case ICMD_CHECKEXCEPTION:   /* ... ==> ...                            */
3102
3103                         M_CMPI(REG_RESULT, 0);
3104                         M_BEQ(0);
3105                         codegen_addxexceptionrefs(cd, mcodeptr);
3106                         break;
3107
3108                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
3109                                       /* op1 = dimension, val.a = array descriptor    */
3110
3111                         /* check for negative sizes and copy sizes to stack if necessary  */
3112
3113                         MCODECHECK((iptr->op1 << 1) + 64);
3114
3115                         for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3116                                 var_to_reg_int(s2, src, REG_ITMP1);
3117                                 M_CMPI(s2, 0);
3118                                 M_BLT(0);
3119                                 codegen_addxcheckarefs(cd, mcodeptr);
3120
3121                                 /* copy SAVEDVAR sizes to stack */
3122
3123                                 if (src->varkind != ARGVAR)
3124 #if defined(__DARWIN__)
3125                                         M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3126 #else
3127                                         M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3128 #endif
3129                         }
3130
3131                         /* is patcher function set? */
3132
3133                         if (iptr->target) {
3134                                 codegen_addpatchref(cd, mcodeptr,
3135                                                                         (functionptr) iptr->target, iptr->val.a);
3136
3137                                 if (opt_showdisassemble)
3138                                         M_NOP;
3139
3140                                 a = 0;
3141
3142                         } else {
3143                                 a = (ptrint) iptr->val.a;
3144                         }
3145
3146                         /* a0 = dimension count */
3147
3148                         ICONST(rd->argintregs[0], iptr->op1);
3149
3150                         /* a1 = arraydescriptor */
3151
3152                         a = dseg_addaddress(cd, iptr->val.a);
3153                         M_ALD(rd->argintregs[1], REG_PV, a);
3154
3155                         /* a2 = pointer to dimensions = stack pointer */
3156
3157 #if defined(__DARWIN__)
3158                         M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3159 #else
3160                         M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3161 #endif
3162
3163                         a = dseg_addaddress(cd, BUILTIN_multianewarray);
3164                         M_ALD(REG_PV, REG_PV, a);
3165                         M_MTCTR(REG_PV);
3166                         M_JSR;
3167                         s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3168                         M_MFLR(REG_ITMP1);
3169                         if (s1 <= 32768)
3170                                 M_LDA (REG_PV, REG_ITMP1, -s1);
3171                         else {
3172                                 s4 ml = -s1, mh = 0;
3173                                 while (ml < -32768) {ml += 65536; mh--;}
3174                                 M_LDA(REG_PV, REG_ITMP1, ml);
3175                                 M_LDAH(REG_PV, REG_PV, mh);
3176                     }
3177                         s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3178                         M_INTMOVE(REG_RESULT, s1);
3179                         store_reg_to_var_int(iptr->dst, s1);
3180                         break;
3181
3182
3183                 default:
3184                         throw_cacao_exception_exit(string_java_lang_InternalError,
3185                                                                            "Unknown ICMD %d", iptr->opc);
3186         } /* switch */
3187                 
3188         } /* for instruction */
3189                 
3190         /* copy values to interface registers */
3191
3192         src = bptr->outstack;
3193         len = bptr->outdepth;
3194         MCODECHECK(64 + len);
3195 #ifdef LSRA
3196         if (!opt_lsra)
3197 #endif
3198         while (src) {
3199                 len--;
3200                 if ((src->varkind != STACKVAR)) {
3201                         s2 = src->type;
3202                         if (IS_FLT_DBL_TYPE(s2)) {
3203                                 var_to_reg_flt(s1, src, REG_FTMP1);
3204                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3205                                         M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3206
3207                                 } else {
3208                                         M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3209                                 }
3210
3211                         } else {
3212                                 var_to_reg_int(s1, src, REG_ITMP1);
3213                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3214                                         M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3215
3216                                 } else {
3217                                         if (IS_2_WORD_TYPE(s2)) {
3218                                                 M_IST(GET_HIGH_REG(s1),
3219                             REG_SP, rd->interfaces[len][s2].regoff * 4);
3220                                                 M_IST(GET_LOW_REG(s1), REG_SP,
3221                                                     rd->interfaces[len][s2].regoff * 4 + 4);
3222                                         } else {
3223                                                 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3224                                         }
3225
3226                                 }
3227                         }
3228                 }
3229                 src = src->prev;
3230         }
3231         } /* if (bptr -> flags >= BBREACHED) */
3232         } /* for basic block */
3233
3234         codegen_createlinenumbertable(cd);
3235
3236         {
3237
3238         s4        *xcodeptr;
3239         branchref *bref;
3240
3241         /* generate ArithemticException check stubs */
3242
3243         xcodeptr = NULL;
3244
3245         for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3246                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3247                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3248                                                           bref->branchpos,
3249                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3250                         continue;
3251                 }
3252
3253                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3254                                   bref->branchpos,
3255                                                   (u1 *) mcodeptr - cd->mcodebase);
3256
3257                 MCODECHECK(20);
3258
3259                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3260
3261                 if (xcodeptr != NULL) {
3262                         disp = xcodeptr - mcodeptr - 1;
3263                         M_BR(disp);
3264
3265                 } else {
3266                         xcodeptr = mcodeptr;
3267
3268                         if (m->isleafmethod) {
3269                                 M_MFLR(REG_ITMP3);
3270                                 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3271                         }
3272
3273                         M_MOV(REG_PV, rd->argintregs[0]);
3274                         M_MOV(REG_SP, rd->argintregs[1]);
3275
3276                         if (m->isleafmethod)
3277                                 M_MOV(REG_ITMP3, rd->argintregs[2]);
3278                         else
3279                                 M_ALD(rd->argintregs[2],
3280                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3281
3282                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3283
3284                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3285                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3286
3287                         disp = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3288                         M_ALD(REG_ITMP1, REG_PV, disp);
3289                         M_MTCTR(REG_ITMP1);
3290                         M_JSR;
3291                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3292
3293                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3294                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3295
3296                         if (m->isleafmethod) {
3297                                 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3298                                 M_MTLR(REG_ITMP3);
3299                         }
3300
3301                         disp = dseg_addaddress(cd, asm_handle_exception);
3302                         M_ALD(REG_ITMP3, REG_PV, disp);
3303                         M_MTCTR(REG_ITMP3);
3304                         M_RTS;
3305                 }
3306         }
3307
3308         /* generate ArrayIndexOutOfBoundsException stubs */
3309
3310         xcodeptr = NULL;
3311
3312         for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3313                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3314                                   bref->branchpos,
3315                                                   (u1 *) mcodeptr - cd->mcodebase);
3316
3317                 MCODECHECK(21);
3318
3319                 /* move index register into REG_ITMP1 */
3320
3321                 M_MOV(bref->reg, REG_ITMP1);
3322
3323                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3324
3325                 if (xcodeptr != NULL) {
3326                         disp = xcodeptr - mcodeptr - 1;
3327                         M_BR(disp);
3328
3329                 } else {
3330                         xcodeptr = mcodeptr;
3331
3332                         if (m->isleafmethod) {
3333                                 M_MFLR(REG_ITMP3);
3334                                 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3335                         }
3336
3337                         M_MOV(REG_PV, rd->argintregs[0]);
3338                         M_MOV(REG_SP, rd->argintregs[1]);
3339
3340                         if (m->isleafmethod)
3341                                 M_MOV(REG_ITMP3, rd->argintregs[2]);
3342                         else
3343                                 M_ALD(rd->argintregs[2],
3344                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3345
3346                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3347                         M_MOV(REG_ITMP1, rd->argintregs[4]);
3348
3349                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 6 * 4));
3350                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3351
3352                         disp = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3353                         M_ALD(REG_ITMP1, REG_PV, disp);
3354                         M_MTCTR(REG_ITMP1);
3355                         M_JSR;
3356                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3357
3358                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3359                         M_IADD_IMM(REG_SP, LA_SIZE + 6 * 4, REG_SP);
3360
3361                         if (m->isleafmethod) {
3362                                 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3363                                 M_MTLR(REG_ITMP3);
3364                         }
3365
3366                         disp = dseg_addaddress(cd, asm_handle_exception);
3367                         M_ALD(REG_ITMP3, REG_PV, disp);
3368                         M_MTCTR(REG_ITMP3);
3369                         M_RTS;
3370                 }
3371         }
3372
3373         /* generate ArrayStoreException check stubs */
3374
3375         xcodeptr = NULL;
3376         
3377         for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3378                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3379                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3380                                                           bref->branchpos,
3381                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3382                         continue;
3383                 }
3384
3385                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3386                                   bref->branchpos,
3387                                                   (u1 *) mcodeptr - cd->mcodebase);
3388
3389                 MCODECHECK(15);
3390
3391                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3392
3393                 if (xcodeptr != NULL) {
3394                         disp = xcodeptr - mcodeptr - 1;
3395                         M_BR(disp);
3396
3397                 } else {
3398                         xcodeptr = mcodeptr;
3399
3400                         M_MOV(REG_PV, rd->argintregs[0]);
3401                         M_MOV(REG_SP, rd->argintregs[1]);
3402                         M_ALD(rd->argintregs[2],
3403                                   REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3404                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3405
3406                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3407                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3408
3409                         disp = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3410                         M_ALD(REG_ITMP1, REG_PV, disp);
3411                         M_MTCTR(REG_ITMP1);
3412                         M_JSR;
3413                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3414
3415                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3416                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3417
3418                         disp = dseg_addaddress(cd, asm_handle_exception);
3419                         M_ALD(REG_ITMP3, REG_PV, disp);
3420                         M_MTCTR(REG_ITMP3);
3421                         M_RTS;
3422                 }
3423         }
3424
3425         /* generate ClassCastException stubs */
3426
3427         xcodeptr = NULL;
3428         
3429         for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3430                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3431                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3432                                                           bref->branchpos,
3433                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3434                         continue;
3435                 }
3436
3437                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3438                                   bref->branchpos,
3439                                                   (u1 *) mcodeptr - cd->mcodebase);
3440
3441                 MCODECHECK(20);
3442
3443                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3444
3445                 if (xcodeptr != NULL) {
3446                         disp = xcodeptr - mcodeptr - 1;
3447                         M_BR(disp);
3448
3449                 } else {
3450                         xcodeptr = mcodeptr;
3451
3452                         if (m->isleafmethod) {
3453                                 M_MFLR(REG_ITMP3);
3454                                 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3455                         }
3456
3457                         M_MOV(REG_PV, rd->argintregs[0]);
3458                         M_MOV(REG_SP, rd->argintregs[1]);
3459
3460                         if (m->isleafmethod)
3461                                 M_MOV(REG_ITMP3, rd->argintregs[2]);
3462                         else
3463                                 M_ALD(rd->argintregs[2],
3464                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3465
3466                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3467
3468                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3469                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3470
3471                         disp = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3472                         M_ALD(REG_ITMP1, REG_PV, disp);
3473                         M_MTCTR(REG_ITMP1);
3474                         M_JSR;
3475                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3476
3477                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3478                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3479
3480                         if (m->isleafmethod) {
3481                                 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3482                                 M_MTLR(REG_ITMP3);
3483                         }
3484
3485                         disp = dseg_addaddress(cd, asm_handle_exception);
3486                         M_ALD(REG_ITMP3, REG_PV, disp);
3487                         M_MTCTR(REG_ITMP3);
3488                         M_RTS;
3489                 }
3490         }
3491
3492         /* generate NegativeArraySizeException stubs */
3493
3494         xcodeptr = NULL;
3495         
3496         for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3497                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3498                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3499                                                           bref->branchpos,
3500                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3501                         continue;
3502                 }
3503
3504                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3505                                   bref->branchpos,
3506                                                   (u1 *) mcodeptr - cd->mcodebase);
3507
3508                 MCODECHECK(16);
3509
3510                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3511
3512                 if (xcodeptr != NULL) {
3513                         disp = xcodeptr - mcodeptr - 1;
3514                         M_BR(disp);
3515
3516                 } else {
3517                         xcodeptr = mcodeptr;
3518
3519                         M_MOV(REG_PV, rd->argintregs[0]);
3520                         M_MOV(REG_SP, rd->argintregs[1]);
3521                         M_ALD(rd->argintregs[2],
3522                                   REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3523                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3524
3525                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3526                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3527
3528                         disp = dseg_addaddress(cd, stacktrace_inline_negativearraysizeexception);
3529                         M_ALD(REG_ITMP1, REG_PV, disp);
3530                         M_MTCTR(REG_ITMP1);
3531                         M_JSR;
3532                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3533
3534                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3535                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3536
3537                         disp = dseg_addaddress(cd, asm_handle_exception);
3538                         M_ALD(REG_ITMP3, REG_PV, disp);
3539                         M_MTCTR(REG_ITMP3);
3540                         M_RTS;
3541                 }
3542         }
3543
3544         /* generate NullPointerException stubs */
3545
3546         xcodeptr = NULL;
3547
3548         for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3549                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3550                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3551                                                           bref->branchpos,
3552                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3553                         continue;
3554                 }
3555
3556                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3557                                   bref->branchpos,
3558                                                   (u1 *) mcodeptr - cd->mcodebase);
3559
3560                 MCODECHECK(20);
3561
3562                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3563
3564                 if (xcodeptr != NULL) {
3565                         disp = xcodeptr - mcodeptr - 1;
3566                         M_BR(disp);
3567
3568                 } else {
3569                         xcodeptr = mcodeptr;
3570
3571                         if (m->isleafmethod) {
3572                                 M_MFLR(REG_ITMP3);
3573                                 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3574                         }
3575
3576                         M_MOV(REG_PV, rd->argintregs[0]);
3577                         M_MOV(REG_SP, rd->argintregs[1]);
3578
3579                         if (m->isleafmethod)
3580                                 M_MOV(REG_ITMP3, rd->argintregs[2]);
3581                         else
3582                                 M_ALD(rd->argintregs[2],
3583                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3584
3585                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3586
3587                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3588                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3589
3590                         disp = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3591                         M_ALD(REG_ITMP1, REG_PV, disp);
3592                         M_MTCTR(REG_ITMP1);
3593                         M_JSR;
3594                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3595
3596                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3597                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3598
3599                         if (m->isleafmethod) {
3600                                 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3601                                 M_MTLR(REG_ITMP3);
3602                         }
3603
3604                         disp = dseg_addaddress(cd, asm_handle_exception);
3605                         M_ALD(REG_ITMP3, REG_PV, disp);
3606                         M_MTCTR(REG_ITMP3);
3607                         M_RTS;
3608                 }
3609         }
3610
3611         /* generate ICMD_CHECKEXCEPTION stubs */
3612
3613         xcodeptr = NULL;
3614
3615         for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3616                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3617                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3618                                                           bref->branchpos,
3619                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3620                         continue;
3621                 }
3622
3623                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3624                                   bref->branchpos,
3625                                                   (u1 *) mcodeptr - cd->mcodebase);
3626
3627                 MCODECHECK(16);
3628
3629                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3630
3631                 if (xcodeptr != NULL) {
3632                         disp = xcodeptr - mcodeptr - 1;
3633                         M_BR(disp);
3634
3635                 } else {
3636                         xcodeptr = mcodeptr;
3637
3638                         M_MOV(REG_PV, rd->argintregs[0]);
3639                         M_MOV(REG_SP, rd->argintregs[1]);
3640                         M_ALD(rd->argintregs[2],
3641                                   REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3642                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3643
3644                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3645                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3646
3647                         disp = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3648                         M_ALD(REG_ITMP1, REG_PV, disp);
3649                         M_MTCTR(REG_ITMP1);
3650                         M_JSR;
3651                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3652
3653                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3654                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3655
3656                         disp = dseg_addaddress(cd, asm_handle_exception);
3657                         M_ALD(REG_ITMP3, REG_PV, disp);
3658                         M_MTCTR(REG_ITMP3);
3659                         M_RTS;
3660                 }
3661         }
3662
3663         /* generate patcher stub call code */
3664
3665         {
3666                 patchref *pref;
3667                 u4        mcode;
3668                 s4       *tmpmcodeptr;
3669
3670                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3671                         /* check code segment size */
3672
3673                         MCODECHECK(16);
3674
3675                         /* Get machine code which is patched back in later. The call is   */
3676                         /* 1 instruction word long.                                       */
3677
3678                         xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3679                         mcode = *xcodeptr;
3680
3681                         /* patch in the call to call the following code (done at compile  */
3682                         /* time)                                                          */
3683
3684                         tmpmcodeptr = mcodeptr;         /* save current mcodeptr          */
3685                         mcodeptr = xcodeptr;            /* set mcodeptr to patch position */
3686
3687                         M_BL(tmpmcodeptr - (xcodeptr + 1));
3688
3689                         mcodeptr = tmpmcodeptr;         /* restore the current mcodeptr   */
3690
3691                         /* create stack frame - keep stack 16-byte aligned */
3692
3693                         M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3694
3695                         /* move return address onto stack */
3696
3697                         M_MFLR(REG_ITMP3);
3698                         M_AST(REG_ITMP3, REG_SP, 4 * 4);
3699
3700                         /* move pointer to java_objectheader onto stack */
3701
3702 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3703                         /* order reversed because of data segment layout */
3704
3705                         (void) dseg_addaddress(cd, get_dummyLR());          /* monitorPtr */
3706                         disp = dseg_addaddress(cd, NULL);                   /* vftbl      */
3707
3708                         if (disp >= -32768) {
3709                                 M_LDA(REG_ITMP3, REG_PV, disp);
3710                         } else {
3711                                 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3712                                 M_LDA(REG_ITMP3, REG_ITMP3, disp);
3713                         }
3714                         M_AST(REG_ITMP3, REG_SP, 3 * 4);
3715 #else
3716                         M_CLR(REG_ITMP3);
3717                         M_AST(REG_ITMP3, REG_SP, 3 * 4);
3718 #endif
3719
3720                         /* move machine code onto stack */
3721
3722                         disp = dseg_adds4(cd, mcode);
3723                         if (disp >= -32768) {
3724                                 M_ILD(REG_ITMP3, REG_PV, disp);
3725                         } else {
3726                                 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3727                                 M_ILD(REG_ITMP3, REG_ITMP3, disp);
3728                         }
3729                         M_IST(REG_ITMP3, REG_SP, 2 * 4);
3730
3731                         /* move class/method/field reference onto stack */
3732
3733                         disp = dseg_addaddress(cd, pref->ref);
3734                         if (disp >= -32768) {
3735                                 M_ALD(REG_ITMP3, REG_PV, disp);
3736                         } else {
3737                                 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3738                                 M_ALD(REG_ITMP3, REG_ITMP3, disp);
3739                         }
3740                         M_AST(REG_ITMP3, REG_SP, 1 * 4);
3741
3742                         /* move patcher function pointer onto stack */
3743
3744                         disp = dseg_addaddress(cd, pref->patcher);
3745                         if (disp >= -32768) {
3746                                 M_ALD(REG_ITMP3, REG_PV, disp);
3747                         } else {
3748                                 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3749                                 M_ALD(REG_ITMP3, REG_ITMP3, disp);
3750                         }
3751                         M_AST(REG_ITMP3, REG_SP, 0 * 4);
3752
3753                         disp = dseg_addaddress(cd, asm_wrapper_patcher);
3754                         if (disp >= -32768) {
3755                                 M_ALD(REG_ITMP3, REG_PV, disp);
3756                         } else {
3757                                 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3758                                 M_ALD(REG_ITMP3, REG_ITMP3, disp);
3759                         }
3760                         M_MTCTR(REG_ITMP3);
3761                         M_RTS;
3762                 }
3763         }
3764
3765         }
3766
3767         codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3768
3769         asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3770 }
3771
3772
3773 /* createcompilerstub **********************************************************
3774
3775    Creates a stub routine which calls the compiler.
3776         
3777 *******************************************************************************/
3778
3779 #define COMPSTUBSIZE 6
3780
3781 functionptr createcompilerstub(methodinfo *m)
3782 {
3783         s4 *s = CNEW(s4, COMPSTUBSIZE);     /* memory to hold the stub            */
3784         s4 *mcodeptr = s;                   /* code generation pointer            */
3785
3786         M_LDA(REG_ITMP1, REG_PV, 4*4);
3787         M_ALD(REG_PV, REG_PV, 5*4);
3788         M_MTCTR(REG_PV);
3789         M_RTS;
3790
3791         s[4] = (s4) m;                      /* literals to be adressed            */
3792         s[5] = (s4) asm_call_jit_compiler;  /* jump directly via PV from above    */
3793
3794         asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
3795
3796 #if defined(STATISTICS)
3797         if (opt_stat)
3798                 count_cstub_len += COMPSTUBSIZE * 4;
3799 #endif
3800
3801         return (functionptr) (ptrint) s;
3802 }
3803
3804
3805 /* createnativestub ************************************************************
3806
3807    Creates a stub routine which calls a native method.
3808
3809 *******************************************************************************/
3810
3811 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
3812                                                          registerdata *rd, methoddesc *nmd)
3813 {
3814         s4         *mcodeptr;               /* code generation pointer            */
3815         s4          stackframesize;         /* size of stackframe if needed       */
3816         s4          disp;
3817         methoddesc *md;
3818         s4          nativeparams;
3819         s4          i, j;                   /* count variables                    */
3820         s4          t;
3821         s4          s1, s2, off;
3822
3823         /* set some variables */
3824
3825         md = m->parseddesc;
3826         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3827
3828         /* calculate stackframe size */
3829
3830         stackframesize =
3831                 sizeof(stackframeinfo) / SIZEOF_VOID_P + /* native stackinfo          */
3832                 4 +                             /* 4 stackframeinfo arguments (darwin)*/
3833                 nmd->paramcount * 2 +           /* assume all arguments are doubles   */
3834                 nmd->memuse;
3835
3836         stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3837
3838
3839         /* create method header */
3840
3841         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
3842         (void) dseg_adds4(cd, stackframesize * 4);              /* FrameSize      */
3843         (void) dseg_adds4(cd, 0);                               /* IsSync         */
3844         (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
3845         (void) dseg_adds4(cd, 0);                               /* IntSave        */
3846         (void) dseg_adds4(cd, 0);                               /* FltSave        */
3847         (void) dseg_addlinenumbertablesize(cd);
3848         (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
3849
3850
3851         /* initialize mcode variables */
3852         
3853         mcodeptr = (s4 *) cd->mcodebase;
3854         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
3855
3856
3857         /* generate code */
3858
3859         M_MFLR(REG_ITMP1);
3860         M_AST(REG_ITMP1, REG_SP, LA_LR_OFFSET);
3861         M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
3862
3863
3864         /* if function is static, check for initialized */
3865
3866         if ((m->flags & ACC_STATIC) && !m->class->initialized) {
3867                 codegen_addpatchref(cd, mcodeptr, PATCHER_clinit, m->class);
3868
3869                 if (opt_showdisassemble)
3870                         M_NOP;
3871         }
3872
3873         if (runverbose) {
3874                 /* parent_argbase == stackframesize * 4 */
3875                 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, stackframesize * 4 , 
3876                                                                           true);
3877         }
3878
3879
3880         /* save integer and float argument registers */
3881
3882         for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3883                 t = md->paramtypes[i].type;
3884
3885                 if (IS_INT_LNG_TYPE(t)) {
3886                         s1 = md->params[i].regoff;
3887                         if (IS_2_WORD_TYPE(t)) {
3888                                 M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3889                                 M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3890                         } else {
3891                                 M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3892                         }
3893                 }
3894         }
3895
3896         for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3897                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3898                         s1 = md->params[i].regoff;
3899                         M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 8);
3900                 }
3901         }
3902
3903         /* create native stack info */
3904
3905         M_AADD_IMM(REG_SP, stackframesize * 4 - sizeof(stackframeinfo),
3906                            rd->argintregs[0]);
3907         M_MOV(REG_PV, rd->argintregs[1]);
3908         M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[2]);
3909         M_ALD(rd->argintregs[3], REG_SP, stackframesize * 4 + LA_LR_OFFSET);
3910         off = dseg_addaddress(cd, stacktrace_create_native_stackframeinfo);
3911         M_ALD(REG_ITMP1, REG_PV, off);
3912         M_MTCTR(REG_ITMP1);
3913         M_JSR;
3914
3915         /* restore integer and float argument registers */
3916
3917         for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3918                 t = md->paramtypes[i].type;
3919
3920                 if (IS_INT_LNG_TYPE(t)) {
3921                         s1 = md->params[i].regoff;
3922
3923                         if (IS_2_WORD_TYPE(t)) {
3924                                 M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3925                                 M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3926                         } else {
3927                                 M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3928                         }
3929                 }
3930         }
3931
3932         for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3933                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3934                         s1 = md->params[i].regoff;
3935                         M_DLD(rd->argfltregs[i], REG_SP, LA_SIZE + 4 * 4 + j++ * 8);
3936                 }
3937         }
3938
3939         
3940         /* copy or spill arguments to new locations */
3941
3942         for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3943                 t = md->paramtypes[i].type;
3944
3945                 if (IS_INT_LNG_TYPE(t)) {
3946                         if (!md->params[i].inmemory) {
3947                                 if (IS_2_WORD_TYPE(t))
3948                                         s1 = PACK_REGS(
3949                                                 rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
3950                                             rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
3951                                 else
3952                                         s1 = rd->argintregs[md->params[i].regoff];
3953
3954                                 if (!nmd->params[j].inmemory) {
3955                                         if (IS_2_WORD_TYPE(t))
3956                                                 s2 = PACK_REGS(
3957                                                    rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
3958                                                    rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
3959                                         else
3960                                                 s2 = rd->argintregs[nmd->params[j].regoff];
3961                                         M_TINTMOVE(t, s1, s2);
3962
3963                                 } else {
3964                                         s2 = nmd->params[j].regoff;
3965                                         if (IS_2_WORD_TYPE(t)) {
3966                                                 M_IST(GET_HIGH_REG(s1), REG_SP, s2 * 4);
3967                                                 M_IST(GET_LOW_REG(s1), REG_SP, s2 * 4 + 4);
3968                                         } else {
3969                                                 M_IST(s1, REG_SP, s2 * 4);
3970                                         }
3971                                 }
3972
3973                         } else {
3974                                 s1 = md->params[i].regoff + stackframesize;
3975                                 s2 = nmd->params[j].regoff;
3976
3977                                 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3978                                 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3979                                 if (IS_2_WORD_TYPE(t)) {
3980                                         M_ILD(REG_ITMP1, REG_SP, s1 * 4 + 4);
3981                                         M_IST(REG_ITMP1, REG_SP, s2 * 4 + 4);
3982                                 }
3983                         }
3984
3985                 } else {
3986                         /* We only copy spilled float arguments, as the float argument    */
3987                         /* registers keep unchanged.                                      */
3988
3989                         if (md->params[i].inmemory) {
3990                                 s1 = md->params[i].regoff + stackframesize;
3991                                 s2 = nmd->params[j].regoff;
3992
3993                                 if (IS_2_WORD_TYPE(t)) {
3994                                         M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3995                                         M_DST(REG_FTMP1, REG_SP, s2 * 4);
3996
3997                                 } else {
3998                                         M_FLD(REG_FTMP1, REG_SP, s1 * 4);
3999                                         M_FST(REG_FTMP1, REG_SP, s2 * 4);
4000                                 }
4001                         }
4002                 }
4003         }
4004
4005         /* put class into second argument register */
4006
4007         if (m->flags & ACC_STATIC) {
4008                 off = dseg_addaddress(cd, m->class);
4009                 M_ALD(rd->argintregs[1], REG_PV, off);
4010         }
4011
4012         /* put env into first argument register */
4013
4014         off = dseg_addaddress(cd, &env);
4015         M_ALD(rd->argintregs[0], REG_PV, off);
4016
4017         /* generate the actual native call */
4018
4019 #if !defined(ENABLE_STATICVM)
4020         if (f == NULL) {
4021                 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m);
4022
4023                 if (opt_showdisassemble)
4024                         M_NOP;
4025         }
4026 #endif
4027
4028         off = dseg_addaddress(cd, f);
4029         M_ALD(REG_PV, REG_PV, off);
4030         M_MTCTR(REG_PV);
4031         M_JSR;
4032         disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4033         M_MFLR(REG_ITMP1);
4034         M_LDA(REG_PV, REG_ITMP1, -disp);                  /* recompute pv from ra */
4035
4036
4037         /* remove native stackframe info */
4038
4039         switch (md->returntype.type) {
4040         case TYPE_LNG:
4041                 M_IST(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4042                 /* fall through */
4043         case TYPE_INT:
4044         case TYPE_ADR:
4045                 M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4046                 break;
4047         case TYPE_FLT:
4048                 M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4049                 break;
4050         case TYPE_DBL:
4051                 M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4052                 break;
4053         }
4054
4055         M_AADD_IMM(REG_SP, stackframesize * 4 - sizeof(stackframeinfo),
4056                            rd->argintregs[0]);
4057         off = dseg_addaddress(cd, stacktrace_remove_stackframeinfo);
4058         M_ALD(REG_ITMP1, REG_PV, off);
4059         M_MTCTR(REG_ITMP1);
4060         M_JSR;
4061
4062         switch (md->returntype.type) {
4063         case TYPE_LNG:
4064                 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4065                 /* fall through */
4066         case TYPE_INT:
4067         case TYPE_ADR:
4068                 M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4069                 break;
4070         case TYPE_FLT:
4071                 M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4072                 break;
4073         case TYPE_DBL:
4074                 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4075                 break;
4076         }
4077
4078
4079         /* print call trace */
4080
4081         if (runverbose) {
4082                 M_LDA(REG_SP, REG_SP, -(LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4));
4083                 M_IST(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
4084                 M_IST(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
4085                 M_DST(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
4086
4087                 /* keep this order */
4088                 switch (md->returntype.type) {
4089                 case TYPE_INT:
4090                 case TYPE_ADR:
4091 #if defined(__DARWIN__)
4092                         M_MOV(REG_RESULT, rd->argintregs[2]);
4093                         M_CLR(rd->argintregs[1]);
4094 #else
4095                         M_MOV(REG_RESULT, rd->argintregs[3]);
4096                         M_CLR(rd->argintregs[2]);
4097 #endif
4098                         break;
4099
4100                 case TYPE_LNG:
4101 #if defined(__DARWIN__)
4102                         M_MOV(REG_RESULT2, rd->argintregs[2]);
4103                         M_MOV(REG_RESULT, rd->argintregs[1]);
4104 #else
4105                         M_MOV(REG_RESULT2, rd->argintregs[3]);
4106                         M_MOV(REG_RESULT, rd->argintregs[2]);
4107 #endif
4108                         break;
4109                 }
4110
4111                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4112                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4113                 off = dseg_addaddress(cd, m);
4114                 M_ALD(rd->argintregs[0], REG_PV, off);
4115
4116                 off = dseg_addaddress(cd, builtin_displaymethodstop);
4117                 M_ALD(REG_ITMP2, REG_PV, off);
4118                 M_MTCTR(REG_ITMP2);
4119                 M_JSR;
4120
4121                 M_ILD(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
4122                 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
4123                 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
4124                 M_LDA(REG_SP, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4);
4125         }
4126
4127         /* check for exception */
4128
4129 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4130         switch (md->returntype.type) {
4131         case TYPE_LNG:
4132                 M_IST(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
4133                 /* fall through */
4134         case TYPE_INT:
4135         case TYPE_ADR:
4136                 M_IST(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
4137                 break;
4138         case TYPE_FLT:
4139                 M_FST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4140                 break;
4141         case TYPE_DBL:
4142                 M_DST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4143                 break;
4144         }
4145
4146         off = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4147         M_ALD(REG_ITMP1, REG_PV, off);
4148         M_MTCTR(REG_ITMP1);
4149         M_JSR;
4150         M_MOV(REG_RESULT, REG_ITMP2);
4151
4152         switch (md->returntype.type) {
4153         case TYPE_LNG:
4154                 M_ILD(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
4155                 /* fall through */
4156         case TYPE_INT:
4157         case TYPE_ADR:
4158                 M_ILD(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
4159                 break;
4160         case TYPE_FLT:
4161                 M_FLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4162                 break;
4163         case TYPE_DBL:
4164                 M_DLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4165                 break;
4166         }
4167 #else
4168         off = dseg_addaddress(cd, &_exceptionptr)
4169         M_ALD(REG_ITMP2, REG_PV, off);
4170 #endif
4171         M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1     */
4172         M_TST(REG_ITMP1_XPTR);
4173         M_BNE(4);                           /* if no exception then return        */
4174
4175         M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra   */
4176         M_MTLR(REG_ITMP1);
4177         M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe           */
4178
4179         M_RET;
4180
4181         /* handle exception */
4182
4183         M_CLR(REG_ITMP3);
4184         M_AST(REG_ITMP3, REG_ITMP2, 0);     /* store NULL into exceptionptr       */
4185
4186         M_ALD(REG_ITMP2, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra   */
4187         M_MTLR(REG_ITMP2);
4188
4189         M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe           */
4190
4191         M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address                */
4192
4193         off = dseg_addaddress(cd, asm_handle_nat_exception);
4194         M_ALD(REG_ITMP3, REG_PV, off);
4195         M_MTCTR(REG_ITMP3);
4196         M_RTS;
4197
4198         /* generate patcher stub call code */
4199
4200         {
4201                 patchref *pref;
4202                 s4       *xcodeptr;
4203                 s4        mcode;
4204                 s4       *tmpmcodeptr;
4205
4206                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4207                         /* Get machine code which is patched back in later. The call is   */
4208                         /* 1 instruction word long.                                       */
4209
4210                         xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4211                         mcode = (u4) *xcodeptr;
4212
4213                         /* patch in the call to call the following code (done at compile  */
4214                         /* time)                                                          */
4215
4216                         tmpmcodeptr = mcodeptr;         /* save current mcodeptr          */
4217                         mcodeptr = xcodeptr;            /* set mcodeptr to patch position */
4218
4219                         M_BL(tmpmcodeptr - (xcodeptr + 1));
4220
4221                         mcodeptr = tmpmcodeptr;         /* restore the current mcodeptr   */
4222
4223                         /* create stack frame - keep stack 16-byte aligned                */
4224
4225                         M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
4226
4227                         /* move return address onto stack */
4228
4229                         M_MFLR(REG_ITMP3);
4230                         M_AST(REG_ITMP3, REG_SP, 4 * 4);
4231
4232                         /* move pointer to java_objectheader onto stack */
4233
4234 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4235                         /* order reversed because of data segment layout */
4236
4237                         (void) dseg_addaddress(cd, get_dummyLR());          /* monitorPtr */
4238                         off = dseg_addaddress(cd, NULL);                    /* vftbl      */
4239
4240                         M_LDA(REG_ITMP3, REG_PV, off);
4241                         M_AST(REG_ITMP3, REG_SP, 3 * 4);
4242 #else
4243                         M_CLR(REG_ITMP3);
4244                         M_AST(REG_ITMP3, REG_SP, 3 * 4);
4245 #endif
4246
4247                         /* move machine code onto stack */
4248
4249                         off = dseg_adds4(cd, mcode);
4250                         M_ILD(REG_ITMP3, REG_PV, off);
4251                         M_IST(REG_ITMP3, REG_SP, 2 * 4);
4252
4253                         /* move class/method/field reference onto stack */
4254
4255                         off = dseg_addaddress(cd, pref->ref);
4256                         M_ALD(REG_ITMP3, REG_PV, off);
4257                         M_AST(REG_ITMP3, REG_SP, 1 * 4);
4258
4259                         /* move patcher function pointer onto stack */
4260
4261                         off = dseg_addaddress(cd, pref->patcher);
4262                         M_ALD(REG_ITMP3, REG_PV, off);
4263                         M_AST(REG_ITMP3, REG_SP, 0 * 4);
4264
4265                         off = dseg_addaddress(cd, asm_wrapper_patcher);
4266                         M_ALD(REG_ITMP3, REG_PV, off);
4267                         M_MTCTR(REG_ITMP3);
4268                         M_RTS;
4269                 }
4270         }
4271
4272         codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4273
4274         asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4275
4276         return m->entrypoint;
4277 }
4278
4279
4280 s4 *codegen_trace_args(methodinfo *m, codegendata *cd, registerdata *rd,
4281                                            s4 *mcodeptr, s4 parentargs_base, bool nativestub)
4282 {
4283         s4 s1, p, t, d;
4284         int stack_off;
4285         int stack_size;
4286         methoddesc *md;
4287
4288         md = m->parseddesc;
4289         
4290         if (!nativestub)
4291                 M_MFLR(REG_ITMP3);
4292         /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
4293         /* For Darwin:                                                        */
4294         /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR                      */
4295         /* LA_SIZE(=6*4) + 8*8         + 4          + 4  + 0(Padding)         */
4296         /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16                            */
4297         /* For Linux:                                                         */
4298         /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo         */
4299         /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
4300         /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8                          */
4301         /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16                */
4302         
4303         /* in nativestubs no Place to save the LR (Link Register) would be needed */
4304         /* but since the stack frame has to be aligned the 4 Bytes would have to  */
4305         /* be padded again */
4306
4307 #if defined(__DARWIN__)
4308         stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
4309 #else
4310         stack_size = 6 * 16;
4311 #endif
4312         M_LDA(REG_SP, REG_SP, -stack_size);
4313
4314         /* Save LR */
4315         if (!nativestub)
4316                 M_IST(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4317
4318         M_CLR(REG_ITMP1);    /* clear help register */
4319
4320         /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
4321 #if defined(__DARWIN__)
4322         /* Copy Params starting from first to Stack                          */
4323         /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs    */ 
4324         /* are saved                                                         */
4325         p = 0;
4326 #else
4327         /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in   */
4328         /* integer argument regs                                             */
4329         /* all integer argument registers have to be saved                   */
4330         for (p = 0; p < 8; p++) {
4331                 d = rd->argintregs[p];
4332                 /* save integer argument registers */
4333                 M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4334         }
4335         p = 4;
4336 #endif
4337         stack_off = LA_SIZE;
4338         for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
4339                 t = md->paramtypes[p].type;
4340                 if (IS_INT_LNG_TYPE(t)) {
4341                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
4342                                 if (IS_2_WORD_TYPE(t)) {
4343                                         M_IST(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4344                                                   , REG_SP, stack_off);
4345                                         M_IST(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4346                                                   , REG_SP, stack_off + 4);
4347                                 } else {
4348                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4349                                         M_IST(rd->argintregs[md->params[p].regoff]
4350                                                   , REG_SP, stack_off + 4);
4351                                 }
4352                         } else { /* Param on Stack */
4353                                 s1 = (md->params[p].regoff + parentargs_base) * 4 
4354                                         + stack_size;
4355                                 if (IS_2_WORD_TYPE(t)) {
4356                                         M_ILD(REG_ITMP2, REG_SP, s1);
4357                                         M_IST(REG_ITMP2, REG_SP, stack_off);
4358                                         M_ILD(REG_ITMP2, REG_SP, s1 + 4);
4359                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4360                                 } else {
4361                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4362                                         M_ILD(REG_ITMP2, REG_SP, s1);
4363                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4364                                 }
4365                         }
4366                 } else { /* IS_FLT_DBL_TYPE(t) */
4367                         if (!md->params[p].inmemory) { /* in Arg Reg */
4368                                 s1 = rd->argfltregs[md->params[p].regoff];
4369                                 if (!IS_2_WORD_TYPE(t)) {
4370                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4371                                         M_FST(s1, REG_SP, stack_off + 4);
4372                                 } else {
4373                                         M_DST(s1, REG_SP, stack_off);
4374                                 }
4375                         } else { /* on Stack */
4376                                 /* this should not happen */
4377                         }
4378                 }
4379         }
4380
4381         /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
4382 #if defined(__DARWIN__)
4383         for (p = 0; p < 8; p++) {
4384                 d = rd->argintregs[p];
4385                 M_ILD(d, REG_SP, LA_SIZE + p * 4);
4386         }
4387 #else
4388         /* LINUX */
4389         /* Set integer and float argument registers vor trace_args call */
4390         /* offset to saved integer argument registers                   */
4391         stack_off = LA_SIZE + 4 * 8 + 4;
4392         for (p = 0; (p < 4) && (p < md->paramcount); p++) {
4393                 t = md->paramtypes[p].type;
4394                 if (IS_INT_LNG_TYPE(t)) {
4395                         /* "stretch" int types */
4396                         if (!IS_2_WORD_TYPE(t)) {
4397                                 M_CLR(rd->argintregs[2 * p]);
4398                                 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off);
4399                                 stack_off += 4;
4400                         } else {
4401                                 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off + 4);
4402                                 M_ILD(rd->argintregs[2 * p], REG_SP,stack_off);
4403                                 stack_off += 8;
4404                         }
4405                 } else { /* Float/Dbl */
4406                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
4407                                 /* use reserved Place on Stack (sp + 5 * 16) to copy  */
4408                                 /* float/double arg reg to int reg                    */
4409                                 s1 = rd->argfltregs[md->params[p].regoff];
4410                                 if (!IS_2_WORD_TYPE(t)) {
4411                                         M_FST(s1, REG_SP, 5 * 16);
4412                                         M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16);
4413                                         M_CLR(rd->argintregs[2 * p]);
4414                                 } else {
4415                                         M_DST(s1, REG_SP, 5 * 16);
4416                                         M_ILD(rd->argintregs[2 * p + 1], REG_SP,  5 * 16 + 4);
4417                                         M_ILD(rd->argintregs[2 * p], REG_SP, 5 * 16);
4418                                 }
4419                         }
4420                 }
4421         }
4422 #endif
4423
4424         /* put methodinfo pointer on Stackframe */
4425         p = dseg_addaddress(cd, m);
4426         M_ALD(REG_ITMP1, REG_PV, p);
4427 #if defined(__DARWIN__)
4428         M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8); 
4429 #else
4430         M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
4431 #endif
4432         p = dseg_addaddress(cd, (void *) builtin_trace_args);
4433         M_ALD(REG_ITMP2, REG_PV, p);
4434         M_MTCTR(REG_ITMP2);
4435         M_JSR;
4436
4437 #if defined(__DARWIN__)
4438         /* restore integer argument registers from the reserved stack space */
4439
4440         stack_off = LA_SIZE;
4441         for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; 
4442                  p++, stack_off += 8) {
4443                 t = md->paramtypes[p].type;
4444
4445                 if (IS_INT_LNG_TYPE(t)) {
4446                         if (!md->params[p].inmemory) {
4447                                 if (IS_2_WORD_TYPE(t)) {
4448                                         M_ILD(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4449                                                   , REG_SP, stack_off);
4450                                         M_ILD(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4451                                                   , REG_SP, stack_off + 4);
4452                                 } else {
4453                                         M_ILD(rd->argintregs[md->params[p].regoff]
4454                                                   , REG_SP, stack_off + 4);
4455                                 }
4456                         }
4457                 }
4458         }
4459 #else
4460         /* LINUX */
4461         for (p = 0; p < 8; p++) {
4462                 d = rd->argintregs[p];
4463                 /* save integer argument registers */
4464                 M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4465         }
4466 #endif
4467
4468         if (!nativestub)
4469                 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4470
4471         M_LDA(REG_SP, REG_SP, stack_size);
4472         if (!nativestub)
4473                 M_MTLR(REG_ITMP3);
4474         return mcodeptr;
4475 }
4476
4477 /*
4478  * These are local overrides for various environment variables in Emacs.
4479  * Please do not remove this and leave it at the end of the file, where
4480  * Emacs will automagically detect them.
4481  * ---------------------------------------------------------------------
4482  * Local variables:
4483  * mode: c
4484  * indent-tabs-mode: t
4485  * c-basic-offset: 4
4486  * tab-width: 4
4487  * End:
4488  */