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