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