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