asm_switchstackandcall now defined in asmpart.h
[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         {(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 #if defined(__I386__)
987                 case 1:
988                         sprintf(logtext+strlen(logtext), "%llx", a0);
989                         break;
990
991                 case 2:
992                         sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
993                         break;
994
995                 case 3:
996                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
997                         break;
998
999                 case 4:
1000                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1001                                                                                           a0,   a1,   a2,   a3);
1002                         break;
1003
1004                 case 5:
1005                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1006                                                                                           a0,   a1,   a2,   a3,   a4);
1007                         break;
1008
1009                 case 6:
1010                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1011                                                                                           a0,   a1,   a2,   a3,   a4,   a5);
1012                         break;
1013
1014 #if TRACE_ARGS_NUM > 6
1015                 case 7:
1016                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1017                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   a6);
1018                         break;
1019
1020                 case 8:
1021                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1022                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
1023                         break;
1024
1025                 default:
1026                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1027                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
1028                         break;
1029 #else
1030                 default:
1031                         sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1032                                                                                           a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
1033                         break;
1034 #endif
1035 #else
1036                 case 1:
1037                         sprintf(logtext+strlen(logtext), "%lx", a0);
1038                         break;
1039
1040                 case 2:
1041                         sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1042                         break;
1043
1044                 case 3:
1045                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1046                         break;
1047
1048                 case 4:
1049                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1050                                                                                           a0,  a1,  a2,  a3);
1051                         break;
1052
1053                 case 5:
1054                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1055                                                                                           a0,  a1,  a2,  a3,  a4);
1056                         break;
1057
1058                 case 6:
1059                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1060                                                                                           a0,  a1,  a2,  a3,  a4,  a5);
1061                         break;
1062
1063 #if TRACE_ARGS_NUM > 6
1064                 case 7:
1065                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1066                                                                                           a0,  a1,  a2,  a3,  a4,  a5,  a6);
1067                         break;
1068
1069                 case 8:
1070                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1071                                                                                           a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
1072                         break;
1073
1074                 default:
1075                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1076                                                                                           a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
1077                         break;
1078 #else
1079                 default:
1080                         sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1081                                                                                           a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
1082                         break;
1083 #endif
1084 #endif
1085                 }
1086         sprintf (logtext+strlen(logtext), ")");
1087
1088         dolog ();
1089         methodindent++;
1090 }
1091 #endif
1092
1093 void builtin_displaymethodstart(methodinfo *method)
1094 {
1095         sprintf (logtext, "                                                                                             ");
1096         sprintf (logtext+methodindent, "called: ");
1097         utf_sprint (logtext+strlen(logtext), method->class->name);
1098         sprintf (logtext+strlen(logtext), ".");
1099         utf_sprint (logtext+strlen(logtext), method->name);
1100         utf_sprint (logtext+strlen(logtext), method->descriptor);
1101         dolog ();
1102         methodindent++;
1103 }
1104
1105 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1106 {
1107         int i;
1108         for (i=0; i<methodindent; i++)
1109                 logtext[i] = '\t';
1110         methodindent--;
1111         sprintf (logtext+methodindent, "finished: ");
1112         utf_sprint (logtext+strlen(logtext), method->class->name);
1113         sprintf (logtext+strlen(logtext), ".");
1114         utf_sprint (logtext+strlen(logtext), method->name);
1115         utf_sprint (logtext+strlen(logtext), method->descriptor);
1116         switch (method->returntype) {
1117                 case TYPE_INT:
1118                         sprintf (logtext+strlen(logtext), "->%d", (s4) l);
1119                         break;
1120                 case TYPE_LONG:
1121 #if defined(__I386__)
1122                         sprintf(logtext+strlen(logtext), "->%lld", (s8) l);
1123 #else
1124                         sprintf(logtext+strlen(logtext), "->%ld", (s8) l);
1125 #endif
1126                         break;
1127                 case TYPE_ADDRESS:
1128 #if defined(__I386__)
1129                         sprintf(logtext+strlen(logtext), "->%p", (u1*) ((s4) l));
1130 #else
1131                         sprintf(logtext+strlen(logtext), "->%p", (u1*) l);
1132 #endif
1133                         break;
1134                 case TYPE_FLOAT:
1135                         sprintf (logtext+strlen(logtext), "->%g", f);
1136                         break;
1137                 case TYPE_DOUBLE:
1138                         sprintf (logtext+strlen(logtext), "->%g", d);
1139                         break;
1140                 }
1141         dolog ();
1142 }
1143
1144 void builtin_displaymethodexception(methodinfo *method)
1145 {
1146         int i;
1147         for (i=0; i<methodindent; i++)
1148                 logtext[i] = '\t';
1149         sprintf (logtext+methodindent, "exception abort: ");
1150         utf_sprint (logtext+strlen(logtext), method->class->name);
1151         sprintf (logtext+strlen(logtext), ".");
1152         utf_sprint (logtext+strlen(logtext), method->name);
1153         utf_sprint (logtext+strlen(logtext), method->descriptor);
1154         dolog ();
1155 }
1156
1157
1158 /****************************************************************************
1159                          SYNCHRONIZATION FUNCTIONS
1160 *****************************************************************************/
1161
1162 /*
1163  * Lock the mutex of an object.
1164  */
1165 #ifdef USE_THREADS
1166 void
1167 internal_lock_mutex_for_object (java_objectheader *object)
1168 {
1169         mutexHashEntry *entry;
1170         int hashValue;
1171
1172         assert(object != 0);
1173
1174         hashValue = MUTEX_HASH_VALUE(object);
1175         entry = &mutexHashTable[hashValue];
1176
1177         if (entry->object != 0)
1178         {
1179                 if (entry->mutex.count == 0 && entry->conditionCount == 0)
1180                 {
1181                         entry->object = 0;
1182                         entry->mutex.holder = 0;
1183                         entry->mutex.count = 0;
1184                         entry->mutex.muxWaiters = 0;
1185                 }
1186         else
1187         {
1188                 while (entry->next != 0 && entry->object != object)
1189                 entry = entry->next;
1190
1191                 if (entry->object != object)
1192                 {
1193                         entry->next = firstFreeOverflowEntry;
1194                         firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1195
1196                         entry = entry->next;
1197                         entry->object = 0;
1198                         entry->next = 0;
1199                         assert(entry->conditionCount == 0);
1200                 }
1201         }
1202         }
1203         else
1204         {
1205                 entry->mutex.holder = 0;
1206                 entry->mutex.count = 0;
1207                 entry->mutex.muxWaiters = 0;
1208         }
1209
1210         if (entry->object == 0)
1211                 entry->object = object;
1212         
1213         internal_lock_mutex(&entry->mutex);
1214 }
1215 #endif
1216
1217
1218 /*
1219  * Unlocks the mutex of an object.
1220  */
1221 #ifdef USE_THREADS
1222 void
1223 internal_unlock_mutex_for_object (java_objectheader *object)
1224 {
1225         int hashValue;
1226         mutexHashEntry *entry;
1227
1228         hashValue = MUTEX_HASH_VALUE(object);
1229         entry = &mutexHashTable[hashValue];
1230
1231         if (entry->object == object)
1232                 internal_unlock_mutex(&entry->mutex);
1233         else
1234         {
1235                 while (entry->next != 0 && entry->next->object != object)
1236                         entry = entry->next;
1237
1238                 assert(entry->next != 0);
1239
1240                 internal_unlock_mutex(&entry->next->mutex);
1241
1242                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
1243                 {
1244                         mutexHashEntry *unlinked = entry->next;
1245
1246                         entry->next = unlinked->next;
1247                         unlinked->next = firstFreeOverflowEntry;
1248                         firstFreeOverflowEntry = unlinked;
1249                 }
1250         }
1251 }
1252 #endif
1253
1254 void
1255 builtin_monitorenter (java_objectheader *o)
1256 {
1257 #ifdef USE_THREADS
1258         int hashValue;
1259
1260         assert(blockInts == 0);
1261
1262         ++blockInts;
1263
1264         hashValue = MUTEX_HASH_VALUE(o);
1265         if (mutexHashTable[hashValue].object == o
1266                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1267                 ++mutexHashTable[hashValue].mutex.count;
1268         else
1269                 internal_lock_mutex_for_object(o);
1270
1271         --blockInts;
1272
1273         assert(blockInts == 0);
1274 #endif
1275 }
1276
1277 void builtin_monitorexit (java_objectheader *o)
1278 {
1279 #ifdef USE_THREADS
1280         int hashValue;
1281
1282         assert(blockInts == 0);
1283
1284         ++blockInts;
1285
1286         hashValue = MUTEX_HASH_VALUE(o);
1287         if (mutexHashTable[hashValue].object == o)
1288         {
1289                 if (mutexHashTable[hashValue].mutex.count == 1
1290                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1291                         internal_unlock_mutex_for_object(o);
1292                 else
1293                         --mutexHashTable[hashValue].mutex.count;
1294         }
1295         else
1296                 internal_unlock_mutex_for_object(o);
1297
1298         --blockInts;
1299
1300         assert(blockInts == 0);
1301 #endif
1302 }
1303
1304
1305 /*****************************************************************************
1306                           MISCELLANEOUS HELPER FUNCTIONS
1307 *****************************************************************************/
1308
1309
1310
1311 /*********** Functions for integer divisions *****************************
1312  
1313         On some systems (eg. DEC ALPHA), integer division is not supported by the
1314         CPU. These helper functions implement the missing functionality.
1315
1316 ******************************************************************************/
1317
1318 s4 builtin_idiv (s4 a, s4 b) { return a/b; }
1319 s4 builtin_irem (s4 a, s4 b) { return a%b; }
1320
1321
1322 /************** Functions for long arithmetics *******************************
1323
1324         On systems where 64 bit Integers are not supported by the CPU, these
1325         functions are needed.
1326
1327 ******************************************************************************/
1328
1329
1330 s8 builtin_ladd (s8 a, s8 b) 
1331
1332 #if U8_AVAILABLE
1333         return a+b; 
1334 #else
1335         return builtin_i2l(0);
1336 #endif
1337 }
1338
1339 s8 builtin_lsub (s8 a, s8 b) 
1340
1341 #if U8_AVAILABLE
1342         return a-b; 
1343 #else
1344         return builtin_i2l(0);
1345 #endif
1346 }
1347
1348 s8 builtin_lmul (s8 a, s8 b) 
1349
1350 #if U8_AVAILABLE
1351         return a*b; 
1352 #else
1353         return builtin_i2l(0);
1354 #endif
1355 }
1356
1357 s8 builtin_ldiv (s8 a, s8 b) 
1358
1359 #if U8_AVAILABLE
1360         return a/b; 
1361 #else
1362         return builtin_i2l(0);
1363 #endif
1364 }
1365
1366 s8 builtin_lrem (s8 a, s8 b) 
1367
1368 #if U8_AVAILABLE
1369         return a%b; 
1370 #else
1371         return builtin_i2l(0);
1372 #endif
1373 }
1374
1375 s8 builtin_lshl (s8 a, s4 b) 
1376
1377 #if U8_AVAILABLE
1378         return a<<(b&63);
1379 #else
1380         return builtin_i2l(0);
1381 #endif
1382 }
1383
1384 s8 builtin_lshr (s8 a, s4 b) 
1385
1386 #if U8_AVAILABLE
1387         return a>>(b&63);
1388 #else
1389         return builtin_i2l(0);
1390 #endif
1391 }
1392
1393 s8 builtin_lushr (s8 a, s4 b) 
1394
1395 #if U8_AVAILABLE
1396         return ((u8)a)>>(b&63);
1397 #else
1398         return builtin_i2l(0);
1399 #endif
1400 }
1401
1402 s8 builtin_land (s8 a, s8 b) 
1403
1404 #if U8_AVAILABLE
1405         return a&b; 
1406 #else
1407         return builtin_i2l(0);
1408 #endif
1409 }
1410
1411 s8 builtin_lor (s8 a, s8 b) 
1412
1413 #if U8_AVAILABLE
1414         return a|b; 
1415 #else
1416         return builtin_i2l(0);
1417 #endif
1418 }
1419
1420 s8 builtin_lxor (s8 a, s8 b) 
1421
1422 #if U8_AVAILABLE
1423         return a^b; 
1424 #else
1425         return builtin_i2l(0);
1426 #endif
1427 }
1428
1429 s8 builtin_lneg (s8 a) 
1430
1431 #if U8_AVAILABLE
1432         return -a;
1433 #else
1434         return builtin_i2l(0);
1435 #endif
1436 }
1437
1438 s4 builtin_lcmp (s8 a, s8 b) 
1439
1440 #if U8_AVAILABLE
1441         if (a<b) return -1;
1442         if (a>b) return 1;
1443         return 0;
1444 #else
1445         return 0;
1446 #endif
1447 }
1448
1449
1450
1451
1452
1453 /*********** Functions for floating point operations *************************/
1454
1455 float builtin_fadd (float a, float b)
1456 {
1457         if (isnanf(a)) return FLT_NAN;
1458         if (isnanf(b)) return FLT_NAN;
1459         if (finitef(a)) {
1460                 if (finitef(b)) return a+b;
1461                 else return b;
1462                 }
1463         else {
1464                 if (finitef(b)) return a;
1465                 else {
1466                         if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
1467                         else  return FLT_NAN;
1468                         }
1469                 }
1470 }
1471
1472 float builtin_fsub (float a, float b)
1473 {
1474         return builtin_fadd (a, builtin_fneg(b));
1475 }
1476
1477 float builtin_fmul (float a, float b)
1478 {
1479         if (isnanf(a)) return FLT_NAN;
1480         if (isnanf(b)) return FLT_NAN;
1481         if (finitef(a)) {
1482                 if (finitef(b)) return a*b;
1483                 else {
1484                         if (a==0) return FLT_NAN;
1485                                  else return copysignf(b, copysignf(1.0, b)*a);
1486                         }
1487                 }
1488         else {
1489                 if (finitef(b)) {
1490                         if (b==0) return FLT_NAN;
1491                                  else return copysignf(a, copysignf(1.0, a)*b);
1492                         }
1493                 else {
1494                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1495                         }
1496                 }
1497 }
1498
1499 float builtin_fdiv (float a, float b)
1500 {
1501         if (finitef(a) && finitef(b)) {
1502                 if (b != 0)
1503                         return a / b;
1504                 else {
1505                         if (a > 0)
1506                                 return FLT_POSINF;
1507                         else if (a < 0)
1508                                 return FLT_NEGINF;
1509                         }
1510                 }
1511         return FLT_NAN;
1512 }
1513
1514 float builtin_frem (float a, float b)
1515 {
1516         return fmodf(a, b);
1517 }
1518
1519
1520 float builtin_fneg (float a)
1521 {
1522         if (isnanf(a)) return a;
1523         else {
1524                 if (finitef(a)) return -a;
1525                                    else return copysignf(a,-copysignf(1.0, a));
1526                 }
1527 }
1528
1529 s4 builtin_fcmpl (float a, float b)
1530 {
1531         if (isnanf(a)) return -1;
1532         if (isnanf(b)) return -1;
1533         if (!finitef(a) || !finitef(b)) {
1534                 a = finitef(a) ? 0 : copysignf(1.0,      a);
1535                 b = finitef(b) ? 0 : copysignf(1.0, b);
1536                 }
1537         if (a>b) return 1;
1538         if (a==b) return 0;
1539         return -1;
1540 }
1541
1542 s4 builtin_fcmpg (float a, float b)
1543 {
1544         if (isnanf(a)) return 1;
1545         if (isnanf(b)) return 1;
1546         if (!finitef(a) || !finitef(b)) {
1547                 a = finitef(a) ? 0 : copysignf(1.0, a);
1548                 b = finitef(b) ? 0 : copysignf(1.0, b);
1549                 }
1550         if (a>b) return 1;
1551         if (a==b) return 0;
1552         return -1;
1553 }
1554
1555
1556
1557 /************************* Functions for doubles ****************************/
1558
1559 double builtin_dadd (double a, double b)
1560 {
1561         if (isnan(a)) return DBL_NAN;
1562         if (isnan(b)) return DBL_NAN;
1563         if (finite(a)) {
1564                 if (finite(b)) return a+b;
1565                 else return b;
1566                 }
1567         else {
1568                 if (finite(b)) return a;
1569                 else {
1570                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1571                         else  return DBL_NAN;
1572                         }
1573                 }
1574 }
1575
1576 double builtin_dsub (double a, double b)
1577 {
1578         return builtin_dadd (a, builtin_dneg(b));
1579 }
1580
1581 double builtin_dmul (double a, double b)
1582 {
1583         if (isnan(a)) return DBL_NAN;
1584         if (isnan(b)) return DBL_NAN;
1585         if (finite(a)) {
1586                 if (finite(b)) return a*b;
1587                 else {
1588                         if (a==0) return DBL_NAN;
1589                                  else return copysign(b, copysign(1.0, b)*a);
1590                         }
1591                 }
1592         else {
1593                 if (finite(b)) {
1594                         if (b==0) return DBL_NAN;
1595                                  else return copysign(a, copysign(1.0, a)*b);
1596                         }
1597                 else {
1598                         return copysign(a, copysign(1.0, a)*copysign(1.0, b));
1599                         }
1600                 }
1601 }
1602
1603 double builtin_ddiv (double a, double b)
1604 {
1605         if (finite(a) && finite(b)) {
1606                 if (b != 0)
1607                         return a / b;
1608                 else {
1609                         if (a > 0)
1610                                 return DBL_POSINF;
1611                         else if (a < 0)
1612                                 return DBL_NEGINF;
1613                         }
1614                 }
1615         return DBL_NAN;
1616 }
1617
1618 double builtin_drem (double a, double b)
1619 {
1620         return fmod(a, b);
1621 }
1622
1623 double builtin_dneg (double a)
1624 {
1625         if (isnan(a)) return a;
1626         else {
1627                 if (finite(a)) return -a;
1628                                   else return copysign(a,-copysign(1.0, a));
1629                 }
1630 }
1631
1632 s4 builtin_dcmpl (double a, double b)
1633 {
1634         if (isnan(a)) return -1;
1635         if (isnan(b)) return -1;
1636         if (!finite(a) || !finite(b)) {
1637                 a = finite(a) ? 0 : copysign(1.0, a);
1638                 b = finite(b) ? 0 : copysign(1.0, b);
1639                 }
1640         if (a>b) return 1;
1641         if (a==b) return 0;
1642         return -1;
1643 }
1644
1645 s4 builtin_dcmpg (double a, double b)
1646 {
1647         if (isnan(a)) return 1;
1648         if (isnan(b)) return 1;
1649         if (!finite(a) || !finite(b)) {
1650                 a = finite(a) ? 0 : copysign(1.0, a);
1651                 b = finite(b) ? 0 : copysign(1.0, b);
1652                 }
1653         if (a>b) return 1;
1654         if (a==b) return 0;
1655         return -1;
1656 }
1657
1658
1659 /*********************** Conversion operations ****************************/
1660
1661 s8 builtin_i2l (s4 i)
1662 {
1663 #if U8_AVAILABLE
1664         return i;
1665 #else
1666         s8 v; v.high = 0; v.low=i; return v;
1667 #endif
1668 }
1669
1670 float builtin_i2f (s4 a)
1671 {
1672 float f = (float) a;
1673 return f;
1674 }
1675
1676 double builtin_i2d (s4 a)
1677 {
1678 double d = (double) a;
1679 return d;
1680 }
1681
1682
1683 s4 builtin_l2i (s8 l)
1684 {
1685 #if U8_AVAILABLE
1686         return (s4) l;
1687 #else
1688         return l.low;
1689 #endif
1690 }
1691
1692 float builtin_l2f (s8 a)
1693 {
1694 #if U8_AVAILABLE
1695         float f = (float) a;
1696         return f;
1697 #else
1698         return 0.0;
1699 #endif
1700 }
1701
1702 double builtin_l2d (s8 a)
1703 {
1704 #if U8_AVAILABLE
1705         double d = (double) a;
1706         return d;
1707 #else
1708         return 0.0;
1709 #endif
1710 }
1711
1712
1713 s4 builtin_f2i(float a) 
1714 {
1715
1716 return builtin_d2i((double) a);
1717
1718 /*      float f;
1719         
1720         if (isnanf(a))
1721                 return 0;
1722         if (finitef(a)) {
1723                 if (a > 2147483647)
1724                         return 2147483647;
1725                 if (a < (-2147483648))
1726                         return (-2147483648);
1727                 return (s4) a;
1728                 }
1729         f = copysignf((float) 1.0, a);
1730         if (f > 0)
1731                 return 2147483647;
1732         return (-2147483648); */
1733 }
1734
1735
1736 s8 builtin_f2l (float a)
1737 {
1738
1739 return builtin_d2l((double) a);
1740
1741 /*      float f;
1742         
1743         if (finitef(a)) {
1744                 if (a > 9223372036854775807L)
1745                         return 9223372036854775807L;
1746                 if (a < (-9223372036854775808L))
1747                         return (-9223372036854775808L);
1748                 return (s8) a;
1749                 }
1750         if (isnanf(a))
1751                 return 0;
1752         f = copysignf((float) 1.0, a);
1753         if (f > 0)
1754                 return 9223372036854775807L;
1755         return (-9223372036854775808L); */
1756 }
1757
1758
1759 double builtin_f2d (float a)
1760 {
1761         if (finitef(a)) return (double) a;
1762         else {
1763                 if (isnanf(a)) return DBL_NAN;
1764                 else               return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
1765                 }
1766 }
1767
1768
1769 s4 builtin_d2i (double a) 
1770
1771         double d;
1772         
1773         if (finite(a)) {
1774                 if (a >= 2147483647)
1775                         return 2147483647;
1776                 if (a <= (-2147483647-1))
1777                         return (-2147483647-1);
1778                 return (s4) a;
1779                 }
1780         if (isnan(a))
1781                 return 0;
1782         d = copysign(1.0, a);
1783         if (d > 0)
1784                 return 2147483647;
1785         return (-2147483647-1);
1786 }
1787
1788
1789 s8 builtin_d2l (double a)
1790 {
1791         double d;
1792         
1793         if (finite(a)) {
1794                 if (a >= 9223372036854775807LL)
1795                         return 9223372036854775807LL;
1796                 if (a <= (-9223372036854775807LL-1))
1797                         return (-9223372036854775807LL-1);
1798                 return (s8) a;
1799                 }
1800         if (isnan(a))
1801                 return 0;
1802         d = copysign(1.0, a);
1803         if (d > 0)
1804                 return 9223372036854775807LL;
1805         return (-9223372036854775807LL-1);
1806 }
1807
1808
1809 float builtin_d2f (double a)
1810 {
1811         if (finite(a)) return (float) a;
1812         else {
1813                 if (isnan(a)) return FLT_NAN;
1814                 else              return copysignf (FLT_POSINF, (float) copysign(1.0, a));
1815                 }
1816 }
1817
1818
1819 /*
1820  * These are local overrides for various environment variables in Emacs.
1821  * Please do not remove this and leave it at the end of the file, where
1822  * Emacs will automagically detect them.
1823  * ---------------------------------------------------------------------
1824  * Local variables:
1825  * mode: c
1826  * indent-tabs-mode: t
1827  * c-basic-offset: 4
1828  * tab-width: 4
1829  * End:
1830  */