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