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