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