*** empty log message ***
[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 #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         {(functionptr) builtin_anewarray,          "anewarray"},
44         {(functionptr) builtin_newarray_array,     "newarray_array"},
45 #ifdef __I386__
46         /*
47          * have 2 parameters (needs stack manipulation)
48          */
49         {(functionptr) asm_builtin_anewarray,      "anewarray"},
50         {(functionptr) asm_builtin_newarray_array, "newarray_array"},
51 #endif
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(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
857 #if TRACE_ARGS_NUM > 6
858                 s8 a6, s8 a7,
859 #endif
860                                                 methodinfo *method)
861 {
862         int i;
863         for (i=0; i<methodindent; i++)
864                 logtext[i] = '\t';
865         sprintf (logtext+methodindent, "called: ");
866         utf_sprint (logtext+strlen(logtext), method->class->name);
867         sprintf (logtext+strlen(logtext), ".");
868         utf_sprint (logtext+strlen(logtext), method->name);
869         utf_sprint (logtext+strlen(logtext), method->descriptor);
870         sprintf (logtext+strlen(logtext), "(");
871         switch (method->paramcount) {
872 #if TRACE_ARGS_NUM > 6
873                 case 8:
874                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
875                                                                                            a0,  a1,      a2,  a3,  a4,  a5, a6, a7);
876                         break;
877                 case 7:
878                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
879                                                                                            a0,  a1,      a2,  a3,  a4,  a5, a6);
880                         break;
881 #endif
882                 case 6:
883                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
884                                                                                            a0,  a1,      a2,  a3,  a4,  a5);
885                         break;
886                 case 5:
887                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
888                                                                                            a0,  a1,      a2,  a3,  a4);
889                         break;
890                 case 4:
891                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
892                                                                                            a0, a1, a2, a3);
893                         break;
894                 case 3:
895                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
896                         break;
897                 case 2:
898                         sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
899                         break;
900                 case 1:
901                         sprintf(logtext+strlen(logtext), "%llx", a0);
902                         break;
903                 }
904         sprintf (logtext+strlen(logtext), ")");
905
906         dolog ();
907         methodindent++;
908 }
909 #endif
910
911 void builtin_displaymethodstart(methodinfo *method)
912 {
913         sprintf (logtext, "                                                                                             ");
914         sprintf (logtext+methodindent, "called: ");
915         utf_sprint (logtext+strlen(logtext), method->class->name);
916         sprintf (logtext+strlen(logtext), ".");
917         utf_sprint (logtext+strlen(logtext), method->name);
918         utf_sprint (logtext+strlen(logtext), method->descriptor);
919         dolog ();
920         methodindent++;
921 }
922
923 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
924 {
925         int i;
926         for (i=0; i<methodindent; i++)
927                 logtext[i] = '\t';
928         methodindent--;
929         sprintf (logtext+methodindent, "finished: ");
930         utf_sprint (logtext+strlen(logtext), method->class->name);
931         sprintf (logtext+strlen(logtext), ".");
932         utf_sprint (logtext+strlen(logtext), method->name);
933         utf_sprint (logtext+strlen(logtext), method->descriptor);
934         switch (method->returntype) {
935                 case TYPE_INT:
936                 case TYPE_LONG:
937                 case TYPE_ADDRESS:
938                         sprintf (logtext+strlen(logtext), "->%ld", l);
939                         break;
940                 case TYPE_FLOAT:
941                         sprintf (logtext+strlen(logtext), "->%g", f);
942                         break;
943                 case TYPE_DOUBLE:
944                         sprintf (logtext+strlen(logtext), "->%g", d);
945                         break;
946                 }
947         dolog ();
948 }
949
950 void builtin_displaymethodexception(methodinfo *method)
951 {
952         int i;
953         for (i=0; i<methodindent; i++)
954                 logtext[i] = '\t';
955         sprintf (logtext+methodindent, "exception abort: ");
956         utf_sprint (logtext+strlen(logtext), method->class->name);
957         sprintf (logtext+strlen(logtext), ".");
958         utf_sprint (logtext+strlen(logtext), method->name);
959         utf_sprint (logtext+strlen(logtext), method->descriptor);
960         dolog ();
961 }
962
963
964 /****************************************************************************
965                          SYNCHRONIZATION FUNCTIONS
966 *****************************************************************************/
967
968 /*
969  * Lock the mutex of an object.
970  */
971 #ifdef USE_THREADS
972 void
973 internal_lock_mutex_for_object (java_objectheader *object)
974 {
975         mutexHashEntry *entry;
976         int hashValue;
977
978         assert(object != 0);
979
980         hashValue = MUTEX_HASH_VALUE(object);
981         entry = &mutexHashTable[hashValue];
982
983         if (entry->object != 0)
984         {
985                 if (entry->mutex.count == 0 && entry->conditionCount == 0)
986                 {
987                         entry->object = 0;
988                         entry->mutex.holder = 0;
989                         entry->mutex.count = 0;
990                         entry->mutex.muxWaiters = 0;
991                 }
992         else
993         {
994                 while (entry->next != 0 && entry->object != object)
995                 entry = entry->next;
996
997                 if (entry->object != object)
998                 {
999                         entry->next = firstFreeOverflowEntry;
1000                         firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1001
1002                         entry = entry->next;
1003                         entry->object = 0;
1004                         entry->next = 0;
1005                         assert(entry->conditionCount == 0);
1006                 }
1007         }
1008         }
1009         else
1010         {
1011                 entry->mutex.holder = 0;
1012                 entry->mutex.count = 0;
1013                 entry->mutex.muxWaiters = 0;
1014         }
1015
1016         if (entry->object == 0)
1017                 entry->object = object;
1018         
1019         internal_lock_mutex(&entry->mutex);
1020 }
1021 #endif
1022
1023
1024 /*
1025  * Unlocks the mutex of an object.
1026  */
1027 #ifdef USE_THREADS
1028 void
1029 internal_unlock_mutex_for_object (java_objectheader *object)
1030 {
1031         int hashValue;
1032         mutexHashEntry *entry;
1033
1034         hashValue = MUTEX_HASH_VALUE(object);
1035         entry = &mutexHashTable[hashValue];
1036
1037         if (entry->object == object)
1038                 internal_unlock_mutex(&entry->mutex);
1039         else
1040         {
1041                 while (entry->next != 0 && entry->next->object != object)
1042                         entry = entry->next;
1043
1044                 assert(entry->next != 0);
1045
1046                 internal_unlock_mutex(&entry->next->mutex);
1047
1048                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
1049                 {
1050                         mutexHashEntry *unlinked = entry->next;
1051
1052                         entry->next = unlinked->next;
1053                         unlinked->next = firstFreeOverflowEntry;
1054                         firstFreeOverflowEntry = unlinked;
1055                 }
1056         }
1057 }
1058 #endif
1059
1060 void
1061 builtin_monitorenter (java_objectheader *o)
1062 {
1063 #ifdef USE_THREADS
1064         int hashValue;
1065
1066         assert(blockInts == 0);
1067
1068         ++blockInts;
1069
1070         hashValue = MUTEX_HASH_VALUE(o);
1071         if (mutexHashTable[hashValue].object == o
1072                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1073                 ++mutexHashTable[hashValue].mutex.count;
1074         else
1075                 internal_lock_mutex_for_object(o);
1076
1077         --blockInts;
1078
1079         assert(blockInts == 0);
1080 #endif
1081 }
1082
1083 void builtin_monitorexit (java_objectheader *o)
1084 {
1085 #ifdef USE_THREADS
1086         int hashValue;
1087
1088         assert(blockInts == 0);
1089
1090         ++blockInts;
1091
1092         hashValue = MUTEX_HASH_VALUE(o);
1093         if (mutexHashTable[hashValue].object == o)
1094         {
1095                 if (mutexHashTable[hashValue].mutex.count == 1
1096                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1097                         internal_unlock_mutex_for_object(o);
1098                 else
1099                         --mutexHashTable[hashValue].mutex.count;
1100         }
1101         else
1102                 internal_unlock_mutex_for_object(o);
1103
1104         --blockInts;
1105
1106         assert(blockInts == 0);
1107 #endif
1108 }
1109
1110
1111 /*****************************************************************************
1112                           MISCELLANEOUS HELPER FUNCTIONS
1113 *****************************************************************************/
1114
1115
1116
1117 /*********** Functions for integer divisions *****************************
1118  
1119         On some systems (eg. DEC ALPHA), integer division is not supported by the
1120         CPU. These helper functions implement the missing functionality.
1121
1122 ******************************************************************************/
1123
1124 s4 builtin_idiv (s4 a, s4 b) { return a/b; }
1125 s4 builtin_irem (s4 a, s4 b) { return a%b; }
1126
1127
1128 /************** Functions for long arithmetics *******************************
1129
1130         On systems where 64 bit Integers are not supported by the CPU, these
1131         functions are needed.
1132
1133 ******************************************************************************/
1134
1135
1136 s8 builtin_ladd (s8 a, s8 b) 
1137
1138 #if U8_AVAILABLE
1139         return a+b; 
1140 #else
1141         return builtin_i2l(0);
1142 #endif
1143 }
1144
1145 s8 builtin_lsub (s8 a, s8 b) 
1146
1147 #if U8_AVAILABLE
1148         return a-b; 
1149 #else
1150         return builtin_i2l(0);
1151 #endif
1152 }
1153
1154 s8 builtin_lmul (s8 a, s8 b) 
1155
1156 #if U8_AVAILABLE
1157         return a*b; 
1158 #else
1159         return builtin_i2l(0);
1160 #endif
1161 }
1162
1163 s8 builtin_ldiv (s8 a, s8 b) 
1164
1165 #if U8_AVAILABLE
1166         return a/b; 
1167 #else
1168         return builtin_i2l(0);
1169 #endif
1170 }
1171
1172 s8 builtin_lrem (s8 a, s8 b) 
1173
1174 #if U8_AVAILABLE
1175         return a%b; 
1176 #else
1177         return builtin_i2l(0);
1178 #endif
1179 }
1180
1181 s8 builtin_lshl (s8 a, s4 b) 
1182
1183 #if U8_AVAILABLE
1184         return a<<(b&63);
1185 #else
1186         return builtin_i2l(0);
1187 #endif
1188 }
1189
1190 s8 builtin_lshr (s8 a, s4 b) 
1191
1192 #if U8_AVAILABLE
1193         return a>>(b&63);
1194 #else
1195         return builtin_i2l(0);
1196 #endif
1197 }
1198
1199 s8 builtin_lushr (s8 a, s4 b) 
1200
1201 #if U8_AVAILABLE
1202         return ((u8)a)>>(b&63);
1203 #else
1204         return builtin_i2l(0);
1205 #endif
1206 }
1207
1208 s8 builtin_land (s8 a, s8 b) 
1209
1210 #if U8_AVAILABLE
1211         return a&b; 
1212 #else
1213         return builtin_i2l(0);
1214 #endif
1215 }
1216
1217 s8 builtin_lor (s8 a, s8 b) 
1218
1219 #if U8_AVAILABLE
1220         return a|b; 
1221 #else
1222         return builtin_i2l(0);
1223 #endif
1224 }
1225
1226 s8 builtin_lxor (s8 a, s8 b) 
1227
1228 #if U8_AVAILABLE
1229         return a^b; 
1230 #else
1231         return builtin_i2l(0);
1232 #endif
1233 }
1234
1235 s8 builtin_lneg (s8 a) 
1236
1237 #if U8_AVAILABLE
1238         return -a;
1239 #else
1240         return builtin_i2l(0);
1241 #endif
1242 }
1243
1244 s4 builtin_lcmp (s8 a, s8 b) 
1245
1246 #if U8_AVAILABLE
1247         if (a<b) return -1;
1248         if (a>b) return 1;
1249         return 0;
1250 #else
1251         return 0;
1252 #endif
1253 }
1254
1255
1256
1257
1258
1259 /*********** Functions for floating point operations *************************/
1260
1261 float builtin_fadd (float a, float b)
1262 {
1263         if (isnanf(a)) return FLT_NAN;
1264         if (isnanf(b)) return FLT_NAN;
1265         if (finitef(a)) {
1266                 if (finitef(b)) return a+b;
1267                 else return b;
1268                 }
1269         else {
1270                 if (finitef(b)) return a;
1271                 else {
1272                         if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
1273                         else  return FLT_NAN;
1274                         }
1275                 }
1276 }
1277
1278 float builtin_fsub (float a, float b)
1279 {
1280         return builtin_fadd (a, builtin_fneg(b));
1281 }
1282
1283 float builtin_fmul (float a, float b)
1284 {
1285         if (isnanf(a)) return FLT_NAN;
1286         if (isnanf(b)) return FLT_NAN;
1287         if (finitef(a)) {
1288                 if (finitef(b)) return a*b;
1289                 else {
1290                         if (a==0) return FLT_NAN;
1291                                  else return copysignf(b, copysignf(1.0, b)*a);
1292                         }
1293                 }
1294         else {
1295                 if (finitef(b)) {
1296                         if (b==0) return FLT_NAN;
1297                                  else return copysignf(a, copysignf(1.0, a)*b);
1298                         }
1299                 else {
1300                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1301                         }
1302                 }
1303 }
1304
1305 float builtin_fdiv (float a, float b)
1306 {
1307         if (finitef(a) && finitef(b)) {
1308                 if (b != 0)
1309                         return a / b;
1310                 else {
1311                         if (a > 0)
1312                                 return FLT_POSINF;
1313                         else if (a < 0)
1314                                 return FLT_NEGINF;
1315                         }
1316                 }
1317         return FLT_NAN;
1318 }
1319
1320 float builtin_frem (float a, float b)
1321 {
1322
1323 /* return (float) builtin_drem((double) a, (double) b); */
1324
1325         float f;
1326
1327         if (finite((double) a) && finite((double) b)) {
1328                 f = a / b;
1329                 if (finite((double) f))
1330                         return fmodf(a, b);
1331                 return FLT_NAN;
1332                 }
1333         if (isnan((double) b))
1334                 return FLT_NAN;
1335         if (finite((double) a))
1336                 return a;
1337         return FLT_NAN;
1338
1339 /*      float f;
1340
1341         if (finitef(a) && finitef(b)) {
1342                 f = a / b;
1343                 if (finitef(f))
1344                         return a - floorf(f) * b;
1345                 return FLT_NAN;
1346                 }
1347         if (isnanf(b))
1348                 return FLT_NAN;
1349         if (finitef(a))
1350                 return a;
1351         return FLT_NAN; */
1352 }
1353
1354
1355 float builtin_fneg (float a)
1356 {
1357         if (isnanf(a)) return a;
1358         else {
1359                 if (finitef(a)) return -a;
1360                                    else return copysignf(a,-copysignf(1.0, a));
1361                 }
1362 }
1363
1364 s4 builtin_fcmpl (float a, float b)
1365 {
1366         if (isnanf(a)) return -1;
1367         if (isnanf(b)) return -1;
1368         if (!finitef(a) || !finitef(b)) {
1369                 a = finitef(a) ? 0 : copysignf(1.0,      a);
1370                 b = finitef(b) ? 0 : copysignf(1.0, b);
1371                 }
1372         if (a>b) return 1;
1373         if (a==b) return 0;
1374         return -1;
1375 }
1376
1377 s4 builtin_fcmpg (float a, float b)
1378 {
1379         if (isnanf(a)) return 1;
1380         if (isnanf(b)) return 1;
1381         if (!finitef(a) || !finitef(b)) {
1382                 a = finitef(a) ? 0 : copysignf(1.0, a);
1383                 b = finitef(b) ? 0 : copysignf(1.0, b);
1384                 }
1385         if (a>b) return 1;
1386         if (a==b) return 0;
1387         return -1;
1388 }
1389
1390
1391
1392 /************************* Functions for doubles ****************************/
1393
1394 double builtin_dadd (double a, double b)
1395 {
1396         if (isnan(a)) return DBL_NAN;
1397         if (isnan(b)) return DBL_NAN;
1398         if (finite(a)) {
1399                 if (finite(b)) return a+b;
1400                 else return b;
1401                 }
1402         else {
1403                 if (finite(b)) return a;
1404                 else {
1405                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1406                         else  return DBL_NAN;
1407                         }
1408                 }
1409 }
1410
1411 double builtin_dsub (double a, double b)
1412 {
1413         return builtin_dadd (a, builtin_dneg(b));
1414 }
1415
1416 double builtin_dmul (double a, double b)
1417 {
1418         if (isnan(a)) return DBL_NAN;
1419         if (isnan(b)) return DBL_NAN;
1420         if (finite(a)) {
1421                 if (finite(b)) return a*b;
1422                 else {
1423                         if (a==0) return DBL_NAN;
1424                                  else return copysign(b, copysign(1.0, b)*a);
1425                         }
1426                 }
1427         else {
1428                 if (finite(b)) {
1429                         if (b==0) return DBL_NAN;
1430                                  else return copysign(a, copysign(1.0, a)*b);
1431                         }
1432                 else {
1433                         return copysign(a, copysign(1.0, a)*copysign(1.0, b));
1434                         }
1435                 }
1436 }
1437
1438 double builtin_ddiv (double a, double b)
1439 {
1440         if (finite(a) && finite(b)) {
1441                 if (b != 0)
1442                         return a / b;
1443                 else {
1444                         if (a > 0)
1445                                 return DBL_POSINF;
1446                         else if (a < 0)
1447                                 return DBL_NEGINF;
1448                         }
1449                 }
1450         return DBL_NAN;
1451 }
1452
1453 double builtin_drem (double a, double b)
1454 {
1455         double d;
1456
1457         if (finite(a) && finite(b)) {
1458                 d = a / b;
1459                 if (finite(d)) {
1460                         if ((d < 1.0) && (d > 0.0))
1461                                 return a;
1462                         return fmod(a, b);
1463                         }
1464                 return DBL_NAN;
1465                 }
1466         if (isnan(b))
1467                 return DBL_NAN;
1468         if (finite(a))
1469                 return a;
1470         return DBL_NAN;
1471 }
1472
1473 double builtin_dneg (double a)
1474 {
1475         if (isnan(a)) return a;
1476         else {
1477                 if (finite(a)) return -a;
1478                                   else return copysign(a,-copysign(1.0, a));
1479                 }
1480 }
1481
1482 s4 builtin_dcmpl (double a, double b)
1483 {
1484         if (isnan(a)) return -1;
1485         if (isnan(b)) return -1;
1486         if (!finite(a) || !finite(b)) {
1487                 a = finite(a) ? 0 : copysign(1.0, a);
1488                 b = finite(b) ? 0 : copysign(1.0, b);
1489                 }
1490         if (a>b) return 1;
1491         if (a==b) return 0;
1492         return -1;
1493 }
1494
1495 s4 builtin_dcmpg (double a, double b)
1496 {
1497         if (isnan(a)) return 1;
1498         if (isnan(b)) return 1;
1499         if (!finite(a) || !finite(b)) {
1500                 a = finite(a) ? 0 : copysign(1.0, a);
1501                 b = finite(b) ? 0 : copysign(1.0, b);
1502                 }
1503         if (a>b) return 1;
1504         if (a==b) return 0;
1505         return -1;
1506 }
1507
1508
1509 /*********************** Conversion operations ****************************/
1510
1511 s8 builtin_i2l (s4 i)
1512 {
1513 #if U8_AVAILABLE
1514         return i;
1515 #else
1516         s8 v; v.high = 0; v.low=i; return v;
1517 #endif
1518 }
1519
1520 float builtin_i2f (s4 a)
1521 {
1522 float f = (float) a;
1523 return f;
1524 }
1525
1526 double builtin_i2d (s4 a)
1527 {
1528 double d = (double) a;
1529 return d;
1530 }
1531
1532
1533 s4 builtin_l2i (s8 l)
1534 {
1535 #if U8_AVAILABLE
1536         return (s4) l;
1537 #else
1538         return l.low;
1539 #endif
1540 }
1541
1542 float builtin_l2f (s8 a)
1543 {
1544 #if U8_AVAILABLE
1545         float f = (float) a;
1546         return f;
1547 #else
1548         return 0.0;
1549 #endif
1550 }
1551
1552 double builtin_l2d (s8 a)
1553 {
1554 #if U8_AVAILABLE
1555         double d = (double) a;
1556         return d;
1557 #else
1558         return 0.0;
1559 #endif
1560 }
1561
1562
1563 s4 builtin_f2i(float a) 
1564 {
1565
1566 return builtin_d2i((double) a);
1567
1568 /*      float f;
1569         
1570         if (isnanf(a))
1571                 return 0;
1572         if (finitef(a)) {
1573                 if (a > 2147483647)
1574                         return 2147483647;
1575                 if (a < (-2147483648))
1576                         return (-2147483648);
1577                 return (s4) a;
1578                 }
1579         f = copysignf((float) 1.0, a);
1580         if (f > 0)
1581                 return 2147483647;
1582         return (-2147483648); */
1583 }
1584
1585
1586 s8 builtin_f2l (float a)
1587 {
1588
1589 return builtin_d2l((double) a);
1590
1591 /*      float f;
1592         
1593         if (finitef(a)) {
1594                 if (a > 9223372036854775807L)
1595                         return 9223372036854775807L;
1596                 if (a < (-9223372036854775808L))
1597                         return (-9223372036854775808L);
1598                 return (s8) a;
1599                 }
1600         if (isnanf(a))
1601                 return 0;
1602         f = copysignf((float) 1.0, a);
1603         if (f > 0)
1604                 return 9223372036854775807L;
1605         return (-9223372036854775808L); */
1606 }
1607
1608
1609 double builtin_f2d (float a)
1610 {
1611         if (finitef(a)) return (double) a;
1612         else {
1613                 if (isnanf(a)) return DBL_NAN;
1614                 else               return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
1615                 }
1616 }
1617
1618
1619 s4 builtin_d2i (double a) 
1620
1621         double d;
1622         
1623         if (finite(a)) {
1624                 if (a >= 2147483647)
1625                         return 2147483647;
1626                 if (a <= (-2147483648))
1627                         return (-2147483648);
1628                 return (s4) a;
1629                 }
1630         if (isnan(a))
1631                 return 0;
1632         d = copysign(1.0, a);
1633         if (d > 0)
1634                 return 2147483647;
1635         return (-2147483648);
1636 }
1637
1638
1639 s8 builtin_d2l (double a)
1640 {
1641         double d;
1642         
1643         if (finite(a)) {
1644                 if (a >= 9223372036854775807L)
1645                         return 9223372036854775807L;
1646                 if (a <= (-9223372036854775807L-1))
1647                         return (-9223372036854775807L-1);
1648                 return (s8) a;
1649                 }
1650         if (isnan(a))
1651                 return 0;
1652         d = copysign(1.0, a);
1653         if (d > 0)
1654                 return 9223372036854775807L;
1655         return (-9223372036854775807L-1);
1656 }
1657
1658
1659 float builtin_d2f (double a)
1660 {
1661         if (finite(a)) return (float) a;
1662         else {
1663                 if (isnan(a)) return FLT_NAN;
1664                 else              return copysignf (FLT_POSINF, (float) copysign(1.0, a));
1665                 }
1666 }
1667
1668
1669 /*
1670  * These are local overrides for various environment variables in Emacs.
1671  * Please do not remove this and leave it at the end of the file, where
1672  * Emacs will automagically detect them.
1673  * ---------------------------------------------------------------------
1674  * Local variables:
1675  * mode: c
1676  * indent-tabs-mode: t
1677  * c-basic-offset: 4
1678  * tab-width: 4
1679  * End:
1680  */