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