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_create_jump_trampoline (mono_domain_get (), method, TRUE);
26 * Same as mono_ldftn, but do not add a synchronized wrapper. Used in the
27 * synchronized wrappers to avoid infinite recursion.
30 mono_ldftn_nosync (MonoMethod *method)
36 addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
42 mono_ldvirtfn (MonoObject *obj, MonoMethod *method)
46 method = mono_object_get_virtual_method (obj, method);
48 return mono_ldftn (method);
52 helper_initobj (void *addr, int size)
56 memset (addr, 0, size);
60 helper_memcpy (void *addr, void *src, int size)
64 memcpy (addr, src, size);
68 helper_memset (void *addr, int val, int size)
72 memset (addr, val, size);
76 helper_stelem_ref (MonoArray *array, int index, MonoObject *val)
80 if (index >= array->max_length)
81 mono_raise_exception (mono_get_exception_index_out_of_range ());
83 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
84 mono_raise_exception (mono_get_exception_array_type_mismatch ());
86 mono_array_set (array, gpointer, index, val);
90 helper_stelem_ref_check (MonoArray *array, MonoObject *val)
94 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
95 mono_raise_exception (mono_get_exception_array_type_mismatch ());
99 mono_llmult (gint64 a, gint64 b)
101 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
106 mono_llmult_ovf_un (guint64 a, guint64 b)
109 guint32 ah = a >> 32;
111 guint32 bh = b >> 32;
116 // fixme: this is incredible slow
119 goto raise_exception;
121 res = (guint64)al * (guint64)bl;
123 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
126 goto raise_exception;
128 res += ((guint64)t1) << 32;
133 mono_raise_exception (mono_get_exception_overflow ());
139 mono_llmult_ovf (gint64 a, gint64 b)
146 Use Karatsuba algorithm where:
147 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
148 where Ah is the "high half" (most significant 32 bits) of a and
149 where Al is the "low half" (least significant 32 bits) of a and
150 where Bh is the "high half" of b and Bl is the "low half" and
151 where R is the Radix or "size of the half" (in our case 32 bits)
153 Note, for the product of two 64 bit numbers to fit into a 64
154 result, ah and/or bh must be 0. This will save us from doing
155 the AhBh term at all.
157 Also note that we refactor so that we don't overflow 64 bits with
158 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
166 /* need to work with absoulte values, so find out what the
167 resulting sign will be and convert any negative numbers
168 from two's complement
172 /* flip the bits and add 1 */
183 /* flip the bits and add 1 */
193 /* we overflow for sure if both upper halves are greater
194 than zero because we would need to shift their
195 product 64 bits to the left and that will not fit
196 in a 64 bit result */
198 goto raise_exception;
200 /* do the AlBl term first */
201 t1 = (gint64)al * (gint64)bl;
205 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
206 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
208 /* check for overflow */
209 if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
210 goto raise_exception;
215 goto raise_exception;
223 mono_raise_exception (mono_get_exception_overflow ());
228 mono_lldiv (gint64 a, gint64 b)
236 mono_llrem (gint64 a, gint64 b)
244 mono_lldiv_un (guint64 a, guint64 b)
252 mono_llrem_un (guint64 a, guint64 b)
260 mono_lshl (guint64 a, gint32 shamt)
264 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
267 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
273 mono_lshr_un (guint64 a, gint32 shamt)
277 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
280 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
286 mono_lshr (gint64 a, gint32 shamt)
290 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
293 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
299 * ves_array_element_address:
300 * @this: a pointer to the array object
302 * Returns: the address of an array element.
305 ves_array_element_address (MonoArray *this, ...)
309 int i, ind, esize, realidx;
314 g_assert (this != NULL);
318 class = this->obj.vtable->klass;
320 g_assert (this->bounds != NULL);
322 esize = mono_array_element_size (class);
323 ind = va_arg(ap, int);
324 ind -= (int)this->bounds [0].lower_bound;
325 if ((guint32)ind >= (guint32)this->bounds [0].length)
326 mono_raise_exception (mono_get_exception_index_out_of_range ());
327 for (i = 1; i < class->rank; i++) {
328 realidx = va_arg(ap, int) - (int)this->bounds [i].lower_bound;
329 if ((guint32)realidx >= (guint32)this->bounds [i].length)
330 mono_raise_exception (mono_get_exception_index_out_of_range ());
331 ind *= this->bounds [i].length;
336 ea = (gpointer*)((char*)this->vector + esize);
344 mono_array_new_va (MonoMethod *cm, ...)
346 MonoDomain *domain = mono_domain_get ();
349 guint32 *lower_bounds;
356 pcount = cm->signature->param_count;
357 rank = cm->klass->rank;
361 lengths = alloca (sizeof (guint32) * pcount);
362 for (i = 0; i < pcount; ++i)
363 lengths [i] = d = va_arg(ap, int);
365 if (rank == pcount) {
366 /* Only lengths provided. */
369 g_assert (pcount == (rank * 2));
370 /* lower bounds are first. */
371 lower_bounds = lengths;
376 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
380 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
387 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
389 mono_class_init (field->parent);
391 vtable = mono_class_vtable (domain, field->parent);
392 if (!vtable->initialized)
393 mono_runtime_class_init (vtable);
395 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
397 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
398 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
400 addr = (char*)vtable->data + field->offset;
406 mono_ldtoken_wrapper (MonoImage *image, int token)
408 MonoClass *handle_class;
412 res = mono_ldtoken (image, token, &handle_class);
413 mono_class_init (handle_class);
419 mono_fconv_u8 (double v)
421 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
425 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
427 mono_fconv_i8 (double v)
429 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
435 mono_fconv_u4 (double v)
437 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
442 /* should mostly work */
454 mono_fconv_ovf_i8 (double v)
462 if (isnan(v) || truncl (v) != res) {
463 mono_raise_exception (mono_get_exception_overflow ());
469 mono_fconv_ovf_u8 (double v)
477 if (isnan(v) || truncl (v) != res) {
478 mono_raise_exception (mono_get_exception_overflow ());
483 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
485 mono_lconv_to_r8 (gint64 a)
491 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
493 mono_lconv_to_r4 (gint64 a)
499 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
501 mono_lconv_to_r8_un (guint64 a)