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 helper_stelem_ref_check (MonoArray *array, MonoObject *val)
80 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
81 mono_raise_exception (mono_get_exception_array_type_mismatch ());
85 mono_llmult (gint64 a, gint64 b)
87 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
92 mono_llmult_ovf_un (guint64 a, guint64 b)
102 // fixme: this is incredible slow
105 goto raise_exception;
107 res = (guint64)al * (guint64)bl;
109 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
112 goto raise_exception;
114 res += ((guint64)t1) << 32;
119 mono_raise_exception (mono_get_exception_overflow ());
125 mono_llmult_ovf (gint64 a, gint64 b)
132 Use Karatsuba algorithm where:
133 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
134 where Ah is the "high half" (most significant 32 bits) of a and
135 where Al is the "low half" (least significant 32 bits) of a and
136 where Bh is the "high half" of b and Bl is the "low half" and
137 where R is the Radix or "size of the half" (in our case 32 bits)
139 Note, for the product of two 64 bit numbers to fit into a 64
140 result, ah and/or bh must be 0. This will save us from doing
141 the AhBh term at all.
143 Also note that we refactor so that we don't overflow 64 bits with
144 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
152 /* need to work with absoulte values, so find out what the
153 resulting sign will be and convert any negative numbers
154 from two's complement
158 /* flip the bits and add 1 */
169 /* flip the bits and add 1 */
179 /* we overflow for sure if both upper halves are greater
180 than zero because we would need to shift their
181 product 64 bits to the left and that will not fit
182 in a 64 bit result */
184 goto raise_exception;
186 /* do the AlBl term first */
187 t1 = (gint64)al * (gint64)bl;
191 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
192 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
194 /* check for overflow */
195 if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
196 goto raise_exception;
201 goto raise_exception;
209 mono_raise_exception (mono_get_exception_overflow ());
214 mono_lldiv (gint64 a, gint64 b)
222 mono_llrem (gint64 a, gint64 b)
230 mono_lldiv_un (guint64 a, guint64 b)
238 mono_llrem_un (guint64 a, guint64 b)
246 mono_lshl (guint64 a, gint32 shamt)
250 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
253 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
259 mono_lshr_un (guint64 a, gint32 shamt)
263 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
266 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
272 mono_lshr (gint64 a, gint32 shamt)
276 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
279 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
285 * ves_array_element_address:
286 * @this: a pointer to the array object
288 * Returns: the address of an array element.
291 ves_array_element_address (MonoArray *this, ...)
295 int i, ind, esize, realidx;
300 g_assert (this != NULL);
304 class = this->obj.vtable->klass;
306 g_assert (this->bounds != NULL);
308 esize = mono_array_element_size (class);
309 ind = va_arg(ap, int);
310 ind -= (int)this->bounds [0].lower_bound;
311 if ((guint32)ind >= (guint32)this->bounds [0].length)
312 mono_raise_exception (mono_get_exception_index_out_of_range ());
313 for (i = 1; i < class->rank; i++) {
314 realidx = va_arg(ap, int) - (int)this->bounds [i].lower_bound;
315 if ((guint32)realidx >= (guint32)this->bounds [i].length)
316 mono_raise_exception (mono_get_exception_index_out_of_range ());
317 ind *= this->bounds [i].length;
322 ea = (gpointer*)((char*)this->vector + esize);
330 mono_array_new_va (MonoMethod *cm, ...)
332 MonoDomain *domain = mono_domain_get ();
335 guint32 *lower_bounds;
342 pcount = cm->signature->param_count;
343 rank = cm->klass->rank;
347 lengths = alloca (sizeof (guint32) * pcount);
348 for (i = 0; i < pcount; ++i)
349 lengths [i] = d = va_arg(ap, int);
351 if (rank == pcount) {
352 /* Only lengths provided. */
355 g_assert (pcount == (rank * 2));
356 /* lower bounds are first. */
357 lower_bounds = lengths;
362 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
366 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
373 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
375 mono_class_init (field->parent);
377 vtable = mono_class_vtable (domain, field->parent);
378 if (!vtable->initialized)
379 mono_runtime_class_init (vtable);
381 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
383 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
384 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
386 addr = (char*)vtable->data + field->offset;
392 mono_ldtoken_wrapper (MonoImage *image, int token)
394 MonoClass *handle_class;
398 res = mono_ldtoken (image, token, &handle_class);
399 mono_class_init (handle_class);
405 mono_fconv_u8 (double v)
407 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
411 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
413 mono_fconv_i8 (double v)
415 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
421 mono_fconv_u4 (double v)
423 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
428 mono_fconv_ovf_i8 (double v)
436 if (isnan(v) || v != res) {
437 mono_raise_exception (mono_get_exception_overflow ());
443 mono_fconv_ovf_u8 (double v)
451 if (isnan(v) || v != res) {
452 mono_raise_exception (mono_get_exception_overflow ());
457 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
459 mono_lconv_to_r8 (gint64 a)
465 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
467 mono_lconv_to_r4 (gint64 a)
473 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
475 mono_lconv_to_r8_un (guint64 a)