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