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