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