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