2 * jit-icalls.c: internal calls used by the JIT
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2002 Ximian, Inc.
14 mono_ldftn (MonoMethod *method)
20 addr = mono_compile_method (method);
26 mono_ldvirtfn (MonoObject *obj, MonoMethod *method)
30 method = mono_object_get_virtual_method (obj, method);
31 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
32 method = mono_marshal_get_synchronized_wrapper (method);
34 return mono_ldftn (method);
38 helper_initobj (void *addr, int size)
42 memset (addr, 0, size);
46 helper_memcpy (void *addr, void *src, int size)
50 memcpy (addr, src, size);
54 helper_memset (void *addr, int val, int size)
58 memset (addr, val, size);
62 helper_stelem_ref (MonoArray *array, int index, MonoObject *val)
66 if (index >= array->max_length)
67 mono_raise_exception (mono_get_exception_index_out_of_range ());
69 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
70 mono_raise_exception (mono_get_exception_array_type_mismatch ());
72 mono_array_set (array, gpointer, index, val);
76 mono_llmult (gint64 a, gint64 b)
78 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
83 mono_llmult_ovf_un (guint64 a, guint64 b)
93 // fixme: this is incredible slow
98 res = (guint64)al * (guint64)bl;
100 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
103 goto raise_exception;
105 res += ((guint64)t1) << 32;
110 mono_raise_exception (mono_get_exception_overflow ());
116 mono_llmult_ovf (gint64 a, gint64 b)
123 Use Karatsuba algorithm where:
124 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
125 where Ah is the "high half" (most significant 32 bits) of a and
126 where Al is the "low half" (least significant 32 bits) of a and
127 where Bh is the "high half" of b and Bl is the "low half" and
128 where R is the Radix or "size of the half" (in our case 32 bits)
130 Note, for the product of two 64 bit numbers to fit into a 64
131 result, ah and/or bh must be 0. This will save us from doing
132 the AhBh term at all.
134 Also note that we refactor so that we don't overflow 64 bits with
135 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
143 /* need to work with absoulte values, so find out what the
144 resulting sign will be and convert any negative numbers
145 from two's complement
149 /* flip the bits and add 1 */
160 /* flip the bits and add 1 */
170 /* we overflow for sure if both upper halves are greater
171 than zero because we would need to shift their
172 product 64 bits to the left and that will not fit
173 in a 64 bit result */
175 goto raise_exception;
177 /* do the AlBl term first */
178 t1 = (gint64)al * (gint64)bl;
182 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
183 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
185 /* check for overflow */
186 if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
187 goto raise_exception;
192 goto raise_exception;
200 mono_raise_exception (mono_get_exception_overflow ());
205 mono_lldiv (gint64 a, gint64 b)
213 mono_llrem (gint64 a, gint64 b)
221 mono_lldiv_un (guint64 a, guint64 b)
229 mono_llrem_un (guint64 a, guint64 b)
237 mono_lshl (guint64 a, gint32 shamt)
241 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
244 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
250 mono_lshr_un (guint64 a, gint32 shamt)
254 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
257 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
263 mono_lshr (gint64 a, gint32 shamt)
267 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
270 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
276 * ves_array_element_address:
277 * @this: a pointer to the array object
279 * Returns: the address of an array element.
282 ves_array_element_address (MonoArray *this, ...)
286 int i, ind, esize, realidx;
291 g_assert (this != NULL);
295 class = this->obj.vtable->klass;
297 g_assert (this->bounds != NULL);
299 esize = mono_array_element_size (class);
300 ind = va_arg(ap, int);
301 ind -= (int)this->bounds [0].lower_bound;
302 if ((guint32)ind >= (guint32)this->bounds [0].length)
303 mono_raise_exception (mono_get_exception_index_out_of_range ());
304 for (i = 1; i < class->rank; i++) {
305 realidx = va_arg(ap, int) - (int)this->bounds [i].lower_bound;
306 if ((guint32)realidx >= (guint32)this->bounds [i].length)
307 mono_raise_exception (mono_get_exception_index_out_of_range ());
308 ind *= this->bounds [i].length;
313 ea = (gpointer*)((char*)this->vector + esize);
321 mono_array_new_va (MonoMethod *cm, ...)
323 MonoDomain *domain = mono_domain_get ();
326 guint32 *lower_bounds;
333 pcount = cm->signature->param_count;
334 rank = cm->klass->rank;
338 lengths = alloca (sizeof (guint32) * pcount);
339 for (i = 0; i < pcount; ++i)
340 lengths [i] = d = va_arg(ap, int);
342 if (rank == pcount) {
343 /* Only lengths provided. */
346 g_assert (pcount == (rank * 2));
347 /* lower bounds are first. */
348 lower_bounds = lengths;
353 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
357 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
364 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
366 mono_class_init (field->parent);
368 vtable = mono_class_vtable (domain, field->parent);
369 if (!vtable->initialized)
370 mono_runtime_class_init (vtable);
372 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
374 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
375 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
377 addr = (char*)vtable->data + field->offset;
383 mono_ldtoken_wrapper (MonoImage *image, int token)
385 MonoClass *handle_class;
389 res = mono_ldtoken (image, token, &handle_class);
390 mono_class_init (handle_class);
396 mono_fconv_u8 (double v)
398 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
402 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
404 mono_fconv_i8 (double v)
406 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
412 mono_fconv_u4 (double v)
414 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
419 mono_fconv_ovf_i8 (double v)
427 if (isnan(v) || v != res) {
428 mono_raise_exception (mono_get_exception_overflow ());
434 mono_fconv_ovf_u8 (double v)
442 if (isnan(v) || v != res) {
443 mono_raise_exception (mono_get_exception_overflow ());
448 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
450 mono_lconv_to_r8 (gint64 a)
456 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
458 mono_lconv_to_r4 (gint64 a)
464 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
466 mono_lconv_to_r8_un (guint64 a)