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 (guint32 al, guint32 ah, guint32 bl, guint32 bh)
89 // fixme: this is incredible slow
94 res = (guint64)al * (guint64)bl;
96 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
101 res += ((guint64)t1) << 32;
106 mono_raise_exception (mono_get_exception_overflow ());
112 mono_llmult_ovf (guint32 al, gint32 ah, guint32 bl, gint32 bh)
115 Use Karatsuba algorithm where:
116 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
117 where Ah is the "high half" (most significant 32 bits) of a and
118 where Al is the "low half" (least significant 32 bits) of a and
119 where Bh is the "high half" of b and Bl is the "low half" and
120 where R is the Radix or "size of the half" (in our case 32 bits)
122 Note, for the product of two 64 bit numbers to fit into a 64
123 result, ah and/or bh must be 0. This will save us from doing
124 the AhBh term at all.
126 Also note that we refactor so that we don't overflow 64 bits with
127 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
135 /* need to work with absoulte values, so find out what the
136 resulting sign will be and convert any negative numbers
137 from two's complement
141 /* flip the bits and add 1 */
152 /* flip the bits and add 1 */
162 /* we overflow for sure if both upper halves are greater
163 than zero because we would need to shift their
164 product 64 bits to the left and that will not fit
165 in a 64 bit result */
167 goto raise_exception;
169 /* do the AlBl term first */
170 t1 = (gint64)al * (gint64)bl;
174 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
175 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
177 /* check for overflow */
178 if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
179 goto raise_exception;
184 goto raise_exception;
192 mono_raise_exception (mono_get_exception_overflow ());
197 mono_lldiv (gint64 a, gint64 b)
205 mono_llrem (gint64 a, gint64 b)
213 mono_lldiv_un (guint64 a, guint64 b)
221 mono_llrem_un (guint64 a, guint64 b)
229 mono_lshl (guint64 a, gint32 shamt)
233 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
236 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
242 mono_lshr_un (guint64 a, gint32 shamt)
246 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
249 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
255 mono_lshr (gint64 a, gint32 shamt)
259 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
262 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
268 * ves_array_element_address:
269 * @this: a pointer to the array object
271 * Returns: the address of an array element.
274 ves_array_element_address (MonoArray *this, ...)
278 int i, ind, esize, realidx;
283 g_assert (this != NULL);
287 class = this->obj.vtable->klass;
289 g_assert (this->bounds != NULL);
291 esize = mono_array_element_size (class);
292 ind = va_arg(ap, int);
293 ind -= (int)this->bounds [0].lower_bound;
294 if ((guint32)ind >= (guint32)this->bounds [0].length)
295 mono_raise_exception (mono_get_exception_index_out_of_range ());
296 for (i = 1; i < class->rank; i++) {
297 realidx = va_arg(ap, int) - (int)this->bounds [i].lower_bound;
298 if ((guint32)realidx >= (guint32)this->bounds [i].length)
299 mono_raise_exception (mono_get_exception_index_out_of_range ());
300 ind *= this->bounds [i].length;
305 ea = (gpointer*)((char*)this->vector + esize);
313 mono_array_new_va (MonoMethod *cm, ...)
315 MonoDomain *domain = mono_domain_get ();
318 guint32 *lower_bounds;
325 pcount = cm->signature->param_count;
326 rank = cm->klass->rank;
330 lengths = alloca (sizeof (guint32) * pcount);
331 for (i = 0; i < pcount; ++i)
332 lengths [i] = d = va_arg(ap, int);
334 if (rank == pcount) {
335 /* Only lengths provided. */
338 g_assert (pcount == (rank * 2));
339 /* lower bounds are first. */
340 lower_bounds = lengths;
345 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
349 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
356 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
358 mono_class_init (field->parent);
360 vtable = mono_class_vtable (domain, field->parent);
361 if (!vtable->initialized)
362 mono_runtime_class_init (vtable);
364 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
366 if (!domain->thread_static_fields || !(addr = g_hash_table_lookup (domain->thread_static_fields, field)))
367 addr = (char*)vtable->data + field->offset;
369 addr = mono_threads_get_static_data (GPOINTER_TO_UINT (addr));
375 mono_ldtoken_wrapper (MonoImage *image, int token)
377 MonoClass *handle_class;
381 res = mono_ldtoken (image, token, &handle_class);
382 mono_class_init (handle_class);
388 mono_fconv_u8 (double v)
390 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
395 mono_fconv_u4 (double v)
397 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
402 mono_fconv_ovf_i8 (double v)
410 if (isnan(v) || v != res) {
411 mono_raise_exception (mono_get_exception_overflow ());
417 mono_fconv_ovf_u8 (double v)
425 if (isnan(v) || v != res) {
426 mono_raise_exception (mono_get_exception_overflow ());