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