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)
259 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
262 mono_lshl (guint64 a, gint32 shamt)
266 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
269 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
275 mono_lshr_un (guint64 a, gint32 shamt)
279 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
282 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
288 mono_lshr (gint64 a, gint32 shamt)
292 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
295 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
303 * ves_array_element_address:
304 * @this: a pointer to the array object
306 * Returns: the address of an array element.
309 ves_array_element_address (MonoArray *this, ...)
313 int i, ind, esize, realidx;
318 g_assert (this != NULL);
322 class = this->obj.vtable->klass;
324 g_assert (this->bounds != NULL);
326 esize = mono_array_element_size (class);
327 ind = va_arg(ap, int);
328 ind -= (int)this->bounds [0].lower_bound;
329 if ((guint32)ind >= (guint32)this->bounds [0].length)
330 mono_raise_exception (mono_get_exception_index_out_of_range ());
331 for (i = 1; i < class->rank; i++) {
332 realidx = va_arg(ap, int) - (int)this->bounds [i].lower_bound;
333 if ((guint32)realidx >= (guint32)this->bounds [i].length)
334 mono_raise_exception (mono_get_exception_index_out_of_range ());
335 ind *= this->bounds [i].length;
340 ea = (gpointer*)((char*)this->vector + esize);
348 mono_array_new_va (MonoMethod *cm, ...)
350 MonoDomain *domain = mono_domain_get ();
353 guint32 *lower_bounds;
360 pcount = cm->signature->param_count;
361 rank = cm->klass->rank;
365 lengths = alloca (sizeof (guint32) * pcount);
366 for (i = 0; i < pcount; ++i)
367 lengths [i] = d = va_arg(ap, int);
369 if (rank == pcount) {
370 /* Only lengths provided. */
373 g_assert (pcount == (rank * 2));
374 /* lower bounds are first. */
375 lower_bounds = lengths;
380 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
384 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
391 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
393 mono_class_init (field->parent);
395 vtable = mono_class_vtable (domain, field->parent);
396 if (!vtable->initialized)
397 mono_runtime_class_init (vtable);
399 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
401 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
402 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
404 addr = (char*)vtable->data + field->offset;
410 mono_ldtoken_wrapper (MonoImage *image, int token)
412 MonoClass *handle_class;
416 res = mono_ldtoken (image, token, &handle_class, NULL);
417 mono_class_init (handle_class);
423 mono_fconv_u8 (double v)
425 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
429 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
431 mono_fconv_i8 (double v)
433 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
439 mono_fconv_u4 (double v)
441 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
448 extern long double aintl (long double);
451 /* should mostly work */
459 #endif /* HAVE_AINTL */
461 #endif /* HAVE_TRUNCL */
464 mono_fconv_ovf_i8 (double v)
472 if (isnan(v) || truncl (v) != res) {
473 mono_raise_exception (mono_get_exception_overflow ());
479 mono_fconv_ovf_u8 (double v)
487 if (isnan(v) || truncl (v) != res) {
488 mono_raise_exception (mono_get_exception_overflow ());
493 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
495 mono_lconv_to_r8 (gint64 a)
501 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
503 mono_lconv_to_r4 (gint64 a)
509 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
511 mono_conv_to_r8_un (guint32 a)
517 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
519 mono_lconv_to_r8_un (guint64 a)