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