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