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