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