334dbada29be73b8e25c770490be75e2ae706381
[cacao.git] / src / vm / jit / s390 / codegen.c
1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdio.h>
31
32 #include "vm/jit/s390/arch.h"
33 #include "vm/jit/s390/codegen.h"
34 #include "vm/jit/s390/emit.h"
35 #include "vm/jit/s390/md-abi.h"
36
37 #include "native/localref.hpp"
38 #include "native/native.hpp"
39
40 #include "mm/memory.hpp"
41
42 #include "threads/lock.hpp"
43
44 #include "vm/jit/builtin.hpp"
45 #include "vm/exceptions.hpp"
46 #include "vm/global.h"
47 #include "vm/loader.hpp"
48 #include "vm/options.h"
49 #include "vm/statistics.h"
50 #include "vm/types.h"
51 #include "vm/vm.hpp"
52
53 #include "vm/jit/abi.h"
54 #include "vm/jit/asmpart.h"
55 #include "vm/jit/codegen-common.hpp"
56 #include "vm/jit/dseg.h"
57 #include "vm/jit/emit-common.hpp"
58 #include "vm/jit/jit.hpp"
59 #include "vm/jit/linenumbertable.hpp"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.hpp"
62 #include "vm/jit/patcher-common.hpp"
63 #include "vm/jit/reg.h"
64 #include "vm/jit/stacktrace.hpp"
65 #include "vm/jit/trap.hpp"
66
67
68 /* DO__LOG generates a call to do__log. No registers are destroyed,
69  * so you may use it anywhere. regs is an array containing all general
70  * purpose registers.
71  */
72
73 /*
74 static void do__log(u4 *regs) {
75 }
76 */
77
78 #define DO__LOG \
79         N_AHI(REG_SP, -200); \
80         N_STM(R0, R15, 96, REG_SP); \
81         M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
82         N_LA(R2, 96, RN, REG_SP); \
83         N_BASR(R14, R14); \
84         N_LM(R0, R15, 96, REG_SP); \
85         N_AHI(REG_SP, 200);
86
87 /* If the following macro is defined, workaround code for hercules quirks
88  * is generated
89  */
90
91 /* #define SUPPORT_HERCULES 1 */
92
93 /*
94
95 Layout of stackframe:
96
97 Meaning                                Offset
98 ===============================================================================
99 return_address                         (stackframesize - 1) * 8 
100 saved_int_reg[INT_SAV_CNT - 1]         (stackframseize - 2) * 8
101 ...
102 saved_int_reg[rd->savintreguse]  
103 saved_flt_reg[FLT_SAV_CNT - 1]
104 ...
105 saved_flt_reg[rd->savfltreguse]        (stackframesize - 1 - savedregs_num) * 8
106
107 return_value_tmp                       (rd->memuse + 1) * 8
108 monitorenter_argument                  (rd->memuse) * 8 
109 ???
110 local[rd->memuse - 1]                  (rd->memuse - 1) * 8
111 ....
112 local[2]                               2 * 8
113 local[1]                               1 * 8
114 local[0]                               0 * 8
115
116 */
117
118
119 /**
120  * Generates machine code for the method prolog.
121  */
122 void codegen_emit_prolog(jitdata* jd)
123 {
124         varinfo*    var;
125         methoddesc* md;
126         int32_t     s1;
127         int32_t     p, t, l;
128         int32_t     varindex;
129         int         i;
130
131         // Get required compiler data.
132         methodinfo*   m    = jd->m;
133         codeinfo*     code = jd->code;
134         codegendata*  cd   = jd->cd;
135         registerdata* rd   = jd->rd;
136
137         /* CAUTION:
138          * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
139          */
140
141         /* Offset PV */
142
143         M_AADD_IMM(N_PV_OFFSET, REG_PV);
144
145         /* create stack frame (if necessary) */
146
147         if (cd->stackframesize) {
148                 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
149         }
150
151         /* store return address */
152
153         M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
154
155         /* save used callee saved registers and return address */
156
157         p = cd->stackframesize - 1;
158
159         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
160                 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
161         }
162         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
163                 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
164         }
165
166         /* take arguments out of register or stack frame */
167
168         md = m->parseddesc;
169
170         for (p = 0, l = 0; p < md->paramcount; p++) {
171                 t = md->paramtypes[p].type;
172                 varindex = jd->local_map[l * 5 + t];
173
174                 l++;
175
176                 if (IS_2_WORD_TYPE(t))
177                         l++;
178
179                 if (varindex == UNUSED)
180                         continue;
181
182                 var = VAR(varindex);
183
184                 s1 = md->params[p].regoff;
185
186                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
187                         if (IS_2_WORD_TYPE(t)) {
188                                 s2 = PACK_REGS(
189                                         GET_LOW_REG(s1),
190                                         GET_HIGH_REG(s1)
191                                 );
192                         } else {
193                                 s2 = s1;
194                         }
195                         if (!md->params[p].inmemory) {           /* register arguments    */
196                                 if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
197                                         if (IS_2_WORD_TYPE(t)) {
198                                                 M_LNGMOVE(s2, var->vv.regoff);
199                                         } else {
200                                                 M_INTMOVE(s2, var->vv.regoff);
201                                         }
202                                 } else {                             /* reg arg -> spilled    */
203                                         if (IS_2_WORD_TYPE(t)) {
204                                                 M_LST(s2, REG_SP, var->vv.regoff);
205                                         } else {
206                                                 M_IST(s2, REG_SP, var->vv.regoff);
207                                         }
208                                 }
209
210                         } else {                                 /* stack arguments       */
211                                 if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
212                                         if (IS_2_WORD_TYPE(t)) {
213                                                 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
214                                         } else {
215                                                 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
216                                         }
217                                 } else {                             /* stack arg -> spilled  */
218                                         N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
219                                 }
220                         }
221
222                 } else {                                     /* floating args         */
223                         if (!md->params[p].inmemory) {           /* register arguments    */
224                                 s2 = s1;
225                                 if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
226                                         emit_fmove(cd, s2, var->vv.regoff);
227
228                                 } else {                                         /* reg arg -> spilled    */
229                                         if (IS_2_WORD_TYPE(t))
230                                                 M_DST(s2, REG_SP, var->vv.regoff);
231                                         else
232                                                 M_FST(s2, REG_SP, var->vv.regoff);
233                                 }
234
235                         } else {                                 /* stack arguments       */
236                                 if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
237                                         if (IS_2_WORD_TYPE(t))
238                                                 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
239
240                                         else
241                                                 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
242
243                                 } else {                             /* stack-arg -> spilled  */
244                                         N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
245                                         var->vv.regoff = cd->stackframesize * 8 + s1;
246                                 }
247                         }
248                 }
249         } /* end for */
250 }
251
252
253 /**
254  * Generates machine code for the method epilog.
255  */
256 void codegen_emit_epilog(jitdata* jd)
257 {
258         int32_t p;
259         int i;
260
261         // Get required compiler data.
262         codegendata*  cd = jd->cd;
263         registerdata* rd = jd->rd;
264
265         p = cd->stackframesize;
266
267         /* restore return address */
268
269         p--; M_ALD(REG_RA, REG_SP, p * 8);
270
271         /* restore saved registers */
272
273         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
274                 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
275         }
276         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
277                 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
278         }
279
280         /* deallocate stack */
281
282         if (cd->stackframesize)
283                 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
284
285         M_RET;
286 }
287
288
289 /**
290  * Generates machine code for one ICMD.
291  */
292 void codegen_emit_instruction(jitdata* jd, instruction* iptr)
293 {
294         varinfo*            var;
295         builtintable_entry* bte;
296         methodinfo*         lm;             // Local methodinfo for ICMD_INVOKE*.
297         unresolved_method*  um;
298         fieldinfo*          fi;
299         unresolved_field*   uf;
300         int32_t             fieldtype;
301         int32_t             s1, s2, s3, d;
302         int32_t             disp;
303
304         // Get required compiler data.
305         codeinfo*     code = jd->code;
306         codegendata*  cd   = jd->cd;
307
308         switch (iptr->opc) {
309
310                 /* constant operations ************************************************/
311
312                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
313                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
314                         disp = dseg_add_float(cd, iptr->sx.val.f);
315                         M_FLD_DSEG(d, disp, REG_ITMP1);
316                         emit_store_dst(jd, iptr, d);
317                         break;
318                 
319                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
320                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
321                         disp = dseg_add_double(cd, iptr->sx.val.d);
322                         M_DLD_DSEG(d, disp, REG_ITMP1);
323                         emit_store_dst(jd, iptr, d);
324                         break;
325
326                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
327                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
328
329                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
330                                 constant_classref *cr = iptr->sx.val.c.ref;
331                                 disp = dseg_add_unique_address(cd, cr);
332
333                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
334                                                                           cr, disp);
335
336                                 M_ALD_DSEG(d, disp);
337                         } else {
338                                 if (iptr->sx.val.anyptr == 0) {
339                                         M_CLR(d);
340                                 } else {
341                                         disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
342                                         M_ALD_DSEG(d, disp);
343                                         /*
344                                         if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
345                                                 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
346                                                 M_SLL_IMM(16, d);
347                                                 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
348                                         } else {
349                                                 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
350                                                 M_ALD_DSEG(d, disp);
351                                         }
352                                         */
353                                 }
354                         }
355                         emit_store_dst(jd, iptr, d);
356                         break;
357
358
359                 /* integer operations *************************************************/
360
361                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
362
363                         s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
364                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
365                         M_INEG(s1, d);
366                         emit_store_dst(jd, iptr, d);
367
368                         break;
369
370                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
371
372                         s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
373                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
374                         M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
375                         M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
376                         N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI); 
377                         N_AHI(GET_HIGH_REG(d), -1);
378                         emit_store_dst(jd, iptr, d);
379                         break;
380
381                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
382
383                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
384                         if (! N_IS_EVEN_ODD(d)) {
385                                 d = REG_ITMP31_PACKED;
386                         }
387                         assert(N_IS_EVEN_ODD(d));
388
389                         s1 = emit_load_s1(jd, iptr, REG_ITMP2);
390
391                         M_INTMOVE(s1, GET_HIGH_REG(d));
392                         M_SRDA_IMM(32, GET_HIGH_REG(d));
393
394                         emit_copy_dst(jd, iptr, d);
395                         emit_store_dst(jd, iptr, d);
396                         break;
397
398                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
399                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
400                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
401                         M_INTMOVE(GET_LOW_REG(s1), d);
402                         emit_store_dst(jd, iptr, d);
403                         break;
404
405                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
406                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
407                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
408                         M_INTMOVE(s1, d);
409                         M_SLL_IMM(24, d);
410                         M_SRA_IMM(24, d);
411                         emit_store_dst(jd, iptr, d);
412                         break;
413
414                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
415                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
416                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
417                         M_INTMOVE(s1, d);
418                         M_SLL_IMM(16, d);
419                         M_SRL_IMM(16, d);
420                         emit_store_dst(jd, iptr, d);
421                         break;
422
423                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
424
425                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
426                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
427                         M_INTMOVE(s1, d);
428                         M_SLL_IMM(16, d);
429                         M_SRA_IMM(16, d);
430                         emit_store_dst(jd, iptr, d);
431                         break;
432
433                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
434
435                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
436                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
437                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
438                         if (s2 == d)
439                                 M_IADD(s1, d);
440                         else {
441                                 M_INTMOVE(s1, d);
442                                 M_IADD(s2, d);
443                         }
444                         emit_store_dst(jd, iptr, d);
445
446                         break;
447
448                 case ICMD_IINC:
449                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
450                                       /* sx.val.i = constant                             */
451                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
452                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
453                         M_INTMOVE(s1, d);
454
455                         if (N_VALID_IMM(iptr->sx.val.i)) {
456                                 M_IADD_IMM(iptr->sx.val.i, d);
457                         } else {
458                                 ICONST(REG_ITMP2, iptr->sx.val.i);
459                                 M_IADD(REG_ITMP2, d);   
460                         }
461                         emit_store_dst(jd, iptr, d);
462                         break;
463
464                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
465
466                         /* M, (r, q) -> (r, q) */
467
468                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
469
470                         s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
471                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
472                         dd = GET_HIGH_REG(d);
473
474                         if (s2 == dd) {
475                                 M_IADD(s1, dd);
476                         } else {
477                                 M_INTMOVE(s1, dd);
478                                 M_IADD(s2, dd);
479                         }
480
481                         s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
482                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
483                         dd = GET_LOW_REG(d);
484
485                         if (s2 == dd) {
486                                 N_ALR(dd, s1);
487                         } else {
488                                 M_INTMOVE(s1, dd);
489                                 N_ALR(dd, s2);
490                         }
491
492                         N_BRC(8 | 4, SZ_BRC + SZ_AHI); 
493                         N_AHI(GET_HIGH_REG(d), 1);
494
495                         emit_store_dst(jd, iptr, d);
496                         break;
497
498                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
499                                       /* sx.val.l = constant                             */
500
501                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
502                         dd = GET_HIGH_REG(d);
503
504                         s1 = emit_load_s1_high(jd, iptr, dd);
505                         s3 = iptr->sx.val.l >> 32;
506
507                         M_INTMOVE(s1, dd);
508
509                         if (N_VALID_IMM(s3)) {
510                                 M_IADD_IMM(s3, dd);
511                         } else {
512                                 ICONST(REG_ITMP3, s3);
513                                 M_IADD(REG_ITMP3, dd);
514                         }
515
516                         dd = GET_LOW_REG(d);
517                         s1 = emit_load_s1_low(jd, iptr, dd);
518                         s3 = iptr->sx.val.l & 0xffffffff;
519                         ICONST(REG_ITMP3, s3);
520
521                         M_INTMOVE(s1, dd);
522                         N_ALR(dd, REG_ITMP3);
523
524                         N_BRC(8 | 4, SZ_BRC + SZ_AHI); 
525                         N_AHI(GET_HIGH_REG(d), 1);
526
527                         emit_store_dst(jd, iptr, d);
528                         break;
529
530                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
531                                                                  
532                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
533                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
534                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
535                         if (s2 == d) {
536                                 M_INTMOVE(s1, REG_ITMP1);
537                                 M_ISUB(s2, REG_ITMP1);
538                                 M_INTMOVE(REG_ITMP1, d);
539                         } else {
540                                 M_INTMOVE(s1, d);
541                                 M_ISUB(s2, d);
542                         }
543                         emit_store_dst(jd, iptr, d);
544
545                         break;
546
547                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
548                                       /* sx.val.i = constant                             */
549
550                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
551                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
552                         M_INTMOVE(s1, d);
553
554                         if (N_VALID_IMM(-iptr->sx.val.i)) {
555                                 M_ISUB_IMM(iptr->sx.val.i, d);
556                         } else {
557                                 ICONST(REG_ITMP2, iptr->sx.val.i);
558                                 M_ISUB(REG_ITMP2, d);
559                         }
560                         emit_store_dst(jd, iptr, d);
561
562                         break;
563
564                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
565
566                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
567
568                         s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
569                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
570                         dd = GET_HIGH_REG(d);
571
572                         if (s2 == dd) {
573                                 M_INTMOVE(s2, REG_ITMP3);
574                                 s2 = REG_ITMP3;
575                         }
576
577                         M_INTMOVE(s1, dd);
578                         M_ISUB(s2, dd);
579
580                         s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
581                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
582                         dd = GET_LOW_REG(d);
583
584                         if (s2 == dd) {
585                                 M_INTMOVE(s2, REG_ITMP3);
586                                 s2 = REG_ITMP3;
587                         } 
588
589                         M_INTMOVE(s1, dd);
590                         N_SLR(dd, s2);
591
592                         N_BRC(1 | 2, SZ_BRC + SZ_AHI); 
593                         N_AHI(GET_HIGH_REG(d), -1);
594
595                         emit_store_dst(jd, iptr, d);
596                         break;
597
598                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
599                                       /* sx.val.l = constant                             */
600
601                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
602
603                         dd = GET_HIGH_REG(d);
604                         s1 = emit_load_s1_high(jd, iptr, dd);
605                         s3 = iptr->sx.val.l >> 32;
606
607                         M_INTMOVE(s1, dd);
608
609                         if (N_VALID_IMM(-s3)) {
610                                 M_IADD_IMM(-s3, dd);
611                         } else {
612                                 ICONST(REG_ITMP3, s3);
613                                 M_ISUB(REG_ITMP3, dd);
614                         }
615
616                         dd = GET_LOW_REG(d);
617                         s1 = emit_load_s1_low(jd, iptr, dd);
618                         s3 = iptr->sx.val.l & 0xffffffff;
619                         ICONST(REG_ITMP3, s3);
620
621                         M_INTMOVE(s1, dd);
622                         N_SLR(dd, REG_ITMP3);
623
624                         N_BRC(1 | 2, SZ_BRC + SZ_AHI); 
625                         N_AHI(GET_HIGH_REG(d), -1);
626
627                         emit_store_dst(jd, iptr, d);
628                         break;
629
630                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
631
632                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
633                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
634                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
635                         if (s2 == d)
636                                 M_IMUL(s1, d);
637                         else {
638                                 M_INTMOVE(s1, d);
639                                 M_IMUL(s2, d);
640                         }
641                         emit_store_dst(jd, iptr, d);
642
643                         break;
644
645                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
646                                       /* sx.val.i = constant                             */
647                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
648                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
649                         M_INTMOVE(s1, d);
650                         if (iptr->sx.val.i == 2) {
651                                 M_SLL_IMM(1, d);
652                         } else if (N_VALID_IMM(iptr->sx.val.i)) {
653                                 M_IMUL_IMM(iptr->sx.val.i, d);
654                         } else {
655                                 disp = dseg_add_s4(cd, iptr->sx.val.i);
656                                 M_ILD_DSEG(REG_ITMP2, disp);
657                                 M_IMUL(REG_ITMP2, d);   
658                         }
659                         emit_store_dst(jd, iptr, d);
660                         break;
661
662                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
663                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
664
665                         /* load s1 into r0 */
666
667                         s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
668                         M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
669                         s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
670
671                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
672
673                         /* extend s1 to long */
674
675                         M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
676
677                         /* divide */
678
679                         N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
680
681                         /* take result */
682
683                         switch (iptr->opc) {
684                                 case ICMD_IREM:
685                                         d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
686                                         M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
687                                         break;
688                                 case ICMD_IDIV:
689                                         d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
690                                         M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
691                                         break;
692                         }
693
694                         emit_store_dst(jd, iptr, d);
695
696                         break;
697
698                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
699                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
700
701                         bte = iptr->sx.s23.s3.bte;
702                         md  = bte->md;
703
704                         /* test s2 for zero */
705
706                         s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
707                         M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
708                         M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
709                         emit_arithmetic_check(cd, iptr, REG_ITMP3);
710
711                         /* TODO SIGFPE? */
712
713                         disp = dseg_add_functionptr(cd, bte->fp);
714
715                         /* load arguments */
716
717                         M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
718
719                         s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
720                         M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
721
722                         /* call builtin */
723
724                         M_ASUB_IMM(96, REG_SP);
725                         M_ALD_DSEG(REG_ITMP2, disp);
726                         M_JSR(REG_RA, REG_ITMP2);
727                         M_AADD_IMM(96, REG_SP);
728
729                         /* store result */
730
731                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
732                         M_LNGMOVE(REG_RESULT_PACKED, d);
733                         emit_store_dst(jd, iptr, d);
734
735                         break;
736
737                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
738                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
739                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
740
741                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
742                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
743                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
744
745                         /* Use only 5 bits of sencond operand. */
746
747                         M_INTMOVE(s2, REG_ITMP2);
748                         s2 = REG_ITMP2;
749                         ICONST(REG_ITMP3, 0x1F);
750                         M_IAND(REG_ITMP3, s2);
751
752                         M_INTMOVE(s1, d);
753
754                         switch (iptr->opc) {
755                                 case ICMD_ISHL:
756                                         M_SLL(s2, d);
757                                         break;
758                                 case ICMD_ISHR:
759                                         M_SRA(s2, d);
760                                         break;
761                                 case ICMD_IUSHR:
762                                         M_SRL(s2, d);
763                                         break;
764                                 default:
765                                         assert(0);
766                         }
767                         emit_store_dst(jd, iptr, d);
768                         break;
769
770                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
771                                       /* sx.val.i = constant                             */
772                         {
773                                 u1 *ref;
774
775                                 assert(iptr->sx.val.i <= 32);
776
777                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
778                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
779
780                                 M_INTMOVE(s1, d);
781                                 M_TEST(d);
782                                 ref = cd->mcodeptr;
783                                 M_BGE(0);
784
785                                 s3 = (1 << iptr->sx.val.i) - 1;
786
787                                 if (N_VALID_IMM(s3)) {
788                                         M_IADD_IMM(s3, d);
789                                 } else  {
790                                         ICONST(REG_ITMP1, -1);
791                                         M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
792                                         M_IADD(REG_ITMP1, d);
793                                 }
794
795                                 N_BRC_BACK_PATCH(ref);
796
797                                 M_SRA_IMM(iptr->sx.val.i, d);
798
799                                 emit_store_dst(jd, iptr, d);
800                         }
801
802                         break;
803         
804                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
805                                       /* sx.val.i = constant                             */
806
807                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
808                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
809
810                         if (s1 == d) {
811                                 M_MOV(s1, REG_ITMP1);
812                                 s1 = REG_ITMP1;
813                         }
814                                 
815                         ICONST(REG_ITMP3, iptr->sx.val.i);
816
817                         M_INTMOVE(s1, d);
818                         M_IAND(REG_ITMP3, d);
819
820                         M_TEST(s1);
821                         M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
822
823                         N_LCR(d, s1);
824                         N_NR(d, REG_ITMP3);
825                         N_LCR(d, d);
826
827                         emit_store_dst(jd, iptr, d);
828
829                         break;
830
831                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
832                                       /* sx.val.i = constant                             */
833                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
834                                       /* sx.val.i = constant                             */
835                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
836                                       /* sx.val.i = constant                             */
837                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
839
840                         M_INTMOVE(s1, d);
841
842                         disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
843
844                         switch (iptr->opc) {
845                                 case ICMD_ISHLCONST:
846                                         N_SLL(d, disp, RN);
847                                         break;
848                                 case ICMD_ISHRCONST:
849                                         N_SRA(d, disp, RN);
850                                         break;
851                                 case ICMD_IUSHRCONST:
852                                         N_SRL(d, disp, RN);
853                                         break;
854                                 default:
855                                         assert(0);
856                         }
857
858                         emit_store_dst(jd, iptr, d);
859                         break;
860
861                 case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
862
863                 case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
864
865                 case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
866
867                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
868
869                         /* Use only 6 bits of second operand */
870
871                         M_INTMOVE(s2, REG_ITMP2);
872                         s2 = REG_ITMP2;
873                         ICONST(REG_ITMP1, 0x3F);
874                         M_IAND(REG_ITMP1, s2);
875
876                         s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
877                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
878
879                         /* Destination must be even-odd pair */
880
881                         if (! N_IS_EVEN_ODD(d)) {
882                                 d = REG_ITMP31_PACKED;
883                         }
884
885                         assert(N_IS_EVEN_ODD(d));
886
887                         M_LNGMOVE(s1, d);
888
889                         switch (iptr->opc) {
890                                 case ICMD_LSHL:
891                                         M_SLDL(s2, GET_HIGH_REG(d));
892                                         break;
893                                 case ICMD_LSHR:
894                                         M_SRDA(s2, GET_HIGH_REG(d));
895                                         break;
896                                 case ICMD_LUSHR:
897                                         M_SRDL(s2, GET_HIGH_REG(d));
898                                         break;
899                                 default:
900                                         assert(0);
901                         }
902
903                         emit_copy_dst(jd, iptr, d);
904                         emit_store_dst(jd, iptr, d);
905
906                         break;
907
908         case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
909                                           /* sx.val.i = constant                             */
910                 case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
911                                       /* sx.val.i = constant                             */
912                 case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
913                                       /* sx.val.l = constant                             */
914                 case ICMD_LMULPOW2:
915                 
916                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
917                         if (! N_IS_EVEN_ODD(d)) {
918                                 d = REG_ITMP31_PACKED;
919                         }
920                         assert(N_IS_EVEN_ODD(d));
921
922                         s1 = emit_load_s1(jd, iptr, d);
923                 
924                         M_LNGMOVE(s1, d);
925
926                         disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
927
928                         switch (iptr->opc) {
929                                 case ICMD_LSHLCONST:
930                                         N_SLDL(GET_HIGH_REG(d), disp, RN);
931                                         break;
932                                 case ICMD_LSHRCONST:
933                                         N_SRDA(GET_HIGH_REG(d), disp, RN);
934                                         break;
935                                 case ICMD_LUSHRCONST:
936                                         N_SRDL(GET_HIGH_REG(d), disp, RN);
937                                         break;
938                                 case ICMD_LMULPOW2:
939                                         N_SLDL(GET_HIGH_REG(d), disp, RN);
940                                         break;
941                                 default:
942                                         assert(0);
943                         }
944
945                         emit_copy_dst(jd, iptr, d);
946                         emit_store_dst(jd, iptr, d);
947                         break;
948
949                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
950
951                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
952                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
953                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
954                         if (s2 == d)
955                                 M_IAND(s1, d);
956                         else {
957                                 M_INTMOVE(s1, d);
958                                 M_IAND(s2, d);
959                         }
960                         emit_store_dst(jd, iptr, d);
961
962                         break;
963
964                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
965
966                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
967                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
968                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
969                         if (s2 == d)
970                                 M_IOR(s1, d);
971                         else {
972                                 M_INTMOVE(s1, d);
973                                 M_IOR(s2, d);
974                         }
975                         emit_store_dst(jd, iptr, d);
976
977                         break;
978
979                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
980
981                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
982                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
983                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
984                         if (s2 == d)
985                                 M_IXOR(s1, d);
986                         else {
987                                 M_INTMOVE(s1, d);
988                                 M_IXOR(s2, d);
989                         }
990                         emit_store_dst(jd, iptr, d);
991
992                         break;
993
994
995
996                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
997                                       /* sx.val.i = constant                             */
998                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
999                                       /* sx.val.i = constant                             */
1000                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1001                                       /* sx.val.i = constant                             */
1002
1003                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1004                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1005
1006                         M_INTMOVE(s1, d);
1007                         ICONST(REG_ITMP2, iptr->sx.val.i);
1008
1009                         switch (iptr->opc) {
1010                                 case ICMD_IANDCONST:
1011                                         M_IAND(REG_ITMP2, d);
1012                                         break;
1013                                 case ICMD_IXORCONST:
1014                                         M_IXOR(REG_ITMP2, d);
1015                                         break;
1016                                 case ICMD_IORCONST:
1017                                         M_IOR(REG_ITMP2, d);
1018                                         break;
1019                                 default:
1020                                         assert(0);
1021                         }
1022
1023                         emit_store_dst(jd, iptr, d);
1024
1025                         break;
1026
1027                 case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1028                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1029                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1030
1031                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1032
1033                         s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1034                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1035                         dd = GET_LOW_REG(d);
1036
1037                         switch (iptr->opc) {
1038                                 case ICMD_LAND:
1039                                         if (s2 == dd) {
1040                                                 M_IAND(s1, dd);
1041                                         } else {
1042                                                 M_INTMOVE(s1, dd);
1043                                                 M_IAND(s2, dd);
1044                                         }
1045                                         break;
1046                                 case ICMD_LXOR:
1047                                         if (s2 == dd) {
1048                                                 M_IXOR(s1, dd);
1049                                         } else {
1050                                                 M_INTMOVE(s1, dd);
1051                                                 M_IXOR(s2, dd);
1052                                         }
1053                                         break;
1054                                 case ICMD_LOR:
1055                                         if (s2 == dd) {
1056                                                 M_IOR(s1, dd);
1057                                         } else {
1058                                                 M_INTMOVE(s1, dd);
1059                                                 M_IOR(s2, dd);
1060                                         }
1061                                         break;
1062                                 default:
1063                                         assert(0);
1064                         }
1065
1066                         s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1067                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1068                         dd = GET_HIGH_REG(d);
1069
1070                         switch (iptr->opc) {
1071                                 case ICMD_LAND:
1072                                         if (s2 == dd) {
1073                                                 M_IAND(s1, dd);
1074                                         } else {
1075                                                 M_INTMOVE(s1, dd);
1076                                                 M_IAND(s2, dd);
1077                                         }
1078                                         break;
1079                                 case ICMD_LXOR:
1080                                         if (s2 == dd) {
1081                                                 M_IXOR(s1, dd);
1082                                         } else {
1083                                                 M_INTMOVE(s1, dd);
1084                                                 M_IXOR(s2, dd);
1085                                         }
1086                                         break;
1087                                 case ICMD_LOR:
1088                                         if (s2 == dd) {
1089                                                 M_IOR(s1, dd);
1090                                         } else {
1091                                                 M_INTMOVE(s1, dd);
1092                                                 M_IOR(s2, dd);
1093                                         }
1094                                         break;
1095                                 default:
1096                                         assert(0);
1097                         }
1098
1099                         emit_store_dst(jd, iptr, d);
1100                         break;
1101
1102                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1103                                       /* sx.val.l = constant                             */
1104                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1105                                       /* sx.val.l = constant                             */
1106                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1107                                       /* sx.val.l = constant                             */
1108
1109                         /* TODO should use memory operand to access data segment, not load */
1110
1111                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1112
1113                         s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1114                         s3 = iptr->sx.val.l & 0xffffffff;
1115
1116                         M_INTMOVE(s1, GET_LOW_REG(d));
1117
1118                         ICONST(REG_ITMP3, s3);
1119
1120                         switch (iptr->opc) {
1121                                 case ICMD_LANDCONST:
1122                                         M_IAND(REG_ITMP3, GET_LOW_REG(d));
1123                                         break;
1124                                 case ICMD_LXORCONST:
1125                                         M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1126                                         break;
1127                                 case ICMD_LORCONST:
1128                                         M_IOR(REG_ITMP3, GET_LOW_REG(d));
1129                                         break;
1130                                 default:
1131                                         assert(0);
1132                         }
1133
1134                         s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1135                         s3 = iptr->sx.val.l >> 32;
1136
1137                         M_INTMOVE(s1, GET_HIGH_REG(d));
1138
1139                         ICONST(REG_ITMP3, s3);
1140
1141                         switch (iptr->opc) {
1142                                 case ICMD_LANDCONST:
1143                                         M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1144                                         break;
1145                                 case ICMD_LXORCONST:
1146                                         M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1147                                         break;
1148                                 case ICMD_LORCONST:
1149                                         M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1150                                         break;
1151                                 default:
1152                                         assert(0);
1153                         }
1154
1155                         emit_store_dst(jd, iptr, d);
1156
1157                         break;
1158
1159                 /* floating operations ************************************************/
1160
1161                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1162                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1163                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1164                         M_FMOVN(s1, d);
1165                         emit_store_dst(jd, iptr, d);
1166                         break;
1167
1168                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1169                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1170                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1171                         M_DMOVN(s1, d);
1172                         emit_store_dst(jd, iptr, d);
1173                         break;
1174
1175                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1176                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1177                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1178                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1179                         if (s2 == d)
1180                                 M_FADD(s1, d);
1181                         else {
1182                                 emit_fmove(cd, s1, d);
1183                                 M_FADD(s2, d);
1184                         }
1185                         emit_store_dst(jd, iptr, d);
1186                         break;
1187
1188                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1189                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1190                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1191                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1192                         if (s2 == d)
1193                                 M_DADD(s1, d);
1194                         else {
1195                                 emit_fmove(cd, s1, d);
1196                                 M_DADD(s2, d);
1197                         }
1198                         emit_store_dst(jd, iptr, d);
1199                         break;
1200
1201                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1202                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1203                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1204                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1205
1206                         emit_fmove(cd, s1, d);
1207                         M_FSUB(s2, d);
1208                         emit_store_dst(jd, iptr, d);
1209                         break;
1210
1211                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1212                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1213                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1214                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1215
1216                         emit_fmove(cd, s1, d);
1217                         M_DSUB(s2, d);
1218                         emit_store_dst(jd, iptr, d);
1219                         break;
1220
1221                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1222                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1223                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1224                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1225                         if (s2 == d)
1226                                 M_FMUL(s1, d);
1227                         else {
1228                                 emit_fmove(cd, s1, d);
1229                                 M_FMUL(s2, d);
1230                         }
1231                         emit_store_dst(jd, iptr, d);
1232                         break;
1233
1234                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1235                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1236                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1237                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1238                         if (s2 == d)
1239                                 M_DMUL(s1, d);
1240                         else {
1241                                 emit_fmove(cd, s1, d);
1242                                 M_DMUL(s2, d);
1243                         }
1244                         emit_store_dst(jd, iptr, d);
1245                         break;
1246
1247                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1248                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1249                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1250                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1251
1252                         emit_fmove(cd, s1, d);
1253                         M_FDIV(s2, d);
1254                         emit_store_dst(jd, iptr, d);
1255                         break;
1256
1257                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1258                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1259                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1260                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1261
1262                         emit_fmove(cd, s1, d);
1263                         M_DDIV(s2, d);
1264                         emit_store_dst(jd, iptr, d);
1265                         break;
1266
1267                 case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
1268                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1269                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1270                         M_CVTIF(s1, d);
1271                         emit_store_dst(jd, iptr, d);
1272                         break;
1273
1274                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
1275                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1276                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1277                         M_CVTID(s1, d);
1278                         emit_store_dst(jd, iptr, d);
1279                         break;
1280
1281                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1282                 case ICMD_D2I:
1283                         {
1284                                 u1 *ref1;
1285 #ifdef SUPPORT_HERCULES
1286                                 u1 *ref2, *ref3;
1287 #endif
1288
1289                                 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1290                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1291
1292                                 /* Test if NAN */
1293
1294                                 switch (iptr->opc) {
1295                                         case ICMD_F2I:
1296                                                 N_LTEBR(s1, s1); 
1297                                                 break;
1298                                         case ICMD_D2I:
1299                                                 N_LTDBR(s1, s1);
1300                                                 break;
1301                                 }
1302
1303                                 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1304                                 N_LHI(d, 0); /* Load 0 */
1305                                 ref1 = cd->mcodeptr;
1306                                 N_BRC(DD_ANY, 0); /* Exit */
1307
1308                                 /* Convert */
1309
1310                                 switch (iptr->opc) {
1311                                         case ICMD_F2I:
1312                                                 M_CVTFI(s1, d); 
1313                                                 break;
1314                                         case ICMD_D2I:
1315                                                 M_CVTDI(s1, d); 
1316                                                 break;
1317                                 }
1318
1319 #ifdef SUPPORT_HERCULES
1320                                 /* Hercules does the conversion using a plain C conversion.
1321                                  * According to manual, real hardware should *NOT* require this.
1322                                  *
1323                                  * Corner case: Positive float leads to INT_MIN (overflow).
1324                                  */
1325
1326                                 switch (iptr->opc) {
1327                                         case ICMD_F2I:
1328                                                 N_LTEBR(s1, s1); 
1329                                                 break;
1330                                         case ICMD_D2I:
1331                                                 N_LTDBR(s1, s1);
1332                                                 break;
1333                                 }
1334
1335                                 ref2 = cd->mcodeptr;
1336                                 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1337
1338                                 M_TEST(d);
1339
1340                                 ref3 = cd->mcodeptr;
1341                                 M_BGE(0); /* If integer result is negative, continue */
1342
1343                                 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1344                                 M_ILD_DSEG(d, disp);
1345 #endif
1346                                 N_BRC_BACK_PATCH(ref1);
1347 #ifdef SUPPORT_HERCULES
1348                                 N_BRC_BACK_PATCH(ref2);
1349                                 N_BRC_BACK_PATCH(ref3);
1350 #endif
1351                                 emit_store_dst(jd, iptr, d);
1352                         }
1353                         break;
1354
1355                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1356                         {
1357 #ifdef SUPPORT_HERCULES
1358                                 u1 *ref;
1359 #endif
1360                                 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1361                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1362 #ifdef SUPPORT_HERCULES
1363                                 N_LTEBR(s1, s1);
1364                                 ref = cd->mcodeptr;
1365                                 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1366                                 disp = dseg_add_double(cd, 0.0 / 0.0);
1367                                 M_DLD_DSEG(d, disp, REG_ITMP1);
1368                                 emit_label_br(cd, BRANCH_LABEL_1);
1369                                 N_BRC_BACK_PATCH(ref);
1370 #endif
1371                                 M_CVTFD(s1, d);
1372 #ifdef SUPPORT_HERCULES
1373                                 emit_label(cd, BRANCH_LABEL_1);
1374 #endif
1375                                 emit_store_dst(jd, iptr, d);
1376                         }
1377                         break;
1378
1379                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
1380                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1381                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1382                         M_CVTDF(s1, d);
1383                         emit_store_dst(jd, iptr, d);
1384                         break;
1385
1386                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1387                                           /* == => 0, < => 1, > => -1 */
1388                 case ICMD_DCMPL:
1389
1390
1391                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1392                                           /* == => 0, < => 1, > => -1 */
1393                 case ICMD_DCMPG:
1394
1395                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1396                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1397                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1398
1399                         switch (iptr->opc) {
1400                                 case ICMD_FCMPG:
1401                                 case ICMD_FCMPL:
1402                                         M_FCMP(s1, s2);
1403                                         break;
1404                                 case ICMD_DCMPG:
1405                                 case ICMD_DCMPL:
1406                                         M_DCMP(s1, s2);
1407                                         break;  
1408                         }
1409
1410                         N_BRC( /* load 1 */
1411                                 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1412                                 SZ_BRC + SZ_BRC + SZ_BRC
1413                         );
1414
1415                         N_BRC( /* load -1 */
1416                                 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1417                                 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1418                         );
1419
1420                         N_BRC( /* load 0 */
1421                                 DD_E,
1422                                 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1423                         );
1424
1425                         N_LHI(d, 1); /* GT */
1426                         M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1427                         N_LHI(d, -1); /* LT */
1428                         M_BR(SZ_BRC + SZ_LHI);
1429                         N_LHI(d, 0); /* EQ */
1430
1431                         emit_store_dst(jd, iptr, d);
1432
1433                         break;
1434
1435
1436                 /* memory operations **************************************************/
1437
1438                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1439                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1440                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1441                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1442
1443                         /* implicit null-pointer check */
1444                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1445
1446                         N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1447
1448                         M_SLL_IMM(24, d);
1449                         M_SRA_IMM(24, d);
1450
1451                         emit_store_dst(jd, iptr, d);
1452                         break;
1453
1454                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1455
1456                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1457                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1458                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1459
1460                         /* implicit null-pointer check */
1461                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1462
1463                         M_INTMOVE(s2, REG_ITMP2);
1464                         M_SLL_IMM(1, REG_ITMP2);
1465
1466                         N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1467
1468                         /* N_LH does sign extends, undo ! */
1469
1470                         M_SLL_IMM(16, d);
1471                         M_SRL_IMM(16, d);
1472
1473                         emit_store_dst(jd, iptr, d);
1474                         break;                  
1475
1476                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1477                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1478                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1479                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1480
1481                         /* implicit null-pointer check */
1482                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1483
1484                         M_INTMOVE(s2, REG_ITMP2);
1485                         M_SLL_IMM(1, REG_ITMP2);
1486
1487                         N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1488                         emit_store_dst(jd, iptr, d);
1489                         break;
1490
1491                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1492                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1493                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1494                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1495
1496                         /* implicit null-pointer check */
1497                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1498                         
1499                         M_INTMOVE(s2, REG_ITMP2);
1500                         M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1501                         N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1502                         emit_store_dst(jd, iptr, d);
1503                         break;
1504
1505                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1506
1507                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1508                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1509
1510                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1511
1512                         /* implicit null-pointer check */
1513                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1514                         
1515                         M_INTMOVE(s2, REG_ITMP2);
1516                         M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1517
1518                         N_L(
1519                                 GET_LOW_REG(d) /* maybe itmp3 */, 
1520                                 OFFSET(java_longarray_t, data[0]) + 4, 
1521                                 REG_ITMP2, s1 /* maybe itmp1 */
1522                         );
1523
1524                         N_L(
1525                                 GET_HIGH_REG(d) /* maybe itmp1 */, 
1526                                 OFFSET(java_longarray_t, data[0]), 
1527                                 REG_ITMP2, s1 /* maybe itmp1 */
1528                         );
1529
1530                         emit_store_dst(jd, iptr, d);
1531
1532                         break;
1533
1534                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1535
1536                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1537                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1538                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1539
1540                         /* implicit null-pointer check */
1541                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1542
1543                         M_INTMOVE(s2, REG_ITMP2);
1544                         M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1545         
1546                         N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1547
1548                         emit_store_dst(jd, iptr, d);
1549                         break;
1550
1551                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1552                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1553                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1554                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1555
1556                         /* implicit null-pointer check */
1557                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1558
1559                         M_INTMOVE(s2, REG_ITMP2);
1560                         M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1561         
1562                         N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1563
1564                         emit_store_dst(jd, iptr, d);
1565                         break;
1566
1567                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1568                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1569                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1570                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1571
1572                         /* implicit null-pointer check */
1573                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1574                         
1575                         M_INTMOVE(s2, REG_ITMP2);
1576                         M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1577                         N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1578                         emit_store_dst(jd, iptr, d);
1579                         break;
1580
1581                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1582                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1583                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1584                         /* implicit null-pointer check */
1585                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1586                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1587
1588                         N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1589                         break;
1590
1591                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1592
1593                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1594                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1595                         /* implicit null-pointer check */
1596                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1597                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1598
1599                         M_INTMOVE(s2, REG_ITMP2);
1600                         M_SLL_IMM(1, REG_ITMP2);
1601
1602                         N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1603
1604                         break;
1605
1606                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1607                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1608                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1609                         /* implicit null-pointer check */
1610                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1611                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1612
1613                         M_INTMOVE(s2, REG_ITMP2);
1614                         M_SLL_IMM(1, REG_ITMP2);
1615
1616                         N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1617                         break;
1618
1619                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1620
1621                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1622                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1623                         /* implicit null-pointer check */
1624                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1625
1626                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1627
1628                         M_INTMOVE(s2, REG_ITMP2);
1629                         M_SLL_IMM(2, REG_ITMP2);
1630
1631                         N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1632                         break;
1633
1634                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1635
1636                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1637                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1638                         /* implicit null-pointer check */
1639                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1640
1641                         M_INTMOVE(s2, REG_ITMP2);
1642                         M_SLL_IMM(3, REG_ITMP2);
1643
1644                         s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1645                         N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
1646                         s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1647                         N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
1648                         break;
1649
1650                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1651                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1652                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1653                         /* implicit null-pointer check */
1654                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1655                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1656
1657                         M_INTMOVE(s2, REG_ITMP2);
1658                         M_SLL_IMM(2, REG_ITMP2);
1659
1660                         N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1661                         break;
1662
1663                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1664                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1665                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1666                         /* implicit null-pointer check */
1667                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1668                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1669
1670                         M_INTMOVE(s2, REG_ITMP2);
1671                         M_SLL_IMM(3, REG_ITMP2);
1672
1673                         N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1674                         break;
1675
1676                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1677
1678                         s1 = emit_load_s1(jd, iptr, REG_A0);
1679                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1680                         /* implicit null-pointer check */
1681                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1682                         s3 = emit_load_s3(jd, iptr, REG_A1);
1683
1684                         M_INTMOVE(s1, REG_A0);
1685                         M_INTMOVE(s3, REG_A1);
1686
1687                         disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1688                         M_ALD_DSEG(REG_ITMP2, disp);
1689                         M_ASUB_IMM(96, REG_SP);
1690                         M_JSR(REG_RA, REG_ITMP2);
1691                         M_AADD_IMM(96, REG_SP);
1692
1693                         emit_arraystore_check(cd, iptr);
1694
1695                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1696                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1697                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1698
1699                         M_INTMOVE(s2, REG_ITMP2);
1700                         M_SLL_IMM(2, REG_ITMP2);
1701                         N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1702
1703                         /*
1704                         M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1705                         M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1706                         */
1707                         break;
1708
1709                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1710
1711                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1712                         emit_nullpointer_check(cd, iptr, s1);
1713
1714                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1715                                 uf        = iptr->sx.s23.s3.uf;
1716                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1717                                 disp      = 0;
1718
1719                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1720                         }
1721                         else {
1722                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1723                                 fieldtype = fi->type;
1724                                 disp      = fi->offset;
1725                         }
1726
1727                         switch (fieldtype) {
1728                         case TYPE_INT:
1729                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1730                                 M_ILD(d, s1, disp);
1731                                 break;
1732                         case TYPE_LNG:
1733                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1734                                 if (GET_HIGH_REG(d) == s1) {
1735                                         M_ILD(GET_LOW_REG(d), s1, disp + 4);
1736                                         M_ILD(GET_HIGH_REG(d), s1, disp);
1737                                 }
1738                                 else {
1739                                         M_ILD(GET_LOW_REG(d), s1, disp + 4);
1740                                         M_ILD(GET_HIGH_REG(d), s1, disp);
1741                                 }
1742                                 break;
1743                         case TYPE_ADR:
1744                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1745                                 M_ALD(d, s1, disp);
1746                                 break;
1747                         case TYPE_FLT:
1748                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1749                                 M_FLD(d, s1, disp);
1750                                 break;
1751                         case TYPE_DBL:                          
1752                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1753                                 M_DLD(d, s1, disp);
1754                                 break;
1755                         }
1756                         emit_store_dst(jd, iptr, d);
1757                         break;
1758
1759                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
1760                         {
1761                         u1 *ref;
1762
1763                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1764                         emit_nullpointer_check(cd, iptr, s1);
1765
1766                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1767                                 uf        = iptr->sx.s23.s3.uf;
1768                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1769                                 disp      = 0;
1770                         } 
1771                         else {
1772                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1773                                 fieldtype = fi->type;
1774                                 disp      = fi->offset;
1775                         }
1776
1777                         /* We can't add a patcher ref behind this load,
1778                          * because the patcher would destroy REG_ITMP3.
1779                          *
1780                          * We pass in the disp parameter, how many bytes
1781                          * to skip to the to the actual store.
1782                          *
1783                          * XXX this relies on patcher_add_patch_ref internals
1784                          */
1785
1786                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1787                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1788                                 ref = cd->mcodeptr;
1789                         }
1790
1791
1792                         if (IS_INT_LNG_TYPE(fieldtype)) {
1793                                 if (IS_2_WORD_TYPE(fieldtype))
1794                                         s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1795                                 else
1796                                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1797                         } else {
1798                                 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1799                         }
1800
1801                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1802                                 ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
1803                         }
1804
1805                         switch (fieldtype) {
1806                                 case TYPE_INT:
1807                                         M_IST(s2, s1, disp);
1808                                         break;
1809                                 case TYPE_LNG:
1810                                         M_IST(GET_LOW_REG(s2), s1, disp + 4);      /* keep this order */
1811                                         M_IST(GET_HIGH_REG(s2), s1, disp);         /* keep this order */
1812                                         break;
1813                                 case TYPE_ADR:
1814                                         M_AST(s2, s1, disp);
1815                                         break;
1816                                 case TYPE_FLT:
1817                                         M_FST(s2, s1, disp);
1818                                         break;
1819                                 case TYPE_DBL:
1820                                         M_DST(s2, s1, disp);
1821                                         break;
1822                         }
1823
1824                         }
1825                         break;
1826
1827                 /* branch operations **************************************************/
1828
1829                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1830
1831                         disp = dseg_add_functionptr(cd, asm_handle_exception);
1832                         M_ALD_DSEG(REG_ITMP1, disp);
1833                         M_JMP(REG_ITMP1_XPC, REG_ITMP1);
1834                         M_NOP;
1835
1836                         break;
1837
1838                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
1839                 case ICMD_IF_LLE:       /* op1 = target JavaVM pc, val.l = constant   */
1840                 case ICMD_IF_LGT:
1841                 case ICMD_IF_LGE:
1842                 case ICMD_IF_LEQ:
1843                 case ICMD_IF_LNE:
1844
1845                         /* ATTENTION: compare high words signed and low words unsigned */
1846
1847 #                       define LABEL_OUT BRANCH_LABEL_1
1848
1849                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1850
1851                         if (N_VALID_IMM(iptr->sx.val.l >> 32))
1852                                 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
1853                         else {
1854                                 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
1855                                 if (N_VALID_DSEG_DISP(disp)) {
1856                                         N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
1857                                 } else {
1858                                         ICONST(REG_ITMP2, disp);
1859                                         N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
1860                                 }
1861                         }
1862
1863                         switch(iptr->opc) {
1864                                 case ICMD_IF_LLT:
1865                                 case ICMD_IF_LLE:
1866                                         emit_blt(cd, iptr->dst.block);
1867                                         /* EQ ... fall through */
1868                                         emit_label_bgt(cd, LABEL_OUT);
1869                                         break;
1870                                 case ICMD_IF_LGT:
1871                                 case ICMD_IF_LGE:
1872                                         emit_bgt(cd, iptr->dst.block);
1873                                         /* EQ ... fall through */
1874                                         emit_label_blt(cd, LABEL_OUT);
1875                                         break;
1876                                 case ICMD_IF_LEQ: 
1877                                         /* EQ ... fall through */
1878                                         emit_label_bne(cd, LABEL_OUT);
1879                                         break;
1880                                 case ICMD_IF_LNE:
1881                                         /* EQ ... fall through */
1882                                         emit_bne(cd, iptr->dst.block);
1883                                         break;
1884                                 default:
1885                                         assert(0);
1886                         }
1887
1888                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1889
1890                         disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
1891                         if (N_VALID_DSEG_DISP(disp)) {
1892                                 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
1893                         } else {
1894                                 ICONST(REG_ITMP2, disp);
1895                                 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
1896                         }
1897
1898                         switch(iptr->opc) {
1899                                 case ICMD_IF_LLT:
1900                                         emit_blt(cd, iptr->dst.block);
1901                                         emit_label(cd, LABEL_OUT);
1902                                         break;
1903                                 case ICMD_IF_LLE:
1904                                         emit_ble(cd, iptr->dst.block);
1905                                         emit_label(cd, LABEL_OUT);
1906                                         break;
1907                                 case ICMD_IF_LGT:
1908                                         emit_bgt(cd, iptr->dst.block);
1909                                         emit_label(cd, LABEL_OUT);
1910                                         break;
1911                                 case ICMD_IF_LGE:
1912                                         emit_bge(cd, iptr->dst.block);
1913                                         emit_label(cd, LABEL_OUT);
1914                                         break;
1915                                 case ICMD_IF_LEQ:
1916                                         emit_beq(cd, iptr->dst.block);
1917                                         emit_label(cd, LABEL_OUT);
1918                                         break;
1919                                 case ICMD_IF_LNE:
1920                                         emit_bne(cd, iptr->dst.block);
1921                                         break;
1922                                 default:
1923                                         assert(0);
1924                         }
1925
1926 #                       undef LABEL_OUT
1927                         break;
1928
1929                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
1930                 case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
1931
1932                         /* Compare addresses as 31 bit unsigned integers */
1933
1934                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1935                         M_LDA(REG_ITMP1, s1, 0);
1936
1937                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1938                         M_LDA(REG_ITMP2, s2, 0);
1939
1940                         M_CMP(REG_ITMP1, REG_ITMP2);
1941
1942                         switch (iptr->opc) {
1943                                 case ICMD_IF_ACMPEQ:
1944                                         emit_beq(cd, iptr->dst.block);
1945                                         break;
1946                                 case ICMD_IF_ACMPNE:
1947                                         emit_bne(cd, iptr->dst.block);
1948                                         break;
1949                         }
1950
1951                         break;
1952
1953                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
1954                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
1955                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
1956                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
1957                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
1958                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
1959                         {
1960
1961                                 u1 *out_ref = NULL;
1962
1963                                 /* ATTENTION: compare high words signed and low words unsigned */
1964         
1965                                 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1966                                 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1967
1968                                 M_ICMP(s1, s2);
1969
1970                                 switch(iptr->opc) {
1971                                 case ICMD_IF_LCMPLT:
1972                                 case ICMD_IF_LCMPLE:
1973                                         emit_blt(cd, iptr->dst.block);
1974                                         /* EQ ... fall through */
1975                                         out_ref = cd->mcodeptr;
1976                                         M_BGT(0);
1977                                         break;
1978                                 case ICMD_IF_LCMPGT:
1979                                 case ICMD_IF_LCMPGE:
1980                                         emit_bgt(cd, iptr->dst.block);
1981                                         /* EQ ... fall through */
1982                                         out_ref = cd->mcodeptr;
1983                                         M_BLT(0);
1984                                         break;
1985                                 case ICMD_IF_LCMPEQ: 
1986                                         /* EQ ... fall through */
1987                                         out_ref = cd->mcodeptr;
1988                                         M_BNE(0);
1989                                         break;
1990                                 case ICMD_IF_LCMPNE:
1991                                         /* EQ ... fall through */
1992                                         emit_bne(cd, iptr->dst.block);
1993                                         break;
1994                                 default:
1995                                         assert(0);
1996                                 }
1997
1998                                 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1999                                 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2000         
2001                                 M_ICMPU(s1, s2);
2002
2003                                 switch(iptr->opc) {
2004                                 case ICMD_IF_LCMPLT:
2005                                         emit_blt(cd, iptr->dst.block);
2006                                         break;
2007                                 case ICMD_IF_LCMPLE:
2008                                         emit_ble(cd, iptr->dst.block);
2009                                         break;
2010                                 case ICMD_IF_LCMPGT:
2011                                         emit_bgt(cd, iptr->dst.block);
2012                                         break;
2013                                 case ICMD_IF_LCMPGE:
2014                                         emit_bge(cd, iptr->dst.block);
2015                                         break;
2016                                 case ICMD_IF_LCMPEQ:
2017                                         emit_beq(cd, iptr->dst.block);
2018                                         break;
2019                                 case ICMD_IF_LCMPNE:
2020                                         emit_bne(cd, iptr->dst.block);
2021                                         break;
2022                                 default:
2023                                         assert(0);
2024                                 }
2025
2026                                 if (out_ref != NULL) {
2027                                         N_BRC_BACK_PATCH(out_ref);
2028                                 }
2029
2030                         }
2031                         break;
2032
2033                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2034                         {
2035                                 s4 i, l;
2036                                 branch_target_t *table;
2037
2038                                 table = iptr->dst.table;
2039
2040                                 l = iptr->sx.s23.s2.tablelow;
2041                                 i = iptr->sx.s23.s3.tablehigh;
2042
2043                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2044                                 M_INTMOVE(s1, REG_ITMP1);
2045
2046                                 if (l == 0) {
2047                                         /* do nothing */
2048                                 } else if (N_VALID_IMM(-l)) {
2049                                         M_ISUB_IMM(l, REG_ITMP1);
2050                                 } else {
2051                                         ICONST(REG_ITMP2, l);
2052                                         M_ISUB(REG_ITMP2, REG_ITMP1);
2053                                 }
2054
2055                                 /* number of targets */
2056
2057                                 i = i - l + 1;
2058
2059                                 /* range check */
2060
2061                                 ICONST(REG_ITMP2, i);
2062                                 M_ICMPU(REG_ITMP1, REG_ITMP2);
2063                                 emit_bge(cd, table[0].block);
2064
2065                                 /* build jump table top down and use address of lowest entry */
2066
2067                                 table += i;
2068
2069                                 while (--i >= 0) {
2070                                         dseg_add_target(cd, table->block); 
2071                                         --table;
2072                                 }
2073                         }
2074
2075                         /* length of dataseg after last dseg_add_target is used by load */
2076
2077                         M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2078                         M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2079                         N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2080                         M_JMP(RN, REG_ITMP1);
2081
2082                         break;
2083
2084
2085                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
2086                         bte = iptr->sx.s23.s3.bte;
2087                         if (bte->stub == NULL) {
2088                                 disp = dseg_add_functionptr(cd, bte->fp);
2089                                 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */   
2090                         } else {
2091                                 disp = dseg_add_functionptr(cd, bte->stub);
2092                         }
2093
2094                         if (N_VALID_DSEG_DISP(disp)) {
2095                                 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2096                         } else {
2097                                 N_LHI(REG_ITMP1, disp);
2098                                 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2099                         }
2100
2101                         /* generate the actual call */
2102                         M_CALL(REG_PV);
2103
2104                         /* post call finalization */
2105                         if (bte->stub == NULL) {
2106                                 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2107                         }
2108                         break;
2109
2110                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2111                                 /* TODO softnull */
2112                                 /* Implicit NULL pointer check */
2113                                 M_ILD(REG_ITMP1, REG_A0, 0);
2114                                 /* fall through */
2115
2116                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2117                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2118                                 um = iptr->sx.s23.s3.um;
2119                                 disp = dseg_add_unique_address(cd, um);
2120
2121                                 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2122                                                                         um, disp);
2123                         }
2124                         else {
2125                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2126                                 disp = dseg_add_address(cd, lm->stubroutine);
2127                         }
2128
2129                         if (N_VALID_DSEG_DISP(disp)) {
2130                                 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2131                         } else {
2132                                 N_LHI(REG_ITMP1, disp);
2133                                 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2134                         }
2135
2136                         /* generate the actual call */
2137                         M_CALL(REG_PV);
2138                         break;
2139
2140                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2141                         /* TODO softnull REG_A0 */
2142
2143                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2144                                 um = iptr->sx.s23.s3.um;
2145                                 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2146
2147                                 s1 = 0;
2148                         }
2149                         else {
2150                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2151                                 s1 = OFFSET(vftbl_t, table[0]) +
2152                                         sizeof(methodptr) * lm->vftblindex;
2153                         }
2154
2155                         /* implicit null-pointer check */
2156
2157                         M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2158                         M_ALD(REG_PV, REG_METHODPTR, s1);
2159
2160                         /* generate the actual call */
2161                         M_CALL(REG_PV);
2162                         break;
2163
2164                 case ICMD_INVOKEINTERFACE:
2165                         /* TODO softnull REG_A0 */
2166
2167                         /* s1 will be negative here, so use (0xFFF + s1) as displacement
2168                          * and -0xFFF in index register (itmp1)
2169                          */
2170
2171                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2172                                 um = iptr->sx.s23.s3.um;
2173                                 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2174
2175                                 s1 = 0;
2176                                 s2 = 0;
2177                         }
2178                         else {
2179                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2180                                 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2181                                         sizeof(methodptr*) * lm->clazz->index;
2182
2183                                 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2184                         }
2185
2186                         /* Implicit null-pointer check */
2187                         M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2188                         N_LHI(REG_ITMP2, s1);
2189                         N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2190                         M_ALD(REG_PV, REG_METHODPTR, s2);
2191
2192                         /* generate the actual call */
2193                         M_CALL(REG_PV);
2194                         break;
2195
2196                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2197
2198                                       /* val.a: (classinfo*) superclass               */
2199
2200                         /*  superclass is an interface:
2201                          *      
2202                          *  OK if ((sub == NULL) ||
2203                          *         (sub->vftbl->interfacetablelength > super->index) &&
2204                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
2205                          *      
2206                          *  superclass is a class:
2207                          *      
2208                          *  OK if ((sub == NULL) || (0
2209                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2210                          *         super->vftbl->diffval));
2211                          */
2212
2213                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2214                                 /* object type cast-check */
2215
2216                                 classinfo *super;
2217                                 vftbl_t   *supervftbl;
2218                                 s4         superindex;
2219
2220 #                               define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2221 #                               define LABEL_CLASS BRANCH_LABEL_2
2222 #                               define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2223 #                               define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2224 #                               define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2225
2226                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2227                                         super = NULL;
2228                                         superindex = 0;
2229                                         supervftbl = NULL;
2230                                 }
2231                                 else {
2232                                         super = iptr->sx.s23.s3.c.cls;
2233                                         superindex = super->index;
2234                                         supervftbl = super->vftbl;
2235                                 }
2236
2237                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2238
2239                                 /* if class is not resolved, check which code to call */
2240
2241                                 if (super == NULL) {
2242                                         M_TEST(s1);
2243                                         emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2244
2245                                         disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
2246
2247                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2248                                                                                   iptr->sx.s23.s3.c.ref,
2249                                                                                   disp);
2250
2251                                         ICONST(REG_ITMP3, ACC_INTERFACE);
2252
2253                                         if (N_VALID_DSEG_DISP(disp)) {
2254                                                 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
2255                                         } else {
2256                                                 ICONST(REG_ITMP2, disp);
2257                                                 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2258                                         }
2259                                         emit_label_beq(cd, LABEL_CLASS);
2260                                 }
2261
2262                                 /* interface checkcast code */
2263
2264                                 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2265                                         if (super == NULL) {
2266                                                 patcher_add_patch_ref(jd,
2267                                                                                           PATCHER_checkcast_instanceof_interface,
2268                                                                                           iptr->sx.s23.s3.c.ref,
2269                                                                                           0);
2270                                         } else {
2271                                                 M_TEST(s1);
2272                                                 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2273                                         }
2274
2275                                         M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2276                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2277                                         M_ISUB_IMM(superindex, REG_ITMP3);
2278                                         emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
2279                                         N_AHI(
2280                                                 REG_ITMP2,
2281                                                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2282                                                         superindex * sizeof(methodptr*))
2283                                         );
2284                                         M_ALD(REG_ITMP2, REG_ITMP2, 0);
2285                                         emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
2286
2287                                         if (super == NULL) {
2288                                                 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
2289                                         }
2290                                 }
2291
2292                                 /* class checkcast code */
2293                                 
2294                                 if (super == NULL) {
2295                                         emit_label(cd, LABEL_CLASS);
2296                                 }
2297
2298                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2299                                         if (super == NULL) {
2300                                                 disp = dseg_add_unique_address(cd, NULL);
2301
2302                                                 patcher_add_patch_ref(jd,
2303                                                                                           PATCHER_resolve_classref_to_vftbl,
2304                                                                                           iptr->sx.s23.s3.c.ref,
2305                                                                                           disp);
2306                                         }
2307                                         else {
2308                                                 disp = dseg_add_address(cd, supervftbl);
2309                                                 M_TEST(s1);
2310                                                 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2311                                         }
2312
2313 #if 1
2314                                         /* REG_ITMP3 := baseval(s1) */
2315                                         M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2316                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2317
2318                                         /* REG_ITMP2 := baseval(class) */
2319                                         M_ALD_DSEG(REG_ITMP2, disp);
2320                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2321
2322                                         /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
2323                                         M_ISUB(REG_ITMP2, REG_ITMP3);
2324
2325                                         /* REG_ITMP2 := diffval(class) */
2326                                         M_ALD_DSEG(REG_ITMP2, disp);
2327                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2328
2329                                         M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
2330
2331                                         /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2332                                         /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2333                                         /* Branch if greater then */
2334 #else
2335                                         M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2336                                         M_ALD_DSEG(REG_ITMP3, disp);
2337
2338                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2339                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2340                                         M_ISUB(REG_ITMP3, REG_ITMP2);
2341                                         M_ALD_DSEG(REG_ITMP3, disp);
2342                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2343
2344                                         M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
2345                                         /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2346                                         /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2347                                         /* Branch if greater then */
2348 #endif
2349                                         emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
2350                                 }
2351
2352                                 if (super == NULL) {
2353                                         emit_label(cd, LABEL_EXIT_CHECK_NULL);
2354                                         emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
2355                                 } else if (super->flags & ACC_INTERFACE) {
2356                                         emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
2357                                 } else {
2358                                         emit_label(cd, LABEL_EXIT_CLASS_NULL);
2359                                 }
2360
2361                                 d = codegen_reg_of_dst(jd, iptr, s1);
2362
2363 #                               undef LABEL_EXIT_CHECK_NULL
2364 #                               undef LABEL_CLASS
2365 #                               undef LABEL_EXIT_INTERFACE_NULL
2366 #                               undef LABEL_EXIT_INTERFACE_DONE
2367 #                               undef LABEL_EXIT_CLASS_NULL
2368                         }
2369                         else {
2370                                 /* array type cast-check */
2371
2372                                 s1 = emit_load_s1(jd, iptr, REG_A0);
2373                                 M_INTMOVE(s1, REG_A0);
2374
2375                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2376                                         disp = dseg_add_unique_address(cd, NULL);
2377
2378                                         patcher_add_patch_ref(jd,
2379                                                                                   PATCHER_resolve_classref_to_classinfo,
2380                                                                                   iptr->sx.s23.s3.c.ref,
2381                                                                                   disp);
2382                                 }
2383                                 else
2384                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2385
2386                                 M_ALD_DSEG(REG_A1, disp);
2387                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2388                                 M_ALD_DSEG(REG_ITMP1, disp);
2389                                 M_ASUB_IMM(96, REG_SP);
2390                                 M_JSR(REG_RA, REG_ITMP1);
2391                                 M_AADD_IMM(96, REG_SP);
2392
2393                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2394                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2395
2396                                 d = codegen_reg_of_dst(jd, iptr, s1);
2397                         }
2398
2399                         M_INTMOVE(s1, d);
2400                         emit_store_dst(jd, iptr, d);
2401                         break;
2402
2403                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2404                                       /* val.a: (classinfo*) superclass               */
2405
2406                         /*  superclass is an interface:
2407                          *      
2408                          *  return (sub != NULL) &&
2409                          *         (sub->vftbl->interfacetablelength > super->index) &&
2410                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
2411                          *      
2412                          *  superclass is a class:
2413                          *      
2414                          *  return ((sub != NULL) && (0
2415                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2416                          *          super->vftbl->diffvall));
2417                          *
2418                          *  If superclass is unresolved, we include both code snippets 
2419                          *  above, a patcher resolves the class' flags and we select
2420                          *  the right code at runtime.
2421                          */
2422
2423                         {
2424                         classinfo *super;
2425                         vftbl_t   *supervftbl;
2426                         s4         superindex;
2427
2428                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2429                                 super = NULL;
2430                                 superindex = 0;
2431                                 supervftbl = NULL;
2432
2433                         } else {
2434                                 super = iptr->sx.s23.s3.c.cls;
2435                                 superindex = super->index;
2436                                 supervftbl = super->vftbl;
2437                         }
2438
2439 #                       define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2440 #                       define LABEL_CLASS BRANCH_LABEL_2
2441 #                       define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2442 #                       define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
2443 #                       define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
2444 #                       define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
2445
2446                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2447                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2448                         if (s1 == d) {
2449                                 M_MOV(s1, REG_ITMP1);
2450                                 s1 = REG_ITMP1;
2451                         }
2452
2453                         /* if class is not resolved, check which code to call */
2454
2455                         if (super == NULL) {
2456                                 M_CLR(d);
2457                                 
2458                                 M_TEST(s1);
2459                                 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2460
2461                                 disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
2462
2463                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2464                                                                           iptr->sx.s23.s3.c.ref, disp);
2465
2466                                 ICONST(REG_ITMP3, ACC_INTERFACE);
2467
2468                                 if (N_VALID_DSEG_DISP(disp)) {
2469                                         N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
2470                                 } else {
2471                                         ICONST(REG_ITMP2, disp);
2472                                         N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2473                                 }
2474
2475                                 emit_label_beq(cd, LABEL_CLASS);
2476                         }
2477
2478                         /* interface instanceof code */
2479
2480                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2481                                 if (super == NULL) {
2482                                         /* If d == REG_ITMP2, then it's destroyed in check
2483                                            code above. */
2484                                         if (d == REG_ITMP2)
2485                                                 M_CLR(d);
2486
2487                                         patcher_add_patch_ref(jd,
2488                                                                                   PATCHER_checkcast_instanceof_interface,
2489                                                                                   iptr->sx.s23.s3.c.ref, 0);
2490                                 }
2491                                 else {
2492                                         M_CLR(d);
2493                                         M_TEST(s1);
2494                                         emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2495                                 }
2496
2497                                 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2498                                 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2499                                 M_ISUB_IMM(superindex, REG_ITMP3);
2500
2501                                 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
2502
2503                                 N_AHI(
2504                                         REG_ITMP1,
2505                                         (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2506                                                 superindex * sizeof(methodptr*))
2507                                 );
2508                                 M_ALD(REG_ITMP1, REG_ITMP1, 0);
2509                                 
2510                                 /* d := (REG_ITMP1 != 0)  */
2511
2512                                 N_LTR(d, REG_ITMP1);
2513                                 M_BEQ(SZ_BRC + SZ_LHI);
2514                                 N_LHI(d, 1);
2515
2516                                 if (super == NULL) {
2517                                         emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
2518                                 }
2519                         }
2520
2521                         /* class instanceof code */
2522
2523                         if (super == NULL) {
2524                                 emit_label(cd, LABEL_CLASS);
2525                         }
2526
2527                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2528                                 if (super == NULL) {
2529                                         disp = dseg_add_unique_address(cd, NULL);
2530
2531                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2532                                                                                   iptr->sx.s23.s3.c.ref,
2533                                                                                   disp);
2534                                 }
2535                                 else {
2536                                         disp = dseg_add_address(cd, supervftbl);
2537
2538                                         M_CLR(d);
2539
2540                                         M_TEST(s1);
2541                                         emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2542                                 }
2543
2544                                 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2545                                 M_ALD_DSEG(REG_ITMP2, disp);
2546
2547                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2548                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2549                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2550
2551                                 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 :=  itmp1 (sub.baseval) - itmp3 (super.baseval) */
2552
2553                                 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
2554                                 N_LHI(d, 0);
2555                                 M_BGT(SZ_BRC + SZ_LHI);
2556                                 N_LHI(d, 1);
2557                         }
2558
2559                         if (super == NULL) {
2560                                 emit_label(cd, LABEL_EXIT_CHECK_NULL);
2561                                 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
2562                                 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
2563                         } else if (super->flags & ACC_INTERFACE) {
2564                                 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
2565                                 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
2566                         } else {
2567                                 emit_label(cd, LABEL_EXIT_CLASS_NULL);
2568                         }
2569
2570 #                       undef LABEL_EXIT_CHECK_NULL
2571 #                       undef LABEL_CLASS
2572 #                       undef LABEL_EXIT_INTERFACE_NULL
2573 #                       undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
2574 #                       undef LABEL_EXIT_INTERFACE_DONE
2575 #                       undef LABEL_EXIT_CLASS_NULL
2576                                 
2577                         emit_store_dst(jd, iptr, d);
2578
2579                         }
2580
2581                         break;
2582
2583                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2584
2585                         /* check for negative sizes and copy sizes to stack if necessary  */
2586
2587                         /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
2588                         MCODECHECK(512);
2589
2590                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2591
2592                                 /* copy SAVEDVAR sizes to stack */
2593                                 var = VAR(iptr->sx.s23.s2.args[s1]);
2594
2595                                 /* Already Preallocated? */
2596                                 if (!(var->flags & PREALLOC)) {
2597                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
2598                                         M_IST(s2, REG_SP, s1 * 4);
2599                                 }
2600                         }
2601
2602                         /* is a patcher function set? */
2603
2604                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2605                                 disp = dseg_add_unique_address(cd, 0);
2606
2607                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2608                                                                           iptr->sx.s23.s3.c.ref,
2609                                                                           disp);
2610                         }
2611                         else
2612                                 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2613
2614                         /* a0 = dimension count */
2615
2616                         ICONST(REG_A0, iptr->s1.argcount);
2617
2618                         /* a1 = classinfo */
2619
2620                         M_ALD_DSEG(REG_A1, disp);
2621
2622                         /* a2 = pointer to dimensions = stack pointer */
2623
2624                         M_MOV(REG_SP, REG_A2);
2625
2626                         disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2627                         M_ALD_DSEG(REG_ITMP1, disp);
2628                         M_ASUB_IMM(96, REG_SP);
2629                         M_JSR(REG_RA, REG_ITMP1);
2630                         M_AADD_IMM(96, REG_SP);
2631
2632                         /* check for exception before result assignment */
2633
2634                         emit_exception_check(cd, iptr);
2635
2636                         s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2637                         M_INTMOVE(REG_RESULT, s1);
2638                         emit_store_dst(jd, iptr, s1);
2639
2640                         break;
2641
2642                 default:
2643                         vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2644         } /* switch */
2645 }
2646
2647
2648 /* codegen_emit_stub_native ****************************************************
2649
2650    Emits a stub routine which calls a native method.
2651
2652 *******************************************************************************/
2653
2654 /*
2655            arguments on stack                   \
2656 -------------------------------------------------| <- SP on nativestub entry
2657            return address                        |
2658            callee saved int regs (none)          |
2659            callee saved float regs (none)        | stack frame like in cacao
2660            local variable slots (none)           |
2661            arguments for calling methods (none) /
2662 ------------------------------------------------------------------ <- datasp 
2663            stackframe info
2664            locaref table
2665            integer arguments
2666            float arguments
2667 96 - ...   on stack parameters (nmd->memuse slots) \ stack frame like in ABI         
2668 0 - 96     register save area for callee           /
2669 -------------------------------------------------------- <- SP native method
2670                                                             ==
2671                                                             SP after method entry
2672 */
2673
2674 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2675 {
2676         methodinfo  *m;
2677         codeinfo    *code;
2678         codegendata *cd;
2679         methoddesc  *md;
2680         int          i, j;
2681         int          t;
2682         int          s1, s2;
2683         int          disp;
2684
2685         /* get required compiler data */
2686
2687         m    = jd->m;
2688         code = jd->code;
2689         cd   = jd->cd;
2690
2691         /* set some variables */
2692
2693         md = m->parseddesc;
2694
2695         /* calculate stackframe size */
2696
2697         cd->stackframesize =
2698                 1 + /* return address */
2699                 sizeof(stackframeinfo_t) / 8 +
2700                 sizeof(localref_table) / 8 +
2701                 nmd->paramcount +
2702                 nmd->memuse +
2703                 (96 / 8); /* linkage area */
2704
2705         /* keep stack 8-byte aligned */
2706
2707         /*ALIGN_2(cd->stackframesize);*/
2708
2709         /* create method header */
2710
2711         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
2712         (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
2713         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
2714         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
2715         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
2716
2717         /* generate code */
2718
2719         M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
2720         M_AADD_IMM(N_PV_OFFSET, REG_PV);
2721
2722         /* store return address */
2723
2724         M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
2725
2726 #if defined(ENABLE_GC_CACAO)
2727         /* Save callee saved integer registers in stackframeinfo (GC may
2728            need to recover them during a collection). */
2729
2730         disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2731                 OFFSET(stackframeinfo_t, intregs);
2732
2733         for (i = 0; i < INT_SAV_CNT; i++)
2734                 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2735 #endif
2736
2737         /* save integer and float argument registers */
2738
2739         for (i = 0; i < md->paramcount; i++) {
2740                 if (!md->params[i].inmemory) {
2741                         s1 = md->params[i].regoff;
2742
2743                         switch (md->paramtypes[i].type) {
2744                         case TYPE_INT:
2745                         case TYPE_ADR:
2746                                 M_IST(s1, REG_SP, 96 + i * 8);
2747                                 break;
2748                         case TYPE_LNG:
2749                                 M_LST(s1, REG_SP, 96 + i * 8);
2750                                 break;
2751                         case TYPE_FLT:
2752                         case TYPE_DBL:
2753                                 M_DST(s1, REG_SP, 96 + i * 8);
2754                                 break;
2755                         }
2756                 }
2757         }
2758
2759         /* create native stack info */
2760
2761         M_MOV(REG_SP, REG_A0);
2762         M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
2763         disp = dseg_add_functionptr(cd, codegen_start_native_call);
2764         M_ALD_DSEG(REG_ITMP2, disp);
2765         M_CALL(REG_ITMP2);
2766
2767         /* remember class argument */
2768
2769         if (m->flags & ACC_STATIC)
2770                 M_MOV(REG_RESULT, REG_ITMP3);
2771
2772         /* restore integer and float argument registers */
2773
2774         for (i = 0; i < md->paramcount; i++) {
2775                 if (!md->params[i].inmemory) {
2776                         s1 = md->params[i].regoff;
2777
2778                         switch (md->paramtypes[i].type) {
2779                         case TYPE_INT:
2780                         case TYPE_ADR:
2781                                 M_ILD(s1, REG_SP, 96 + i * 8);
2782                                 break;
2783                         case TYPE_LNG:
2784                                 M_LLD(s1, REG_SP, 96 + i * 8);
2785                                 break;
2786                         case TYPE_FLT:
2787                         case TYPE_DBL:
2788                                 M_DLD(s1, REG_SP, 96 + i * 8);
2789                                 break;
2790                         }
2791                 }
2792         }
2793
2794         /* copy or spill arguments to new locations */
2795
2796         for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2797                 t = md->paramtypes[i].type;
2798
2799                 if (IS_INT_LNG_TYPE(t)) {
2800                         if (!md->params[i].inmemory) {
2801                                 s1 = md->params[i].regoff;
2802                                 s2 = nmd->params[j].regoff;
2803
2804                                 if (!nmd->params[j].inmemory) {
2805                                         if (IS_2_WORD_TYPE(t))
2806                                                 M_LNGMOVE(s1, s2);
2807                                         else
2808                                                 M_INTMOVE(s1, s2);
2809                                 }
2810                                 else {
2811                                         if (IS_2_WORD_TYPE(t))
2812                                                 M_LST(s1, REG_SP, s2);
2813                                         else
2814                                                 M_IST(s1, REG_SP, s2);
2815                                 }
2816                         }
2817                         else {
2818                                 s1 = md->params[i].regoff + cd->stackframesize * 8;
2819                                 s2 = nmd->params[j].regoff;
2820
2821                                 if (IS_2_WORD_TYPE(t)) {
2822                                         N_MVC(s2, 8, REG_SP, s1, REG_SP);
2823                                 } else {
2824                                         N_MVC(s2, 4, REG_SP, s1, REG_SP);
2825                                 }
2826                         }
2827                 }
2828                 else {
2829                         /* We only copy spilled float arguments, as the float
2830                            argument registers keep unchanged. */
2831
2832                         if (md->params[i].inmemory) {
2833                                 s1 = md->params[i].regoff + cd->stackframesize * 8;
2834                                 s2 = nmd->params[j].regoff;
2835
2836                                 if (IS_2_WORD_TYPE(t)) {
2837                                         N_MVC(s2, 8, REG_SP, s1, REG_SP);
2838                                 } else {
2839                                         N_MVC(s2, 4, REG_SP, s1, REG_SP);
2840                                 }
2841                         }
2842                 }
2843         }
2844
2845         /* Handle native Java methods. */
2846
2847         if (m->flags & ACC_NATIVE) {
2848                 /* put class into second argument register */
2849
2850                 if (m->flags & ACC_STATIC)
2851                         M_MOV(REG_ITMP3, REG_A1);
2852
2853                 /* put env into first argument register */
2854
2855                 disp = dseg_add_address(cd, VM_get_jnienv());
2856                 M_ALD_DSEG(REG_A0, disp);
2857         }
2858
2859         /* Call native function. */
2860
2861         disp = dseg_add_functionptr(cd, f);
2862         M_ALD_DSEG(REG_ITMP2, disp);
2863         M_CALL(REG_ITMP2);
2864
2865         /* save return value */
2866
2867         switch (md->returntype.type) {
2868         case TYPE_INT:
2869         case TYPE_ADR:
2870                 M_IST(REG_RESULT, REG_SP, 96);
2871                 break;
2872         case TYPE_LNG:
2873                 M_LST(REG_RESULT_PACKED, REG_SP, 96);
2874                 break;
2875         case TYPE_FLT:
2876         case TYPE_DBL:
2877                 M_DST(REG_FRESULT, REG_SP, 96);
2878                 break;
2879         case TYPE_VOID:
2880                 break;
2881         }
2882
2883         /* remove native stackframe info */
2884
2885         M_MOV(REG_SP, REG_A0);
2886         M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
2887         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2888         M_ALD_DSEG(REG_ITMP1, disp);
2889         M_CALL(REG_ITMP1);
2890
2891         M_MOV(REG_RESULT, REG_ITMP3_XPTR);
2892
2893         /* restore return value */
2894
2895         switch (md->returntype.type) {
2896         case TYPE_INT:
2897         case TYPE_ADR:
2898                 M_ILD(REG_RESULT, REG_SP, 96);
2899                 break;
2900         case TYPE_LNG:
2901                 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
2902                 break;
2903         case TYPE_FLT:
2904         case TYPE_DBL:
2905                 M_DLD(REG_FRESULT, REG_SP, 96);
2906                 break;
2907         case TYPE_VOID:
2908                 break;
2909         }
2910
2911 #if defined(ENABLE_GC_CACAO)
2912         /* Restore callee saved integer registers from stackframeinfo (GC
2913            might have modified them during a collection). */
2914          
2915         disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2916                 OFFSET(stackframeinfo_t, intregs);
2917
2918         for (i = 0; i < INT_SAV_CNT; i++)
2919                 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2920 #endif
2921
2922         /* load return address */
2923
2924         M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
2925
2926         /* remove stackframe       */
2927
2928         M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2929
2930         /* check for exception */
2931
2932         M_TEST(REG_ITMP3_XPTR);
2933         M_BNE(SZ_BRC + SZ_BCR);                     /* if no exception then return        */
2934
2935         M_RET;
2936
2937         /* handle exception */
2938
2939         M_MOV(REG_RA, REG_ITMP1_XPC);
2940         M_ASUB_IMM(2, REG_ITMP1_XPC);
2941
2942         disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2943         M_ALD_DSEG(REG_ITMP2, disp);
2944         M_JMP(RN, REG_ITMP2);
2945 }
2946
2947 /*
2948  * These are local overrides for various environment variables in Emacs.
2949  * Please do not remove this and leave it at the end of the file, where
2950  * Emacs will automagically detect them.
2951  * ---------------------------------------------------------------------
2952  * Local variables:
2953  * mode: c
2954  * indent-tabs-mode: t
2955  * c-basic-offset: 4
2956  * tab-width: 4
2957  * End:
2958  * vim:noexpandtab:sw=4:ts=4:
2959  */