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