Renamed class_init to initialize_class.
[cacao.git] / src / vm / builtin.c
1 /* src/vm/builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
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    Changes: Christian Thalinger
32
33    Contains C functions for JavaVM Instructions that cannot be
34    translated to machine language directly. Consequently, the
35    generated machine code for these instructions contains function
36    calls instead of machine instructions, using the C calling
37    convention.
38
39    $Id: builtin.c 2201 2005-04-03 21:48:11Z twisti $
40
41 */
42
43
44 #include <assert.h>
45 #include <math.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #include "config.h"
50 #include "arch.h"
51 #include "types.h"
52 #include "mm/boehm.h"
53 #include "mm/memory.h"
54 #include "native/native.h"
55 #include "native/include/java_lang_Cloneable.h"
56 #include "native/include/java_lang_VMObject.h"
57
58 #if defined(USE_THREADS)
59 # if defined(NATIVE_THREADS)
60 #  include "threads/native/threads.h"
61 # else
62 #  include "threads/green/threads.h"
63 #  include "threads/green/locks.h"
64 # endif
65 #endif
66
67 #include "toolbox/logging.h"
68 #include "vm/builtin.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/loader.h"
73 #include "vm/options.h"
74 #include "vm/stringlocal.h"
75 #include "vm/tables.h"
76 #include "vm/jit/asmpart.h"
77
78
79 #undef DEBUG /*define DEBUG 1*/
80
81 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
82 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
83
84
85 #if defined(USEBUILTINTABLE)
86
87 #if 0
88 stdopdescriptor builtintable[] = {
89         { ICMD_LCMP,   TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2,
90           (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false },
91         { ICMD_LAND,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
92           (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
93         { ICMD_LOR,    TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
94           (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
95         { ICMD_LXOR,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
96           (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
97         { ICMD_LSHL,   TYPE_LONG, TYPE_INT,  TYPE_LONG, ICMD_BUILTIN2,
98           (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
99         { ICMD_LSHR,   TYPE_LONG, TYPE_INT,  TYPE_LONG, ICMD_BUILTIN2,
100           (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
101         { ICMD_LUSHR,  TYPE_LONG, TYPE_INT,  TYPE_LONG, ICMD_BUILTIN2,
102           (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
103         { ICMD_LADD,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
104           (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
105         { ICMD_LSUB,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
106           (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
107         { ICMD_LNEG,   TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1, 
108           (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true },
109         { ICMD_LMUL,   TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
110           (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false },
111         { ICMD_I2F,    TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
112           (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true },
113         { ICMD_I2D,    TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1, 
114           (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true },
115         { ICMD_L2F,    TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
116           (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
117         { ICMD_L2D,    TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1, 
118           (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
119         { ICMD_F2L,    TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
120           (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
121         { ICMD_D2L,    TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
122           (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
123         { ICMD_F2I,    TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
124           (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true },
125         { ICMD_D2I,    TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
126           (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true },
127         { 255, 0, 0, 0, 0, NULL, true, false },
128 };
129
130 #endif
131
132 static int builtintablelen;
133
134 #endif /* USEBUILTINTABLE */
135
136
137 /*****************************************************************************
138                                                  TABLE OF BUILTIN FUNCTIONS
139
140     This table lists the builtin functions which are used inside
141     BUILTIN* opcodes.
142
143     The first part of the table (up to the 255-marker) lists the
144     opcodes which are automatically replaced in stack.c.
145
146     The second part lists the builtin functions which are "manually"
147     used for BUILTIN* opcodes in parse.c and stack.c.
148
149 *****************************************************************************/
150
151 builtin_descriptor builtin_desc[] = {
152 #if defined(USEBUILTINTABLE)
153         {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_INT   ,
154                      SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
155         
156         {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
157                      SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"},
158         {ICMD_LOR  , BUILTIN_lor  ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
159                      SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"},
160         {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
161                      SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"},
162         
163         {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_INT   ,TYPE_VOID ,TYPE_LONG  ,
164                      SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"},
165         {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_INT   ,TYPE_VOID ,TYPE_LONG  ,
166                      SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"},
167         {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_INT   ,TYPE_VOID ,TYPE_LONG  ,
168                      SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"},
169         
170         {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
171                      SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"},
172         {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
173                      SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"},
174         {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG  ,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,
175                      SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"},
176         {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID ,TYPE_LONG  ,
177                      SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"},
178         
179         {ICMD_I2F  , BUILTIN_i2f  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID ,TYPE_FLOAT ,
180                      SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"},
181         {ICMD_I2D  , BUILTIN_i2d  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID ,TYPE_DOUBLE,
182                      SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"},
183         {ICMD_L2F  , BUILTIN_l2f  ,ICMD_BUILTIN1,TYPE_LONG  ,TYPE_VOID  ,TYPE_VOID ,TYPE_FLOAT ,
184                      SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"},
185         {ICMD_L2D  , BUILTIN_l2d  ,ICMD_BUILTIN1,TYPE_LONG  ,TYPE_VOID  ,TYPE_VOID ,TYPE_DOUBLE,
186                      SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"},
187         {ICMD_F2L  , BUILTIN_f2l  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,
188                      SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"},
189         {ICMD_D2L  , BUILTIN_d2l  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,
190                      SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"},
191         {ICMD_F2I  , BUILTIN_f2i  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,
192                      SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
193         {ICMD_D2I  , BUILTIN_d2i  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,
194                      SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
195
196         { ICMD_FADD , BUILTIN_fadd  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd"  },
197         { ICMD_FSUB , BUILTIN_fsub  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub"  },
198         { ICMD_FMUL , BUILTIN_fmul  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul"  },
199         { ICMD_FDIV , BUILTIN_fdiv  , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv"  },
200         { ICMD_FNEG , BUILTIN_fneg  , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg"  },
201         { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" },
202         { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT  , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" },
203
204         { ICMD_DADD , BUILTIN_dadd  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd"  },
205         { ICMD_DSUB , BUILTIN_dsub  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub"  },
206         { ICMD_DMUL , BUILTIN_dmul  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul"  },
207         { ICMD_DDIV , BUILTIN_ddiv  , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv"  },
208         { ICMD_DNEG , BUILTIN_dneg  , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg"  },
209         { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" },
210         { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL  , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" },
211
212         { ICMD_F2D,  BUILTIN_f2d  , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" },
213         { ICMD_D2F,  BUILTIN_d2f  , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" },
214 #endif
215
216         /* this record marks the end of the automatically replaced opcodes */
217         {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
218
219         /* the following functions are not replaced automatically */
220         
221 #if defined(__ALPHA__)
222         {255, BUILTIN_f2l  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,0,0,"f2l"},
223         {255, BUILTIN_d2l  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_LONG  ,0,0,"d2l"},
224         {255, BUILTIN_f2i  ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,0,0,"f2i"},
225         {255, BUILTIN_d2i  ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID  ,TYPE_VOID ,TYPE_INT   ,0,0,"d2i"},
226 #endif
227
228         {255,BUILTIN_instanceof      ,ICMD_BUILTIN2,TYPE_ADR   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_INT   ,0,0,"instanceof"},
229         {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_INT   ,0,0,"arrayinstanceof"},
230         {255,BUILTIN_checkarraycast  ,ICMD_BUILTIN2,TYPE_ADR   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,0,0,"checkarraycast"},
231         {255,BUILTIN_aastore         ,ICMD_BUILTIN3,TYPE_ADR   ,TYPE_INT   ,TYPE_ADR   ,TYPE_VOID  ,0,0,"aastore"},
232         {255,BUILTIN_new             ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"new"},
233         {255,BUILTIN_newarray        ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray"},
234         {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_boolean"},
235         {255,BUILTIN_newarray_char   ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_char"},
236         {255,BUILTIN_newarray_float  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_float"},
237         {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_double"},
238         {255,BUILTIN_newarray_byte   ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_byte"},
239         {255,BUILTIN_newarray_short  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_short"},
240         {255,BUILTIN_newarray_int    ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_int"},
241         {255,BUILTIN_newarray_long   ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_long"},
242         {255,BUILTIN_anewarray       ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_ADR   ,TYPE_VOID  ,TYPE_ADR   ,0,0,"anewarray"},
243 #if defined(USE_THREADS)
244         {255,BUILTIN_monitorenter    ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_VOID  ,0,0,"monitorenter"},
245         {255,BUILTIN_monitorexit     ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_VOID  ,0,0,"monitorexit"},
246 #endif
247 #if !SUPPORT_DIVISION
248         {255,BUILTIN_idiv            ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_INT   ,TYPE_VOID  ,TYPE_INT   ,0,0,"idiv"},
249         {255,BUILTIN_irem            ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_INT   ,TYPE_VOID  ,TYPE_INT   ,0,0,"irem"},
250 #endif
251 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
252         {255,BUILTIN_ldiv            ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID  ,TYPE_LONG  ,0,0,"ldiv"},
253         {255,BUILTIN_lrem            ,ICMD_BUILTIN2,TYPE_LONG  ,TYPE_LONG  ,TYPE_VOID  ,TYPE_LONG  ,0,0,"lrem"},
254 #endif
255         {255,BUILTIN_frem            ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID  ,TYPE_FLOAT ,0,0,"frem"},
256         {255,BUILTIN_drem            ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID  ,TYPE_DOUBLE,0,0,"drem"},
257
258         /* this record marks the end of the list */
259         {  0,NULL,0,0,0,0,0,0,0,"<END>"}
260 };
261
262
263 #if defined(USEBUILTINTABLE)
264
265 static int stdopcompare(const void *a, const void *b)
266 {
267         builtin_descriptor *o1 = (builtin_descriptor *) a;
268         builtin_descriptor *o2 = (builtin_descriptor *) b;
269         if (!o1->supported && o2->supported)
270                 return -1;
271         if (o1->supported && !o2->supported)
272                 return 1;
273         return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
274 }
275
276
277 void sort_builtintable(void)
278 {
279         int len;
280
281         len = 0;
282         while (builtin_desc[len].opcode != 255) len++;
283         qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
284
285         for (--len; len>=0 && builtin_desc[len].supported; len--);
286         builtintablelen = ++len;
287 }
288
289
290 builtin_descriptor *find_builtin(int icmd)
291 {
292         builtin_descriptor *first = builtin_desc;
293         builtin_descriptor *last = builtin_desc + builtintablelen;
294         int len = last - first;
295         int half;
296         builtin_descriptor *middle;
297
298         while (len > 0) {
299                 half = len / 2;
300                 middle = first + half;
301                 if (middle->opcode < icmd) {
302                         first = middle + 1;
303                         len -= half + 1;
304                 } else
305                         len = half;
306         }
307         return first != last ? first : NULL;
308 }
309
310 #endif /* defined(USEBUILTINTABLE) */
311
312
313 /*****************************************************************************
314                                                                 TYPE CHECKS
315 *****************************************************************************/
316
317
318
319 /*************** internal function: builtin_isanysubclass *********************
320
321         Checks a subclass relation between two classes. Implemented interfaces
322         are interpreted as super classes.
323         Return value:  1 ... sub is subclass of super
324                                    0 ... otherwise
325                                         
326 *****************************************************************************/                                  
327 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
328 {
329         s4 res;
330         castinfo classvalues;
331
332         if (sub == super)
333                 return 1;
334
335         if (super->flags & ACC_INTERFACE)
336                 return (sub->vftbl->interfacetablelength > super->index) &&
337                         (sub->vftbl->interfacetable[-super->index] != NULL);
338
339         asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
340
341         res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
342                 (u4) classvalues.super_diffval;
343
344         return res;
345 }
346
347
348 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
349 {
350         s4 res;
351         s4 base;
352         castinfo classvalues;
353
354         if (sub == super)
355                 return 1;
356
357         asm_getclassvalues_atomic(super, sub, &classvalues);
358
359         if ((base = classvalues.super_baseval) <= 0)
360                 /* super is an interface */
361                 res = (sub->interfacetablelength > -base) &&
362                         (sub->interfacetable[base] != NULL);
363         else
364             res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
365                         <= (u4) classvalues.super_diffval;
366
367         return res;
368 }
369
370
371 /****************** function: builtin_instanceof *****************************
372
373         Checks if an object is an instance of some given class (or subclass of
374         that class). If class is an interface, checks if the interface is
375         implemented.
376         Return value:  1 ... obj is an instance of class or implements the interface
377                                    0 ... otherwise or if obj == NULL
378                          
379 *****************************************************************************/
380
381 /* XXX should use vftbl */
382 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
383 {
384 #ifdef DEBUG
385         log_text ("builtin_instanceof called");
386 #endif  
387         if (!obj)
388                 return 0;
389
390         return builtin_isanysubclass(obj->vftbl->class, class);
391 }
392
393
394
395 /**************** function: builtin_checkcast *******************************
396
397         The same as builtin_instanceof except that 1 is returned when
398         obj == NULL
399                           
400 ****************************************************************************/
401
402 /* XXX should use vftbl */
403 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
404 {
405 #ifdef DEBUG
406         log_text("builtin_checkcast called");
407 #endif
408
409         if (obj == NULL)
410                 return 1;
411         if (builtin_isanysubclass(obj->vftbl->class, class))
412                 return 1;
413
414 #if DEBUG
415         printf("#### checkcast failed ");
416         utf_display(obj->vftbl->class->name);
417         printf(" -> ");
418         utf_display(class->name);
419         printf("\n");
420 #endif
421
422         return 0;
423 }
424
425
426 /*********** internal function: builtin_descriptorscompatible ******************
427
428         Checks if two array type descriptors are assignment compatible
429         Return value:  1 ... target = desc is possible
430                                    0 ... otherwise
431                         
432 ******************************************************************************/
433
434 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
435 {
436         if (desc==target) return 1;
437         if (desc->arraytype != target->arraytype) return 0;
438         if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
439         
440         /* {both arrays are arrays of references} */
441         if (desc->dimension == target->dimension) {
442                 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
443                 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
444                 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
445         }
446         if (desc->dimension < target->dimension) return 0;
447
448         /* {desc has higher dimension than target} */
449         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
450 }
451
452
453 /******************** function: builtin_checkarraycast ***********************
454
455         Checks if an object is really a subtype of the requested array type.
456         The object has to be an array to begin with. For simple arrays (int, short,
457         double, etc.) the types have to match exactly.
458         For arrays of objects, the type of elements in the array has to be a
459         subtype (or the same type) of the requested element type. For arrays of
460         arrays (which in turn can again be arrays of arrays), the types at the
461         lowest level have to satisfy the corresponding sub class relation.
462         
463         Return value:  1 ... cast is possible
464                                    0 ... otherwise
465         
466         ATTENTION: a cast with a NULL pointer is always possible.
467                         
468 *****************************************************************************/
469
470 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
471 {
472         arraydescriptor *desc;
473         
474         if (!o) return 1;
475         if ((desc = o->vftbl->arraydesc) == NULL) return 0;
476
477         return builtin_descriptorscompatible(desc, target->arraydesc);
478 }
479
480
481 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
482 {
483         if (!obj) return 1;
484         return builtin_checkarraycast(obj, target);
485 }
486
487
488 /************************** exception functions *******************************
489
490 ******************************************************************************/
491
492 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
493 {
494         if (opt_verbose) {
495                 char logtext[MAXLOGTEXT];
496                 sprintf(logtext, "Builtin exception thrown: ");
497
498                 if (xptr) {
499                         java_lang_Throwable *t = (java_lang_Throwable *) xptr;
500
501                         utf_sprint_classname(logtext + strlen(logtext),
502                                                                  xptr->vftbl->class->name);
503
504                         if (t->detailMessage) {
505                                 char *buf;
506
507                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
508                                 sprintf(logtext + strlen(logtext), ": %s", buf);
509                                 MFREE(buf, char, strlen(buf));
510                         }
511
512                 } else {
513                         sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
514                 }
515
516                 log_text(logtext);
517         }
518
519         *exceptionptr = xptr;
520
521         return xptr;
522 }
523
524
525
526 /******************* function: builtin_canstore *******************************
527
528         Checks, if an object can be stored in an array.
529         Return value:  1 ... possible
530                                    0 ... otherwise
531
532 ******************************************************************************/
533
534 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
535 {
536         arraydescriptor *desc;
537         arraydescriptor *valuedesc;
538         vftbl_t *componentvftbl;
539         vftbl_t *valuevftbl;
540     int dim_m1;
541         int base;
542         castinfo classvalues;
543         
544         if (!o) return 1;
545
546         /* The following is guaranteed (by verifier checks):
547          *
548          *     *) a->...vftbl->arraydesc != NULL
549          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
550          *     *) o->vftbl is not an interface vftbl
551          */
552         
553         desc = a->header.objheader.vftbl->arraydesc;
554     componentvftbl = desc->componentvftbl;
555         valuevftbl = o->vftbl;
556
557     if ((dim_m1 = desc->dimension - 1) == 0) {
558                 s4 res;
559
560                 /* {a is a one-dimensional array} */
561                 /* {a is an array of references} */
562                 
563                 if (valuevftbl == componentvftbl)
564                         return 1;
565
566                 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
567
568                 if ((base = classvalues.super_baseval) <= 0)
569                         /* an array of interface references */
570                         return (valuevftbl->interfacetablelength > -base &&
571                                         valuevftbl->interfacetable[base] != NULL);
572                 
573                 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
574                         <= (unsigned) classvalues.super_diffval;
575
576                 return res;
577     }
578     /* {a has dimension > 1} */
579         /* {componentvftbl->arraydesc != NULL} */
580
581         /* check if o is an array */
582         if ((valuedesc = valuevftbl->arraydesc) == NULL)
583                 return 0;
584         /* {o is an array} */
585
586         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
587 }
588
589
590 /* This is an optimized version where a is guaranteed to be one-dimensional */
591 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
592 {
593         arraydescriptor *desc;
594         vftbl_t *elementvftbl;
595         vftbl_t *valuevftbl;
596         s4 res;
597         int base;
598         castinfo classvalues;
599         
600         if (!o) return 1;
601
602         /* The following is guaranteed (by verifier checks):
603          *
604          *     *) a->...vftbl->arraydesc != NULL
605          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
606          *     *) a->...vftbl->arraydesc->dimension == 1
607          *     *) o->vftbl is not an interface vftbl
608          */
609
610         desc = a->header.objheader.vftbl->arraydesc;
611     elementvftbl = desc->elementvftbl;
612         valuevftbl = o->vftbl;
613
614         /* {a is a one-dimensional array} */
615         
616         if (valuevftbl == elementvftbl)
617                 return 1;
618
619         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
620
621         if ((base = classvalues.super_baseval) <= 0)
622                 /* an array of interface references */
623                 return (valuevftbl->interfacetablelength > -base &&
624                                 valuevftbl->interfacetable[base] != NULL);
625
626         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
627                 <= (unsigned) classvalues.super_diffval;
628
629         return res;
630 }
631
632
633 /* This is an optimized version where a is guaranteed to be a
634  * one-dimensional array of a class type */
635 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
636 {
637         vftbl_t *elementvftbl;
638         vftbl_t *valuevftbl;
639         s4 res;
640         castinfo classvalues;
641         
642         if (!o) return 1;
643
644         /* The following is guaranteed (by verifier checks):
645          *
646          *     *) a->...vftbl->arraydesc != NULL
647          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
648          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
649          *     *) a->...vftbl->arraydesc->dimension == 1
650          *     *) o->vftbl is not an interface vftbl
651          */
652
653     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
654         valuevftbl = o->vftbl;
655
656         /* {a is a one-dimensional array} */
657         
658         if (valuevftbl == elementvftbl)
659                 return 1;
660
661         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
662
663         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
664                 <= (unsigned) classvalues.super_diffval;
665
666         return res;
667 }
668
669
670 /* builtin_new *****************************************************************
671
672    Creates a new instance of class c on the heap.
673
674    Return value: pointer to the object or NULL if no memory is
675    available
676                         
677 *******************************************************************************/
678
679 java_objectheader *builtin_new(classinfo *c)
680 {
681         java_objectheader *o;
682
683         /* is the class loaded */
684         /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
685         assert(c->loaded);
686
687         /* is the class linked */
688         if (!c->linked)
689                 if (!link_class(c))
690                         return NULL;
691
692         if (!c->initialized) {
693                 if (initverbose)
694                         log_message_class("Initialize class (from builtin_new): ", c);
695
696                 if (!initialize_class(c))
697                         return NULL;
698         }
699
700         o = heap_allocate(c->instancesize, true, c->finalizer);
701
702         if (!o)
703                 return NULL;
704
705         MSET(o, 0, u1, c->instancesize);
706
707         o->vftbl = c->vftbl;
708
709 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
710         initObjectLock(o);
711 #endif
712
713         return o;
714 }
715
716
717 /* builtin_newarray ************************************************************
718
719    Creates an array with the given vftbl on the heap.
720
721    Return value:  pointer to the array or NULL if no memory is available
722
723    CAUTION: The given vftbl must be the vftbl of the *array* class,
724    not of the element class.
725
726 *******************************************************************************/
727
728 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
729 {
730         java_arrayheader *a;
731         arraydescriptor *desc;
732         s4 dataoffset;
733         s4 componentsize;
734         s4 actualsize;
735
736         desc = arrayvftbl->arraydesc;
737         dataoffset = desc->dataoffset;
738         componentsize = desc->componentsize;
739
740         if (size < 0) {
741                 *exceptionptr = new_negativearraysizeexception();
742                 return NULL;
743         }
744
745         actualsize = dataoffset + size * componentsize;
746
747         if (((u4) actualsize) < ((u4) size)) { /* overflow */
748                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
749                 return NULL;
750         }
751
752         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
753
754         if (!a)
755                 return NULL;
756
757         MSET(a, 0, u1, actualsize);
758
759         a->objheader.vftbl = arrayvftbl;
760
761 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
762         initObjectLock(&a->objheader);
763 #endif
764
765         a->size = size;
766
767         return a;
768 }
769
770
771 /********************** Function: builtin_anewarray *************************
772
773         Creates an array of references to the given class type on the heap.
774
775         Return value: pointer to the array or NULL if no memory is available
776
777     XXX This function does not do The Right Thing, because it uses a
778     classinfo pointer at runtime. builtin_newarray should be used
779     instead.
780
781 *****************************************************************************/
782
783 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
784 {
785         classinfo *c;
786         
787         /* is class loaded */
788         assert(component->loaded);
789
790         /* is class linked */
791         if (!component->linked)
792                 if (!link_class(component))
793                         return NULL;
794
795         c = class_array_of(component,true);
796         if (!c)
797                 return NULL;
798         return (java_objectarray *) builtin_newarray(size, c->vftbl);
799 }
800
801
802 /******************** Function: builtin_newarray_int ***********************
803
804         Creates an array of 32 bit Integers on the heap.
805
806         Return value:  pointer to the array or NULL if no memory is available
807
808 *****************************************************************************/
809
810 java_intarray *builtin_newarray_int(s4 size)
811 {
812         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
813 }
814
815
816 /******************** Function: builtin_newarray_long ***********************
817
818         Creates an array of 64 bit Integers on the heap.
819
820         Return value:  pointer to the array or NULL if no memory is available
821
822 *****************************************************************************/
823
824 java_longarray *builtin_newarray_long(s4 size)
825 {
826         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
827 }
828
829
830 /******************** function: builtin_newarray_float ***********************
831
832         Creates an array of 32 bit IEEE floats on the heap.
833
834         Return value:  pointer to the array or NULL if no memory is available
835
836 *****************************************************************************/
837
838 java_floatarray *builtin_newarray_float(s4 size)
839 {
840         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
841 }
842
843
844 /******************** function: builtin_newarray_double ***********************
845
846         Creates an array of 64 bit IEEE floats on the heap.
847
848         Return value:  pointer to the array or NULL if no memory is available
849
850 *****************************************************************************/
851
852 java_doublearray *builtin_newarray_double(s4 size)
853 {
854         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
855 }
856
857
858 /******************** function: builtin_newarray_byte ***********************
859
860         Creates an array of 8 bit Integers on the heap.
861
862         Return value:  pointer to the array or NULL if no memory is available
863
864 *****************************************************************************/
865
866 java_bytearray *builtin_newarray_byte(s4 size)
867 {
868         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
869 }
870
871
872 /******************** function: builtin_newarray_char ************************
873
874         Creates an array of characters on the heap.
875
876         Return value:  pointer to the array or NULL if no memory is available
877
878 *****************************************************************************/
879
880 java_chararray *builtin_newarray_char(s4 size)
881 {
882         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
883 }
884
885
886 /******************** function: builtin_newarray_short ***********************
887
888         Creates an array of 16 bit Integers on the heap.
889
890         Return value:  pointer to the array or NULL if no memory is available
891
892 *****************************************************************************/
893
894 java_shortarray *builtin_newarray_short(s4 size)
895 {
896         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
897 }
898
899
900 /******************** function: builtin_newarray_boolean ************************
901
902         Creates an array of bytes on the heap. The array is designated as an array
903         of booleans (important for casts)
904         
905         Return value:  pointer to the array or NULL if no memory is available
906
907 *****************************************************************************/
908
909 java_booleanarray *builtin_newarray_boolean(s4 size)
910 {
911         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
912 }
913
914
915 /**************** function: builtin_nmultianewarray ***************************
916
917         Creates a multi-dimensional array on the heap. The dimensions are passed in
918         an array of longs.
919
920     Arguments:
921         n............number of dimensions to create
922         arrayvftbl...vftbl of the array class
923         dims.........array containing the size of each dimension to create
924
925         Return value:  pointer to the array or NULL if no memory is available
926
927 ******************************************************************************/
928
929 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
930 /*  java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
931 {
932         s4 size, i;
933         java_arrayheader *a;
934         vftbl_t *componentvftbl;
935
936 /*      utf_display(arrayclass->name); */
937
938 /*      class_load(arrayclass); */
939 /*      class_link(arrayclass); */
940         
941         /* create this dimension */
942         size = (s4) dims[0];
943         a = builtin_newarray(size, arrayvftbl);
944 /*      a = builtin_newarray(size, arrayclass->vftbl); */
945
946         if (!a)
947                 return NULL;
948
949         /* if this is the last dimension return */
950         if (!--n)
951                 return a;
952
953         /* get the vftbl of the components to create */
954         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
955 /*      component = arrayclass->vftbl->arraydesc; */
956
957         /* The verifier guarantees this. */
958         /* if (!componentvftbl) */
959         /*      panic ("multianewarray with too many dimensions"); */
960
961         /* create the component arrays */
962         for (i = 0; i < size; i++) {
963                 java_arrayheader *ea = 
964                         builtin_nmultianewarray(n, componentvftbl, dims + 1);
965
966                 if (!ea)
967                         return NULL;
968                 
969                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
970         }
971
972         return a;
973 }
974
975
976 /*****************************************************************************
977                                           METHOD LOGGING
978
979         Various functions for printing a message at method entry or exit (for
980         debugging)
981         
982 *****************************************************************************/
983
984 u4 methodindent = 0;
985
986 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
987                                                                                    methodinfo *m,
988                                                                                    void *pos,
989                                                                                    s4 line,
990                                                                                    s4 noindent)
991 {
992         if (!noindent) {
993                 if (methodindent)
994                         methodindent--;
995                 else
996                         log_text("WARNING: unmatched methodindent--");
997         }
998         if (opt_verbose || runverbose || verboseexception) {
999                 if (xptr) {
1000                         printf("Exception ");
1001                         utf_display_classname(xptr->vftbl->class->name);
1002
1003                 } else {
1004                         printf("Some Throwable");
1005                 }
1006                 printf(" thrown in ");
1007
1008                 if (m) {
1009                         utf_display_classname(m->class->name);
1010                         printf(".");
1011                         utf_display(m->name);
1012                         if (m->flags & ACC_SYNCHRONIZED) {
1013                                 printf("(SYNC");
1014
1015                         } else{
1016                                 printf("(NOSYNC");
1017                         }
1018
1019                         if (m->flags & ACC_NATIVE) {
1020                                 printf(",NATIVE");
1021 #if POINTERSIZE == 8
1022                                 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1023 #else
1024                                 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1025 #endif
1026
1027                         } else {
1028 #if POINTERSIZE == 8
1029                                 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1030 #else
1031                                 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1032 #endif
1033                                 if (m->class->sourcefile == NULL) {
1034                                         printf("<NO CLASSFILE INFORMATION>");
1035
1036                                 } else {
1037                                         utf_display(m->class->sourcefile);
1038                                 }
1039                                 printf(":%d)\n", line);
1040                         }
1041
1042                 } else
1043                         printf("call_java_method\n");
1044                 fflush(stdout);
1045         }
1046
1047         return xptr;
1048 }
1049
1050
1051 #ifdef TRACE_ARGS_NUM
1052 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1053 #if TRACE_ARGS_NUM >= 6
1054                                                 s8 a4, s8 a5,
1055 #endif
1056 #if TRACE_ARGS_NUM == 8
1057                                                 s8 a6, s8 a7,
1058 #endif
1059                                                 methodinfo *m)
1060 {
1061         s4 i;
1062         char logtext[MAXLOGTEXT];
1063         for (i = 0; i < methodindent; i++)
1064                 logtext[i] = '\t';
1065         if (methodindent == 0) 
1066                         sprintf(logtext + methodindent, "1st_call: ");
1067         else
1068                 sprintf(logtext + methodindent, "called: ");
1069
1070         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1071         sprintf(logtext + strlen(logtext), ".");
1072         utf_sprint(logtext + strlen(logtext), m->name);
1073         utf_sprint(logtext + strlen(logtext), m->descriptor);
1074
1075         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
1076         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
1077         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
1078         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
1079         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
1080         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1081         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
1082         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
1083         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
1084         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
1085         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
1086         
1087
1088         sprintf(logtext + strlen(logtext), "(");
1089
1090         switch (m->paramcount) {
1091         case 0:
1092                 break;
1093
1094 #if defined(__I386__) || defined(__POWERPC__)
1095         case 1:
1096                 sprintf(logtext+strlen(logtext), "%llx", a0);
1097                 break;
1098
1099         case 2:
1100                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1101                 break;
1102
1103         case 3:
1104                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1105                 break;
1106
1107         case 4:
1108                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1109                                 a0,   a1,   a2,   a3);
1110                 break;
1111
1112 #if TRACE_ARGS_NUM >= 6
1113         case 5:
1114                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1115                                 a0,   a1,   a2,   a3,   a4);
1116                 break;
1117
1118         case 6:
1119                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1120                                 a0,   a1,   a2,   a3,   a4,   a5);
1121                 break;
1122 #endif /* TRACE_ARGS_NUM >= 6 */
1123
1124 #if TRACE_ARGS_NUM == 8
1125         case 7:
1126                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1127                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
1128                 break;
1129
1130         case 8:
1131                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1132                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
1133                 break;
1134
1135         default:
1136                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1137                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   m->paramcount - 8);
1138                 break;
1139 #else /* TRACE_ARGS_NUM == 8 */
1140         default:
1141                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1142                                 a0,   a1,   a2,   a3,   a4,   a5,   m->paramcount - 6);
1143                 break;
1144 #endif /* TRACE_ARGS_NUM == 8 */
1145 #else /* defined(__I386__) || defined(__POWERPC__) */
1146         case 1:
1147                 sprintf(logtext+strlen(logtext), "%lx", a0);
1148                 break;
1149
1150         case 2:
1151                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1152                 break;
1153
1154         case 3:
1155                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1156                 break;
1157
1158         case 4:
1159                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1160                                 a0,  a1,  a2,  a3);
1161                 break;
1162
1163 #if TRACE_ARGS_NUM >= 6
1164         case 5:
1165                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1166                                 a0,  a1,  a2,  a3,  a4);
1167                 break;
1168
1169         case 6:
1170                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1171                                 a0,  a1,  a2,  a3,  a4,  a5);
1172                 break;
1173 #endif /* TRACE_ARGS_NUM >= 6 */
1174
1175 #if TRACE_ARGS_NUM == 8
1176         case 7:
1177                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1178                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
1179                 break;
1180
1181         case 8:
1182                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1183                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
1184                 break;
1185 #endif /* TRACE_ARGS_NUM == 8 */
1186
1187         default:
1188 #if TRACE_ARGS_NUM == 4
1189                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1190                                 a0,  a1,  a2,  a3,   m->paramcount - 4);
1191
1192 #elif TRACE_ARGS_NUM == 6
1193                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1194                                 a0,  a1,  a2,  a3,  a4,  a5,  m->paramcount - 6);
1195
1196 #elif TRACE_ARGS_NUM == 8
1197                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1198                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  m->paramcount - 8);
1199 #endif
1200                 break;
1201 #endif /* defined(__I386__) || defined(__POWERPC__) */
1202         }
1203
1204         sprintf(logtext + strlen(logtext), ")");
1205         log_text(logtext);
1206
1207         methodindent++;
1208 }
1209 #endif
1210
1211
1212 void builtin_displaymethodstart(methodinfo *m)
1213 {
1214         char logtext[MAXLOGTEXT];
1215         sprintf(logtext, "                                                                                              ");
1216         sprintf(logtext + methodindent, "called: ");
1217         utf_sprint(logtext + strlen(logtext), m->class->name);
1218         sprintf(logtext + strlen(logtext), ".");
1219         utf_sprint(logtext + strlen(logtext), m->name);
1220         utf_sprint(logtext + strlen(logtext), m->descriptor);
1221
1222         if (m->flags & ACC_PUBLIC)       sprintf(logtext + strlen(logtext), " PUBLIC");
1223         if (m->flags & ACC_PRIVATE)      sprintf(logtext + strlen(logtext), " PRIVATE");
1224         if (m->flags & ACC_PROTECTED)    sprintf(logtext + strlen(logtext), " PROTECTED");
1225         if (m->flags & ACC_STATIC)       sprintf(logtext + strlen(logtext), " STATIC");
1226         if (m->flags & ACC_FINAL)        sprintf(logtext + strlen(logtext), " FINAL");
1227         if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1228         if (m->flags & ACC_VOLATILE)     sprintf(logtext + strlen(logtext), " VOLATILE");
1229         if (m->flags & ACC_TRANSIENT)    sprintf(logtext + strlen(logtext), " TRANSIENT");
1230         if (m->flags & ACC_NATIVE)       sprintf(logtext + strlen(logtext), " NATIVE");
1231         if (m->flags & ACC_INTERFACE)    sprintf(logtext + strlen(logtext), " INTERFACE");
1232         if (m->flags & ACC_ABSTRACT)     sprintf(logtext + strlen(logtext), " ABSTRACT");
1233
1234         log_text(logtext);
1235         methodindent++;
1236 }
1237
1238
1239 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1240 {
1241         int i;
1242         char logtext[MAXLOGTEXT];
1243         for (i = 0; i < methodindent; i++)
1244                 logtext[i] = '\t';
1245         if (methodindent)
1246                 methodindent--;
1247         else
1248                 log_text("WARNING: unmatched methodindent--");
1249
1250         sprintf(logtext + methodindent, "finished: ");
1251         utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1252         sprintf(logtext + strlen(logtext), ".");
1253         utf_sprint(logtext + strlen(logtext), m->name);
1254         utf_sprint(logtext + strlen(logtext), m->descriptor);
1255
1256         switch (m->returntype) {
1257         case TYPE_INT:
1258                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1259                 break;
1260
1261         case TYPE_LONG:
1262 #if defined(__I386__) || defined(__POWERPC__)
1263                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1264 #else
1265                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1266 #endif
1267                 break;
1268
1269         case TYPE_ADDRESS:
1270 #if defined(__I386__) || defined(__POWERPC__)
1271                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1272 #else
1273                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1274 #endif
1275                 break;
1276
1277         case TYPE_FLOAT:
1278                 sprintf(logtext + strlen(logtext), "->%g", f);
1279                 break;
1280
1281         case TYPE_DOUBLE:
1282                 sprintf(logtext + strlen(logtext), "->%g", d);
1283                 break;
1284         }
1285         log_text(logtext);
1286 }
1287
1288
1289 /****************************************************************************
1290                          SYNCHRONIZATION FUNCTIONS
1291 *****************************************************************************/
1292
1293 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1294 /*
1295  * Lock the mutex of an object.
1296  */
1297 void internal_lock_mutex_for_object(java_objectheader *object)
1298 {
1299         mutexHashEntry *entry;
1300         int hashValue;
1301
1302         assert(object != 0);
1303
1304         hashValue = MUTEX_HASH_VALUE(object);
1305         entry = &mutexHashTable[hashValue];
1306
1307         if (entry->object != 0) {
1308                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1309                         entry->object = 0;
1310                         entry->mutex.holder = 0;
1311                         entry->mutex.count = 0;
1312                         entry->mutex.muxWaiters = 0;
1313
1314                 } else {
1315                         while (entry->next != 0 && entry->object != object)
1316                                 entry = entry->next;
1317
1318                         if (entry->object != object) {
1319                                 entry->next = firstFreeOverflowEntry;
1320                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1321
1322                                 entry = entry->next;
1323                                 entry->object = 0;
1324                                 entry->next = 0;
1325                                 assert(entry->conditionCount == 0);
1326                         }
1327                 }
1328
1329         } else {
1330                 entry->mutex.holder = 0;
1331                 entry->mutex.count = 0;
1332                 entry->mutex.muxWaiters = 0;
1333         }
1334
1335         if (entry->object == 0)
1336                 entry->object = object;
1337         
1338         internal_lock_mutex(&entry->mutex);
1339 }
1340 #endif
1341
1342
1343 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1344 /*
1345  * Unlocks the mutex of an object.
1346  */
1347 void internal_unlock_mutex_for_object (java_objectheader *object)
1348 {
1349         int hashValue;
1350         mutexHashEntry *entry;
1351
1352         hashValue = MUTEX_HASH_VALUE(object);
1353         entry = &mutexHashTable[hashValue];
1354
1355         if (entry->object == object) {
1356                 internal_unlock_mutex(&entry->mutex);
1357
1358         } else {
1359                 while (entry->next != 0 && entry->next->object != object)
1360                         entry = entry->next;
1361
1362                 assert(entry->next != 0);
1363
1364                 internal_unlock_mutex(&entry->next->mutex);
1365
1366                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1367                         mutexHashEntry *unlinked = entry->next;
1368
1369                         entry->next = unlinked->next;
1370                         unlinked->next = firstFreeOverflowEntry;
1371                         firstFreeOverflowEntry = unlinked;
1372                 }
1373         }
1374 }
1375 #endif
1376
1377
1378 #if defined(USE_THREADS)
1379 void builtin_monitorenter(java_objectheader *o)
1380 {
1381 #if !defined(NATIVE_THREADS)
1382         int hashValue;
1383
1384         ++blockInts;
1385
1386         hashValue = MUTEX_HASH_VALUE(o);
1387         if (mutexHashTable[hashValue].object == o 
1388                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1389                 ++mutexHashTable[hashValue].mutex.count;
1390         else
1391                 internal_lock_mutex_for_object(o);
1392
1393         --blockInts;
1394 #else
1395         monitorEnter((threadobject *) THREADOBJECT, o);
1396 #endif
1397 }
1398 #endif
1399
1400
1401 #if defined(USE_THREADS)
1402 /*
1403  * Locks the class object - needed for static synchronized methods.
1404  * The use_class_as_object call is needed in order to circumvent a
1405  * possible deadlock with builtin_monitorenter called by another
1406  * thread calling use_class_as_object.
1407  */
1408 void builtin_staticmonitorenter(classinfo *c)
1409 {
1410         use_class_as_object(c);
1411         builtin_monitorenter(&c->header);
1412 }
1413 #endif
1414
1415
1416 #if defined(USE_THREADS)
1417 void *builtin_monitorexit(java_objectheader *o)
1418 {
1419 #if !defined(NATIVE_THREADS)
1420         int hashValue;
1421
1422         ++blockInts;
1423
1424         hashValue = MUTEX_HASH_VALUE(o);
1425         if (mutexHashTable[hashValue].object == o) {
1426                 if (mutexHashTable[hashValue].mutex.count == 1
1427                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1428                         internal_unlock_mutex_for_object(o);
1429                 else
1430                         --mutexHashTable[hashValue].mutex.count;
1431
1432         } else
1433                 internal_unlock_mutex_for_object(o);
1434
1435         --blockInts;
1436         return o;
1437 #else
1438         monitorExit((threadobject *) THREADOBJECT, o);
1439         return o;
1440 #endif
1441 }
1442 #endif
1443
1444
1445 /*****************************************************************************
1446                           MISCELLANEOUS HELPER FUNCTIONS
1447 *****************************************************************************/
1448
1449
1450
1451 /*********** Functions for integer divisions *****************************
1452  
1453         On some systems (eg. DEC ALPHA), integer division is not supported by the
1454         CPU. These helper functions implement the missing functionality.
1455
1456 ******************************************************************************/
1457
1458 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1459 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1460
1461
1462 /************** Functions for long arithmetics *******************************
1463
1464         On systems where 64 bit Integers are not supported by the CPU, these
1465         functions are needed.
1466
1467 ******************************************************************************/
1468
1469
1470 s8 builtin_ladd(s8 a, s8 b)
1471
1472 #if U8_AVAILABLE
1473         return a + b; 
1474 #else
1475         return builtin_i2l(0);
1476 #endif
1477 }
1478
1479 s8 builtin_lsub(s8 a, s8 b) 
1480
1481 #if U8_AVAILABLE
1482         return a - b; 
1483 #else
1484         return builtin_i2l(0);
1485 #endif
1486 }
1487
1488 s8 builtin_lmul(s8 a, s8 b) 
1489
1490 #if U8_AVAILABLE
1491         return a * b; 
1492 #else
1493         return builtin_i2l(0);
1494 #endif
1495 }
1496
1497 s8 builtin_ldiv(s8 a, s8 b) 
1498
1499 #if U8_AVAILABLE
1500         return a / b; 
1501 #else
1502         return builtin_i2l(0);
1503 #endif
1504 }
1505
1506 s8 builtin_lrem(s8 a, s8 b) 
1507
1508 #if U8_AVAILABLE
1509         return a % b; 
1510 #else
1511         return builtin_i2l(0);
1512 #endif
1513 }
1514
1515 s8 builtin_lshl(s8 a, s4 b) 
1516
1517 #if U8_AVAILABLE
1518         return a << (b & 63);
1519 #else
1520         return builtin_i2l(0);
1521 #endif
1522 }
1523
1524 s8 builtin_lshr(s8 a, s4 b) 
1525
1526 #if U8_AVAILABLE
1527         return a >> (b & 63);
1528 #else
1529         return builtin_i2l(0);
1530 #endif
1531 }
1532
1533 s8 builtin_lushr(s8 a, s4 b) 
1534
1535 #if U8_AVAILABLE
1536         return ((u8) a) >> (b & 63);
1537 #else
1538         return builtin_i2l(0);
1539 #endif
1540 }
1541
1542 s8 builtin_land(s8 a, s8 b) 
1543
1544 #if U8_AVAILABLE
1545         return a & b; 
1546 #else
1547         return builtin_i2l(0);
1548 #endif
1549 }
1550
1551 s8 builtin_lor(s8 a, s8 b) 
1552
1553 #if U8_AVAILABLE
1554         return a | b; 
1555 #else
1556         return builtin_i2l(0);
1557 #endif
1558 }
1559
1560 s8 builtin_lxor(s8 a, s8 b) 
1561
1562 #if U8_AVAILABLE
1563         return a ^ b; 
1564 #else
1565         return builtin_i2l(0);
1566 #endif
1567 }
1568
1569 s8 builtin_lneg(s8 a) 
1570
1571 #if U8_AVAILABLE
1572         return -a;
1573 #else
1574         return builtin_i2l(0);
1575 #endif
1576 }
1577
1578 s4 builtin_lcmp(s8 a, s8 b) 
1579
1580 #if U8_AVAILABLE
1581         if (a < b) return -1;
1582         if (a > b) return 1;
1583         return 0;
1584 #else
1585         return 0;
1586 #endif
1587 }
1588
1589
1590
1591
1592
1593 /*********** Functions for floating point operations *************************/
1594
1595 float builtin_fadd(float a, float b)
1596 {
1597         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1598         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1599         if (finitef(a)) {
1600                 if (finitef(b))
1601                         return a + b;
1602                 else
1603                         return b;
1604         }
1605         else {
1606                 if (finitef(b))
1607                         return a;
1608                 else {
1609                         if (copysignf(1.0, a) == copysignf(1.0, b))
1610                                 return a;
1611                         else
1612                                 return intBitsToFloat(FLT_NAN);
1613                 }
1614         }
1615 }
1616
1617
1618 float builtin_fsub(float a, float b)
1619 {
1620         return builtin_fadd(a, builtin_fneg(b));
1621 }
1622
1623
1624 float builtin_fmul(float a, float b)
1625 {
1626         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1627         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1628         if (finitef(a)) {
1629                 if (finitef(b)) return a * b;
1630                 else {
1631                         if (a == 0) return intBitsToFloat(FLT_NAN);
1632                         else return copysignf(b, copysignf(1.0, b)*a);
1633                 }
1634         }
1635         else {
1636                 if (finitef(b)) {
1637                         if (b == 0) return intBitsToFloat(FLT_NAN);
1638                         else return copysignf(a, copysignf(1.0, a)*b);
1639                 }
1640                 else {
1641                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1642                 }
1643         }
1644 }
1645
1646
1647 float builtin_fdiv(float a, float b)
1648 {
1649         if (finitef(a) && finitef(b)) {
1650                 if (b != 0)
1651                         return a / b;
1652                 else {
1653                         if (a > 0)
1654                                 return intBitsToFloat(FLT_POSINF);
1655                         else if (a < 0)
1656                                 return intBitsToFloat(FLT_NEGINF);
1657                 }
1658         }
1659         return intBitsToFloat(FLT_NAN);
1660 }
1661
1662
1663 float builtin_frem(float a, float b)
1664 {
1665         return fmodf(a, b);
1666 }
1667
1668
1669 float builtin_fneg(float a)
1670 {
1671         if (isnanf(a)) return a;
1672         else {
1673                 if (finitef(a)) return -a;
1674                 else return copysignf(a, -copysignf(1.0, a));
1675         }
1676 }
1677
1678
1679 s4 builtin_fcmpl(float a, float b)
1680 {
1681         if (isnanf(a)) return -1;
1682         if (isnanf(b)) return -1;
1683         if (!finitef(a) || !finitef(b)) {
1684                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1685                 b = finitef(b) ? 0 : copysignf(1.0, b);
1686         }
1687         if (a > b) return 1;
1688         if (a == b) return 0;
1689         return -1;
1690 }
1691
1692
1693 s4 builtin_fcmpg(float a, float b)
1694 {
1695         if (isnanf(a)) return 1;
1696         if (isnanf(b)) return 1;
1697         if (!finitef(a) || !finitef(b)) {
1698                 a = finitef(a) ? 0 : copysignf(1.0, a);
1699                 b = finitef(b) ? 0 : copysignf(1.0, b);
1700         }
1701         if (a > b) return 1;
1702         if (a == b) return 0;
1703         return -1;
1704 }
1705
1706
1707
1708 /************************* Functions for doubles ****************************/
1709
1710 double builtin_dadd(double a, double b)
1711 {
1712         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1713         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1714         if (finite(a)) {
1715                 if (finite(b)) return a + b;
1716                 else return b;
1717         }
1718         else {
1719                 if (finite(b)) return a;
1720                 else {
1721                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1722                         else return longBitsToDouble(DBL_NAN);
1723                 }
1724         }
1725 }
1726
1727
1728 double builtin_dsub(double a, double b)
1729 {
1730         return builtin_dadd(a, builtin_dneg(b));
1731 }
1732
1733
1734 double builtin_dmul(double a, double b)
1735 {
1736         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1737         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1738         if (finite(a)) {
1739                 if (finite(b)) return a * b;
1740                 else {
1741                         if (a == 0) return longBitsToDouble(DBL_NAN);
1742                         else return copysign(b, copysign(1.0, b) * a);
1743                 }
1744         }
1745         else {
1746                 if (finite(b)) {
1747                         if (b == 0) return longBitsToDouble(DBL_NAN);
1748                         else return copysign(a, copysign(1.0, a) * b);
1749                 }
1750                 else {
1751                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1752                 }
1753         }
1754 }
1755
1756
1757 double builtin_ddiv(double a, double b)
1758 {
1759         if (finite(a)) {
1760                 if (finite(b)) {
1761                         return a / b;
1762
1763                 } else {
1764                         if (isnan(b))
1765                                 return longBitsToDouble(DBL_NAN);
1766                         else
1767                                 return copysign(0.0, b);
1768                 }
1769
1770         } else {
1771                 if (finite(b)) {
1772                         if (a > 0)
1773                                 return longBitsToDouble(DBL_POSINF);
1774                         else if (a < 0)
1775                                 return longBitsToDouble(DBL_NEGINF);
1776
1777                 } else
1778                         return longBitsToDouble(DBL_NAN);
1779         }
1780
1781 /*      if (finite(a) && finite(b)) { */
1782 /*              if (b != 0) */
1783 /*                      return a / b; */
1784 /*              else { */
1785 /*                      if (a > 0) */
1786 /*                              return longBitsToDouble(DBL_POSINF); */
1787 /*                      else if (a < 0) */
1788 /*                              return longBitsToDouble(DBL_NEGINF); */
1789 /*              } */
1790 /*      } */
1791
1792         /* keep compiler happy */
1793         return 0;
1794 }
1795
1796
1797 double builtin_drem(double a, double b)
1798 {
1799         return fmod(a, b);
1800 }
1801
1802
1803 double builtin_dneg(double a)
1804 {
1805         if (isnan(a)) return a;
1806         else {
1807                 if (finite(a)) return -a;
1808                 else return copysign(a, -copysign(1.0, a));
1809         }
1810 }
1811
1812
1813 s4 builtin_dcmpl(double a, double b)
1814 {
1815         if (isnan(a)) return -1;
1816         if (isnan(b)) return -1;
1817         if (!finite(a) || !finite(b)) {
1818                 a = finite(a) ? 0 : copysign(1.0, a);
1819                 b = finite(b) ? 0 : copysign(1.0, b);
1820         }
1821         if (a > b) return 1;
1822         if (a == b) return 0;
1823         return -1;
1824 }
1825
1826
1827 s4 builtin_dcmpg(double a, double b)
1828 {
1829         if (isnan(a)) return 1;
1830         if (isnan(b)) return 1;
1831         if (!finite(a) || !finite(b)) {
1832                 a = finite(a) ? 0 : copysign(1.0, a);
1833                 b = finite(b) ? 0 : copysign(1.0, b);
1834         }
1835         if (a > b) return 1;
1836         if (a == b) return 0;
1837         return -1;
1838 }
1839
1840
1841 /*********************** Conversion operations ****************************/
1842
1843 s8 builtin_i2l(s4 i)
1844 {
1845 #if U8_AVAILABLE
1846         return i;
1847 #else
1848         s8 v;
1849         v.high = 0;
1850         v.low = i;
1851         return v;
1852 #endif
1853 }
1854
1855
1856 float builtin_i2f(s4 a)
1857 {
1858         float f = (float) a;
1859         return f;
1860 }
1861
1862
1863 double builtin_i2d(s4 a)
1864 {
1865         double d = (double) a;
1866         return d;
1867 }
1868
1869
1870 s4 builtin_l2i(s8 l)
1871 {
1872 #if U8_AVAILABLE
1873         return (s4) l;
1874 #else
1875         return l.low;
1876 #endif
1877 }
1878
1879
1880 float builtin_l2f(s8 a)
1881 {
1882 #if U8_AVAILABLE
1883         float f = (float) a;
1884         return f;
1885 #else
1886         return 0.0;
1887 #endif
1888 }
1889
1890
1891 double builtin_l2d(s8 a)
1892 {
1893 #if U8_AVAILABLE
1894         double d = (double) a;
1895         return d;
1896 #else
1897         return 0.0;
1898 #endif
1899 }
1900
1901
1902 s4 builtin_f2i(float a) 
1903 {
1904
1905         return builtin_d2i((double) a);
1906
1907         /*      float f;
1908         
1909                 if (isnanf(a))
1910                 return 0;
1911                 if (finitef(a)) {
1912                 if (a > 2147483647)
1913                 return 2147483647;
1914                 if (a < (-2147483648))
1915                 return (-2147483648);
1916                 return (s4) a;
1917                 }
1918                 f = copysignf((float) 1.0, a);
1919                 if (f > 0)
1920                 return 2147483647;
1921                 return (-2147483648); */
1922 }
1923
1924
1925 s8 builtin_f2l(float a)
1926 {
1927
1928         return builtin_d2l((double) a);
1929
1930         /*      float f;
1931         
1932                 if (finitef(a)) {
1933                 if (a > 9223372036854775807L)
1934                 return 9223372036854775807L;
1935                 if (a < (-9223372036854775808L))
1936                 return (-9223372036854775808L);
1937                 return (s8) a;
1938                 }
1939                 if (isnanf(a))
1940                 return 0;
1941                 f = copysignf((float) 1.0, a);
1942                 if (f > 0)
1943                 return 9223372036854775807L;
1944                 return (-9223372036854775808L); */
1945 }
1946
1947
1948 double builtin_f2d(float a)
1949 {
1950         if (finitef(a)) return (double) a;
1951         else {
1952                 if (isnanf(a))
1953                         return longBitsToDouble(DBL_NAN);
1954                 else
1955                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1956         }
1957 }
1958
1959
1960 s4 builtin_d2i(double a) 
1961
1962         double d;
1963         
1964         if (finite(a)) {
1965                 if (a >= 2147483647)
1966                         return 2147483647;
1967                 if (a <= (-2147483647-1))
1968                         return (-2147483647-1);
1969                 return (s4) a;
1970         }
1971         if (isnan(a))
1972                 return 0;
1973         d = copysign(1.0, a);
1974         if (d > 0)
1975                 return 2147483647;
1976         return (-2147483647-1);
1977 }
1978
1979
1980 s8 builtin_d2l(double a)
1981 {
1982         double d;
1983         
1984         if (finite(a)) {
1985                 if (a >= 9223372036854775807LL)
1986                         return 9223372036854775807LL;
1987                 if (a <= (-9223372036854775807LL-1))
1988                         return (-9223372036854775807LL-1);
1989                 return (s8) a;
1990         }
1991         if (isnan(a))
1992                 return 0;
1993         d = copysign(1.0, a);
1994         if (d > 0)
1995                 return 9223372036854775807LL;
1996         return (-9223372036854775807LL-1);
1997 }
1998
1999
2000 float builtin_d2f(double a)
2001 {
2002         if (finite(a))
2003                 return (float) a;
2004         else {
2005                 if (isnan(a))
2006                         return intBitsToFloat(FLT_NAN);
2007                 else
2008                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2009         }
2010 }
2011
2012
2013 /* used to convert FLT_xxx defines into float values */
2014
2015 inline float intBitsToFloat(s4 i)
2016 {
2017         imm_union imb;
2018
2019         imb.i = i;
2020         return imb.f;
2021 }
2022
2023
2024 /* used to convert DBL_xxx defines into double values */
2025
2026 inline float longBitsToDouble(s8 l)
2027 {
2028         imm_union imb;
2029
2030         imb.l = l;
2031         return imb.d;
2032 }
2033
2034
2035 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2036 {
2037         return (java_arrayheader *)
2038                 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2039 }
2040
2041
2042 s4 builtin_dummy()
2043 {
2044         panic("Internal error: builtin_dummy called (native function is missing)");
2045         return 0; /* for the compiler */
2046 }
2047
2048
2049 /* builtin_asm_get_exceptionptrptr *********************************************
2050
2051    this is a wrapper for calls from asmpart
2052
2053 *******************************************************************************/
2054
2055 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2056 java_objectheader **builtin_asm_get_exceptionptrptr()
2057 {
2058         return builtin_get_exceptionptrptr();
2059 }
2060 #endif
2061
2062
2063 methodinfo *builtin_asm_get_threadrootmethod()
2064 {
2065         return *threadrootmethod;
2066 }
2067
2068
2069 inline void* builtin_asm_get_stackframeinfo()
2070 {
2071 /*log_text("builtin_asm_get_stackframeinfo()");*/
2072 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2073         return &THREADINFO->_stackframeinfo;
2074 #else
2075 #if defined(__GNUC__)
2076 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2077 #endif
2078                 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2079 #endif
2080 }
2081
2082 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2083 /*      stacktraceelement *el;*/
2084         size_t s;
2085         s=(end-begin);
2086         /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2087         *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2088 #if 0
2089         *el=MNEW(stacktraceelement,s+1); /*GC*/
2090 #endif
2091         memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2092         (*el)[s].method=0;
2093 #if defined(__GNUC__)
2094 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2095 #endif
2096         (*el)[s].linenumber=-1; /* -1 can never be reched otherwise, since line numbers are only u2, so it is save to use that as flag */
2097         return *el;
2098 }
2099
2100 /*
2101  * These are local overrides for various environment variables in Emacs.
2102  * Please do not remove this and leave it at the end of the file, where
2103  * Emacs will automagically detect them.
2104  * ---------------------------------------------------------------------
2105  * Local variables:
2106  * mode: c
2107  * indent-tabs-mode: t
2108  * c-basic-offset: 4
2109  * tab-width: 4
2110  * End:
2111  */