* src/vm/jit/s390/emit.c,
[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 7581 2007-03-26 07:23:16Z 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
1201                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1202                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1203                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1204                         if (s2 == d)
1205                                 M_IAND(s1, d);
1206                         else {
1207                                 M_INTMOVE(s1, d);
1208                                 M_IAND(s2, d);
1209                         }
1210                         emit_store_dst(jd, iptr, d);
1211
1212                         break;
1213
1214                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1215
1216                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1217                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1218                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1219                         if (s2 == d)
1220                                 M_IOR(s1, d);
1221                         else {
1222                                 M_INTMOVE(s1, d);
1223                                 M_IOR(s2, d);
1224                         }
1225                         emit_store_dst(jd, iptr, d);
1226
1227                         break;
1228
1229                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1230
1231                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1232                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1233                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1234                         if (s2 == d)
1235                                 M_IXOR(s1, d);
1236                         else {
1237                                 M_INTMOVE(s1, d);
1238                                 M_IXOR(s2, d);
1239                         }
1240                         emit_store_dst(jd, iptr, d);
1241
1242                         break;
1243
1244
1245
1246                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
1247                                       /* sx.val.i = constant                             */
1248                         OOPS();
1249 #if 0
1250                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1251                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1252                         M_INTMOVE(s1, d);
1253                         M_IAND_IMM(iptr->sx.val.i, d);
1254                         emit_store_dst(jd, iptr, d);
1255 #endif
1256                         break;
1257
1258                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1259                         OOPS();
1260 #if 0
1261                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1262                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1263                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1264                         if (s2 == d)
1265                                 M_LAND(s1, d);
1266                         else {
1267                                 M_INTMOVE(s1, d);
1268                                 M_LAND(s2, d);
1269                         }
1270                         emit_store_dst(jd, iptr, d);
1271 #endif
1272                         break;
1273
1274                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1275                                       /* sx.val.l = constant                             */
1276
1277                         s3 = iptr->sx.val.l & 0xffffffff;
1278                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1279                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1280                         if ((s3 >= 0) && (s3 <= 65535))
1281                                 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1282                         else {
1283                                 ICONST(REG_ITMP3, s3);
1284                                 M_AND(s1, REG_ITMP3, GET_LOW_REG(d));
1285                         }
1286                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1287                         s3 = iptr->sx.val.l >> 32;
1288                         if ((s3 >= 0) && (s3 <= 65535))
1289                                 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1290                         else {
1291                                 ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
1292                                 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1293                         }
1294                         emit_store_dst(jd, iptr, d);
1295
1296                         OOPS();
1297 #if 0
1298                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1299                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1300                         M_INTMOVE(s1, d);
1301                         if (IS_IMM32(iptr->sx.val.l))
1302                                 M_LAND_IMM(iptr->sx.val.l, d);
1303                         else {
1304                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1305                                 M_LAND(REG_ITMP2, d);
1306                         }
1307                         emit_store_dst(jd, iptr, d);
1308 #endif
1309                         break;
1310
1311                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
1312                                       /* sx.val.i = constant                             */
1313                         OOPS();
1314 #if 0
1315                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1316                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1317                         M_INTMOVE(s1, d);
1318                         M_IOR_IMM(iptr->sx.val.i, d);
1319                         emit_store_dst(jd, iptr, d);
1320 #endif
1321                         break;
1322
1323                 case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1324                         OOPS();
1325 #if 0
1326                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1327                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1328                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1329                         if (s2 == d)
1330                                 M_LOR(s1, d);
1331                         else {
1332                                 M_INTMOVE(s1, d);
1333                                 M_LOR(s2, d);
1334                         }
1335                         emit_store_dst(jd, iptr, d);
1336 #endif
1337                         break;
1338
1339                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1340                                       /* sx.val.l = constant                             */
1341                         OOPS();
1342 #if 0
1343                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1344                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1345                         M_INTMOVE(s1, d);
1346                         if (IS_IMM32(iptr->sx.val.l))
1347                                 M_LOR_IMM(iptr->sx.val.l, d);
1348                         else {
1349                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1350                                 M_LOR(REG_ITMP2, d);
1351                         }
1352                         emit_store_dst(jd, iptr, d);
1353 #endif
1354                         break;
1355
1356                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1357                                       /* sx.val.i = constant                             */
1358                         OOPS();
1359 #if 0
1360                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1361                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1362                         M_INTMOVE(s1, d);
1363                         M_IXOR_IMM(iptr->sx.val.i, d);
1364                         emit_store_dst(jd, iptr, d);
1365 #endif
1366                         break;
1367
1368                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1369                         OOPS();
1370 #if 0
1371                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1372                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1373                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1374                         if (s2 == d)
1375                                 M_LXOR(s1, d);
1376                         else {
1377                                 M_INTMOVE(s1, d);
1378                                 M_LXOR(s2, d);
1379                         }
1380                         emit_store_dst(jd, iptr, d);
1381 #endif
1382                         break;
1383
1384                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1385                                       /* sx.val.l = constant                             */
1386                         OOPS();
1387 #if 0
1388                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1389                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1390                         M_INTMOVE(s1, d);
1391                         if (IS_IMM32(iptr->sx.val.l))
1392                                 M_LXOR_IMM(iptr->sx.val.l, d);
1393                         else {
1394                                 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1395                                 M_LXOR(REG_ITMP2, d);
1396                         }
1397                         emit_store_dst(jd, iptr, d);
1398 #endif
1399                         break;
1400
1401
1402                 /* floating operations ************************************************/
1403
1404                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1405                         OOPS();
1406 #if 0
1407                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1408                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1409                         disp = dseg_add_s4(cd, 0x80000000);
1410                         M_FLTMOVE(s1, d);
1411                         emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1412                         emit_xorps_reg_reg(cd, REG_FTMP2, d);
1413                         emit_store_dst(jd, iptr, d);
1414 #endif
1415                         break;
1416
1417                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1418                         OOPS();
1419 #if 0
1420                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1421                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1422                         disp = dseg_add_s8(cd, 0x8000000000000000);
1423                         M_FLTMOVE(s1, d);
1424                         emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1425                         emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1426                         emit_store_dst(jd, iptr, d);
1427 #endif
1428                         break;
1429
1430                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1431                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1432                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1433                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1434                         if (s2 == d)
1435                                 M_FADD(s1, d);
1436                         else {
1437                                 M_FLTMOVE(s1, d);
1438                                 M_FADD(s2, d);
1439                         }
1440                         emit_store_dst(jd, iptr, d);
1441                         break;
1442
1443                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1444                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1445                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1446                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1447                         if (s2 == d)
1448                                 M_DADD(s1, d);
1449                         else {
1450                                 M_FLTMOVE(s1, d);
1451                                 M_DADD(s2, d);
1452                         }
1453                         emit_store_dst(jd, iptr, d);
1454                         break;
1455
1456                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1457                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1458                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1459                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1460
1461                         M_FLTMOVE(s1, d);
1462                         M_FSUB(s2, d);
1463                         emit_store_dst(jd, iptr, d);
1464                         break;
1465
1466                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1467                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1468                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1469                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1470
1471                         M_FLTMOVE(s1, d);
1472                         M_DSUB(s2, d);
1473                         emit_store_dst(jd, iptr, d);
1474                         break;
1475
1476                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1477                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1478                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1479                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1480                         if (s2 == d)
1481                                 M_FMUL(s1, d);
1482                         else {
1483                                 M_FLTMOVE(s1, d);
1484                                 M_FMUL(s2, d);
1485                         }
1486                         emit_store_dst(jd, iptr, d);
1487                         break;
1488
1489                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1490                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1491                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1492                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1493                         if (s2 == d)
1494                                 M_DMUL(s1, d);
1495                         else {
1496                                 M_FLTMOVE(s1, d);
1497                                 M_DMUL(s2, d);
1498                         }
1499                         emit_store_dst(jd, iptr, d);
1500                         break;
1501
1502                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1503                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1504                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1505                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1506
1507                         M_FLTMOVE(s1, d);
1508                         M_FDIV(s2, d);
1509                         emit_store_dst(jd, iptr, d);
1510                         break;
1511
1512                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1513                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1514                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1515                         s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1516
1517                         M_FLTMOVE(s1, d);
1518                         M_DDIV(s2, d);
1519                         emit_store_dst(jd, iptr, d);
1520                         break;
1521
1522                 case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
1523                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1524                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1525                         M_CVTIF(s1, d);
1526                         emit_store_dst(jd, iptr, d);
1527                         break;
1528
1529                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
1530                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1531                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1532                         M_CVTID(s1, d);
1533                         emit_store_dst(jd, iptr, d);
1534                         break;
1535
1536                 case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
1537                         OOPS();
1538 #if 0
1539                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1540                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1541                         M_CVTLF(s1, d);
1542                         emit_store_dst(jd, iptr, d);
1543 #endif
1544                         break;
1545                         
1546                 case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
1547                         OOPS();
1548 #if 0
1549                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1550                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1551                         M_CVTLD(s1, d);
1552                         emit_store_dst(jd, iptr, d);
1553 #endif
1554                         break;
1555                         
1556                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1557                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1558                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1559                         M_CVTFI(s1, d);
1560                         emit_store_dst(jd, iptr, d);
1561                         /* TODO: corner cases ? */
1562                         break;
1563
1564                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
1565                         OOPS();
1566 #if 0
1567                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1568                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1569                         M_CVTDI(s1, d);
1570                         M_ICMP_IMM(0x80000000, d);                        /* corner cases */
1571                         disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1572                                 ((REG_RESULT == d) ? 0 : 3);
1573                         M_BNE(disp);
1574                         M_FLTMOVE(s1, REG_FTMP1);
1575                         M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1576                         M_CALL(REG_ITMP2);
1577                         M_INTMOVE(REG_RESULT, d);
1578                         emit_store_dst(jd, iptr, d);
1579 #endif
1580                         break;
1581
1582                 case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
1583                         OOPS();
1584 #if 0
1585                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1586                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1587                         M_CVTFL(s1, d);
1588                         M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1589                         M_LCMP(REG_ITMP2, d);                             /* corner cases */
1590                         disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1591                                 ((REG_RESULT == d) ? 0 : 3);
1592                         M_BNE(disp);
1593                         M_FLTMOVE(s1, REG_FTMP1);
1594                         M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1595                         M_CALL(REG_ITMP2);
1596                         M_INTMOVE(REG_RESULT, d);
1597                         emit_store_dst(jd, iptr, d);
1598 #endif
1599                         break;
1600
1601                 case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
1602                         OOPS();
1603 #if 0
1604                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1605                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1606                         M_CVTDL(s1, d);
1607                         M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1608                         M_LCMP(REG_ITMP2, d);                             /* corner cases */
1609                         disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1610                                 ((REG_RESULT == d) ? 0 : 3);
1611                         M_BNE(disp);
1612                         M_FLTMOVE(s1, REG_FTMP1);
1613                         M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1614                         M_CALL(REG_ITMP2);
1615                         M_INTMOVE(REG_RESULT, d);
1616                         emit_store_dst(jd, iptr, d);
1617 #endif
1618                         break;
1619
1620                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1621                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1622                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1623                         M_CVTFD(s1, d);
1624                         emit_store_dst(jd, iptr, d);
1625                         break;
1626
1627                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
1628                         OOPS();
1629 #if 0
1630                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1631                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1632                         M_CVTDF(s1, d);
1633                         emit_store_dst(jd, iptr, d);
1634 #endif
1635                         break;
1636
1637                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1638                                           /* == => 0, < => 1, > => -1 */
1639                 case ICMD_DCMPL:
1640
1641
1642                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1643                                           /* == => 0, < => 1, > => -1 */
1644                 case ICMD_DCMPG:
1645
1646                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1647                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1648                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1649
1650                         switch (iptr->opc) {
1651                                 case ICMD_FCMPG:
1652                                 case ICMD_FCMPL:
1653                                         N_CEBR(s1, s2);
1654                                         break;
1655                                 case ICMD_DCMPG:
1656                                 case ICMD_DCMPL:
1657                                         N_CDBR(s1, s2);
1658                                         break;  
1659                         }
1660
1661                         N_BRC( /* load 1 */
1662                                 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1663                                 SZ_BRC + SZ_BRC + SZ_BRC
1664                         );
1665
1666                         N_BRC( /* load -1 */
1667                                 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1668                                 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1669                         );
1670
1671                         N_BRC( /* load 0 */
1672                                 DD_E,
1673                                 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1674                         );
1675
1676                         N_LHI(d, 1); /* GT */
1677                         M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1678                         N_LHI(d, -1); /* LT */
1679                         M_BR(SZ_BRC + SZ_LHI);
1680                         N_LHI(d, 0); /* EQ */
1681
1682                         emit_store_dst(jd, iptr, d);
1683
1684                         break;
1685
1686
1687                 /* memory operations **************************************************/
1688
1689                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., (int) length        */
1690
1691                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1692                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1693                         gen_nullptr_check(s1);
1694                         M_ILD(d, s1, OFFSET(java_arrayheader, size));
1695                         emit_store_dst(jd, iptr, d);
1696
1697                         break;
1698
1699                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1700                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1701                         s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1702                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1703
1704                         emit_array_checks(cd, iptr, s1, s2);
1705
1706                         N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1707                         /* TODO improove this */
1708                         N_SLL(d, 24, RN);
1709                         N_SRL(d, 24, RN);
1710                         emit_store_dst(jd, iptr, d);
1711                         break;
1712
1713                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1714
1715                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1716                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1717                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1718
1719                         emit_array_checks(cd, iptr, s1, s2);
1720
1721                         M_INTMOVE(s2, REG_ITMP2);
1722                         M_ISLL_IMM(1, REG_ITMP2);
1723
1724                         N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1725                         emit_store_dst(jd, iptr, d);
1726                         break;                  
1727
1728                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1729                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1730                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1731                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1732
1733                         emit_array_checks(cd, iptr, s1, s2);
1734
1735                         M_INTMOVE(s2, REG_ITMP2);
1736                         M_ISLL_IMM(1, REG_ITMP2);
1737
1738                         N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1739                         emit_store_dst(jd, iptr, d);
1740                         break;
1741
1742                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1743                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1744                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1745                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1746                         emit_array_checks(cd, iptr, s1, s2);
1747                         
1748                         M_INTMOVE(s2, REG_ITMP2);
1749                         M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1750                         N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1751                         emit_store_dst(jd, iptr, d);
1752                         break;
1753
1754                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1755                         OOPS();
1756 #if 0
1757                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1758                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1759                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1760                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1761                                 gen_nullptr_check(s1);
1762                                 gen_bound_check;
1763                         }
1764                         emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1765                         emit_store_dst(jd, iptr, d);
1766 #endif
1767                         break;
1768
1769                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1770                         OOPS();
1771 #if 0
1772                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1773                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1774                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1775                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1776                                 gen_nullptr_check(s1);
1777                                 gen_bound_check;
1778                         }
1779                         emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1780                         emit_store_dst(jd, iptr, d);
1781 #endif
1782                         break;
1783
1784                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1785                         OOPS();
1786 #if 0
1787                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1788                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1789                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1790                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1791                                 gen_nullptr_check(s1);
1792                                 gen_bound_check;
1793                         }
1794                         emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1795                         emit_store_dst(jd, iptr, d);
1796 #endif
1797                         break;
1798
1799                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1800                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1801                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1802                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1803                         emit_array_checks(cd, iptr, s1, s2);
1804                         
1805                         M_INTMOVE(s2, REG_ITMP2);
1806                         M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1807                         N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1808                         emit_store_dst(jd, iptr, d);
1809                         break;
1810
1811                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1812                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1813                         s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1814                         emit_array_checks(cd, iptr, s1, s2);
1815                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1816
1817                         N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1818                         break;
1819
1820                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1821
1822                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1823                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1824                         emit_array_checks(cd, iptr, s1, s2);
1825                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1826
1827                         M_INTMOVE(s2, REG_ITMP2);
1828                         M_ISLL_IMM(1, REG_ITMP2);
1829
1830                         N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1831
1832                         break;
1833
1834                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1835                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1836                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1837                         emit_array_checks(cd, iptr, s1, s2);
1838                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1839
1840                         M_INTMOVE(s2, REG_ITMP2);
1841                         M_ISLL_IMM(1, REG_ITMP2);
1842
1843                         N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1844                         break;
1845
1846                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
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(2, REG_ITMP2);
1854
1855                         N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1856                         break;
1857
1858                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1859                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1860                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1861                         emit_array_checks(cd, iptr, s1, s2);
1862
1863                         M_INTMOVE(s2, REG_ITMP2);
1864                         M_ISLL_IMM(3, REG_ITMP2);
1865
1866                         s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1867                         N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1868                         s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1869                         N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1870                         break;
1871
1872                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1873                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1874                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1875                         emit_array_checks(cd, iptr, s1, s2);
1876                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1877
1878                         M_INTMOVE(s2, REG_ITMP2);
1879                         M_ISLL_IMM(2, REG_ITMP2);
1880
1881                         N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1882                         break;
1883
1884                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1885                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1886                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1887                         emit_array_checks(cd, iptr, s1, s2);
1888                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1889
1890                         M_INTMOVE(s2, REG_ITMP2);
1891                         M_ISLL_IMM(3, REG_ITMP2);
1892
1893                         N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1894                         break;
1895
1896                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1897
1898                         s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1899                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1900                         emit_array_checks(cd, iptr, s1, s2);
1901                         s3 = emit_load_s3(jd, iptr, REG_A1);
1902
1903                         M_INTMOVE(s1, REG_A0);
1904                         M_INTMOVE(s3, REG_A1);
1905
1906                         disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1907                         ICONST(REG_ITMP3, disp);
1908                         N_L(REG_PV, 0, REG_ITMP3, REG_PV);
1909                         M_ISUB_IMM(96, REG_SP);
1910                         M_JSR(REG_RA, REG_PV);
1911                         M_IADD_IMM(96, REG_SP);
1912                         N_BASR(REG_ITMP1, RN);
1913                         disp = (s4) (cd->mcodeptr - cd->mcodebase);
1914                         M_LDA(REG_PV, REG_ITMP1, -disp);
1915
1916                         M_TEST(REG_RESULT);
1917                         M_BEQ(0);
1918                         codegen_add_arraystoreexception_ref(cd);
1919
1920                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1921                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1922                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1923
1924                         M_INTMOVE(s2, REG_ITMP2);
1925                         M_ISLL_IMM(2, REG_ITMP2);
1926                         N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1927
1928                         /*
1929                         M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1930                         M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1931                         */
1932                         break;
1933
1934
1935                 case ICMD_BASTORECONST: /* ..., arrayref, index  ==> ...              */
1936                         OOPS();
1937 #if 0
1938                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1939                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1940                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1941                                 gen_nullptr_check(s1);
1942                                 gen_bound_check;
1943                         }
1944                         emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1945 #endif
1946                         break;
1947
1948                 case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
1949                         OOPS();
1950 #if 0
1951                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1952                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1953                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1954                                 gen_nullptr_check(s1);
1955                                 gen_bound_check;
1956                         }
1957                         emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
1958 #endif
1959                         break;
1960
1961                 case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...            */
1962                         OOPS();
1963 #if 0
1964                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1965                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1966                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1967                                 gen_nullptr_check(s1);
1968                                 gen_bound_check;
1969                         }
1970                         emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1971 #endif
1972                         break;
1973
1974                 case ICMD_IASTORECONST: /* ..., arrayref, index  ==> ...              */
1975                         OOPS();
1976 #if 0
1977                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1978                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1979                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1980                                 gen_nullptr_check(s1);
1981                                 gen_bound_check;
1982                         }
1983                         emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
1984 #endif
1985                         break;
1986
1987                 case ICMD_LASTORECONST: /* ..., arrayref, index  ==> ...              */
1988                         OOPS();
1989 #if 0
1990                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1991                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1992                         if (INSTRUCTION_MUST_CHECK(iptr)) {
1993                                 gen_nullptr_check(s1);
1994                                 gen_bound_check;
1995                         }
1996
1997                         if (IS_IMM32(iptr->sx.s23.s3.constval)) {
1998                                 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
1999                         } else {
2000                                 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2001                                 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2002                         }
2003 #endif
2004                         break;
2005
2006                 case ICMD_AASTORECONST: /* ..., arrayref, index  ==> ...              */
2007                         OOPS();
2008 #if 0
2009                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2010                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2011                         if (INSTRUCTION_MUST_CHECK(iptr)) {
2012                                 gen_nullptr_check(s1);
2013                                 gen_bound_check;
2014                         }
2015                         emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2016 #endif
2017                         break;
2018
2019
2020                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
2021
2022                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2023                                 uf        = iptr->sx.s23.s3.uf;
2024                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2025                                 disp      = dseg_add_unique_address(cd, NULL);
2026
2027 /*                              PROFILE_CYCLE_STOP; */
2028
2029                                 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2030
2031 /*                              PROFILE_CYCLE_START; */
2032                         }
2033                         else {
2034                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2035                                 fieldtype = fi->type;
2036                                 disp      = dseg_add_address(cd, &(fi->value));
2037
2038                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2039                                         PROFILE_CYCLE_STOP;
2040
2041                                         codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2042
2043                                         PROFILE_CYCLE_START;
2044                                 }
2045                         }
2046
2047                         M_ALD(REG_ITMP1, REG_PV, disp);
2048
2049                         switch (fieldtype) {
2050                         case TYPE_INT:
2051                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2052                                 M_ILD(d, REG_ITMP1, 0);
2053                                 break;
2054                         case TYPE_LNG:
2055                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2056                                 M_LLD(d, REG_ITMP1, 0);
2057                                 break;
2058                         case TYPE_ADR:
2059                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2060                                 M_ALD(d, REG_ITMP1, 0);
2061                                 break;
2062                         case TYPE_FLT:
2063                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2064                                 M_FLD(d, REG_ITMP1, 0);
2065                                 break;
2066                         case TYPE_DBL:                          
2067                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2068                                 M_DLD(d, REG_ITMP1, 0);
2069                                 break;
2070                         }
2071
2072                         emit_store_dst(jd, iptr, d);
2073
2074                         break;
2075
2076                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
2077
2078                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2079                                 uf        = iptr->sx.s23.s3.uf;
2080                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2081                                 disp      = dseg_add_unique_address(cd, uf);
2082
2083                                 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2084                         }
2085                         else {
2086                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2087                                 fieldtype = fi->type;
2088                                 disp      = dseg_add_address(cd, &(fi->value));
2089
2090                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2091                                         codegen_addpatchref(cd, PATCHER_clinit,
2092                                                                                 fi->class, disp);
2093                         }
2094
2095                         M_ALD(REG_ITMP1, REG_PV, disp);
2096                         switch (fieldtype) {
2097                         case TYPE_INT:
2098                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2099                                 M_IST(s1, REG_ITMP1, 0);
2100                                 break;
2101                         case TYPE_LNG:
2102                                 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2103                                 M_LST(s1, REG_ITMP1, 0);
2104                                 break;
2105                         case TYPE_ADR:
2106                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2107                                 M_AST(s1, REG_ITMP1, 0);
2108                                 break;
2109                         case TYPE_FLT:
2110                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2111                                 M_FST(s1, REG_ITMP1, 0);
2112                                 break;
2113                         case TYPE_DBL:
2114                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2115                                 M_DST(s1, REG_ITMP1, 0);
2116                                 break;
2117                         }
2118                         break;
2119
2120                 case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
2121                                           /* val = value (in current instruction)     */
2122                                           /* following NOP)                           */
2123                         OOPS();
2124 #if 0
2125                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2126                                 uf        = iptr->sx.s23.s3.uf;
2127                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2128                                 disp      = dseg_add_unique_address(cd, uf);
2129
2130                                 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2131                         }
2132                         else {
2133                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2134                                 fieldtype = fi->type;
2135                                 disp      = dseg_add_address(cd, &(fi->value));
2136
2137                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2138                                         codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
2139                                                                                   0);
2140                         }
2141                         
2142                         M_ALD(REG_ITMP1, REG_PV, disp);
2143
2144                         switch (fieldtype) {
2145                         case TYPE_INT:
2146                                 M_IST(REG_ZERO, REG_ITMP1, 0);
2147                                 break;
2148                         case TYPE_LNG:
2149                                 M_LST(REG_ZERO, REG_ITMP1, 0);
2150                                 break;
2151                         case TYPE_ADR:
2152                                 M_AST(REG_ZERO, REG_ITMP1, 0);
2153                                 break;
2154                         case TYPE_FLT:
2155                                 M_FST(REG_ZERO, REG_ITMP1, 0);
2156                                 break;
2157                         case TYPE_DBL:
2158                                 M_DST(REG_ZERO, REG_ITMP1, 0);
2159                                 break;
2160                         }
2161 #endif
2162                         break;
2163
2164                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
2165
2166                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2167                         emit_nullpointer_check(cd, iptr, s1);
2168
2169                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2170                                 uf        = iptr->sx.s23.s3.uf;
2171                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2172                                 disp      = 0;
2173
2174                                 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2175                         }
2176                         else {
2177                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2178                                 fieldtype = fi->type;
2179                                 disp      = fi->offset;
2180                         }
2181
2182                         switch (fieldtype) {
2183                         case TYPE_INT:
2184                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2185                                 M_ILD(d, s1, disp);
2186                                 break;
2187                         case TYPE_LNG:
2188                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2189                                 if (GET_HIGH_REG(d) == s1) {
2190                                         M_ILD(GET_LOW_REG(d), s1, disp + 4);
2191                                         M_ILD(GET_HIGH_REG(d), s1, disp);
2192                                 }
2193                                 else {
2194                                         M_ILD(GET_LOW_REG(d), s1, disp + 4);
2195                                         M_ILD(GET_HIGH_REG(d), s1, disp);
2196                                 }
2197                                 break;
2198                         case TYPE_ADR:
2199                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2200                                 M_ALD(d, s1, disp);
2201                                 break;
2202                         case TYPE_FLT:
2203                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2204                                 M_FLD(d, s1, disp);
2205                                 break;
2206                         case TYPE_DBL:                          
2207                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2208                                 M_DLD(d, s1, disp);
2209                                 break;
2210                         }
2211                         emit_store_dst(jd, iptr, d);
2212                         break;
2213
2214                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
2215
2216                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2217                         gen_nullptr_check(s1);
2218
2219                         s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2220
2221                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2222                                 uf        = iptr->sx.s23.s3.uf;
2223                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2224                                 disp      = 0;
2225                         } 
2226                         else {
2227                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2228                                 fieldtype = fi->type;
2229                                 disp      = fi->offset;
2230                         }
2231
2232                         if (IS_INT_LNG_TYPE(fieldtype)) {
2233                                 if (IS_2_WORD_TYPE(fieldtype))
2234                                         s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2235                                 else
2236                                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2237                         }
2238                         else
2239                                 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2240
2241                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
2242                                 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2243
2244                         switch (fieldtype) {
2245                         case TYPE_INT:
2246                                 M_IST(s2, s1, disp);
2247                                 break;
2248                         case TYPE_LNG:
2249                                 /* TODO really order */
2250                                 M_IST(GET_LOW_REG(s2), s1, disp + 4);      /* keep this order */
2251                                 M_IST(GET_HIGH_REG(s2), s1, disp);         /* keep this order */
2252                                 break;
2253                         case TYPE_ADR:
2254                                 M_AST(s2, s1, disp);
2255                                 break;
2256                         case TYPE_FLT:
2257                                 M_FST(s2, s1, disp);
2258                                 break;
2259                         case TYPE_DBL:
2260                                 M_DST(s2, s1, disp);
2261                                 break;
2262                         }
2263                         break;
2264
2265                 case ICMD_PUTFIELDCONST:  /* ..., objectref, value  ==> ...           */
2266                                           /* val = value (in current instruction)     */
2267                                           /* following NOP)                           */
2268                         OOPS();
2269 #if 0
2270                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2271                         gen_nullptr_check(s1);
2272
2273                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2274                                 uf        = iptr->sx.s23.s3.uf;
2275                                 fieldtype = uf->fieldref->parseddesc.fd->type;
2276                                 disp      = 0;
2277
2278 /*                              PROFILE_CYCLE_STOP; */
2279
2280                                 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2281
2282 /*                              PROFILE_CYCLE_START; */
2283                         } 
2284                         else {
2285                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
2286                                 fieldtype = fi->type;
2287                                 disp      = fi->offset;
2288                         }
2289
2290                         switch (fieldtype) {
2291                         case TYPE_INT:
2292                         case TYPE_FLT:
2293                                 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2294                                 break;
2295                         case TYPE_LNG:
2296                         case TYPE_ADR:
2297                         case TYPE_DBL:
2298                                 /* XXX why no check for IS_IMM32? */
2299                                 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2300                                 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2301                                 break;
2302                         }
2303 #endif
2304                         break;
2305
2306
2307                 /* branch operations **************************************************/
2308
2309                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
2310
2311                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2312                         M_INTMOVE(s1, REG_ITMP1_XPTR);
2313
2314                         PROFILE_CYCLE_STOP;
2315
2316 #ifdef ENABLE_VERIFIER
2317                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2318                                 uc = iptr->sx.s23.s2.uc;
2319
2320                                 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2321                         }
2322 #endif /* ENABLE_VERIFIER */
2323
2324                         disp = dseg_add_functionptr(cd, asm_handle_exception);
2325                         M_ALD(REG_ITMP2, REG_PV, disp);
2326                         M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2327                         M_NOP;
2328
2329                         break;
2330
2331                 case ICMD_GOTO:         /* ... ==> ...                                */
2332                 case ICMD_RET:          /* ... ==> ...                                */
2333
2334                         M_BR(0);
2335                         codegen_add_branch_ref(cd, iptr->dst.block);
2336
2337                         break;
2338
2339                 case ICMD_JSR:          /* ... ==> ...                                */
2340                         OOPS();
2341 #if 0
2342                         M_JMP_IMM(0);
2343                         codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2344 #endif
2345                         break;
2346                         
2347                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
2348                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
2349                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2350                         M_TEST(s1);
2351                         switch (iptr->opc) {    
2352                                 case ICMD_IFNULL:
2353                                         M_BEQ(0);
2354                                         break;
2355                                 case ICMD_IFNONNULL:
2356                                         M_BNE(0);
2357                                         break;
2358                         }
2359                         codegen_add_branch_ref(cd, iptr->dst.block);
2360                         break;
2361
2362                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
2363                 case ICMD_IFLT:         /* ..., value ==> ...                         */
2364                 case ICMD_IFLE:         /* ..., value ==> ...                         */
2365                 case ICMD_IFNE:         /* ..., value ==> ...                         */
2366                 case ICMD_IFGT:         /* ..., value ==> ...                         */
2367                 case ICMD_IFGE:         /* ..., value ==> ...                         */
2368                         
2369                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2370
2371                         if (N_VALID_IMM(iptr->sx.val.i))
2372                                 N_CHI(s1, iptr->sx.val.i);
2373                         else {
2374                                 disp = dseg_add_s4(cd, iptr->sx.val.i);
2375                                 N_LHI(REG_ITMP2, disp);
2376                                 N_C(s1, 0, REG_ITMP2, REG_PV);
2377                         }
2378
2379                         switch (iptr->opc) {
2380                         case ICMD_IFLT:
2381                                 M_BLT(0);
2382                                 break;
2383                         case ICMD_IFLE:
2384                                 M_BLE(0);
2385                                 break;
2386                         case ICMD_IFNE:
2387                                 M_BNE(0);
2388                                 break;
2389                         case ICMD_IFGT:
2390                                 M_BGT(0);
2391                                 break;
2392                         case ICMD_IFGE:
2393                                 M_BGE(0);
2394                                 break;
2395                         case ICMD_IFEQ:
2396                                 M_BEQ(0);
2397                                 break;
2398                         }
2399                         codegen_add_branch_ref(cd, iptr->dst.block);
2400
2401                         break;
2402
2403                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
2404                 case ICMD_IF_LLE:       /* op1 = target JavaVM pc, val.l = constant   */
2405                 case ICMD_IF_LGT:
2406                 case ICMD_IF_LGE:
2407                 case ICMD_IF_LEQ:
2408                 case ICMD_IF_LNE:
2409                         {
2410
2411                                 u1 *out_ref = NULL;
2412
2413                                 /* ATTENTION: compare high words signed and low words unsigned */
2414         
2415                                 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2416
2417                                 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2418                                         N_CHI(s1, iptr->sx.val.l >> 32);
2419                                 else {
2420                                         disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2421                                         N_LHI(REG_ITMP2, disp);
2422                                         N_C(s1, 0, REG_ITMP2, REG_PV);
2423                                 }
2424
2425                                 switch(iptr->opc) {
2426                                 case ICMD_IF_LLT:
2427                                 case ICMD_IF_LLE:
2428                                         M_BLT(0);
2429                                         codegen_addreference(cd, iptr->dst.block);
2430                                         /* EQ ... fall through */
2431                                         out_ref = cd->mcodeptr;
2432                                         M_BGT(0);
2433                                         break;
2434                                 case ICMD_IF_LGT:
2435                                 case ICMD_IF_LGE:
2436                                         M_BGT(0);
2437                                         codegen_addreference(cd, iptr->dst.block);
2438                                         /* EQ ... fall through */
2439                                         out_ref = cd->mcodeptr;
2440                                         M_BLT(0);
2441                                         break;
2442                                 case ICMD_IF_LEQ: 
2443                                         /* EQ ... fall through */
2444                                         out_ref = cd->mcodeptr;
2445                                         M_BNE(0);
2446                                         break;
2447                                 case ICMD_IF_LNE:
2448                                         /* EQ ... fall through */
2449                                         M_BNE(0);
2450                                         codegen_addreference(cd, iptr->dst.block);
2451                                         break;
2452                                 default:
2453                                         assert(0);
2454                                 }
2455
2456                                 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2457
2458                                 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2459                                 N_LHI(REG_ITMP2, disp);
2460                                 N_CL(s1, 0, REG_ITMP2, REG_PV);
2461
2462                                 switch(iptr->opc) {
2463                                 case ICMD_IF_LLT:
2464                                         M_BLT(0);
2465                                         break;
2466                                 case ICMD_IF_LLE:
2467                                         M_BLE(0);
2468                                         break;
2469                                 case ICMD_IF_LGT:
2470                                         M_BGT(0);
2471                                         break;
2472                                 case ICMD_IF_LGE:
2473                                         M_BGE(0);
2474                                         break;
2475                                 case ICMD_IF_LEQ:
2476                                         M_BEQ(0);
2477                                         break;
2478                                 case ICMD_IF_LNE:
2479                                         M_BNE(0);
2480                                         break;
2481                                 default:
2482                                         assert(0);
2483                                 }
2484                                 codegen_addreference(cd, iptr->dst.block);
2485
2486                                 if (out_ref != NULL) {
2487                                         *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2488                                 }
2489
2490                         }
2491                         break;
2492
2493                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
2494                 case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
2495
2496                         /* Compare addresses as 31 bit unsigned integers */
2497
2498                         s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2499                         N_LA(REG_ITMP1, 0, RN, s1);
2500
2501                         s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2502                         N_LA(REG_ITMP2, 0, RN, s2);
2503
2504                         M_CMP(REG_ITMP1, REG_ITMP2);
2505
2506                         switch (iptr->opc) {
2507                                 case ICMD_IF_ACMPEQ:
2508                                         M_BEQ(0);
2509                                         break;
2510                                 case ICMD_IF_ACMPNE:
2511                                         M_BNE(0);
2512                                         break;
2513                         }
2514
2515                         codegen_add_branch_ref(cd, iptr->dst.block);
2516                         break;
2517
2518
2519                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
2520                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
2521                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
2522                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
2523                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
2524                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
2525
2526                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2527                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2528                         M_CMP(s1, s2);
2529                         switch (iptr->opc) {
2530                                 case ICMD_IF_ICMPEQ:
2531                                         M_BEQ(0);
2532                                         break;
2533                                 case ICMD_IF_ICMPNE:
2534                                         M_BNE(0);
2535                                         break;
2536                                 case ICMD_IF_ICMPLT:
2537                                         M_BLT(0);
2538                                         break;
2539                                 case ICMD_IF_ICMPGT:
2540                                         M_BGT(0);
2541                                         break;
2542                                 case ICMD_IF_ICMPLE:
2543                                         M_BLE(0);
2544                                         break;
2545                                 case ICMD_IF_ICMPGE:
2546                                         M_BGE(0);
2547                                         break;
2548                         }
2549                         codegen_add_branch_ref(cd, iptr->dst.block);
2550
2551                         break;
2552
2553                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
2554                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
2555                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
2556                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
2557                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
2558                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
2559                         {
2560
2561                                 u1 *out_ref = NULL;
2562
2563                                 /* ATTENTION: compare high words signed and low words unsigned */
2564         
2565                                 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2566                                 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2567
2568                                 N_CR(s1, s2);
2569
2570                                 switch(iptr->opc) {
2571                                 case ICMD_IF_LCMPLT:
2572                                 case ICMD_IF_LCMPLE:
2573                                         M_BLT(0);
2574                                         codegen_addreference(cd, iptr->dst.block);
2575                                         /* EQ ... fall through */
2576                                         out_ref = cd->mcodeptr;
2577                                         M_BGT(0);
2578                                         break;
2579                                 case ICMD_IF_LCMPGT:
2580                                 case ICMD_IF_LCMPGE:
2581                                         M_BGT(0);
2582                                         codegen_addreference(cd, iptr->dst.block);
2583                                         /* EQ ... fall through */
2584                                         out_ref = cd->mcodeptr;
2585                                         M_BLT(0);
2586                                         break;
2587                                 case ICMD_IF_LCMPEQ: 
2588                                         /* EQ ... fall through */
2589                                         out_ref = cd->mcodeptr;
2590                                         M_BNE(0);
2591                                         break;
2592                                 case ICMD_IF_LCMPNE:
2593                                         /* EQ ... fall through */
2594                                         M_BNE(0);
2595                                         codegen_addreference(cd, iptr->dst.block);
2596                                         break;
2597                                 default:
2598                                         assert(0);
2599                                 }
2600
2601                                 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2602                                 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2603         
2604                                 N_CLR(s1, s2);
2605
2606                                 switch(iptr->opc) {
2607                                 case ICMD_IF_LCMPLT:
2608                                         M_BLT(0);
2609                                         break;
2610                                 case ICMD_IF_LCMPLE:
2611                                         M_BLE(0);
2612                                         break;
2613                                 case ICMD_IF_LCMPGT:
2614                                         M_BGT(0);
2615                                         break;
2616                                 case ICMD_IF_LCMPGE:
2617                                         M_BGE(0);
2618                                         break;
2619                                 case ICMD_IF_LCMPEQ:
2620                                         M_BEQ(0);
2621                                         break;
2622                                 case ICMD_IF_LCMPNE:
2623                                         M_BNE(0);
2624                                         break;
2625                                 default:
2626                                         assert(0);
2627                                 }
2628
2629                                 codegen_addreference(cd, iptr->dst.block);
2630
2631                                 if (out_ref != NULL) {
2632                                         *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2633                                 }
2634
2635                         }
2636                         break;
2637
2638                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2639
2640                         REPLACEMENT_POINT_RETURN(cd, iptr);
2641                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
2642                         M_INTMOVE(s1, REG_RESULT);
2643                         goto nowperformreturn;
2644
2645                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
2646
2647                         REPLACEMENT_POINT_RETURN(cd, iptr);
2648                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
2649                         M_INTMOVE(s1, REG_RESULT);
2650
2651 #ifdef ENABLE_VERIFIER
2652                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2653                                 unresolved_class *uc = iptr->sx.s23.s2.uc;
2654
2655                                 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2656                         }
2657 #endif /* ENABLE_VERIFIER */
2658                         goto nowperformreturn;
2659
2660                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
2661
2662                         REPLACEMENT_POINT_RETURN(cd, iptr);
2663                         s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2664                         M_LNGMOVE(s1, REG_RESULT_PACKED);
2665                         goto nowperformreturn;
2666
2667                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2668                 case ICMD_DRETURN:
2669
2670                         REPLACEMENT_POINT_RETURN(cd, iptr);
2671                         s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2672                         M_FLTMOVE(s1, REG_FRESULT);
2673                         goto nowperformreturn;
2674
2675                 case ICMD_RETURN:      /* ...  ==> ...                                */
2676
2677                         REPLACEMENT_POINT_RETURN(cd, iptr);
2678
2679 nowperformreturn:
2680                         {
2681                         s4 i, p;
2682                         
2683                         p = cd->stackframesize;
2684
2685                         /* call trace function */
2686
2687 #if !defined(NDEBUG)
2688                         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2689                                 emit_verbosecall_exit(jd);
2690 #endif /* !defined(NDEBUG) */
2691
2692 #if defined(ENABLE_THREADS)
2693                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2694                                 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2695                                 M_ALD(REG_ITMP3, REG_PV, disp);
2696                                 M_CALL(REG_ITMP3);
2697
2698                                 /* we need to save the proper return value */
2699
2700                                 switch (iptr->opc) {
2701                                 case ICMD_LRETURN:
2702                                         M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2703                                         /* fall through */
2704                                 case ICMD_IRETURN:
2705                                 case ICMD_ARETURN:
2706                                         M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2707                                         break;
2708                                 case ICMD_FRETURN:
2709                                         M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2710                                         break;
2711                                 case ICMD_DRETURN:
2712                                         M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2713                                         break;
2714                                 }
2715
2716                                 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2717                                 M_JSR;
2718
2719                                 /* and now restore the proper return value */
2720
2721                                 switch (iptr->opc) {
2722                                 case ICMD_LRETURN:
2723                                         M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2724                                         /* fall through */
2725                                 case ICMD_IRETURN:
2726                                 case ICMD_ARETURN:
2727                                         M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2728                                         break;
2729                                 case ICMD_FRETURN:
2730                                         M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2731                                         break;
2732                                 case ICMD_DRETURN:
2733                                         M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2734                                         break;
2735                                 }
2736                         }
2737 #endif
2738
2739                         /* restore return address                                         */
2740
2741                         p--; M_ALD(REG_RA, REG_SP, p * 4);
2742
2743                         /* restore saved registers                                        */
2744
2745                         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2746                                 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2747                         }
2748                         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2749                                 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2750                         }
2751
2752                         /* deallocate stack                                               */
2753
2754                         if (cd->stackframesize)
2755                                 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2756
2757                         M_RET;
2758                         ALIGNCODENOP;
2759                         }
2760                         break;
2761
2762                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2763                         OOPS();
2764 #if 0
2765                         {
2766                                 s4 i, l;
2767                                 branch_target_t *table;
2768
2769                                 table = iptr->dst.table;
2770
2771                                 l = iptr->sx.s23.s2.tablelow;
2772                                 i = iptr->sx.s23.s3.tablehigh;
2773
2774                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2775                                 M_INTMOVE(s1, REG_ITMP1);
2776
2777                                 if (l != 0)
2778                                         M_ISUB_IMM(l, REG_ITMP1);
2779
2780                                 /* number of targets */
2781                                 i = i - l + 1;
2782
2783                 /* range check */
2784                                 M_ICMP_IMM(i - 1, REG_ITMP1);
2785                                 M_BA(0);
2786
2787                                 codegen_add_branch_ref(cd, table[0].block); /* default target */
2788
2789                                 /* build jump table top down and use address of lowest entry */
2790
2791                                 table += i;
2792
2793                                 while (--i >= 0) {
2794                                         dseg_add_target(cd, table->block);
2795                                         --table;
2796                                 }
2797
2798                                 /* length of dataseg after last dseg_add_target is used
2799                                    by load */
2800
2801                                 M_MOV_IMM(0, REG_ITMP2);
2802                                 dseg_adddata(cd);
2803                                 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2804                                 M_JMP(REG_ITMP1);
2805                         }
2806 #endif
2807                         break;
2808
2809
2810                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2811                         OOPS();
2812 #if 0
2813                         {
2814                                 s4 i;
2815                                 lookup_target_t *lookup;
2816
2817                                 lookup = iptr->dst.lookup;
2818
2819                                 i = iptr->sx.s23.s2.lookupcount;
2820                         
2821                                 MCODECHECK(8 + ((7 + 6) * i) + 5);
2822                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2823
2824                                 while (--i >= 0) {
2825                                         M_ICMP_IMM(lookup->value, s1);
2826                                         M_BEQ(0);
2827                                         codegen_add_branch_ref(cd, lookup->target.block);
2828                                         lookup++;
2829                                 }
2830
2831                                 M_JMP_IMM(0);
2832                         
2833                                 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2834                         }
2835 #endif
2836                         break;
2837
2838
2839                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
2840
2841                         bte = iptr->sx.s23.s3.bte;
2842                         md  = bte->md;
2843                         goto gen_method;
2844
2845                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2846                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2847                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2848                 case ICMD_INVOKEINTERFACE:
2849
2850                         REPLACEMENT_POINT_INVOKE(cd, iptr);
2851
2852                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2853                                 lm = NULL;
2854                                 um = iptr->sx.s23.s3.um;
2855                                 md = um->methodref->parseddesc.md;
2856                         }
2857                         else {
2858                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2859                                 um = NULL;
2860                                 md = lm->parseddesc;
2861                         }
2862
2863 gen_method:
2864                         s3 = md->paramcount;
2865
2866                         MCODECHECK((s3 << 1) + 64);
2867
2868                         /* copy arguments to registers or stack location */
2869
2870                         for (s3 = s3 - 1; s3 >= 0; s3--) {
2871                                 var = VAR(iptr->sx.s23.s2.args[s3]);
2872
2873                                 /* Already Preallocated? */
2874                                 if (var->flags & PREALLOC)
2875                                         continue;
2876
2877                                 if (IS_INT_LNG_TYPE(var->type)) {
2878                                         if (!md->params[s3].inmemory) {
2879                                                 if (IS_2_WORD_TYPE(var->type)) {
2880                                                         s1 = PACK_REGS(
2881                                                                 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2882                                                                 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2883                                                         );
2884                                                         d = emit_load(jd, iptr, var, s1);
2885                                                         M_LNGMOVE(d, s1);
2886                                                 }
2887                                                 else {
2888                                                         s1 = rd->argintregs[md->params[s3].regoff];
2889                                                         d = emit_load(jd, iptr, var, s1);
2890                                                         M_INTMOVE(d, s1);
2891                                                 }
2892                                         }
2893                                         else {
2894                                                 if (IS_2_WORD_TYPE(var->type)) {
2895                                                         d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2896                                                         M_LST(d, REG_SP, md->params[s3].regoff * 4);
2897                                                 }
2898                                                 else {
2899                                                         d = emit_load(jd, iptr, var, REG_ITMP1);
2900                                                         M_IST(d, REG_SP, md->params[s3].regoff * 4);
2901                                                 }
2902                                         }
2903                                 }
2904                                 else {
2905                                         if (!md->params[s3].inmemory) {
2906                                                 s1 = rd->argfltregs[md->params[s3].regoff];
2907                                                 d = emit_load(jd, iptr, var, s1);
2908                                                 M_FLTMOVE(d, s1);
2909                                         }
2910                                         else {
2911                                                 d = emit_load(jd, iptr, var, REG_FTMP1);
2912                                                 if (IS_2_WORD_TYPE(var->type))
2913                                                         M_DST(d, REG_SP, md->params[s3].regoff * 4);
2914                                                 else
2915                                                         M_FST(d, REG_SP, md->params[s3].regoff * 4);
2916                                         }
2917                                 }
2918                         }
2919
2920                         switch (iptr->opc) {
2921                         case ICMD_BUILTIN:
2922                                 disp = dseg_add_functionptr(cd, bte->fp);
2923
2924                                 N_AHI(REG_SP, -96); /* register save area as required by C abi */       
2925                                 N_LHI(REG_ITMP1, disp);
2926                                 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2927                                 break;
2928
2929                         case ICMD_INVOKESPECIAL:
2930                                 emit_nullpointer_check(cd, iptr, REG_A0);
2931                                 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr   */
2932                                 /* fall through */
2933
2934                         case ICMD_INVOKESTATIC:
2935                                 if (lm == NULL) {
2936                                         disp = dseg_add_unique_address(cd, um);
2937
2938                                         codegen_addpatchref(cd, PATCHER_invokestatic_special,
2939                                                                                 um, disp);
2940                                 }
2941                                 else
2942                                         disp = dseg_add_address(cd, lm->stubroutine);
2943
2944                                 N_LHI(REG_ITMP1, disp);
2945                                 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2946                                 break;
2947
2948                         case ICMD_INVOKEVIRTUAL:
2949                                 emit_nullpointer_check(cd, iptr, REG_A0);
2950
2951                                 if (lm == NULL) {
2952                                         codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2953
2954                                         s1 = 0;
2955                                 }
2956                                 else {
2957                                         s1 = OFFSET(vftbl_t, table[0]) +
2958                                                 sizeof(methodptr) * lm->vftblindex;
2959                                 }
2960
2961                                 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2962                                 M_ALD(REG_PV, REG_METHODPTR, s1);
2963                                 break;
2964
2965                         case ICMD_INVOKEINTERFACE:
2966                                 emit_nullpointer_check(cd, iptr, REG_A0);
2967
2968                                 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2969                                  * and -0xFFF in index register (itmp1)
2970                                  */
2971
2972                                 N_LHI(REG_ITMP1, -N_DISP_MAX);
2973
2974                                 if (lm == NULL) {
2975                                         codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2976
2977                                         s1 = 0;
2978                                         s2 = 0;
2979                                 }
2980                                 else {
2981                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
2982                                                 sizeof(methodptr*) * lm->class->index +
2983                                                 N_DISP_MAX;
2984
2985                                         s2 = sizeof(methodptr) * (lm - lm->class->methods);
2986                                 }
2987
2988                                 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2989                                 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2990                                 M_ALD(REG_PV, REG_METHODPTR, s2);
2991                                 break;
2992                         }
2993
2994                         /* generate the actual call */
2995
2996                         M_CALL(REG_PV);
2997                         REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2998                         N_BASR(REG_ITMP1, RN);
2999                         disp = (s4) (cd->mcodeptr - cd->mcodebase);
3000                         M_LDA(REG_PV, REG_ITMP1, -disp);
3001         
3002                         /* post call finalization */
3003
3004                         if (iptr->opc == ICMD_BUILTIN) {
3005                                 N_AHI(REG_SP, 96); /* remove C abi register save area */
3006                         }
3007
3008                         /* actually only used for ICMD_BUILTIN */
3009
3010                         if (INSTRUCTION_MUST_CHECK(iptr)) {
3011                                 M_TEST(REG_RESULT);
3012                                 M_BEQ(0);
3013                                 codegen_add_fillinstacktrace_ref(cd);
3014                         }
3015
3016                         /* store return value */
3017
3018                         d = md->returntype.type;
3019
3020                         if (d != TYPE_VOID) {
3021                                 if (IS_INT_LNG_TYPE(d)) {
3022                                         if (IS_2_WORD_TYPE(d)) {
3023                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
3024                                                 M_LNGMOVE(REG_RESULT_PACKED, s1);
3025                                         }
3026                                         else {
3027                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3028                                                 M_INTMOVE(REG_RESULT, s1);
3029                                         }
3030                                 }
3031                                 else {
3032                                         s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
3033                                         M_FLTMOVE(REG_FRESULT, s1);
3034                                 }
3035                                 emit_store_dst(jd, iptr, s1);
3036                         }
3037
3038                         break;
3039
3040
3041                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
3042
3043                                       /* val.a: (classinfo*) superclass               */
3044
3045                         /*  superclass is an interface:
3046                          *      
3047                          *  OK if ((sub == NULL) ||
3048                          *         (sub->vftbl->interfacetablelength > super->index) &&
3049                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
3050                          *      
3051                          *  superclass is a class:
3052                          *      
3053                          *  OK if ((sub == NULL) || (0
3054                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3055                          *         super->vftbl->diffval));
3056                          */
3057
3058                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3059                                 /* object type cast-check */
3060
3061                                 classinfo *super;
3062                                 vftbl_t   *supervftbl;
3063                                 s4         superindex;
3064
3065                                 u1        *class_label_refs[] = { 0 }, *class_label;
3066                                 u1        *exit_label_refs[] = { 0, 0, 0, 0 };
3067
3068                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3069                                         super = NULL;
3070                                         superindex = 0;
3071                                         supervftbl = NULL;
3072                                 }
3073                                 else {
3074                                         super = iptr->sx.s23.s3.c.cls;
3075                                         superindex = super->index;
3076                                         supervftbl = super->vftbl;
3077                                 }
3078
3079 #if defined(ENABLE_THREADS)
3080                                 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3081 #endif
3082                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3083
3084                                 /* if class is not resolved, check which code to call */
3085
3086                                 if (super == NULL) {
3087                                         M_TEST(s1);
3088                                         exit_label_refs[0] = cd->mcodeptr;
3089                                         M_BEQ(0);
3090
3091                                         disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
3092
3093                                         codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3094                                                                                   iptr->sx.s23.s3.c.ref,
3095                                                                                   disp);
3096
3097                                         ICONST(REG_ITMP2, ACC_INTERFACE);
3098                                         ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3099                                         N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3100                                         class_label_refs[0] = cd->mcodeptr;
3101                                         M_BEQ(0);
3102                                 }
3103
3104                                 /* interface checkcast code */
3105
3106                                 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3107                                         if (super == NULL) {
3108                                                 codegen_add_patch_ref(cd,
3109                                                                                           PATCHER_checkcast_instanceof_interface,
3110                                                                                           iptr->sx.s23.s3.c.ref,
3111                                                                                           0);
3112                                         } else {
3113                                                 M_TEST(s1);
3114                                                 exit_label_refs[1] = cd->mcodeptr;
3115                                                 M_BEQ(0);
3116                                         }
3117
3118                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3119                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3120                                         M_ISUB_IMM(superindex, REG_ITMP3);
3121                                         M_BLE(0);
3122                                         codegen_add_classcastexception_ref(cd, s1);
3123                                         N_AHI(
3124                                                 REG_ITMP2,
3125                                                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3126                                                         superindex * sizeof(methodptr*))
3127                                         );
3128                                         M_ALD(REG_ITMP2, REG_ITMP2, 0);
3129                                         M_TEST(REG_ITMP2);
3130                                         M_BEQ(0);
3131                                         codegen_add_classcastexception_ref(cd, s1);
3132
3133                                         if (super == NULL) {
3134                                                 exit_label_refs[2] = cd->mcodeptr;
3135                                                 M_BR(0);
3136                                         }
3137                                 }
3138
3139                                 /* class checkcast code */
3140
3141                                 class_label = cd->mcodeptr;
3142
3143                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3144                                         if (super == NULL) {
3145                                                 disp = dseg_add_unique_address(cd, NULL);
3146
3147                                                 codegen_add_patch_ref(cd,
3148                                                                                           PATCHER_resolve_classref_to_vftbl,
3149                                                                                           iptr->sx.s23.s3.c.ref,
3150                                                                                           disp);
3151                                         }
3152                                         else {
3153                                                 disp = dseg_add_address(cd, supervftbl);
3154                                                 M_TEST(s1);
3155                                                 exit_label_refs[3] = cd->mcodeptr;
3156                                                 M_BEQ(0);
3157                                         }
3158
3159                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3160                                         M_ALD(REG_ITMP3, REG_PV, disp);
3161 #if defined(ENABLE_THREADS)
3162                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3163 #endif
3164                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3165                                         /*                              if (s1 != REG_ITMP1) { */
3166                                         /*                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3167                                         /*                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3168                                         /*  #if defined(ENABLE_THREADS) */
3169                                         /*                                      codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3170                                         /*  #endif */
3171                                         /*                                      M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3172
3173                                         /*                              } else { */
3174                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3175                                         M_ISUB(REG_ITMP3, REG_ITMP2);
3176                                         M_ALD(REG_ITMP3, REG_PV, disp);
3177                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3178 #if defined(ENABLE_THREADS)
3179                                         codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3180 #endif
3181                                         /*                              } */
3182                                         N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3183                                         /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3184                                         M_BGT(0); /* Branch if greater then */
3185                                         /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3186                                         codegen_add_classcastexception_ref(cd, s1);
3187                                 }
3188
3189                                 /* resolve labels by adding the correct displacement */
3190
3191                                 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3192                                         if (exit_label_refs[s2])
3193                                                 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3194                                 }
3195
3196                                 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3197                                         if (class_label_refs[s2])
3198                                                 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3199                                 }
3200
3201                                 d = codegen_reg_of_dst(jd, iptr, s1);
3202                         }
3203                         else {
3204                                 /* array type cast-check */
3205
3206                                 s1 = emit_load_s1(jd, iptr, REG_A0);
3207                                 M_INTMOVE(s1, REG_A0);
3208
3209                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3210                                         disp = dseg_add_unique_address(cd, NULL);
3211
3212                                         codegen_add_patch_ref(cd,
3213                                                                                   PATCHER_resolve_classref_to_classinfo,
3214                                                                                   iptr->sx.s23.s3.c.ref,
3215                                                                                   disp);
3216                                 }
3217                                 else
3218                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3219
3220                                 M_ALD(REG_A1, REG_PV, disp);
3221                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3222                                 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3223                                 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3224                                 M_JSR(REG_RA, REG_PV);
3225                                 N_BASR(REG_ITMP1, RN);
3226                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3227                                 M_LDA(REG_PV, REG_ITMP1, -disp);
3228
3229                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3230                                 M_TEST(REG_RESULT);
3231                                 M_BEQ(0);
3232                                 codegen_add_classcastexception_ref(cd, s1);
3233
3234                                 d = codegen_reg_of_dst(jd, iptr, s1);
3235                         }
3236
3237                         M_INTMOVE(s1, d);
3238                         emit_store_dst(jd, iptr, d);
3239                         break;
3240
3241                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
3242                                       /* val.a: (classinfo*) superclass               */
3243
3244                         /*  superclass is an interface:
3245                          *      
3246                          *  return (sub != NULL) &&
3247                          *         (sub->vftbl->interfacetablelength > super->index) &&
3248                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
3249                          *      
3250                          *  superclass is a class:
3251                          *      
3252                          *  return ((sub != NULL) && (0
3253                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3254                          *          super->vftbl->diffvall));
3255                          */
3256
3257                         {
3258                         classinfo *super;
3259                         vftbl_t   *supervftbl;
3260                         s4         superindex;
3261
3262                         u1        *class_label, *class_label_refs[1] = { 0 };
3263                         u1        *exit_label_refs[4] = { 0, 0, 0, 0 };
3264                         u1        *label1, *label1_refs[1] = { 0 };
3265
3266                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3267                                 super = NULL;
3268                                 superindex = 0;
3269                                 supervftbl = NULL;
3270
3271                         } else {
3272                                 super = iptr->sx.s23.s3.c.cls;
3273                                 superindex = super->index;
3274                                 supervftbl = super->vftbl;
3275                         }
3276
3277 #if defined(ENABLE_THREADS)
3278                         codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3279 #endif
3280                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3281                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3282                         if (s1 == d) {
3283                                 M_MOV(s1, REG_ITMP1);
3284                                 s1 = REG_ITMP1;
3285                         }
3286
3287                         /* if class is not resolved, check which code to call */
3288
3289                         if (super == NULL) {
3290                                 M_CLR(d);
3291                                 
3292                                 M_TEST(s1);
3293                                 exit_label_refs[0] = cd->mcodeptr;
3294                                 M_BEQ(0);
3295
3296                                 disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
3297
3298                                 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3299                                                                           iptr->sx.s23.s3.c.ref, disp);
3300
3301                                 ICONST(REG_ITMP2, ACC_INTERFACE);
3302                                 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3303                                 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3304                                 class_label_refs[0] = cd->mcodeptr;
3305                                 M_BEQ(0);
3306                         }
3307
3308                         /* interface instanceof code */
3309
3310                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3311                                 if (super == NULL) {
3312                                         /* If d == REG_ITMP2, then it's destroyed in check
3313                                            code above. */
3314                                         if (d == REG_ITMP2)
3315                                                 M_CLR(d);
3316
3317                                         codegen_add_patch_ref(cd,
3318                                                                                   PATCHER_checkcast_instanceof_interface,
3319                                                                                   iptr->sx.s23.s3.c.ref, 0);
3320                                 }
3321                                 else {
3322                                         M_CLR(d);
3323                                         M_TEST(s1);
3324                                         exit_label_refs[1] = cd->mcodeptr;
3325                                         M_BEQ(0);
3326                                 }
3327
3328                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3329                                 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3330                                 M_ISUB_IMM(superindex, REG_ITMP3);
3331                                 label1_refs[0] = cd->mcodeptr;
3332                                 M_BLE(0); 
3333                                 N_AHI(
3334                                         REG_ITMP1,
3335                                         (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3336                                                 superindex * sizeof(methodptr*))
3337                                 );
3338                                 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3339                                 
3340                                 /* d := (REG_ITMP1 != 0)  */
3341
3342                                 N_LTR(d, REG_ITMP1);
3343                                 M_BEQ(SZ_BRC + SZ_LHI);
3344                                 N_LHI(d, 1);
3345
3346                                 label1 = cd->mcodeptr;
3347
3348                                 if (super == NULL) {
3349                                         exit_label_refs[2] = cd->mcodeptr;
3350                                         M_BR(0);
3351                                 }
3352                         }
3353
3354                         /* class instanceof code */
3355
3356                         class_label = cd->mcodeptr;
3357
3358                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3359                                 if (super == NULL) {
3360                                         disp = dseg_add_unique_address(cd, NULL);
3361
3362                                         codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3363                                                                                   iptr->sx.s23.s3.c.ref,
3364                                                                                   disp);
3365                                 }
3366                                 else {
3367                                         disp = dseg_add_address(cd, supervftbl);
3368
3369                                         M_CLR(d);
3370
3371                                         M_TEST(s1);
3372                                         exit_label_refs[3] = cd->mcodeptr;
3373                                         M_BEQ(0);
3374                                 }
3375
3376                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3377                                 M_ALD(REG_ITMP2, REG_PV, disp);
3378 #if defined(ENABLE_THREADS)
3379                                 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3380 #endif
3381                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3382                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3383                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3384 #if defined(ENABLE_THREADS)
3385                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3386 #endif
3387                                 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 :=  itmp1 (sub.baseval) - itmp3 (super.baseval) */
3388
3389                                 N_CLR(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3390                                 N_LHI(d, 0);
3391                                 M_BGT(SZ_BRC + SZ_LHI);
3392                                 N_LHI(d, 1);
3393                         }
3394
3395                         /* resolve labels by adding the correct displacement */
3396
3397                         for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3398                                 if (exit_label_refs[s2])
3399                                         *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3400                         }
3401
3402                         for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3403                                 if (class_label_refs[s2])
3404                                         *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3405                         }
3406
3407                         for (s2 = 0; s2 < sizeof(label1_refs) / sizeof(label1_refs[0]); ++s2) {
3408                                 if (label1_refs[s2])
3409                                         *(u4 *)label1_refs[s2] |= (u4)(label1 - label1_refs[s2]) / 2;
3410                         }
3411
3412                         emit_store_dst(jd, iptr, d);
3413
3414                         }
3415
3416                         break;
3417
3418                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
3419                         OOPS();
3420 #if 0
3421
3422                         /* check for negative sizes and copy sizes to stack if necessary  */
3423
3424                         MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3425
3426                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3427
3428                                 /* copy SAVEDVAR sizes to stack */
3429                                 var = VAR(iptr->sx.s23.s2.args[s1]);
3430
3431                                 /* Already Preallocated? */
3432                                 if (!(var->flags & PREALLOC)) {
3433                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
3434                                         M_LST(s2, REG_SP, s1 * 8);
3435                                 }
3436                         }
3437
3438                         /* is a patcher function set? */
3439
3440                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3441                                 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3442                                                                           iptr->sx.s23.s3.c.ref, 0);
3443                         }
3444
3445                         /* a0 = dimension count */
3446
3447                         M_MOV_IMM(iptr->s1.argcount, REG_A0);
3448
3449                         /* a1 = classinfo */
3450
3451                         M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3452
3453                         /* a2 = pointer to dimensions = stack pointer */
3454
3455                         M_MOV(REG_SP, REG_A2);
3456
3457                         M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3458                         M_CALL(REG_ITMP1);
3459
3460                         /* check for exception before result assignment */
3461
3462                         M_TEST(REG_RESULT);
3463                         M_BEQ(0);
3464                         codegen_add_fillinstacktrace_ref(cd);
3465
3466                         s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3467                         M_INTMOVE(REG_RESULT, s1);
3468                         emit_store_dst(jd, iptr, s1);
3469 #endif
3470                         break;
3471
3472                 default:
3473                         exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3474                         return false;
3475         } /* switch */
3476
3477         } /* for instruction */
3478                 
3479         MCODECHECK(512); /* XXX require a lower number? */
3480
3481         /* At the end of a basic block we may have to append some nops,
3482            because the patcher stub calling code might be longer than the
3483            actual instruction. So codepatching does not change the
3484            following block unintentionally. */
3485
3486         if (cd->mcodeptr < cd->lastmcodeptr) {
3487                 while (cd->mcodeptr < cd->lastmcodeptr) {
3488                         M_NOP;
3489                 }
3490         }
3491
3492         } /* if (bptr -> flags >= BBREACHED) */
3493         } /* for basic block */
3494
3495         dseg_createlinenumbertable(cd);
3496
3497         /* generate stubs */
3498
3499         emit_exception_stubs(jd);
3500         emit_patcher_stubs(jd);
3501 #if 0
3502         emit_replacement_stubs(jd);
3503 #endif
3504
3505         codegen_finish(jd);
3506
3507         /* everything's ok */
3508
3509         return true;
3510 }
3511
3512
3513 /* createcompilerstub **********************************************************
3514
3515    Creates a stub routine which calls the compiler.
3516         
3517 *******************************************************************************/
3518
3519 #define COMPILERSTUB_DATASIZE    (3 * SIZEOF_VOID_P)
3520 #define COMPILERSTUB_CODESIZE    (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3521
3522 #define COMPILERSTUB_SIZE        (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3523
3524
3525 u1 *createcompilerstub(methodinfo *m)
3526 {
3527         u1          *s;                     /* memory to hold the stub            */
3528         ptrint      *d;
3529         codeinfo    *code;
3530         codegendata *cd;
3531         s4           dumpsize;
3532
3533         s = CNEW(u1, COMPILERSTUB_SIZE);
3534
3535         /* set data pointer and code pointer */
3536
3537         d = (ptrint *) s;
3538         s = s + COMPILERSTUB_DATASIZE;
3539
3540         /* mark start of dump memory area */
3541
3542         dumpsize = dump_size();
3543
3544         cd = DNEW(codegendata);
3545         cd->mcodeptr = s;
3546
3547         /* Store the codeinfo pointer in the same place as in the
3548            methodheader for compiled methods. */
3549
3550         code = code_codeinfo_new(m);
3551
3552         d[0] = (ptrint) asm_call_jit_compiler;
3553         d[1] = (ptrint) m;
3554         d[2] = (ptrint) code;
3555
3556         /* code for the stub */
3557
3558         /* don't touch ITMP3 as it cointains the return address */
3559
3560         M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3561
3562         M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo  */
3563         /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3564         M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3565         N_BR(REG_PV);
3566
3567 #if defined(ENABLE_STATISTICS)
3568         if (opt_stat)
3569                 count_cstub_len += COMPILERSTUB_SIZE;
3570 #endif
3571
3572         /* release dump area */
3573
3574         dump_release(dumpsize);
3575
3576         return s;
3577 }
3578
3579
3580 /* createnativestub ************************************************************
3581
3582    Creates a stub routine which calls a native method.
3583
3584 *******************************************************************************/
3585
3586 /*
3587            arguments on stack                   \
3588 -------------------------------------------------| <- SP on nativestub entry
3589            return address                        |
3590            callee saved int regs (none)          |
3591            callee saved float regs (none)        | stack frame like in cacao
3592            local variable slots (none)           |
3593            arguments for calling methods (none) /
3594 ------------------------------------------------------------------ <- datasp 
3595            stackframe info
3596            locaref table
3597            integer arguments
3598            float arguments
3599 96 - ...   on stack parameters (nmd->memuse slots) \ stack frame like in ABI         
3600 0 - 96     register save area for callee           /
3601 -------------------------------------------------------- <- SP native method
3602                                                             ==
3603                                                             SP after method entry
3604 */
3605
3606 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3607 {
3608         methodinfo   *m;
3609         codeinfo     *code;
3610         codegendata  *cd;
3611         registerdata *rd;
3612         methoddesc   *md;
3613         s4            nativeparams;
3614         s4            i, j;                 /* count variables                    */
3615         s4            t;
3616         s4            s1, s2;
3617         s4            disp;
3618
3619         /* get required compiler data */
3620
3621         m    = jd->m;
3622         code = jd->code;
3623         cd   = jd->cd;
3624         rd   = jd->rd;
3625
3626         /* initialize variables */
3627
3628         md = m->parseddesc;
3629         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3630
3631         /* calculate stack frame size */
3632 #if 0
3633         cd->stackframesize =
3634                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3635                 sizeof(localref_table) / SIZEOF_VOID_P +
3636                 INT_ARG_CNT + FLT_ARG_CNT +
3637                 1 +                       /* functionptr, TODO: store in data segment */
3638                 nmd->memuse;
3639
3640         cd->stackframesize |= 0x1;                  /* keep stack 16-byte aligned */
3641 #endif
3642
3643         cd->stackframesize = 
3644                 1 + /* r14 - return address */ +
3645                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3646                 sizeof(localref_table) / SIZEOF_VOID_P +
3647                 1 + /* itmp3 */
3648                 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3649                 nmd->memuse + /* parameter passing */
3650                 96 / SIZEOF_VOID_P /* required by ABI */;
3651
3652         cd->stackframesize |= 0x1;                  /* keep stack 8-byte aligned */
3653
3654
3655         /* create method header */
3656
3657         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
3658         (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
3659         (void) dseg_add_unique_s4(cd, 0);                      /* IsSync          */
3660         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
3661         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
3662         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
3663         (void) dseg_addlinenumbertablesize(cd);
3664         (void) dseg_add_unique_s4(cd, 0);                      /* ExTableSize     */
3665
3666         /* generate native method profiling code */
3667 #if 0
3668         if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3669                 /* count frequency */
3670
3671                 M_MOV_IMM(code, REG_ITMP3);
3672                 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3673         }
3674 #endif
3675
3676         /* generate stub code */
3677
3678         N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3679
3680         /* save return address */
3681
3682         N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3683
3684 #if 0
3685 #if !defined(NDEBUG)
3686         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3687                 emit_verbosecall_enter(jd);
3688 #endif
3689 #endif
3690
3691         /* get function address (this must happen before the stackframeinfo) */
3692
3693         disp = dseg_add_functionptr(cd, f);
3694
3695 #if !defined(WITH_STATIC_CLASSPATH)
3696         if (f == NULL)
3697                 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3698 #endif
3699
3700         M_ILD(REG_ITMP1, REG_PV, disp);
3701
3702         j = 96 + (nmd->memuse * 4);
3703
3704         /* todo some arg registers are not volatile in C-abi terms */
3705
3706         /* save integer and float argument registers */
3707
3708         for (i = 0; i < md->paramcount; i++) {
3709                 if (! md->params[i].inmemory) {
3710                         s1 = md->params[i].regoff;
3711
3712                         if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3713                                 if (IS_2_WORD_TYPE(t)) {
3714                                         /* todo store multiple */
3715                                         N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3716                                         N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3717                                 } else {
3718                                         N_ST(rd->argintregs[s1], j, RN, REG_SP);
3719                                 }
3720                         } else {
3721                                 if (IS_2_WORD_TYPE(t)) {
3722                                         N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3723                                 } else {
3724                                         N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3725                                 }
3726                         }
3727
3728                         j += 8;
3729                 }
3730         }
3731
3732         N_ST(REG_ITMP1, j, RN, REG_SP);
3733
3734         /* create dynamic stack info */
3735
3736         N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3737         N_LR(REG_A1, REG_PV); /* pv */
3738         N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3739         N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3740
3741         disp = dseg_add_functionptr(cd, codegen_start_native_call);
3742         M_ILD(REG_ITMP1, REG_PV, disp);
3743
3744         M_CALL(REG_ITMP1); /* call */
3745
3746         /* restore integer and float argument registers */
3747
3748         j = 96 + (nmd->memuse * 4);
3749
3750         for (i = 0; i < md->paramcount; i++) {
3751                 if (! md->params[i].inmemory) {
3752                         s1 = md->params[i].regoff;
3753
3754                         if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3755                                 if (IS_2_WORD_TYPE(t)) {
3756                                         /* todo load multiple ! */
3757                                         N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3758                                         N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3759                                 } else {
3760                                         N_L(rd->argintregs[s1], j, RN, REG_SP);
3761                                 }
3762                         } else {
3763                                 if (IS_2_WORD_TYPE(t)) {
3764                                         N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3765                                 } else {
3766                                         N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3767                                 }
3768                         }
3769
3770                         j += 8;
3771                 }
3772         }
3773
3774         N_L(REG_ITMP1, j, RN, REG_SP);
3775
3776         /* copy or spill arguments to new locations */
3777
3778         for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3779                 t = md->paramtypes[i].type;
3780
3781                 if (IS_INT_LNG_TYPE(t)) {
3782
3783                         if (!md->params[i].inmemory) {
3784
3785                                 s1 = rd->argintregs[md->params[i].regoff];
3786
3787                                 if (!nmd->params[j].inmemory) {
3788                                         s2 = rd->argintregs[nmd->params[j].regoff];
3789                                         if (IS_2_WORD_TYPE(t)) {
3790                                                 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3791                                                 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3792                                         } else {
3793                                                 N_LR(s2, s1);
3794                                         }
3795                                 } else {
3796                                         s2 = nmd->params[j].regoff;
3797                                         if (IS_2_WORD_TYPE(t)) {
3798                                                 N_STM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3799                                         } else {
3800                                                 N_ST(s1, 96 + (s2 * 4), RN, REG_SP);
3801                                         }
3802                                 }
3803
3804                         } else {
3805                                 s1 = md->params[i].regoff + cd->stackframesize + 1;   /* + 1 (RA) */
3806                                 s2 = nmd->params[j].regoff;
3807                                 
3808                                 if (IS_2_WORD_TYPE(t)) {
3809                                         N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3810                                 } else {
3811                                         N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3812                                 }
3813                         }
3814
3815                 } else {
3816                         /* We only copy spilled float arguments, as the float argument    */
3817                         /* registers keep unchanged.                                      */
3818
3819                         if (md->params[i].inmemory) {
3820                                 s1 = md->params[i].regoff + cd->stackframesize + 1;   /* + 1 (RA) */
3821                                 s2 = nmd->params[j].regoff;
3822
3823                                 if (IS_2_WORD_TYPE(t)) {
3824                                         N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3825                                 } else {
3826                                         N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3827                                 }
3828                         }
3829                 }
3830         }
3831
3832         /* put class into second argument register */
3833
3834         if (m->flags & ACC_STATIC) {
3835                 disp = dseg_add_address(cd, m->class);
3836                 M_ILD(REG_A1, REG_PV, disp);
3837         }
3838
3839         /* put env into first argument register */
3840
3841         disp = dseg_add_address(cd, _Jv_env);
3842         M_ILD(REG_A0, REG_PV, disp);
3843
3844         /* do the native function call */
3845
3846         M_CALL(REG_ITMP1); /* call */
3847
3848         /* save return value */
3849
3850         t = md->returntype.type;
3851
3852         if (t != TYPE_VOID) {
3853                 if (IS_INT_LNG_TYPE(t)) {
3854                         if (IS_2_WORD_TYPE(t)) {
3855                                 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3856                         } else {
3857                                 N_ST(REG_RESULT, 96, RN, REG_SP);
3858                         }
3859                 } else {
3860                         if (IS_2_WORD_TYPE(t)) {
3861                                 N_STD(REG_FRESULT, 96, RN, REG_SP);
3862                         } else {
3863                                 N_STE(REG_FRESULT, 96, RN, REG_SP);
3864                         }
3865                 }
3866         }
3867
3868 #if 0
3869 #if !defined(NDEBUG)
3870         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3871                 emit_verbosecall_exit(jd);
3872 #endif
3873 #endif
3874
3875         /* remove native stackframe info */
3876
3877         N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3878         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3879         M_ILD(REG_ITMP1, REG_PV, disp);
3880         M_CALL(REG_ITMP1);
3881         N_LR(REG_ITMP3, REG_RESULT);
3882
3883         /* restore return value */
3884
3885         if (t != TYPE_VOID) {
3886                 if (IS_INT_LNG_TYPE(t)) {
3887                         if (IS_2_WORD_TYPE(t)) {
3888                                 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3889                         } else {
3890                                 N_L(REG_RESULT, 96, RN, REG_SP);
3891                         }
3892                 } else {
3893                         if (IS_2_WORD_TYPE(t)) {
3894                                 N_LD(REG_FRESULT, 96, RN, REG_SP);
3895                         } else {
3896                                 N_LE(REG_FRESULT, 96, RN, REG_SP);
3897                         }
3898                 }
3899         }
3900
3901         /* load return address */
3902         
3903         N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3904
3905         /* remove stackframe */
3906
3907         N_AHI(REG_SP, cd->stackframesize * 4);
3908
3909         /* test for exception */
3910
3911         N_LTR(REG_ITMP3, REG_ITMP3);
3912         N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3913
3914         /* return */
3915
3916         N_BCR(DD_ANY, REG_ITMP2); 
3917
3918         /* handle exception */
3919
3920         M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3921         M_ALD(REG_ITMP2_XPC, REG_SP, (cd->stackframesize - 1) * 4);     /* get return address from stack */
3922 #if 0
3923         /* TODO */
3924         M_ASUB_IMM(3, REG_ITMP2_XPC);                                    /* callq */
3925 #endif
3926         disp = dseg_add_functionptr(cd, /*asm_handle_nat_exception*/ panic);
3927         N_AHI(REG_SP, 96);
3928         M_ALD(REG_ITMP3, REG_PV, disp);
3929         M_JMP(RN, REG_ITMP3);
3930
3931         /* generate patcher stubs */
3932
3933         emit_patcher_stubs(jd);
3934
3935         codegen_finish(jd);
3936
3937         return code->entrypoint;
3938         return NULL;
3939 }
3940
3941 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3942         codegendata *cd = jd->cd;
3943         s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3944         if (reg == 0) {
3945                 M_MOV(reg, tempregnum);
3946                 return tempregnum;
3947         } else {
3948                 return reg;
3949         }
3950 }
3951
3952 /*
3953  * These are local overrides for various environment variables in Emacs.
3954  * Please do not remove this and leave it at the end of the file, where
3955  * Emacs will automagically detect them.
3956  * ---------------------------------------------------------------------
3957  * Local variables:
3958  * mode: c
3959  * indent-tabs-mode: t
3960  * c-basic-offset: 4
3961  * tab-width: 4
3962  * End:
3963  * vim:noexpandtab:sw=4:ts=4:
3964  */