d9bfac3c9a5609879143d14beff981c1696fc590
[cacao.git] / src / vm / jit / s390 / codegen.c
1 /* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28             Christian Thalinger
29             Christian Ullrich
30             Edwin Steiner
31
32    $Id: codegen.c 7534 2007-03-16 23:00:18Z pm $
33
34 */
35
36
37 #include "config.h"
38
39 #include <assert.h>
40 #include <stdio.h>
41
42 #include "vm/types.h"
43
44 #include "md-abi.h"
45
46 #include "vm/jit/s390/arch.h"
47 #include "vm/jit/s390/codegen.h"
48 #include "vm/jit/s390/emit.h"
49
50 #include "mm/memory.h"
51 #include "native/jni.h"
52 #include "native/native.h"
53
54 #if defined(ENABLE_THREADS)
55 # include "threads/native/lock.h"
56 #endif
57
58 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/global.h"
61 #include "vmcore/loader.h"
62 #include "vmcore/options.h"
63 #include "vmcore/statistics.h"
64 #include "vm/stringlocal.h"
65 #include "vm/vm.h"
66 #include "vm/jit/asmpart.h"
67 #include "vm/jit/codegen-common.h"
68 #include "vm/jit/dseg.h"
69 #include "vm/jit/emit-common.h"
70 #include "vm/jit/jit.h"
71 #include "vm/jit/methodheader.h"
72 #include "vm/jit/parse.h"
73 #include "vm/jit/patcher.h"
74 #include "vm/jit/reg.h"
75 #include "vm/jit/replace.h"
76 #include "vm/jit/stacktrace.h"
77
78 #if defined(ENABLE_LSRA)
79 # include "vm/jit/allocator/lsra.h"
80 #endif
81
82 #define OOPS() assert(0);
83
84 void panic() { }
85
86 #if 0
87 u1 *createcompilerstub(methodinfo *m) {
88         OOPS();
89         u1 *stub = malloc(8);
90         bzero(stub, 8);
91         return stub;
92 }
93 #endif
94
95 #if 0
96 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) {
97         OOPS();
98         return createcompilerstub(NULL);
99 }
100 #endif
101
102
103
104 /* codegen *********************************************************************
105
106    Generates machine code.
107
108 *******************************************************************************/
109
110
111 bool codegen(jitdata *jd)
112 {
113         methodinfo         *m;
114         codeinfo           *code;
115         codegendata        *cd;
116         registerdata       *rd;
117         s4                  len, s1, s2, s3, d, disp;
118         u2                  currentline;
119         ptrint              a;
120         varinfo            *var, *var1, *var2, *dst;
121         basicblock         *bptr;
122         instruction        *iptr;
123         exception_entry    *ex;
124         constant_classref  *cr;
125         unresolved_class   *uc;
126         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
127         unresolved_method  *um;
128         builtintable_entry *bte;
129         methoddesc         *md;
130         fieldinfo          *fi;
131         unresolved_field   *uf;
132         s4                  fieldtype;
133 #if 0
134         rplpoint           *replacementpoint;
135 #endif
136         s4                 varindex;
137
138         /* get required compiler data */
139
140         m    = jd->m;
141         code = jd->code;
142         cd   = jd->cd;
143         rd   = jd->rd;
144
145         /* prevent compiler warnings */
146
147         d   = 0;
148         lm  = NULL;
149         um  = NULL;
150         bte = NULL;
151
152         {
153         s4 i, p, t, l;
154         s4 savedregs_num;
155
156         savedregs_num = 0; 
157
158         /* space to save used callee saved registers */
159
160         savedregs_num += (INT_SAV_CNT - rd->savintreguse);
161         savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
162
163         cd->stackframesize = rd->memuse + savedregs_num + 1  /* space to save RA */;
164
165         /* CAUTION:
166          * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
167          */
168
169 #if defined(ENABLE_THREADS)
170         /* space to save argument of monitor_enter */
171         OOPS(); /* see powerpc  */
172 #if 0
173         if (checksync && (m->flags & ACC_SYNCHRONIZED))
174                 cd->stackframesize++;
175 #endif
176 #endif
177
178         /* Keep stack of non-leaf functions 16-byte aligned for calls into
179            native code e.g. libc or jni (alignment problems with
180            movaps). */
181
182         if (!jd->isleafmethod || opt_verbosecall )
183                 /* TODO really 16 bytes ? */
184                 cd->stackframesize = (cd->stackframesize + 3) & ~3;
185
186         /* create method header */
187
188         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
189         (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
190
191 #if defined(ENABLE_THREADS)
192         /* IsSync contains the offset relative to the stack pointer for the
193            argument of monitor_exit used in the exception handler. Since the
194            offset could be zero and give a wrong meaning of the flag it is
195            offset by one.
196         */
197
198         if (checksync && (m->flags & ACC_SYNCHRONIZED))
199                 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync        */
200         else
201 #endif
202 /*
203                 (void) dseg_add_unique_s4(cd, 0);*/                  /* IsSync          */
204
205         disp = dseg_add_unique_address(cd, 0);
206
207         (void) dseg_add_unique_s4(cd, jd->isleafmethod);               /* IsLeaf  */
208         (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
209         (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
210
211         (void) dseg_addlinenumbertablesize(cd);
212
213         (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize   */
214
215         /* create exception table */
216
217         for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
218                 dseg_add_target(cd, ex->start);
219                 dseg_add_target(cd, ex->end);
220                 dseg_add_target(cd, ex->handler);
221                 (void) dseg_add_unique_address(cd, ex->catchtype.any);
222         }
223         
224         /* generate method profiling code */
225
226 #if defined(ENABLE_PROFILING)
227         if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
228                 /* count frequency */
229
230                 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
231                 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
232                 M_IADD_IMM(1, REG_ITMP2);
233                 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
234
235 /*              PROFILE_CYCLE_START; */
236         }
237 #endif
238
239         /* create stack frame (if necessary) */
240
241         if (cd->stackframesize)
242                 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
243
244         N_LHI(REG_ITMP2, disp);
245         N_ST(REG_SP, 0, REG_ITMP2, REG_PV);
246
247         /* save used callee saved registers and return address */
248
249         p = cd->stackframesize;
250         p--; M_AST(REG_RA, REG_SP, p * 4);
251
252         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
253                 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
254         }
255         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
256                 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
257         }
258
259         /* take arguments out of register or stack frame */
260
261         md = m->parseddesc;
262
263         for (p = 0, l = 0; p < md->paramcount; p++) {
264                 t = md->paramtypes[p].type;
265                 varindex = jd->local_map[l * 5 + t];
266
267                 l++;
268                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
269                         l++;
270
271                 if (varindex == UNUSED)
272                         continue;
273
274                 var = VAR(varindex);
275
276                 s1 = md->params[p].regoff;
277                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
278                         if (IS_2_WORD_TYPE(t))
279                                 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
280                                                            rd->argintregs[GET_HIGH_REG(s1)]);
281                         else
282                                 s2 = rd->argintregs[s1];
283                         if (!md->params[p].inmemory) {           /* register arguments    */
284                                 if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
285                                         if (IS_2_WORD_TYPE(t))
286                                                 M_LNGMOVE(s2, var->vv.regoff);
287                                         else
288                                                 M_INTMOVE(s2, var->vv.regoff);
289
290                                 } else {                             /* reg arg -> spilled    */
291                                         if (IS_2_WORD_TYPE(t))
292                                                 M_LST(s2, REG_SP, var->vv.regoff * 4);
293                                         else
294                                                 M_IST(s2, REG_SP, var->vv.regoff * 4);
295                                 }
296
297                         } else {                                 /* stack arguments       */
298                                 if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
299                                         if (IS_2_WORD_TYPE(t))
300                                                 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
301                                         else
302                                                 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
303
304                                 } else {                             /* stack arg -> spilled  */
305                                         M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
306                                         M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
307                                         if (IS_2_WORD_TYPE(t)) {
308                                                 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
309                                                 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
310                                         }
311                                 }
312                         }
313
314                 } else {                                     /* floating args         */
315                         if (!md->params[p].inmemory) {           /* register arguments    */
316                                 s2 = rd->argfltregs[s1];
317                                 if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
318                                         M_FLTMOVE(s2, var->vv.regoff);
319
320                                 } else {                                         /* reg arg -> spilled    */
321                                         if (IS_2_WORD_TYPE(t))
322                                                 M_DST(s2, REG_SP, var->vv.regoff * 4);
323                                         else
324                                                 M_FST(s2, REG_SP, var->vv.regoff * 4);
325                                 }
326
327                         } else {                                 /* stack arguments       */
328                                 if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
329                                         if (IS_2_WORD_TYPE(t))
330                                                 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
331
332                                         else
333                                                 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
334
335                                 } else {                             /* stack-arg -> spilled  */
336                                         if (IS_2_WORD_TYPE(t)) {
337                                                 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
338                                                 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
339                                                 var->vv.regoff = cd->stackframesize + s1;
340
341                                         } else {
342                                                 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
343                                                 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
344                                         }
345                                 }
346                         }
347                 }
348         } /* end for */
349
350         /* save monitorenter argument */
351
352 #if defined(ENABLE_THREADS)
353         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
354                 /* stack offset for monitor argument */
355
356                 s1 = rd->memuse;
357
358                 if (opt_verbosecall) {
359                         M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
360
361                         for (p = 0; p < INT_ARG_CNT; p++)
362                                 M_LST(rd->argintregs[p], REG_SP, p * 8);
363
364                         for (p = 0; p < FLT_ARG_CNT; p++)
365                                 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
366
367                         s1 += INT_ARG_CNT + FLT_ARG_CNT;
368                 }
369
370                 /* decide which monitor enter function to call */
371
372                 if (m->flags & ACC_STATIC) {
373                         M_MOV_IMM(&m->class->object.header, REG_A0);
374                 }
375                 else {
376                         M_TEST(REG_A0);
377                         M_BEQ(0);
378                         codegen_add_nullpointerexception_ref(cd);
379                 }
380
381                 M_AST(REG_A0, REG_SP, s1 * 8);
382                 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
383                 M_CALL(REG_ITMP1);
384
385                 if (opt_verbosecall) {
386                         for (p = 0; p < INT_ARG_CNT; p++)
387                                 M_LLD(rd->argintregs[p], REG_SP, p * 8);
388
389                         for (p = 0; p < FLT_ARG_CNT; p++)
390                                 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
391
392                         M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
393                 }
394         }
395 #endif
396
397 #if !defined(NDEBUG)
398         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
399                 emit_verbosecall_enter(jd);
400 #endif /* !defined(NDEBUG) */
401
402         }
403
404         /* end of header generation */
405 #if 0
406         replacementpoint = jd->code->rplpoints;
407 #endif
408
409         /* walk through all basic blocks */
410
411         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
412
413                 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
414
415                 if (bptr->flags >= BBREACHED) {
416
417                 /* branch resolving */
418
419                 codegen_resolve_branchrefs(cd, bptr);
420
421                 /* handle replacement points */
422
423 #if 0
424                 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
425                         replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
426                         
427                         replacementpoint++;
428
429                         assert(cd->lastmcodeptr <= cd->mcodeptr);
430                         cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
431                 }
432 #endif
433
434                 /* copy interface registers to their destination */
435
436                 len = bptr->indepth;
437                 MCODECHECK(512);
438
439                 /* generate basicblock profiling code */
440
441                 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
442                         /* count frequency */
443
444                         M_MOV_IMM(code->bbfrequency, REG_ITMP3);
445                         M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
446
447                         /* if this is an exception handler, start profiling again */
448
449                         if (bptr->type == BBTYPE_EXH)
450                                 PROFILE_CYCLE_START;
451                 }
452
453 #if defined(ENABLE_LSRA)
454                 if (opt_lsra) {
455                         while (len) {
456                                 len--;
457                                 src = bptr->invars[len];
458                                 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
459                                         if (bptr->type == BBTYPE_EXH) {
460 /*                                      d = reg_of_var(rd, src, REG_ITMP1); */
461                                                 if (!IS_INMEMORY(src->flags))
462                                                         d= src->vv.regoff;
463                                                 else
464                                                         d=REG_ITMP1;
465                                                 M_INTMOVE(REG_ITMP1, d);
466                                                 emit_store(jd, NULL, src, d);
467                                         }
468                                 }
469                         }
470                         
471                 } else {
472 #endif
473
474                 while (len) {
475                         len--;
476                         var = VAR(bptr->invars[len]);
477                         if ((len ==  bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
478                                 if (bptr->type == BBTYPE_EXH) {
479                                         d = codegen_reg_of_var(0, var, REG_ITMP1);
480                                         M_INTMOVE(REG_ITMP1, d);
481                                         emit_store(jd, NULL, var, d);
482                                 }
483                         } 
484                         else {
485                                 assert((var->flags & INOUT));
486                         }
487                 }
488 #if defined(ENABLE_LSRA)
489                 }
490 #endif
491                 /* walk through all instructions */
492                 
493                 len = bptr->icount;
494                 currentline = 0;
495
496                 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
497                         if (iptr->line != currentline) {
498                                 dseg_addlinenumber(cd, iptr->line);
499                                 currentline = iptr->line;
500                         }
501
502                         MCODECHECK(1024);                         /* 1KB should be enough */
503
504                 switch (iptr->opc) {
505                 case ICMD_NOP:        /* ...  ==> ...                                 */
506                 case ICMD_POP:        /* ..., value  ==> ...                          */
507                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
508                 case ICMD_INLINE_START: /* internal ICMDs                         */
509                 case ICMD_INLINE_END:
510                         break;
511
512                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
513                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
514                         M_TEST(s1);
515                         M_BEQ(0);
516                         codegen_add_nullpointerexception_ref(cd);
517                         break;
518
519                 /* constant operations ************************************************/
520
521                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
522                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
523                         ICONST(d, iptr->sx.val.i);
524                         emit_store_dst(jd, iptr, d);
525                         break;
526
527                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
528
529                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
530                         LCONST(d, iptr->sx.val.l);
531                         emit_store_dst(jd, iptr, d);
532                         break;
533
534                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
535                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
536                         disp = dseg_add_float(cd, iptr->sx.val.f);
537                         M_FLDN(d, REG_PV, disp, REG_ITMP1);
538                         emit_store_dst(jd, iptr, d);
539                         break;
540                 
541                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
542                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
543                         disp = dseg_add_double(cd, iptr->sx.val.d);
544                         M_DLDN(d, REG_PV, disp, REG_ITMP1);
545                         emit_store_dst(jd, iptr, d);
546                         break;
547
548                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
549                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
550
551                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
552                                 cr = iptr->sx.val.c.ref;
553                                 disp = dseg_add_unique_address(cd, cr);
554
555 /*                              PROFILE_CYCLE_STOP; */
556
557                                 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
558                                                                           cr, disp);
559
560 /*                              PROFILE_CYCLE_START; */
561
562                                 M_ALD(d, REG_PV, disp);
563                         } else {
564                                 if (iptr->sx.val.anyptr == 0) {
565                                         M_CLR(d);
566                                 } else {
567                                         disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
568                                         M_ALD(d, REG_PV, disp);
569                                 }
570                         }
571                         emit_store_dst(jd, iptr, d);
572                         break;
573
574
575                 /* load/store/copy/move operations ************************************/
576
577                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
578                 case ICMD_ALOAD:      /* s1 = local variable                          */
579                 case ICMD_LLOAD:
580                 case ICMD_FLOAD:  
581                 case ICMD_DLOAD:  
582                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
583                 case ICMD_LSTORE:
584                 case ICMD_FSTORE:
585                 case ICMD_DSTORE: 
586                 case ICMD_COPY:
587                 case ICMD_MOVE:
588                         emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
589                         break;
590
591                 case ICMD_ASTORE:
592                         if (!(iptr->flags.bits & INS_FLAG_RETADDR))
593                                 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
594                         break;
595
596                 /* integer operations *************************************************/
597
598                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
599
600                         s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
601                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
602                         N_LCR(d, s1);
603                         emit_store_dst(jd, iptr, d);
604
605                         break;
606
607                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
608                         OOPS();
609 #if 0
610                         s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
611                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
612                         M_INTMOVE(s1, d);
613                         M_LNEG(d);
614                         emit_store_dst(jd, iptr, d);
615 #endif
616                         break;
617
618                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
619                         OOPS();
620 #if 0
621                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
622                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
623                         M_ISEXT(s1, d);
624                         emit_store_dst(jd, iptr, d);
625 #endif
626                         break;
627
628                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
629                         OOPS();
630 #if 0
631                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
632                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
633                         M_IMOV(s1, d);
634                         emit_store_dst(jd, iptr, d);
635 #endif
636                         break;
637
638                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
639                         OOPS();
640 #if 0
641                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
642                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
643                         M_BSEXT(s1, d);
644                         emit_store_dst(jd, iptr, d);
645 #endif
646                         break;
647
648                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
649                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
650                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
651                         M_INTMOVE(s1, d);
652                         N_SLL(d, 16, RN);
653                         N_SRL(d, 16, RN);
654                         emit_store_dst(jd, iptr, d);
655                         break;
656
657                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
658                         OOPS();
659 #if 0
660                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
661                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
662                         M_SSEXT(s1, d);
663                         emit_store_dst(jd, iptr, d);
664 #endif
665                         break;
666
667
668                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
669
670                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
671                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
672                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
673                         if (s2 == d)
674                                 M_IADD(s1, d);
675                         else {
676                                 M_INTMOVE(s1, d);
677                                 M_IADD(s2, d);
678                         }
679                         emit_store_dst(jd, iptr, d);
680
681                         break;
682
683                 case ICMD_IINC:
684                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
685                                       /* sx.val.i = constant                             */
686                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
687                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
688                         M_INTMOVE(s1, d);
689
690                         if (N_VALID_IMM(iptr->sx.val.i)) {
691                                 M_IADD_IMM(iptr->sx.val.i, d);
692                         } else {
693                                 disp = dseg_add_s4(cd, iptr->sx.val.i);
694                                 M_ILD(REG_ITMP2, REG_PV, disp);
695                                 M_IADD(REG_ITMP2, d);   
696                         }
697                         emit_store_dst(jd, iptr, d);
698                         break;
699
700                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
701                         OOPS();
702 #if 0
703                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
704                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
705                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
706                         if (s2 == d)
707                                 M_LADD(s1, d);
708                         else {
709                                 M_INTMOVE(s1, d);
710                                 M_LADD(s2, d);
711                         }
712                         emit_store_dst(jd, iptr, d);
713 #endif
714                         break;
715
716                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
717                                       /* sx.val.l = constant                             */
718                         OOPS();
719 #if 0
720                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
721                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
722                         M_INTMOVE(s1, d);
723                         if (IS_IMM32(iptr->sx.val.l))
724                                 M_LADD_IMM(iptr->sx.val.l, d);
725                         else {
726                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
727                                 M_LADD(REG_ITMP2, d);
728                         }
729                         emit_store_dst(jd, iptr, d);
730 #endif
731                         break;
732
733                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
734                                                                  
735                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
736                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
737                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
738                         if (s2 == d) {
739                                 M_INTMOVE(s1, REG_ITMP1);
740                                 M_ISUB(s2, REG_ITMP1);
741                                 M_INTMOVE(REG_ITMP1, d);
742                         } else {
743                                 M_INTMOVE(s1, d);
744                                 M_ISUB(s2, d);
745                         }
746                         emit_store_dst(jd, iptr, d);
747
748                         break;
749
750                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
751                                       /* sx.val.i = constant                             */
752
753                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
754                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
755                         M_INTMOVE(s1, d);
756                         /* TODO range */
757                         if (N_VALID_IMM(iptr->sx.val.i)) {
758                                 M_ISUB_IMM(iptr->sx.val.i, d);
759                         } else {
760                                 disp = dseg_add_s4(cd, iptr->sx.val.i);
761                                 M_ILD(REG_ITMP2, REG_PV, disp);
762                                 M_ISUB(REG_ITMP2, d);
763                         }
764                         emit_store_dst(jd, iptr, d);
765
766                         break;
767
768                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
769                         OOPS();
770 #if 0
771                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
772                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
773                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
774                         if (s2 == d) {
775                                 M_INTMOVE(s1, REG_ITMP1);
776                                 M_LSUB(s2, REG_ITMP1);
777                                 M_INTMOVE(REG_ITMP1, d);
778                         } else {
779                                 M_INTMOVE(s1, d);
780                                 M_LSUB(s2, d);
781                         }
782                         emit_store_dst(jd, iptr, d);
783 #endif
784                         break;
785
786                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
787                                       /* sx.val.l = constant                             */
788                         OOPS();
789 #if 0
790                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
791                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
792                         M_INTMOVE(s1, d);
793                         if (IS_IMM32(iptr->sx.val.l))
794                                 M_LSUB_IMM(iptr->sx.val.l, d);
795                         else {
796                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
797                                 M_LSUB(REG_ITMP2, d);
798                         }
799                         emit_store_dst(jd, iptr, d);
800 #endif
801                         break;
802
803                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
804                         OOPS();
805 #if 0
806                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
807                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
808                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
809                         if (s2 == d)
810                                 M_IMUL(s1, d);
811                         else {
812                                 M_INTMOVE(s1, d);
813                                 M_IMUL(s2, d);
814                         }
815                         emit_store_dst(jd, iptr, d);
816 #endif
817                         break;
818
819                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
820                                       /* sx.val.i = constant                             */
821                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
822                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
823                         M_INTMOVE(s1, d);
824                         if (iptr->sx.val.i == 2) {
825                                 M_ISLL_IMM(1, d);
826                         } else if (N_VALID_IMM(iptr->sx.val.i)) {
827                                 M_IMUL_IMM(iptr->sx.val.i, d);
828                         } else {
829                                 disp = dseg_add_s4(cd, iptr->sx.val.i);
830                                 M_ILD(REG_ITMP2, REG_PV, disp);
831                                 M_IMUL(REG_ITMP2, d);   
832                         }
833                         emit_store_dst(jd, iptr, d);
834                         break;
835
836                 case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
837                         OOPS();
838 #if 0
839                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
840                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
841                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
842                         if (s2 == d)
843                                 M_LMUL(s1, d);
844                         else {
845                                 M_INTMOVE(s1, d);
846                                 M_LMUL(s2, d);
847                         }
848                         emit_store_dst(jd, iptr, d);
849 #endif
850                         break;
851
852                 case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant        */
853                                       /* sx.val.l = constant                             */
854                         OOPS();
855 #if 0
856                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
857                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
858                         if (IS_IMM32(iptr->sx.val.l))
859                                 M_LMUL_IMM(s1, iptr->sx.val.l, d);
860                         else {
861                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
862                                 M_INTMOVE(s1, d);
863                                 M_LMUL(REG_ITMP2, d);
864                         }
865                         emit_store_dst(jd, iptr, d);
866 #endif
867                         break;
868
869                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
870                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
871
872                         /* For this operation we need a register pair.
873                          * We will use r0 and itmp1 and will backup r0.
874                          */
875
876                         M_INTMOVE(R0, REG_ITMP3);
877
878                         s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
879
880                         s1 = emit_load_s1(jd, iptr, R0);
881                         M_INTMOVE(s1, R0);
882                         N_LHI(REG_ITMP1, 0);
883                         N_SRDA(R0, 32, RN);
884
885                         N_DR(R0, s2);
886
887                         if (iptr->opc == ICMD_IREM) {
888                                 d = codegen_reg_of_dst(jd, iptr, R0);
889                                 M_INTMOVE(R0, d);
890                         } else {
891                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
892                                 M_INTMOVE(REG_ITMP1, d);
893                         }
894
895                         emit_store_dst(jd, iptr, d);
896
897                         M_INTMOVE(REG_ITMP3, R0);
898
899                         break;
900
901                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
902                                       /* sx.val.i = constant                             */
903                         OOPS();
904 #if 0
905                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
906                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
907                         M_INTMOVE(s1, REG_ITMP1);
908                         emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
909                         emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
910                         emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
911                         emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
912                         emit_mov_reg_reg(cd, REG_ITMP1, d);
913                         emit_store_dst(jd, iptr, d);
914 #endif
915                         break;
916
917                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
918                                       /* sx.val.i = constant                             */
919                         OOPS();
920 #if 0
921                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
922                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
923                         M_INTMOVE(s1, REG_ITMP1);
924                         emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
925                         emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
926                         emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
927                         emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
928                         emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
929                         emit_mov_reg_reg(cd, REG_ITMP1, d);
930                         emit_store_dst(jd, iptr, d);
931 #endif
932                         break;
933
934
935                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
936                         OOPS();
937 #if 0
938                         var1 = VAROP(iptr->s1);
939                         var2 = VAROP(iptr->sx.s23.s2);
940                         dst  = VAROP(iptr->dst);
941
942                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
943
944                 if (IS_INMEMORY(var1->flags))
945                                 M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
946                         else
947                                 M_INTMOVE(var1->vv.regoff, RAX);
948                         
949                         if (IS_INMEMORY(var2->flags))
950                                 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
951                         else
952                                 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
953
954                         if (checknull) {
955                                 M_TEST(REG_ITMP3);
956                                 M_BEQ(0);
957                                 codegen_add_arithmeticexception_ref(cd);
958                         }
959
960                         /* check as described in jvm spec */
961                         disp = dseg_add_s8(cd, 0x8000000000000000LL);
962                         M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
963                         M_BNE(4 + 6);
964                         M_LCMP_IMM(-1, REG_ITMP3);                              /* 4 bytes */
965                         M_BEQ(3 + 2 + 3);                                      /* 6 bytes */
966
967                         M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
968                         emit_cqto(cd);
969                         emit_idiv_reg(cd, REG_ITMP3);
970
971                         if (IS_INMEMORY(dst->flags)) {
972                                 M_LST(RAX, REG_SP, dst->vv.regoff * 8);
973                                 M_MOV(REG_ITMP2, RDX);                        /* restore %rdx */
974
975                         } else {
976                                 M_INTMOVE(RAX, dst->vv.regoff);
977
978                                 if (dst->vv.regoff != RDX) {
979                                         M_MOV(REG_ITMP2, RDX);                    /* restore %rdx */
980                                 }
981                         }
982 #endif
983                         break;
984
985                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
986                         OOPS();
987 #if 0
988                         var1 = VAROP(iptr->s1);
989                         var2 = VAROP(iptr->sx.s23.s2);
990                         dst  = VAROP(iptr->dst);
991
992                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
993                         
994                         if (IS_INMEMORY(var1->flags))
995                                 M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
996                         else
997                                 M_INTMOVE(var1->vv.regoff, REG_ITMP1);
998                         
999                         if (IS_INMEMORY(var2->flags))
1000                                 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
1001                         else
1002                                 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
1003                         /*
1004                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1005                         M_INTMOVE(s1, REG_ITMP1);
1006                         s2 = emit_load_s2(jd, iptr, REG_ITMP3);
1007                         M_INTMOVE(s2, REG_ITMP3);
1008                         */
1009                         if (checknull) {
1010                                 M_ITEST(REG_ITMP3);
1011                                 M_BEQ(0);
1012                                 codegen_add_arithmeticexception_ref(cd);
1013                         }
1014
1015                         M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1016
1017                         /* check as described in jvm spec */
1018                         disp = dseg_add_s8(cd, 0x8000000000000000LL);
1019                         M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
1020                         M_BNE(3 + 4 + 6);
1021
1022 #if 0
1023                         emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX);         /* 2 bytes */
1024 #endif
1025                         M_LXOR(RDX, RDX);                                      /* 3 bytes */
1026                         M_LCMP_IMM(-1, REG_ITMP3);                              /* 4 bytes */
1027                         M_BEQ(2 + 3);                                          /* 6 bytes */
1028
1029                         emit_cqto(cd);
1030                         emit_idiv_reg(cd, REG_ITMP3);
1031
1032                         if (IS_INMEMORY(dst->flags)) {
1033                                 M_LST(RDX, REG_SP, dst->vv.regoff * 8);
1034                                 M_MOV(REG_ITMP2, RDX);                        /* restore %rdx */
1035
1036                         } else {
1037                                 M_INTMOVE(RDX, dst->vv.regoff);
1038
1039                                 if (dst->vv.regoff != RDX) {
1040                                         M_MOV(REG_ITMP2, RDX);                    /* restore %rdx */
1041                                 }
1042                         }
1043 #endif
1044                         break;
1045
1046                 case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
1047                                       /* sx.val.i = constant                             */
1048                         OOPS();
1049 #if 0
1050                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1051                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1052                         M_INTMOVE(s1, REG_ITMP1);
1053                         emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1054                         emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
1055                         emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1056                         emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
1057                         emit_mov_reg_reg(cd, REG_ITMP1, d);
1058                         emit_store_dst(jd, iptr, d);
1059 #endif
1060                         break;
1061
1062                 case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
1063                                       /* sx.val.l = constant                             */
1064                         OOPS();
1065 #if 0
1066                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1067                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1068                         M_INTMOVE(s1, REG_ITMP1);
1069                         emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1070                         emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
1071                         emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1072                         emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
1073                         emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1074                         emit_mov_reg_reg(cd, REG_ITMP1, d);
1075                         emit_store_dst(jd, iptr, d);
1076 #endif
1077                         break;
1078
1079                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
1080                         OOPS();
1081 #if 0
1082                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1083                         emit_ishift(jd, SHIFT_SHL, iptr);
1084 #endif
1085                         break;
1086
1087                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
1088                                       /* sx.val.i = constant                             */
1089                         OOPS();
1090 #if 0
1091                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1092                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1093                         M_INTMOVE(s1, d);
1094                         M_ISLL_IMM(iptr->sx.val.i, d);
1095                         emit_store_dst(jd, iptr, d);
1096 #endif
1097                         break;
1098
1099                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1100                         OOPS();
1101 #if 0
1102                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1103                         emit_ishift(jd, SHIFT_SAR, iptr);
1104 #endif
1105                         break;
1106
1107                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
1108                                       /* sx.val.i = constant                             */
1109                         OOPS();
1110 #if 0
1111                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1112                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1113                         M_INTMOVE(s1, d);
1114                         M_ISRA_IMM(iptr->sx.val.i, d);
1115                         emit_store_dst(jd, iptr, d);
1116 #endif
1117                         break;
1118
1119                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1120                         OOPS();
1121 #if 0
1122                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1123                         emit_ishift(jd, SHIFT_SHR, iptr);
1124 #endif
1125                         break;
1126
1127                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1128                                       /* sx.val.i = constant                             */
1129                         OOPS();
1130 #if 0
1131                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1132                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1133                         M_INTMOVE(s1, d);
1134                         M_ISRL_IMM(iptr->sx.val.i, d);
1135                         emit_store_dst(jd, iptr, d);
1136 #endif
1137                         break;
1138
1139                 case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
1140                         OOPS();
1141 #if 0
1142                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1143                         emit_lshift(jd, SHIFT_SHL, iptr);
1144 #endif
1145                         break;
1146
1147         case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
1148                                           /* sx.val.i = constant                             */
1149                         OOPS();
1150 #if 0
1151                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1152                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1153                         M_INTMOVE(s1, d);
1154                         M_LSLL_IMM(iptr->sx.val.i, d);
1155                         emit_store_dst(jd, iptr, d);
1156 #endif
1157                         break;
1158
1159                 case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1160                         OOPS();
1161 #if 0
1162                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1163                         emit_lshift(jd, SHIFT_SAR, iptr);
1164 #endif
1165                         break;
1166
1167                 case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
1168                                       /* sx.val.i = constant                             */
1169                         OOPS();
1170 #if 0
1171                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1172                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1173                         M_INTMOVE(s1, d);
1174                         M_LSRA_IMM(iptr->sx.val.i, d);
1175                         emit_store_dst(jd, iptr, d);
1176 #endif
1177                         break;
1178
1179                 case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1180                         OOPS();
1181 #if 0
1182                         d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1183                         emit_lshift(jd, SHIFT_SHR, iptr);
1184 #endif
1185                         break;
1186
1187                 case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1188                                       /* sx.val.l = constant                             */
1189                         OOPS();
1190 #if 0
1191                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1192                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1193                         M_INTMOVE(s1, d);
1194                         M_LSRL_IMM(iptr->sx.val.i, d);
1195                         emit_store_dst(jd, iptr, d);
1196 #endif
1197                         break;
1198
1199                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1200                         OOPS();
1201 #if 0
1202                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1203                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1204                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1205                         if (s2 == d)
1206                                 M_IAND(s1, d);
1207                         else {
1208                                 M_INTMOVE(s1, d);
1209                                 M_IAND(s2, d);
1210                         }
1211                         emit_store_dst(jd, iptr, d);
1212 #endif
1213                         break;
1214
1215                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
1216                                       /* sx.val.i = constant                             */
1217                         OOPS();
1218 #if 0
1219                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1220                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1221                         M_INTMOVE(s1, d);
1222                         M_IAND_IMM(iptr->sx.val.i, d);
1223                         emit_store_dst(jd, iptr, d);
1224 #endif
1225                         break;
1226
1227                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1228                         OOPS();
1229 #if 0
1230                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1231                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1232                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1233                         if (s2 == d)
1234                                 M_LAND(s1, d);
1235                         else {
1236                                 M_INTMOVE(s1, d);
1237                                 M_LAND(s2, d);
1238                         }
1239                         emit_store_dst(jd, iptr, d);
1240 #endif
1241                         break;
1242
1243                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1244                                       /* sx.val.l = constant                             */
1245                         OOPS();
1246 #if 0
1247                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1248                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1249                         M_INTMOVE(s1, d);
1250                         if (IS_IMM32(iptr->sx.val.l))
1251                                 M_LAND_IMM(iptr->sx.val.l, d);
1252                         else {
1253                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1254                                 M_LAND(REG_ITMP2, d);
1255                         }
1256                         emit_store_dst(jd, iptr, d);
1257 #endif
1258                         break;
1259
1260                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1261                         OOPS();
1262 #if 0
1263                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1264                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1265                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1266                         if (s2 == d)
1267                                 M_IOR(s1, d);
1268                         else {
1269                                 M_INTMOVE(s1, d);
1270                                 M_IOR(s2, d);
1271                         }
1272                         emit_store_dst(jd, iptr, d);
1273 #endif
1274                         break;
1275
1276                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
1277                                       /* sx.val.i = constant                             */
1278                         OOPS();
1279 #if 0
1280                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1281                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1282                         M_INTMOVE(s1, d);
1283                         M_IOR_IMM(iptr->sx.val.i, d);
1284                         emit_store_dst(jd, iptr, d);
1285 #endif
1286                         break;
1287
1288                 case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1289                         OOPS();
1290 #if 0
1291                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1292                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1293                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1294                         if (s2 == d)
1295                                 M_LOR(s1, d);
1296                         else {
1297                                 M_INTMOVE(s1, d);
1298                                 M_LOR(s2, d);
1299                         }
1300                         emit_store_dst(jd, iptr, d);
1301 #endif
1302                         break;
1303
1304                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1305                                       /* sx.val.l = constant                             */
1306                         OOPS();
1307 #if 0
1308                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1309                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1310                         M_INTMOVE(s1, d);
1311                         if (IS_IMM32(iptr->sx.val.l))
1312                                 M_LOR_IMM(iptr->sx.val.l, d);
1313                         else {
1314                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1315                                 M_LOR(REG_ITMP2, d);
1316                         }
1317                         emit_store_dst(jd, iptr, d);
1318 #endif
1319                         break;
1320
1321                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1322                         OOPS();
1323 #if 0
1324                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1325                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1326                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1327                         if (s2 == d)
1328                                 M_IXOR(s1, d);
1329                         else {
1330                                 M_INTMOVE(s1, d);
1331                                 M_IXOR(s2, d);
1332                         }
1333                         emit_store_dst(jd, iptr, d);
1334 #endif
1335                         break;
1336
1337                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1338                                       /* sx.val.i = constant                             */
1339                         OOPS();
1340 #if 0
1341                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1342                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1343                         M_INTMOVE(s1, d);
1344                         M_IXOR_IMM(iptr->sx.val.i, d);
1345                         emit_store_dst(jd, iptr, d);
1346 #endif
1347                         break;
1348
1349                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1350                         OOPS();
1351 #if 0
1352                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1353                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1354                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1355                         if (s2 == d)
1356                                 M_LXOR(s1, d);
1357                         else {
1358                                 M_INTMOVE(s1, d);
1359                                 M_LXOR(s2, d);
1360                         }
1361                         emit_store_dst(jd, iptr, d);
1362 #endif
1363                         break;
1364
1365                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1366                                       /* sx.val.l = constant                             */
1367                         OOPS();
1368 #if 0
1369                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1370                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1371                         M_INTMOVE(s1, d);
1372                         if (IS_IMM32(iptr->sx.val.l))
1373                                 M_LXOR_IMM(iptr->sx.val.l, d);
1374                         else {
1375                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1376                                 M_LXOR(REG_ITMP2, d);
1377                         }
1378                         emit_store_dst(jd, iptr, d);
1379 #endif
1380                         break;
1381
1382
1383                 /* floating operations ************************************************/
1384
1385                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1386                         OOPS();
1387 #if 0
1388                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1389                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1390                         disp = dseg_add_s4(cd, 0x80000000);
1391                         M_FLTMOVE(s1, d);
1392                         emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1393                         emit_xorps_reg_reg(cd, REG_FTMP2, d);
1394                         emit_store_dst(jd, iptr, d);
1395 #endif
1396                         break;
1397
1398                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1399                         OOPS();
1400 #if 0
1401                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1402                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1403                         disp = dseg_add_s8(cd, 0x8000000000000000);
1404                         M_FLTMOVE(s1, d);
1405                         emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1406                         emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1407                         emit_store_dst(jd, iptr, d);
1408 #endif
1409                         break;
1410
1411                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1412                         OOPS();
1413 #if 0
1414                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1415                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1416                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1417                         if (s2 == d)
1418                                 M_FADD(s1, d);
1419                         else {
1420                                 M_FLTMOVE(s1, d);
1421                                 M_FADD(s2, d);
1422                         }
1423                         emit_store_dst(jd, iptr, d);
1424 #endif
1425                         break;
1426
1427                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1428                         OOPS();
1429 #if 0
1430                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1431                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1432                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1433                         if (s2 == d)
1434                                 M_DADD(s1, d);
1435                         else {
1436                                 M_FLTMOVE(s1, d);
1437                                 M_DADD(s2, d);
1438                         }
1439                         emit_store_dst(jd, iptr, d);
1440 #endif
1441                         break;
1442
1443                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1444                         OOPS();
1445 #if 0
1446                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1447                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1448                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1449                         if (s2 == d) {
1450                                 M_FLTMOVE(s2, REG_FTMP2);
1451                                 s2 = REG_FTMP2;
1452                         }
1453                         M_FLTMOVE(s1, d);
1454                         M_FSUB(s2, d);
1455                         emit_store_dst(jd, iptr, d);
1456 #endif
1457                         break;
1458
1459                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1460                         OOPS();
1461 #if 0
1462                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1463                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1464                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1465                         if (s2 == d) {
1466                                 M_FLTMOVE(s2, REG_FTMP2);
1467                                 s2 = REG_FTMP2;
1468                         }
1469                         M_FLTMOVE(s1, d);
1470                         M_DSUB(s2, d);
1471                         emit_store_dst(jd, iptr, d);
1472 #endif
1473                         break;
1474
1475                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1476                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1477                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1478                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1479                         if (s2 == d)
1480                                 M_FMUL(s1, d);
1481                         else {
1482                                 M_FLTMOVE(s1, d);
1483                                 M_FMUL(s2, d);
1484                         }
1485                         emit_store_dst(jd, iptr, d);
1486
1487                         break;
1488
1489                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1490                         OOPS();
1491 #if 0
1492                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1493                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1494                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1495                         if (s2 == d)
1496                                 M_DMUL(s1, d);
1497                         else {
1498                                 M_FLTMOVE(s1, d);
1499                                 M_DMUL(s2, d);
1500                         }
1501                         emit_store_dst(jd, iptr, d);
1502 #endif
1503                         break;
1504
1505                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1506                         OOPS();
1507 #if 0
1508                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1509                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1510                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1511                         if (s2 == d) {
1512                                 M_FLTMOVE(s2, REG_FTMP2);
1513                                 s2 = REG_FTMP2;
1514                         }
1515                         M_FLTMOVE(s1, d);
1516                         M_FDIV(s2, d);
1517                         emit_store_dst(jd, iptr, d);
1518 #endif
1519                         break;
1520
1521                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1522                         OOPS();
1523 #if 0
1524                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1525                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1526                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1527                         if (s2 == d) {
1528                                 M_FLTMOVE(s2, REG_FTMP2);
1529                                 s2 = REG_FTMP2;
1530                         }
1531                         M_FLTMOVE(s1, d);
1532                         M_DDIV(s2, d);
1533                         emit_store_dst(jd, iptr, d);
1534 #endif
1535                         break;
1536
1537                 case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
1538                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1539                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1540                         M_CVTIF(s1, d);
1541                         emit_store_dst(jd, iptr, d);
1542                         break;
1543
1544                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
1545                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1546                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1547                         M_CVTID(s1, d);
1548                         emit_store_dst(jd, iptr, d);
1549                         break;
1550
1551                 case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
1552                         OOPS();
1553 #if 0
1554                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1555                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1556                         M_CVTLF(s1, d);
1557                         emit_store_dst(jd, iptr, d);
1558 #endif
1559                         break;
1560                         
1561                 case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
1562                         OOPS();
1563 #if 0
1564                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1565                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1566                         M_CVTLD(s1, d);
1567                         emit_store_dst(jd, iptr, d);
1568 #endif
1569                         break;
1570                         
1571                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1572                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1573                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1574                         M_CVTFI(s1, d);
1575                         emit_store_dst(jd, iptr, d);
1576                         /* TODO: corner cases ? */
1577                         break;
1578
1579                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
1580                         OOPS();
1581 #if 0
1582                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1583                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1584                         M_CVTDI(s1, d);
1585                         M_ICMP_IMM(0x80000000, d);                        /* corner cases */
1586                         disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1587                                 ((REG_RESULT == d) ? 0 : 3);
1588                         M_BNE(disp);
1589                         M_FLTMOVE(s1, REG_FTMP1);
1590                         M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1591                         M_CALL(REG_ITMP2);
1592                         M_INTMOVE(REG_RESULT, d);
1593                         emit_store_dst(jd, iptr, d);
1594 #endif
1595                         break;
1596
1597                 case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
1598                         OOPS();
1599 #if 0
1600                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1601                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1602                         M_CVTFL(s1, d);
1603                         M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1604                         M_LCMP(REG_ITMP2, d);                             /* corner cases */
1605                         disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1606                                 ((REG_RESULT == d) ? 0 : 3);
1607                         M_BNE(disp);
1608                         M_FLTMOVE(s1, REG_FTMP1);
1609                         M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1610                         M_CALL(REG_ITMP2);
1611                         M_INTMOVE(REG_RESULT, d);
1612                         emit_store_dst(jd, iptr, d);
1613 #endif
1614                         break;
1615
1616                 case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
1617                         OOPS();
1618 #if 0
1619                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1620                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1621                         M_CVTDL(s1, d);
1622                         M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1623                         M_LCMP(REG_ITMP2, d);                             /* corner cases */
1624                         disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1625                                 ((REG_RESULT == d) ? 0 : 3);
1626                         M_BNE(disp);
1627                         M_FLTMOVE(s1, REG_FTMP1);
1628                         M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1629                         M_CALL(REG_ITMP2);
1630                         M_INTMOVE(REG_RESULT, d);
1631                         emit_store_dst(jd, iptr, d);
1632 #endif
1633                         break;
1634
1635                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1636                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1637                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1638                         M_CVTFD(s1, d);
1639                         emit_store_dst(jd, iptr, d);
1640                         break;
1641
1642                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
1643                         OOPS();
1644 #if 0
1645                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1646                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1647                         M_CVTDF(s1, d);
1648                         emit_store_dst(jd, iptr, d);
1649 #endif
1650                         break;
1651
1652                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1653                                           /* == => 0, < => 1, > => -1 */
1654                 case ICMD_DCMPL:
1655
1656
1657                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1658                                           /* == => 0, < => 1, > => -1 */
1659                 case ICMD_DCMPG:
1660
1661                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1662                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1663                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1664
1665                         switch (iptr->opc) {
1666                                 case ICMD_FCMPG:
1667                                 case ICMD_FCMPL:
1668                                         N_CEBR(s1, s2);
1669                                         break;
1670                                 case ICMD_DCMPG:
1671                                 case ICMD_DCMPL:
1672                                         N_CDBR(s1, s2);
1673                                         break;  
1674                         }
1675
1676                         N_BRC( /* load 1 */
1677                                 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1678                                 SZ_BRC + SZ_BRC + SZ_BRC
1679                         );
1680
1681                         N_BRC( /* load -1 */
1682                                 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1683                                 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1684                         );
1685
1686                         N_BRC( /* load 0 */
1687                                 DD_E,
1688                                 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1689                         );
1690
1691                         N_LHI(d, 1); /* GT */
1692                         M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1693                         N_LHI(d, -1); /* LT */
1694                         M_BR(SZ_BRC + SZ_LHI);
1695                         N_LHI(d, 0); /* EQ */
1696
1697                         emit_store_dst(jd, iptr, d);
1698
1699                         break;
1700
1701
1702                 /* memory operations **************************************************/
1703
1704                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., (int) length        */
1705
1706                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1707                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1708                         gen_nullptr_check(s1);
1709                         M_ILD(d, s1, OFFSET(java_arrayheader, size));
1710                         emit_store_dst(jd, iptr, d);
1711
1712                         break;
1713
1714                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1715                         OOPS();
1716 #if 0
1717                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1718                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1719                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1720                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1721                                 gen_nullptr_check(s1);
1722                                 gen_bound_check;
1723                         }
1724                         emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1725                         emit_store_dst(jd, iptr, d);
1726 #endif
1727                         break;
1728
1729                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1730
1731                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1732                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1733                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1734
1735                         emit_array_checks(cd, iptr, s1, s2);
1736
1737                         M_INTMOVE(s2, REG_ITMP2);
1738                         M_ISLL_IMM(1, REG_ITMP2);
1739
1740                         N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1741                         emit_store_dst(jd, iptr, d);
1742                         break;                  
1743
1744                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1745                         OOPS();
1746 #if 0
1747                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1748                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1749                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1750                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1751                                 gen_nullptr_check(s1);
1752                                 gen_bound_check;
1753                         }
1754                         emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1755                         emit_store_dst(jd, iptr, d);
1756 #endif
1757                         break;
1758
1759                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1760                         OOPS();
1761 #if 0
1762                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1763                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1764                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1765                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1766                                 gen_nullptr_check(s1);
1767                                 gen_bound_check;
1768                         }
1769                         emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1770                         emit_store_dst(jd, iptr, d);
1771 #endif
1772                         break;
1773
1774                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1775                         OOPS();
1776 #if 0
1777                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1778                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1779                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1780                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1781                                 gen_nullptr_check(s1);
1782                                 gen_bound_check;
1783                         }
1784                         emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1785                         emit_store_dst(jd, iptr, d);
1786 #endif
1787                         break;
1788
1789                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1790                         OOPS();
1791 #if 0
1792                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1793                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1794                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1795                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1796                                 gen_nullptr_check(s1);
1797                                 gen_bound_check;
1798                         }
1799                         emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1800                         emit_store_dst(jd, iptr, d);
1801 #endif
1802                         break;
1803
1804                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1805                         OOPS();
1806 #if 0
1807                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1808                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1809                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1810                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1811                                 gen_nullptr_check(s1);
1812                                 gen_bound_check;
1813                         }
1814                         emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1815                         emit_store_dst(jd, iptr, d);
1816 #endif
1817                         break;
1818
1819                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1820                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1821                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1822                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1823                         emit_array_checks(cd, iptr, s1, s2);
1824                         
1825                         M_INTMOVE(s2, REG_ITMP2);
1826                         M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1827                         N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1828                         emit_store_dst(jd, iptr, d);
1829                         break;
1830
1831                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1832                         OOPS();
1833 #if 0
1834                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1835                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1836                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1837                                 gen_nullptr_check(s1);
1838                                 gen_bound_check;
1839                         }
1840                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1841                         emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1842 #endif
1843                         break;
1844
1845                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1846
1847                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1848                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1849                         emit_array_checks(cd, iptr, s1, s2);
1850                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1851
1852                         M_INTMOVE(s2, REG_ITMP2);
1853                         M_ISLL_IMM(1, REG_ITMP2);
1854
1855                         N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1856
1857                         break;
1858
1859                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1860                         OOPS();
1861 #if 0
1862                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1863                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1864                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1865                                 gen_nullptr_check(s1);
1866                                 gen_bound_check;
1867                         }
1868                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1869                         emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1870 #endif
1871                         break;
1872
1873                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1874                         OOPS();
1875 #if 0
1876                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1877                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1878                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1879                                 gen_nullptr_check(s1);
1880                                 gen_bound_check;
1881                         }
1882                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1883                         emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
1884 #endif
1885                         break;
1886
1887                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1888                         OOPS();
1889 #if 0
1890                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1891                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1892                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1893                                 gen_nullptr_check(s1);
1894                                 gen_bound_check;
1895                         }
1896                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1897                         emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
1898 #endif
1899                         break;
1900
1901                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1902                         OOPS();
1903 #if 0
1904                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1905                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1906                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1907                                 gen_nullptr_check(s1);
1908                                 gen_bound_check;
1909                         }
1910                         s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1911                         emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
1912 #endif
1913                         break;
1914
1915                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1916                         OOPS();
1917 #if 0
1918                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1919                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1920                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1921                                 gen_nullptr_check(s1);
1922                                 gen_bound_check;
1923                         }
1924                         s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1925                         emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
1926 #endif
1927                         break;
1928
1929                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1930
1931                         s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1932                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1933                         emit_array_checks(cd, iptr, s1, s2);
1934                         s3 = emit_load_s3(jd, iptr, REG_A1);
1935
1936                         M_INTMOVE(s1, REG_A0);
1937                         M_INTMOVE(s3, REG_A1);
1938
1939                         disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1940                         ICONST(REG_ITMP3, disp);
1941                         N_L(REG_PV, 0, REG_ITMP3, REG_PV);
1942                         M_ISUB_IMM(96, REG_SP);
1943                         M_JSR(REG_RA, REG_PV);
1944                         M_IADD_IMM(96, REG_SP);
1945                         N_BASR(REG_ITMP1, RN);
1946                         disp = (s4) (cd->mcodeptr - cd->mcodebase);
1947                         M_LDA(REG_PV, REG_ITMP1, -disp);
1948
1949                         M_TEST(REG_RESULT);
1950                         M_BEQ(0);
1951                         codegen_add_arraystoreexception_ref(cd);
1952
1953                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1954                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1955                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1956
1957                         M_INTMOVE(s2, REG_ITMP2);
1958                         M_ISLL_IMM(2, REG_ITMP2);
1959                         N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1960
1961                         /*
1962                         M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1963                         M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1964                         */
1965                         break;
1966
1967
1968                 case ICMD_BASTORECONST: /* ..., arrayref, index  ==> ...              */
1969                         OOPS();
1970 #if 0
1971                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1972                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1973                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1974                                 gen_nullptr_check(s1);
1975                                 gen_bound_check;
1976                         }
1977                         emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1978 #endif
1979                         break;
1980
1981                 case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
1982                         OOPS();
1983 #if 0
1984                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1985                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1986                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1987                                 gen_nullptr_check(s1);
1988                                 gen_bound_check;
1989                         }
1990                         emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
1991 #endif
1992                         break;
1993
1994                 case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...            */
1995                         OOPS();
1996 #if 0
1997                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1998                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1999                         if (INSTRUCTION_MUST_CHECK(iptr)) {
2000                                 gen_nullptr_check(s1);
2001                                 gen_bound_check;
2002                         }
2003                         emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2004 #endif
2005                         break;
2006
2007                 case ICMD_IASTORECONST: /* ..., arrayref, index  ==> ...              */
2008                         OOPS();
2009 #if 0
2010                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2011                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2012                         if (INSTRUCTION_MUST_CHECK(iptr)) {
2013                                 gen_nullptr_check(s1);
2014                                 gen_bound_check;
2015                         }
2016                         emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
2017 #endif
2018                         break;
2019
2020                 case ICMD_LASTORECONST: /* ..., arrayref, index  ==> ...              */
2021                         OOPS();
2022 #if 0
2023                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2024                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2025                         if (INSTRUCTION_MUST_CHECK(iptr)) {
2026                                 gen_nullptr_check(s1);
2027                                 gen_bound_check;
2028                         }
2029
2030                         if (IS_IMM32(iptr->sx.s23.s3.constval)) {
2031                                 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2032                         } else {
2033                                 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2034                                 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2035                         }
2036 #endif
2037                         break;
2038
2039                 case ICMD_AASTORECONST: /* ..., arrayref, index  ==> ...              */
2040                         OOPS();
2041 #if 0
2042                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2043                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2044                         if (INSTRUCTION_MUST_CHECK(iptr)) {
2045                                 gen_nullptr_check(s1);
2046                                 gen_bound_check;
2047                         }
2048                         emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2049 #endif
2050                         break;
2051
2052
2053                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
2054
2055                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2056                                 uf        = iptr->sx.s23.s3.uf;
2057                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2058                                 disp      = dseg_add_unique_address(cd, NULL);
2059
2060 /*                              PROFILE_CYCLE_STOP; */
2061
2062                                 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2063
2064 /*                              PROFILE_CYCLE_START; */
2065                         }
2066                         else {
2067                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2068                                 fieldtype = fi->type;
2069                                 disp      = dseg_add_address(cd, &(fi->value));
2070
2071                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2072                                         PROFILE_CYCLE_STOP;
2073
2074                                         codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2075
2076                                         PROFILE_CYCLE_START;
2077                                 }
2078                         }
2079
2080                         M_ALD(REG_ITMP1, REG_PV, disp);
2081
2082                         switch (fieldtype) {
2083                         case TYPE_INT:
2084                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2085                                 M_ILD(d, REG_ITMP1, 0);
2086                                 break;
2087                         case TYPE_LNG:
2088                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2089                                 M_LLD(d, REG_ITMP1, 0);
2090                                 break;
2091                         case TYPE_ADR:
2092                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2093                                 M_ALD(d, REG_ITMP1, 0);
2094                                 break;
2095                         case TYPE_FLT:
2096                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2097                                 M_FLD(d, REG_ITMP1, 0);
2098                                 break;
2099                         case TYPE_DBL:                          
2100                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2101                                 M_DLD(d, REG_ITMP1, 0);
2102                                 break;
2103                         }
2104
2105                         emit_store_dst(jd, iptr, d);
2106
2107                         break;
2108
2109                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
2110
2111                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2112                                 uf        = iptr->sx.s23.s3.uf;
2113                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2114                                 disp      = dseg_add_unique_address(cd, uf);
2115
2116                                 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2117                         }
2118                         else {
2119                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2120                                 fieldtype = fi->type;
2121                                 disp      = dseg_add_address(cd, &(fi->value));
2122
2123                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2124                                         codegen_addpatchref(cd, PATCHER_clinit,
2125                                                                                 fi->class, disp);
2126                         }
2127
2128                         M_ALD(REG_ITMP1, REG_PV, disp);
2129                         switch (fieldtype) {
2130                         case TYPE_INT:
2131                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2132                                 M_IST(s1, REG_ITMP1, 0);
2133                                 break;
2134                         case TYPE_LNG:
2135                                 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2136                                 M_LST(s1, REG_ITMP1, 0);
2137                                 break;
2138                         case TYPE_ADR:
2139                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2140                                 M_AST(s1, REG_ITMP1, 0);
2141                                 break;
2142                         case TYPE_FLT:
2143                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2144                                 M_FST(s1, REG_ITMP1, 0);
2145                                 break;
2146                         case TYPE_DBL:
2147                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2148                                 M_DST(s1, REG_ITMP1, 0);
2149                                 break;
2150                         }
2151                         break;
2152
2153                 case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
2154                                           /* val = value (in current instruction)     */
2155                                           /* following NOP)                           */
2156                         OOPS();
2157 #if 0
2158                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2159                                 uf        = iptr->sx.s23.s3.uf;
2160                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2161                                 disp      = dseg_add_unique_address(cd, uf);
2162
2163                                 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2164                         }
2165                         else {
2166                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2167                                 fieldtype = fi->type;
2168                                 disp      = dseg_add_address(cd, &(fi->value));
2169
2170                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2171                                         codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
2172                                                                                   0);
2173                         }
2174                         
2175                         M_ALD(REG_ITMP1, REG_PV, disp);
2176
2177                         switch (fieldtype) {
2178                         case TYPE_INT:
2179                                 M_IST(REG_ZERO, REG_ITMP1, 0);
2180                                 break;
2181                         case TYPE_LNG:
2182                                 M_LST(REG_ZERO, REG_ITMP1, 0);
2183                                 break;
2184                         case TYPE_ADR:
2185                                 M_AST(REG_ZERO, REG_ITMP1, 0);
2186                                 break;
2187                         case TYPE_FLT:
2188                                 M_FST(REG_ZERO, REG_ITMP1, 0);
2189                                 break;
2190                         case TYPE_DBL:
2191                                 M_DST(REG_ZERO, REG_ITMP1, 0);
2192                                 break;
2193                         }
2194 #endif
2195                         break;
2196
2197                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
2198
2199                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2200                         emit_nullpointer_check(cd, iptr, s1);
2201
2202                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2203                                 uf        = iptr->sx.s23.s3.uf;
2204                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2205                                 disp      = 0;
2206
2207                                 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2208                         }
2209                         else {
2210                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2211                                 fieldtype = fi->type;
2212                                 disp      = fi->offset;
2213                         }
2214
2215                         switch (fieldtype) {
2216                         case TYPE_INT:
2217                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2218                                 M_ILD(d, s1, disp);
2219                                 break;
2220                         case TYPE_LNG:
2221                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2222                                 if (GET_HIGH_REG(d) == s1) {
2223                                         M_ILD(GET_LOW_REG(d), s1, disp + 4);
2224                                         M_ILD(GET_HIGH_REG(d), s1, disp);
2225                                 }
2226                                 else {
2227                                         M_ILD(GET_LOW_REG(d), s1, disp + 4);
2228                                         M_ILD(GET_HIGH_REG(d), s1, disp);
2229                                 }
2230                                 break;
2231                         case TYPE_ADR:
2232                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2233                                 M_ALD(d, s1, disp);
2234                                 break;
2235                         case TYPE_FLT:
2236                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2237                                 M_FLD(d, s1, disp);
2238                                 break;
2239                         case TYPE_DBL:                          
2240                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2241                                 M_DLD(d, s1, disp);
2242                                 break;
2243                         }
2244                         emit_store_dst(jd, iptr, d);
2245                         break;
2246
2247                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
2248
2249                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2250                         gen_nullptr_check(s1);
2251
2252                         s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2253
2254                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2255                                 uf        = iptr->sx.s23.s3.uf;
2256                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2257                                 disp      = 0;
2258                         } 
2259                         else {
2260                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2261                                 fieldtype = fi->type;
2262                                 disp      = fi->offset;
2263                         }
2264
2265                         if (IS_INT_LNG_TYPE(fieldtype)) {
2266                                 if (IS_2_WORD_TYPE(fieldtype))
2267                                         s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2268                                 else
2269                                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2270                         }
2271                         else
2272                                 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2273
2274                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
2275                                 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2276
2277                         switch (fieldtype) {
2278                         case TYPE_INT:
2279                                 M_IST(s2, s1, disp);
2280                                 break;
2281                         case TYPE_LNG:
2282                                 /* TODO really order */
2283                                 M_IST(GET_LOW_REG(s2), s1, disp + 4);      /* keep this order */
2284                                 M_IST(GET_HIGH_REG(s2), s1, disp);         /* keep this order */
2285                                 break;
2286                         case TYPE_ADR:
2287                                 M_AST(s2, s1, disp);
2288                                 break;
2289                         case TYPE_FLT:
2290                                 M_FST(s2, s1, disp);
2291                                 break;
2292                         case TYPE_DBL:
2293                                 M_DST(s2, s1, disp);
2294                                 break;
2295                         }
2296                         break;
2297
2298                 case ICMD_PUTFIELDCONST:  /* ..., objectref, value  ==> ...           */
2299                                           /* val = value (in current instruction)     */
2300                                           /* following NOP)                           */
2301                         OOPS();
2302 #if 0
2303                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2304                         gen_nullptr_check(s1);
2305
2306                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2307                                 uf        = iptr->sx.s23.s3.uf;
2308                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2309                                 disp      = 0;
2310
2311 /*                              PROFILE_CYCLE_STOP; */
2312
2313                                 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2314
2315 /*                              PROFILE_CYCLE_START; */
2316                         } 
2317                         else {
2318                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2319                                 fieldtype = fi->type;
2320                                 disp      = fi->offset;
2321                         }
2322
2323                         switch (fieldtype) {
2324                         case TYPE_INT:
2325                         case TYPE_FLT:
2326                                 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2327                                 break;
2328                         case TYPE_LNG:
2329                         case TYPE_ADR:
2330                         case TYPE_DBL:
2331                                 /* XXX why no check for IS_IMM32? */
2332                                 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2333                                 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2334                                 break;
2335                         }
2336 #endif
2337                         break;
2338
2339
2340                 /* branch operations **************************************************/
2341
2342                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
2343
2344                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2345                         M_INTMOVE(s1, REG_ITMP1_XPTR);
2346
2347                         PROFILE_CYCLE_STOP;
2348
2349 #ifdef ENABLE_VERIFIER
2350                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2351                                 uc = iptr->sx.s23.s2.uc;
2352
2353                                 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2354                         }
2355 #endif /* ENABLE_VERIFIER */
2356
2357                         disp = dseg_add_functionptr(cd, asm_handle_exception);
2358                         M_ALD(REG_ITMP2, REG_PV, disp);
2359                         M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2360                         M_NOP;
2361
2362                         break;
2363
2364                 case ICMD_GOTO:         /* ... ==> ...                                */
2365                 case ICMD_RET:          /* ... ==> ...                                */
2366
2367                         M_BR(0);
2368                         codegen_add_branch_ref(cd, iptr->dst.block);
2369
2370                         break;
2371
2372                 case ICMD_JSR:          /* ... ==> ...                                */
2373                         OOPS();
2374 #if 0
2375                         M_JMP_IMM(0);
2376                         codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2377 #endif
2378                         break;
2379                         
2380                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
2381                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
2382                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2383                         M_TEST(s1);
2384                         switch (iptr->opc) {    
2385                                 case ICMD_IFNULL:
2386                                         M_BEQ(0);
2387                                         break;
2388                                 case ICMD_IFNONNULL:
2389                                         M_BNE(0);
2390                                         break;
2391                         }
2392                         codegen_add_branch_ref(cd, iptr->dst.block);
2393                         break;
2394
2395                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
2396                 case ICMD_IFLT:         /* ..., value ==> ...                         */
2397                 case ICMD_IFLE:         /* ..., value ==> ...                         */
2398                 case ICMD_IFNE:         /* ..., value ==> ...                         */
2399                 case ICMD_IFGT:         /* ..., value ==> ...                         */
2400                 case ICMD_IFGE:         /* ..., value ==> ...                         */
2401                         
2402                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2403
2404                         if (N_VALID_IMM(iptr->sx.val.i))
2405                                 N_CHI(s1, iptr->sx.val.i);
2406                         else {
2407                                 disp = dseg_add_s4(cd, iptr->sx.val.i);
2408                                 N_LHI(REG_ITMP2, disp);
2409                                 N_C(s1, 0, REG_ITMP2, REG_PV);
2410                         }
2411
2412                         switch (iptr->opc) {
2413                         case ICMD_IFLT:
2414                                 M_BLT(0);
2415                                 break;
2416                         case ICMD_IFLE:
2417                                 M_BLE(0);
2418                                 break;
2419                         case ICMD_IFNE:
2420                                 M_BNE(0);
2421                                 break;
2422                         case ICMD_IFGT:
2423                                 M_BGT(0);
2424                                 break;
2425                         case ICMD_IFGE:
2426                                 M_BGE(0);
2427                                 break;
2428                         case ICMD_IFEQ:
2429                                 M_BEQ(0);
2430                                 break;
2431                         }
2432                         codegen_add_branch_ref(cd, iptr->dst.block);
2433
2434                         break;
2435
2436                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
2437                 case ICMD_IF_LLE:       /* op1 = target JavaVM pc, val.l = constant   */
2438                 case ICMD_IF_LGT:
2439                 case ICMD_IF_LGE:
2440                 case ICMD_IF_LEQ:
2441                 case ICMD_IF_LNE:
2442                         {
2443
2444                                 u1 *out_ref = NULL;
2445
2446                                 /* ATTENTION: compare high words signed and low words unsigned */
2447         
2448                                 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2449
2450                                 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2451                                         N_CHI(s1, iptr->sx.val.l >> 32);
2452                                 else {
2453                                         disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2454                                         N_LHI(REG_ITMP2, disp);
2455                                         N_C(s1, 0, REG_ITMP2, REG_PV);
2456                                 }
2457
2458                                 switch(iptr->opc) {
2459                                 case ICMD_IF_LLT:
2460                                 case ICMD_IF_LLE:
2461                                         M_BLT(0);
2462                                         codegen_addreference(cd, iptr->dst.block);
2463                                         /* EQ ... fall through */
2464                                         out_ref = cd->mcodeptr;
2465                                         M_BGT(0);
2466                                         break;
2467                                 case ICMD_IF_LGT:
2468                                 case ICMD_IF_LGE:
2469                                         M_BGT(0);
2470                                         codegen_addreference(cd, iptr->dst.block);
2471                                         /* EQ ... fall through */
2472                                         out_ref = cd->mcodeptr;
2473                                         M_BLT(0);
2474                                         break;
2475                                 case ICMD_IF_LEQ: 
2476                                         /* EQ ... fall through */
2477                                         out_ref = cd->mcodeptr;
2478                                         M_BNE(0);
2479                                         break;
2480                                 case ICMD_IF_LNE:
2481                                         /* EQ ... fall through */
2482                                         M_BNE(0);
2483                                         codegen_addreference(cd, iptr->dst.block);
2484                                         break;
2485                                 default:
2486                                         assert(0);
2487                                 }
2488
2489                                 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2490
2491                                 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2492                                 N_LHI(REG_ITMP2, disp);
2493                                 N_CL(s1, 0, REG_ITMP2, REG_PV);
2494
2495                                 switch(iptr->opc) {
2496                                 case ICMD_IF_LLT:
2497                                         M_BLT(0);
2498                                         break;
2499                                 case ICMD_IF_LLE:
2500                                         M_BLE(0);
2501                                         break;
2502                                 case ICMD_IF_LGT:
2503                                         M_BGT(0);
2504                                         break;
2505                                 case ICMD_IF_LGE:
2506                                         M_BGE(0);
2507                                         break;
2508                                 case ICMD_IF_LEQ:
2509                                         M_BEQ(0);
2510                                         break;
2511                                 case ICMD_IF_LNE:
2512                                         M_BNE(0);
2513                                         break;
2514                                 default:
2515                                         assert(0);
2516                                 }
2517                                 codegen_addreference(cd, iptr->dst.block);
2518
2519                                 if (out_ref != NULL) {
2520                                         *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2521                                 }
2522
2523                         }
2524                         break;
2525
2526                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
2527                 case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
2528
2529                         /* Compare addresses as 31 bit unsigned integers */
2530
2531                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2532                         N_LA(REG_ITMP1, 0, RN, s1);
2533
2534                         s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2535                         N_LA(REG_ITMP2, 0, RN, s2);
2536
2537                         M_CMP(REG_ITMP1, REG_ITMP2);
2538
2539                         switch (iptr->opc) {
2540                                 case ICMD_IF_ACMPEQ:
2541                                         M_BEQ(0);
2542                                         break;
2543                                 case ICMD_IF_ACMPNE:
2544                                         M_BNE(0);
2545                                         break;
2546                         }
2547
2548                         codegen_add_branch_ref(cd, iptr->dst.block);
2549                         break;
2550
2551
2552                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
2553                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
2554                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
2555                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
2556                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
2557                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
2558
2559                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2560                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2561                         M_CMP(s1, s2);
2562                         switch (iptr->opc) {
2563                                 case ICMD_IF_ICMPEQ:
2564                                         M_BEQ(0);
2565                                         break;
2566                                 case ICMD_IF_ICMPNE:
2567                                         M_BNE(0);
2568                                         break;
2569                                 case ICMD_IF_ICMPLT:
2570                                         M_BLT(0);
2571                                         break;
2572                                 case ICMD_IF_ICMPGT:
2573                                         M_BGT(0);
2574                                         break;
2575                                 case ICMD_IF_ICMPLE:
2576                                         M_BLE(0);
2577                                         break;
2578                                 case ICMD_IF_ICMPGE:
2579                                         M_BGE(0);
2580                                         break;
2581                         }
2582                         codegen_add_branch_ref(cd, iptr->dst.block);
2583
2584                         break;
2585
2586                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
2587                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
2588                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
2589                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
2590                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
2591                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
2592                         {
2593
2594                                 u1 *out_ref = NULL;
2595
2596                                 /* ATTENTION: compare high words signed and low words unsigned */
2597         
2598                                 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2599                                 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2600
2601                                 N_CR(s1, s2);
2602
2603                                 switch(iptr->opc) {
2604                                 case ICMD_IF_LCMPLT:
2605                                 case ICMD_IF_LCMPLE:
2606                                         M_BLT(0);
2607                                         codegen_addreference(cd, iptr->dst.block);
2608                                         /* EQ ... fall through */
2609                                         out_ref = cd->mcodeptr;
2610                                         M_BGT(0);
2611                                         break;
2612                                 case ICMD_IF_LCMPGT:
2613                                 case ICMD_IF_LCMPGE:
2614                                         M_BGT(0);
2615                                         codegen_addreference(cd, iptr->dst.block);
2616                                         /* EQ ... fall through */
2617                                         out_ref = cd->mcodeptr;
2618                                         M_BLT(0);
2619                                         break;
2620                                 case ICMD_IF_LCMPEQ: 
2621                                         /* EQ ... fall through */
2622                                         out_ref = cd->mcodeptr;
2623                                         M_BNE(0);
2624                                         break;
2625                                 case ICMD_IF_LCMPNE:
2626                                         /* EQ ... fall through */
2627                                         M_BNE(0);
2628                                         codegen_addreference(cd, iptr->dst.block);
2629                                         break;
2630                                 default:
2631                                         assert(0);
2632                                 }
2633
2634                                 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2635                                 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2636         
2637                                 N_CLR(s1, s2);
2638
2639                                 switch(iptr->opc) {
2640                                 case ICMD_IF_LCMPLT:
2641                                         M_BLT(0);
2642                                         break;
2643                                 case ICMD_IF_LCMPLE:
2644                                         M_BLE(0);
2645                                         break;
2646                                 case ICMD_IF_LCMPGT:
2647                                         M_BGT(0);
2648                                         break;
2649                                 case ICMD_IF_LCMPGE:
2650                                         M_BGE(0);
2651                                         break;
2652                                 case ICMD_IF_LCMPEQ:
2653                                         M_BEQ(0);
2654                                         break;
2655                                 case ICMD_IF_LCMPNE:
2656                                         M_BNE(0);
2657                                         break;
2658                                 default:
2659                                         assert(0);
2660                                 }
2661
2662                                 codegen_addreference(cd, iptr->dst.block);
2663
2664                                 if (out_ref != NULL) {
2665                                         *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2666                                 }
2667
2668                         }
2669                         break;
2670
2671                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2672
2673                         REPLACEMENT_POINT_RETURN(cd, iptr);
2674                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
2675                         M_INTMOVE(s1, REG_RESULT);
2676                         goto nowperformreturn;
2677
2678                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
2679
2680                         REPLACEMENT_POINT_RETURN(cd, iptr);
2681                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
2682                         M_INTMOVE(s1, REG_RESULT);
2683
2684 #ifdef ENABLE_VERIFIER
2685                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2686                                 unresolved_class *uc = iptr->sx.s23.s2.uc;
2687
2688                                 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2689                         }
2690 #endif /* ENABLE_VERIFIER */
2691                         goto nowperformreturn;
2692
2693                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
2694
2695                         REPLACEMENT_POINT_RETURN(cd, iptr);
2696                         s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2697                         M_LNGMOVE(s1, REG_RESULT_PACKED);
2698                         goto nowperformreturn;
2699
2700                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2701                 case ICMD_DRETURN:
2702
2703                         REPLACEMENT_POINT_RETURN(cd, iptr);
2704                         s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2705                         M_FLTMOVE(s1, REG_FRESULT);
2706                         goto nowperformreturn;
2707
2708                 case ICMD_RETURN:      /* ...  ==> ...                                */
2709
2710                         REPLACEMENT_POINT_RETURN(cd, iptr);
2711
2712 nowperformreturn:
2713                         {
2714                         s4 i, p;
2715                         
2716                         p = cd->stackframesize;
2717
2718                         /* call trace function */
2719
2720 #if !defined(NDEBUG)
2721                         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2722                                 emit_verbosecall_exit(jd);
2723 #endif /* !defined(NDEBUG) */
2724
2725 #if defined(ENABLE_THREADS)
2726                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2727                                 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2728                                 M_ALD(REG_ITMP3, REG_PV, disp);
2729                                 M_CALL(REG_ITMP3);
2730
2731                                 /* we need to save the proper return value */
2732
2733                                 switch (iptr->opc) {
2734                                 case ICMD_LRETURN:
2735                                         M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2736                                         /* fall through */
2737                                 case ICMD_IRETURN:
2738                                 case ICMD_ARETURN:
2739                                         M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2740                                         break;
2741                                 case ICMD_FRETURN:
2742                                         M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2743                                         break;
2744                                 case ICMD_DRETURN:
2745                                         M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2746                                         break;
2747                                 }
2748
2749                                 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2750                                 M_JSR;
2751
2752                                 /* and now restore the proper return value */
2753
2754                                 switch (iptr->opc) {
2755                                 case ICMD_LRETURN:
2756                                         M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2757                                         /* fall through */
2758                                 case ICMD_IRETURN:
2759                                 case ICMD_ARETURN:
2760                                         M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2761                                         break;
2762                                 case ICMD_FRETURN:
2763                                         M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2764                                         break;
2765                                 case ICMD_DRETURN:
2766                                         M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2767                                         break;
2768                                 }
2769                         }
2770 #endif
2771
2772                         /* restore return address                                         */
2773
2774                         p--; M_ALD(REG_RA, REG_SP, p * 4);
2775
2776                         /* restore saved registers                                        */
2777
2778                         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2779                                 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2780                         }
2781                         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2782                                 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2783                         }
2784
2785                         /* deallocate stack                                               */
2786
2787                         if (cd->stackframesize)
2788                                 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2789
2790                         M_RET;
2791                         ALIGNCODENOP;
2792                         }
2793                         break;
2794
2795                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2796                         OOPS();
2797 #if 0
2798                         {
2799                                 s4 i, l;
2800                                 branch_target_t *table;
2801
2802                                 table = iptr->dst.table;
2803
2804                                 l = iptr->sx.s23.s2.tablelow;
2805                                 i = iptr->sx.s23.s3.tablehigh;
2806
2807                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2808                                 M_INTMOVE(s1, REG_ITMP1);
2809
2810                                 if (l != 0)
2811                                         M_ISUB_IMM(l, REG_ITMP1);
2812
2813                                 /* number of targets */
2814                                 i = i - l + 1;
2815
2816                 /* range check */
2817                                 M_ICMP_IMM(i - 1, REG_ITMP1);
2818                                 M_BA(0);
2819
2820                                 codegen_add_branch_ref(cd, table[0].block); /* default target */
2821
2822                                 /* build jump table top down and use address of lowest entry */
2823
2824                                 table += i;
2825
2826                                 while (--i >= 0) {
2827                                         dseg_add_target(cd, table->block);
2828                                         --table;
2829                                 }
2830
2831                                 /* length of dataseg after last dseg_add_target is used
2832                                    by load */
2833
2834                                 M_MOV_IMM(0, REG_ITMP2);
2835                                 dseg_adddata(cd);
2836                                 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2837                                 M_JMP(REG_ITMP1);
2838                         }
2839 #endif
2840                         break;
2841
2842
2843                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2844                         OOPS();
2845 #if 0
2846                         {
2847                                 s4 i;
2848                                 lookup_target_t *lookup;
2849
2850                                 lookup = iptr->dst.lookup;
2851
2852                                 i = iptr->sx.s23.s2.lookupcount;
2853                         
2854                                 MCODECHECK(8 + ((7 + 6) * i) + 5);
2855                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2856
2857                                 while (--i >= 0) {
2858                                         M_ICMP_IMM(lookup->value, s1);
2859                                         M_BEQ(0);
2860                                         codegen_add_branch_ref(cd, lookup->target.block);
2861                                         lookup++;
2862                                 }
2863
2864                                 M_JMP_IMM(0);
2865                         
2866                                 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2867                         }
2868 #endif
2869                         break;
2870
2871
2872                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
2873
2874                         bte = iptr->sx.s23.s3.bte;
2875                         md  = bte->md;
2876                         goto gen_method;
2877
2878                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2879                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2880                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2881                 case ICMD_INVOKEINTERFACE:
2882
2883                         REPLACEMENT_POINT_INVOKE(cd, iptr);
2884
2885                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2886                                 lm = NULL;
2887                                 um = iptr->sx.s23.s3.um;
2888                                 md = um->methodref->parseddesc.md;
2889                         }
2890                         else {
2891                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2892                                 um = NULL;
2893                                 md = lm->parseddesc;
2894                         }
2895
2896 gen_method:
2897                         s3 = md->paramcount;
2898
2899                         MCODECHECK((s3 << 1) + 64);
2900
2901                         /* copy arguments to registers or stack location */
2902
2903                         for (s3 = s3 - 1; s3 >= 0; s3--) {
2904                                 var = VAR(iptr->sx.s23.s2.args[s3]);
2905
2906                                 /* Already Preallocated? */
2907                                 if (var->flags & PREALLOC)
2908                                         continue;
2909
2910                                 if (IS_INT_LNG_TYPE(var->type)) {
2911                                         if (!md->params[s3].inmemory) {
2912                                                 if (IS_2_WORD_TYPE(var->type)) {
2913                                                         s1 = PACK_REGS(
2914                                                                 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2915                                                                 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2916                                                         );
2917                                                         d = emit_load(jd, iptr, var, s1);
2918                                                         M_LNGMOVE(d, s1);
2919                                                 }
2920                                                 else {
2921                                                         s1 = rd->argintregs[md->params[s3].regoff];
2922                                                         d = emit_load(jd, iptr, var, s1);
2923                                                         M_INTMOVE(d, s1);
2924                                                 }
2925                                         }
2926                                         else {
2927                                                 if (IS_2_WORD_TYPE(var->type)) {
2928                                                         d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2929                                                         M_LST(d, REG_SP, md->params[s3].regoff * 4);
2930                                                 }
2931                                                 else {
2932                                                         d = emit_load(jd, iptr, var, REG_ITMP1);
2933                                                         M_IST(d, REG_SP, md->params[s3].regoff * 4);
2934                                                 }
2935                                         }
2936                                 }
2937                                 else {
2938                                         if (!md->params[s3].inmemory) {
2939                                                 s1 = rd->argfltregs[md->params[s3].regoff];
2940                                                 d = emit_load(jd, iptr, var, s1);
2941                                                 M_FLTMOVE(d, s1);
2942                                         }
2943                                         else {
2944                                                 d = emit_load(jd, iptr, var, REG_FTMP1);
2945                                                 if (IS_2_WORD_TYPE(var->type))
2946                                                         M_DST(d, REG_SP, md->params[s3].regoff * 4);
2947                                                 else
2948                                                         M_FST(d, REG_SP, md->params[s3].regoff * 4);
2949                                         }
2950                                 }
2951                         }
2952
2953                         switch (iptr->opc) {
2954                         case ICMD_BUILTIN:
2955                                 disp = dseg_add_functionptr(cd, bte->fp);
2956
2957                                 N_AHI(REG_SP, -96); /* register save area as required by C abi */       
2958                                 N_LHI(REG_ITMP1, disp);
2959                                 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2960                                 break;
2961
2962                         case ICMD_INVOKESPECIAL:
2963                                 emit_nullpointer_check(cd, iptr, REG_A0);
2964                                 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr   */
2965                                 /* fall through */
2966
2967                         case ICMD_INVOKESTATIC:
2968                                 if (lm == NULL) {
2969                                         disp = dseg_add_unique_address(cd, um);
2970
2971                                         codegen_addpatchref(cd, PATCHER_invokestatic_special,
2972                                                                                 um, disp);
2973                                 }
2974                                 else
2975                                         disp = dseg_add_address(cd, lm->stubroutine);
2976
2977                                 N_LHI(REG_ITMP1, disp);
2978                                 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2979                                 break;
2980
2981                         case ICMD_INVOKEVIRTUAL:
2982                                 emit_nullpointer_check(cd, iptr, REG_A0);
2983
2984                                 if (lm == NULL) {
2985                                         codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2986
2987                                         s1 = 0;
2988                                 }
2989                                 else {
2990                                         s1 = OFFSET(vftbl_t, table[0]) +
2991                                                 sizeof(methodptr) * lm->vftblindex;
2992                                 }
2993
2994                                 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2995                                 M_ALD(REG_PV, REG_METHODPTR, s1);
2996                                 break;
2997
2998                         case ICMD_INVOKEINTERFACE:
2999                                 emit_nullpointer_check(cd, iptr, REG_A0);
3000
3001                                 /* s1 will be negative here, so use (0xFFF + s1) as displacement
3002                                  * and -0xFFF in index register (itmp1)
3003                                  */
3004
3005                                 N_LHI(REG_ITMP1, -N_DISP_MAX);
3006
3007                                 if (lm == NULL) {
3008                                         codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3009
3010                                         s1 = 0;
3011                                         s2 = 0;
3012                                 }
3013                                 else {
3014                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
3015                                                 sizeof(methodptr*) * lm->class->index +
3016                                                 N_DISP_MAX;
3017
3018                                         s2 = sizeof(methodptr) * (lm - lm->class->methods);
3019                                 }
3020
3021                                 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3022                                 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
3023                                 M_ALD(REG_PV, REG_METHODPTR, s2);
3024                                 break;
3025                         }
3026
3027                         /* generate the actual call */
3028
3029                         M_CALL(REG_PV);
3030                         REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
3031                         N_BASR(REG_ITMP1, RN);
3032                         disp = (s4) (cd->mcodeptr - cd->mcodebase);
3033                         M_LDA(REG_PV, REG_ITMP1, -disp);
3034         
3035                         /* post call finalization */
3036
3037                         if (iptr->opc == ICMD_BUILTIN) {
3038                                 N_AHI(REG_SP, 96); /* remove C abi register save area */
3039                         }
3040
3041                         /* actually only used for ICMD_BUILTIN */
3042
3043                         if (INSTRUCTION_MUST_CHECK(iptr)) {
3044                                 M_TEST(REG_RESULT);
3045                                 M_BEQ(0);
3046                                 codegen_add_fillinstacktrace_ref(cd);
3047                         }
3048
3049                         /* store return value */
3050
3051                         d = md->returntype.type;
3052
3053                         if (d != TYPE_VOID) {
3054                                 if (IS_INT_LNG_TYPE(d)) {
3055                                         if (IS_2_WORD_TYPE(d)) {
3056                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
3057                                                 M_LNGMOVE(REG_RESULT_PACKED, s1);
3058                                         }
3059                                         else {
3060                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3061                                                 M_INTMOVE(REG_RESULT, s1);
3062                                         }
3063                                 }
3064                                 else {
3065                                         s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
3066                                         M_FLTMOVE(REG_FRESULT, s1);
3067                                 }
3068                                 emit_store_dst(jd, iptr, s1);
3069                         }
3070
3071                         break;
3072
3073
3074                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
3075
3076                                       /* val.a: (classinfo*) superclass               */
3077
3078                         /*  superclass is an interface:
3079                          *      
3080                          *  OK if ((sub == NULL) ||
3081                          *         (sub->vftbl->interfacetablelength > super->index) &&
3082                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
3083                          *      
3084                          *  superclass is a class:
3085                          *      
3086                          *  OK if ((sub == NULL) || (0
3087                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3088                          *         super->vftbl->diffval));
3089                          */
3090
3091                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3092                                 /* object type cast-check */
3093
3094                                 classinfo *super;
3095                                 vftbl_t   *supervftbl;
3096                                 s4         superindex;
3097
3098                                 u1        *class_label_refs[] = { 0 }, *class_label;
3099                                 u1        *exit_label_refs[] = { 0, 0, 0, 0 };
3100
3101                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3102                                         super = NULL;
3103                                         superindex = 0;
3104                                         supervftbl = NULL;
3105                                 }
3106                                 else {
3107                                         super = iptr->sx.s23.s3.c.cls;
3108                                         superindex = super->index;
3109                                         supervftbl = super->vftbl;
3110                                 }
3111
3112 #if defined(ENABLE_THREADS)
3113                                 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3114 #endif
3115                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3116
3117                                 /* if class is not resolved, check which code to call */
3118
3119                                 if (super == NULL) {
3120                                         M_TEST(s1);
3121                                         exit_label_refs[0] = cd->mcodeptr;
3122                                         M_BEQ(0);
3123
3124                                         disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
3125
3126                                         codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3127                                                                                   iptr->sx.s23.s3.c.ref,
3128                                                                                   disp);
3129
3130                                         ICONST(REG_ITMP2, ACC_INTERFACE);
3131                                         ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3132                                         N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3133                                         class_label_refs[0] = cd->mcodeptr;
3134                                         M_BEQ(0);
3135                                 }
3136
3137                                 /* interface checkcast code */
3138
3139                                 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3140                                         if (super == NULL) {
3141                                                 codegen_add_patch_ref(cd,
3142                                                                                           PATCHER_checkcast_instanceof_interface,
3143                                                                                           iptr->sx.s23.s3.c.ref,
3144                                                                                           0);
3145                                         } else {
3146                                                 M_TEST(s1);
3147                                                 exit_label_refs[1] = cd->mcodeptr;
3148                                                 M_BEQ(0);
3149                                         }
3150
3151                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3152                                         M_ILD(REG_ITMP3, REG_ITMP2,
3153                                                   OFFSET(vftbl_t, interfacetablelength));
3154                                         M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3155                                         M_TEST(REG_ITMP3);
3156                                         M_BLE(0);
3157                                         codegen_add_classcastexception_ref(cd, s1);
3158                                         M_ALD(REG_ITMP3, REG_ITMP2,
3159                                                   (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3160                                                                 superindex * sizeof(methodptr*)));
3161                                         M_TEST(REG_ITMP3);
3162                                         M_BEQ(0);
3163                                         codegen_add_classcastexception_ref(cd, s1);
3164
3165                                         if (super == NULL) {
3166                                                 exit_label_refs[2] = cd->mcodeptr;
3167                                                 M_BR(0);
3168                                         }
3169                                 }
3170
3171                                 /* class checkcast code */
3172
3173                                 class_label = cd->mcodeptr;
3174
3175                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3176                                         if (super == NULL) {
3177                                                 disp = dseg_add_unique_address(cd, NULL);
3178
3179                                                 codegen_add_patch_ref(cd,
3180                                                                                           PATCHER_resolve_classref_to_vftbl,
3181                                                                                           iptr->sx.s23.s3.c.ref,
3182                                                                                           disp);
3183                                         }
3184                                         else {
3185                                                 disp = dseg_add_address(cd, supervftbl);
3186                                                 M_TEST(s1);
3187                                                 exit_label_refs[3] = cd->mcodeptr;
3188                                                 M_BEQ(0);
3189                                         }
3190
3191                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3192                                         M_ALD(REG_ITMP3, REG_PV, disp);
3193 #if defined(ENABLE_THREADS)
3194                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3195 #endif
3196                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3197                                         /*                              if (s1 != REG_ITMP1) { */
3198                                         /*                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3199                                         /*                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3200                                         /*  #if defined(ENABLE_THREADS) */
3201                                         /*                                      codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3202                                         /*  #endif */
3203                                         /*                                      M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3204
3205                                         /*                              } else { */
3206                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3207                                         M_ISUB(REG_ITMP3, REG_ITMP2);
3208                                         M_ALD(REG_ITMP3, REG_PV, disp);
3209                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3210 #if defined(ENABLE_THREADS)
3211                                         codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3212 #endif
3213                                         /*                              } */
3214                                         N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3215                                         /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3216                                         M_BGT(0); /* Branch if greater then */
3217                                         /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3218                                         codegen_add_classcastexception_ref(cd, s1);
3219                                 }
3220
3221                                 /* resolve labels by adding the correct displacement */
3222
3223                                 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3224                                         if (exit_label_refs[s2])
3225                                                 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3226                                 }
3227
3228                                 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3229                                         if (class_label_refs[s2])
3230                                                 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3231                                 }
3232
3233                                 d = codegen_reg_of_dst(jd, iptr, s1);
3234                         }
3235                         else {
3236                                 /* array type cast-check */
3237
3238                                 s1 = emit_load_s1(jd, iptr, REG_A0);
3239                                 M_INTMOVE(s1, REG_A0);
3240
3241                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3242                                         disp = dseg_add_unique_address(cd, NULL);
3243
3244                                         codegen_add_patch_ref(cd,
3245                                                                                   PATCHER_resolve_classref_to_classinfo,
3246                                                                                   iptr->sx.s23.s3.c.ref,
3247                                                                                   disp);
3248                                 }
3249                                 else
3250                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3251
3252                                 M_ALD(REG_A1, REG_PV, disp);
3253                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3254                                 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3255                                 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3256                                 M_JSR(REG_RA, REG_PV);
3257                                 N_BASR(REG_ITMP1, RN);
3258                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3259                                 M_LDA(REG_PV, REG_ITMP1, -disp);
3260
3261                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3262                                 M_TEST(REG_RESULT);
3263                                 M_BEQ(0);
3264                                 codegen_add_classcastexception_ref(cd, s1);
3265
3266                                 d = codegen_reg_of_dst(jd, iptr, s1);
3267                         }
3268
3269                         M_INTMOVE(s1, d);
3270                         emit_store_dst(jd, iptr, d);
3271                         break;
3272
3273                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
3274                                       /* val.a: (classinfo*) superclass               */
3275
3276                         /*  superclass is an interface:
3277                          *      
3278                          *  return (sub != NULL) &&
3279                          *         (sub->vftbl->interfacetablelength > super->index) &&
3280                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
3281                          *      
3282                          *  superclass is a class:
3283                          *      
3284                          *  return ((sub != NULL) && (0
3285                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3286                          *          super->vftbl->diffvall));
3287                          */
3288
3289                         {
3290                         classinfo *super;
3291                         vftbl_t   *supervftbl;
3292                         s4         superindex;
3293
3294                         u1        *class_label, *class_label_refs[1] = { 0 };
3295                         u1        *exit_label_refs[4] = { 0, 0, 0, 0 };
3296                         u1        *label1, *label1_refs[1] = { 0 };
3297
3298                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3299                                 super = NULL;
3300                                 superindex = 0;
3301                                 supervftbl = NULL;
3302
3303                         } else {
3304                                 super = iptr->sx.s23.s3.c.cls;
3305                                 superindex = super->index;
3306                                 supervftbl = super->vftbl;
3307                         }
3308
3309 #if defined(ENABLE_THREADS)
3310                         codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3311 #endif
3312                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3313                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3314                         if (s1 == d) {
3315                                 M_MOV(s1, REG_ITMP1);
3316                                 s1 = REG_ITMP1;
3317                         }
3318
3319                         /* if class is not resolved, check which code to call */
3320
3321                         if (super == NULL) {
3322                                 M_CLR(d);
3323                                 
3324                                 M_TEST(s1);
3325                                 exit_label_refs[0] = cd->mcodeptr;
3326                                 M_BEQ(0);
3327
3328                                 disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
3329
3330                                 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3331                                                                           iptr->sx.s23.s3.c.ref, disp);
3332
3333                                 ICONST(REG_ITMP2, ACC_INTERFACE);
3334                                 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3335                                 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3336                                 class_label_refs[0] = cd->mcodeptr;
3337                                 M_BEQ(0);
3338                         }
3339
3340                         /* interface instanceof code */
3341
3342                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3343                                 if (super == NULL) {
3344                                         /* If d == REG_ITMP2, then it's destroyed in check
3345                                            code above. */
3346                                         if (d == REG_ITMP2)
3347                                                 M_CLR(d);
3348
3349                                         codegen_add_patch_ref(cd,
3350                                                                                   PATCHER_checkcast_instanceof_interface,
3351                                                                                   iptr->sx.s23.s3.c.ref, 0);
3352                                 }
3353                                 else {
3354                                         M_CLR(d);
3355                                         M_TEST(s1);
3356                                         exit_label_refs[1] = cd->mcodeptr;
3357                                         M_BEQ(0);
3358                                 }
3359
3360                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3361                                 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3362                                 M_ASUB_IMM(superindex, REG_ITMP3);
3363                                 label1_refs[0] = cd->mcodeptr;
3364                                 M_BLE(0); 
3365                                 N_AHI(
3366                                         REG_ITMP1,
3367                                         (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3368                                                 superindex * sizeof(methodptr*))
3369                                 );
3370                                 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3371                                 
3372                                 /* d := (REG_ITMP1 != 0)  */
3373
3374                                 N_LTR(d, REG_ITMP1);
3375                                 M_BEQ(SZ_LHI);
3376                                 N_LHI(d, 1);
3377
3378                                 label1 = cd->mcodeptr;
3379
3380                                 if (super == NULL) {
3381                                         exit_label_refs[2] = cd->mcodeptr;
3382                                         M_BR(0);
3383                                 }
3384                         }
3385
3386                         /* class instanceof code */
3387
3388                         class_label = cd->mcodeptr;
3389
3390                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3391                                 if (super == NULL) {
3392                                         disp = dseg_add_unique_address(cd, NULL);
3393
3394                                         codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3395                                                                                   iptr->sx.s23.s3.c.ref,
3396                                                                                   disp);
3397                                 }
3398                                 else {
3399                                         disp = dseg_add_address(cd, supervftbl);
3400
3401                                         M_CLR(d);
3402
3403                                         M_TEST(s1);
3404                                         exit_label_refs[3] = cd->mcodeptr;
3405                                         M_BEQ(0);
3406                                 }
3407
3408                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3409                                 M_ALD(REG_ITMP2, REG_PV, disp);
3410 #if defined(ENABLE_THREADS)
3411                                 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3412 #endif
3413                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3414                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3415                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3416 #if defined(ENABLE_THREADS)
3417                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3418 #endif
3419                                 M_ISUB(REG_ITMP1, REG_ITMP3);
3420
3421                                 N_CLR(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3422                                 N_LHI(d, 0);
3423                                 M_BGT(SZ_LHI);
3424                                 N_LHI(d, 1);
3425                         }
3426
3427                         /* resolve labels by adding the correct displacement */
3428
3429                         for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3430                                 if (exit_label_refs[s2])
3431                                         *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3432                         }
3433
3434                         for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3435                                 if (class_label_refs[s2])
3436                                         *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3437                         }
3438
3439                         for (s2 = 0; s2 < sizeof(label1_refs) / sizeof(label1_refs[0]); ++s2) {
3440                                 if (label1_refs[s2])
3441                                         *(u4 *)label1_refs[s2] |= (u4)(label1 - label1_refs[s2]) / 2;
3442                         }
3443
3444                         emit_store_dst(jd, iptr, d);
3445
3446                         }
3447
3448                         break;
3449
3450                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
3451                         OOPS();
3452 #if 0
3453
3454                         /* check for negative sizes and copy sizes to stack if necessary  */
3455
3456                         MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3457
3458                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3459
3460                                 /* copy SAVEDVAR sizes to stack */
3461                                 var = VAR(iptr->sx.s23.s2.args[s1]);
3462
3463                                 /* Already Preallocated? */
3464                                 if (!(var->flags & PREALLOC)) {
3465                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
3466                                         M_LST(s2, REG_SP, s1 * 8);
3467                                 }
3468                         }
3469
3470                         /* is a patcher function set? */
3471
3472                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3473                                 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3474                                                                           iptr->sx.s23.s3.c.ref, 0);
3475                         }
3476
3477                         /* a0 = dimension count */
3478
3479                         M_MOV_IMM(iptr->s1.argcount, REG_A0);
3480
3481                         /* a1 = classinfo */
3482
3483                         M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3484
3485                         /* a2 = pointer to dimensions = stack pointer */
3486
3487                         M_MOV(REG_SP, REG_A2);
3488
3489                         M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3490                         M_CALL(REG_ITMP1);
3491
3492                         /* check for exception before result assignment */
3493
3494                         M_TEST(REG_RESULT);
3495                         M_BEQ(0);
3496                         codegen_add_fillinstacktrace_ref(cd);
3497
3498                         s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3499                         M_INTMOVE(REG_RESULT, s1);
3500                         emit_store_dst(jd, iptr, s1);
3501 #endif
3502                         break;
3503
3504                 default:
3505                         exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3506                         return false;
3507         } /* switch */
3508
3509         } /* for instruction */
3510                 
3511         MCODECHECK(512); /* XXX require a lower number? */
3512
3513         /* At the end of a basic block we may have to append some nops,
3514            because the patcher stub calling code might be longer than the
3515            actual instruction. So codepatching does not change the
3516            following block unintentionally. */
3517
3518         if (cd->mcodeptr < cd->lastmcodeptr) {
3519                 while (cd->mcodeptr < cd->lastmcodeptr) {
3520                         M_NOP;
3521                 }
3522         }
3523
3524         } /* if (bptr -> flags >= BBREACHED) */
3525         } /* for basic block */
3526
3527         dseg_createlinenumbertable(cd);
3528
3529         /* generate stubs */
3530
3531         emit_exception_stubs(jd);
3532         emit_patcher_stubs(jd);
3533 #if 0
3534         emit_replacement_stubs(jd);
3535 #endif
3536
3537         codegen_finish(jd);
3538
3539         /* everything's ok */
3540
3541         return true;
3542 }
3543
3544
3545 /* createcompilerstub **********************************************************
3546
3547    Creates a stub routine which calls the compiler.
3548         
3549 *******************************************************************************/
3550
3551 #define COMPILERSTUB_DATASIZE    (3 * SIZEOF_VOID_P)
3552 #define COMPILERSTUB_CODESIZE    (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3553
3554 #define COMPILERSTUB_SIZE        (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3555
3556
3557 u1 *createcompilerstub(methodinfo *m)
3558 {
3559         u1          *s;                     /* memory to hold the stub            */
3560         ptrint      *d;
3561         codeinfo    *code;
3562         codegendata *cd;
3563         s4           dumpsize;
3564
3565         s = CNEW(u1, COMPILERSTUB_SIZE);
3566
3567         /* set data pointer and code pointer */
3568
3569         d = (ptrint *) s;
3570         s = s + COMPILERSTUB_DATASIZE;
3571
3572         /* mark start of dump memory area */
3573
3574         dumpsize = dump_size();
3575
3576         cd = DNEW(codegendata);
3577         cd->mcodeptr = s;
3578
3579         /* Store the codeinfo pointer in the same place as in the
3580            methodheader for compiled methods. */
3581
3582         code = code_codeinfo_new(m);
3583
3584         d[0] = (ptrint) asm_call_jit_compiler;
3585         d[1] = (ptrint) m;
3586         d[2] = (ptrint) code;
3587
3588         /* code for the stub */
3589
3590         /* don't touch ITMP3 as it cointains the return address */
3591
3592         M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3593
3594         M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo  */
3595         /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3596         M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3597         N_BR(REG_PV);
3598
3599 #if defined(ENABLE_STATISTICS)
3600         if (opt_stat)
3601                 count_cstub_len += COMPILERSTUB_SIZE;
3602 #endif
3603
3604         /* release dump area */
3605
3606         dump_release(dumpsize);
3607
3608         return s;
3609 }
3610
3611
3612 /* createnativestub ************************************************************
3613
3614    Creates a stub routine which calls a native method.
3615
3616 *******************************************************************************/
3617
3618 /*
3619            arguments on stack                   \
3620 -------------------------------------------------| <- SP on nativestub entry
3621            return address                        |
3622            callee saved int regs (none)          |
3623            callee saved float regs (none)        | stack frame like in cacao
3624            local variable slots (none)           |
3625            arguments for calling methods (none) /
3626 ------------------------------------------------------------------ <- datasp 
3627            stackframe info
3628            locaref table
3629            integer arguments
3630            float arguments
3631 96 - ...   on stack parameters (nmd->memuse slots) \ stack frame like in ABI         
3632 0 - 96     register save area for callee           /
3633 -------------------------------------------------------- <- SP native method
3634                                                             ==
3635                                                             SP after method entry
3636 */
3637
3638 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3639 {
3640         methodinfo   *m;
3641         codeinfo     *code;
3642         codegendata  *cd;
3643         registerdata *rd;
3644         methoddesc   *md;
3645         s4            nativeparams;
3646         s4            i, j;                 /* count variables                    */
3647         s4            t;
3648         s4            s1, s2;
3649         s4            disp;
3650
3651         /* get required compiler data */
3652
3653         m    = jd->m;
3654         code = jd->code;
3655         cd   = jd->cd;
3656         rd   = jd->rd;
3657
3658         /* initialize variables */
3659
3660         md = m->parseddesc;
3661         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3662
3663         /* calculate stack frame size */
3664 #if 0
3665         cd->stackframesize =
3666                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3667                 sizeof(localref_table) / SIZEOF_VOID_P +
3668                 INT_ARG_CNT + FLT_ARG_CNT +
3669                 1 +                       /* functionptr, TODO: store in data segment */
3670                 nmd->memuse;
3671
3672         cd->stackframesize |= 0x1;                  /* keep stack 16-byte aligned */
3673 #endif
3674
3675         cd->stackframesize = 
3676                 1 + /* r14 - return address */ +
3677                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3678                 sizeof(localref_table) / SIZEOF_VOID_P +
3679                 1 + /* itmp3 */
3680                 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3681                 nmd->memuse + /* parameter passing */
3682                 96 / SIZEOF_VOID_P /* required by ABI */;
3683
3684         cd->stackframesize |= 0x1;                  /* keep stack 8-byte aligned */
3685
3686
3687         /* create method header */
3688
3689         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
3690         (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
3691         (void) dseg_add_unique_s4(cd, 0);                      /* IsSync          */
3692         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
3693         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
3694         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
3695         (void) dseg_addlinenumbertablesize(cd);
3696         (void) dseg_add_unique_s4(cd, 0);                      /* ExTableSize     */
3697
3698         /* generate native method profiling code */
3699 #if 0
3700         if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3701                 /* count frequency */
3702
3703                 M_MOV_IMM(code, REG_ITMP3);
3704                 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3705         }
3706 #endif
3707
3708         /* generate stub code */
3709
3710         N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3711
3712         /* save return address */
3713
3714         N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3715
3716 #if 0
3717 #if !defined(NDEBUG)
3718         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3719                 emit_verbosecall_enter(jd);
3720 #endif
3721 #endif
3722
3723         /* get function address (this must happen before the stackframeinfo) */
3724
3725         disp = dseg_add_functionptr(cd, f);
3726
3727 #if !defined(WITH_STATIC_CLASSPATH)
3728         if (f == NULL)
3729                 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3730 #endif
3731
3732         M_ILD(REG_ITMP1, REG_PV, disp);
3733
3734         j = 96 + (nmd->memuse * 4);
3735
3736         /* todo some arg registers are not volatile in C-abi terms */
3737
3738         /* save integer and float argument registers */
3739
3740         for (i = 0; i < md->paramcount; i++) {
3741                 if (! md->params[i].inmemory) {
3742                         s1 = md->params[i].regoff;
3743
3744                         if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3745                                 if (IS_2_WORD_TYPE(t)) {
3746                                         /* todo store multiple */
3747                                         N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3748                                         N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3749                                 } else {
3750                                         N_ST(rd->argintregs[s1], j, RN, REG_SP);
3751                                 }
3752                         } else {
3753                                 if (IS_2_WORD_TYPE(t)) {
3754                                         N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3755                                 } else {
3756                                         N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3757                                 }
3758                         }
3759
3760                         j += 8;
3761                 }
3762         }
3763
3764         N_ST(REG_ITMP1, j, RN, REG_SP);
3765
3766         /* create dynamic stack info */
3767
3768         N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3769         N_LR(REG_A1, REG_PV); /* pv */
3770         N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3771         N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3772
3773         disp = dseg_add_functionptr(cd, codegen_start_native_call);
3774         M_ILD(REG_ITMP1, REG_PV, disp);
3775
3776         M_CALL(REG_ITMP1); /* call */
3777
3778         /* restore integer and float argument registers */
3779
3780         j = 96 + (nmd->memuse * 4);
3781
3782         for (i = 0; i < md->paramcount; i++) {
3783                 if (! md->params[i].inmemory) {
3784                         s1 = md->params[i].regoff;
3785
3786                         if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3787                                 if (IS_2_WORD_TYPE(t)) {
3788                                         /* todo load multiple ! */
3789                                         N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3790                                         N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3791                                 } else {
3792                                         N_L(rd->argintregs[s1], j, RN, REG_SP);
3793                                 }
3794                         } else {
3795                                 if (IS_2_WORD_TYPE(t)) {
3796                                         N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3797                                 } else {
3798                                         N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3799                                 }
3800                         }
3801
3802                         j += 8;
3803                 }
3804         }
3805
3806         N_L(REG_ITMP1, j, RN, REG_SP);
3807
3808         /* copy or spill arguments to new locations */
3809
3810         for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3811                 t = md->paramtypes[i].type;
3812
3813                 if (IS_INT_LNG_TYPE(t)) {
3814
3815                         if (!md->params[i].inmemory) {
3816
3817                                 s1 = rd->argintregs[md->params[i].regoff];
3818
3819                                 if (!nmd->params[j].inmemory) {
3820                                         s2 = rd->argintregs[nmd->params[j].regoff];
3821                                         if (IS_2_WORD_TYPE(t)) {
3822                                                 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3823                                                 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3824                                         } else {
3825                                                 N_LR(s2, s1);
3826                                         }
3827                                 } else {
3828                                         s2 = nmd->params[j].regoff;
3829                                         if (IS_2_WORD_TYPE(t)) {
3830                                                 N_STM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3831                                         } else {
3832                                                 N_ST(s1, 96 + (s2 * 4), RN, REG_SP);
3833                                         }
3834                                 }
3835
3836                         } else {
3837                                 s1 = md->params[i].regoff + cd->stackframesize + 1;   /* + 1 (RA) */
3838                                 s2 = nmd->params[j].regoff;
3839                                 
3840                                 if (IS_2_WORD_TYPE(t)) {
3841                                         N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3842                                 } else {
3843                                         N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3844                                 }
3845                         }
3846
3847                 } else {
3848                         /* We only copy spilled float arguments, as the float argument    */
3849                         /* registers keep unchanged.                                      */
3850
3851                         if (md->params[i].inmemory) {
3852                                 s1 = md->params[i].regoff + cd->stackframesize + 1;   /* + 1 (RA) */
3853                                 s2 = nmd->params[j].regoff;
3854
3855                                 if (IS_2_WORD_TYPE(t)) {
3856                                         N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3857                                 } else {
3858                                         N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3859                                 }
3860                         }
3861                 }
3862         }
3863
3864         /* put class into second argument register */
3865
3866         if (m->flags & ACC_STATIC) {
3867                 disp = dseg_add_address(cd, m->class);
3868                 M_ILD(REG_A1, REG_PV, disp);
3869         }
3870
3871         /* put env into first argument register */
3872
3873         disp = dseg_add_address(cd, _Jv_env);
3874         M_ILD(REG_A0, REG_PV, disp);
3875
3876         /* do the native function call */
3877
3878         M_CALL(REG_ITMP1); /* call */
3879
3880         /* save return value */
3881
3882         t = md->returntype.type;
3883
3884         if (t != TYPE_VOID) {
3885                 if (IS_INT_LNG_TYPE(t)) {
3886                         if (IS_2_WORD_TYPE(t)) {
3887                                 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3888                         } else {
3889                                 N_ST(REG_RESULT, 96, RN, REG_SP);
3890                         }
3891                 } else {
3892                         if (IS_2_WORD_TYPE(t)) {
3893                                 N_STD(REG_FRESULT, 96, RN, REG_SP);
3894                         } else {
3895                                 N_STE(REG_FRESULT, 96, RN, REG_SP);
3896                         }
3897                 }
3898         }
3899
3900 #if 0
3901 #if !defined(NDEBUG)
3902         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3903                 emit_verbosecall_exit(jd);
3904 #endif
3905 #endif
3906
3907         /* remove native stackframe info */
3908
3909         N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3910         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3911         M_ILD(REG_ITMP1, REG_PV, disp);
3912         M_CALL(REG_ITMP1);
3913         N_LR(REG_ITMP3, REG_RESULT);
3914
3915         /* restore return value */
3916
3917         if (t != TYPE_VOID) {
3918                 if (IS_INT_LNG_TYPE(t)) {
3919                         if (IS_2_WORD_TYPE(t)) {
3920                                 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3921                         } else {
3922                                 N_L(REG_RESULT, 96, RN, REG_SP);
3923                         }
3924                 } else {
3925                         if (IS_2_WORD_TYPE(t)) {
3926                                 N_LD(REG_FRESULT, 96, RN, REG_SP);
3927                         } else {
3928                                 N_LE(REG_FRESULT, 96, RN, REG_SP);
3929                         }
3930                 }
3931         }
3932
3933         /* load return address */
3934         
3935         N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3936
3937         /* remove stackframe */
3938
3939         N_AHI(REG_SP, cd->stackframesize * 4);
3940
3941         /* test for exception */
3942
3943         N_LTR(REG_ITMP3, REG_ITMP3);
3944         N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3945
3946         /* return */
3947
3948         N_BCR(DD_ANY, REG_ITMP2); 
3949
3950         /* handle exception */
3951
3952         M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3953         M_ALD(REG_ITMP2_XPC, REG_SP, (cd->stackframesize - 1) * 4);     /* get return address from stack */
3954 #if 0
3955         /* TODO */
3956         M_ASUB_IMM(3, REG_ITMP2_XPC);                                    /* callq */
3957 #endif
3958         disp = dseg_add_functionptr(cd, /*asm_handle_nat_exception*/ panic);
3959         N_AHI(REG_SP, 96);
3960         M_ALD(REG_ITMP3, REG_PV, disp);
3961         M_JMP(RN, REG_ITMP3);
3962
3963         /* generate patcher stubs */
3964
3965         emit_patcher_stubs(jd);
3966
3967         codegen_finish(jd);
3968
3969         return code->entrypoint;
3970         return NULL;
3971 }
3972
3973 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3974         codegendata *cd = jd->cd;
3975         s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3976         if (reg == 0) {
3977                 M_MOV(reg, tempregnum);
3978                 return tempregnum;
3979         } else {
3980                 return reg;
3981         }
3982 }
3983
3984 /*
3985  * These are local overrides for various environment variables in Emacs.
3986  * Please do not remove this and leave it at the end of the file, where
3987  * Emacs will automagically detect them.
3988  * ---------------------------------------------------------------------
3989  * Local variables:
3990  * mode: c
3991  * indent-tabs-mode: t
3992  * c-basic-offset: 4
3993  * tab-width: 4
3994  * End:
3995  * vim:noexpandtab:sw=4:ts=4:
3996  */