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