cleaned up macros
[cacao.git] / 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 "sysdep/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
348         o = heap_allocate ( c->alignedsize, true, c->finalizer );
349 #else
350         o = heap_allocate ( c->instancesize, true, c->finalizer );
351 #endif
352         if (!o) return NULL;
353         
354         memset (o, 0, c->instancesize);
355
356         o -> vftbl = c -> vftbl;
357         return o;
358 }
359
360
361
362 /******************** Funktion: builtin_anewarray ****************************
363
364         Legt ein Array von Zeigern auf Objekte am Heap an.
365         Parameter: 
366                 size ......... Anzahl der Elemente
367                 elementtype .. ein Zeiger auf die classinfo-Struktur des Typs
368                                der Elemente
369
370         Return: Zeiger auf das Array, oder NULL (wenn kein Speicher frei)
371
372 *****************************************************************************/
373
374 static
375 void* __builtin_newarray(s4 base_size,
376                                                  s4 size, 
377                                                  bool references,
378                                                  int elementsize,
379                                                  int arraytype)
380 {
381         java_arrayheader *a;
382 #ifdef SIZE_FROM_CLASSINFO
383         s4 alignedsize = align_size(base_size + (size-1) * elementsize);
384
385         a = heap_allocate ( alignedsize, true, NULL );
386 #else   
387         a = heap_allocate ( sizeof(java_objectarray) + (size-1) * elementsize, 
388                             references, 
389                                                 NULL);
390 #endif
391         if (!a) return NULL;
392
393 #if SIZE_FROM_CLASSINFO
394         memset(a, 0, alignedsize);
395 #else
396         memset(a, 0, base_size + (size-1) * elementsize);
397 #endif  
398
399         a -> objheader.vftbl = class_array -> vftbl;
400         a -> size = size;
401 #ifdef SIZE_FROM_CLASSINFO
402         a -> alignedsize = alignedsize;
403 #endif
404         a -> arraytype = arraytype;
405
406         return a;
407 }
408
409
410 java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype)
411 {
412         java_objectarray *a;    
413         a = (java_objectarray*)__builtin_newarray(sizeof(java_objectarray),
414                                                                                           size, 
415                                                                                           true, 
416                                                                                           sizeof(void*), 
417                                                                                           ARRAYTYPE_OBJECT);
418         if (!a) return NULL;
419
420         a -> elementtype = elementtype;
421         return a;
422 }
423
424
425
426 /******************** Funktion: builtin_newarray_array ***********************
427
428         Legt ein Array von Zeigern auf Arrays am Heap an.
429         Paramter: size ......... Anzahl der Elemente
430                   elementdesc .. Zeiger auf die Arraybeschreibungs-Struktur f"ur
431                                  die Element-Arrays.
432
433         Return: Zeiger auf das Array, oder NULL
434
435 *****************************************************************************/
436
437 java_arrayarray *builtin_newarray_array 
438         (s4 size, constant_arraydescriptor *elementdesc)
439 {
440         java_arrayarray *a;     
441         a = (java_arrayarray*)__builtin_newarray(sizeof(java_arrayarray),
442                                                                                          size, 
443                                                                                          true, 
444                                                                                          sizeof(void*), 
445                                                                                          ARRAYTYPE_ARRAY);
446         if (!a) return NULL;
447
448         a -> elementdescriptor = elementdesc;
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         a = (java_booleanarray*)__builtin_newarray(sizeof(java_booleanarray),
466                                                                                            size, 
467                                                                                            false, 
468                                                                                            sizeof(u1), 
469                                                                                            ARRAYTYPE_BOOLEAN);
470         return a;
471 }
472
473 /******************** Funktion: builtin_newarray_char ************************
474
475         Legt ein Array von 16-bit-Integers am Heap an.
476         Return: Zeiger auf das Array, oder NULL 
477
478 *****************************************************************************/
479
480 java_chararray *builtin_newarray_char (s4 size)
481 {
482         java_chararray *a;      
483         a = (java_chararray*)__builtin_newarray(sizeof(java_chararray),
484                                                                                         size, 
485                                                                                         false, 
486                                                                                         sizeof(u2), 
487                                                                                         ARRAYTYPE_CHAR);
488         return a;
489 }
490
491
492 /******************** Funktion: builtin_newarray_float ***********************
493
494         Legt ein Array von 32-bit-IEEE-float am Heap an.
495         Return: Zeiger auf das Array, oder NULL 
496
497 *****************************************************************************/
498
499 java_floatarray *builtin_newarray_float (s4 size)
500 {
501         java_floatarray *a;     
502         a = (java_floatarray*)__builtin_newarray(sizeof(java_floatarray),
503                                                                                          size, 
504                                                                                          false, 
505                                                                                          sizeof(float), 
506                                                                                          ARRAYTYPE_FLOAT);
507         return a;
508 }
509
510
511 /******************** Funktion: builtin_newarray_double ***********************
512
513         Legt ein Array von 64-bit-IEEE-float am Heap an.
514         Return: Zeiger auf das Array, oder NULL 
515
516 *****************************************************************************/
517
518 java_doublearray *builtin_newarray_double (s4 size)
519 {
520         java_doublearray *a;    
521         a = (java_doublearray*)__builtin_newarray(sizeof(java_doublearray),
522                                                                                           size, 
523                                                                                           false, 
524                                                                                           sizeof(double), 
525                                                                                           ARRAYTYPE_DOUBLE);
526         return a;
527 }
528
529
530
531
532 /******************** Funktion: builtin_newarray_byte ***********************
533
534         Legt ein Array von 8-bit-Integers am Heap an.
535         Return: Zeiger auf das Array, oder NULL 
536
537 *****************************************************************************/
538
539 java_bytearray *builtin_newarray_byte (s4 size)
540 {
541         java_bytearray *a;      
542         a = (java_bytearray*)__builtin_newarray(sizeof(java_bytearray),
543                                                                                         size, 
544                                                                                         false, 
545                                                                                         sizeof(u1), 
546                                                                                         ARRAYTYPE_BYTE);
547         return a;
548 }
549
550
551 /******************** Funktion: builtin_newarray_short ***********************
552
553         Legt ein Array von 16-bit-Integers am Heap an.
554         Return: Zeiger auf das Array, oder NULL 
555
556 *****************************************************************************/
557
558 java_shortarray *builtin_newarray_short (s4 size)
559 {
560         java_shortarray *a;     
561         a = (java_shortarray*)__builtin_newarray(sizeof(java_shortarray),
562                                                                                            size, 
563                                                                                            false, 
564                                                                                            sizeof(s2), 
565                                                                                            ARRAYTYPE_SHORT);
566         return a;
567 }
568
569
570 /******************** Funktion: builtin_newarray_int ***********************
571
572         Legt ein Array von 32-bit-Integers am Heap an.
573         Return: Zeiger auf das Array, oder NULL 
574
575 *****************************************************************************/
576
577 java_intarray *builtin_newarray_int (s4 size)
578 {
579         java_intarray *a;       
580         a = (java_intarray*)__builtin_newarray(sizeof(java_intarray),
581                                                                                    size, 
582                                                                                    false, 
583                                                                                    sizeof(s4), 
584                                                                                    ARRAYTYPE_INT);
585         return a;
586 }
587
588
589 /******************** Funktion: builtin_newarray_long ***********************
590
591         Legt ein Array von 64-bit-Integers am Heap an.
592         Return: Zeiger auf das Array, oder NULL 
593
594 *****************************************************************************/
595
596 java_longarray *builtin_newarray_long (s4 size)
597 {
598         java_longarray *a;      
599         a = (java_longarray*)__builtin_newarray(sizeof(java_longarray),
600                                                                                         size, 
601                                                                                         false, 
602                                                                                         sizeof(s8), 
603                                                                                         ARRAYTYPE_LONG);
604         return a;
605 }
606
607
608
609 /***************** Funktion: builtin_multianewarray ***************************
610
611         Legt ein mehrdimensionales Array am Heap an.
612         Die Gr"ossen der einzelnen Dimensionen werden in einem Integerarray
613         "ubergeben. Der Typ es zu erzeugenden Arrays wird als 
614         Referenz auf eine constant_arraydescriptor - Struktur "ubergeben.
615
616         Return: Ein Zeiger auf das Array, oder NULL, wenn kein Speicher mehr
617                 vorhanden ist.
618
619 ******************************************************************************/
620
621         /* Hilfsfunktion */
622
623 static java_arrayheader *multianewarray_part (java_intarray *dims, int thisdim,
624                        constant_arraydescriptor *desc)
625 {
626         u4 size,i;
627         java_arrayarray *a;
628
629         size = dims -> data[thisdim];
630         
631         if (thisdim == (dims->header.size-1)) {
632                 /* letzte Dimension schon erreicht */
633                 
634                 switch (desc -> arraytype) {
635                 case ARRAYTYPE_BOOLEAN:  
636                         return (java_arrayheader*) builtin_newarray_boolean (size); 
637                 case ARRAYTYPE_CHAR:  
638                         return (java_arrayheader*) builtin_newarray_char (size); 
639                 case ARRAYTYPE_FLOAT:  
640                         return (java_arrayheader*) builtin_newarray_float (size); 
641                 case ARRAYTYPE_DOUBLE:  
642                         return (java_arrayheader*) builtin_newarray_double (size); 
643                 case ARRAYTYPE_BYTE:  
644                         return (java_arrayheader*) builtin_newarray_byte (size); 
645                 case ARRAYTYPE_SHORT:  
646                         return (java_arrayheader*) builtin_newarray_short (size); 
647                 case ARRAYTYPE_INT:  
648                         return (java_arrayheader*) builtin_newarray_int (size); 
649                 case ARRAYTYPE_LONG:  
650                         return (java_arrayheader*) builtin_newarray_long (size); 
651                 case ARRAYTYPE_OBJECT:
652                         return (java_arrayheader*) builtin_anewarray (size, desc->objectclass);
653                 
654                 case ARRAYTYPE_ARRAY:
655                         return (java_arrayheader*) builtin_newarray_array (size, desc->elementdescriptor);
656                 
657                 default: panic ("Invalid arraytype in multianewarray");
658                 }
659                 }
660
661         /* wenn letzte Dimension noch nicht erreicht wurde */
662
663         if (desc->arraytype != ARRAYTYPE_ARRAY) 
664                 panic ("multianewarray with too many dimensions");
665
666         a = builtin_newarray_array (size, desc->elementdescriptor);
667         if (!a) return NULL;
668         
669         for (i=0; i<size; i++) {
670                 java_arrayheader *ea = 
671                   multianewarray_part (dims, thisdim+1, desc->elementdescriptor);
672                 if (!ea) return NULL;
673
674                 a -> data[i] = ea;
675                 }
676                 
677         return (java_arrayheader*) a;
678 }
679
680
681 java_arrayheader *builtin_multianewarray (java_intarray *dims,
682                       constant_arraydescriptor *desc)
683 {
684         return multianewarray_part (dims, 0, desc);
685 }
686
687
688 static java_arrayheader *nmultianewarray_part (int n, long *dims, int thisdim,
689                        constant_arraydescriptor *desc)
690 {
691         int size, i;
692         java_arrayarray *a;
693
694         size = (int) dims[thisdim];
695         
696         if (thisdim == (n - 1)) {
697                 /* letzte Dimension schon erreicht */
698                 
699                 switch (desc -> arraytype) {
700                 case ARRAYTYPE_BOOLEAN:  
701                         return (java_arrayheader*) builtin_newarray_boolean(size); 
702                 case ARRAYTYPE_CHAR:  
703                         return (java_arrayheader*) builtin_newarray_char(size); 
704                 case ARRAYTYPE_FLOAT:  
705                         return (java_arrayheader*) builtin_newarray_float(size); 
706                 case ARRAYTYPE_DOUBLE:  
707                         return (java_arrayheader*) builtin_newarray_double(size); 
708                 case ARRAYTYPE_BYTE:  
709                         return (java_arrayheader*) builtin_newarray_byte(size); 
710                 case ARRAYTYPE_SHORT:  
711                         return (java_arrayheader*) builtin_newarray_short(size); 
712                 case ARRAYTYPE_INT:  
713                         return (java_arrayheader*) builtin_newarray_int(size); 
714                 case ARRAYTYPE_LONG:  
715                         return (java_arrayheader*) builtin_newarray_long(size); 
716                 case ARRAYTYPE_OBJECT:
717                         return (java_arrayheader*) builtin_anewarray(size,
718                                                    desc->objectclass);
719                 case ARRAYTYPE_ARRAY:
720                         return (java_arrayheader*) builtin_newarray_array(size,
721                                                    desc->elementdescriptor);
722                 
723                 default: panic ("Invalid arraytype in multianewarray");
724                 }
725                 }
726
727         /* wenn letzte Dimension noch nicht erreicht wurde */
728
729         if (desc->arraytype != ARRAYTYPE_ARRAY) 
730                 panic ("multianewarray with too many dimensions");
731
732         a = builtin_newarray_array(size, desc->elementdescriptor);
733         if (!a) return NULL;
734         
735         for (i = 0; i < size; i++) {
736                 java_arrayheader *ea = 
737                         nmultianewarray_part(n, dims, thisdim + 1, desc->elementdescriptor);
738                 if (!ea) return NULL;
739
740                 a -> data[i] = ea;
741                 }
742                 
743         return (java_arrayheader*) a;
744 }
745
746
747 java_arrayheader *builtin_nmultianewarray (int size,
748                       constant_arraydescriptor *desc, long *dims)
749 {
750         (void) builtin_newarray_int(size); /* for compatibility with -old */
751         return nmultianewarray_part (size, dims, 0, desc);
752 }
753
754
755
756
757 /************************* Funktion: builtin_aastore *************************
758
759         speichert eine Referenz auf ein Objekt in einem Object-Array oder
760         in einem Array-Array.
761         Dabei wird allerdings vorher "uberpr"uft, ob diese Operation 
762         zul"assig ist.
763
764         Return: 1, wenn alles OK ist
765                 0, wenn dieses Objekt nicht in dieses Array gespeichert werden
766                    darf
767
768 *****************************************************************************/
769
770 s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o)
771 {
772         if (builtin_canstore(a,o)) {
773                 a->data[index] = o;
774                 return 1;
775                 }
776         return 0;
777 }
778
779
780
781
782
783
784 /*****************************************************************************
785                       METHODEN-PROTOKOLLIERUNG
786
787         Verschiedene Funktionen, mit denen eine Meldung ausgegeben werden
788         kann, wann immer Methoden aufgerufen oder beendet werden.
789         (f"ur Debug-Zwecke)
790
791 *****************************************************************************/
792
793
794 u4 methodindent=0;
795
796 java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
797                    methodinfo *method, int *pos, int noindent) {
798
799         if (!noindent)
800                 methodindent--;
801         if (verbose || runverbose) {
802                 printf("Exception ");
803                 unicode_display (exceptionptr->vftbl->class->name);
804                 printf(" thrown in ");
805                 if (method) {
806                         unicode_display (method->class->name);
807                         printf(".");
808                         unicode_display (method->name);
809                         if (method->flags & ACC_SYNCHRONIZED)
810                                 printf("(SYNC)");
811                         else
812                                 printf("(NOSYNC)");
813                         printf("(%p) at position %p\n", method->entrypoint, pos);
814                         }
815                 else
816                         printf("call_java_method\n");
817                 fflush (stdout);
818                 }
819         return exceptionptr;
820 }
821
822
823 void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5,
824                         methodinfo *method)
825 {
826         sprintf (logtext, "                                             ");
827         sprintf (logtext+methodindent, "called: ");
828         unicode_sprint (logtext+strlen(logtext), method->class->name);
829         sprintf (logtext+strlen(logtext), ".");
830         unicode_sprint (logtext+strlen(logtext), method->name);
831         unicode_sprint (logtext+strlen(logtext), method->descriptor);
832         sprintf (logtext+strlen(logtext), "(");
833         switch (method->paramcount) {
834                 case 6:
835                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
836                                                    a0,  a1,  a2,  a3,  a4,  a5);
837                         break;
838                 case 5:
839                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
840                                                    a0,  a1,  a2,  a3,  a4);
841                         break;
842                 case 4:
843                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
844                                                    a0,  a1,  a2,  a3);
845                         break;
846                 case 3:
847                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0,  a1,  a2);
848                         break;
849                 case 2:
850                         sprintf(logtext+strlen(logtext), "%lx, %lx", a0,  a1);
851                         break;
852                 case 1:
853                         sprintf(logtext+strlen(logtext), "%lx", a0);
854                         break;
855                 }
856         sprintf (logtext+strlen(logtext), ")");
857
858         dolog ();
859         methodindent++;
860 }
861
862 void builtin_displaymethodstart(methodinfo *method)
863 {
864         sprintf (logtext, "                                             ");
865         sprintf (logtext+methodindent, "called: ");
866         unicode_sprint (logtext+strlen(logtext), method->class->name);
867         sprintf (logtext+strlen(logtext), ".");
868         unicode_sprint (logtext+strlen(logtext), method->name);
869         unicode_sprint (logtext+strlen(logtext), method->descriptor);
870         dolog ();
871         methodindent++;
872 }
873
874 void builtin_displaymethodstop(methodinfo *method, long l, double d)
875 {
876         methodindent--;
877         sprintf (logtext, "                                             ");
878         sprintf (logtext+methodindent, "finished: ");
879         unicode_sprint (logtext+strlen(logtext), method->class->name);
880         sprintf (logtext+strlen(logtext), ".");
881         unicode_sprint (logtext+strlen(logtext), method->name);
882         unicode_sprint (logtext+strlen(logtext), method->descriptor);
883         switch (method->returntype) {
884                 case TYPE_INT:
885                 case TYPE_LONG:
886                         sprintf (logtext+strlen(logtext), "->%ld", l);
887                         break;
888                 case TYPE_FLOAT:
889                 case TYPE_DOUBLE:
890                         sprintf (logtext+strlen(logtext), "->%g", d);
891                         break;
892                 case TYPE_ADDRESS:
893                         sprintf (logtext+strlen(logtext), "->%p", (void*) l);
894                         break;
895                 }
896         dolog ();
897 }
898
899 void builtin_displaymethodexception(methodinfo *method)
900 {
901         sprintf (logtext, "                                             ");
902         sprintf (logtext+methodindent, "exception abort: ");
903         unicode_sprint (logtext+strlen(logtext), method->class->name);
904         sprintf (logtext+strlen(logtext), ".");
905         unicode_sprint (logtext+strlen(logtext), method->name);
906         unicode_sprint (logtext+strlen(logtext), method->descriptor);
907         dolog ();
908 }
909
910
911 /****************************************************************************
912              SYNCHRONIZATION FUNCTIONS
913 *****************************************************************************/
914
915 /*
916  * Lock the mutex of an object.
917  */
918 #ifdef USE_THREADS
919 void
920 internal_lock_mutex_for_object (java_objectheader *object)
921 {
922     mutexHashEntry *entry;
923     int hashValue;
924
925     assert(object != 0);
926
927     hashValue = MUTEX_HASH_VALUE(object);
928     entry = &mutexHashTable[hashValue];
929
930     if (entry->object != 0)
931     {
932                 if (entry->mutex.count == 0 && entry->conditionCount == 0)
933                 {
934                         entry->object = 0;
935                         entry->mutex.holder = 0;
936                         entry->mutex.count = 0;
937                         entry->mutex.muxWaiters = 0;
938                 }
939         else
940         {
941             while (entry->next != 0 && entry->object != object)
942                 entry = entry->next;
943
944             if (entry->object != object)
945             {
946                         entry->next = firstFreeOverflowEntry;
947                         firstFreeOverflowEntry = firstFreeOverflowEntry->next;
948
949                         entry = entry->next;
950                         entry->object = 0;
951                         entry->next = 0;
952                         assert(entry->conditionCount == 0);
953             }
954         }
955     }
956     else
957     {
958                 entry->mutex.holder = 0;
959                 entry->mutex.count = 0;
960                 entry->mutex.muxWaiters = 0;
961     }
962
963     if (entry->object == 0)
964         entry->object = object;
965     
966     internal_lock_mutex(&entry->mutex);
967 }
968 #endif
969
970
971 /*
972  * Unlocks the mutex of an object.
973  */
974 #ifdef USE_THREADS
975 void
976 internal_unlock_mutex_for_object (java_objectheader *object)
977 {
978     int hashValue;
979     mutexHashEntry *entry;
980
981     hashValue = MUTEX_HASH_VALUE(object);
982     entry = &mutexHashTable[hashValue];
983
984     if (entry->object == object)
985                 internal_unlock_mutex(&entry->mutex);
986     else
987     {
988                 while (entry->next != 0 && entry->next->object != object)
989                         entry = entry->next;
990
991                 assert(entry->next != 0);
992
993                 internal_unlock_mutex(&entry->next->mutex);
994
995                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
996                 {
997                         mutexHashEntry *unlinked = entry->next;
998
999                         entry->next = unlinked->next;
1000                         unlinked->next = firstFreeOverflowEntry;
1001                         firstFreeOverflowEntry = unlinked;
1002                 }
1003     }
1004 }
1005 #endif
1006
1007 void
1008 builtin_monitorenter (java_objectheader *o)
1009 {
1010 #ifdef USE_THREADS
1011     int hashValue;
1012
1013         assert(blockInts == 0);
1014
1015     ++blockInts;
1016
1017     hashValue = MUTEX_HASH_VALUE(o);
1018     if (mutexHashTable[hashValue].object == o
1019                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1020                 ++mutexHashTable[hashValue].mutex.count;
1021     else
1022                 internal_lock_mutex_for_object(o);
1023
1024         --blockInts;
1025
1026         assert(blockInts == 0);
1027 #endif
1028 }
1029
1030 void builtin_monitorexit (java_objectheader *o)
1031 {
1032 #ifdef USE_THREADS
1033     int hashValue;
1034
1035         assert(blockInts == 0);
1036
1037     ++blockInts;
1038
1039     hashValue = MUTEX_HASH_VALUE(o);
1040     if (mutexHashTable[hashValue].object == o)
1041     {
1042                 if (mutexHashTable[hashValue].mutex.count == 1
1043                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1044                         internal_unlock_mutex_for_object(o);
1045                 else
1046                         --mutexHashTable[hashValue].mutex.count;
1047     }
1048     else
1049                 internal_unlock_mutex_for_object(o);
1050
1051         --blockInts;
1052
1053         assert(blockInts == 0);
1054 #endif
1055 }
1056
1057
1058 /*****************************************************************************
1059                       DIVERSE HILFSFUNKTIONEN
1060 *****************************************************************************/
1061
1062
1063
1064 /*********** Funktionen f"ur die Integerdivision *****************************
1065  
1066         Auf manchen Systemen (z.B. DEC ALPHA) wird durch die CPU keine Integer-
1067         division unterst"utzt.
1068         Daf"ur gibt es dann diese Hilfsfunktionen
1069
1070 ******************************************************************************/
1071
1072 s4 builtin_idiv (s4 a, s4 b) { return a/b; }
1073 s4 builtin_irem (s4 a, s4 b) { return a%b; }
1074
1075
1076 /************** Funktionen f"ur Long-Arithmetik *******************************
1077
1078         Auf Systemen, auf denen die CPU keine 64-Bit-Integers unterst"utzt,
1079         werden diese Funktionen gebraucht
1080
1081 ******************************************************************************/
1082
1083
1084 s8 builtin_ladd (s8 a, s8 b) 
1085
1086 #if U8_AVAILABLE
1087         return a+b; 
1088 #else
1089         return builtin_i2l(0);
1090 #endif
1091 }
1092
1093 s8 builtin_lsub (s8 a, s8 b) 
1094
1095 #if U8_AVAILABLE
1096         return a-b; 
1097 #else
1098         return builtin_i2l(0);
1099 #endif
1100 }
1101
1102 s8 builtin_lmul (s8 a, s8 b) 
1103
1104 #if U8_AVAILABLE
1105         return a*b; 
1106 #else
1107         return builtin_i2l(0);
1108 #endif
1109 }
1110
1111 s8 builtin_ldiv (s8 a, s8 b) 
1112
1113 #if U8_AVAILABLE
1114         return a/b; 
1115 #else
1116         return builtin_i2l(0);
1117 #endif
1118 }
1119
1120 s8 builtin_lrem (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_lshl (s8 a, s4 b) 
1130
1131 #if U8_AVAILABLE
1132         return a<<(b&63);
1133 #else
1134         return builtin_i2l(0);
1135 #endif
1136 }
1137
1138 s8 builtin_lshr (s8 a, s4 b) 
1139
1140 #if U8_AVAILABLE
1141         return a>>(b&63);
1142 #else
1143         return builtin_i2l(0);
1144 #endif
1145 }
1146
1147 s8 builtin_lushr (s8 a, s4 b) 
1148
1149 #if U8_AVAILABLE
1150         return ((u8)a)>>(b&63);
1151 #else
1152         return builtin_i2l(0);
1153 #endif
1154 }
1155
1156 s8 builtin_land (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_lor (s8 a, s8 b) 
1166
1167 #if U8_AVAILABLE
1168         return a|b; 
1169 #else
1170         return builtin_i2l(0);
1171 #endif
1172 }
1173
1174 s8 builtin_lxor (s8 a, s8 b) 
1175
1176 #if U8_AVAILABLE
1177         return a^b; 
1178 #else
1179         return builtin_i2l(0);
1180 #endif
1181 }
1182
1183 s8 builtin_lneg (s8 a) 
1184
1185 #if U8_AVAILABLE
1186         return -a;
1187 #else
1188         return builtin_i2l(0);
1189 #endif
1190 }
1191
1192 s4 builtin_lcmp (s8 a, s8 b) 
1193
1194 #if U8_AVAILABLE
1195         if (a<b) return -1;
1196         if (a>b) return 1;
1197         return 0;
1198 #else
1199         return 0;
1200 #endif
1201 }
1202
1203
1204
1205
1206
1207 /*********** Funktionen f"ur die Floating-Point-Operationen ******************/
1208
1209 float builtin_fadd (float a, float b)
1210 {
1211         if (isnanf(a)) return FLT_NAN;
1212         if (isnanf(b)) return FLT_NAN;
1213         if (finitef(a)) {
1214                 if (finitef(b)) return a+b;
1215                 else return b;
1216                 }
1217         else {
1218                 if (finitef(b)) return a;
1219                 else {
1220                         if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
1221                         else  return FLT_NAN;
1222                         }
1223                 }
1224 }
1225
1226 float builtin_fsub (float a, float b)
1227 {
1228         return builtin_fadd (a, builtin_fneg(b));
1229 }
1230
1231 float builtin_fmul (float a, float b)
1232 {
1233         if (isnanf(a)) return FLT_NAN;
1234         if (isnanf(b)) return FLT_NAN;
1235         if (finitef(a)) {
1236                 if (finitef(b)) return a*b;
1237                 else {
1238                         if (a==0) return FLT_NAN;
1239                              else return copysignf(b, copysignf(1.0, b)*a);
1240                         }
1241                 }
1242         else {
1243                 if (finitef(b)) {
1244                         if (b==0) return FLT_NAN;
1245                              else return copysignf(a, copysignf(1.0, a)*b);
1246                         }
1247                 else {
1248                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1249                         }
1250                 }
1251 }
1252
1253 float builtin_fdiv (float a, float b)
1254 {
1255         if (finitef(a) && finitef(b)) {
1256                 if (b != 0)
1257                         return a / b;
1258                 else {
1259                         if (a > 0)
1260                                 return FLT_POSINF;
1261                         else if (a < 0)
1262                                 return FLT_NEGINF;
1263                         }
1264                 }
1265         return FLT_NAN;
1266 }
1267
1268 float builtin_frem (float a, float b)
1269 {
1270
1271 /* return (float) builtin_drem((double) a, (double) b); */
1272
1273         float f;
1274
1275         if (finite((double) a) && finite((double) b)) {
1276                 f = a / b;
1277                 if (finite((double) f))
1278                         return fmodf(a, b);
1279                 return FLT_NAN;
1280                 }
1281         if (isnan((double) b))
1282                 return FLT_NAN;
1283         if (finite((double) a))
1284                 return a;
1285         return FLT_NAN;
1286
1287 /*      float f;
1288
1289         if (finitef(a) && finitef(b)) {
1290                 f = a / b;
1291                 if (finitef(f))
1292                         return a - floorf(f) * b;
1293                 return FLT_NAN;
1294                 }
1295         if (isnanf(b))
1296                 return FLT_NAN;
1297         if (finitef(a))
1298                 return a;
1299         return FLT_NAN; */
1300 }
1301
1302
1303 float builtin_fneg (float a)
1304 {
1305         if (isnanf(a)) return a;
1306         else {
1307                 if (finitef(a)) return -a;
1308                            else return copysignf(a,-copysignf(1.0, a));
1309                 }
1310 }
1311
1312 s4 builtin_fcmpl (float a, float b)
1313 {
1314         if (isnanf(a)) return -1;
1315         if (isnanf(b)) return -1;
1316         if (!finitef(a) || !finitef(b)) {
1317                 a = finitef(a) ? 0 : copysignf(1.0,  a);
1318                 b = finitef(b) ? 0 : copysignf(1.0, b);
1319                 }
1320         if (a>b) return 1;
1321         if (a==b) return 0;
1322         return -1;
1323 }
1324
1325 s4 builtin_fcmpg (float a, float b)
1326 {
1327         if (isnanf(a)) return 1;
1328         if (isnanf(b)) return 1;
1329         if (!finitef(a) || !finitef(b)) {
1330                 a = finitef(a) ? 0 : copysignf(1.0, a);
1331                 b = finitef(b) ? 0 : copysignf(1.0, b);
1332                 }
1333         if (a>b) return 1;
1334         if (a==b) return 0;
1335         return -1;
1336 }
1337
1338
1339
1340 /*********** Funktionen f"ur doppelt genaue Fliesskommazahlen ***************/
1341
1342 double builtin_dadd (double a, double b)
1343 {
1344         if (isnan(a)) return DBL_NAN;
1345         if (isnan(b)) return DBL_NAN;
1346         if (finite(a)) {
1347                 if (finite(b)) return a+b;
1348                 else return b;
1349                 }
1350         else {
1351                 if (finite(b)) return a;
1352                 else {
1353                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1354                         else  return DBL_NAN;
1355                         }
1356                 }
1357 }
1358
1359 double builtin_dsub (double a, double b)
1360 {
1361         return builtin_dadd (a, builtin_dneg(b));
1362 }
1363
1364 double builtin_dmul (double a, double b)
1365 {
1366         if (isnan(a)) return DBL_NAN;
1367         if (isnan(b)) return DBL_NAN;
1368         if (finite(a)) {
1369                 if (finite(b)) return a*b;
1370                 else {
1371                         if (a==0) return DBL_NAN;
1372                              else return copysign(b, copysign(1.0, b)*a);
1373                         }
1374                 }
1375         else {
1376                 if (finite(b)) {
1377                         if (b==0) return DBL_NAN;
1378                              else return copysign(a, copysign(1.0, a)*b);
1379                         }
1380                 else {
1381                         return copysign(a, copysign(1.0, a)*copysign(1.0, b));
1382                         }
1383                 }
1384 }
1385
1386 double builtin_ddiv (double a, double b)
1387 {
1388         if (finite(a) && finite(b)) {
1389                 if (b != 0)
1390                         return a / b;
1391                 else {
1392                         if (a > 0)
1393                                 return DBL_POSINF;
1394                         else if (a < 0)
1395                                 return DBL_NEGINF;
1396                         }
1397                 }
1398         return DBL_NAN;
1399 }
1400
1401 double builtin_drem (double a, double b)
1402 {
1403         double d;
1404
1405         if (finite(a) && finite(b)) {
1406                 d = a / b;
1407                 if (finite(d)) {
1408                         if ((d < 1.0) && (d > 0.0))
1409                                 return a;
1410                         return fmod(a, b);
1411                         }
1412                 return DBL_NAN;
1413                 }
1414         if (isnan(b))
1415                 return DBL_NAN;
1416         if (finite(a))
1417                 return a;
1418         return DBL_NAN;
1419 }
1420
1421 double builtin_dneg (double a)
1422 {
1423         if (isnan(a)) return a;
1424         else {
1425                 if (finite(a)) return -a;
1426                           else return copysign(a,-copysign(1.0, a));
1427                 }
1428 }
1429
1430 s4 builtin_dcmpl (double a, double b)
1431 {
1432         if (isnan(a)) return -1;
1433         if (isnan(b)) return -1;
1434         if (!finite(a) || !finite(b)) {
1435                 a = finite(a) ? 0 : copysign(1.0, a);
1436                 b = finite(b) ? 0 : copysign(1.0, b);
1437                 }
1438         if (a>b) return 1;
1439         if (a==b) return 0;
1440         return -1;
1441 }
1442
1443 s4 builtin_dcmpg (double a, double b)
1444 {
1445         if (isnan(a)) return 1;
1446         if (isnan(b)) return 1;
1447         if (!finite(a) || !finite(b)) {
1448                 a = finite(a) ? 0 : copysign(1.0, a);
1449                 b = finite(b) ? 0 : copysign(1.0, b);
1450                 }
1451         if (a>b) return 1;
1452         if (a==b) return 0;
1453         return -1;
1454 }
1455
1456
1457 /*********************** Umwandlungsoperationen ****************************/
1458
1459 s8 builtin_i2l (s4 i)
1460 {
1461 #if U8_AVAILABLE
1462         return i;
1463 #else
1464         s8 v; v.high = 0; v.low=i; return v;
1465 #endif
1466 }
1467
1468 float builtin_i2f (s4 a)
1469 {
1470 float f = (float) a;
1471 return f;
1472 }
1473
1474 double builtin_i2d (s4 a)
1475 {
1476 double d = (double) a;
1477 return d;
1478 }
1479
1480
1481 s4 builtin_l2i (s8 l)
1482 {
1483 #if U8_AVAILABLE
1484         return (s4) l;
1485 #else
1486         return l.low;
1487 #endif
1488 }
1489
1490 float builtin_l2f (s8 a)
1491 {
1492 #if U8_AVAILABLE
1493         float f = (float) a;
1494         return f;
1495 #else
1496         return 0.0;
1497 #endif
1498 }
1499
1500 double builtin_l2d (s8 a)
1501 {
1502 #if U8_AVAILABLE
1503         double d = (double) a;
1504         return d;
1505 #else
1506         return 0.0;
1507 #endif
1508 }
1509
1510
1511 s4 builtin_f2i(float a) 
1512 {
1513
1514 return builtin_d2i((double) a);
1515
1516 /*      float f;
1517         
1518         if (isnanf(a))
1519                 return 0;
1520         if (finitef(a)) {
1521                 if (a > 2147483647)
1522                         return 2147483647;
1523                 if (a < (-2147483648))
1524                         return (-2147483648);
1525                 return (s4) a;
1526                 }
1527         f = copysignf((float) 1.0, a);
1528         if (f > 0)
1529                 return 2147483647;
1530         return (-2147483648); */
1531 }
1532
1533
1534 s8 builtin_f2l (float a)
1535 {
1536
1537 return builtin_d2l((double) a);
1538
1539 /*      float f;
1540         
1541         if (finitef(a)) {
1542                 if (a > 9223372036854775807L)
1543                         return 9223372036854775807L;
1544                 if (a < (-9223372036854775808L))
1545                         return (-9223372036854775808L);
1546                 return (s8) a;
1547                 }
1548         if (isnanf(a))
1549                 return 0;
1550         f = copysignf((float) 1.0, a);
1551         if (f > 0)
1552                 return 9223372036854775807L;
1553         return (-9223372036854775808L); */
1554 }
1555
1556
1557 double builtin_f2d (float a)
1558 {
1559         if (finitef(a)) return (double) a;
1560         else {
1561                 if (isnanf(a)) return DBL_NAN;
1562                 else           return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
1563                 }
1564 }
1565
1566
1567 s4 builtin_d2i (double a) 
1568
1569         double d;
1570         
1571         if (finite(a)) {
1572                 if (a >= 2147483647)
1573                         return 2147483647;
1574                 if (a <= (-2147483648))
1575                         return (-2147483648);
1576                 return (s4) a;
1577                 }
1578         if (isnan(a))
1579                 return 0;
1580         d = copysign(1.0, a);
1581         if (d > 0)
1582                 return 2147483647;
1583         return (-2147483648);
1584 }
1585
1586
1587 s8 builtin_d2l (double a)
1588 {
1589         double d;
1590         
1591         if (finite(a)) {
1592                 if (a >= 9223372036854775807L)
1593                         return 9223372036854775807L;
1594                 if (a <= (-9223372036854775807L-1))
1595                         return (-9223372036854775807L-1);
1596                 return (s8) a;
1597                 }
1598         if (isnan(a))
1599                 return 0;
1600         d = copysign(1.0, a);
1601         if (d > 0)
1602                 return 9223372036854775807L;
1603         return (-9223372036854775807L-1);
1604 }
1605
1606
1607 float builtin_d2f (double a)
1608 {
1609         if (finite(a)) return (float) a;
1610         else {
1611                 if (isnan(a)) return FLT_NAN;
1612                 else          return copysignf (FLT_POSINF, (float) copysign(1.0, a));
1613                 }
1614 }
1615
1616
1617 /*
1618  * These are local overrides for various environment variables in Emacs.
1619  * Please do not remove this and leave it at the end of the file, where
1620  * Emacs will automagically detect them.
1621  * ---------------------------------------------------------------------
1622  * Local variables:
1623  * mode: c
1624  * indent-tabs-mode: t
1625  * c-basic-offset: 4
1626  * tab-width: 4
1627  * End:
1628  */