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