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