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