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