* src/vm/jit/m68k/codegen.c (ICMD_CALOAD): Fixed.
[cacao.git] / src / vm / jit / m68k / codegen.c
1 /* src/vm/jit/m68k/codegen.c
2
3    Copyright (C) 1996-2005, 2006, 2007 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    $Id: codegen.c 7564 2007-03-23 23:36:17Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "md-abi.h"
35
36 #include "vm/types.h"
37 #include "vm/jit/m68k/codegen.h"
38 #include "vm/jit/m68k/emit.h"
39
40 #include "mm/memory.h"
41 #include "native/jni.h"
42 #include "native/native.h"
43
44 #include "threads/lock-common.h"
45
46 #include "vm/builtin.h"
47 #include "vm/exceptions.h"
48 #include "vm/global.h"
49 #include "vm/stringlocal.h"
50 #include "vm/vm.h"
51
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/codegen-common.h"
54 #include "vm/jit/dseg.h"
55 #include "vm/jit/emit-common.h"
56 #include "vm/jit/jit.h"
57 #include "vm/jit/parse.h"
58 #include "vm/jit/patcher.h"
59 #include "vm/jit/reg.h"
60 #include "vm/jit/replace.h"
61 #include "vm/jit/stacktrace.h"
62 #include "vm/jit/md.h"
63
64 #include "vmcore/loader.h"
65 #include "vmcore/options.h"
66 #include "vmcore/utf8.h"
67
68
69 bool codegen_emit(jitdata *jd) 
70 {       
71         methodinfo         *m;
72         codeinfo           *code;
73         codegendata        *cd;
74         registerdata       *rd;
75         s4                  len, s1, s2, s3, d, disp;
76         ptrint              a;
77         varinfo            *var;
78         basicblock         *bptr;
79         instruction        *iptr;
80         exception_entry    *ex;
81         u2                  currentline;
82         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
83         unresolved_method  *um;
84         builtintable_entry *bte;
85         methoddesc         *md;
86         s4                  fieldtype;
87         s4                  varindex;
88         unresolved_field   *uf;
89         fieldinfo          *fi;
90
91         /* get required compiler data */
92
93         m    = jd->m;
94         code = jd->code;
95         cd   = jd->cd;
96         rd   = jd->rd;
97
98         /* prevent compiler warnings */
99
100         d = 0;
101         lm = NULL;
102         bte = NULL;
103
104         {
105                 s4 i, p, t, l;
106                 /* save calle saved registers */
107                 s4 savedregs_num = 0;
108
109                 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
110                 savedregs_num += (ADR_SAV_CNT - rd->savadrreguse);
111                 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
112
113                 cd->stackframesize = rd->memuse + savedregs_num;
114 #if defined(ENABLE_THREADS)
115                 assert(0);
116 #endif
117         
118                 /* create method header */
119                 (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
120                 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
121 #if defined(ENABLE_THREADS)
122                 if (checksync && (m->flags & ACC_SYNCHRONIZED))
123                         (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4);/* IsSync         */
124                 else
125 #endif
126                 (void) dseg_add_unique_s4(cd, 0);                      /* IsSync          */
127                 (void) dseg_add_unique_s4(cd, jd->isleafmethod);       /* IsLeaf          */
128
129                 /* XXX we use the IntSAce a split field for the adr now */
130                 (void) dseg_add_unique_s4(cd, (ADR_SAV_CNT - rd->savadrreguse) << 16 | (INT_SAV_CNT - rd->savintreguse)); /* IntSave */
131                 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
132
133                 dseg_addlinenumbertablesize(cd);
134
135                 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize   */
136
137                 /* create exception table */
138                 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
139                         dseg_add_target(cd, ex->start);
140                         dseg_add_target(cd, ex->end);
141                         dseg_add_target(cd, ex->handler);
142                         (void) dseg_add_unique_address(cd, ex->catchtype.any);
143                 }
144
145 #if defined(ENABLE_PROFILING)
146                 assert(0);
147 #endif
148
149 #if !defined(NDEBUG)
150                 emit_verbosecall_enter(jd);
151 #endif
152                 /* create stack frame */
153                 M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
154
155                 /* save used callee saved registers */
156                 p = cd->stackframesize;
157                 for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
158                         p--; M_IST(rd->savintregs[i], REG_SP, p*4);
159                 }
160                 for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
161                         p--; M_AST(rd->savadrregs[i], REG_SP, p*4);
162                 }
163 #if !defined(ENABLE_SOFTFLOAT)
164                 for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
165                         p-=2; M_FST(rd->savfltregs[i], REG_SP, p*4);    /* FIXME */
166                 }       
167 #else
168                 assert(FLT_SAV_CNT == 0);
169                 assert(rd->savfltreguse == 0);
170 #endif
171                 /* take arguments out of stack frame */
172                 md = m->parseddesc;
173                 for (p = 0, l = 0; p < md->paramcount; p++) {
174                         t = md->paramtypes[p].type;
175                         varindex = jd->local_map[l * 5 + t];
176         
177                         l++;
178                         if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
179                                 l++;
180
181                         if (varindex == UNUSED)
182                                 continue;
183
184                         var = VAR(varindex);
185         
186                         s1 = md->params[p].regoff;
187                         assert(md->params[p].inmemory);                 /* all args are on stack */
188
189                         switch (t)      {
190 #if defined(ENABLE_SOFTFLOAT)
191                         case TYPE_FLT:
192                         case TYPE_DBL:
193 #endif
194                         case TYPE_LNG:
195                         case TYPE_INT:
196                                 if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
197                                         if (IS_2_WORD_TYPE(t))  {
198                                                 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
199                                         } else {
200                                                 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
201                                         }
202                                 } else {                             /* stack arg -> spilled  */
203 #if 1
204                                         M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
205                                         M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
206                                         if (IS_2_WORD_TYPE(t)) {
207                                                 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4 + 4);
208                                                 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
209                                         }
210 #else
211                                         /* Reuse Memory Position on Caller Stack */
212                                         var->vv.regoff = cd->stackframesize + s1;
213 #endif
214                                 } 
215                                 break;
216 #if !defined(ENABLE_SOFTFLOAT)
217                         case TYPE_FLT:
218                         case TYPE_DBL:
219                                 if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
220                                         if (IS_2_WORD_TYPE(t))  {
221                                                 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
222                                         } else {
223                                                 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
224                                         }
225                                 } else {                             /* stack-arg -> spilled  */
226 #if 1
227                                         if (IS_2_WORD_TYPE(t)) {
228                                                 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
229                                                 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
230                                         } else {
231                                                 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
232                                                 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
233                                         }
234 #else
235                                         /* Reuse Memory Position on Caller Stack */
236                                         var->vv.regoff = cd->stackframesize + s1;
237 #endif
238                                 }
239                                 break;
240 #endif /* SOFTFLOAT */
241                         case TYPE_ADR:
242                                 if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
243                                         M_ALD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
244                                 } else {                             /* stack-arg -> spilled  */
245 #if 1
246                                         M_ALD(REG_ATMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
247                                         M_AST(REG_ATMP1, REG_SP, var->vv.regoff * 4);
248 #else
249                                 /* Reuse Memory Position on Caller Stack */
250                                 var->vv.regoff = cd->stackframesize + s1;
251 #endif
252                                 }
253                                 break;
254                         default: assert(0);
255                         }
256                 } /* end for argument out of stack*/
257         }
258
259
260
261         /* create replacement points */
262         REPLACEMENT_POINTS_INIT(cd, jd);
263
264         /* foreach basic block */
265         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
266         
267         bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
268
269         if (bptr->flags >= BBREACHED)   {
270         
271         /* branch resolving */
272         codegen_resolve_branchrefs(cd, bptr);
273
274         /* FIXME there are still some constrcuts to copy in here */
275
276         /* walk through all instructions */
277         len = bptr->icount;
278         currentline = 0;
279
280         for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
281                 if (iptr->line != currentline) {
282                         dseg_addlinenumber(cd, iptr->line);
283                         currentline = iptr->line;
284                 }
285
286                 MCODECHECK(1024);                         /* 1kB should be enough */
287
288                 switch (iptr->opc) {
289                 case ICMD_NOP:        /* ...  ==> ...                                 */
290                 case ICMD_POP:        /* ..., value  ==> ...                          */
291                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
292                         break;
293
294                 case ICMD_INLINE_START:
295
296                         REPLACEMENT_POINT_INLINE_START(cd, iptr);
297                         break;
298
299                 case ICMD_INLINE_BODY:
300
301                         REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
302                         dseg_addlinenumber_inline_start(cd, iptr);
303                         dseg_addlinenumber(cd, iptr->line);
304                         break;
305
306                 case ICMD_INLINE_END:
307
308                         dseg_addlinenumber_inline_end(cd, iptr);
309                         dseg_addlinenumber(cd, iptr->line);
310                         break;
311
312                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
313
314                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
315                         assert(VAROP(iptr->s1)->type == TYPE_ADR);
316                         emit_nullpointer_check(cd, iptr, s1);
317                         break;
318
319
320                 /* CONST **************************************************************/
321                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
322                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
323                         M_IMOV_IMM(iptr->sx.val.i, d);
324                         emit_store_dst(jd, iptr, d);
325                         break;
326
327                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
328
329                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
330                         LCONST(iptr->sx.val.l, d);
331                         emit_store_dst(jd, iptr, d);
332                         break;
333
334                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
335
336 #if defined(ENABLE_SOFTFLOAT)
337                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
338                         M_IMOV_IMM(iptr->sx.val.i, d);
339                         emit_store_dst(jd, iptr, d);
340 #else
341                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
342                         FCONST(iptr->sx.val.f, d);
343                         emit_store_dst(jd, iptr, d);
344 #endif
345                         break;
346
347                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
348
349 #if defined(ENABLE_SOFTFLOAT)
350                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
351                         LCONST(iptr->sx.val.l, d);
352                         emit_store_dst(jd, iptr, d);
353 #else
354                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
355                         DCONST(iptr->sx.val.d, d);
356                         emit_store_dst(jd, iptr, d);
357 #endif
358                         break;
359
360
361
362                 /* integer operations ************************************************/
363                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
364
365                         s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
366                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
367                         M_INTMOVE(s1, REG_ITMP1);
368                         M_INEG(REG_ITMP1);
369                         M_INTMOVE(REG_ITMP1, d);
370                         emit_store_dst(jd, iptr, d);
371                         break;
372
373 #if 0
374                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
375
376                         s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
377                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
378                         M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
379                         M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
380                         emit_store_dst(jd, iptr, d);
381                         break;
382 #endif
383                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
384
385                         s1 = emit_load_s1(jd, iptr, REG_ITMP3);
386                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
387                         M_IMOV(s1, GET_LOW_REG(d));                             /* sets negativ bit */
388                         M_BPL(4);
389                         M_ISET(GET_HIGH_REG(d));
390                         M_TPFW;
391                         M_ICLR(GET_HIGH_REG(d));
392
393                         emit_store_dst(jd, iptr, d);
394                         break;
395
396                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
397
398                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
399                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
400                         M_INTMOVE(s1, d);
401                         emit_store_dst(jd, iptr, d);
402                         break;
403                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
404
405                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
406                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
407                         M_BSEXT(s1, d);
408                         emit_store_dst(jd, iptr, d);
409                         break;
410
411                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
412
413                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
414                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
415                         M_CZEXT(s1, d);
416                         emit_store_dst(jd, iptr, d);
417                         break;
418
419                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
420
421                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
422                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
423                         M_SSEXT(s1, d);
424                         emit_store_dst(jd, iptr, d);
425                         break;
426
427
428
429                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
430
431                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
432                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
433                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
434                         M_INTMOVE(s2, REG_ITMP2);
435                         M_IADD(s1, REG_ITMP2);
436                         M_INTMOVE(REG_ITMP2, d);
437                         emit_store_dst(jd, iptr, d);
438                         break;
439
440                                       /* s1.localindex = variable, sx.val.i = constant*/
441
442                 case ICMD_IINC:
443                 case ICMD_IADDCONST:
444
445                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
446                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
447                         M_INTMOVE(s1, REG_ITMP1);
448                         M_IADD_IMM(iptr->sx.val.i, REG_ITMP1);
449                         M_INTMOVE(REG_ITMP1, d);
450                         emit_store_dst(jd, iptr, d);
451                         break;
452
453                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
454
455                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
456                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
457                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
458                         M_INTMOVE(s1, REG_ITMP1);
459                         M_ISUB(s2, REG_ITMP1);
460                         M_INTMOVE(REG_ITMP1, d);
461                         emit_store_dst(jd, iptr, d);
462                         break;
463
464                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
465                                       /* sx.val.i = constant                          */
466
467                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
468                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
469                         M_INTMOVE(s1, REG_ITMP1);
470                         M_IADD_IMM(-iptr->sx.val.i, REG_ITMP1);
471                         M_INTMOVE(REG_ITMP1, d);
472                         emit_store_dst(jd, iptr, d);
473                         break;
474
475                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
476                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
477                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
478                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
479                         emit_arithmetic_check(cd, iptr, s2);
480                         M_INTMOVE(s1, REG_ITMP1);
481                         M_IDIV(s2, REG_ITMP1);
482                         M_INTMOVE(REG_ITMP1, d);
483                         emit_store_dst(jd, iptr, d);
484                         break;
485
486                 case ICMD_IDIVPOW2:             /* ..., value  ==> ..., value << constant       */
487                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
488                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
489                         M_INTMOVE(s1, REG_ITMP1);
490
491                         M_ITST(REG_ITMP1);
492                         M_BPL(6);
493                         M_IADD_IMM((1 << iptr->sx.val.i) - 1, REG_ITMP1);
494
495                         M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
496                         M_ISSR(REG_ITMP2, REG_ITMP1);
497                         M_INTMOVE(REG_ITMP1, d);
498                         emit_store_dst(jd, iptr, d);
499                         break;
500
501                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
502                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
503                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
504                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
505                         emit_arithmetic_check(cd, iptr, s2);
506
507                         M_ICMP_IMM(0x80000000, s1);
508                         M_BNE(4+8);
509                         M_ICMP_IMM(-1, s2);
510                         M_BNE(4);
511                         M_ICLR(REG_ITMP3);
512                         M_TPFL;                                 /* hides the next instruction */
513                         M_IREM(s2, s1, REG_ITMP3);
514
515                         M_INTMOVE(REG_ITMP3, d);
516
517                         emit_store_dst(jd, iptr, d);
518                         break;
519
520                 case ICMD_IREMPOW2:             /* ..., value  ==> ..., value << constant       */
521                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
522                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
523                         if (s1 == d) {
524                                 M_IMOV(s1, REG_ITMP1);
525                                 s1 = REG_ITMP1;
526                         } 
527                         M_INTMOVE(s1, d);
528                         M_IAND_IMM(iptr->sx.val.i, d);
529                         M_ITST(s1);
530                         M_BGE(2 + 2 + 6 + 2);
531                         M_IMOV(s1, d);  /* don't use M_INTMOVE, so we know the jump offset */
532                         M_INEG(d);
533                         M_IAND_IMM(iptr->sx.val.i, d);     /* use 32-bit for jump offset */
534                         M_INEG(d);
535
536                         emit_store_dst(jd, iptr, d);
537                         break;
538
539
540                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
541                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
542
543                         bte = iptr->sx.s23.s3.bte;
544                         md  = bte->md;
545
546                         s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
547                         M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
548                         M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
549                         /* XXX could be optimized */
550                         emit_arithmetic_check(cd, iptr, REG_ITMP3);
551
552                         M_LST(s2, REG_SP, 2 * 4);
553                         s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
554                         M_LST(s1, REG_SP, 0 * 4);
555
556                         M_JSR_IMM(bte->fp);
557
558                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
559                         M_LNGMOVE(REG_RESULT_PACKED, d);
560                         emit_store_dst(jd, iptr, d);
561                         break;
562
563                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
564
565                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
566                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
567                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
568                         M_INTMOVE(s2, REG_ITMP2);
569                         M_IMUL(s1, REG_ITMP2);
570                         M_INTMOVE(REG_ITMP2, d);
571                         emit_store_dst(jd, iptr, d);
572                         break;
573
574                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
575                                       /* sx.val.i = constant                          */
576                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
577                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
578                         M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
579                         M_IMUL(s1, REG_ITMP2);
580                         M_INTMOVE(REG_ITMP2, d);
581                         emit_store_dst(jd, iptr, d);
582                         break;
583
584                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
585
586                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
587                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
588                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
589                         M_INTMOVE(s1, REG_ITMP1);
590                         M_INTMOVE(s2, REG_ITMP2);
591                         M_IAND_IMM(0x1f, REG_ITMP2);
592                         M_ISSL(REG_ITMP2, REG_ITMP1);
593                         M_INTMOVE(REG_ITMP1, d);
594                         emit_store_dst(jd, iptr, d);
595                         break;
596
597                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
598                                       /* sx.val.i = constant                          */
599
600                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
601                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
602                         if (iptr->sx.val.i & 0x1f)      {
603                                 M_INTMOVE(s1, REG_ITMP1)
604                                 if ((iptr->sx.val.i & 0x1f) <= 7)       {
605                                         M_ISSL_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
606                                 } else  {
607                                         M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
608                                         M_ISSL(REG_ITMP2, REG_ITMP1);
609                                 }
610                                 M_INTMOVE(REG_ITMP1, d);
611                         } else  {
612                                 M_INTMOVE(s1, d);
613                         }
614                         emit_store_dst(jd, iptr, d);
615                         break;
616
617                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
618
619                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
620                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
621                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
622                         M_INTMOVE(s1, REG_ITMP1);
623                         M_INTMOVE(s2, REG_ITMP2);
624                         M_IAND_IMM(0x1f, REG_ITMP2);
625                         M_ISSR(REG_ITMP2, REG_ITMP1);
626                         M_INTMOVE(REG_ITMP1, d);
627                         emit_store_dst(jd, iptr, d);
628                         break;
629
630                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
631                                       /* sx.val.i = constant                          */
632
633                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
634                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
635                         if (iptr->sx.val.i & 0x1f)      {
636                                 M_INTMOVE(s1, REG_ITMP1)
637                                 if ((iptr->sx.val.i & 0x1f) <= 7)       {
638                                         M_ISSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
639                                 } else  {
640                                         M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
641                                         M_ISSR(REG_ITMP2, REG_ITMP1);
642                                 }
643                                 M_INTMOVE(REG_ITMP1, d);
644                         } else  {
645                                 M_INTMOVE(s1, d);
646                         }
647                         emit_store_dst(jd, iptr, d);
648                         break;
649
650                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
651
652                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
653                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
654                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
655                         M_INTMOVE(s1, REG_ITMP1);
656                         M_INTMOVE(s2, REG_ITMP2);
657                         M_IAND_IMM(0x1f, REG_ITMP2);
658                         M_IUSR(REG_ITMP2, REG_ITMP1);
659                         M_INTMOVE(REG_ITMP1, d);
660                         emit_store_dst(jd, iptr, d);
661                         break;
662
663                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
664                                       /* sx.val.i = constant                          */
665                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
666                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
667                         if (iptr->sx.val.i & 0x1f)      {
668                                 M_INTMOVE(s1, REG_ITMP1)
669                                 if ((iptr->sx.val.i & 0x1f) <= 7)       {
670                                         M_IUSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
671                                 } else  {
672                                         M_IMOV_IMM(iptr->sx.val.i & 0x1f, REG_ITMP2);
673                                         M_IUSR(REG_ITMP2, REG_ITMP1);
674                                 }
675                                 M_INTMOVE(REG_ITMP1, d);
676                         } else  {
677                                 M_INTMOVE(s1, d);
678                         }
679                         emit_store_dst(jd, iptr, d);
680                         break;
681
682                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
683
684                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
685                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
686                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
687                         M_INTMOVE(s2, REG_ITMP2);
688                         M_IAND(s1, REG_ITMP2);
689                         M_INTMOVE(REG_ITMP2, d);
690                         emit_store_dst(jd, iptr, d);
691                         break;
692
693                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
694                                       /* sx.val.i = constant                          */
695
696                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
697                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
698                         M_INTMOVE(s1, REG_ITMP1);
699                         M_IAND_IMM(iptr->sx.val.i, REG_ITMP1);
700                         M_INTMOVE(REG_ITMP1, d);
701                         emit_store_dst(jd, iptr, d);
702                         break;
703
704                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
705                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
706                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
707                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
708                         M_INTMOVE(s2, REG_ITMP2);
709                         M_IOR(s1, REG_ITMP2);
710                         M_INTMOVE(REG_ITMP2, d);
711                         emit_store_dst(jd, iptr, d);
712                         break;
713
714                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
715                                       /* sx.val.i = constant                          */
716                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
717                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
718                         M_INTMOVE(s1, REG_ITMP1);
719                         M_IOR_IMM(iptr->sx.val.i, REG_ITMP1);
720                         M_INTMOVE(REG_ITMP1, d);
721                         emit_store_dst(jd, iptr, d);
722                         break;
723
724                 case ICMD_IXOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
725                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
726                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
727                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
728                         M_INTMOVE(s2, REG_ITMP2);
729                         M_IXOR(s1, REG_ITMP2);
730                         M_INTMOVE(REG_ITMP2, d);
731                         emit_store_dst(jd, iptr, d);
732                         break;
733
734                 case ICMD_IXORCONST:   /* ..., value  ==> ..., value | constant        */
735                                       /* sx.val.i = constant                          */
736                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
737                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
738                         M_INTMOVE(s1, REG_ITMP1);
739                         M_IXOR_IMM(iptr->sx.val.i, REG_ITMP1);
740                         M_INTMOVE(REG_ITMP1, d);
741                         emit_store_dst(jd, iptr, d);
742                         break;
743
744
745
746                 /* load/store/copy/move operations ************************************/
747
748                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
749                 case ICMD_ALOAD:      /* s1 = local variable                          */
750                 case ICMD_LLOAD:
751                 case ICMD_FLOAD:  
752                 case ICMD_DLOAD:  
753                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
754                 case ICMD_LSTORE:
755                 case ICMD_FSTORE:
756                 case ICMD_DSTORE: 
757                 case ICMD_COPY:
758                 case ICMD_MOVE:
759
760                         emit_copy(jd, iptr);
761                         break;
762
763                 case ICMD_ASTORE:
764
765                         if (!(iptr->flags.bits & INS_FLAG_RETADDR))
766                                 emit_copy(jd, iptr);
767                         break;
768
769
770                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
771                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
772
773                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
774                                 constant_classref *cr = iptr->sx.val.c.ref;;
775                                 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
776                                 M_AMOV_IMM(0, d);
777                         } else {
778                                 M_AMOV_IMM(iptr->sx.val.anyptr, d);
779                         }
780                         emit_store_dst(jd, iptr, d);
781                         break;
782                 /* BRANCH *************************************************************/
783
784                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
785
786                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
787                         M_ADRMOVE(s1, REG_ATMP1_XPTR);
788
789 #ifdef ENABLE_VERIFIER
790                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
791                                 unresolved_class *uc = iptr->sx.s23.s2.uc;
792
793                                 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
794                         }
795 #endif /* ENABLE_VERIFIER */
796                         M_JSR_PCREL(2);                         /* get current PC */
797                         M_APOP(REG_ATMP2);              
798
799                         M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
800                         M_JMP(REG_ATMP3);
801                         ALIGNCODENOP;
802                         break;
803
804                 case ICMD_GOTO:         /* ... ==> ...                                */
805                 case ICMD_RET:          /* ... ==> ...                                */
806
807                         emit_br(cd, iptr->dst.block);
808                         ALIGNCODENOP;
809                         break;
810
811                 case ICMD_JSR:          /* ... ==> ...                                */
812
813                         emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
814                         ALIGNCODENOP;
815                         break;
816
817
818
819                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
820                 case ICMD_IFNONNULL:
821                         assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
822                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
823                         M_ATST(s1);
824                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
825                         break;
826
827                 case ICMD_IFLT:
828                 case ICMD_IFLE:
829                 case ICMD_IFNE:
830                 case ICMD_IFGT:
831                 case ICMD_IFGE:
832                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
833
834                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
835                         assert (VAROP(iptr->s1)->type == TYPE_INT);
836                         M_ICMP_IMM(iptr->sx.val.i, s1); 
837                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
838                         break;
839
840                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
841                 case ICMD_IF_ICMPNE:
842                 case ICMD_IF_ICMPLT:
843                 case ICMD_IF_ICMPGT:
844                 case ICMD_IF_ICMPLE:
845                 case ICMD_IF_ICMPGE:
846
847                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
848                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
849                         M_ICMP(s2, s1);
850                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
851                         break;
852
853                 case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
854                 case ICMD_IF_ACMPNE:
855
856                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
857                         s2 = emit_load_s2(jd, iptr, REG_ATMP2);
858                         M_ACMP(s1, s2);
859                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
860                         break;
861
862
863                 /* MEMORY *************************************************************/
864                 case ICMD_GETSTATIC:
865                         if (INSTRUCTION_IS_UNRESOLVED(iptr))    {
866                                 uf        = iptr->sx.s23.s3.uf;
867                                 fieldtype = uf->fieldref->parseddesc.fd->type;
868                                 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
869                         } else  {
870                                 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
871
872                                 fieldtype = fi->type;
873                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
874                                         codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, 0);
875                                 }
876
877                                 disp = (ptrint) &(fi->value);
878                         }
879                         M_AMOV_IMM(disp, REG_ATMP1);
880                         switch (fieldtype) {
881 #if defined(ENABLE_SOFTFLOAT)
882                         case TYPE_FLT:
883 #endif
884                         case TYPE_INT:
885                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
886                                 M_ILD(d, REG_ATMP1, 0);
887                                 break;
888                         case TYPE_ADR:
889                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
890                                 M_ALD(d, REG_ATMP1, 0);
891                                 break;
892 #if defined(ENABLE_SOFTFLOAT)
893                         case TYPE_DBL:
894 #endif
895                         case TYPE_LNG:
896                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
897                                 M_LLD(d, REG_ATMP1, 0);
898                                 break;
899 #if !defined(ENABLE_SOFTFLOAT)
900                         case TYPE_FLT:
901                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
902                                 M_FLD(d, REG_ATMP1, 0);
903                                 break;
904                         case TYPE_DBL:                          
905                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
906                                 M_DLD(d, REG_ATMP1, 0);
907                                 break;
908 #endif
909                         }
910                         emit_store_dst(jd, iptr, d);
911                         break;
912
913                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
914
915                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
916                                 uf        = iptr->sx.s23.s3.uf;
917                                 fieldtype = uf->fieldref->parseddesc.fd->type;
918
919                                 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
920                         } else {
921                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
922                                 fieldtype = fi->type;
923                                 disp      = &(fi->value);
924
925                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
926                                         codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, 0);
927                         }
928                 
929                         M_AMOV_IMM(disp, REG_ATMP1);
930                         switch (fieldtype) {
931 #if defined(ENABLE_SOFTFLOAT)
932                         case TYPE_FLT:
933 #endif
934                         case TYPE_INT:
935                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
936                                 M_IST(s1, REG_ATMP1, 0);
937                                 break;
938 #if defined(ENABLE_SOFTFLOAT)
939                         case TYPE_DBL:
940 #endif
941                         case TYPE_LNG:
942                                 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
943                                 M_LST(s1, REG_ATMP1, 0);
944                                 break;
945                         case TYPE_ADR:
946                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
947                                 M_AST(s1, REG_ATMP1, 0);
948                                 break;
949 #if !defined(ENABLE_SOFTFLOAT)
950                         case TYPE_FLT:
951                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
952                                 M_FST(s1, REG_ATMP1, 0);
953                                 break;
954                         case TYPE_DBL:
955                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
956                                 M_DST(s1, REG_ATMP1, 0);
957                                 break;
958 #endif
959                         default: assert(0);
960                         }
961                         break;
962
963                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
964
965                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
966
967                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
968                                 uf        = iptr->sx.s23.s3.uf;
969                                 fieldtype = uf->fieldref->parseddesc.fd->type;
970                                 disp      = 0;
971
972                                 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
973                         }
974                         else {
975                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
976                                 fieldtype = fi->type;
977                                 disp      = fi->offset;
978                         }
979
980                         /* implicit null-pointer check */
981                         switch (fieldtype) {
982 #if defined(ENABLE_SOFTFLOAT)
983                         case TYPE_FLT:
984 #endif
985                         case TYPE_INT:
986                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
987                                 M_ILD(d, s1, disp);
988                                 break;
989 #if defined(ENABLE_SOFTFLOAT)
990                         case TYPE_DBL:
991 #endif
992                         case TYPE_LNG:
993                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
994                                 M_LLD(d, s1, disp);
995                                 break;
996                         case TYPE_ADR:
997                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
998                                 M_ALD(d, s1, disp);
999                                 break;
1000 #if !defined(ENABLE_SOFTFLOAT)
1001                         case TYPE_FLT:
1002                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1003                                 M_FLD(d, s1, disp);
1004                                 break;
1005                         case TYPE_DBL:                          
1006                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1007                                 M_DLD(d, s1, disp);
1008                                 break;
1009 #endif
1010                         }
1011                         emit_store_dst(jd, iptr, d);
1012                         break;
1013
1014                 case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
1015
1016                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1017
1018                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1019                                 uf        = iptr->sx.s23.s3.uf;
1020                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1021                                 disp      = 0;
1022                         }
1023                         else {
1024                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1025                                 fieldtype = fi->type;
1026                                 disp      = fi->offset;
1027                         }
1028
1029                         if (IS_INT_LNG_TYPE(fieldtype)) {
1030                                 if (IS_2_WORD_TYPE(fieldtype)) {
1031                                         s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1032                                 } else {
1033                                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1034                                 }
1035                         } else {
1036                                 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1037                         }
1038
1039                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1040                                 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1041
1042                         /* implicit null-pointer check */
1043                         switch (fieldtype) {
1044 #if defined(ENABLE_SOFTFLOAT)
1045                         case TYPE_FLT:
1046 #endif
1047                         case TYPE_INT:
1048                                 M_IST(s2, s1, disp);
1049                                 break;
1050
1051 #if defined(ENABLE_SOFTFLOAT)
1052                         case TYPE_DBL:
1053 #endif
1054                         case TYPE_LNG:
1055                                 M_LST(s2, s1, disp);  
1056                                 break;
1057                         case TYPE_ADR:
1058                                 M_AST(s2, s1, disp);
1059                                 break;
1060 #if !defined(ENABLE_SOFTFLOAT)
1061                         case TYPE_FLT:
1062                                 M_FST(s2, s1, disp);
1063                                 break;
1064                         case TYPE_DBL:
1065                                 M_DST(s2, s1, disp);
1066                                 break;
1067 #endif
1068                         }
1069                         break;
1070
1071                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1072
1073                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1074                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1075                         /* implicit null-pointer check */
1076                         M_ILD(d, s1, OFFSET(java_arrayheader, size));
1077                         emit_store_dst(jd, iptr, d);
1078                         break;
1079
1080                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1081
1082                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1083                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1084                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1085                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1086                         M_INTMOVE(s2, REG_ITMP2);
1087                         M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
1088                         M_ADRMOVE(s1, REG_ATMP1);
1089                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1090                         /* implicit null-pointer check */
1091                         M_LBZX(REG_ATMP1, d);
1092                         M_BSEXT(d, d);
1093                         emit_store_dst(jd, iptr, d);
1094                         break;                  
1095
1096                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1097
1098                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1099                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1100                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1101                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1102                         M_INTMOVE(s2, REG_ITMP2);
1103                         M_ISSL_IMM(1, REG_ITMP2);
1104                         M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2);
1105                         M_ADRMOVE(s1, REG_ATMP1);
1106                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1107                         /* implicit null-pointer check */
1108                         M_LHZX(REG_ATMP1, d);
1109                         M_CZEXT(d, d);
1110                         emit_store_dst(jd, iptr, d);
1111                         break;
1112
1113                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1114
1115                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1116                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1117                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1118                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1119                         M_INTMOVE(s2, REG_ITMP2);
1120                         M_ISSL_IMM(1, REG_ITMP2);
1121                         M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
1122                         M_ADRMOVE(s1, REG_ATMP1);
1123                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1124                 
1125                         /* implicit null-pointer check */
1126                         M_LHZX(REG_ATMP1, d);
1127                         M_SSEXT(d, d);
1128                         emit_store_dst(jd, iptr, d);
1129                         break;
1130
1131                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1132
1133                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1134                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1135                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1136                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1137                         M_INTMOVE(s2, REG_ITMP2);
1138                         M_ISSL_IMM(2, REG_ITMP2);
1139                         M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
1140                         M_ADRMOVE(s1, REG_ATMP1);
1141                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1142         
1143                         /* implicit null-pointer check */
1144                         M_LWZX(REG_ATMP1, d);
1145                         emit_store_dst(jd, iptr, d);
1146                         break;
1147
1148                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1149                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1150                         s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1151                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1152                         /* implicit null-pointer check */
1153                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1154                         M_INTMOVE(s2, REG_ITMP1);
1155                         M_ISSL_IMM(3, REG_ITMP1);
1156                         M_IADD_IMM(OFFSET(java_longarray, data[0]), REG_ITMP1);
1157                         M_ADRMOVE(s1, REG_ATMP1);
1158                         M_AADDINT(REG_ITMP1, REG_ATMP1);
1159                         #if 0
1160                         M_LWZX(REG_ATMP1, GET_LOW_REG(d));
1161                         M_AADD_IMM(4, REG_ATMP1);
1162                         M_LWZX(REG_ATMP1, GET_HIGH_REG(d));
1163                         #endif
1164                         M_LLD(d, REG_ATMP1, 0);
1165                         emit_store_dst(jd, iptr, d);
1166                         break;
1167
1168                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1169                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1170                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1171                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1172                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1173                         M_INTMOVE(s2, REG_ITMP2);
1174                         M_ISSL_IMM(2, REG_ITMP2);
1175                         M_IADD_IMM(OFFSET(java_floatarray, data[0]), REG_ITMP2);
1176                         M_ADRMOVE(s1, REG_ATMP1);
1177                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1178                         /* implicit null-pointer check */
1179 #if !defined(ENABLE_SOFTFLOAT)
1180                         M_LFSX(REG_ATMP1, d);
1181 #else
1182                         M_LWZX(REG_ATMP1, d);
1183 #endif
1184                         emit_store_dst(jd, iptr, d);
1185                         break;
1186
1187                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1188                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1189                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1190                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1191                         M_INTMOVE(s2, REG_ITMP2);
1192                         M_ISSL_IMM(3, REG_ITMP2);
1193                         M_IADD_IMM(OFFSET(java_doublearray, data[0]), REG_ITMP2);
1194                         M_ADRMOVE(s1, REG_ATMP1);
1195                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1196                         /* implicit null-pointer check */
1197 #if !defined(ENABLE_SOFTFLOAT)
1198                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);    /* FIXME */
1199                         M_LFDX(REG_ATMP1, s3);
1200 #else
1201                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1202                         /* implicit null-pointer check */
1203                         M_LLD(d, REG_ATMP1, 0);
1204 #endif
1205                         emit_store_dst(jd, iptr, d);
1206                         break;
1207
1208                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1209
1210                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1211                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1212                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1213                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1214                         M_INTMOVE(s2, REG_ITMP2);
1215                         M_ISSL_IMM(2, REG_ITMP2);
1216                         M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP2);
1217                         M_ADRMOVE(s1, REG_ATMP1);
1218                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1219         
1220                         /* implicit null-pointer check */
1221                         M_LAX(REG_ATMP1, d);
1222                         emit_store_dst(jd, iptr, d);
1223                         break;
1224
1225
1226                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1227
1228                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1229                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1230                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1231                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1232                         M_INTMOVE(s2, REG_ITMP2);
1233                         M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
1234                         M_ADRMOVE(s1, REG_ATMP1);
1235                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1236         
1237                         /* implicit null-pointer check */
1238                         M_STBX(REG_ATMP1, s3);
1239                         break;
1240
1241                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1242
1243                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1244                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1245                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1246                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1247                         M_INTMOVE(s2, REG_ITMP2);
1248                         M_ISSL_IMM(1, REG_ITMP2);
1249                         M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2); 
1250                         M_ADRMOVE(s1, REG_ATMP1);
1251                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1252                         /* implicit null-pointer check */
1253                         M_STHX(REG_ATMP1, s3);
1254                         break;
1255
1256                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1257
1258                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1259                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1260                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1261                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1262                         M_INTMOVE(s2, REG_ITMP2);
1263                         M_ISSL_IMM(1, REG_ITMP2);
1264                         M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
1265                         M_ADRMOVE(s1, REG_ATMP1);
1266                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1267                         /* implicit null-pointer check */
1268                         M_STHX(REG_ATMP1, s3);
1269                         break;
1270
1271                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1272
1273                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1274                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1275                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1276                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1277                         M_INTMOVE(s2, REG_ITMP2);
1278                         M_ISSL_IMM(2, REG_ITMP2);
1279                         M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
1280                         M_ADRMOVE(s1, REG_ATMP1);
1281                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1282                         /* implicit null-pointer check */
1283                         M_STWX(REG_ATMP1, s3);
1284                         break;
1285
1286                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1287                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1288                         s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1289                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1290
1291                         M_INTMOVE(s2, REG_ITMP1);
1292                         M_ISSL_IMM(3, REG_ITMP1);
1293                         M_IADD_IMM(OFFSET(java_longarray, data[0]), REG_ITMP1);
1294                         M_ADRMOVE(s1, REG_ATMP1);
1295                         M_AADDINT(REG_ITMP1, REG_ATMP1);
1296                         /* implicit null-pointer check */
1297                         #if 0
1298                         M_STWX(REG_ATMP1, s3);
1299                         M_AADD_IMM(4, REG_ATMP1);
1300                         s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1301                         /* implicit null-pointer check */
1302                         M_STWX(REG_ATMP1, s3);
1303                         #endif
1304                         s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1305                         M_LST(s3, REG_ATMP1, 0);
1306                         break;
1307
1308                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1309                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1310                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1311                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1312                         s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1313                         M_INTMOVE(s2, REG_ITMP2);
1314                         M_ISSL_IMM(2, REG_ITMP2);
1315                         M_IADD_IMM(OFFSET(java_floatarray, data[0]), REG_ITMP2);
1316                         M_ADRMOVE(s1, REG_ATMP1);
1317                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1318                         /* implicit null-pointer check */
1319 #if !defined(ENABLE_SOFTFLOAT)
1320                         M_STFSX(REG_ATMP1, s3);
1321 #else
1322                         M_STWX(REG_ATMP1, s3);
1323 #endif
1324                         break;
1325
1326                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1327                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1328                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1329                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1330                         M_INTMOVE(s2, REG_ITMP2);
1331                         M_ISSL_IMM(3, REG_ITMP2);
1332                         M_IADD_IMM(OFFSET(java_doublearray, data[0]), REG_ITMP2);
1333                         M_ADRMOVE(s1, REG_ATMP1);
1334                         M_AADDINT(REG_ITMP2, REG_ATMP1);
1335                         /* implicit null-pointer check */
1336 #if !defined(ENABLE_SOFTFLOAT)
1337                         s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1338                         M_STFDX(REG_ATMP1, s3); /*FIXME*/
1339                         assert(0);
1340 #else
1341                         s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1342                         /* implicit null-pointer check */
1343                         M_LST(s3, REG_ATMP1, 0);
1344 #endif
1345                         break;
1346
1347                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1348
1349                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1350                         s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1351                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1352                         s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1353
1354                         /* XXX what if array is NULL */
1355                         disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1356
1357                         M_AST(s1, REG_SP, 0*4);
1358                         M_AST(s3, REG_SP, 1*4);
1359                         M_JSR_IMM(BUILTIN_canstore);    
1360                         emit_exception_check(cd, iptr);
1361
1362                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1363                         s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1364                         s3 = emit_load_s3(jd, iptr, REG_ATMP2);
1365                         M_INTMOVE(s2, REG_ITMP1);
1366                         M_ISSL_IMM(2, REG_ITMP1);
1367                         M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP1);
1368                         M_ADRMOVE(s1, REG_ATMP1);
1369                         M_AADDINT(REG_ITMP1, REG_ATMP1);
1370                         /* implicit null-pointer check */
1371                         M_STAX(REG_ATMP1, s3);
1372                         break;
1373
1374
1375
1376                 /* METHOD INVOCATION *********************************************************/
1377                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
1378                         bte = iptr->sx.s23.s3.bte;
1379                         md  = bte->md;
1380                         goto gen_method;
1381
1382                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
1383                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1384                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
1385                 case ICMD_INVOKEINTERFACE:
1386                         REPLACEMENT_POINT_INVOKE(cd, iptr);
1387
1388                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1389                                 lm = NULL;
1390                                 um = iptr->sx.s23.s3.um;
1391                                 md = um->methodref->parseddesc.md;
1392                         }
1393                         else {
1394                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1395                                 um = NULL;
1396                                 md = lm->parseddesc;
1397                         }
1398         gen_method:
1399                         s3 = md->paramcount;
1400         
1401                         MCODECHECK((s3 << 1) + 64);
1402
1403                         /* copy arguments to stack */
1404                         for (s3 = s3 - 1; s3 >= 0; s3--)        {
1405                                 var = VAR(iptr->sx.s23.s2.args[s3]);
1406                                 /* already preallocated */
1407                                 if (var->flags & PREALLOC) continue;
1408                 
1409                                 if (!md->params[s3].inmemory) assert(0);
1410
1411                                 switch (var->type)      {
1412 #if defined(ENABLE_SOFTFLOAT)
1413                                         case TYPE_DBL:
1414 #endif
1415                                         case TYPE_LNG:
1416                                                 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
1417                                                 M_LST(d, REG_SP, md->params[s3].regoff*4);
1418                                                 break;
1419 #if defined(ENABLE_SOFTFLOAT)
1420                                         case TYPE_FLT:
1421 #endif
1422                                         case TYPE_INT:
1423                                                 d = emit_load(jd, iptr, var, REG_ITMP1);
1424                                                 M_IST(d, REG_SP, md->params[s3].regoff*4);
1425                                                 break;
1426                                         case TYPE_ADR:
1427                                                 d = emit_load(jd, iptr, var, REG_ATMP1);
1428                                                 M_AST(d, REG_SP, md->params[s3].regoff*4);
1429                                                 break;
1430 #if !defined(ENABLE_SOFTFLOAT)
1431                                         case TYPE_FLT:
1432                                         case TYPE_DBL:
1433 #endif
1434                                         default:
1435                                                 assert(0);
1436                                 }
1437                         }
1438
1439                         /* arguments in place now */
1440                         switch(iptr->opc)       {
1441                                 case ICMD_BUILTIN: 
1442                                         disp = (ptrint) bte->fp;
1443                                         d = md->returntype.type;
1444                                         M_JSR_IMM(disp);
1445
1446                                         REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1447                                         emit_exception_check(cd, iptr);
1448                                         break;
1449
1450                                 case ICMD_INVOKESPECIAL: 
1451                                         /* adress register for sure */
1452                                         M_ALD(REG_ATMP1, REG_SP, 0);
1453                                         emit_nullpointer_check(cd, iptr, REG_ATMP1);
1454                                         /* fall through */
1455                                 case ICMD_INVOKESTATIC: 
1456                                         if (lm == NULL) {
1457                                                 codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
1458                                                 disp = 0;
1459                                                 M_AMOV_IMM(disp, REG_ATMP1);
1460                                         } else  {
1461                                                 disp = lm->stubroutine;
1462                                                 M_AMOV_IMM(disp, REG_ATMP1);
1463                                         }
1464
1465                                         /* generate the actual call */
1466                                         M_JSR(REG_ATMP1);
1467                                         REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1468                                         break;
1469
1470
1471                                 case ICMD_INVOKEVIRTUAL:
1472                                         if (lm == NULL) {
1473                                                 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
1474                                                 s1 = 0;
1475                                         } else {
1476                                                 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1477                                         }
1478                                         /* load object pointer (==argument 0) */
1479                                         M_ALD(REG_ATMP1, REG_SP, 0);
1480                                         /* implicit null-pointer check */
1481                                         M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
1482                                         M_ALD(REG_ATMP3, REG_METHODPTR, s1);
1483                                         /* generate the actual call */
1484                                         M_JSR(REG_ATMP3);
1485                                         break;
1486                                 case ICMD_INVOKEINTERFACE: 
1487                                         if (lm == NULL) {
1488                                                 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
1489
1490                                                 s1 = 0;
1491                                                 s2 = 0;
1492                                         } else {
1493                                                 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
1494                                                 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1495                                         }
1496                                         /* load object pointer (==argument 0) */
1497                                         M_ALD(REG_ATMP1, REG_SP, 0);
1498
1499                                         /* implicit null-pointer check */
1500                                         M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
1501                                         M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
1502                                         M_ALD(REG_ATMP3, REG_METHODPTR, s2);
1503
1504                                         /* generate the actual call */
1505                                         M_JSR(REG_ATMP3);
1506                                         REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1507                                         break;
1508
1509                                 default: assert(0);
1510                                 }       /* switch (iptr->opc) */
1511
1512                                 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
1513                                 
1514                                 /* store return value */
1515                                 d = md->returntype.type;
1516
1517                                 switch (d)      {
1518                                         case TYPE_VOID: break;
1519 #if defined(ENABLE_SOFTFLOAT)
1520                                         case TYPE_FLT:
1521 #endif
1522                                         case TYPE_INT:
1523                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
1524                                                 M_INTMOVE(REG_RESULT, s1);
1525                                                 break;
1526 #if defined(ENABLE_SOFTFLOAT)
1527                                         case TYPE_DBL:
1528 #endif
1529                                         case TYPE_LNG:
1530                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1531                                                 M_LNGMOVE(REG_RESULT_PACKED, s1);
1532                                                 break;
1533                                         case TYPE_ADR:
1534                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
1535                                                 /* all stuff is returned in %d0 */
1536                                                 M_INT2ADRMOVE(REG_RESULT, s1);
1537                                                 break;
1538 #if !defined(ENABLE_SOFTFLOAT)
1539                                         case TYPE_FLT:
1540                                         case TYPE_DBL:
1541 #endif
1542                                         default:
1543                                                 assert(0);
1544                                 }
1545                                 if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
1546                         break; /* ICMD_INVOKE* */
1547
1548 #if defined(ENABLE_SOFTFLOAT)
1549                 case ICMD_FRETURN:
1550 #endif
1551                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
1552
1553                         REPLACEMENT_POINT_RETURN(cd, iptr);
1554                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
1555                         M_INTMOVE(s1, REG_RESULT);
1556                         goto nowperformreturn;
1557
1558                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
1559
1560                         REPLACEMENT_POINT_RETURN(cd, iptr);
1561                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
1562                         assert(VAROP(iptr->s1)->type == TYPE_ADR);
1563                         M_ADR2INTMOVE(s1, REG_RESULT);
1564
1565 #ifdef ENABLE_VERIFIER
1566                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1567                                 unresolved_class *uc = iptr->sx.s23.s2.uc;
1568
1569                                 codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
1570                         }
1571 #endif /* ENABLE_VERIFIER */
1572                         goto nowperformreturn;
1573
1574 #if defined(ENABLE_SOFTFLOAT)
1575                 case ICMD_DRETURN:
1576 #endif
1577                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
1578
1579                         REPLACEMENT_POINT_RETURN(cd, iptr);
1580                         s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
1581                         M_LNGMOVE(s1, REG_RESULT_PACKED);
1582                         goto nowperformreturn;
1583
1584 #if !defined(ENABLE_SOFTFLOAT)
1585                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
1586                 case ICMD_DRETURN:
1587
1588                         REPLACEMENT_POINT_RETURN(cd, iptr);
1589                         s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1590                         M_FLTMOVE(s1, REG_FRESULT);
1591                         goto nowperformreturn;
1592 #endif
1593
1594                 case ICMD_RETURN:      /* ...  ==> ...                                */
1595
1596                         REPLACEMENT_POINT_RETURN(cd, iptr);
1597
1598 nowperformreturn:
1599                         {
1600                         s4 i, p;
1601                         
1602                         p = cd->stackframesize;
1603
1604                         /* call trace function */
1605 #if !defined(NDEBUG)
1606                         emit_verbosecall_exit(jd);
1607 #endif
1608
1609 #if defined(ENABLE_THREADS)
1610                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1611                                 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
1612                                 M_ALD(REG_ITMP3, REG_PV, disp);
1613                                 M_MTCTR(REG_ITMP3);
1614
1615                                 /* we need to save the proper return value */
1616
1617                                 switch (iptr->opc) {
1618                                 case ICMD_LRETURN:
1619                                         M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
1620                                         /* fall through */
1621                                 case ICMD_IRETURN:
1622                                 case ICMD_ARETURN:
1623                                         M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
1624                                         break;
1625                                 case ICMD_FRETURN:
1626                                         M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
1627                                         break;
1628                                 case ICMD_DRETURN:
1629                                         M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
1630                                         break;
1631                                 }
1632
1633                                 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
1634                                 M_JSR;
1635
1636                                 /* and now restore the proper return value */
1637
1638                                 switch (iptr->opc) {
1639                                 case ICMD_LRETURN:
1640                                         M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
1641                                         /* fall through */
1642                                 case ICMD_IRETURN:
1643                                 case ICMD_ARETURN:
1644                                         M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
1645                                         break;
1646                                 case ICMD_FRETURN:
1647                                         M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
1648                                         break;
1649                                 case ICMD_DRETURN:
1650                                         M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
1651                                         break;
1652                                 }
1653                         }
1654 #endif
1655
1656
1657                         /* restore return address                                         */
1658 #if 0
1659                         if (!jd->isleafmethod) {
1660                                 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
1661                                    may have a displacement overflow. */
1662
1663                                 M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
1664                                 M_MTLR(REG_ITMP1);
1665                         }
1666 #endif
1667                         /* restore saved registers                                        */
1668
1669                         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
1670                                 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
1671                         }
1672                         for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
1673                                 p--; M_ALD(rd->savadrregs[i], REG_SP, p*4);
1674                         }
1675 #if !defined(ENABLE_SOFTFLOAT)
1676                         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
1677                                 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
1678                         }
1679 #endif
1680                         /* deallocate stack                                               */
1681                         M_AADD_IMM(cd->stackframesize*4, REG_SP);
1682                         M_RET;
1683                         }
1684                         break;
1685
1686                 /* the evil ones */
1687                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
1688                                       /* val.a: (classinfo*) superclass               */
1689
1690                         /*  superclass is an interface:
1691                          *
1692                          *  return (sub != NULL) &&
1693                          *         (sub->vftbl->interfacetablelength > super->index) &&
1694                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
1695                          *
1696                          *  superclass is a class:
1697                          *
1698                          *  return ((sub != NULL) && (0
1699                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
1700                          *          super->vftbl->diffvall));
1701                          */
1702
1703                         {
1704                         classinfo *super;
1705                         s4         superindex;
1706
1707                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1708                                 super      = NULL;
1709                                 superindex = 0;
1710                         }
1711                         else {
1712                                 super      = iptr->sx.s23.s3.c.cls;
1713                                 superindex = super->index;
1714                         }
1715                         
1716 #if defined(ENABLE_THREADS)
1717                         codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
1718 #endif
1719                         s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1720                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1721
1722                         assert(VAROP(iptr->s1 )->type == TYPE_ADR);
1723                         assert(VAROP(iptr->dst)->type == TYPE_INT);
1724
1725                         M_ICLR(d);
1726
1727                         /* if class is not resolved, check which code to call */
1728
1729                         if (super == NULL) {
1730                                 M_ATST(s1);
1731                                 emit_label_beq(cd, BRANCH_LABEL_1);
1732
1733                                 codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
1734
1735                                 M_IMOV_IMM32(0, REG_ITMP3);
1736                                 M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
1737                                 emit_label_beq(cd, BRANCH_LABEL_2);
1738                         }
1739
1740                         /* interface instanceof code */
1741
1742                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1743                                 if (super == NULL) {
1744                                         codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
1745                                 } else {
1746                                         M_ATST(s1);
1747                                         emit_label_beq(cd, BRANCH_LABEL_3);
1748                                 }
1749
1750                                 M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
1751                                 M_ILD(REG_ITMP3, REG_ATMP1, OFFSET(vftbl_t, interfacetablelength));
1752                                 M_IADD_IMM(-superindex, REG_ITMP3);     /* -superindex may be patched patched */
1753                                 M_ITST(REG_ITMP3);
1754                                 M_BLE(10);
1755                                 M_ALD(REG_ATMP1, REG_ATMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*));      /* patch here too! */
1756                                 M_ATST(REG_ATMP1);
1757                                 M_BEQ(2);
1758                                 M_IMOV_IMM(1, d);
1759
1760                                 if (super == NULL)
1761                                         emit_label_br(cd, BRANCH_LABEL_4);
1762                                 else
1763                                         emit_label(cd, BRANCH_LABEL_3);
1764                         }
1765
1766                         /* class instanceof code */
1767
1768                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1769                                 if (super == NULL) {
1770                                         emit_label(cd, BRANCH_LABEL_2);
1771
1772                                         codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
1773                                         M_AMOV_IMM(0, REG_ATMP2);
1774                                 } else {
1775                                         M_AMOV_IMM(super->vftbl, REG_ATMP2);
1776                                         M_ATST(s1);
1777                                         emit_label_beq(cd, BRANCH_LABEL_5);
1778                                 }
1779
1780                                 M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
1781 #if defined(ENABLE_THREADS)
1782                                 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
1783 #endif
1784                                 M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
1785                                 M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
1786                                 M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
1787 #if defined(ENABLE_THREADS)
1788                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
1789 #endif
1790                                 M_ISUB(REG_ITMP3, REG_ITMP1);
1791                                 M_ICMP(REG_ITMP2, REG_ITMP1);
1792                                 M_BHI(4);
1793                                 M_IMOV_IMM(1, d);
1794                                 M_TPFW;                 /* overlaps next instruction */
1795                                 M_ICLR(d);
1796
1797                                 if (super != NULL)
1798                                         emit_label(cd, BRANCH_LABEL_5);
1799                         }
1800
1801                         if (super == NULL) {
1802                                 emit_label(cd, BRANCH_LABEL_1);
1803                                 emit_label(cd, BRANCH_LABEL_4);
1804                         }
1805
1806                         emit_store_dst(jd, iptr, d);
1807                         }
1808                         break;
1809
1810                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
1811                                       /* val.a: (classinfo*) superclass               */
1812
1813                         /*  superclass is an interface:
1814                          *
1815                          *  OK if ((sub == NULL) ||
1816                          *         (sub->vftbl->interfacetablelength > super->index) &&
1817                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
1818                          *
1819                          *  superclass is a class:
1820                          *
1821                          *  OK if ((sub == NULL) || (0
1822                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
1823                          *         super->vftbl->diffvall));
1824                          */
1825
1826                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1827                                 /* object type cast-check */
1828
1829                                 classinfo *super;
1830                                 s4         superindex;
1831
1832                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1833                                         super      = NULL;
1834                                         superindex = 0;
1835                                 }
1836                                 else {
1837                                         super      = iptr->sx.s23.s3.c.cls;
1838                                         superindex = super->index;
1839                                 }
1840
1841 #if defined(ENABLE_THREADS)
1842                                 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
1843 #endif
1844
1845                                 s1 = emit_load_s1(jd, iptr, REG_ATMP1);
1846                                 assert(VAROP(iptr->s1)->type == TYPE_ADR);
1847
1848                                 /* if class is not resolved, check which code to call */
1849
1850                                 if (super == NULL) {
1851                                         M_ATST(s1);
1852                                         emit_label_beq(cd, BRANCH_LABEL_1);
1853
1854                                         codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
1855                         
1856                                         M_IMOV_IMM32(0, REG_ITMP2);
1857                                         M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
1858                                         emit_label_beq(cd, BRANCH_LABEL_2);
1859                                 }
1860
1861                                 /* interface checkcast code */
1862
1863                                 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1864                                         if (super == NULL) {
1865                                                 codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
1866                                         } else {
1867                                                 M_ATST(s1);
1868                                                 emit_label_beq(cd, BRANCH_LABEL_3);
1869                                         }
1870
1871                                         M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
1872                                         M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetablelength));
1873         
1874                                         M_IADD_IMM(-superindex, REG_ITMP3);     /* superindex patched */
1875                                         M_ITST(REG_ITMP3);
1876                                         emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
1877
1878                                         M_ALD(REG_ATMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*));      /* patched*/
1879                                         M_ATST(REG_ATMP3);
1880                                         emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ATMP3, s1);
1881
1882                                         if (super == NULL)
1883                                                 emit_label_br(cd, BRANCH_LABEL_4);
1884                                         else
1885                                                 emit_label(cd, BRANCH_LABEL_3);
1886                                 }
1887
1888                                 /* class checkcast code */
1889
1890                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1891                                         if (super == NULL) {
1892                                                 emit_label(cd, BRANCH_LABEL_2);
1893
1894                                                 codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
1895                                                 M_AMOV_IMM(0, REG_ATMP3);
1896                                         } else {
1897                                                 M_AMOV_IMM(super->vftbl, REG_ATMP3);
1898                                                 M_ATST(s1);
1899                                                 emit_label_beq(cd, BRANCH_LABEL_5);
1900                                         }
1901
1902                                         M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
1903 #if defined(ENABLE_THREADS)
1904                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
1905 #endif
1906                                         M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));  /* REG_ITMP3 == sub->vftbl->baseval */
1907                                         M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
1908                                         M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
1909 #if defined(ENABLE_THREADS)
1910                                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
1911 #endif
1912                                         M_ISUB(REG_ITMP1, REG_ITMP3);
1913                                         M_ICMP(REG_ITMP2, REG_ITMP3);   /* XXX was CMPU */
1914
1915                                         emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); /* XXX was BRANCH_GT */
1916
1917                                         if (super != NULL)
1918                                                 emit_label(cd, BRANCH_LABEL_5);
1919                                 }
1920
1921                                 if (super == NULL) {
1922                                         emit_label(cd, BRANCH_LABEL_1);
1923                                         emit_label(cd, BRANCH_LABEL_4);
1924                                 }
1925
1926                                 d = codegen_reg_of_dst(jd, iptr, s1);
1927                         } else {
1928                                 /* array type cast-check */
1929
1930                                 s1 = emit_load_s1(jd, iptr, REG_ATMP2);
1931
1932                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1933                                         codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
1934                                         M_AMOV_IMM(0, REG_ATMP1);
1935                                 } else {
1936                                         M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
1937                                 }
1938         
1939                                 M_APUSH(REG_ATMP1);
1940                                 M_APUSH(s1);
1941                                 M_JSR_IMM(BUILTIN_arraycheckcast);
1942                                 M_AADD_IMM(2*4, REG_SP);                /* pop arguments off stack */
1943                                 M_ITST(REG_RESULT);
1944                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
1945
1946                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1947                                 d = codegen_reg_of_dst(jd, iptr, s1);
1948                         }
1949                         assert(VAROP(iptr->dst)->type == TYPE_ADR);
1950                         M_ADRMOVE(s1, d);
1951                         emit_store_dst(jd, iptr, d);
1952                         break;
1953
1954                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
1955                         {
1956                         s4 i, l;
1957                         branch_target_t *table;
1958
1959                         table = iptr->dst.table;
1960
1961                         l = iptr->sx.s23.s2.tablelow;
1962                         i = iptr->sx.s23.s3.tablehigh;
1963                         
1964                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1965                         M_INTMOVE(s1, REG_ITMP1);
1966                         if (l != 0) M_ISUB_IMM(l, REG_ITMP1);
1967
1968                         i = i - l + 1;
1969
1970                         /* range check */
1971                         M_ICMP_IMM(i - 1, REG_ITMP1);
1972                         emit_bugt(cd, table[0].block);
1973
1974                         /* build jump table top down and use address of lowest entry */
1975                         table += i;
1976
1977                         while (--i >= 0) {
1978                                 dseg_add_target(cd, table->block); 
1979                                 --table;
1980                         }
1981
1982                         /* length of dataseg after last dseg_add_target is used by load */
1983                         M_AMOV_IMM(0, REG_ATMP2);
1984                         dseg_adddata(cd);
1985
1986                         M_ISSL_IMM(2, REG_ITMP1);                       /* index * 4 == offset in table */
1987                         M_AADDINT(REG_ITMP1, REG_ATMP2);                /* offset in table */
1988                         M_AADD_IMM(-(cd->dseglen), REG_ATMP2);          /* start of table in dseg */
1989                         M_ALD(REG_ATMP1, REG_ATMP2, 0);
1990
1991                         M_JMP(REG_ATMP1);
1992                         ALIGNCODENOP;
1993                         }
1994                         break;
1995
1996                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
1997                         {
1998                         s4 i;
1999                         lookup_target_t *lookup;
2000
2001                         lookup = iptr->dst.lookup;
2002
2003                         i = iptr->sx.s23.s2.lookupcount;
2004                         
2005                         MCODECHECK((i<<2)+8);
2006                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2007
2008                         while (--i >= 0) {
2009                                 M_ICMP_IMM(lookup->value, s1);
2010                                 emit_beq(cd, lookup->target.block);
2011                                 lookup++;
2012                         }
2013
2014                         emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2015                         ALIGNCODENOP;
2016                         break;
2017                         }
2018
2019                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2020
2021                         /* check for negative sizes and copy sizes to stack if necessary  */
2022                         MCODECHECK((iptr->s1.argcount << 1) + 64);
2023
2024                         for (s1 = iptr->s1.argcount; --s1 >= 0;) {
2025                                 var = VAR(iptr->sx.s23.s2.args[s1]);
2026
2027                                 /* Already Preallocated? */
2028                                 if (!(var->flags & PREALLOC)) {
2029                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
2030                                         M_IST(s2, REG_SP, (s1 + 3) * 4);
2031                                 }
2032                         }
2033
2034                         /* a0 = dimension count */
2035                         M_IMOV_IMM(iptr->s1.argcount, REG_ITMP1);
2036                         M_IST(REG_ITMP1, REG_SP, 0*4);
2037
2038                         /* a1 = arraydescriptor */
2039                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2040                                 codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
2041                                 M_AMOV_IMM(0, REG_ATMP1);
2042                         } else  {
2043                                 M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
2044                         }
2045                         M_AST(REG_ATMP1, REG_SP, 1*4);
2046
2047                         /* a2 = pointer to dimensions = stack pointer */
2048                         M_AMOV(REG_SP, REG_ATMP1);
2049                         M_AADD_IMM(3*4, REG_ATMP1);
2050                         M_AST(REG_ATMP1, REG_SP, 2*4);
2051
2052                         M_JSR_IMM(BUILTIN_multianewarray);
2053
2054                         /* check for exception before result assignment */
2055                         emit_exception_check(cd, iptr);
2056
2057                         assert(VAROP(iptr->dst)->type == TYPE_ADR);
2058                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2059                         M_INT2ADRMOVE(REG_RESULT, d);
2060                         emit_store_dst(jd, iptr, d);
2061                         break;
2062
2063
2064
2065                 default:
2066                         printf("UNKNOWN OPCODE %d\n", iptr->opc);
2067                         exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
2068                         return false;
2069         } /* switch */
2070         M_TPF;
2071         } /* for each instruction */
2072         } /* if (btpre->flags >= BBREACHED) */
2073         } /* for each basic block */
2074
2075         dseg_createlinenumbertable(cd);
2076
2077         /* generate stubs */
2078         emit_patcher_stubs(jd);
2079         REPLACEMENT_EMIT_STUBS(jd);
2080
2081         return true;
2082 }
2083
2084
2085 /* codegen_emit_stub_compiler **************************************************
2086
2087    Emits a stub routine which calls the compiler.
2088         
2089 *******************************************************************************/
2090
2091 void codegen_emit_stub_compiler(jitdata *jd)
2092 {
2093         methodinfo  *m;
2094         codegendata *cd;
2095
2096         /* get required compiler data */
2097
2098         m  = jd->m;
2099         cd = jd->cd;
2100
2101         /* code for the stub */
2102
2103         M_AMOV_IMM(m, REG_ATMP1);
2104         M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
2105         M_JMP(REG_ATMP3);
2106 }
2107
2108
2109 /* codegen_emit_stub_native ****************************************************
2110
2111    Emits a stub routine which calls a native method.
2112
2113 *******************************************************************************/
2114
2115 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
2116 {
2117         methodinfo   *m;
2118         codeinfo     *code;
2119         codegendata  *cd;
2120         registerdata *rd;
2121         methoddesc   *md;
2122         s4 nativeparams, i, j, t, s1, s2;
2123         
2124         /* get required compiler data */
2125
2126         m    = jd->m;
2127         code = jd->code;
2128         cd   = jd->cd;
2129         rd   = jd->rd;
2130
2131         md = m->parseddesc;
2132         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
2133
2134         /* calc stackframe size */
2135         cd->stackframesize =    sizeof(stackframeinfo) / SIZEOF_VOID_P +
2136                                 sizeof(localref_table) / SIZEOF_VOID_P +
2137                                 nmd->memuse +
2138                         #if 0
2139                                 4 +                                             /* %d0,%d1,%a0,%a1*/
2140                                 2 * 2 +                                         /* %f0,%f1 */
2141                         #endif
2142                                 1 +                                             /* functionptr */
2143                                 4;                                              /* args for codegen_start_native_call */
2144
2145         /* create method header */
2146         (void) dseg_add_unique_address(cd, code);                      /* CodeinfoPointer */
2147         (void) dseg_add_unique_s4(cd, cd->stackframesize * 4);         /* FrameSize       */
2148         (void) dseg_add_unique_s4(cd, 0);                              /* IsSync          */
2149         (void) dseg_add_unique_s4(cd, 0);                              /* IsLeaf          */
2150         (void) dseg_add_unique_s4(cd, 0);                              /* IntSave         */
2151         (void) dseg_add_unique_s4(cd, 0);                              /* FltSave         */
2152         (void) dseg_addlinenumbertablesize(cd);
2153         (void) dseg_add_unique_s4(cd, 0);                              /* ExTableSize     */
2154
2155         /* print call trace */
2156 #if !defined(NDEBUG)
2157         if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2158                 emit_verbosecall_enter(jd);
2159         }
2160 #endif
2161
2162         /* generate code */
2163         M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
2164
2165         /* get function address (this must happen before the stackframeinfo) */
2166 #if !defined(WITH_STATIC_CLASSPATH)
2167         if (f == NULL)  {
2168                 codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
2169         }
2170 #endif
2171         M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
2172
2173         M_AST(REG_ATMP2, REG_SP, 4 * 4);
2174
2175         /* save integer and float temp registers */
2176         /*
2177         M_IST(REG_D0, REG_SP, 4*4 + 2*8 + 3*4);
2178         M_IST(REG_D1, REG_SP, 4*4 + 2*8 + 2*4);
2179         M_AST(REG_A0, REG_SP, 4*4 + 2*8 + 1*4);
2180         M_AST(REG_A1, REG_SP, 4*4 + 2*8 + 0*4);
2181         */
2182
2183         /* TODO */
2184         /* store %f0, %f1 */
2185
2186         /* put arguments for codegen_start_native_call onto stack */
2187         /* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
2188         
2189         M_AMOV(REG_SP, REG_ATMP1);
2190         M_AADD_IMM(cd->stackframesize * 4, REG_ATMP1);
2191
2192         M_ALD(REG_ATMP3, REG_ATMP1, 0 * 4);
2193         M_AST(REG_ATMP3, REG_SP, 3 * 4);                /* ra */
2194
2195         M_AST(REG_ATMP1, REG_SP, 0 * 4);                /* datasp */
2196
2197         M_AADD_IMM(1 * 4 , REG_ATMP1);                  
2198         M_AST(REG_ATMP1, REG_SP, 2 * 4);                /* sp */
2199
2200         M_AMOV_IMM(0, REG_ATMP2);                       /* 0 needs to patched */
2201         dseg_adddata(cd);                                   /* this patches it */
2202
2203         M_AST(REG_ATMP2, REG_SP, 1 * 4);                /* pv */
2204
2205         M_JSR_IMM(codegen_start_native_call);
2206
2207         /* load function pointer */
2208         M_ALD(REG_ATMP2, REG_SP, 4 * 4);
2209
2210         /* copy arguments into stackframe */
2211         for (i = md->paramcount -1, j = i + nativeparams; i >= 0; --i, --j)     {
2212                 t = md->paramtypes[i].type;
2213                 /* all arguments via stack */
2214                 assert(md->params[i].inmemory);                                         
2215
2216                 s1 = (md->params[i].regoff + cd->stackframesize + 1) * 4;
2217                 s2 = nmd->params[j].regoff * 4;
2218
2219                 /* simply copy argument stack */
2220                 M_ILD(REG_ITMP1, REG_SP, s1);
2221                 M_IST(REG_ITMP1, REG_SP, s2);
2222                 if (IS_2_WORD_TYPE(t))  {
2223                         M_ILD(REG_ITMP1, REG_SP, s1 + 4);
2224                         M_IST(REG_ITMP1, REG_SP, s2 + 4);
2225                 }
2226         }
2227
2228         /* for static function class as second arg */
2229         if (m->flags & ACC_STATIC)      {
2230                 M_AMOV_IMM(m->class, REG_ATMP1);
2231                 M_AST(REG_ATMP1, REG_SP, 1 * 4);
2232         }
2233         /* env ist first argument */
2234         M_AMOV_IMM(_Jv_env, REG_ATMP1);
2235         M_AST(REG_ATMP1, REG_SP, 0 * 4);
2236
2237         /* call the native function */
2238         M_JSR(REG_ATMP2);
2239
2240         /* save return value */
2241         switch (md->returntype.type)    {
2242                 case TYPE_VOID: break;
2243
2244 #if defined(ENABLE_SOFTFLOAT)
2245                 case TYPE_DBL:
2246 #endif
2247                 case TYPE_LNG:
2248                         M_IST(REG_D1, REG_SP, 2 * 4);
2249                         /* fall through */
2250
2251 #if defined(ENABLE_SOFTFLOAT)
2252                 case TYPE_FLT:
2253 #endif
2254                 case TYPE_INT:
2255                 case TYPE_ADR:
2256                         M_IST(REG_D0, REG_SP, 1 * 4);
2257                         break;
2258
2259 #if !defined(ENABLE_SOFTFLOAT)
2260                 case TYPE_FLT:
2261                 case TYPE_DBL:  /* FIXME */
2262 #endif
2263                 default: assert(0);
2264         }
2265         
2266         /* print call trace */
2267 #if ! defined(NDEBUG)
2268         if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2269                 emit_verbosecall_exit(jd);
2270         }
2271 #endif
2272         /* remove native stackframe info */
2273         /* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
2274
2275         M_AMOV(REG_SP, REG_ATMP3);
2276         M_AADD_IMM(cd->stackframesize * 4, REG_ATMP3);
2277         M_AST(REG_ATMP3, REG_SP, 0 * 4);                        /* datasp */
2278         M_JSR_IMM(codegen_finish_native_call);
2279         
2280         M_INT2ADRMOVE(REG_RESULT, REG_ATMP1);
2281         /* restore return value */
2282         switch (md->returntype.type)    {
2283                 case TYPE_VOID: break;
2284
2285 #if defined(ENABLE_SOFTFLOAT)
2286                 case TYPE_DBL:
2287 #endif
2288                 case TYPE_LNG:
2289                         M_ILD(REG_D1, REG_SP, 2 * 4);
2290                         /* fall through */
2291 #if defined(ENABLE_SOFTFLOAT)
2292                 case TYPE_FLT:
2293 #endif
2294                 case TYPE_INT:
2295                 case TYPE_ADR:
2296                         M_ILD(REG_D0, REG_SP, 1 * 4);
2297                         break;
2298
2299 #if !defined(ENABLE_SOFTFLOAT)
2300                 case TYPE_FLT:
2301                 case TYPE_DBL:  /* FIXME */
2302 #endif
2303                 default: assert(0);
2304         }
2305         /* restore saved registers */
2306
2307         M_AADD_IMM(cd->stackframesize*4, REG_SP);
2308         /* check for exception */
2309         M_ATST(REG_ATMP1);
2310         M_BNE(2);
2311         M_RET;
2312
2313         /* handle exception, REG_ATMP1 already contains exception object, REG_ATMP2 holds address */
2314         
2315         M_ALD(REG_ATMP2_XPC, REG_SP, 0);                /* take return address as faulting instruction */
2316         M_AADD_IMM(-2, REG_ATMP2_XPC);                  /* which is off by 2 */
2317         M_JMP_IMM(asm_handle_nat_exception);
2318
2319         /* should never be reached from within jit code*/
2320         M_JSR_IMM(0);
2321
2322         /* generate patcher stub call code */
2323         emit_patcher_stubs(jd);
2324 }
2325
2326
2327 /*
2328  * These are local overrides for various environment variables in Emacs.
2329  * Please do not remove this and leave it at the end of the file, where
2330  * Emacs will automagically detect them.
2331  * ---------------------------------------------------------------------
2332  * Local variables:
2333  * mode: c
2334  * indent-tabs-mode: t
2335  * c-basic-offset: 4
2336  * tab-width: 4
2337  * End:
2338  * vim:noexpandtab:sw=4:ts=4:
2339  */