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