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