headers.c
[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         Contains C functions for JavaVM Instructions that cannot be translated
8         to machine language directly. Consequently, the generated machine code
9         for these instructions contains function calls instead of machine
10         instructions, using the C calling convention.
11
12         Authors: Reinhard Grafl          EMAIL: cacao@complang.tuwien.ac.at
13                          Andreas  Krall          EMAIL: cacao@complang.tuwien.ac.at
14                          Mark Probst             EMAIL: cacao@complang.tuwien.ac.at
15
16         Last Change: 2003/02/12
17
18 *******************************************************************************/
19
20 #include <assert.h>
21
22 #include "global.h"
23 #include "builtin.h"
24
25 #include "loader.h"
26 #include "tables.h"
27
28 #include "threads/thread.h"
29 #include "threads/locks.h"                              /* schani */
30
31 #include "native-math.h"
32
33 builtin_descriptor builtin_desc[] = {
34         {(functionptr) builtin_instanceof,                 "instanceof"},
35         {(functionptr) builtin_checkcast,                  "checkcast"},
36         {(functionptr) asm_builtin_checkcast,      "checkcast"},
37         {(functionptr) builtin_arrayinstanceof,    "arrayinstanceof"},
38 #if defined(__I386__)
39         {(functionptr) asm_builtin_arrayinstanceof,"arrayinstanceof"},
40 #endif
41         {(functionptr) builtin_checkarraycast,     "checkarraycast"},
42         {(functionptr) asm_builtin_checkarraycast, "checkarraycast"},
43         {(functionptr) asm_builtin_aastore,                "aastore"},
44         {(functionptr) builtin_new,                                "new"},
45         {(functionptr) builtin_anewarray,          "anewarray"},
46         {(functionptr) builtin_newarray_array,     "newarray_array"},
47 #if defined(__I386__)
48         /*
49          * have 2 parameters (needs stack manipulation)
50          */
51         {(functionptr) asm_builtin_anewarray,      "anewarray"},
52         {(functionptr) asm_builtin_newarray_array, "newarray_array"},
53 #endif
54         {(functionptr) builtin_newarray_boolean,   "newarray_boolean"},
55         {(functionptr) builtin_newarray_char,      "newarray_char"},
56         {(functionptr) builtin_newarray_float,     "newarray_float"},
57         {(functionptr) builtin_newarray_double,    "newarray_double"},
58         {(functionptr) builtin_newarray_byte,      "newarray_byte"},
59         {(functionptr) builtin_newarray_short,     "newarray_short"},
60         {(functionptr) builtin_newarray_int,       "newarray_int"},
61         {(functionptr) builtin_newarray_long,      "newarray_long"},
62         {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
63         {(functionptr) builtin_displaymethodstop,  "displaymethodstop"},
64         {(functionptr) builtin_monitorenter,       "monitorenter"},
65         {(functionptr) asm_builtin_monitorenter,   "monitorenter"},
66         {(functionptr) builtin_monitorexit,                "monitorexit"},
67         {(functionptr) asm_builtin_monitorexit,    "monitorexit"},
68 #if !SUPPORT_DIVISION
69         {(functionptr) builtin_idiv,                       "idiv"},
70         {(functionptr) asm_builtin_idiv,                   "idiv"},
71         {(functionptr) builtin_irem,                       "irem"},
72         {(functionptr) asm_builtin_irem,                   "irem"},
73 #endif
74         {(functionptr) builtin_ladd,                       "ladd"},
75         {(functionptr) builtin_lsub,                       "lsub"},
76         {(functionptr) builtin_lmul,                       "lmul"},
77 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV)
78         {(functionptr) builtin_ldiv,                       "ldiv"},
79         {(functionptr) asm_builtin_ldiv,                   "ldiv"},
80         {(functionptr) builtin_lrem,                       "lrem"},
81         {(functionptr) asm_builtin_lrem,                   "lrem"},
82 #endif
83         {(functionptr) builtin_lshl,                       "lshl"},
84         {(functionptr) builtin_lshr,                       "lshr"},
85         {(functionptr) builtin_lushr,                      "lushr"},
86         {(functionptr) builtin_land,                       "land"},
87         {(functionptr) builtin_lor,                                "lor"},
88         {(functionptr) builtin_lxor,                       "lxor"},
89         {(functionptr) builtin_lneg,                       "lneg"},
90         {(functionptr) builtin_lcmp,                       "lcmp"},
91         {(functionptr) builtin_fadd,                       "fadd"},
92         {(functionptr) builtin_fsub,                       "fsub"},
93         {(functionptr) builtin_fmul,                       "fmul"},
94         {(functionptr) builtin_fdiv,                       "fdiv"},
95         {(functionptr) builtin_frem,                       "frem"},
96         {(functionptr) builtin_fneg,                       "fneg"},
97         {(functionptr) builtin_fcmpl,                      "fcmpl"},
98         {(functionptr) builtin_fcmpg,                      "fcmpg"},
99         {(functionptr) builtin_dadd,                       "dadd"},
100         {(functionptr) builtin_dsub,                       "dsub"},
101         {(functionptr) builtin_dmul,                       "dmul"},
102         {(functionptr) builtin_ddiv,                       "ddiv"},
103         {(functionptr) builtin_drem,                       "drem"},
104         {(functionptr) builtin_dneg,                       "dneg"},
105         {(functionptr) builtin_dcmpl,                      "dcmpl"},
106         {(functionptr) builtin_dcmpg,                      "dcmpg"},
107         {(functionptr) builtin_i2l,                                "i2l"},
108         {(functionptr) builtin_i2f,                                "i2f"},
109         {(functionptr) builtin_i2d,                                "i2d"},
110         {(functionptr) builtin_l2i,                                "l2i"},
111         {(functionptr) builtin_l2f,                                "l2f"},
112         {(functionptr) builtin_l2d,                                "l2d"},
113         {(functionptr) builtin_f2i,                                "f2i"},
114         {(functionptr) builtin_f2l,                                "f2l"},
115         {(functionptr) builtin_f2d,                                "f2d"},
116         {(functionptr) builtin_d2i,                                "d2i"},
117         {(functionptr) builtin_d2l,                                "d2l"},
118         {(functionptr) builtin_d2f,                                "d2f"},
119         {(functionptr) NULL,                                       "unknown"}
120         };
121
122
123 /*****************************************************************************
124                                                                 TYPE CHECKS
125 *****************************************************************************/
126
127
128
129 /*************** internal function: builtin_isanysubclass *********************
130
131         Checks a subclass relation between two classes. Implemented interfaces
132         are interpreted as super classes.
133         Return value:  1 ... sub is subclass of super
134                                    0 ... otherwise
135                                         
136 *****************************************************************************/                                  
137
138 s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
139
140         if (super->flags & ACC_INTERFACE)
141                 return (sub->vftbl->interfacetablelength > super->index) &&
142                            (sub->vftbl->interfacetable[-super->index] != NULL);
143
144         /*
145         while (sub != 0)
146                 if (sub == super)
147                         return 1;
148                 else
149                         sub = sub->super;
150
151         return 0;
152         */
153
154         return (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
155                    (unsigned) (super->vftbl->diffval);
156 }
157
158
159 /****************** function: builtin_instanceof *****************************
160
161         Checks if an object is an instance of some given class (or subclass of
162         that class). If class is an interface, checks if the interface is
163         implemented.
164         Return value:  1 ... obj is an instance of class or implements the interface
165                                    0 ... otherwise or if obj == NULL
166                          
167 *****************************************************************************/
168
169 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
170 {
171         #ifdef DEBUG
172         log_text ("builtin_instanceof called");
173         #endif
174         
175         if (!obj) return 0;
176         return builtin_isanysubclass (obj->vftbl->class, class);
177 }
178
179
180
181 /**************** function: builtin_checkcast *******************************
182
183         The same as builtin_instanceof except that 1 is returned when
184         obj == NULL
185                           
186 ****************************************************************************/
187
188 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
189 {
190 #ifdef DEBUG
191         log_text ("builtin_checkcast called");
192 #endif
193
194         if (obj == NULL)
195                 return 1;
196         if (builtin_isanysubclass (obj->vftbl->class, class))
197                 return 1;
198
199 #if DEBUG
200         printf ("#### checkcast failed ");
201         utf_display (obj->vftbl->class->name);
202         printf (" -> ");
203         utf_display (class->name);
204         printf ("\n");
205 #endif
206
207         return 0;
208 }
209
210
211 /*********** internal function: builtin_descriptorscompatible ******************
212
213         Checks if two array type descriptors are assignment compatible
214         Return value:  1 ... target = desc is possible
215                                    0 ... otherwise
216                         
217 ******************************************************************************/
218
219 static s4 builtin_descriptorscompatible(constant_arraydescriptor *desc, constant_arraydescriptor *target)
220 {
221         if (desc==target) return 1;
222         if (desc->arraytype != target->arraytype) return 0;
223         switch (target->arraytype) {
224                 case ARRAYTYPE_OBJECT: 
225                         return builtin_isanysubclass (desc->objectclass, target->objectclass);
226                 case ARRAYTYPE_ARRAY:
227                         return builtin_descriptorscompatible 
228                           (desc->elementdescriptor, target->elementdescriptor);
229                 default: return 1;
230                 }
231 }
232
233
234
235 /******************** function: builtin_checkarraycast ***********************
236
237         Checks if an object is really a subtype of the requested array type.
238         The object has to be an array to begin with. For simple arrays (int, short,
239         double, etc.) the types have to match exactly.
240         For arrays of objects, the type of elements in the array has to be a
241         subtype (or the same type) of the requested element type. For arrays of
242         arrays (which in turn can again be arrays of arrays), the types at the
243         lowest level have to satisfy the corresponding sub class relation.
244         
245         Return value:  1 ... cast is possible
246                                    0 ... otherwise
247         
248         ATTENTION: a cast with a NULL pointer is always possible.
249                         
250 *****************************************************************************/
251
252 s4 builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *desc)
253 {
254         java_arrayheader *a = (java_arrayheader*) o;
255
256         if (!o) return 1;
257         if (o->vftbl->class != class_array) {
258 #ifdef DEBUG
259                 printf ("#### checkarraycast failed 1\n");
260 #endif
261                 return 0;
262                 }
263                 
264         if (a->arraytype != desc->arraytype) {
265 #ifdef DEBUG
266                 printf ("#### checkarraycast failed 2\n");
267 #endif
268                 return 0;
269                 }
270         
271         switch (a->arraytype) {
272                 case ARRAYTYPE_OBJECT: {
273                         java_objectarray *oa = (java_objectarray*) o;
274                         int result = builtin_isanysubclass (oa->elementtype, desc->objectclass);
275
276 #ifdef DEBUG
277                         if (!result)
278                                 printf ("#### checkarraycast failed 3\n");
279 #endif
280                         return result;
281                         }
282                 case ARRAYTYPE_ARRAY: {
283                         java_arrayarray *aa = (java_arrayarray*) o;
284                         int result = builtin_descriptorscompatible
285                                 (aa->elementdescriptor, desc->elementdescriptor);
286
287 #ifdef DEBUG
288                         if (!result)
289                                 printf ("#### checkarraycast failed 4\n");
290 #endif
291                         return result;
292                         }
293                 default:   
294                         return 1;
295                 }
296 }
297
298
299 s4 builtin_arrayinstanceof(java_objectheader *obj, constant_arraydescriptor *desc)
300 {
301         if (!obj) return 1;
302         return builtin_checkarraycast (obj, desc);
303 }
304
305
306 /************************** exception functions *******************************
307
308 ******************************************************************************/
309
310 java_objectheader *builtin_throw_exception (java_objectheader *local_exceptionptr) {
311         if (verbose) {
312                 sprintf(logtext, "Builtin exception thrown: ");
313                 utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
314                 dolog();
315                 }
316         exceptionptr = local_exceptionptr;
317         return local_exceptionptr;
318 }
319
320
321 /******************* function: builtin_canstore *******************************
322
323         Checks, if an object can be stored in an array.
324         Return value:  1 ... possible
325                                    0 ... otherwise
326
327 ******************************************************************************/
328
329
330 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
331 {
332         if (!o) return 1;
333         
334         switch (a->header.arraytype) {
335         case ARRAYTYPE_OBJECT:
336                 if ( ! builtin_checkcast (o, a->elementtype) ) {
337                         return 0;
338                         }
339                 return 1;
340                 break;
341
342         case ARRAYTYPE_ARRAY:
343                 if ( ! builtin_checkarraycast 
344                                  (o, ((java_arrayarray*)a)->elementdescriptor) ) {
345                         return 0;
346                         }
347                 return 1;
348                 break;
349
350         default:
351                 panic ("builtin_canstore called with invalid arraytype");
352                 return 0;
353         }
354 }
355
356
357
358 /*****************************************************************************
359                                                   ARRAY OPERATIONS
360 *****************************************************************************/
361
362
363
364 /******************** Function: builtin_new **********************************
365
366         Creates a new instance of class c on the heap.
367         Return value:  pointer to the object or NULL if no memory is
368                                    available
369                         
370 *****************************************************************************/
371
372 #define ALIGNMENT 3
373 #define align_size(size)        ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
374
375 java_objectheader *builtin_new(classinfo *c)
376 {
377         java_objectheader *o;
378
379         class_init(c);
380
381 #ifdef SIZE_FROM_CLASSINFO
382         c->alignedsize = align_size(c->instancesize);
383         o = heap_allocate(c->alignedsize, true, c->finalizer);
384 #else
385         o = heap_allocate(c->instancesize, true, c->finalizer);
386 #endif
387         if (!o) return NULL;
388         
389         memset(o, 0, c->instancesize);
390
391         o->vftbl = c->vftbl;
392
393         return o;
394 }
395
396
397
398 /******************** function: builtin_anewarray ****************************
399
400         Creates an array of pointers to objects on the heap.
401         Parameters:
402                 size ......... number of elements
403         elementtype .. pointer to the classinfo structure for the element type
404         
405         Return value:  pointer to the array or NULL if no memory is available
406
407 *****************************************************************************/
408
409 void XXX_copy_vftbl(vftbl **dest, vftbl *src)
410 {
411         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
412         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
413         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
414 }
415
416 void XXX_use_class_as_object(classinfo *c, char *cname)
417 {
418         vftbl *vt = class_get(utf_new_char(cname))->vftbl;
419         vftbl *newtbl;
420         if (!c->classvftbl) {
421                 c->classvftbl = true;
422                 XXX_copy_vftbl(&newtbl, vt);
423                 newtbl->class = c->header.vftbl->class;
424                 newtbl->baseval = c->header.vftbl->baseval;
425                 newtbl->diffval = c->header.vftbl->diffval;
426                 c->header.vftbl = newtbl;
427         }
428 }
429
430 static
431 void* __builtin_newarray(s4 base_size,
432                                                  s4 size, 
433                                                  bool references,
434                                                  int elementsize,
435                                                  int arraytype,
436                                                  classinfo *el)
437 {
438         java_arrayheader *a;
439
440 #ifdef SIZE_FROM_CLASSINFO
441         s4 alignedsize = align_size(base_size + (size-1) * elementsize);
442         a = heap_allocate( alignedsize, references, NULL );
443 #else   
444         a = heap_allocate(sizeof(java_objectarray) + (size-1) * elementsize, 
445                                           references, 
446                                           NULL);
447 #endif
448         if (!a) return NULL;
449
450 #ifdef SIZE_FROM_CLASSINFO
451         memset(a, 0, alignedsize);
452 #else
453         memset(a, 0, base_size + (size-1) * elementsize);
454 #endif  
455
456 #if 0
457         {
458         classinfo *c;
459
460         switch (arraytype) {
461         case ARRAYTYPE_INT:
462                 c = create_array_class(utf_new_char("[I"));
463                 XXX_use_class_as_object(c, "int");
464                 break;
465
466         case ARRAYTYPE_LONG:
467                 c = create_array_class(utf_new_char("[J"));
468                 XXX_use_class_as_object(c, "long");
469                 break;
470
471         case ARRAYTYPE_FLOAT:
472                 c = create_array_class(utf_new_char("[F"));
473                 XXX_use_class_as_object(c, "float");
474                 break;
475
476         case ARRAYTYPE_DOUBLE:
477                 c = create_array_class(utf_new_char("[D"));
478                 XXX_use_class_as_object(c, "double");
479                 break;
480
481         case ARRAYTYPE_BYTE:
482                 c = create_array_class(utf_new_char("[B"));
483                 XXX_use_class_as_object(c, "byte");
484                 break;
485
486         case ARRAYTYPE_CHAR:
487                 c = create_array_class(utf_new_char("[C"));
488                 XXX_use_class_as_object(c, "char");
489                 break;
490
491         case ARRAYTYPE_SHORT:
492                 c = create_array_class(utf_new_char("[S"));
493                 XXX_use_class_as_object(c, "short");
494                 break;
495
496         case ARRAYTYPE_BOOLEAN:
497                 c = create_array_class(utf_new_char("[Z"));
498                 XXX_use_class_as_object(c, "boolean");
499                 break;
500
501         case ARRAYTYPE_OBJECT:
502                 {
503                 char *cname, *buf;
504                 cname = heap_allocate(utf_strlen(el->name), false, NULL);
505                 utf_sprint(cname, el->name);
506                 buf = heap_allocate(strlen(cname) + 3, false, NULL);
507 /*  printf("\n\n[L%s;\n\n", cname); */
508                 sprintf(buf, "[L%s;", cname);
509                 c = create_array_class(utf_new_char(buf));
510 /*              MFREE(buf, char, strlen(cname) + 3); */
511 /*              MFREE(cname, char, utf_strlen(el->name)); */
512                 XXX_use_class_as_object(c, cname);
513                 }
514                 break;
515
516         case ARRAYTYPE_ARRAY:
517                 c = create_array_class(utf_new_char("[["));
518                 XXX_use_class_as_object(c, "java/lang/Boolean");
519                 break;
520
521         default:
522                 panic("unknown array type");
523         }
524
525         a->objheader.vftbl = c->vftbl;
526         }
527 #else
528         a->objheader.vftbl = class_array->vftbl;
529 #endif
530         a -> size = size;
531 #ifdef SIZE_FROM_CLASSINFO
532         a -> alignedsize = alignedsize;
533 #endif
534         a -> arraytype = arraytype;
535
536         return a;
537 }
538
539
540 java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype)
541 {
542         java_objectarray *a;    
543         a = (java_objectarray*)__builtin_newarray(sizeof(java_objectarray),
544                                                                                           size, 
545                                                                                           true, 
546                                                                                           sizeof(void*), 
547                                                                                           ARRAYTYPE_OBJECT,
548                                                                                           elementtype);
549         if (!a) return NULL;
550
551         a -> elementtype = elementtype;
552         return a;
553 }
554
555
556
557 /******************** function: builtin_newarray_array ***********************
558
559         Creates an array of pointers to arrays on the heap.
560         Parameters:
561                 size ......... number of elements
562         elementdesc .. pointer to the array description structure for the
563                                    element arrays
564         
565         Return value:  pointer to the array or NULL if no memory is available
566
567 *****************************************************************************/
568
569 java_arrayarray *builtin_newarray_array 
570                 (s4 size, constant_arraydescriptor *elementdesc)
571 {
572         java_arrayarray *a; 
573         a = (java_arrayarray*)__builtin_newarray(sizeof(java_arrayarray),
574                                                                                          size, 
575                                                                                          true, 
576                                                                                          sizeof(void*), 
577                                                                                          ARRAYTYPE_ARRAY,
578                                                                                          elementdesc->objectclass);
579         if (!a) return NULL;
580
581         a -> elementdescriptor = elementdesc;
582         return a;
583 }
584
585
586 /******************** function: builtin_newarray_boolean ************************
587
588         Creates an array of bytes on the heap. The array is designated as an array
589         of booleans (important for casts)
590         
591         Return value:  pointer to the array or NULL if no memory is available
592
593 *****************************************************************************/
594
595 java_booleanarray *builtin_newarray_boolean (s4 size)
596 {
597         java_booleanarray *a;   
598         a = (java_booleanarray*)__builtin_newarray(sizeof(java_booleanarray),
599                                                                                            size, 
600                                                                                            false, 
601                                                                                            sizeof(u1), 
602                                                                                            ARRAYTYPE_BOOLEAN,
603                                                                                            NULL);
604         return a;
605 }
606
607 /******************** function: builtin_newarray_char ************************
608
609         Creates an array of characters on the heap.
610
611         Return value:  pointer to the array or NULL if no memory is available
612
613 *****************************************************************************/
614
615 java_chararray *builtin_newarray_char (s4 size)
616 {
617         java_chararray *a;      
618         a = (java_chararray*)__builtin_newarray(sizeof(java_chararray),
619                                                                                         size, 
620                                                                                         false, 
621                                                                                         sizeof(u2), 
622                                                                                         ARRAYTYPE_CHAR,
623                                                                                         NULL);
624         return a;
625 }
626
627
628 /******************** function: builtin_newarray_float ***********************
629
630         Creates an array of 32 bit IEEE floats on the heap.
631
632         Return value:  pointer to the array or NULL if no memory is available
633
634 *****************************************************************************/
635
636 java_floatarray *builtin_newarray_float (s4 size)
637 {
638         java_floatarray *a; 
639         a = (java_floatarray*)__builtin_newarray(sizeof(java_floatarray),
640                                                                                          size, 
641                                                                                          false, 
642                                                                                          sizeof(float), 
643                                                                                          ARRAYTYPE_FLOAT,
644                                                                                          NULL);
645         return a;
646 }
647
648
649 /******************** function: builtin_newarray_double ***********************
650
651         Creates an array of 64 bit IEEE floats on the heap.
652
653         Return value:  pointer to the array or NULL if no memory is available
654
655 *****************************************************************************/
656
657 java_doublearray *builtin_newarray_double (s4 size)
658 {
659         java_doublearray *a;    
660         a = (java_doublearray*)__builtin_newarray(sizeof(java_doublearray),
661                                                                                           size, 
662                                                                                           false, 
663                                                                                           sizeof(double), 
664                                                                                           ARRAYTYPE_DOUBLE,
665                                                                                           NULL);
666         return a;
667 }
668
669
670
671
672 /******************** function: builtin_newarray_byte ***********************
673
674         Creates an array of 8 bit Integers on the heap.
675
676         Return value:  pointer to the array or NULL if no memory is available
677
678 *****************************************************************************/
679
680 java_bytearray *builtin_newarray_byte (s4 size)
681 {
682         java_bytearray *a;      
683         a = (java_bytearray*)__builtin_newarray(sizeof(java_bytearray),
684                                                                                         size, 
685                                                                                         false, 
686                                                                                         sizeof(u1), 
687                                                                                         ARRAYTYPE_BYTE,
688                                                                                         NULL);
689         return a;
690 }
691
692
693 /******************** function: builtin_newarray_short ***********************
694
695         Creates an array of 16 bit Integers on the heap.
696
697         Return value:  pointer to the array or NULL if no memory is available
698
699 *****************************************************************************/
700
701 java_shortarray *builtin_newarray_short (s4 size)
702 {
703         java_shortarray *a; 
704         a = (java_shortarray*)__builtin_newarray(sizeof(java_shortarray),
705                                                                                          size, 
706                                                                                          false, 
707                                                                                          sizeof(s2), 
708                                                                                          ARRAYTYPE_SHORT,
709                                                                                          NULL);
710         return a;
711 }
712
713
714 /******************** Function: builtin_newarray_int ***********************
715
716         Creates an array of 32 bit Integers on the heap.
717
718         Return value:  pointer to the array or NULL if no memory is available
719
720 *****************************************************************************/
721
722 java_intarray *builtin_newarray_int (s4 size)
723 {
724         java_intarray *a;       
725         a = (java_intarray*)__builtin_newarray(sizeof(java_intarray),
726                                                                                    size, 
727                                                                                    false, 
728                                                                                    sizeof(s4), 
729                                                                                    ARRAYTYPE_INT,
730                                                                                    NULL);
731         return a;
732 }
733
734
735 /******************** Function: builtin_newarray_long ***********************
736
737         Creates an array of 64 bit Integers on the heap.
738
739         Return value:  pointer to the array or NULL if no memory is available
740
741 *****************************************************************************/
742
743 java_longarray *builtin_newarray_long (s4 size)
744 {
745         java_longarray *a;      
746         a = (java_longarray*)__builtin_newarray(sizeof(java_longarray),
747                                                                                         size, 
748                                                                                         false, 
749                                                                                         sizeof(s8), 
750                                                                                         ARRAYTYPE_LONG,
751                                                                                         NULL);
752         return a;
753 }
754
755
756
757 /***************** function: builtin_multianewarray ***************************
758
759         Creates a multi-dimensional array on the heap. The dimensions are passed in
760         an array of Integers. The type for the array is passed as a reference to a
761         constant_arraydescriptor structure.
762
763         Return value:  pointer to the array or NULL if no memory is available
764
765 ******************************************************************************/
766
767         /* Helper functions */
768
769 static java_arrayheader *multianewarray_part (java_intarray *dims, int thisdim,
770                                            constant_arraydescriptor *desc)
771 {
772         u4 size,i;
773         java_arrayarray *a;
774
775         size = dims -> data[thisdim];
776         
777         if (thisdim == (dims->header.size-1)) {
778                 /* last dimension reached */
779                 
780                 switch (desc -> arraytype) {
781                 case ARRAYTYPE_BOOLEAN:  
782                         return (java_arrayheader*) builtin_newarray_boolean (size); 
783                 case ARRAYTYPE_CHAR:  
784                         return (java_arrayheader*) builtin_newarray_char (size); 
785                 case ARRAYTYPE_FLOAT:  
786                         return (java_arrayheader*) builtin_newarray_float (size); 
787                 case ARRAYTYPE_DOUBLE:  
788                         return (java_arrayheader*) builtin_newarray_double (size); 
789                 case ARRAYTYPE_BYTE:  
790                         return (java_arrayheader*) builtin_newarray_byte (size); 
791                 case ARRAYTYPE_SHORT:  
792                         return (java_arrayheader*) builtin_newarray_short (size); 
793                 case ARRAYTYPE_INT:      
794                         return (java_arrayheader*) builtin_newarray_int (size); 
795                 case ARRAYTYPE_LONG:  
796                         return (java_arrayheader*) builtin_newarray_long (size); 
797                 case ARRAYTYPE_OBJECT:
798                         return (java_arrayheader*) builtin_anewarray (size, desc->objectclass);
799                 
800                 case ARRAYTYPE_ARRAY:
801                         return (java_arrayheader*) builtin_newarray_array (size, desc->elementdescriptor);
802                 
803                 default: panic ("Invalid arraytype in multianewarray");
804                 }
805                 }
806
807         /* if the last dimension has not been reached yet */
808
809         if (desc->arraytype != ARRAYTYPE_ARRAY) 
810                 panic ("multianewarray with too many dimensions");
811
812         a = builtin_newarray_array (size, desc->elementdescriptor);
813         if (!a) return NULL;
814         
815         for (i=0; i<size; i++) {
816                 java_arrayheader *ea = 
817                   multianewarray_part (dims, thisdim+1, desc->elementdescriptor);
818                 if (!ea) return NULL;
819
820                 a -> data[i] = ea;
821                 }
822                 
823         return (java_arrayheader*) a;
824 }
825
826
827 java_arrayheader *builtin_multianewarray (java_intarray *dims,
828                                           constant_arraydescriptor *desc)
829 {
830         return multianewarray_part (dims, 0, desc);
831 }
832
833
834 static java_arrayheader *nmultianewarray_part (int n, long *dims, int thisdim,
835                                            constant_arraydescriptor *desc)
836 {
837         int size, i;
838         java_arrayarray *a;
839
840         size = (int) dims[thisdim];
841         
842         if (thisdim == (n - 1)) {
843                 /* last dimension reached */
844                 
845                 switch (desc -> arraytype) {
846                 case ARRAYTYPE_BOOLEAN:  
847                         return (java_arrayheader*) builtin_newarray_boolean(size); 
848                 case ARRAYTYPE_CHAR:  
849                         return (java_arrayheader*) builtin_newarray_char(size); 
850                 case ARRAYTYPE_FLOAT:  
851                         return (java_arrayheader*) builtin_newarray_float(size); 
852                 case ARRAYTYPE_DOUBLE:  
853                         return (java_arrayheader*) builtin_newarray_double(size); 
854                 case ARRAYTYPE_BYTE:  
855                         return (java_arrayheader*) builtin_newarray_byte(size); 
856                 case ARRAYTYPE_SHORT:  
857                         return (java_arrayheader*) builtin_newarray_short(size); 
858                 case ARRAYTYPE_INT:      
859                         return (java_arrayheader*) builtin_newarray_int(size); 
860                 case ARRAYTYPE_LONG:  
861                         return (java_arrayheader*) builtin_newarray_long(size); 
862                 case ARRAYTYPE_OBJECT:
863                         return (java_arrayheader*) builtin_anewarray(size,
864                                                                            desc->objectclass);
865                 case ARRAYTYPE_ARRAY:
866                         return (java_arrayheader*) builtin_newarray_array(size,
867                                                                            desc->elementdescriptor);
868                 
869                 default: panic ("Invalid arraytype in multianewarray");
870                 }
871                 }
872
873         /* if the last dimension has not been reached yet */
874
875         if (desc->arraytype != ARRAYTYPE_ARRAY) 
876                 panic ("multianewarray with too many dimensions");
877
878         a = builtin_newarray_array(size, desc->elementdescriptor);
879         if (!a) return NULL;
880         
881         for (i = 0; i < size; i++) {
882                 java_arrayheader *ea = 
883                         nmultianewarray_part(n, dims, thisdim + 1, desc->elementdescriptor);
884                 if (!ea) return NULL;
885
886                 a -> data[i] = ea;
887                 }
888                 
889         return (java_arrayheader*) a;
890 }
891
892
893 java_arrayheader *builtin_nmultianewarray (int size,
894                                           constant_arraydescriptor *desc, long *dims)
895 {
896         (void) builtin_newarray_int(size); /* for compatibility with -old */
897         return nmultianewarray_part (size, dims, 0, desc);
898 }
899
900
901
902
903 /************************* function: builtin_aastore *************************
904
905         Stores a reference to an object into an object array or into an array
906         array. Before any action is performed, the validity of the operation is
907         checked.
908
909         Return value:  1 ... ok
910                                    0 ... this object cannot be stored into this array
911
912 *****************************************************************************/
913
914 s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o)
915 {
916         if (builtin_canstore(a,o)) {
917                 a->data[index] = o;
918                 return 1;
919                 }
920         return 0;
921 }
922
923
924
925
926
927
928 /*****************************************************************************
929                                           METHOD LOGGING
930
931         Various functions for printing a message at method entry or exit (for
932         debugging)
933         
934 *****************************************************************************/
935
936
937 u4 methodindent=0;
938
939 java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
940                                    methodinfo *method, int *pos, int noindent) {
941
942         if (!noindent)
943                 methodindent--;
944         if (verbose || runverbose) {
945                 printf("Exception ");
946                 utf_display (exceptionptr->vftbl->class->name);
947                 printf(" thrown in ");
948                 if (method) {
949                         utf_display (method->class->name);
950                         printf(".");
951                         utf_display (method->name);
952                         if (method->flags & ACC_SYNCHRONIZED)
953                                 printf("(SYNC)");
954                         else
955                                 printf("(NOSYNC)");
956                         printf("(%p) at position %p\n", method->entrypoint, pos);
957                         }
958                 else
959                         printf("call_java_method\n");
960                 fflush (stdout);
961                 }
962         return exceptionptr;
963 }
964
965
966 #ifdef TRACE_ARGS_NUM
967 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
968 #if TRACE_ARGS_NUM > 6
969                                                 s8 a6, s8 a7,
970 #endif
971                                                 methodinfo *method)
972 {
973         int i;
974         for (i=0; i<methodindent; i++)
975                 logtext[i] = '\t';
976         sprintf (logtext+methodindent, "called: ");
977         utf_sprint (logtext+strlen(logtext), method->class->name);
978         sprintf (logtext+strlen(logtext), ".");
979         utf_sprint (logtext+strlen(logtext), method->name);
980         utf_sprint (logtext+strlen(logtext), method->descriptor);
981         sprintf (logtext+strlen(logtext), "(");
982         switch (method->paramcount) {
983         case 0:
984             break;
985
986                 case 1:
987                         sprintf(logtext+strlen(logtext), "%llx", a0);
988                         break;
989
990                 case 2:
991                         sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
992                         break;
993
994                 case 3:
995                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
996                         break;
997
998                 case 4:
999                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1000                                                                                           a0,   a1,   a2,   a3);
1001                         break;
1002
1003                 case 5:
1004                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1005                                                                                           a0,   a1,   a2,   a3,   a4);
1006                         break;
1007
1008                 case 6:
1009                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1010                                                                                           a0,   a1,   a2,   a3,   a4,   a5);
1011                         break;
1012
1013 #if TRACE_ARGS_NUM > 6
1014                 case 7:
1015                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1016                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   a6);
1017                         break;
1018
1019                 case 8:
1020                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1021                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
1022                         break;
1023
1024                 default:
1025                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1026                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
1027                         break;
1028 #else
1029                 default:
1030                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1031                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
1032                         break;
1033 #endif
1034                 }
1035         sprintf (logtext+strlen(logtext), ")");
1036
1037         dolog ();
1038         methodindent++;
1039 }
1040 #endif
1041
1042 void builtin_displaymethodstart(methodinfo *method)
1043 {
1044         sprintf (logtext, "                                                                                             ");
1045         sprintf (logtext+methodindent, "called: ");
1046         utf_sprint (logtext+strlen(logtext), method->class->name);
1047         sprintf (logtext+strlen(logtext), ".");
1048         utf_sprint (logtext+strlen(logtext), method->name);
1049         utf_sprint (logtext+strlen(logtext), method->descriptor);
1050         dolog ();
1051         methodindent++;
1052 }
1053
1054 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1055 {
1056         int i;
1057         for (i=0; i<methodindent; i++)
1058                 logtext[i] = '\t';
1059         methodindent--;
1060         sprintf (logtext+methodindent, "finished: ");
1061         utf_sprint (logtext+strlen(logtext), method->class->name);
1062         sprintf (logtext+strlen(logtext), ".");
1063         utf_sprint (logtext+strlen(logtext), method->name);
1064         utf_sprint (logtext+strlen(logtext), method->descriptor);
1065         switch (method->returntype) {
1066                 case TYPE_INT:
1067                         sprintf (logtext+strlen(logtext), "->%d", (s4) l);
1068                         break;
1069                 case TYPE_LONG:
1070 #if defined(__I386__)
1071                         sprintf(logtext+strlen(logtext), "->%lld", (s8) l);
1072 #else
1073                         sprintf(logtext+strlen(logtext), "->%ld", (s8) l);
1074 #endif
1075                         break;
1076                 case TYPE_ADDRESS:
1077 #if defined(__I386__)
1078                         sprintf(logtext+strlen(logtext), "->%p", (u1*) ((s4) l));
1079 #else
1080                         sprintf(logtext+strlen(logtext), "->%p", (u1*) l);
1081 #endif
1082                         break;
1083                 case TYPE_FLOAT:
1084                         sprintf (logtext+strlen(logtext), "->%g", f);
1085                         break;
1086                 case TYPE_DOUBLE:
1087                         sprintf (logtext+strlen(logtext), "->%g", d);
1088                         break;
1089                 }
1090         dolog ();
1091 }
1092
1093 void builtin_displaymethodexception(methodinfo *method)
1094 {
1095         int i;
1096         for (i=0; i<methodindent; i++)
1097                 logtext[i] = '\t';
1098         sprintf (logtext+methodindent, "exception abort: ");
1099         utf_sprint (logtext+strlen(logtext), method->class->name);
1100         sprintf (logtext+strlen(logtext), ".");
1101         utf_sprint (logtext+strlen(logtext), method->name);
1102         utf_sprint (logtext+strlen(logtext), method->descriptor);
1103         dolog ();
1104 }
1105
1106
1107 /****************************************************************************
1108                          SYNCHRONIZATION FUNCTIONS
1109 *****************************************************************************/
1110
1111 /*
1112  * Lock the mutex of an object.
1113  */
1114 #ifdef USE_THREADS
1115 void
1116 internal_lock_mutex_for_object (java_objectheader *object)
1117 {
1118         mutexHashEntry *entry;
1119         int hashValue;
1120
1121         assert(object != 0);
1122
1123         hashValue = MUTEX_HASH_VALUE(object);
1124         entry = &mutexHashTable[hashValue];
1125
1126         if (entry->object != 0)
1127         {
1128                 if (entry->mutex.count == 0 && entry->conditionCount == 0)
1129                 {
1130                         entry->object = 0;
1131                         entry->mutex.holder = 0;
1132                         entry->mutex.count = 0;
1133                         entry->mutex.muxWaiters = 0;
1134                 }
1135         else
1136         {
1137                 while (entry->next != 0 && entry->object != object)
1138                 entry = entry->next;
1139
1140                 if (entry->object != object)
1141                 {
1142                         entry->next = firstFreeOverflowEntry;
1143                         firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1144
1145                         entry = entry->next;
1146                         entry->object = 0;
1147                         entry->next = 0;
1148                         assert(entry->conditionCount == 0);
1149                 }
1150         }
1151         }
1152         else
1153         {
1154                 entry->mutex.holder = 0;
1155                 entry->mutex.count = 0;
1156                 entry->mutex.muxWaiters = 0;
1157         }
1158
1159         if (entry->object == 0)
1160                 entry->object = object;
1161         
1162         internal_lock_mutex(&entry->mutex);
1163 }
1164 #endif
1165
1166
1167 /*
1168  * Unlocks the mutex of an object.
1169  */
1170 #ifdef USE_THREADS
1171 void
1172 internal_unlock_mutex_for_object (java_objectheader *object)
1173 {
1174         int hashValue;
1175         mutexHashEntry *entry;
1176
1177         hashValue = MUTEX_HASH_VALUE(object);
1178         entry = &mutexHashTable[hashValue];
1179
1180         if (entry->object == object)
1181                 internal_unlock_mutex(&entry->mutex);
1182         else
1183         {
1184                 while (entry->next != 0 && entry->next->object != object)
1185                         entry = entry->next;
1186
1187                 assert(entry->next != 0);
1188
1189                 internal_unlock_mutex(&entry->next->mutex);
1190
1191                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
1192                 {
1193                         mutexHashEntry *unlinked = entry->next;
1194
1195                         entry->next = unlinked->next;
1196                         unlinked->next = firstFreeOverflowEntry;
1197                         firstFreeOverflowEntry = unlinked;
1198                 }
1199         }
1200 }
1201 #endif
1202
1203 void
1204 builtin_monitorenter (java_objectheader *o)
1205 {
1206 #ifdef USE_THREADS
1207         int hashValue;
1208
1209         assert(blockInts == 0);
1210
1211         ++blockInts;
1212
1213         hashValue = MUTEX_HASH_VALUE(o);
1214         if (mutexHashTable[hashValue].object == o
1215                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1216                 ++mutexHashTable[hashValue].mutex.count;
1217         else
1218                 internal_lock_mutex_for_object(o);
1219
1220         --blockInts;
1221
1222         assert(blockInts == 0);
1223 #endif
1224 }
1225
1226 void builtin_monitorexit (java_objectheader *o)
1227 {
1228 #ifdef USE_THREADS
1229         int hashValue;
1230
1231         assert(blockInts == 0);
1232
1233         ++blockInts;
1234
1235         hashValue = MUTEX_HASH_VALUE(o);
1236         if (mutexHashTable[hashValue].object == o)
1237         {
1238                 if (mutexHashTable[hashValue].mutex.count == 1
1239                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1240                         internal_unlock_mutex_for_object(o);
1241                 else
1242                         --mutexHashTable[hashValue].mutex.count;
1243         }
1244         else
1245                 internal_unlock_mutex_for_object(o);
1246
1247         --blockInts;
1248
1249         assert(blockInts == 0);
1250 #endif
1251 }
1252
1253
1254 /*****************************************************************************
1255                           MISCELLANEOUS HELPER FUNCTIONS
1256 *****************************************************************************/
1257
1258
1259
1260 /*********** Functions for integer divisions *****************************
1261  
1262         On some systems (eg. DEC ALPHA), integer division is not supported by the
1263         CPU. These helper functions implement the missing functionality.
1264
1265 ******************************************************************************/
1266
1267 s4 builtin_idiv (s4 a, s4 b) { return a/b; }
1268 s4 builtin_irem (s4 a, s4 b) { return a%b; }
1269
1270
1271 /************** Functions for long arithmetics *******************************
1272
1273         On systems where 64 bit Integers are not supported by the CPU, these
1274         functions are needed.
1275
1276 ******************************************************************************/
1277
1278
1279 s8 builtin_ladd (s8 a, s8 b) 
1280
1281 #if U8_AVAILABLE
1282         return a+b; 
1283 #else
1284         return builtin_i2l(0);
1285 #endif
1286 }
1287
1288 s8 builtin_lsub (s8 a, s8 b) 
1289
1290 #if U8_AVAILABLE
1291         return a-b; 
1292 #else
1293         return builtin_i2l(0);
1294 #endif
1295 }
1296
1297 s8 builtin_lmul (s8 a, s8 b) 
1298
1299 #if U8_AVAILABLE
1300         return a*b; 
1301 #else
1302         return builtin_i2l(0);
1303 #endif
1304 }
1305
1306 s8 builtin_ldiv (s8 a, s8 b) 
1307
1308 #if U8_AVAILABLE
1309         return a/b; 
1310 #else
1311         return builtin_i2l(0);
1312 #endif
1313 }
1314
1315 s8 builtin_lrem (s8 a, s8 b) 
1316
1317 #if U8_AVAILABLE
1318         return a%b; 
1319 #else
1320         return builtin_i2l(0);
1321 #endif
1322 }
1323
1324 s8 builtin_lshl (s8 a, s4 b) 
1325
1326 #if U8_AVAILABLE
1327         return a<<(b&63);
1328 #else
1329         return builtin_i2l(0);
1330 #endif
1331 }
1332
1333 s8 builtin_lshr (s8 a, s4 b) 
1334
1335 #if U8_AVAILABLE
1336         return a>>(b&63);
1337 #else
1338         return builtin_i2l(0);
1339 #endif
1340 }
1341
1342 s8 builtin_lushr (s8 a, s4 b) 
1343
1344 #if U8_AVAILABLE
1345         return ((u8)a)>>(b&63);
1346 #else
1347         return builtin_i2l(0);
1348 #endif
1349 }
1350
1351 s8 builtin_land (s8 a, s8 b) 
1352
1353 #if U8_AVAILABLE
1354         return a&b; 
1355 #else
1356         return builtin_i2l(0);
1357 #endif
1358 }
1359
1360 s8 builtin_lor (s8 a, s8 b) 
1361
1362 #if U8_AVAILABLE
1363         return a|b; 
1364 #else
1365         return builtin_i2l(0);
1366 #endif
1367 }
1368
1369 s8 builtin_lxor (s8 a, s8 b) 
1370
1371 #if U8_AVAILABLE
1372         return a^b; 
1373 #else
1374         return builtin_i2l(0);
1375 #endif
1376 }
1377
1378 s8 builtin_lneg (s8 a) 
1379
1380 #if U8_AVAILABLE
1381         return -a;
1382 #else
1383         return builtin_i2l(0);
1384 #endif
1385 }
1386
1387 s4 builtin_lcmp (s8 a, s8 b) 
1388
1389 #if U8_AVAILABLE
1390         if (a<b) return -1;
1391         if (a>b) return 1;
1392         return 0;
1393 #else
1394         return 0;
1395 #endif
1396 }
1397
1398
1399
1400
1401
1402 /*********** Functions for floating point operations *************************/
1403
1404 float builtin_fadd (float a, float b)
1405 {
1406         if (isnanf(a)) return FLT_NAN;
1407         if (isnanf(b)) return FLT_NAN;
1408         if (finitef(a)) {
1409                 if (finitef(b)) return a+b;
1410                 else return b;
1411                 }
1412         else {
1413                 if (finitef(b)) return a;
1414                 else {
1415                         if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
1416                         else  return FLT_NAN;
1417                         }
1418                 }
1419 }
1420
1421 float builtin_fsub (float a, float b)
1422 {
1423         return builtin_fadd (a, builtin_fneg(b));
1424 }
1425
1426 float builtin_fmul (float a, float b)
1427 {
1428         if (isnanf(a)) return FLT_NAN;
1429         if (isnanf(b)) return FLT_NAN;
1430         if (finitef(a)) {
1431                 if (finitef(b)) return a*b;
1432                 else {
1433                         if (a==0) return FLT_NAN;
1434                                  else return copysignf(b, copysignf(1.0, b)*a);
1435                         }
1436                 }
1437         else {
1438                 if (finitef(b)) {
1439                         if (b==0) return FLT_NAN;
1440                                  else return copysignf(a, copysignf(1.0, a)*b);
1441                         }
1442                 else {
1443                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1444                         }
1445                 }
1446 }
1447
1448 float builtin_fdiv (float a, float b)
1449 {
1450         if (finitef(a) && finitef(b)) {
1451                 if (b != 0)
1452                         return a / b;
1453                 else {
1454                         if (a > 0)
1455                                 return FLT_POSINF;
1456                         else if (a < 0)
1457                                 return FLT_NEGINF;
1458                         }
1459                 }
1460         return FLT_NAN;
1461 }
1462
1463 float builtin_frem (float a, float b)
1464 {
1465         return fmodf(a, b);
1466 }
1467
1468
1469 float builtin_fneg (float a)
1470 {
1471         if (isnanf(a)) return a;
1472         else {
1473                 if (finitef(a)) return -a;
1474                                    else return copysignf(a,-copysignf(1.0, a));
1475                 }
1476 }
1477
1478 s4 builtin_fcmpl (float a, float b)
1479 {
1480         if (isnanf(a)) return -1;
1481         if (isnanf(b)) return -1;
1482         if (!finitef(a) || !finitef(b)) {
1483                 a = finitef(a) ? 0 : copysignf(1.0,      a);
1484                 b = finitef(b) ? 0 : copysignf(1.0, b);
1485                 }
1486         if (a>b) return 1;
1487         if (a==b) return 0;
1488         return -1;
1489 }
1490
1491 s4 builtin_fcmpg (float a, float b)
1492 {
1493         if (isnanf(a)) return 1;
1494         if (isnanf(b)) return 1;
1495         if (!finitef(a) || !finitef(b)) {
1496                 a = finitef(a) ? 0 : copysignf(1.0, a);
1497                 b = finitef(b) ? 0 : copysignf(1.0, b);
1498                 }
1499         if (a>b) return 1;
1500         if (a==b) return 0;
1501         return -1;
1502 }
1503
1504
1505
1506 /************************* Functions for doubles ****************************/
1507
1508 double builtin_dadd (double a, double b)
1509 {
1510         if (isnan(a)) return DBL_NAN;
1511         if (isnan(b)) return DBL_NAN;
1512         if (finite(a)) {
1513                 if (finite(b)) return a+b;
1514                 else return b;
1515                 }
1516         else {
1517                 if (finite(b)) return a;
1518                 else {
1519                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1520                         else  return DBL_NAN;
1521                         }
1522                 }
1523 }
1524
1525 double builtin_dsub (double a, double b)
1526 {
1527         return builtin_dadd (a, builtin_dneg(b));
1528 }
1529
1530 double builtin_dmul (double a, double b)
1531 {
1532         if (isnan(a)) return DBL_NAN;
1533         if (isnan(b)) return DBL_NAN;
1534         if (finite(a)) {
1535                 if (finite(b)) return a*b;
1536                 else {
1537                         if (a==0) return DBL_NAN;
1538                                  else return copysign(b, copysign(1.0, b)*a);
1539                         }
1540                 }
1541         else {
1542                 if (finite(b)) {
1543                         if (b==0) return DBL_NAN;
1544                                  else return copysign(a, copysign(1.0, a)*b);
1545                         }
1546                 else {
1547                         return copysign(a, copysign(1.0, a)*copysign(1.0, b));
1548                         }
1549                 }
1550 }
1551
1552 double builtin_ddiv (double a, double b)
1553 {
1554         if (finite(a) && finite(b)) {
1555                 if (b != 0)
1556                         return a / b;
1557                 else {
1558                         if (a > 0)
1559                                 return DBL_POSINF;
1560                         else if (a < 0)
1561                                 return DBL_NEGINF;
1562                         }
1563                 }
1564         return DBL_NAN;
1565 }
1566
1567 double builtin_drem (double a, double b)
1568 {
1569         return fmod(a, b);
1570 }
1571
1572 double builtin_dneg (double a)
1573 {
1574         if (isnan(a)) return a;
1575         else {
1576                 if (finite(a)) return -a;
1577                                   else return copysign(a,-copysign(1.0, a));
1578                 }
1579 }
1580
1581 s4 builtin_dcmpl (double a, double b)
1582 {
1583         if (isnan(a)) return -1;
1584         if (isnan(b)) return -1;
1585         if (!finite(a) || !finite(b)) {
1586                 a = finite(a) ? 0 : copysign(1.0, a);
1587                 b = finite(b) ? 0 : copysign(1.0, b);
1588                 }
1589         if (a>b) return 1;
1590         if (a==b) return 0;
1591         return -1;
1592 }
1593
1594 s4 builtin_dcmpg (double a, double b)
1595 {
1596         if (isnan(a)) return 1;
1597         if (isnan(b)) return 1;
1598         if (!finite(a) || !finite(b)) {
1599                 a = finite(a) ? 0 : copysign(1.0, a);
1600                 b = finite(b) ? 0 : copysign(1.0, b);
1601                 }
1602         if (a>b) return 1;
1603         if (a==b) return 0;
1604         return -1;
1605 }
1606
1607
1608 /*********************** Conversion operations ****************************/
1609
1610 s8 builtin_i2l (s4 i)
1611 {
1612 #if U8_AVAILABLE
1613         return i;
1614 #else
1615         s8 v; v.high = 0; v.low=i; return v;
1616 #endif
1617 }
1618
1619 float builtin_i2f (s4 a)
1620 {
1621 float f = (float) a;
1622 return f;
1623 }
1624
1625 double builtin_i2d (s4 a)
1626 {
1627 double d = (double) a;
1628 return d;
1629 }
1630
1631
1632 s4 builtin_l2i (s8 l)
1633 {
1634 #if U8_AVAILABLE
1635         return (s4) l;
1636 #else
1637         return l.low;
1638 #endif
1639 }
1640
1641 float builtin_l2f (s8 a)
1642 {
1643 #if U8_AVAILABLE
1644         float f = (float) a;
1645         return f;
1646 #else
1647         return 0.0;
1648 #endif
1649 }
1650
1651 double builtin_l2d (s8 a)
1652 {
1653 #if U8_AVAILABLE
1654         double d = (double) a;
1655         return d;
1656 #else
1657         return 0.0;
1658 #endif
1659 }
1660
1661
1662 s4 builtin_f2i(float a) 
1663 {
1664
1665 return builtin_d2i((double) a);
1666
1667 /*      float f;
1668         
1669         if (isnanf(a))
1670                 return 0;
1671         if (finitef(a)) {
1672                 if (a > 2147483647)
1673                         return 2147483647;
1674                 if (a < (-2147483648))
1675                         return (-2147483648);
1676                 return (s4) a;
1677                 }
1678         f = copysignf((float) 1.0, a);
1679         if (f > 0)
1680                 return 2147483647;
1681         return (-2147483648); */
1682 }
1683
1684
1685 s8 builtin_f2l (float a)
1686 {
1687
1688 return builtin_d2l((double) a);
1689
1690 /*      float f;
1691         
1692         if (finitef(a)) {
1693                 if (a > 9223372036854775807L)
1694                         return 9223372036854775807L;
1695                 if (a < (-9223372036854775808L))
1696                         return (-9223372036854775808L);
1697                 return (s8) a;
1698                 }
1699         if (isnanf(a))
1700                 return 0;
1701         f = copysignf((float) 1.0, a);
1702         if (f > 0)
1703                 return 9223372036854775807L;
1704         return (-9223372036854775808L); */
1705 }
1706
1707
1708 double builtin_f2d (float a)
1709 {
1710         if (finitef(a)) return (double) a;
1711         else {
1712                 if (isnanf(a)) return DBL_NAN;
1713                 else               return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
1714                 }
1715 }
1716
1717
1718 s4 builtin_d2i (double a) 
1719
1720         double d;
1721         
1722         if (finite(a)) {
1723                 if (a >= 2147483647)
1724                         return 2147483647;
1725                 if (a <= (-2147483647-1))
1726                         return (-2147483647-1);
1727                 return (s4) a;
1728                 }
1729         if (isnan(a))
1730                 return 0;
1731         d = copysign(1.0, a);
1732         if (d > 0)
1733                 return 2147483647;
1734         return (-2147483647-1);
1735 }
1736
1737
1738 s8 builtin_d2l (double a)
1739 {
1740         double d;
1741         
1742         if (finite(a)) {
1743                 if (a >= 9223372036854775807LL)
1744                         return 9223372036854775807LL;
1745                 if (a <= (-9223372036854775807LL-1))
1746                         return (-9223372036854775807LL-1);
1747                 return (s8) a;
1748                 }
1749         if (isnan(a))
1750                 return 0;
1751         d = copysign(1.0, a);
1752         if (d > 0)
1753                 return 9223372036854775807LL;
1754         return (-9223372036854775807LL-1);
1755 }
1756
1757
1758 float builtin_d2f (double a)
1759 {
1760         if (finite(a)) return (float) a;
1761         else {
1762                 if (isnan(a)) return FLT_NAN;
1763                 else              return copysignf (FLT_POSINF, (float) copysign(1.0, a));
1764                 }
1765 }
1766
1767
1768 /*
1769  * These are local overrides for various environment variables in Emacs.
1770  * Please do not remove this and leave it at the end of the file, where
1771  * Emacs will automagically detect them.
1772  * ---------------------------------------------------------------------
1773  * Local variables:
1774  * mode: c
1775  * indent-tabs-mode: t
1776  * c-basic-offset: 4
1777  * tab-width: 4
1778  * End:
1779  */