2008-01-24 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / tramp-s390.c
1 /*------------------------------------------------------------------*/
2 /*                                                                  */
3 /* Name        - tramp-s390.c                                       */
4 /*                                                                  */
5 /* Function    - JIT trampoline code for S/390.                     */
6 /*                                                                  */
7 /* Name        - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
8 /*                                                                  */
9 /* Date        - January, 2004                                      */
10 /*                                                                  */
11 /* Derivation  - From exceptions-x86 & exceptions-ppc               */
12 /*               Paolo Molaro (lupus@ximian.com)                    */
13 /*               Dietmar Maurer (dietmar@ximian.com)                */
14 /*                                                                  */
15 /* Copyright   - 2001 Ximian, Inc.                                  */
16 /*                                                                  */
17 /*------------------------------------------------------------------*/
18
19 /*------------------------------------------------------------------*/
20 /*                 D e f i n e s                                    */
21 /*------------------------------------------------------------------*/
22
23 #define GR_SAVE_SIZE            4*sizeof(long)
24 #define FP_SAVE_SIZE            16*sizeof(double)
25 #define METHOD_SAVE_OFFSET      S390_MINIMAL_STACK_SIZE
26 #define CREATE_GR_OFFSET        METHOD_SAVE_OFFSET+sizeof(gpointer)
27 #define CREATE_FP_OFFSET        CREATE_GR_OFFSET+GR_SAVE_SIZE
28 #define CREATE_LMF_OFFSET       CREATE_FP_OFFSET+FP_SAVE_SIZE
29 #define CREATE_STACK_SIZE       (CREATE_LMF_OFFSET+2*sizeof(long)+sizeof(MonoLMF))
30
31 /*------------------------------------------------------------------*/
32 /* Method-specific trampoline code fragment sizes                   */
33 /*------------------------------------------------------------------*/
34 #define METHOD_TRAMPOLINE_SIZE  64
35 #define JUMP_TRAMPOLINE_SIZE    64
36
37 /*========================= End of Defines =========================*/
38
39 /*------------------------------------------------------------------*/
40 /*                 I n c l u d e s                                  */
41 /*------------------------------------------------------------------*/
42
43 #include <config.h>
44 #include <glib.h>
45 #include <string.h>
46
47 #include <mono/metadata/appdomain.h>
48 #include <mono/metadata/marshal.h>
49 #include <mono/metadata/tabledefs.h>
50 #include <mono/arch/s390/s390-codegen.h>
51
52 #include "mini.h"
53 #include "mini-s390.h"
54
55 /*========================= End of Includes ========================*/
56
57 /*------------------------------------------------------------------*/
58 /*                 T y p e d e f s                                  */
59 /*------------------------------------------------------------------*/
60
61 /*========================= End of Typedefs ========================*/
62
63 /*------------------------------------------------------------------*/
64 /*                   P r o t o t y p e s                            */
65 /*------------------------------------------------------------------*/
66
67 /*========================= End of Prototypes ======================*/
68
69 /*------------------------------------------------------------------*/
70 /*                 G l o b a l   V a r i a b l e s                  */
71 /*------------------------------------------------------------------*/
72
73
74 /*====================== End of Global Variables ===================*/
75
76 /*------------------------------------------------------------------*/
77 /*                                                                  */
78 /* Name         - get_unbox_trampoline                              */
79 /*                                                                  */
80 /* Function     - Return a pointer to a trampoline which does the   */
81 /*                unboxing before calling the method.               */
82 /*                                                                  */
83 /*                When value type methods are called through the    */
84 /*                vtable we need to unbox the 'this' argument.      */
85 /*                                                                  */
86 /* Parameters   - method - Methd pointer                            */
87 /*                addr   - Pointer to native code for method        */
88 /*                                                                  */
89 /*------------------------------------------------------------------*/
90
91 static gpointer
92 get_unbox_trampoline (MonoMethod *method, gpointer addr)
93 {
94         guint8 *code, *start;
95         int this_pos = s390_r2;
96
97         start = addr;
98         if ((!mono_method_signature (method)->ret->byref) && 
99             (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)))
100                 this_pos = s390_r3;
101     
102         start = code = mono_global_codeman_reserve (28);
103
104         s390_basr (code, s390_r13, 0);
105         s390_j    (code, 4);
106         s390_word (code, addr);
107         s390_l    (code, s390_r1, 0, s390_r13, 4);
108         s390_ahi  (code, this_pos, sizeof(MonoObject));
109         s390_br   (code, s390_r1);
110
111         g_assert ((code - start) <= 28);
112
113         return start;
114 }
115
116 /*========================= End of Function ========================*/
117
118 /*------------------------------------------------------------------*/
119 /*                                                                  */
120 /* Name         - s390_magic_trampoline                             */
121 /*                                                                  */
122 /* Function     - This method is called by the function             */
123 /*                "arch_create_jit_trampoline", which in turn is    */
124 /*                called by the trampoline functions for virtual    */
125 /*                methods. After having called the JIT compiler to  */
126 /*                compile the method, it inspects the caller code   */
127 /*                to find the address of the method-specific part   */
128 /*                of the trampoline vtable slot for this method,    */
129 /*                updates it with a fragment that calls the newly   */
130 /*                compiled code and returns this address. The calls */
131 /*                generated by mono for S/390 will look like either:*/
132 /*                1. l     %r1,xxx(%rx)                             */
133 /*                   bras  %r14,%r1                                 */
134 /*                2. brasl %r14,xxxxxx                              */
135 /*                                                                  */
136 /* Parameters   - code   - Pointer into caller code                 */
137 /*                method - The method to compile                    */
138 /*                sp     - Stack pointer                            */
139 /*                                                                  */
140 /*------------------------------------------------------------------*/
141
142 static gpointer
143 s390_magic_trampoline (MonoMethod *method, guchar *code, char *sp)
144 {
145         gpointer addr;
146         gint32 displace;
147         int reg;
148         guchar* base;
149         unsigned short opcode;
150         MonoJitInfo *codeJi, 
151                     *addrJi;
152
153         addr = mono_compile_method(method);
154         g_assert(addr);
155
156
157         if (code) {
158
159                 /* The top bit needs to be ignored on S/390 */
160                 code = (guchar*)((guint32)code & 0x7fffffff);
161
162                 codeJi = mono_jit_info_table_find (mono_domain_get(), code);
163                 addrJi = mono_jit_info_table_find (mono_domain_get(), addr);
164                 if (mono_method_same_domain (codeJi, addrJi)) {
165
166                         opcode = *((unsigned short *) (code - 6));
167                         switch (opcode) {
168                         case 0x5810 :
169                                 /* This is a bras r14,r1 instruction */
170                                 code    -= 4;
171                                 reg      = *code >> 4;
172                                 displace = *((short *)code) & 0x0fff;
173                                 if (reg > 5) 
174                                         base = *((guchar **) (sp + S390_REG_SAVE_OFFSET+
175                                                                sizeof(int)*(reg-6)));
176                                 else
177                                         base = *((guchar **) ((sp - CREATE_STACK_SIZE) + 
178                                                                CREATE_GR_OFFSET +
179                                                                sizeof(int)*(reg-2)));
180
181                                 if ((method->klass->valuetype) && 
182                                     (!mono_aot_is_got_entry(code, base))) 
183                                         addr = get_unbox_trampoline(method, addr);
184
185                                 code = base + displace;
186                                 if (mono_domain_owns_vtable_slot(mono_domain_get(), 
187                                                                  code))
188                                         s390_patch(code, (guint32) addr);
189                                 break;
190                         case 0xc0e5 :
191                                 /* This is the 'brasl' instruction */
192                                 code    -= 4;
193                                 displace = ((gint32) addr - (gint32) (code - 2)) / 2;
194                                 if (mono_method_same_domain (codeJi, addrJi)) {
195                                         s390_patch (code, displace);
196                                         mono_arch_flush_icache (code, 4);
197                                 }
198                                 break;
199                         default :
200                                 g_error("Unable to patch instruction prior to %p",code);
201                         }
202                 }
203         }
204
205
206         return addr;
207 }
208
209 /*========================= End of Function ========================*/
210
211 /*------------------------------------------------------------------*/
212 /*                                                                  */
213 /* Name         - s390_class_init_trampoline                        */
214 /*                                                                  */
215 /* Function     - Initialize a class and then no-op the call to     */
216 /*                the trampoline.                                   */
217 /*                                                                  */
218 /*------------------------------------------------------------------*/
219
220 static void
221 s390_class_init_trampoline (void *vtable, guchar *code, char *sp)
222 {
223         char patch[6] = {0x47, 0x00, 0x00, 0x00, 0x07, 0x00};
224
225         mono_runtime_class_init (vtable);
226
227         code = code - 6;
228
229         memcpy(code, patch, sizeof(patch));
230 }
231
232 /*========================= End of Function ========================*/
233
234 /*------------------------------------------------------------------*/
235 /*                                                                  */
236 /* Name         - mono_arch_create_trampoline_code                            */
237 /*                                                                  */
238 /* Function     - Create the designated type of trampoline according*/
239 /*                to the 'tramp_type' parameter.                    */
240 /*                                                                  */
241 /*------------------------------------------------------------------*/
242
243 guchar*
244 mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
245 {
246
247         guint8 *buf, *code = NULL;
248         int i, offset, lmfOffset;
249
250         if(!code) {
251                 /* Now we'll create in 'buf' the S/390 trampoline code. This
252                  is the trampoline code common to all methods  */
253                 
254                 code = buf = mono_global_codeman_reserve(512);
255                 
256                 /*-----------------------------------------------------------
257                 STEP 0: First create a non-standard function prologue with a
258                 stack size big enough to save our registers.
259                 -----------------------------------------------------------*/
260                 
261                 s390_stm  (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
262                 s390_lr   (buf, s390_r11, s390_r15);
263                 s390_ahi  (buf, STK_BASE, -CREATE_STACK_SIZE);
264                 s390_st   (buf, s390_r11, 0, STK_BASE, 0);
265                 s390_st   (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET);
266                 s390_stm  (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET);
267
268                 /* Save the FP registers */
269                 offset = CREATE_FP_OFFSET;
270                 for (i = s390_f0; i <= s390_f15; ++i) {
271                         s390_std  (buf, i, 0, STK_BASE, offset);
272                         offset += 8;
273                 }
274
275                 /*----------------------------------------------------------
276                 STEP 1: call 'mono_get_lmf_addr()' to get the address of our
277                 LMF. We'll need to restore it after the call to
278                 's390_magic_trampoline' and before the call to the native
279                 method.
280                 ----------------------------------------------------------*/
281                                 
282                 s390_basr (buf, s390_r13, 0);
283                 s390_j    (buf, 4);
284                 s390_word (buf, mono_get_lmf_addr);
285                 s390_l    (buf, s390_r1, 0, s390_r13, 4);
286                 s390_basr (buf, s390_r14, s390_r1);
287
288                 /*---------------------------------------------------------------*/
289                 /* we build the MonoLMF structure on the stack - see mini-s390.h */
290                 /* Keep in sync with the code in mono_arch_emit_prolog           */
291                 /*---------------------------------------------------------------*/
292                 lmfOffset = CREATE_STACK_SIZE - sizeof(MonoLMF);
293                                                                                         
294                 s390_lr    (buf, s390_r13, STK_BASE);
295                 s390_ahi   (buf, s390_r13, lmfOffset);  
296                                                                                         
297                 /*---------------------------------------------------------------*/     
298                 /* Set lmf.lmf_addr = jit_tls->lmf                               */     
299                 /*---------------------------------------------------------------*/     
300                 s390_st    (buf, s390_r2, 0, s390_r13,                          
301                             G_STRUCT_OFFSET(MonoLMF, lmf_addr));                        
302                                                                                         
303                 /*---------------------------------------------------------------*/     
304                 /* Get current lmf                                               */     
305                 /*---------------------------------------------------------------*/     
306                 s390_l     (buf, s390_r0, 0, s390_r2, 0);                               
307                                                                                         
308                 /*---------------------------------------------------------------*/     
309                 /* Set our lmf as the current lmf                                */     
310                 /*---------------------------------------------------------------*/     
311                 s390_st    (buf, s390_r13, 0, s390_r2, 0);                              
312                                                                                         
313                 /*---------------------------------------------------------------*/     
314                 /* Have our lmf.previous_lmf point to the last lmf               */     
315                 /*---------------------------------------------------------------*/     
316                 s390_st    (buf, s390_r0, 0, s390_r13,                          
317                             G_STRUCT_OFFSET(MonoLMF, previous_lmf));                    
318                                                                                         
319                 /*---------------------------------------------------------------*/     
320                 /* save method info                                              */     
321                 /*---------------------------------------------------------------*/     
322                 s390_l     (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET);
323                 s390_st    (buf, s390_r1, 0, s390_r13,                          
324                             G_STRUCT_OFFSET(MonoLMF, method));                          
325                                                                         
326                 /*---------------------------------------------------------------*/     
327                 /* save the current SP                                           */     
328                 /*---------------------------------------------------------------*/     
329                 s390_l     (buf, s390_r1, 0, STK_BASE, 0);
330                 s390_st    (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));  
331                                                                         
332                 /*---------------------------------------------------------------*/     
333                 /* save the current IP                                           */     
334                 /*---------------------------------------------------------------*/     
335                 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
336                         s390_lhi   (buf, s390_r1, 0);
337                 } else {
338                         s390_l     (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET);
339                         s390_la    (buf, s390_r1, 0, s390_r1, 0);
340                 }
341                 s390_st    (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));  
342                                                                                         
343                 /*---------------------------------------------------------------*/     
344                 /* Save general and floating point registers                     */     
345                 /*---------------------------------------------------------------*/     
346                 s390_stm   (buf, s390_r2, s390_r12, s390_r13,                           
347                             G_STRUCT_OFFSET(MonoLMF, gregs[2]));                        
348                 for (i = 0; i < 16; i++) {                                              
349                         s390_std  (buf, i, 0, s390_r13,                                 
350                                    G_STRUCT_OFFSET(MonoLMF, fregs[i]));                 
351                 }                                                                       
352
353                 /*---------------------------------------------------------------*/
354                 /* STEP 2: call 's390_magic_trampoline()', who will compile the  */
355                 /* code and fix the method vtable entry for us                   */
356                 /*---------------------------------------------------------------*/
357                                 
358                 /* Set arguments */
359                 
360                 /* Arg 1: MonoMethod *method. It was put in r1 by the
361                 method-specific trampoline code, and then saved before the call
362                 to mono_get_lmf_addr()'. */
363                 s390_l  (buf, s390_r2, 0, STK_BASE, METHOD_SAVE_OFFSET);
364                 
365                 /* Arg 2: code (next address to the instruction that called us) */
366                 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
367                         s390_lhi (buf, s390_r3, 0);
368                 } else {
369                         s390_l  (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET);
370                 }
371                 
372                 /* Arg 3: stack pointer */
373                 s390_lr   (buf, s390_r4, STK_BASE);
374                 s390_ahi  (buf, s390_r4, CREATE_STACK_SIZE);
375                 
376                 /* Calculate call address and call
377                 's390_magic_trampoline'. Return value will be in r2 */
378                 s390_basr (buf, s390_r13, 0);
379                 s390_j    (buf, 4);
380                 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
381                         s390_word (buf, s390_class_init_trampoline);
382                 } else {
383                         s390_word (buf, s390_magic_trampoline);
384                 }
385                 s390_l    (buf, s390_r1, 0, s390_r13, 4);
386                 s390_basr (buf, s390_r14, s390_r1);
387                 
388                 /* OK, code address is now on r2. Move it to r1, so that we
389                 can restore r2 and use it from r1 later */
390                 s390_lr   (buf, s390_r1, s390_r2);
391
392                 /*----------------------------------------------------------
393                 STEP 3: Restore the LMF
394                 ----------------------------------------------------------*/
395                 restoreLMF(buf, STK_BASE, CREATE_STACK_SIZE);
396         
397                 /*----------------------------------------------------------
398                 STEP 4: call the compiled method
399                 ----------------------------------------------------------*/
400                 
401                 /* Restore registers */
402
403                 s390_lm   (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET);
404                 
405                 /* Restore the FP registers */
406                 offset = CREATE_FP_OFFSET;
407                 for (i = s390_f0; i <= s390_f15; ++i) {
408                         s390_ld  (buf, i, 0, STK_BASE, offset);
409                         offset += 8;
410                 }
411
412                 /* Restore stack pointer and jump to the code - 
413                    R14 contains the return address to our caller */
414                 s390_lr   (buf, STK_BASE, s390_r11);
415                 s390_lm   (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
416                 s390_br   (buf, s390_r1);
417
418                 /* Flush instruction cache, since we've generated code */
419                 mono_arch_flush_icache (code, buf - code);
420         
421                 /* Sanity check */
422                 g_assert ((buf - code) <= 512);
423         }
424
425         return code;
426 }
427
428 /*========================= End of Function ========================*/
429
430 /*------------------------------------------------------------------*/
431 /*                                                                  */
432 /* Name         - mono_arch_create_jump_trampoline                  */
433 /*                                                                  */
434 /* Function     - Create the designated type of trampoline according*/
435 /*                to the 'tramp_type' parameter.                    */
436 /*                                                                  */
437 /*------------------------------------------------------------------*/
438
439 MonoJitInfo *
440 mono_arch_create_jump_trampoline (MonoMethod *method)
441 {
442         guint8 *code, *buf, *tramp = NULL;
443         MonoJitInfo *ji;
444         MonoDomain *domain = mono_domain_get();
445         gint32 displace;
446
447         tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_JUMP);
448
449         mono_domain_lock (domain);
450         code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE);
451         mono_domain_unlock (domain);
452
453         s390_basr (buf, s390_r1, 0);
454         s390_j    (buf, 4);
455         s390_word (buf, method);
456         s390_l    (buf, s390_r1, 0, s390_r1, 4);
457         displace = (tramp - buf) / 2;
458         s390_jcl  (buf, S390_CC_UN, displace);
459
460         mono_arch_flush_icache (code, buf-code);
461
462         g_assert ((buf - code) <= JUMP_TRAMPOLINE_SIZE);
463         
464         ji              = g_new0 (MonoJitInfo, 1);
465         ji->method      = method;
466         ji->code_start  = code;
467         ji->code_size   = buf - code;
468         
469         mono_jit_stats.method_trampolines++;
470
471         return ji;
472 }
473
474 /*========================= End of Function ========================*/
475
476 /*------------------------------------------------------------------*/
477 /*                                                                  */
478 /* Name         - mono_arch_create_jit_trampoline                   */
479 /*                                                                  */
480 /* Function     - Creates a trampoline function for virtual methods.*/
481 /*                If the created code is called it first starts JIT */
482 /*                compilation and then calls the newly created      */
483 /*                method. It also replaces the corresponding vtable */
484 /*                entry (see s390_magic_trampoline).                */
485 /*                                                                  */
486 /*                A trampoline consists of two parts: a main        */
487 /*                fragment, shared by all method trampolines, and   */
488 /*                and some code specific to each method, which      */
489 /*                hard-codes a reference to that method and then    */
490 /*                calls the main fragment.                          */
491 /*                                                                  */
492 /*                The main fragment contains a call to              */
493 /*                's390_magic_trampoline', which performs a call    */
494 /*                to the JIT compiler and substitutes the method-   */
495 /*                specific fragment with some code that directly    */
496 /*                calls the JIT-compiled method.                    */
497 /*                                                                  */
498 /* Parameter    - method - Pointer to the method information        */
499 /*                                                                  */
500 /* Returns      - A pointer to the newly created code               */
501 /*                                                                  */
502 /*------------------------------------------------------------------*/
503
504 gpointer
505 mono_arch_create_jit_trampoline (MonoMethod *method)
506 {
507         guint8 *code, *buf;
508         static guint8 *vc = NULL;
509         gint32 displace;
510
511         vc = mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC);
512
513         /*----------------------------------------------------------*/
514         /* This is the method-specific part of the trampoline. Its  */
515         /* purpose is to provide the generic part with the          */
516         /* MonoMethod *method pointer. We'll use r1 to keep it.     */
517         /*----------------------------------------------------------*/
518         code = buf = mono_global_codeman_reserve(METHOD_TRAMPOLINE_SIZE);
519
520         s390_basr (buf, s390_r1, 0);
521         s390_j    (buf, 4);
522         s390_word (buf, method);
523         s390_l    (buf, s390_r1, 0, s390_r1, 4);
524         displace = (vc - buf) / 2;
525         s390_jcl  (buf, S390_CC_UN, displace);
526
527         /* Flush instruction cache, since we've generated code */
528         mono_arch_flush_icache (code, buf - code);
529                 
530         /* Sanity check */
531         g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
532         
533         return code;
534 }
535
536 /*========================= End of Function ========================*/
537
538 /*------------------------------------------------------------------*/
539 /*                                                                  */
540 /* Name         - mono_arch_create_class_init_trampoline            */
541 /*                                                                  */
542 /* Function     - Creates a trampoline function to run a type init- */
543 /*                ializer. If the trampoline is called, it calls    */
544 /*                mono_runtime_class_init with the given vtable,    */
545 /*                then patches the caller code so it does not get   */
546 /*                called any more.                                  */
547 /*                                                                  */
548 /* Parameter    - vtable - The type to initialize                   */
549 /*                                                                  */
550 /* Returns      - A pointer to the newly created code               */
551 /*                                                                  */
552 /*------------------------------------------------------------------*/
553
554 gpointer
555 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
556 {
557         guint8 *code, *buf, *tramp;
558
559         tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
560
561         /*-----------------------------------------------------------*/
562         /* This is the method-specific part of the trampoline. Its   */
563         /* purpose is to provide the generic part with the MonoMethod*/
564         /* *method pointer. We'll use r11 to keep that value, for    */
565         /* instance. However, the generic part of the trampoline     */
566         /* relies on r11 having the same value it had before coming  */
567         /* here, so we must save it before.                          */
568         /*-----------------------------------------------------------*/
569         code = buf = mono_global_codeman_reserve(METHOD_TRAMPOLINE_SIZE);
570
571         s390_st   (buf, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET);
572         s390_ahi  (buf, STK_BASE, -S390_MINIMAL_STACK_SIZE);
573
574         s390_basr (buf, s390_r1, 0);
575         s390_j    (buf, 6);
576         s390_word (buf, vtable);
577         s390_word (buf, s390_class_init_trampoline);
578         s390_lr   (buf, s390_r3, s390_r14);
579         s390_l    (buf, s390_r2, 0, s390_r1, 4);
580         s390_lhi  (buf, s390_r4, 0);
581         s390_l    (buf, s390_r1, 0, s390_r1, 8);
582         s390_basr (buf, s390_r14, s390_r1);
583
584         s390_ahi  (buf, STK_BASE, S390_MINIMAL_STACK_SIZE);
585         s390_l    (buf, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET);
586         s390_br   (buf, s390_r14);
587
588         /* Flush instruction cache, since we've generated code */
589         mono_arch_flush_icache (code, buf - code);
590                 
591         /* Sanity check */
592         g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
593
594         mono_jit_stats.method_trampolines++;
595
596         return code;
597 }
598
599 /*========================= End of Function ========================*/
600
601 /*------------------------------------------------------------------*/
602 /*                                                                  */
603 /* Name         - mono_debuger_create_notification_function         */
604 /*                                                                  */
605 /* Function     - This method is only called when running in the    */
606 /*                Mono debugger. It returns a pointer to the        */
607 /*                arch specific notification function.              */
608 /*                                                                  */
609 /*------------------------------------------------------------------*/
610
611 gpointer
612 mono_debugger_create_notification_function (void)
613 {
614         guint8 *ptr, *buf;
615
616         ptr = buf = mono_global_codeman_reserve (16);
617         s390_break (buf);
618         s390_br (buf, s390_r14);
619
620         return ptr;
621 }
622
623 /*========================= End of Function ========================*/