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