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