Compile fix.
[cacao.git] / src / vm / builtin.c
1 /* builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Andreas Krall
29             Mark Probst
30
31    Contains C functions for JavaVM Instructions that cannot be
32    translated to machine language directly. Consequently, the
33    generated machine code for these instructions contains function
34    calls instead of machine instructions, using the C calling
35    convention.
36
37    $Id: builtin.c 781 2003-12-15 15:24:44Z twisti $
38
39 */
40
41
42 #include <assert.h>
43 #include <string.h>
44 #include <math.h>
45 #include "main.h"
46 #include "global.h"
47 #include "builtin.h"
48 #include "native.h"
49 #include "loader.h"
50 #include "tables.h"
51 #include "asmpart.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
54 #include "toolbox/loging.h"
55 #include "toolbox/memory.h"
56 #include "nat/java_lang_Cloneable.h"
57 #include "nat/java_lang_VMObject.h"
58
59
60 #undef DEBUG /*define DEBUG 1*/
61
62 /* XXX delete? */
63 #if 0
64 builtin_descriptor builtin_desc[] = {
65         {(functionptr) builtin_instanceof,                 "instanceof"},
66         {(functionptr) builtin_checkcast,                  "checkcast"},
67         {(functionptr) asm_builtin_checkcast,      "checkcast"},
68         {(functionptr) builtin_arrayinstanceof,    "arrayinstanceof"},
69 #if defined(__I386__)
70         {(functionptr) asm_builtin_arrayinstanceof,"arrayinstanceof"},
71 #endif
72         {(functionptr) builtin_checkarraycast,     "checkarraycast"},
73         {(functionptr) asm_builtin_checkarraycast, "checkarraycast"},
74         {(functionptr) asm_builtin_aastore,                "aastore"},
75         {(functionptr) builtin_new,                                "new"},
76         {(functionptr) builtin_newarray,       "newarray"},
77         {(functionptr) builtin_anewarray,          "anewarray"},
78 #if defined(__I386__)
79         /*
80          * have 2 parameters (needs stack manipulation)
81          */
82         {(functionptr) asm_builtin_newarray,       "newarray"},
83 #endif
84         {(functionptr) builtin_newarray_boolean,   "newarray_boolean"},
85         {(functionptr) builtin_newarray_char,      "newarray_char"},
86         {(functionptr) builtin_newarray_float,     "newarray_float"},
87         {(functionptr) builtin_newarray_double,    "newarray_double"},
88         {(functionptr) builtin_newarray_byte,      "newarray_byte"},
89         {(functionptr) builtin_newarray_short,     "newarray_short"},
90         {(functionptr) builtin_newarray_int,       "newarray_int"},
91         {(functionptr) builtin_newarray_long,      "newarray_long"},
92         {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
93         {(functionptr) builtin_displaymethodstop,  "displaymethodstop"},
94         {(functionptr) builtin_monitorenter,       "monitorenter"},
95         {(functionptr) asm_builtin_monitorenter,   "monitorenter"},
96         {(functionptr) builtin_monitorexit,                "monitorexit"},
97         {(functionptr) asm_builtin_monitorexit,    "monitorexit"},
98 #if !SUPPORT_DIVISION
99         {(functionptr) builtin_idiv,                       "idiv"},
100         {(functionptr) asm_builtin_idiv,                   "idiv"},
101         {(functionptr) builtin_irem,                       "irem"},
102         {(functionptr) asm_builtin_irem,                   "irem"},
103 #endif
104         {(functionptr) builtin_ladd,                       "ladd"},
105         {(functionptr) builtin_lsub,                       "lsub"},
106         {(functionptr) builtin_lmul,                       "lmul"},
107 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
108         {(functionptr) builtin_ldiv,                       "ldiv"},
109         {(functionptr) asm_builtin_ldiv,                   "ldiv"},
110         {(functionptr) builtin_lrem,                       "lrem"},
111         {(functionptr) asm_builtin_lrem,                   "lrem"},
112 #endif
113         {(functionptr) builtin_lshl,                       "lshl"},
114         {(functionptr) builtin_lshr,                       "lshr"},
115         {(functionptr) builtin_lushr,                      "lushr"},
116         {(functionptr) builtin_land,                       "land"},
117         {(functionptr) builtin_lor,                                "lor"},
118         {(functionptr) builtin_lxor,                       "lxor"},
119         {(functionptr) builtin_lneg,                       "lneg"},
120         {(functionptr) builtin_lcmp,                       "lcmp"},
121         {(functionptr) builtin_fadd,                       "fadd"},
122         {(functionptr) builtin_fsub,                       "fsub"},
123         {(functionptr) builtin_fmul,                       "fmul"},
124         {(functionptr) builtin_fdiv,                       "fdiv"},
125         {(functionptr) builtin_frem,                       "frem"},
126         {(functionptr) builtin_fneg,                       "fneg"},
127         {(functionptr) builtin_fcmpl,                      "fcmpl"},
128         {(functionptr) builtin_fcmpg,                      "fcmpg"},
129         {(functionptr) builtin_dadd,                       "dadd"},
130         {(functionptr) builtin_dsub,                       "dsub"},
131         {(functionptr) builtin_dmul,                       "dmul"},
132         {(functionptr) builtin_ddiv,                       "ddiv"},
133         {(functionptr) builtin_drem,                       "drem"},
134         {(functionptr) builtin_dneg,                       "dneg"},
135         {(functionptr) builtin_dcmpl,                      "dcmpl"},
136         {(functionptr) builtin_dcmpg,                      "dcmpg"},
137         {(functionptr) builtin_i2l,                                "i2l"},
138         {(functionptr) builtin_i2f,                                "i2f"},
139         {(functionptr) builtin_i2d,                                "i2d"},
140         {(functionptr) builtin_l2i,                                "l2i"},
141         {(functionptr) builtin_l2f,                                "l2f"},
142         {(functionptr) builtin_l2d,                                "l2d"},
143         {(functionptr) builtin_f2i,                                "f2i"},
144         {(functionptr) builtin_f2l,                                "f2l"},
145         {(functionptr) builtin_f2d,                                "f2d"},
146         {(functionptr) builtin_d2i,                                "d2i"},
147         {(functionptr) builtin_d2l,                                "d2l"},
148 #if defined(__I386__)
149         {(functionptr) asm_builtin_f2i,                    "f2i"},
150         {(functionptr) asm_builtin_f2l,                    "f2l"},
151         {(functionptr) asm_builtin_d2i,                    "d2i"},
152         {(functionptr) asm_builtin_d2l,                    "d2l"},
153 #endif
154         {(functionptr) builtin_d2f,                                "d2f"},
155         {(functionptr) NULL,                                       "unknown"}
156 };
157 #endif
158
159
160 /*****************************************************************************
161                                                                 TYPE CHECKS
162 *****************************************************************************/
163
164
165
166 /*************** internal function: builtin_isanysubclass *********************
167
168         Checks a subclass relation between two classes. Implemented interfaces
169         are interpreted as super classes.
170         Return value:  1 ... sub is subclass of super
171                                    0 ... otherwise
172                                         
173 *****************************************************************************/                                  
174 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
175
176         s4 res;
177
178         /*classinfo *tmp;*/
179         if (super->flags & ACC_INTERFACE)
180                 return (sub->vftbl->interfacetablelength > super->index) &&
181                         (sub->vftbl->interfacetable[-super->index] != NULL);
182
183         /*
184           while (sub != 0)
185           if (sub == super)
186           return 1;
187           else
188           sub = sub->super;
189
190           return 0;
191         */
192
193 /*
194         for (tmp=sub;tmp!=0;tmp=tmp->super) {
195                 printf("->");
196                 utf_display(tmp->name);
197         }
198                 printf("\n\n");
199         
200         for (tmp=super;tmp!=0;tmp=tmp->super) {
201                 printf("->");
202                 utf_display(tmp->name);
203         }
204                 printf("\n");
205         
206
207         printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
208                         sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
209                         super->vftbl->diffval); */
210
211 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
212         cast_lock();
213 #endif
214
215         res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
216                 (unsigned) (super->vftbl->diffval);
217
218 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
219         cast_unlock();
220 #endif
221
222         return res;
223 }
224
225 /* XXX inline this? */
226 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
227 {
228         int base;
229         s4 res;
230         
231 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
232         cast_lock();
233 #endif
234
235         if ((base = super->baseval) <= 0)
236                 /* super is an interface */
237                 res = (sub->interfacetablelength > -base) &&
238                         (sub->interfacetable[base] != NULL);
239         else
240             res = (unsigned) (sub->baseval - base)
241                         <= (unsigned) (super->diffval);
242
243 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
244         cast_unlock();
245 #endif
246
247         return res;
248 }
249
250
251 /****************** function: builtin_instanceof *****************************
252
253         Checks if an object is an instance of some given class (or subclass of
254         that class). If class is an interface, checks if the interface is
255         implemented.
256         Return value:  1 ... obj is an instance of class or implements the interface
257                                    0 ... otherwise or if obj == NULL
258                          
259 *****************************************************************************/
260
261 /* XXX should use vftbl */
262 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
263 {
264 #ifdef DEBUG
265         log_text ("builtin_instanceof called");
266 #endif  
267         if (!obj) return 0;
268         return builtin_isanysubclass (obj->vftbl->class, class);
269 }
270
271
272
273 /**************** function: builtin_checkcast *******************************
274
275         The same as builtin_instanceof except that 1 is returned when
276         obj == NULL
277                           
278 ****************************************************************************/
279
280 /* XXX should use vftbl */
281 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
282 {
283 #ifdef DEBUG
284         log_text("builtin_checkcast called");
285 #endif
286
287         if (obj == NULL)
288                 return 1;
289         if (builtin_isanysubclass(obj->vftbl->class, class))
290                 return 1;
291
292 #if DEBUG
293         printf("#### checkcast failed ");
294         utf_display(obj->vftbl->class->name);
295         printf(" -> ");
296         utf_display(class->name);
297         printf("\n");
298 #endif
299
300         return 0;
301 }
302
303
304 /*********** internal function: builtin_descriptorscompatible ******************
305
306         Checks if two array type descriptors are assignment compatible
307         Return value:  1 ... target = desc is possible
308                                    0 ... otherwise
309                         
310 ******************************************************************************/
311
312 /* XXX inline this? */
313 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
314 {
315         if (desc==target) return 1;
316         if (desc->arraytype != target->arraytype) return 0;
317         if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
318         
319         /* {both arrays are arrays of references} */
320         if (desc->dimension == target->dimension)
321                 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
322         if (desc->dimension < target->dimension) return 0;
323
324         /* {desc has higher dimension than target} */
325         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
326 }
327
328
329 /******************** function: builtin_checkarraycast ***********************
330
331         Checks if an object is really a subtype of the requested array type.
332         The object has to be an array to begin with. For simple arrays (int, short,
333         double, etc.) the types have to match exactly.
334         For arrays of objects, the type of elements in the array has to be a
335         subtype (or the same type) of the requested element type. For arrays of
336         arrays (which in turn can again be arrays of arrays), the types at the
337         lowest level have to satisfy the corresponding sub class relation.
338         
339         Return value:  1 ... cast is possible
340                                    0 ... otherwise
341         
342         ATTENTION: a cast with a NULL pointer is always possible.
343                         
344 *****************************************************************************/
345
346 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
347 {
348         arraydescriptor *desc;
349         
350         if (!o) return 1;
351         if ((desc = o->vftbl->arraydesc) == NULL) return 0;
352
353         return builtin_descriptorscompatible(desc, target->arraydesc);
354 }
355
356
357 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
358 {
359         if (!obj) return 1;
360         return builtin_checkarraycast(obj, target);
361 }
362
363
364 /************************** exception functions *******************************
365
366 ******************************************************************************/
367
368 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
369 {
370         if (verbose) {
371                 char logtext[MAXLOGTEXT];
372                 sprintf(logtext, "Builtin exception thrown: ");
373                 if (local_exceptionptr)
374                         utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
375                 else {
376                         sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
377                         if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
378                         if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
379                         if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
380                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
381                         if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
382                         if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
383                         if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
384                         if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
385                         if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
386                         if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
387                         }
388                 log_text(logtext);
389         }
390         exceptionptr = local_exceptionptr;
391         return local_exceptionptr;
392 }
393
394
395 /******************* function: builtin_canstore *******************************
396
397         Checks, if an object can be stored in an array.
398         Return value:  1 ... possible
399                                    0 ... otherwise
400
401 ******************************************************************************/
402
403 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
404 {
405         arraydescriptor *desc;
406         arraydescriptor *valuedesc;
407         vftbl *componentvftbl;
408         vftbl *valuevftbl;
409     int dim_m1;
410         int base;
411         
412         if (!o) return 1;
413
414         /* The following is guaranteed (by verifier checks):
415          *
416          *     *) a->...vftbl->arraydesc != NULL
417          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
418          *     *) o->vftbl is not an interface vftbl
419          */
420         
421         desc = a->header.objheader.vftbl->arraydesc;
422     componentvftbl = desc->componentvftbl;
423         valuevftbl = o->vftbl;
424
425     if ((dim_m1 = desc->dimension - 1) == 0) {
426                 s4 res;
427
428                 /* {a is a one-dimensional array} */
429                 /* {a is an array of references} */
430                 
431                 if (valuevftbl == componentvftbl)
432                         return 1;
433
434                 if ((base = componentvftbl->baseval) <= 0)
435                         /* an array of interface references */
436                         return (valuevftbl->interfacetablelength > -base &&
437                                         valuevftbl->interfacetable[base] != NULL);
438                 
439 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
440                 cast_lock();
441 #endif
442
443                 res = (unsigned)(valuevftbl->baseval - base)
444                         <= (unsigned)(componentvftbl->diffval);
445
446 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
447                 cast_unlock();
448 #endif
449
450                 return res;
451     }
452     /* {a has dimension > 1} */
453         /* {componentvftbl->arraydesc != NULL} */
454
455         /* check if o is an array */
456         if ((valuedesc = valuevftbl->arraydesc) == NULL)
457                 return 0;
458         /* {o is an array} */
459
460         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
461 }
462
463
464 /* This is an optimized version where a is guaranteed to be one-dimensional */
465 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
466 {
467         arraydescriptor *desc;
468         vftbl *elementvftbl;
469         vftbl *valuevftbl;
470         int base;
471         s4 res;
472         
473         if (!o) return 1;
474
475         /* The following is guaranteed (by verifier checks):
476          *
477          *     *) a->...vftbl->arraydesc != NULL
478          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
479          *     *) a->...vftbl->arraydesc->dimension == 1
480          *     *) o->vftbl is not an interface vftbl
481          */
482
483         desc = a->header.objheader.vftbl->arraydesc;
484     elementvftbl = desc->elementvftbl;
485         valuevftbl = o->vftbl;
486
487         /* {a is a one-dimensional array} */
488         
489         if (valuevftbl == elementvftbl)
490                 return 1;
491
492         if ((base = elementvftbl->baseval) <= 0)
493                 /* an array of interface references */
494                 return (valuevftbl->interfacetablelength > -base &&
495                                 valuevftbl->interfacetable[base] != NULL);
496         
497 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
498         cast_lock();
499 #endif
500
501         res = (unsigned)(valuevftbl->baseval - base)
502                 <= (unsigned)(elementvftbl->diffval);
503
504 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
505         cast_unlock();
506 #endif
507
508         return res;
509 }
510
511
512 /* This is an optimized version where a is guaranteed to be a
513  * one-dimensional array of a class type */
514 /* XXX this could be inlined by the code generator */
515 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
516 {
517         vftbl *elementvftbl;
518         vftbl *valuevftbl;
519         s4 res;
520         
521         if (!o) return 1;
522
523         /* The following is guaranteed (by verifier checks):
524          *
525          *     *) a->...vftbl->arraydesc != NULL
526          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
527          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
528          *     *) a->...vftbl->arraydesc->dimension == 1
529          *     *) o->vftbl is not an interface vftbl
530          */
531
532     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
533         valuevftbl = o->vftbl;
534
535         /* {a is a one-dimensional array} */
536         
537         if (valuevftbl == elementvftbl)
538                 return 1;
539
540 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
541         cast_lock();
542 #endif
543
544         res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
545                 <= (unsigned)(elementvftbl->diffval);
546
547 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
548         cast_unlock();
549 #endif
550
551         return res;
552 }
553
554
555 /******************** Function: builtin_new **********************************
556
557         Creates a new instance of class c on the heap.
558         Return value:  pointer to the object or NULL if no memory is
559                                    available
560                         
561 *****************************************************************************/
562
563 #define ALIGNMENT 3
564 #define align_size(size)        ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
565
566 java_objectheader *builtin_new(classinfo *c)
567 {
568         java_objectheader *o;
569
570         class_init(c);
571
572 #ifdef SIZE_FROM_CLASSINFO
573         c->alignedsize = align_size(c->instancesize);
574         o = heap_allocate(c->alignedsize, true, c->finalizer);
575 #else
576         o = heap_allocate(c->instancesize, true, c->finalizer);
577 #endif
578         if (!o) return NULL;
579         
580         memset(o, 0, c->instancesize);
581
582         o->vftbl = c->vftbl;
583
584         return o;
585 }
586
587 /********************** Function: builtin_newarray **************************
588
589         Creates an array with the given vftbl on the heap.
590
591         Return value:  pointer to the array or NULL if no memory is available
592
593     CAUTION: The given vftbl must be the vftbl of the *array* class,
594     not of the element class.
595
596 *****************************************************************************/
597
598 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
599 {
600         java_arrayheader *a;
601         arraydescriptor *desc = arrayvftbl->arraydesc;
602         s4 dataoffset = desc->dataoffset;
603         s4 componentsize = desc->componentsize;
604                 s4 actualsize;
605
606         if (size<0) {
607                 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
608                 return NULL;
609         }
610 #ifdef SIZE_FROM_CLASSINFO
611         actualsize = align_size(dataoffset + size * componentsize);
612 #else
613         actualsize = dataoffset + size * componentsize;
614 #endif
615
616         if (((u4)actualsize)<((u4)size)) { /* overflow */
617                 exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
618                 return NULL;
619         }
620         a = (java_arrayheader *) heap_allocate(actualsize,
621                                                                                            (desc->arraytype == ARRAYTYPE_OBJECT),
622                                                                                            NULL);
623         if (!a) return NULL;
624         memset(a,0,actualsize);
625
626
627         /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
628
629         a->objheader.vftbl = arrayvftbl;
630         a->size = size;
631 #ifdef SIZE_FROM_CLASSINFO
632         a->alignedsize = actualsize;
633 #endif
634
635         return a;
636 }
637
638
639 /********************** Function: builtin_anewarray *************************
640
641         Creates an array of references to the given class type on the heap.
642
643         Return value:  pointer to the array or NULL if no memory is available
644
645     XXX This function does not do The Right Thing, because it uses a
646     classinfo pointer at runtime. builtin_newarray should be used
647     instead.
648
649 *****************************************************************************/
650
651 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
652 {
653         return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
654 }
655
656
657 /******************** Function: builtin_newarray_int ***********************
658
659         Creates an array of 32 bit Integers on the heap.
660
661         Return value:  pointer to the array or NULL if no memory is available
662
663 *****************************************************************************/
664
665 java_intarray *builtin_newarray_int(s4 size)
666 {
667         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
668 }
669
670
671 /******************** Function: builtin_newarray_long ***********************
672
673         Creates an array of 64 bit Integers on the heap.
674
675         Return value:  pointer to the array or NULL if no memory is available
676
677 *****************************************************************************/
678
679 java_longarray *builtin_newarray_long(s4 size)
680 {
681         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
682 }
683
684
685 /******************** function: builtin_newarray_float ***********************
686
687         Creates an array of 32 bit IEEE floats on the heap.
688
689         Return value:  pointer to the array or NULL if no memory is available
690
691 *****************************************************************************/
692
693 java_floatarray *builtin_newarray_float(s4 size)
694 {
695         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
696 }
697
698
699 /******************** function: builtin_newarray_double ***********************
700
701         Creates an array of 64 bit IEEE floats on the heap.
702
703         Return value:  pointer to the array or NULL if no memory is available
704
705 *****************************************************************************/
706
707 java_doublearray *builtin_newarray_double(s4 size)
708 {
709         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
710 }
711
712
713 /******************** function: builtin_newarray_byte ***********************
714
715         Creates an array of 8 bit Integers on the heap.
716
717         Return value:  pointer to the array or NULL if no memory is available
718
719 *****************************************************************************/
720
721 java_bytearray *builtin_newarray_byte(s4 size)
722 {
723         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
724 }
725
726
727 /******************** function: builtin_newarray_char ************************
728
729         Creates an array of characters on the heap.
730
731         Return value:  pointer to the array or NULL if no memory is available
732
733 *****************************************************************************/
734
735 java_chararray *builtin_newarray_char(s4 size)
736 {
737         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
738 }
739
740
741 /******************** function: builtin_newarray_short ***********************
742
743         Creates an array of 16 bit Integers on the heap.
744
745         Return value:  pointer to the array or NULL if no memory is available
746
747 *****************************************************************************/
748
749 java_shortarray *builtin_newarray_short(s4 size)
750 {
751         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
752 }
753
754
755 /******************** function: builtin_newarray_boolean ************************
756
757         Creates an array of bytes on the heap. The array is designated as an array
758         of booleans (important for casts)
759         
760         Return value:  pointer to the array or NULL if no memory is available
761
762 *****************************************************************************/
763
764 java_booleanarray *builtin_newarray_boolean(s4 size)
765 {
766         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
767 }
768
769
770 /**************** function: builtin_nmultianewarray ***************************
771
772         Creates a multi-dimensional array on the heap. The dimensions are passed in
773         an array of longs.
774
775     Arguments:
776         n............number of dimensions to create
777         arrayvftbl...vftbl of the array class
778         dims.........array containing the size of each dimension to create
779
780         Return value:  pointer to the array or NULL if no memory is available
781
782 ******************************************************************************/
783
784         /* Helper functions */
785
786 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
787 {
788         int size, i;
789         java_arrayheader *a;
790         vftbl *componentvftbl;
791
792         /* create this dimension */
793         size = (int) dims[0];
794         a = builtin_newarray(size,arrayvftbl);
795         if (!a) return NULL;
796
797         /* if this is the last dimension return */
798         if (!--n) return a;
799
800         /* get the vftbl of the components to create */
801         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
802         if (!componentvftbl) /* XXX the verifier could check this */
803                 panic ("multianewarray with too many dimensions");
804
805         /* create the component arrays */
806         for (i = 0; i < size; i++) {
807                 java_arrayheader *ea = 
808                         builtin_nmultianewarray(n,componentvftbl,dims+1);
809                 if (!ea) return NULL;
810                 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
811         }
812
813         return a;
814 }
815
816
817 /*****************************************************************************
818                                           METHOD LOGGING
819
820         Various functions for printing a message at method entry or exit (for
821         debugging)
822         
823 *****************************************************************************/
824
825
826 u4 methodindent = 0;
827
828 java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
829                                                                                    methodinfo *method, int *pos, 
830                                                                                    int noindent)
831 {
832         if (!noindent)
833                 methodindent--;
834         if (verbose || runverbose) {
835                 printf("Exception ");
836                 if (exceptionptr) {
837                         utf_display (exceptionptr->vftbl->class->name);
838                 }
839                 else {
840                         printf("Error: <Nullpointer instead of exception>");
841                         if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
842                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
843                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
844                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
845                         if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
846                         if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
847                         if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
848                         if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
849                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
850                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
851
852                 }
853                 printf(" thrown in ");
854                 if (method) {
855                         utf_display (method->class->name);
856                         printf(".");
857                         utf_display (method->name);
858                         if (method->flags & ACC_SYNCHRONIZED)
859                                 printf("(SYNC)");
860                         else
861                                 printf("(NOSYNC)");
862                         printf("(%p) at position %p\n", method->entrypoint, pos);
863                 }
864                 else
865                         printf("call_java_method\n");
866                 fflush (stdout);
867         }
868         return exceptionptr;
869 }
870
871
872 #ifdef TRACE_ARGS_NUM
873 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
874 #if TRACE_ARGS_NUM > 6
875                                                 s8 a6, s8 a7,
876 #endif
877                                                 methodinfo *method)
878 {
879         int i;
880         char logtext[MAXLOGTEXT];
881         for (i = 0; i < methodindent; i++)
882                 logtext[i] = '\t';
883         sprintf(logtext + methodindent, "called: ");
884         utf_sprint(logtext + strlen(logtext), method->class->name);
885         sprintf(logtext + strlen(logtext), ".");
886         utf_sprint(logtext + strlen(logtext), method->name);
887         utf_sprint(logtext + strlen(logtext), method->descriptor);
888         sprintf(logtext + strlen(logtext), "(");
889
890         switch (method->paramcount) {
891         case 0:
892                 break;
893
894 #if defined(__I386__)
895         case 1:
896                 sprintf(logtext+strlen(logtext), "%llx", a0);
897                 break;
898
899         case 2:
900                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
901                 break;
902
903         case 3:
904                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
905                 break;
906
907         case 4:
908                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
909                                 a0,   a1,   a2,   a3);
910                 break;
911
912         case 5:
913                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
914                                 a0,   a1,   a2,   a3,   a4);
915                 break;
916
917         case 6:
918                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
919                                 a0,   a1,   a2,   a3,   a4,   a5);
920                 break;
921
922 #if TRACE_ARGS_NUM > 6
923         case 7:
924                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
925                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
926                 break;
927
928         case 8:
929                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
930                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
931                 break;
932
933         default:
934                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
935                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
936                 break;
937 #else
938         default:
939                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
940                                 a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
941                 break;
942 #endif
943 #else
944         case 1:
945                 sprintf(logtext+strlen(logtext), "%lx", a0);
946                 break;
947
948         case 2:
949                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
950                 break;
951
952         case 3:
953                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
954                 break;
955
956         case 4:
957                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
958                                 a0,  a1,  a2,  a3);
959                 break;
960
961         case 5:
962                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
963                                 a0,  a1,  a2,  a3,  a4);
964                 break;
965
966         case 6:
967                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
968                                 a0,  a1,  a2,  a3,  a4,  a5);
969                 break;
970
971 #if TRACE_ARGS_NUM > 6
972         case 7:
973                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
974                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
975                 break;
976
977         case 8:
978                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
979                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
980                 break;
981
982         default:
983                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
984                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
985                 break;
986 #else
987         default:
988                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
989                                 a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
990                 break;
991 #endif
992 #endif
993         }
994         sprintf (logtext+strlen(logtext), ")");
995         log_text(logtext);
996
997         methodindent++;
998 }
999 #endif
1000
1001
1002 void builtin_displaymethodstart(methodinfo *method)
1003 {
1004         char logtext[MAXLOGTEXT];
1005         sprintf(logtext, "                                                                                              ");
1006         sprintf(logtext + methodindent, "called: ");
1007         utf_sprint(logtext + strlen(logtext), method->class->name);
1008         sprintf(logtext + strlen(logtext), ".");
1009         utf_sprint(logtext + strlen(logtext), method->name);
1010         utf_sprint(logtext + strlen(logtext), method->descriptor);
1011         log_text(logtext);
1012         methodindent++;
1013 }
1014
1015
1016 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1017 {
1018         int i;
1019         char logtext[MAXLOGTEXT];
1020         for (i = 0; i < methodindent; i++)
1021                 logtext[i] = '\t';
1022         methodindent--;
1023         sprintf(logtext + methodindent, "finished: ");
1024         utf_sprint(logtext + strlen(logtext), method->class->name);
1025         sprintf(logtext + strlen(logtext), ".");
1026         utf_sprint(logtext + strlen(logtext), method->name);
1027         utf_sprint(logtext + strlen(logtext), method->descriptor);
1028
1029         switch (method->returntype) {
1030         case TYPE_INT:
1031                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1032                 break;
1033         case TYPE_LONG:
1034 #if defined(__I386__)
1035                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1036 #else
1037                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1038 #endif
1039                 break;
1040         case TYPE_ADDRESS:
1041 #if defined(__I386__)
1042                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1043 #else
1044                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1045 #endif
1046                 break;
1047         case TYPE_FLOAT:
1048                 sprintf(logtext + strlen(logtext), "->%g", f);
1049                 break;
1050         case TYPE_DOUBLE:
1051                 sprintf(logtext + strlen(logtext), "->%g", d);
1052                 break;
1053         }
1054         log_text(logtext);
1055 }
1056
1057
1058 void builtin_displaymethodexception(methodinfo *method)
1059 {
1060         int i;
1061         char logtext[MAXLOGTEXT];
1062         for (i = 0; i < methodindent; i++)
1063                 logtext[i] = '\t';
1064         sprintf(logtext + methodindent, "exception abort: ");
1065         utf_sprint(logtext + strlen(logtext), method->class->name);
1066         sprintf(logtext + strlen(logtext), ".");
1067         utf_sprint(logtext + strlen(logtext), method->name);
1068         utf_sprint(logtext + strlen(logtext), method->descriptor);
1069         log_text(logtext);
1070 }
1071
1072
1073 /****************************************************************************
1074                          SYNCHRONIZATION FUNCTIONS
1075 *****************************************************************************/
1076
1077 /*
1078  * Lock the mutex of an object.
1079  */
1080 void internal_lock_mutex_for_object(java_objectheader *object)
1081 {
1082 #ifdef USE_THREADS
1083         mutexHashEntry *entry;
1084         int hashValue;
1085
1086         assert(object != 0);
1087
1088         hashValue = MUTEX_HASH_VALUE(object);
1089         entry = &mutexHashTable[hashValue];
1090
1091         if (entry->object != 0) {
1092                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1093                         entry->object = 0;
1094                         entry->mutex.holder = 0;
1095                         entry->mutex.count = 0;
1096                         entry->mutex.muxWaiters = 0;
1097
1098                 } else {
1099                         while (entry->next != 0 && entry->object != object)
1100                                 entry = entry->next;
1101
1102                         if (entry->object != object) {
1103                                 entry->next = firstFreeOverflowEntry;
1104                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1105
1106                                 entry = entry->next;
1107                                 entry->object = 0;
1108                                 entry->next = 0;
1109                                 assert(entry->conditionCount == 0);
1110                         }
1111                 }
1112
1113         } else {
1114                 entry->mutex.holder = 0;
1115                 entry->mutex.count = 0;
1116                 entry->mutex.muxWaiters = 0;
1117         }
1118
1119         if (entry->object == 0)
1120                 entry->object = object;
1121         
1122         internal_lock_mutex(&entry->mutex);
1123 #endif
1124 }
1125
1126
1127 /*
1128  * Unlocks the mutex of an object.
1129  */
1130 void internal_unlock_mutex_for_object (java_objectheader *object)
1131 {
1132 #ifdef USE_THREADS
1133         int hashValue;
1134         mutexHashEntry *entry;
1135
1136         hashValue = MUTEX_HASH_VALUE(object);
1137         entry = &mutexHashTable[hashValue];
1138
1139         if (entry->object == object) {
1140                 internal_unlock_mutex(&entry->mutex);
1141
1142         } else {
1143                 while (entry->next != 0 && entry->next->object != object)
1144                         entry = entry->next;
1145
1146                 assert(entry->next != 0);
1147
1148                 internal_unlock_mutex(&entry->next->mutex);
1149
1150                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1151                         mutexHashEntry *unlinked = entry->next;
1152
1153                         entry->next = unlinked->next;
1154                         unlinked->next = firstFreeOverflowEntry;
1155                         firstFreeOverflowEntry = unlinked;
1156                 }
1157         }
1158 #endif
1159 }
1160
1161
1162 void builtin_monitorenter(java_objectheader *o)
1163 {
1164 #ifdef USE_THREADS
1165         int hashValue;
1166
1167         assert(blockInts == 0);
1168
1169         ++blockInts;
1170
1171         hashValue = MUTEX_HASH_VALUE(o);
1172         if (mutexHashTable[hashValue].object == o 
1173                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1174                 ++mutexHashTable[hashValue].mutex.count;
1175         else
1176                 internal_lock_mutex_for_object(o);
1177
1178         --blockInts;
1179
1180         assert(blockInts == 0);
1181 #endif
1182 }
1183
1184
1185 void builtin_monitorexit (java_objectheader *o)
1186 {
1187 #ifdef USE_THREADS
1188         int hashValue;
1189
1190         assert(blockInts == 0);
1191
1192         ++blockInts;
1193
1194         hashValue = MUTEX_HASH_VALUE(o);
1195         if (mutexHashTable[hashValue].object == o) {
1196                 if (mutexHashTable[hashValue].mutex.count == 1
1197                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1198                         internal_unlock_mutex_for_object(o);
1199                 else
1200                         --mutexHashTable[hashValue].mutex.count;
1201
1202         } else
1203                 internal_unlock_mutex_for_object(o);
1204
1205         --blockInts;
1206
1207         assert(blockInts == 0);
1208 #endif
1209 }
1210
1211
1212 /*****************************************************************************
1213                           MISCELLANEOUS HELPER FUNCTIONS
1214 *****************************************************************************/
1215
1216
1217
1218 /*********** Functions for integer divisions *****************************
1219  
1220         On some systems (eg. DEC ALPHA), integer division is not supported by the
1221         CPU. These helper functions implement the missing functionality.
1222
1223 ******************************************************************************/
1224
1225 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1226 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1227
1228
1229 /************** Functions for long arithmetics *******************************
1230
1231         On systems where 64 bit Integers are not supported by the CPU, these
1232         functions are needed.
1233
1234 ******************************************************************************/
1235
1236
1237 s8 builtin_ladd(s8 a, s8 b)
1238
1239 #if U8_AVAILABLE
1240         return a + b; 
1241 #else
1242         return builtin_i2l(0);
1243 #endif
1244 }
1245
1246 s8 builtin_lsub(s8 a, s8 b) 
1247
1248 #if U8_AVAILABLE
1249         return a - b; 
1250 #else
1251         return builtin_i2l(0);
1252 #endif
1253 }
1254
1255 s8 builtin_lmul(s8 a, s8 b) 
1256
1257 #if U8_AVAILABLE
1258         return a * b; 
1259 #else
1260         return builtin_i2l(0);
1261 #endif
1262 }
1263
1264 s8 builtin_ldiv(s8 a, s8 b) 
1265
1266 #if U8_AVAILABLE
1267         return a / b; 
1268 #else
1269         return builtin_i2l(0);
1270 #endif
1271 }
1272
1273 s8 builtin_lrem(s8 a, s8 b) 
1274
1275 #if U8_AVAILABLE
1276         return a % b; 
1277 #else
1278         return builtin_i2l(0);
1279 #endif
1280 }
1281
1282 s8 builtin_lshl(s8 a, s4 b) 
1283
1284 #if U8_AVAILABLE
1285         return a << (b & 63);
1286 #else
1287         return builtin_i2l(0);
1288 #endif
1289 }
1290
1291 s8 builtin_lshr(s8 a, s4 b) 
1292
1293 #if U8_AVAILABLE
1294         return a >> (b & 63);
1295 #else
1296         return builtin_i2l(0);
1297 #endif
1298 }
1299
1300 s8 builtin_lushr(s8 a, s4 b) 
1301
1302 #if U8_AVAILABLE
1303         return ((u8) a) >> (b & 63);
1304 #else
1305         return builtin_i2l(0);
1306 #endif
1307 }
1308
1309 s8 builtin_land(s8 a, s8 b) 
1310
1311 #if U8_AVAILABLE
1312         return a & b; 
1313 #else
1314         return builtin_i2l(0);
1315 #endif
1316 }
1317
1318 s8 builtin_lor(s8 a, s8 b) 
1319
1320 #if U8_AVAILABLE
1321         return a | b; 
1322 #else
1323         return builtin_i2l(0);
1324 #endif
1325 }
1326
1327 s8 builtin_lxor(s8 a, s8 b) 
1328
1329 #if U8_AVAILABLE
1330         return a ^ b; 
1331 #else
1332         return builtin_i2l(0);
1333 #endif
1334 }
1335
1336 s8 builtin_lneg(s8 a) 
1337
1338 #if U8_AVAILABLE
1339         return -a;
1340 #else
1341         return builtin_i2l(0);
1342 #endif
1343 }
1344
1345 s4 builtin_lcmp(s8 a, s8 b) 
1346
1347 #if U8_AVAILABLE
1348         if (a < b) return -1;
1349         if (a > b) return 1;
1350         return 0;
1351 #else
1352         return 0;
1353 #endif
1354 }
1355
1356
1357
1358
1359
1360 /*********** Functions for floating point operations *************************/
1361
1362 float builtin_fadd(float a, float b)
1363 {
1364         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1365         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1366         if (finitef(a)) {
1367                 if (finitef(b))
1368                         return a + b;
1369                 else
1370                         return b;
1371         }
1372         else {
1373                 if (finitef(b))
1374                         return a;
1375                 else {
1376                         if (copysignf(1.0, a) == copysignf(1.0, b))
1377                                 return a;
1378                         else
1379                                 return intBitsToFloat(FLT_NAN);
1380                 }
1381         }
1382 }
1383
1384
1385 float builtin_fsub(float a, float b)
1386 {
1387         return builtin_fadd(a, builtin_fneg(b));
1388 }
1389
1390
1391 float builtin_fmul(float a, float b)
1392 {
1393         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1394         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1395         if (finitef(a)) {
1396                 if (finitef(b)) return a * b;
1397                 else {
1398                         if (a == 0) return intBitsToFloat(FLT_NAN);
1399                         else return copysignf(b, copysignf(1.0, b)*a);
1400                 }
1401         }
1402         else {
1403                 if (finitef(b)) {
1404                         if (b == 0) return intBitsToFloat(FLT_NAN);
1405                         else return copysignf(a, copysignf(1.0, a)*b);
1406                 }
1407                 else {
1408                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1409                 }
1410         }
1411 }
1412
1413
1414 float builtin_fdiv(float a, float b)
1415 {
1416         if (finitef(a) && finitef(b)) {
1417                 if (b != 0)
1418                         return a / b;
1419                 else {
1420                         if (a > 0)
1421                                 return intBitsToFloat(FLT_POSINF);
1422                         else if (a < 0)
1423                                 return intBitsToFloat(FLT_NEGINF);
1424                 }
1425         }
1426         return intBitsToFloat(FLT_NAN);
1427 }
1428
1429
1430 float builtin_frem(float a, float b)
1431 {
1432         return fmodf(a, b);
1433 }
1434
1435
1436 float builtin_fneg(float a)
1437 {
1438         if (isnanf(a)) return a;
1439         else {
1440                 if (finitef(a)) return -a;
1441                 else return copysignf(a, -copysignf(1.0, a));
1442         }
1443 }
1444
1445
1446 s4 builtin_fcmpl(float a, float b)
1447 {
1448         if (isnanf(a)) return -1;
1449         if (isnanf(b)) return -1;
1450         if (!finitef(a) || !finitef(b)) {
1451                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1452                 b = finitef(b) ? 0 : copysignf(1.0, b);
1453         }
1454         if (a > b) return 1;
1455         if (a == b) return 0;
1456         return -1;
1457 }
1458
1459
1460 s4 builtin_fcmpg(float a, float b)
1461 {
1462         if (isnanf(a)) return 1;
1463         if (isnanf(b)) return 1;
1464         if (!finitef(a) || !finitef(b)) {
1465                 a = finitef(a) ? 0 : copysignf(1.0, a);
1466                 b = finitef(b) ? 0 : copysignf(1.0, b);
1467         }
1468         if (a > b) return 1;
1469         if (a == b) return 0;
1470         return -1;
1471 }
1472
1473
1474
1475 /************************* Functions for doubles ****************************/
1476
1477 double builtin_dadd(double a, double b)
1478 {
1479         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1480         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1481         if (finite(a)) {
1482                 if (finite(b)) return a + b;
1483                 else return b;
1484         }
1485         else {
1486                 if (finite(b)) return a;
1487                 else {
1488                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1489                         else return longBitsToDouble(DBL_NAN);
1490                 }
1491         }
1492 }
1493
1494
1495 double builtin_dsub(double a, double b)
1496 {
1497         return builtin_dadd(a, builtin_dneg(b));
1498 }
1499
1500
1501 double builtin_dmul(double a, double b)
1502 {
1503         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1504         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1505         if (finite(a)) {
1506                 if (finite(b)) return a * b;
1507                 else {
1508                         if (a == 0) return longBitsToDouble(DBL_NAN);
1509                         else return copysign(b, copysign(1.0, b) * a);
1510                 }
1511         }
1512         else {
1513                 if (finite(b)) {
1514                         if (b == 0) return longBitsToDouble(DBL_NAN);
1515                         else return copysign(a, copysign(1.0, a) * b);
1516                 }
1517                 else {
1518                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1519                 }
1520         }
1521 }
1522
1523
1524 double builtin_ddiv(double a, double b)
1525 {
1526         if (finite(a)) {
1527                 if (finite(b)) {
1528                         return a / b;
1529
1530                 } else {
1531                         if (isnan(b))
1532                                 return longBitsToDouble(DBL_NAN);
1533                         else
1534                                 return copysign(0.0, b);
1535                 }
1536
1537         } else {
1538                 if (finite(b)) {
1539                         if (a > 0)
1540                                 return longBitsToDouble(DBL_POSINF);
1541                         else if (a < 0)
1542                                 return longBitsToDouble(DBL_NEGINF);
1543
1544                 } else
1545                         return longBitsToDouble(DBL_NAN);
1546         }
1547
1548 /*      if (finite(a) && finite(b)) { */
1549 /*              if (b != 0) */
1550 /*                      return a / b; */
1551 /*              else { */
1552 /*                      if (a > 0) */
1553 /*                              return longBitsToDouble(DBL_POSINF); */
1554 /*                      else if (a < 0) */
1555 /*                              return longBitsToDouble(DBL_NEGINF); */
1556 /*              } */
1557 /*      } */
1558
1559         /* keep compiler happy */
1560         return 0;
1561 }
1562
1563
1564 double builtin_drem(double a, double b)
1565 {
1566         return fmod(a, b);
1567 }
1568
1569
1570 double builtin_dneg(double a)
1571 {
1572         if (isnan(a)) return a;
1573         else {
1574                 if (finite(a)) return -a;
1575                 else return copysign(a, -copysign(1.0, a));
1576         }
1577 }
1578
1579
1580 s4 builtin_dcmpl(double a, double b)
1581 {
1582         if (isnan(a)) return -1;
1583         if (isnan(b)) return -1;
1584         if (!finite(a) || !finite(b)) {
1585                 a = finite(a) ? 0 : copysign(1.0, a);
1586                 b = finite(b) ? 0 : copysign(1.0, b);
1587         }
1588         if (a > b) return 1;
1589         if (a == b) return 0;
1590         return -1;
1591 }
1592
1593
1594 s4 builtin_dcmpg(double a, double b)
1595 {
1596         if (isnan(a)) return 1;
1597         if (isnan(b)) return 1;
1598         if (!finite(a) || !finite(b)) {
1599                 a = finite(a) ? 0 : copysign(1.0, a);
1600                 b = finite(b) ? 0 : copysign(1.0, b);
1601         }
1602         if (a > b) return 1;
1603         if (a == b) return 0;
1604         return -1;
1605 }
1606
1607
1608 /*********************** Conversion operations ****************************/
1609
1610 s8 builtin_i2l(s4 i)
1611 {
1612 #if U8_AVAILABLE
1613         return i;
1614 #else
1615         s8 v;
1616         v.high = 0;
1617         v.low = i;
1618         return v;
1619 #endif
1620 }
1621
1622
1623 float builtin_i2f(s4 a)
1624 {
1625         float f = (float) a;
1626         return f;
1627 }
1628
1629
1630 double builtin_i2d(s4 a)
1631 {
1632         double d = (double) a;
1633         return d;
1634 }
1635
1636
1637 s4 builtin_l2i(s8 l)
1638 {
1639 #if U8_AVAILABLE
1640         return (s4) l;
1641 #else
1642         return l.low;
1643 #endif
1644 }
1645
1646
1647 float builtin_l2f(s8 a)
1648 {
1649 #if U8_AVAILABLE
1650         float f = (float) a;
1651         return f;
1652 #else
1653         return 0.0;
1654 #endif
1655 }
1656
1657
1658 double builtin_l2d(s8 a)
1659 {
1660 #if U8_AVAILABLE
1661         double d = (double) a;
1662         return d;
1663 #else
1664         return 0.0;
1665 #endif
1666 }
1667
1668
1669 s4 builtin_f2i(float a) 
1670 {
1671
1672         return builtin_d2i((double) a);
1673
1674         /*      float f;
1675         
1676                 if (isnanf(a))
1677                 return 0;
1678                 if (finitef(a)) {
1679                 if (a > 2147483647)
1680                 return 2147483647;
1681                 if (a < (-2147483648))
1682                 return (-2147483648);
1683                 return (s4) a;
1684                 }
1685                 f = copysignf((float) 1.0, a);
1686                 if (f > 0)
1687                 return 2147483647;
1688                 return (-2147483648); */
1689 }
1690
1691
1692 s8 builtin_f2l(float a)
1693 {
1694
1695         return builtin_d2l((double) a);
1696
1697         /*      float f;
1698         
1699                 if (finitef(a)) {
1700                 if (a > 9223372036854775807L)
1701                 return 9223372036854775807L;
1702                 if (a < (-9223372036854775808L))
1703                 return (-9223372036854775808L);
1704                 return (s8) a;
1705                 }
1706                 if (isnanf(a))
1707                 return 0;
1708                 f = copysignf((float) 1.0, a);
1709                 if (f > 0)
1710                 return 9223372036854775807L;
1711                 return (-9223372036854775808L); */
1712 }
1713
1714
1715 double builtin_f2d(float a)
1716 {
1717         if (finitef(a)) return (double) a;
1718         else {
1719                 if (isnanf(a))
1720                         return longBitsToDouble(DBL_NAN);
1721                 else
1722                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1723         }
1724 }
1725
1726
1727 s4 builtin_d2i(double a) 
1728
1729         double d;
1730         
1731         if (finite(a)) {
1732                 if (a >= 2147483647)
1733                         return 2147483647;
1734                 if (a <= (-2147483647-1))
1735                         return (-2147483647-1);
1736                 return (s4) a;
1737         }
1738         if (isnan(a))
1739                 return 0;
1740         d = copysign(1.0, a);
1741         if (d > 0)
1742                 return 2147483647;
1743         return (-2147483647-1);
1744 }
1745
1746
1747 s8 builtin_d2l(double a)
1748 {
1749         double d;
1750         
1751         if (finite(a)) {
1752                 if (a >= 9223372036854775807LL)
1753                         return 9223372036854775807LL;
1754                 if (a <= (-9223372036854775807LL-1))
1755                         return (-9223372036854775807LL-1);
1756                 return (s8) a;
1757         }
1758         if (isnan(a))
1759                 return 0;
1760         d = copysign(1.0, a);
1761         if (d > 0)
1762                 return 9223372036854775807LL;
1763         return (-9223372036854775807LL-1);
1764 }
1765
1766
1767 float builtin_d2f(double a)
1768 {
1769         if (finite(a))
1770                 return (float) a;
1771         else {
1772                 if (isnan(a))
1773                         return intBitsToFloat(FLT_NAN);
1774                 else
1775                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1776         }
1777 }
1778
1779
1780 /* used to convert FLT_xxx defines into float values */
1781
1782 inline float intBitsToFloat(s4 i)
1783 {
1784         imm_union imb;
1785
1786         imb.i = i;
1787         return imb.f;
1788 }
1789
1790
1791 /* used to convert DBL_xxx defines into double values */
1792
1793 inline float longBitsToDouble(s8 l)
1794 {
1795         imm_union imb;
1796
1797         imb.l = l;
1798         return imb.d;
1799 }
1800
1801
1802 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1803 {
1804         return Java_java_lang_VMObject_clone(0, 0, o);
1805 }
1806
1807
1808 /*
1809  * These are local overrides for various environment variables in Emacs.
1810  * Please do not remove this and leave it at the end of the file, where
1811  * Emacs will automagically detect them.
1812  * ---------------------------------------------------------------------
1813  * Local variables:
1814  * mode: c
1815  * indent-tabs-mode: t
1816  * c-basic-offset: 4
1817  * tab-width: 4
1818  * End:
1819  */