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