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