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