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