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