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