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