ea441550006ed52551f432dbaa95ec2bf427b511
[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 669 2003-11-23 14:04:20Z edwin $
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
537 #ifdef SIZE_FROM_CLASSINFO
538         s4 actualsize = align_size(dataoffset + size * componentsize);
539 #else
540         s4 actualsize = dataoffset + size * componentsize;
541 #endif
542         a = (java_arrayheader *)
543                 heap_allocate(actualsize,
544                                           (desc->arraytype == ARRAYTYPE_OBJECT),
545                                           NULL);
546
547         if (!a) return NULL;
548         memset(a,0,actualsize);
549
550         a->objheader.vftbl = arrayvftbl;
551         a->size = size;
552 #ifdef SIZE_FROM_CLASSINFO
553         a->alignedsize = actualsize;
554 #endif
555         return a;
556 }
557
558 /********************** Function: builtin_anewarray *************************
559
560         Creates an array of references to the given class type on the heap.
561
562         Return value:  pointer to the array or NULL if no memory is available
563
564     XXX This function does not do The Right Thing, because it uses a
565     classinfo pointer at runtime. builtin_newarray should be used
566     instead.
567
568 *****************************************************************************/
569
570 java_objectarray *
571 builtin_anewarray(s4 size,classinfo *component)
572 {
573         return (java_objectarray*) builtin_newarray(size,class_array_of(component)->vftbl);
574 }
575
576 /******************** Function: builtin_newarray_int ***********************
577
578         Creates an array of 32 bit Integers on the heap.
579
580         Return value:  pointer to the array or NULL if no memory is available
581
582 *****************************************************************************/
583
584 java_intarray *builtin_newarray_int (s4 size)
585 {
586         return (java_intarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
587 }
588
589 /******************** Function: builtin_newarray_long ***********************
590
591         Creates an array of 64 bit Integers on the heap.
592
593         Return value:  pointer to the array or NULL if no memory is available
594
595 *****************************************************************************/
596
597 java_longarray *builtin_newarray_long (s4 size)
598 {
599         return (java_longarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
600 }
601
602 /******************** function: builtin_newarray_float ***********************
603
604         Creates an array of 32 bit IEEE floats on the heap.
605
606         Return value:  pointer to the array or NULL if no memory is available
607
608 *****************************************************************************/
609
610 java_floatarray *builtin_newarray_float (s4 size)
611 {
612         return (java_floatarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
613 }
614
615 /******************** function: builtin_newarray_double ***********************
616
617         Creates an array of 64 bit IEEE floats on the heap.
618
619         Return value:  pointer to the array or NULL if no memory is available
620
621 *****************************************************************************/
622
623 java_doublearray *builtin_newarray_double (s4 size)
624 {
625         return (java_doublearray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
626 }
627
628 /******************** function: builtin_newarray_byte ***********************
629
630         Creates an array of 8 bit Integers on the heap.
631
632         Return value:  pointer to the array or NULL if no memory is available
633
634 *****************************************************************************/
635
636 java_bytearray *builtin_newarray_byte (s4 size)
637 {
638         return (java_bytearray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
639 }
640
641 /******************** function: builtin_newarray_char ************************
642
643         Creates an array of characters on the heap.
644
645         Return value:  pointer to the array or NULL if no memory is available
646
647 *****************************************************************************/
648
649 java_chararray *builtin_newarray_char (s4 size)
650 {
651         return (java_chararray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
652 }
653
654 /******************** function: builtin_newarray_short ***********************
655
656         Creates an array of 16 bit Integers on the heap.
657
658         Return value:  pointer to the array or NULL if no memory is available
659
660 *****************************************************************************/
661
662 java_shortarray *builtin_newarray_short (s4 size)
663 {
664         return (java_shortarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
665 }
666
667 /******************** function: builtin_newarray_boolean ************************
668
669         Creates an array of bytes on the heap. The array is designated as an array
670         of booleans (important for casts)
671         
672         Return value:  pointer to the array or NULL if no memory is available
673
674 *****************************************************************************/
675
676 java_booleanarray *builtin_newarray_boolean (s4 size)
677 {
678         return (java_booleanarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
679 }
680
681 /**************** function: builtin_nmultianewarray ***************************
682
683         Creates a multi-dimensional array on the heap. The dimensions are passed in
684         an array of longs.
685
686     Arguments:
687         n............number of dimensions to create
688         arrayvftbl...vftbl of the array class
689         dims.........array containing the size of each dimension to create
690
691         Return value:  pointer to the array or NULL if no memory is available
692
693 ******************************************************************************/
694
695 java_arrayheader *builtin_nmultianewarray (int n,
696                                                                                    vftbl *arrayvftbl, long *dims)
697 {
698         int size, i;
699         java_arrayheader *a;
700         vftbl *componentvftbl;
701
702         /* create this dimension */
703         size = (int) dims[0];
704         a = builtin_newarray(size,arrayvftbl);
705         if (!a) return NULL;
706
707         /* if this is the last dimension return */
708         if (!--n) return a;
709
710         /* get the vftbl of the components to create */
711         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
712         if (!componentvftbl) /* XXX the verifier could check this */
713                 panic ("multianewarray with too many dimensions");
714
715         /* create the component arrays */
716         for (i = 0; i < size; i++) {
717                 java_arrayheader *ea = 
718                         builtin_nmultianewarray(n,componentvftbl,dims+1);
719                 if (!ea) return NULL;
720                 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
721         }
722
723         return a;
724 }
725
726 /*****************************************************************************
727                                           METHOD LOGGING
728
729         Various functions for printing a message at method entry or exit (for
730         debugging)
731         
732 *****************************************************************************/
733
734
735 u4 methodindent = 0;
736
737 java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
738                                                                                    methodinfo *method, int *pos, 
739                                                                                    int noindent)
740 {
741
742         if (!noindent)
743                 methodindent--;
744         if (verbose || runverbose) {
745                 printf("Exception ");
746                 if (exceptionptr) {
747                         utf_display (exceptionptr->vftbl->class->name);
748                 }
749                 else {
750                         printf("Error: <Nullpointer instead of exception>");
751                         if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
752                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
753                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
754                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
755                         if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
756                         if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
757                         if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
758                         if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
759                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
760                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
761
762                 }
763                 printf(" thrown in ");
764                 if (method) {
765                         utf_display (method->class->name);
766                         printf(".");
767                         utf_display (method->name);
768                         if (method->flags & ACC_SYNCHRONIZED)
769                                 printf("(SYNC)");
770                         else
771                                 printf("(NOSYNC)");
772                         printf("(%p) at position %p\n", method->entrypoint, pos);
773                 }
774                 else
775                         printf("call_java_method\n");
776                 fflush (stdout);
777         }
778         return exceptionptr;
779 }
780
781
782 #ifdef TRACE_ARGS_NUM
783 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
784 #if TRACE_ARGS_NUM > 6
785                                                 s8 a6, s8 a7,
786 #endif
787                                                 methodinfo *method)
788 {
789
790         int i;
791         for (i = 0; i < methodindent; i++)
792                 logtext[i] = '\t';
793         sprintf(logtext + methodindent, "called: ");
794         utf_sprint(logtext + strlen(logtext), method->class->name);
795         sprintf(logtext + strlen(logtext), ".");
796         utf_sprint(logtext + strlen(logtext), method->name);
797         utf_sprint(logtext + strlen(logtext), method->descriptor);
798         sprintf(logtext + strlen(logtext), "(");
799
800         switch (method->paramcount) {
801         case 0:
802                 break;
803
804 #if defined(__I386__)
805         case 1:
806                 sprintf(logtext+strlen(logtext), "%llx", a0);
807                 break;
808
809         case 2:
810                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
811                 break;
812
813         case 3:
814                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
815                 break;
816
817         case 4:
818                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
819                                 a0,   a1,   a2,   a3);
820                 break;
821
822         case 5:
823                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
824                                 a0,   a1,   a2,   a3,   a4);
825                 break;
826
827         case 6:
828                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
829                                 a0,   a1,   a2,   a3,   a4,   a5);
830                 break;
831
832 #if TRACE_ARGS_NUM > 6
833         case 7:
834                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
835                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
836                 break;
837
838         case 8:
839                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
840                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
841                 break;
842
843         default:
844                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
845                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
846                 break;
847 #else
848         default:
849                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
850                                 a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
851                 break;
852 #endif
853 #else
854         case 1:
855                 sprintf(logtext+strlen(logtext), "%lx", a0);
856                 break;
857
858         case 2:
859                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
860                 break;
861
862         case 3:
863                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
864                 break;
865
866         case 4:
867                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
868                                 a0,  a1,  a2,  a3);
869                 break;
870
871         case 5:
872                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
873                                 a0,  a1,  a2,  a3,  a4);
874                 break;
875
876         case 6:
877                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
878                                 a0,  a1,  a2,  a3,  a4,  a5);
879                 break;
880
881 #if TRACE_ARGS_NUM > 6
882         case 7:
883                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
884                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
885                 break;
886
887         case 8:
888                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
889                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
890                 break;
891
892         default:
893                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
894                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
895                 break;
896 #else
897         default:
898                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
899                                 a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
900                 break;
901 #endif
902 #endif
903         }
904         sprintf (logtext+strlen(logtext), ")");
905         dolog ();
906
907         methodindent++;
908 }
909 #endif
910
911
912 void builtin_displaymethodstart(methodinfo *method)
913 {
914         sprintf(logtext, "                                                                                              ");
915         sprintf(logtext + methodindent, "called: ");
916         utf_sprint(logtext + strlen(logtext), method->class->name);
917         sprintf(logtext + strlen(logtext), ".");
918         utf_sprint(logtext + strlen(logtext), method->name);
919         utf_sprint(logtext + strlen(logtext), method->descriptor);
920         dolog();
921         methodindent++;
922 }
923
924
925 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
926 {
927         int i;
928         for (i = 0; i < methodindent; i++)
929                 logtext[i] = '\t';
930         methodindent--;
931         sprintf(logtext + methodindent, "finished: ");
932         utf_sprint(logtext + strlen(logtext), method->class->name);
933         sprintf(logtext + strlen(logtext), ".");
934         utf_sprint(logtext + strlen(logtext), method->name);
935         utf_sprint(logtext + strlen(logtext), method->descriptor);
936
937         switch (method->returntype) {
938         case TYPE_INT:
939                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
940                 break;
941         case TYPE_LONG:
942 #if defined(__I386__)
943                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
944 #else
945                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
946 #endif
947                 break;
948         case TYPE_ADDRESS:
949 #if defined(__I386__)
950                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
951 #else
952                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
953 #endif
954                 break;
955         case TYPE_FLOAT:
956                 sprintf(logtext + strlen(logtext), "->%g", f);
957                 break;
958         case TYPE_DOUBLE:
959                 sprintf(logtext + strlen(logtext), "->%g", d);
960                 break;
961         }
962         dolog();
963 }
964
965
966 void builtin_displaymethodexception(methodinfo *method)
967 {
968         int i;
969         for (i = 0; i < methodindent; i++)
970                 logtext[i] = '\t';
971         sprintf(logtext + methodindent, "exception abort: ");
972         utf_sprint(logtext + strlen(logtext), method->class->name);
973         sprintf(logtext + strlen(logtext), ".");
974         utf_sprint(logtext + strlen(logtext), method->name);
975         utf_sprint(logtext + strlen(logtext), method->descriptor);
976         dolog();
977 }
978
979
980 /****************************************************************************
981                          SYNCHRONIZATION FUNCTIONS
982 *****************************************************************************/
983
984 /*
985  * Lock the mutex of an object.
986  */
987 #ifdef USE_THREADS
988 void
989 internal_lock_mutex_for_object (java_objectheader *object)
990 {
991         mutexHashEntry *entry;
992         int hashValue;
993
994         assert(object != 0);
995
996         hashValue = MUTEX_HASH_VALUE(object);
997         entry = &mutexHashTable[hashValue];
998
999         if (entry->object != 0) {
1000                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1001                         entry->object = 0;
1002                         entry->mutex.holder = 0;
1003                         entry->mutex.count = 0;
1004                         entry->mutex.muxWaiters = 0;
1005
1006                 } else {
1007                         while (entry->next != 0 && entry->object != object)
1008                                 entry = entry->next;
1009
1010                         if (entry->object != object) {
1011                                 entry->next = firstFreeOverflowEntry;
1012                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1013
1014                                 entry = entry->next;
1015                                 entry->object = 0;
1016                                 entry->next = 0;
1017                                 assert(entry->conditionCount == 0);
1018                         }
1019                 }
1020
1021         } else {
1022                 entry->mutex.holder = 0;
1023                 entry->mutex.count = 0;
1024                 entry->mutex.muxWaiters = 0;
1025         }
1026
1027         if (entry->object == 0)
1028                 entry->object = object;
1029         
1030         internal_lock_mutex(&entry->mutex);
1031 }
1032 #endif
1033
1034
1035 /*
1036  * Unlocks the mutex of an object.
1037  */
1038 #ifdef USE_THREADS
1039 void
1040 internal_unlock_mutex_for_object (java_objectheader *object)
1041 {
1042         int hashValue;
1043         mutexHashEntry *entry;
1044
1045         hashValue = MUTEX_HASH_VALUE(object);
1046         entry = &mutexHashTable[hashValue];
1047
1048         if (entry->object == object) {
1049                 internal_unlock_mutex(&entry->mutex);
1050
1051         } else {
1052                 while (entry->next != 0 && entry->next->object != object)
1053                         entry = entry->next;
1054
1055                 assert(entry->next != 0);
1056
1057                 internal_unlock_mutex(&entry->next->mutex);
1058
1059                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1060                         mutexHashEntry *unlinked = entry->next;
1061
1062                         entry->next = unlinked->next;
1063                         unlinked->next = firstFreeOverflowEntry;
1064                         firstFreeOverflowEntry = unlinked;
1065                 }
1066         }
1067 }
1068 #endif
1069
1070
1071 void builtin_monitorenter(java_objectheader *o)
1072 {
1073 #ifdef USE_THREADS
1074         int hashValue;
1075
1076         assert(blockInts == 0);
1077
1078         ++blockInts;
1079
1080         hashValue = MUTEX_HASH_VALUE(o);
1081         if (mutexHashTable[hashValue].object == o 
1082                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1083                 ++mutexHashTable[hashValue].mutex.count;
1084         else
1085                 internal_lock_mutex_for_object(o);
1086
1087         --blockInts;
1088
1089         assert(blockInts == 0);
1090 #endif
1091 }
1092
1093
1094 void builtin_monitorexit (java_objectheader *o)
1095 {
1096 #ifdef USE_THREADS
1097         int hashValue;
1098
1099         assert(blockInts == 0);
1100
1101         ++blockInts;
1102
1103         hashValue = MUTEX_HASH_VALUE(o);
1104         if (mutexHashTable[hashValue].object == o) {
1105                 if (mutexHashTable[hashValue].mutex.count == 1
1106                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1107                         internal_unlock_mutex_for_object(o);
1108                 else
1109                         --mutexHashTable[hashValue].mutex.count;
1110
1111         } else
1112                 internal_unlock_mutex_for_object(o);
1113
1114         --blockInts;
1115
1116         assert(blockInts == 0);
1117 #endif
1118 }
1119
1120
1121 /*****************************************************************************
1122                           MISCELLANEOUS HELPER FUNCTIONS
1123 *****************************************************************************/
1124
1125
1126
1127 /*********** Functions for integer divisions *****************************
1128  
1129         On some systems (eg. DEC ALPHA), integer division is not supported by the
1130         CPU. These helper functions implement the missing functionality.
1131
1132 ******************************************************************************/
1133
1134 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1135 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1136
1137
1138 /************** Functions for long arithmetics *******************************
1139
1140         On systems where 64 bit Integers are not supported by the CPU, these
1141         functions are needed.
1142
1143 ******************************************************************************/
1144
1145
1146 s8 builtin_ladd(s8 a, s8 b)
1147
1148 #if U8_AVAILABLE
1149         return a + b; 
1150 #else
1151         return builtin_i2l(0);
1152 #endif
1153 }
1154
1155 s8 builtin_lsub(s8 a, s8 b) 
1156
1157 #if U8_AVAILABLE
1158         return a - b; 
1159 #else
1160         return builtin_i2l(0);
1161 #endif
1162 }
1163
1164 s8 builtin_lmul(s8 a, s8 b) 
1165
1166 #if U8_AVAILABLE
1167         return a * b; 
1168 #else
1169         return builtin_i2l(0);
1170 #endif
1171 }
1172
1173 s8 builtin_ldiv(s8 a, s8 b) 
1174
1175 #if U8_AVAILABLE
1176         return a / b; 
1177 #else
1178         return builtin_i2l(0);
1179 #endif
1180 }
1181
1182 s8 builtin_lrem(s8 a, s8 b) 
1183
1184 #if U8_AVAILABLE
1185         return a % b; 
1186 #else
1187         return builtin_i2l(0);
1188 #endif
1189 }
1190
1191 s8 builtin_lshl(s8 a, s4 b) 
1192
1193 #if U8_AVAILABLE
1194         return a << (b & 63);
1195 #else
1196         return builtin_i2l(0);
1197 #endif
1198 }
1199
1200 s8 builtin_lshr(s8 a, s4 b) 
1201
1202 #if U8_AVAILABLE
1203         return a >> (b & 63);
1204 #else
1205         return builtin_i2l(0);
1206 #endif
1207 }
1208
1209 s8 builtin_lushr(s8 a, s4 b) 
1210
1211 #if U8_AVAILABLE
1212         return ((u8) a) >> (b & 63);
1213 #else
1214         return builtin_i2l(0);
1215 #endif
1216 }
1217
1218 s8 builtin_land(s8 a, s8 b) 
1219
1220 #if U8_AVAILABLE
1221         return a & b; 
1222 #else
1223         return builtin_i2l(0);
1224 #endif
1225 }
1226
1227 s8 builtin_lor(s8 a, s8 b) 
1228
1229 #if U8_AVAILABLE
1230         return a | b; 
1231 #else
1232         return builtin_i2l(0);
1233 #endif
1234 }
1235
1236 s8 builtin_lxor(s8 a, s8 b) 
1237
1238 #if U8_AVAILABLE
1239         return a ^ b; 
1240 #else
1241         return builtin_i2l(0);
1242 #endif
1243 }
1244
1245 s8 builtin_lneg(s8 a) 
1246
1247 #if U8_AVAILABLE
1248         return -a;
1249 #else
1250         return builtin_i2l(0);
1251 #endif
1252 }
1253
1254 s4 builtin_lcmp(s8 a, s8 b) 
1255
1256 #if U8_AVAILABLE
1257         if (a < b) return -1;
1258         if (a > b) return 1;
1259         return 0;
1260 #else
1261         return 0;
1262 #endif
1263 }
1264
1265
1266
1267
1268
1269 /*********** Functions for floating point operations *************************/
1270
1271 float builtin_fadd(float a, float b)
1272 {
1273         if (isnanf(a)) return FLT_NAN;
1274         if (isnanf(b)) return FLT_NAN;
1275         if (finitef(a)) {
1276                 if (finitef(b))
1277                         return a + b;
1278                 else
1279                         return b;
1280         }
1281         else {
1282                 if (finitef(b))
1283                         return a;
1284                 else {
1285                         if (copysignf(1.0, a) == copysignf(1.0, b))
1286                                 return a;
1287                         else
1288                                 return FLT_NAN;
1289                 }
1290         }
1291 }
1292
1293
1294 float builtin_fsub(float a, float b)
1295 {
1296         return builtin_fadd(a, builtin_fneg(b));
1297 }
1298
1299
1300 float builtin_fmul(float a, float b)
1301 {
1302         if (isnanf(a)) return FLT_NAN;
1303         if (isnanf(b)) return FLT_NAN;
1304         if (finitef(a)) {
1305                 if (finitef(b)) return a*b;
1306                 else {
1307                         if (a == 0) return FLT_NAN;
1308                         else return copysignf(b, copysignf(1.0, b)*a);
1309                 }
1310         }
1311         else {
1312                 if (finitef(b)) {
1313                         if (b == 0) return FLT_NAN;
1314                         else return copysignf(a, copysignf(1.0, a)*b);
1315                 }
1316                 else {
1317                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1318                 }
1319         }
1320 }
1321
1322
1323 float builtin_fdiv(float a, float b)
1324 {
1325         if (finitef(a) && finitef(b)) {
1326                 if (b != 0)
1327                         return a / b;
1328                 else {
1329                         if (a > 0)
1330                                 return FLT_POSINF;
1331                         else if (a < 0)
1332                                 return FLT_NEGINF;
1333                 }
1334         }
1335         return FLT_NAN;
1336 }
1337
1338
1339 float builtin_frem(float a, float b)
1340 {
1341         return fmodf(a, b);
1342 }
1343
1344
1345 float builtin_fneg(float a)
1346 {
1347         if (isnanf(a)) return a;
1348         else {
1349                 if (finitef(a)) return -a;
1350                 else return copysignf(a, -copysignf(1.0, a));
1351         }
1352 }
1353
1354
1355 s4 builtin_fcmpl(float a, float b)
1356 {
1357         if (isnanf(a)) return -1;
1358         if (isnanf(b)) return -1;
1359         if (!finitef(a) || !finitef(b)) {
1360                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1361                 b = finitef(b) ? 0 : copysignf(1.0, b);
1362         }
1363         if (a > b) return 1;
1364         if (a == b) return 0;
1365         return -1;
1366 }
1367
1368
1369 s4 builtin_fcmpg(float a, float b)
1370 {
1371         if (isnanf(a)) return 1;
1372         if (isnanf(b)) return 1;
1373         if (!finitef(a) || !finitef(b)) {
1374                 a = finitef(a) ? 0 : copysignf(1.0, a);
1375                 b = finitef(b) ? 0 : copysignf(1.0, b);
1376         }
1377         if (a > b) return 1;
1378         if (a == b) return 0;
1379         return -1;
1380 }
1381
1382
1383
1384 /************************* Functions for doubles ****************************/
1385
1386 double builtin_dadd(double a, double b)
1387 {
1388         if (isnan(a)) return DBL_NAN;
1389         if (isnan(b)) return DBL_NAN;
1390         if (finite(a)) {
1391                 if (finite(b)) return a+b;
1392                 else return b;
1393         }
1394         else {
1395                 if (finite(b)) return a;
1396                 else {
1397                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1398                         else return DBL_NAN;
1399                 }
1400         }
1401 }
1402
1403
1404 double builtin_dsub(double a, double b)
1405 {
1406         return builtin_dadd(a, builtin_dneg(b));
1407 }
1408
1409
1410 double builtin_dmul(double a, double b)
1411 {
1412         if (isnan(a)) return DBL_NAN;
1413         if (isnan(b)) return DBL_NAN;
1414         if (finite(a)) {
1415                 if (finite(b)) return a * b;
1416                 else {
1417                         if (a == 0) return DBL_NAN;
1418                         else return copysign(b, copysign(1.0, b) * a);
1419                 }
1420         }
1421         else {
1422                 if (finite(b)) {
1423                         if (b == 0) return DBL_NAN;
1424                         else return copysign(a, copysign(1.0, a) * b);
1425                 }
1426                 else {
1427                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1428                 }
1429         }
1430 }
1431
1432
1433 double builtin_ddiv(double a, double b)
1434 {
1435         if (finite(a) && finite(b)) {
1436                 if (b != 0)
1437                         return a / b;
1438                 else {
1439                         if (a > 0)
1440                                 return DBL_POSINF;
1441                         else if (a < 0)
1442                                 return DBL_NEGINF;
1443                 }
1444         }
1445         return DBL_NAN;
1446 }
1447
1448
1449 double builtin_drem(double a, double b)
1450 {
1451         return fmod(a, b);
1452 }
1453
1454
1455 double builtin_dneg(double a)
1456 {
1457         if (isnan(a)) return a;
1458         else {
1459                 if (finite(a)) return -a;
1460                 else return copysign(a, -copysign(1.0, a));
1461         }
1462 }
1463
1464
1465 s4 builtin_dcmpl(double a, double b)
1466 {
1467         if (isnan(a)) return -1;
1468         if (isnan(b)) return -1;
1469         if (!finite(a) || !finite(b)) {
1470                 a = finite(a) ? 0 : copysign(1.0, a);
1471                 b = finite(b) ? 0 : copysign(1.0, b);
1472         }
1473         if (a > b) return 1;
1474         if (a == b) return 0;
1475         return -1;
1476 }
1477
1478
1479 s4 builtin_dcmpg(double a, double b)
1480 {
1481         if (isnan(a)) return 1;
1482         if (isnan(b)) return 1;
1483         if (!finite(a) || !finite(b)) {
1484                 a = finite(a) ? 0 : copysign(1.0, a);
1485                 b = finite(b) ? 0 : copysign(1.0, b);
1486         }
1487         if (a > b) return 1;
1488         if (a == b) return 0;
1489         return -1;
1490 }
1491
1492
1493 /*********************** Conversion operations ****************************/
1494
1495 s8 builtin_i2l(s4 i)
1496 {
1497 #if U8_AVAILABLE
1498         return i;
1499 #else
1500         s8 v; v.high = 0; v.low=i; return v;
1501 #endif
1502 }
1503
1504
1505 float builtin_i2f(s4 a)
1506 {
1507         float f = (float) a;
1508         return f;
1509 }
1510
1511
1512 double builtin_i2d(s4 a)
1513 {
1514         double d = (double) a;
1515         return d;
1516 }
1517
1518
1519 s4 builtin_l2i(s8 l)
1520 {
1521 #if U8_AVAILABLE
1522         return (s4) l;
1523 #else
1524         return l.low;
1525 #endif
1526 }
1527
1528
1529 float builtin_l2f(s8 a)
1530 {
1531 #if U8_AVAILABLE
1532         float f = (float) a;
1533         return f;
1534 #else
1535         return 0.0;
1536 #endif
1537 }
1538
1539
1540 double builtin_l2d(s8 a)
1541 {
1542 #if U8_AVAILABLE
1543         double d = (double) a;
1544         return d;
1545 #else
1546         return 0.0;
1547 #endif
1548 }
1549
1550
1551 s4 builtin_f2i(float a) 
1552 {
1553
1554         return builtin_d2i((double) a);
1555
1556         /*      float f;
1557         
1558                 if (isnanf(a))
1559                 return 0;
1560                 if (finitef(a)) {
1561                 if (a > 2147483647)
1562                 return 2147483647;
1563                 if (a < (-2147483648))
1564                 return (-2147483648);
1565                 return (s4) a;
1566                 }
1567                 f = copysignf((float) 1.0, a);
1568                 if (f > 0)
1569                 return 2147483647;
1570                 return (-2147483648); */
1571 }
1572
1573
1574 s8 builtin_f2l(float a)
1575 {
1576
1577         return builtin_d2l((double) a);
1578
1579         /*      float f;
1580         
1581                 if (finitef(a)) {
1582                 if (a > 9223372036854775807L)
1583                 return 9223372036854775807L;
1584                 if (a < (-9223372036854775808L))
1585                 return (-9223372036854775808L);
1586                 return (s8) a;
1587                 }
1588                 if (isnanf(a))
1589                 return 0;
1590                 f = copysignf((float) 1.0, a);
1591                 if (f > 0)
1592                 return 9223372036854775807L;
1593                 return (-9223372036854775808L); */
1594 }
1595
1596
1597 double builtin_f2d(float a)
1598 {
1599         if (finitef(a)) return (double) a;
1600         else {
1601                 if (isnanf(a))
1602                         return DBL_NAN;
1603                 else
1604                         return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
1605         }
1606 }
1607
1608
1609 s4 builtin_d2i(double a) 
1610
1611         double d;
1612         
1613         if (finite(a)) {
1614                 if (a >= 2147483647)
1615                         return 2147483647;
1616                 if (a <= (-2147483647-1))
1617                         return (-2147483647-1);
1618                 return (s4) a;
1619         }
1620         if (isnan(a))
1621                 return 0;
1622         d = copysign(1.0, a);
1623         if (d > 0)
1624                 return 2147483647;
1625         return (-2147483647-1);
1626 }
1627
1628
1629 s8 builtin_d2l(double a)
1630 {
1631         double d;
1632         
1633         if (finite(a)) {
1634                 if (a >= 9223372036854775807LL)
1635                         return 9223372036854775807LL;
1636                 if (a <= (-9223372036854775807LL-1))
1637                         return (-9223372036854775807LL-1);
1638                 return (s8) a;
1639         }
1640         if (isnan(a))
1641                 return 0;
1642         d = copysign(1.0, a);
1643         if (d > 0)
1644                 return 9223372036854775807LL;
1645         return (-9223372036854775807LL-1);
1646 }
1647
1648
1649 float builtin_d2f(double a)
1650 {
1651         if (finite(a))
1652                 return (float) a;
1653         else {
1654                 if (isnan(a))
1655                         return FLT_NAN;
1656                 else
1657                         return copysignf(FLT_POSINF, (float) copysign(1.0, a));
1658         }
1659 }
1660
1661
1662 java_arrayheader *builtin_clone_array(void *env,java_arrayheader *o) {
1663         return Java_java_lang_VMObject_clone ( 0 ,  0, o);
1664 }
1665
1666
1667 /*
1668  * These are local overrides for various environment variables in Emacs.
1669  * Please do not remove this and leave it at the end of the file, where
1670  * Emacs will automagically detect them.
1671  * ---------------------------------------------------------------------
1672  * Local variables:
1673  * mode: c
1674  * indent-tabs-mode: t
1675  * c-basic-offset: 4
1676  * tab-width: 4
1677  * End:
1678  */