3af19842342e54628c9a55ad0aca901b5b68d58d
[mono.git] / mono / mini / jit-icalls.c
1 /*
2  * jit-icalls.c: internal calls used by the JIT
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  */
10
11 #include <math.h>
12 #include <limits.h>
13
14 #include "jit-icalls.h"
15
16 void*
17 mono_ldftn (MonoMethod *method)
18 {
19         gpointer addr;
20
21         MONO_ARCH_SAVE_REGS;
22
23         addr = mono_create_jump_trampoline (mono_domain_get (), method, TRUE);
24
25         return mono_create_ftnptr (mono_domain_get (), addr);
26 }
27
28 /*
29  * Same as mono_ldftn, but do not add a synchronized wrapper. Used in the
30  * synchronized wrappers to avoid infinite recursion.
31  */
32 void*
33 mono_ldftn_nosync (MonoMethod *method)
34 {
35         gpointer addr;
36
37         MONO_ARCH_SAVE_REGS;
38
39         addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
40
41         return mono_create_ftnptr (mono_domain_get (), addr);
42 }
43
44 static void*
45 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
46 {
47         MonoMethod *res;
48
49         MONO_ARCH_SAVE_REGS;
50
51         if (obj == NULL)
52                 mono_raise_exception (mono_get_exception_null_reference ());
53
54         res = mono_object_get_virtual_method (obj, method);
55
56         if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
57                 MonoGenericContext context = { NULL, NULL };
58
59                 if (res->klass->generic_class)
60                         context.class_inst = res->klass->generic_class->context.class_inst;
61                 else if (res->klass->generic_container)
62                         context.class_inst = res->klass->generic_container->context.class_inst;
63                 context.method_inst = mono_method_get_context (method)->method_inst;
64
65                 res = mono_class_inflate_generic_method (res, &context);
66         }
67
68         /* FIXME: only do this for methods which can be shared! */
69         if (res->is_inflated && mono_method_get_context (res)->method_inst &&
70                         mono_class_generic_sharing_enabled (res->klass)) {
71                 res = mono_marshal_get_static_rgctx_invoke (res);
72         }
73
74         return mono_ldftn (res);
75 }
76
77 void*
78 mono_ldvirtfn (MonoObject *obj, MonoMethod *method) 
79 {
80         return ldvirtfn_internal (obj, method, FALSE);
81 }
82
83 void*
84 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method) 
85 {
86         return ldvirtfn_internal (obj, method, TRUE);
87 }
88
89 void
90 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
91 {
92         MONO_ARCH_SAVE_REGS;
93
94         if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
95                 mono_raise_exception (mono_get_exception_array_type_mismatch ());
96 }
97
98 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
99
100 gint64 
101 mono_llmult (gint64 a, gint64 b)
102 {
103         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
104         return a * b;
105 }
106
107 guint64  
108 mono_llmult_ovf_un (guint64 a, guint64 b)
109 {
110         guint32 al = a;
111         guint32 ah = a >> 32;
112         guint32 bl = b;
113         guint32 bh = b >> 32; 
114         guint64 res, t1;
115
116         MONO_ARCH_SAVE_REGS;
117
118         // fixme: this is incredible slow
119
120         if (ah && bh)
121                 goto raise_exception;
122
123         res = (guint64)al * (guint64)bl;
124
125         t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
126
127         if (t1 > 0xffffffff)
128                 goto raise_exception;
129
130         res += ((guint64)t1) << 32; 
131
132         return res;
133
134  raise_exception:
135         mono_raise_exception (mono_get_exception_overflow ());
136         return 0;
137 }
138
139 guint64  
140 mono_llmult_ovf (gint64 a, gint64 b) 
141 {
142         guint32 al = a;
143         gint32 ah = a >> 32;
144         guint32 bl = b;
145         gint32 bh = b >> 32; 
146         /*
147         Use Karatsuba algorithm where:
148                 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
149                 where Ah is the "high half" (most significant 32 bits) of a and
150                 where Al is the "low half" (least significant 32 bits) of a and
151                 where  Bh is the "high half" of b and Bl is the "low half" and
152                 where R is the Radix or "size of the half" (in our case 32 bits)
153
154         Note, for the product of two 64 bit numbers to fit into a 64
155         result, ah and/or bh must be 0.  This will save us from doing
156         the AhBh term at all.
157
158         Also note that we refactor so that we don't overflow 64 bits with 
159         intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
160         */
161
162         gint64 res, t1;
163         gint32 sign;
164
165         MONO_ARCH_SAVE_REGS;
166
167         /* need to work with absoulte values, so find out what the
168            resulting sign will be and convert any negative numbers
169            from two's complement
170         */
171         sign = ah ^ bh;
172         if (ah < 0) {
173                 if (((guint32)ah == 0x80000000) && (al == 0)) {
174                         /* This has no two's complement */
175                         if (b == 0)
176                                 return 0;
177                         else if (b == 1)
178                                 return a;
179                         else
180                                 goto raise_exception;
181                 }
182
183                 /* flip the bits and add 1 */
184                 ah ^= ~0;
185                 if (al ==  0)
186                         ah += 1;
187                 else {
188                         al ^= ~0;
189                         al +=1;
190                 }
191         }
192
193         if (bh < 0) {
194                 if (((guint32)bh == 0x80000000) && (bl == 0)) {
195                         /* This has no two's complement */
196                         if (a == 0)
197                                 return 0;
198                         else if (a == 1)
199                                 return b;
200                         else
201                                 goto raise_exception;
202                 }
203
204                 /* flip the bits and add 1 */
205                 bh ^= ~0;
206                 if (bl ==  0)
207                         bh += 1;
208                 else {
209                         bl ^= ~0;
210                         bl +=1;
211                 }
212         }
213                 
214         /* we overflow for sure if both upper halves are greater 
215            than zero because we would need to shift their 
216            product 64 bits to the left and that will not fit
217            in a 64 bit result */
218         if (ah && bh)
219                 goto raise_exception;
220         if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000)
221                 goto raise_exception;
222
223         /* do the AlBl term first */
224         t1 = (gint64)al * (gint64)bl;
225
226         res = t1;
227
228         /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
229         t1 += (gint64)(ah - al) * (gint64)(bl - bh);
230         /* check for overflow */
231         t1 <<= 32;
232         if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
233                 goto raise_exception;
234
235         res += t1;
236
237         if (res < 0)
238                 goto raise_exception;
239
240         if (sign < 0)
241                 return -res;
242         else
243                 return res;
244
245  raise_exception:
246         mono_raise_exception (mono_get_exception_overflow ());
247         return 0;
248 }
249
250 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
251
252 gint32
253 mono_idiv (gint32 a, gint32 b)
254 {
255         MONO_ARCH_SAVE_REGS;
256
257 #ifdef MONO_ARCH_NEED_DIV_CHECK
258         if (!b)
259                 mono_raise_exception (mono_get_exception_divide_by_zero ());
260         else if (b == -1 && a == (0x80000000))
261                 mono_raise_exception (mono_get_exception_arithmetic ());
262 #endif
263         return a / b;
264 }
265
266 guint32
267 mono_idiv_un (guint32 a, guint32 b)
268 {
269         MONO_ARCH_SAVE_REGS;
270
271 #ifdef MONO_ARCH_NEED_DIV_CHECK
272         if (!b)
273                 mono_raise_exception (mono_get_exception_divide_by_zero ());
274 #endif
275         return a / b;
276 }
277
278 gint32
279 mono_irem (gint32 a, gint32 b)
280 {
281         MONO_ARCH_SAVE_REGS;
282
283 #ifdef MONO_ARCH_NEED_DIV_CHECK
284         if (!b)
285                 mono_raise_exception (mono_get_exception_divide_by_zero ());
286         else if (b == -1 && a == (0x80000000))
287                 mono_raise_exception (mono_get_exception_arithmetic ());
288 #endif
289
290         return a % b;
291 }
292
293 guint32
294 mono_irem_un (guint32 a, guint32 b)
295 {
296         MONO_ARCH_SAVE_REGS;
297
298 #ifdef MONO_ARCH_NEED_DIV_CHECK
299         if (!b)
300                 mono_raise_exception (mono_get_exception_divide_by_zero ());
301 #endif
302         return a % b;
303 }
304
305 #endif
306
307 #ifdef MONO_ARCH_EMULATE_MUL_DIV
308
309 gint32
310 mono_imul (gint32 a, gint32 b)
311 {
312         MONO_ARCH_SAVE_REGS;
313
314         return a * b;
315 }
316
317 gint32
318 mono_imul_ovf (gint32 a, gint32 b)
319 {
320         gint64 res;
321
322         MONO_ARCH_SAVE_REGS;
323
324         res = (gint64)a * (gint64)b;
325
326         if ((res > 0x7fffffffL) || (res < -2147483648))
327                 mono_raise_exception (mono_get_exception_overflow ());
328
329         return res;
330 }
331
332 gint32
333 mono_imul_ovf_un (guint32 a, guint32 b)
334 {
335         guint64 res;
336
337         MONO_ARCH_SAVE_REGS;
338
339         res = (guint64)a * (guint64)b;
340
341         if ((res >> 32))
342                 mono_raise_exception (mono_get_exception_overflow ());
343
344         return res;
345 }
346 #endif
347
348 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
349 double
350 mono_fdiv (double a, double b)
351 {
352         MONO_ARCH_SAVE_REGS;
353
354         return a / b;
355 }
356 #endif
357
358 gint64 
359 mono_lldiv (gint64 a, gint64 b)
360 {
361         MONO_ARCH_SAVE_REGS;
362
363 #ifdef MONO_ARCH_NEED_DIV_CHECK
364         if (!b)
365                 mono_raise_exception (mono_get_exception_divide_by_zero ());
366         else if (b == -1 && a == (-9223372036854775807LL - 1LL))
367                 mono_raise_exception (mono_get_exception_arithmetic ());
368 #endif
369         return a / b;
370 }
371
372 gint64 
373 mono_llrem (gint64 a, gint64 b)
374 {
375         MONO_ARCH_SAVE_REGS;
376
377 #ifdef MONO_ARCH_NEED_DIV_CHECK
378         if (!b)
379                 mono_raise_exception (mono_get_exception_divide_by_zero ());
380         else if (b == -1 && a == (-9223372036854775807LL - 1LL))
381                 mono_raise_exception (mono_get_exception_arithmetic ());
382 #endif
383         return a % b;
384 }
385
386 guint64 
387 mono_lldiv_un (guint64 a, guint64 b)
388 {
389         MONO_ARCH_SAVE_REGS;
390
391 #ifdef MONO_ARCH_NEED_DIV_CHECK
392         if (!b)
393                 mono_raise_exception (mono_get_exception_divide_by_zero ());
394 #endif
395         return a / b;
396 }
397
398 guint64 
399 mono_llrem_un (guint64 a, guint64 b)
400 {
401         MONO_ARCH_SAVE_REGS;
402
403 #ifdef MONO_ARCH_NEED_DIV_CHECK
404         if (!b)
405                 mono_raise_exception (mono_get_exception_divide_by_zero ());
406 #endif
407         return a % b;
408 }
409
410 #endif
411
412 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
413
414 guint64 
415 mono_lshl (guint64 a, gint32 shamt)
416 {
417         guint64 res;
418
419         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
420         res = a << shamt;
421
422         /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
423
424         return res;
425 }
426
427 guint64 
428 mono_lshr_un (guint64 a, gint32 shamt)
429 {
430         guint64 res;
431
432         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
433         res = a >> shamt;
434
435         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
436
437         return res;
438 }
439
440 gint64 
441 mono_lshr (gint64 a, gint32 shamt)
442 {
443         gint64 res;
444
445         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
446         res = a >> shamt;
447
448         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
449
450         return res;
451 }
452
453 #endif
454
455 #ifdef MONO_ARCH_SOFT_FLOAT
456
457 double
458 mono_fsub (double a, double b)
459 {
460         return a - b;
461 }
462
463 double
464 mono_fadd (double a, double b)
465 {
466         return a + b;
467 }
468
469 double
470 mono_fmul (double a, double b)
471 {
472         return a * b;
473 }
474
475 double
476 mono_fneg (double a)
477 {
478         return -a;
479 }
480
481 double
482 mono_fconv_r4 (double a)
483 {
484         return (float)a;
485 }
486
487 double
488 mono_conv_to_r8 (int a)
489 {
490         return (double)a;
491 }
492
493 double
494 mono_conv_to_r4 (int a)
495 {
496         return (double)(float)a;
497 }
498
499 gint8
500 mono_fconv_i1 (double a)
501 {
502         return (gint8)a;
503 }
504
505 gint16
506 mono_fconv_i2 (double a)
507 {
508         return (gint16)a;
509 }
510
511 gint32
512 mono_fconv_i4 (double a)
513 {
514         return (gint32)a;
515 }
516
517 guint8
518 mono_fconv_u1 (double a)
519 {
520         return (guint8)a;
521 }
522
523 guint16
524 mono_fconv_u2 (double a)
525 {
526         return (guint16)a;
527 }
528
529 gboolean
530 mono_fcmp_eq (double a, double b)
531 {
532         return a == b;
533 }
534
535 gboolean
536 mono_fcmp_ge (double a, double b)
537 {
538         return a >= b;
539 }
540
541 gboolean
542 mono_fcmp_gt (double a, double b)
543 {
544         return a > b;
545 }
546
547 gboolean
548 mono_fcmp_le (double a, double b)
549 {
550         return a <= b;
551 }
552
553 gboolean
554 mono_fcmp_lt (double a, double b)
555 {
556         return a < b;
557 }
558
559 gboolean
560 mono_fcmp_ne_un (double a, double b)
561 {
562         return isunordered (a, b) || a != b;
563 }
564
565 gboolean
566 mono_fcmp_ge_un (double a, double b)
567 {
568         return isunordered (a, b) || a >= b;
569 }
570
571 gboolean
572 mono_fcmp_gt_un (double a, double b)
573 {
574         return isunordered (a, b) || a > b;
575 }
576
577 gboolean
578 mono_fcmp_le_un (double a, double b)
579 {
580         return isunordered (a, b) || a <= b;
581 }
582
583 gboolean
584 mono_fcmp_lt_un (double a, double b)
585 {
586         return isunordered (a, b) || a < b;
587 }
588
589 gboolean
590 mono_fceq (double a, double b)
591 {
592         return a == b;
593 }
594
595 gboolean
596 mono_fcgt (double a, double b)
597 {
598         return a > b;
599 }
600
601 gboolean
602 mono_fcgt_un (double a, double b)
603 {
604         return isunordered (a, b) || a > b;
605 }
606
607 gboolean
608 mono_fclt (double a, double b)
609 {
610         return a < b;
611 }
612
613 gboolean
614 mono_fclt_un (double a, double b)
615 {
616         return isunordered (a, b) || a < b;
617 }
618
619 double
620 mono_fload_r4 (float *ptr)
621 {
622         return *ptr;
623 }
624
625 void
626 mono_fstore_r4 (double val, float *ptr)
627 {
628         *ptr = (float)val;
629 }
630
631 /* returns the integer bitpattern that is passed in the regs or stack */
632 guint32
633 mono_fload_r4_arg (double val)
634 {
635         float v = (float)val;
636         return *(guint32*)&v;
637 }
638
639 #endif
640
641 MonoArray *
642 mono_array_new_va (MonoMethod *cm, ...)
643 {
644         MonoDomain *domain = mono_domain_get ();
645         va_list ap;
646         guint32 *lengths;
647         guint32 *lower_bounds;
648         int pcount;
649         int rank;
650         int i, d;
651
652         MONO_ARCH_SAVE_REGS;
653
654         pcount = mono_method_signature (cm)->param_count;
655         rank = cm->klass->rank;
656
657         va_start (ap, cm);
658         
659         lengths = alloca (sizeof (guint32) * pcount);
660         for (i = 0; i < pcount; ++i)
661                 lengths [i] = d = va_arg(ap, int);
662
663         if (rank == pcount) {
664                 /* Only lengths provided. */
665                 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
666                         lower_bounds = alloca (sizeof (guint32) * rank);
667                         memset (lower_bounds, 0, sizeof (guint32) * rank);
668                 } else {
669                         lower_bounds = NULL;
670                 }
671         } else {
672                 g_assert (pcount == (rank * 2));
673                 /* lower bounds are first. */
674                 lower_bounds = lengths;
675                 lengths += rank;
676         }
677         va_end(ap);
678
679         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
680 }
681
682 /* Specialized version of mono_array_new_va () which avoids varargs */
683 MonoArray *
684 mono_array_new_1 (MonoMethod *cm, guint32 length)
685 {
686         MonoDomain *domain = mono_domain_get ();
687         guint32 lengths [1];
688         guint32 *lower_bounds;
689         int pcount;
690         int rank;
691
692         MONO_ARCH_SAVE_REGS;
693
694         pcount = mono_method_signature (cm)->param_count;
695         rank = cm->klass->rank;
696
697         lengths [0] = length;
698
699         g_assert (rank == pcount);
700
701         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
702                 lower_bounds = alloca (sizeof (guint32) * rank);
703                 memset (lower_bounds, 0, sizeof (guint32) * rank);
704         } else {
705                 lower_bounds = NULL;
706         }
707
708         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
709 }
710
711 MonoArray *
712 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
713 {
714         MonoDomain *domain = mono_domain_get ();
715         guint32 lengths [2];
716         guint32 *lower_bounds;
717         int pcount;
718         int rank;
719
720         MONO_ARCH_SAVE_REGS;
721
722         pcount = mono_method_signature (cm)->param_count;
723         rank = cm->klass->rank;
724
725         lengths [0] = length1;
726         lengths [1] = length2;
727
728         g_assert (rank == pcount);
729
730         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
731                 lower_bounds = alloca (sizeof (guint32) * rank);
732                 memset (lower_bounds, 0, sizeof (guint32) * rank);
733         } else {
734                 lower_bounds = NULL;
735         }
736
737         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
738 }
739
740 gpointer
741 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
742 {
743         MonoVTable *vtable;
744         gpointer addr;
745         
746         MONO_ARCH_SAVE_REGS;
747
748         //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
749
750         mono_class_init (field->parent);
751
752         vtable = mono_class_vtable (domain, field->parent);
753         if (!vtable->initialized)
754                 mono_runtime_class_init (vtable);
755
756         //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
757
758         if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
759                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
760         else
761                 addr = (char*)vtable->data + field->offset;
762         
763         return addr;
764 }
765
766 gpointer
767 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
768 {
769         MonoClass *handle_class;
770         gpointer res;
771
772         MONO_ARCH_SAVE_REGS;
773         res = mono_ldtoken (image, token, &handle_class, context);      
774         mono_class_init (handle_class);
775
776         return res;
777 }
778
779 gpointer
780 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
781 {
782         MonoMethodSignature *sig = mono_method_signature (method);
783         MonoGenericContext *generic_context;
784
785         if (sig->is_inflated) {
786                 generic_context = mono_method_get_context (method);
787         } else {
788                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
789                 g_assert (generic_container);
790                 generic_context = &generic_container->context;
791         }
792
793         return mono_ldtoken_wrapper (image, token, generic_context);
794 }
795
796 guint64
797 mono_fconv_u8 (double v)
798 {
799         return (guint64)v;
800 }
801
802 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
803 gint64
804 mono_fconv_i8 (double v)
805 {
806         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
807         return (gint64)v;
808 }
809 #endif
810
811 guint32
812 mono_fconv_u4 (double v)
813 {
814         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
815         return (guint32)v;
816 }
817
818 #ifndef HAVE_TRUNC
819 /* Solaris doesn't have trunc */
820 #ifdef HAVE_AINTL
821 extern long double aintl (long double);
822 #define trunc aintl
823 #else
824 /* FIXME: This means we will never throw overflow exceptions */
825 #define trunc(v) res
826 #endif
827 #endif /* HAVE_TRUNC */
828
829 gint64
830 mono_fconv_ovf_i8 (double v)
831 {
832         gint64 res;
833
834         MONO_ARCH_SAVE_REGS;
835
836         res = (gint64)v;
837
838         if (isnan(v) || trunc (v) != res) {
839                 mono_raise_exception (mono_get_exception_overflow ());
840         }
841         return res;
842 }
843
844 guint64
845 mono_fconv_ovf_u8 (double v)
846 {
847         guint64 res;
848
849         MONO_ARCH_SAVE_REGS;
850 /*
851  * The soft-float implementation of some ARM devices have a buggy guin64 to double
852  * conversion that it looses precision even when the integer if fully representable
853  * as a double.
854  * 
855  * This was found with 4294967295ull, converting to double and back looses one bit of precision.
856  * 
857  * To work around this issue we test for value boundaries instead. 
858  */
859 #if defined(__arm__) && MONO_ARCH_SOFT_FLOAT 
860         if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
861                 mono_raise_exception (mono_get_exception_overflow ());
862         }
863         res = (guint64)v;
864 #else
865         res = (guint64)v;
866         if (isnan(v) || trunc (v) != res) {
867                 mono_raise_exception (mono_get_exception_overflow ());
868         }
869 #endif
870         return res;
871 }
872
873 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
874 double
875 mono_lconv_to_r8 (gint64 a)
876 {
877         return (double)a;
878 }
879 #endif
880
881 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
882 float
883 mono_lconv_to_r4 (gint64 a)
884 {
885         return (float)a;
886 }
887 #endif
888
889 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
890 double
891 mono_conv_to_r8_un (guint32 a)
892 {
893         return (double)a;
894 }
895 #endif
896
897 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
898 double
899 mono_lconv_to_r8_un (guint64 a)
900 {
901         return (double)a;
902 }
903 #endif
904
905 gpointer
906 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
907 {
908         MonoMethod *vmethod, *inflated;
909         gpointer addr;
910         MonoGenericContext *context = mono_method_get_context (method);
911
912         mono_jit_stats.generic_virtual_invocations++;
913
914         if (obj == NULL)
915                 mono_raise_exception (mono_get_exception_null_reference ());
916         vmethod = mono_object_get_virtual_method (obj, method);
917
918         /* 'vmethod' is partially inflated.  All the blanks corresponding to the type parameters of the
919            declaring class have been inflated.  We still need to fully inflate the method parameters.
920
921            FIXME: This code depends on the declaring class being fully inflated, since we inflate it twice with 
922            the same context.
923         */
924         g_assert (!vmethod->klass->generic_container);
925         g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
926         g_assert (!context->method_inst || !context->method_inst->is_open);
927         inflated = mono_class_inflate_generic_method (vmethod, context);
928         if (mono_class_generic_sharing_enabled (inflated->klass) &&
929                         mono_method_is_generic_sharable_impl (method, FALSE)) {
930                 /* The method is shared generic code, so it needs a
931                    MRGCTX. */
932                 inflated = mono_marshal_get_static_rgctx_invoke (inflated);
933         }
934         addr = mono_compile_method (inflated);
935
936         /* Since this is a virtual call, have to unbox vtypes */
937         if (obj->vtable->klass->valuetype)
938                 *this_arg = mono_object_unbox (obj);
939         else
940                 *this_arg = obj;
941
942         return addr;
943 }
944
945 MonoString*
946 mono_helper_ldstr (MonoImage *image, guint32 idx)
947 {
948         return mono_ldstr (mono_domain_get (), image, idx);
949 }
950
951 MonoString*
952 mono_helper_ldstr_mscorlib (guint32 idx)
953 {
954         return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
955 }
956
957 MonoObject*
958 mono_helper_newobj_mscorlib (guint32 idx)
959 {
960         MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx);
961         
962         g_assert (klass);
963
964         return mono_object_new (mono_domain_get (), klass);
965 }
966
967 /*
968  * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
969  * in generated code. So instead we emit a call to this function and place a gdb
970  * breakpoint here.
971  */
972 void
973 mono_break (void)
974 {
975 }
976
977 MonoException *
978 mono_create_corlib_exception_0 (guint32 token)
979 {
980         return mono_exception_from_token (mono_defaults.corlib, token);
981 }
982
983 MonoException *
984 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
985 {
986         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
987 }
988
989 MonoException *
990 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
991 {
992         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
993 }
994
995 MonoObject*
996 mono_object_castclass (MonoObject *obj, MonoClass *klass)
997 {
998         if (!obj)
999                 return NULL;
1000
1001         if (mono_object_isinst (obj, klass))
1002                 return obj;
1003
1004         mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
1005                                         "System", "InvalidCastException"));
1006
1007         return NULL;
1008 }