05fb2cecac28d58dd2f4146a7bc60ec6d434763c
[mono.git] / mono / mini / tramp-amd64.c
1 /*
2  * tramp-amd64.c: JIT trampoline code for amd64
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Zoltan Varga (vargaz@gmail.com)
7  *
8  * (C) 2001 Ximian, Inc.
9  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
10  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13
14 #include <config.h>
15 #include <glib.h>
16
17 #include <mono/metadata/abi-details.h>
18 #include <mono/metadata/appdomain.h>
19 #include <mono/metadata/marshal.h>
20 #include <mono/metadata/tabledefs.h>
21 #include <mono/metadata/mono-debug-debugger.h>
22 #include <mono/metadata/profiler-private.h>
23 #include <mono/metadata/gc-internals.h>
24 #include <mono/arch/amd64/amd64-codegen.h>
25
26 #include <mono/utils/memcheck.h>
27
28 #include "mini.h"
29 #include "mini-amd64.h"
30 #include "debugger-agent.h"
31
32 #if defined(__native_client_codegen__) && defined(__native_client__)
33 #include <malloc.h>
34 #include <nacl/nacl_dyncode.h>
35 #endif
36
37 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
38
39 #define IS_REX(inst) (((inst) >= 0x40) && ((inst) <= 0x4f))
40
41 /*
42  * mono_arch_get_unbox_trampoline:
43  * @m: method pointer
44  * @addr: pointer to native code for @m
45  *
46  * when value type methods are called through the vtable we need to unbox the
47  * this argument. This method returns a pointer to a trampoline which does
48  * unboxing before calling the method
49  */
50 gpointer
51 mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
52 {
53         guint8 *code, *start;
54         GSList *unwind_ops;
55         int this_reg, size = NACL_SIZE (20, 32);
56
57         MonoDomain *domain = mono_domain_get ();
58
59         this_reg = mono_arch_get_this_arg_reg (NULL);
60
61         start = code = (guint8 *)mono_domain_code_reserve (domain, size);
62
63         unwind_ops = mono_arch_get_cie_program ();
64
65         amd64_alu_reg_imm (code, X86_ADD, this_reg, sizeof (MonoObject));
66         /* FIXME: Optimize this */
67         amd64_mov_reg_imm (code, AMD64_RAX, addr);
68         amd64_jump_reg (code, AMD64_RAX);
69         g_assert ((code - start) < size);
70
71         nacl_domain_code_validate (domain, &start, size, &code);
72
73         mono_arch_flush_icache (start, code - start);
74         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
75
76         mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
77
78         return start;
79 }
80
81 /*
82  * mono_arch_get_static_rgctx_trampoline:
83  *
84  *   Create a trampoline which sets RGCTX_REG to MRGCTX, then jumps to ADDR.
85  */
86 gpointer
87 mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr)
88 {
89         guint8 *code, *start;
90         GSList *unwind_ops;
91         int buf_len;
92
93         MonoDomain *domain = mono_domain_get ();
94
95 #ifdef MONO_ARCH_NOMAP32BIT
96         buf_len = 32;
97 #else
98         /* AOTed code could still have a non-32 bit address */
99         if ((((guint64)addr) >> 32) == 0)
100                 buf_len = NACL_SIZE (16, 32);
101         else
102                 buf_len = NACL_SIZE (30, 32);
103 #endif
104
105         start = code = (guint8 *)mono_domain_code_reserve (domain, buf_len);
106
107         unwind_ops = mono_arch_get_cie_program ();
108
109         amd64_mov_reg_imm (code, MONO_ARCH_RGCTX_REG, mrgctx);
110         amd64_jump_code (code, addr);
111         g_assert ((code - start) < buf_len);
112
113         nacl_domain_code_validate (domain, &start, buf_len, &code);
114         mono_arch_flush_icache (start, code - start);
115         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
116
117         mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
118
119         return start;
120 }
121
122 #ifdef _WIN64
123 // Workaround lack of Valgrind support for 64-bit Windows
124 #define VALGRIND_DISCARD_TRANSLATIONS(...)
125 #endif
126
127 /*
128  * mono_arch_patch_callsite:
129  *
130  *   Patch the callsite whose address is given by ORIG_CODE so it calls ADDR. ORIG_CODE
131  * points to the pc right after the call.
132  */
133 void
134 mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr)
135 {
136 #if defined(__default_codegen__)
137         guint8 *code;
138         guint8 buf [16];
139         gboolean can_write = mono_breakpoint_clean_code (method_start, orig_code, 14, buf, sizeof (buf));
140
141         code = buf + 14;
142
143         /* mov 64-bit imm into r11 (followed by call reg?)  or direct call*/
144         if (((code [-13] == 0x49) && (code [-12] == 0xbb)) || (code [-5] == 0xe8)) {
145                 if (code [-5] != 0xe8) {
146                         if (can_write) {
147                                 InterlockedExchangePointer ((gpointer*)(orig_code - 11), addr);
148                                 VALGRIND_DISCARD_TRANSLATIONS (orig_code - 11, sizeof (gpointer));
149                         }
150                 } else {
151                         gboolean disp_32bit = ((((gint64)addr - (gint64)orig_code)) < (1 << 30)) && ((((gint64)addr - (gint64)orig_code)) > -(1 << 30));
152
153                         if ((((guint64)(addr)) >> 32) != 0 && !disp_32bit) {
154                                 /* 
155                                  * This might happen with LLVM or when calling AOTed code. Create a thunk.
156                                  */
157                                 guint8 *thunk_start, *thunk_code;
158
159                                 thunk_start = thunk_code = (guint8 *)mono_domain_code_reserve (mono_domain_get (), 32);
160                                 amd64_jump_membase (thunk_code, AMD64_RIP, 0);
161                                 *(guint64*)thunk_code = (guint64)addr;
162                                 addr = thunk_start;
163                                 g_assert ((((guint64)(addr)) >> 32) == 0);
164                                 mono_arch_flush_icache (thunk_start, thunk_code - thunk_start);
165                                 mono_profiler_code_buffer_new (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
166                         }
167                         if (can_write) {
168                                 InterlockedExchange ((gint32*)(orig_code - 4), ((gint64)addr - (gint64)orig_code));
169                                 VALGRIND_DISCARD_TRANSLATIONS (orig_code - 5, 4);
170                         }
171                 }
172         }
173         else if ((code [-7] == 0x41) && (code [-6] == 0xff) && (code [-5] == 0x15)) {
174                 /* call *<OFFSET>(%rip) */
175                 gpointer *got_entry = (gpointer*)((guint8*)orig_code + (*(guint32*)(orig_code - 4)));
176                 if (can_write) {
177                         InterlockedExchangePointer (got_entry, addr);
178                         VALGRIND_DISCARD_TRANSLATIONS (orig_code - 5, sizeof (gpointer));
179                 }
180         }
181 #elif defined(__native_client__)
182         /* These are essentially the same 2 cases as above, modified for NaCl*/
183
184         /* Target must be bundle-aligned */
185         g_assert (((guint32)addr & kNaClAlignmentMask) == 0);
186         /* Return target must be bundle-aligned */
187         g_assert (((guint32)orig_code & kNaClAlignmentMask) == 0);
188
189         if (orig_code[-5] == 0xe8) {
190                 /* Direct call */
191                 int ret;
192                 gint32 offset = (gint32)addr - (gint32)orig_code;
193                 guint8 buf[sizeof(gint32)];
194                 *((gint32*)(buf)) = offset;
195                 ret = nacl_dyncode_modify (orig_code - sizeof(gint32), buf, sizeof(gint32));
196                 g_assert (ret == 0);
197         }
198
199         else if (is_nacl_call_reg_sequence (orig_code - 10) && orig_code[-16] == 0x41 && orig_code[-15] == 0xbb) {
200                 int ret;
201                 guint8 buf[sizeof(gint32)];
202                 *((gint32 *)(buf)) = addr;
203                 /* orig_code[-14] is the start of the immediate. */
204                 ret = nacl_dyncode_modify (orig_code - 14, buf, sizeof(gint32));
205                 g_assert (ret == 0);
206         }
207         else {
208                 g_assert_not_reached ();
209         }
210
211         return;
212 #endif
213 }
214
215 guint8*
216 mono_arch_create_llvm_native_thunk (MonoDomain *domain, guint8 *addr)
217 {
218         /*
219          * The caller is LLVM code and the call displacement might exceed 32 bits. We can't determine the caller address, so
220          * we add a thunk every time.
221          * Since the caller is also allocated using the domain code manager, hopefully the displacement will fit into 32 bits.
222          * FIXME: Avoid this if possible if !MONO_ARCH_NOMAP32BIT and ADDR is 32 bits.
223          */
224         guint8 *thunk_start, *thunk_code;
225
226         thunk_start = thunk_code = (guint8 *)mono_domain_code_reserve (mono_domain_get (), 32);
227         amd64_jump_membase (thunk_code, AMD64_RIP, 0);
228         *(guint64*)thunk_code = (guint64)addr;
229         addr = thunk_start;
230         mono_arch_flush_icache (thunk_start, thunk_code - thunk_start);
231         mono_profiler_code_buffer_new (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
232         return addr;
233 }
234
235 void
236 mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
237 {
238         gint32 disp;
239         gpointer *plt_jump_table_entry;
240
241 #if defined(__default_codegen__)
242         /* A PLT entry: jmp *<DISP>(%rip) */
243         g_assert (code [0] == 0xff);
244         g_assert (code [1] == 0x25);
245
246         disp = *(gint32*)(code + 2);
247
248         plt_jump_table_entry = (gpointer*)(code + 6 + disp);
249 #elif defined(__native_client_codegen__)
250         /* A PLT entry:            */
251         /* mov <DISP>(%rip), %r11d */
252         /* nacljmp *%r11           */
253
254         /* Verify the 'mov' */
255         g_assert (code [0] == 0x45);
256         g_assert (code [1] == 0x8b);
257         g_assert (code [2] == 0x1d);
258
259         disp = *(gint32*)(code + 3);
260
261         /* 7 = 3 (mov opcode) + 4 (disp) */
262         /* This needs to resolve to the target of the RIP-relative offset */
263         plt_jump_table_entry = (gpointer*)(code + 7 + disp);
264
265 #endif /* __native_client_codegen__ */
266
267         InterlockedExchangePointer (plt_jump_table_entry, addr);
268 }
269
270 static void
271 stack_unaligned (MonoTrampolineType tramp_type)
272 {
273         printf ("%d\n", tramp_type);
274         g_assert_not_reached ();
275 }
276
277 guchar*
278 mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot)
279 {
280         char *tramp_name;
281         guint8 *buf, *code, *tramp, *br [2], *r11_save_code, *after_r11_save_code, *br_ex_check;
282         int i, lmf_offset, offset, res_offset, arg_offset, rax_offset, ex_offset, tramp_offset, ctx_offset, saved_regs_offset;
283         int r11_save_offset, saved_fpregs_offset, rbp_offset, framesize, orig_rsp_to_rbp_offset, cfa_offset;
284         gboolean has_caller;
285         GSList *unwind_ops = NULL;
286         MonoJumpInfo *ji = NULL;
287         const guint kMaxCodeSize = NACL_SIZE (630, 630*2);
288
289 #if defined(__native_client_codegen__)
290         const guint kNaClTrampOffset = 17;
291 #endif
292
293         if (tramp_type == MONO_TRAMPOLINE_JUMP || tramp_type == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)
294                 has_caller = FALSE;
295         else
296                 has_caller = TRUE;
297
298         code = buf = (guint8 *)mono_global_codeman_reserve (kMaxCodeSize);
299
300         /* Compute stack frame size and offsets */
301         offset = 0;
302         rbp_offset = -offset;
303
304         offset += sizeof(mgreg_t);
305         rax_offset = -offset;
306
307         offset += sizeof(mgreg_t);
308         ex_offset = -offset;
309
310         offset += sizeof(mgreg_t);
311         r11_save_offset = -offset;
312
313         offset += sizeof(mgreg_t);
314         tramp_offset = -offset;
315
316         offset += sizeof(gpointer);
317         arg_offset = -offset;
318
319         offset += sizeof(mgreg_t);
320         res_offset = -offset;
321
322         offset += sizeof (MonoContext);
323         ctx_offset = -offset;
324         saved_regs_offset = ctx_offset + MONO_STRUCT_OFFSET (MonoContext, gregs);
325         saved_fpregs_offset = ctx_offset + MONO_STRUCT_OFFSET (MonoContext, fregs);
326
327         offset += sizeof (MonoLMFTramp);
328         lmf_offset = -offset;
329
330 #ifdef TARGET_WIN32
331         /* Reserve space where the callee can save the argument registers */
332         offset += 4 * sizeof (mgreg_t);
333 #endif
334
335         framesize = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
336
337         // CFA = sp + 16 (the trampoline address is on the stack)
338         cfa_offset = 16;
339         mono_add_unwind_op_def_cfa (unwind_ops, code, buf, AMD64_RSP, 16);
340         // IP saved at CFA - 8
341         mono_add_unwind_op_offset (unwind_ops, code, buf, AMD64_RIP, -8);
342
343         orig_rsp_to_rbp_offset = 0;
344         r11_save_code = code;
345         /* Reserve space for the mov_membase_reg to save R11 */
346         code += 5;
347         after_r11_save_code = code;
348
349         /* Pop the return address off the stack */
350         amd64_pop_reg (code, AMD64_R11);
351         orig_rsp_to_rbp_offset += sizeof(mgreg_t);
352
353         cfa_offset -= sizeof(mgreg_t);
354         mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
355
356         /* 
357          * Allocate a new stack frame
358          */
359         amd64_push_reg (code, AMD64_RBP);
360         cfa_offset += sizeof(mgreg_t);
361         mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
362         mono_add_unwind_op_offset (unwind_ops, code, buf, AMD64_RBP, - cfa_offset);
363
364         orig_rsp_to_rbp_offset -= sizeof(mgreg_t);
365         amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof(mgreg_t));
366         mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, AMD64_RBP);
367         amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize);
368
369         /* Compute the trampoline address from the return address */
370         if (aot) {
371 #if defined(__default_codegen__)
372                 /* 7 = length of call *<offset>(rip) */
373                 amd64_alu_reg_imm (code, X86_SUB, AMD64_R11, 7);
374 #elif defined(__native_client_codegen__)
375                 amd64_alu_reg_imm (code, X86_SUB, AMD64_R11, kNaClTrampOffset);
376 #endif
377         } else {
378                 /* 5 = length of amd64_call_membase () */
379                 amd64_alu_reg_imm (code, X86_SUB, AMD64_R11, 5);
380         }
381         amd64_mov_membase_reg (code, AMD64_RBP, tramp_offset, AMD64_R11, sizeof(gpointer));
382
383         /* Save all registers */
384         for (i = 0; i < AMD64_NREG; ++i) {
385                 if (i == AMD64_RBP) {
386                         /* RAX is already saved */
387                         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RBP, rbp_offset, sizeof(mgreg_t));
388                         amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), AMD64_RAX, sizeof(mgreg_t));
389                 } else if (i == AMD64_RIP) {
390                         if (has_caller)
391                                 amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, 8, sizeof(gpointer));
392                         else
393                                 amd64_mov_reg_imm (code, AMD64_R11, 0);
394                         amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), AMD64_R11, sizeof(mgreg_t));
395                 } else if (i == AMD64_RSP) {
396                         amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
397                         amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
398                         amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), AMD64_R11, sizeof(mgreg_t));
399                 } else if (i != AMD64_R11) {
400                         amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), i, sizeof(mgreg_t));
401                 } else {
402                         /* We have to save R11 right at the start of
403                            the trampoline code because it's used as a
404                            scratch register */
405                         /* This happens before the frame is set up, so it goes into the redzone */
406                         amd64_mov_membase_reg (r11_save_code, AMD64_RSP, r11_save_offset + orig_rsp_to_rbp_offset, i, sizeof(mgreg_t));
407                         g_assert (r11_save_code == after_r11_save_code);
408
409                         /* Copy from the save slot into the register array slot */
410                         amd64_mov_reg_membase (code, i, AMD64_RSP, r11_save_offset + orig_rsp_to_rbp_offset, sizeof(mgreg_t));
411                         amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), i, sizeof(mgreg_t));
412                 }
413                 /* cfa = rbp + cfa_offset */
414                 mono_add_unwind_op_offset (unwind_ops, code, buf, i, - cfa_offset + saved_regs_offset + (i * sizeof (mgreg_t)));
415         }
416         for (i = 0; i < 8; ++i)
417                 amd64_movsd_membase_reg (code, AMD64_RBP, saved_fpregs_offset + (i * sizeof(mgreg_t)), i);
418
419         /* Check that the stack is aligned */
420 #if defined(__default_codegen__)
421         amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof (mgreg_t));
422         amd64_alu_reg_imm (code, X86_AND, AMD64_R11, 15);
423         amd64_alu_reg_imm (code, X86_CMP, AMD64_R11, 0);
424         br [0] = code;
425         amd64_branch_disp (code, X86_CC_Z, 0, FALSE);
426         if (aot) {
427                 amd64_mov_reg_imm (code, AMD64_R11, 0);
428                 amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8);
429         } else {
430                 amd64_mov_reg_imm (code, MONO_AMD64_ARG_REG1, tramp_type);
431                 amd64_mov_reg_imm (code, AMD64_R11, stack_unaligned);
432                 amd64_call_reg (code, AMD64_R11);
433         }
434         mono_amd64_patch (br [0], code);
435         //amd64_breakpoint (code);
436 #endif
437
438         if (tramp_type != MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD) {
439                 /* Obtain the trampoline argument which is encoded in the instruction stream */
440                 if (aot) {
441                         /* Load the GOT offset */
442                         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, tramp_offset, sizeof(gpointer));
443 #if defined(__default_codegen__)
444                         /*
445                          * r11 points to a call *<offset>(%rip) instruction, load the
446                          * pc-relative offset from the instruction itself.
447                          */
448                         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_R11, 3, 4);
449                         /* 7 is the length of the call, 8 is the offset to the next got slot */
450                         amd64_alu_reg_imm_size (code, X86_ADD, AMD64_RAX, 7 + sizeof (gpointer), sizeof(gpointer));
451 #elif defined(__native_client_codegen__)
452                         /* The arg is hidden in a "push imm32" instruction, */
453                         /* add one to skip the opcode.                      */
454                         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_R11, kNaClTrampOffset+1, 4);
455 #endif
456                         /* Compute the address of the GOT slot */
457                         amd64_alu_reg_reg_size (code, X86_ADD, AMD64_R11, AMD64_RAX, sizeof(gpointer));
458                         /* Load the value */
459                         amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, sizeof(gpointer));
460                 } else {                        
461                         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, tramp_offset, sizeof(gpointer));
462 #if defined(__default_codegen__)
463                         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_R11, 5, 1);
464                         amd64_widen_reg (code, AMD64_RAX, AMD64_RAX, TRUE, FALSE);
465                         amd64_alu_reg_imm_size (code, X86_CMP, AMD64_RAX, 4, 1);
466                         br [0] = code;
467                         x86_branch8 (code, X86_CC_NE, 6, FALSE);
468                         /* 32 bit immediate */
469                         amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 6, 4);
470                         br [1] = code;
471                         x86_jump8 (code, 10);
472                         /* 64 bit immediate */
473                         mono_amd64_patch (br [0], code);
474                         amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 6, 8);
475                         mono_amd64_patch (br [1], code);
476 #elif defined(__native_client_codegen__)
477                         /* All args are 32-bit pointers in NaCl */
478                         amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 6, 4);
479 #endif
480                 }
481                 amd64_mov_membase_reg (code, AMD64_RBP, arg_offset, AMD64_R11, sizeof(gpointer));
482         } else {
483                 amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, saved_regs_offset + (MONO_AMD64_ARG_REG1 * sizeof(mgreg_t)), sizeof(mgreg_t));
484                 amd64_mov_membase_reg (code, AMD64_RBP, arg_offset, AMD64_R11, sizeof(gpointer));
485         }
486
487         /* Save LMF begin */
488
489         /* Save ip */
490         if (has_caller)
491                 amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, 8, sizeof(gpointer));
492         else
493                 amd64_mov_reg_imm (code, AMD64_R11, 0);
494         amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rip), AMD64_R11, sizeof(mgreg_t));
495         /* Save sp */
496         amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
497         amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
498         amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rsp), AMD64_R11, sizeof(mgreg_t));
499         /* Save pointer to context */
500         amd64_lea_membase (code, AMD64_R11, AMD64_RBP, ctx_offset);
501         amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, ctx), AMD64_R11, sizeof(mgreg_t));
502
503         if (aot) {
504                 code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_get_lmf_addr");
505         } else {
506                 amd64_mov_reg_imm (code, AMD64_R11, mono_get_lmf_addr);
507         }
508         amd64_call_reg (code, AMD64_R11);
509
510         /* Save lmf_addr */
511         amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, lmf_addr), AMD64_RAX, sizeof(gpointer));
512         /* Save previous_lmf */
513         /* Set the lowest bit to signal that this LMF has the ip field set */
514         /* Set the third lowest bit to signal that this is a MonoLMFTramp structure */
515         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RAX, 0, sizeof(gpointer));
516         amd64_alu_reg_imm_size (code, X86_ADD, AMD64_R11, 0x5, sizeof(gpointer));
517         amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_R11, sizeof(gpointer));
518         /* Set new lmf */
519         amd64_lea_membase (code, AMD64_R11, AMD64_RBP, lmf_offset);
520         amd64_mov_membase_reg (code, AMD64_RAX, 0, AMD64_R11, sizeof(gpointer));
521
522         /* Save LMF end */
523
524         /* Arg1 is the pointer to the saved registers */
525         amd64_lea_membase (code, AMD64_ARG_REG1, AMD64_RBP, saved_regs_offset);
526
527         /* Arg2 is the address of the calling code */
528         if (has_caller)
529                 amd64_mov_reg_membase (code, AMD64_ARG_REG2, AMD64_RBP, 8, sizeof(gpointer));
530         else
531                 amd64_mov_reg_imm (code, AMD64_ARG_REG2, 0);
532
533         /* Arg3 is the method/vtable ptr */
534         amd64_mov_reg_membase (code, AMD64_ARG_REG3, AMD64_RBP, arg_offset, sizeof(gpointer));
535
536         /* Arg4 is the trampoline address */
537         amd64_mov_reg_membase (code, AMD64_ARG_REG4, AMD64_RBP, tramp_offset, sizeof(gpointer));
538
539         if (aot) {
540                 char *icall_name = g_strdup_printf ("trampoline_func_%d", tramp_type);
541                 code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, icall_name);
542         } else {
543                 tramp = (guint8*)mono_get_trampoline_func (tramp_type);
544                 amd64_mov_reg_imm (code, AMD64_R11, tramp);
545         }
546         amd64_call_reg (code, AMD64_R11);
547         amd64_mov_membase_reg (code, AMD64_RBP, res_offset, AMD64_RAX, sizeof(mgreg_t));
548
549         /* Restore LMF */
550         amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
551         amd64_alu_reg_imm_size (code, X86_SUB, AMD64_RCX, 0x5, sizeof(gpointer));
552         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, lmf_addr), sizeof(gpointer));
553         amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_RCX, sizeof(gpointer));
554
555         /* 
556          * Save rax to the stack, after the leave instruction, this will become part of
557          * the red zone.
558          */
559         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RBP, res_offset, sizeof(mgreg_t));
560         amd64_mov_membase_reg (code, AMD64_RBP, rax_offset, AMD64_RAX, sizeof(mgreg_t));
561
562         /* Check for thread interruption */
563         /* This is not perf critical code so no need to check the interrupt flag */
564         /* 
565          * Have to call the _force_ variant, since there could be a protected wrapper on the top of the stack.
566          */
567         if (aot) {
568                 code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_thread_force_interruption_checkpoint_noraise");
569         } else {
570                 amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_thread_force_interruption_checkpoint_noraise);
571         }
572         amd64_call_reg (code, AMD64_R11);
573
574         amd64_test_reg_reg (code, AMD64_RAX, AMD64_RAX);
575         br_ex_check = code;
576         amd64_branch8 (code, X86_CC_Z, -1, 1);
577
578         /*
579          * Exception case:
580          * We have an exception we want to throw in the caller's frame, so pop
581          * the trampoline frame and throw from the caller.
582          */
583         amd64_leave (code);
584         /* We are in the parent frame, the exception is in rax */
585         /*
586          * EH is initialized after trampolines, so get the address of the variable
587          * which contains throw_exception, and load it from there.
588          */
589         if (aot) {
590                 /* Not really a jit icall */
591                 code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr");
592         } else {
593                 amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_get_throw_exception_addr ());
594         }
595         amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, sizeof(gpointer));
596         amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, sizeof(mgreg_t));
597         /*
598          * We still have the original return value on the top of the stack, so the
599          * throw trampoline will use that as the throw site.
600          */
601         amd64_jump_reg (code, AMD64_R11);
602
603         /* Normal case */
604         mono_amd64_patch (br_ex_check, code);
605
606         /* Restore argument registers, r10 (imt method/rgxtx)
607            and rax (needed for direct calls to C vararg functions). */
608         for (i = 0; i < AMD64_NREG; ++i)
609                 if (AMD64_IS_ARGUMENT_REG (i) || i == AMD64_R10 || i == AMD64_RAX)
610                         amd64_mov_reg_membase (code, i, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), sizeof(mgreg_t));
611         for (i = 0; i < 8; ++i)
612                 amd64_movsd_reg_membase (code, i, AMD64_RBP, saved_fpregs_offset + (i * sizeof(mgreg_t)));
613
614         /* Restore stack */
615         amd64_leave (code);
616         cfa_offset -= sizeof (mgreg_t);
617         mono_add_unwind_op_def_cfa (unwind_ops, code, buf, AMD64_RSP, cfa_offset);
618
619         if (MONO_TRAMPOLINE_TYPE_MUST_RETURN (tramp_type)) {
620                 /* Load result */
621                 amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, rax_offset - sizeof(mgreg_t), sizeof(mgreg_t));
622                 amd64_ret (code);
623         } else {
624                 /* call the compiled method using the saved rax */
625                 amd64_jump_membase (code, AMD64_RSP, rax_offset - sizeof(mgreg_t));
626         }
627
628         g_assert ((code - buf) <= kMaxCodeSize);
629
630         nacl_global_codeman_validate (&buf, kMaxCodeSize, &code);
631
632         mono_arch_flush_icache (buf, code - buf);
633         mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
634
635         tramp_name = mono_get_generic_trampoline_name (tramp_type);
636         *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
637         g_free (tramp_name);
638
639         return buf;
640 }
641
642 gpointer
643 mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
644 {
645         guint8 *code, *buf, *tramp;
646         int size;
647         gboolean far_addr = FALSE;
648
649         tramp = mono_get_trampoline_code (tramp_type);
650
651 #if defined(__default_codegen__)
652         if ((((guint64)arg1) >> 32) == 0)
653                 size = 5 + 1 + 4;
654         else
655                 size = 5 + 1 + 8;
656
657         code = buf = (guint8 *)mono_domain_code_reserve_align (domain, size, 1);
658
659         if (((gint64)tramp - (gint64)code) >> 31 != 0 && ((gint64)tramp - (gint64)code) >> 31 != -1) {
660 #ifndef MONO_ARCH_NOMAP32BIT
661                 g_assert_not_reached ();
662 #endif
663                 far_addr = TRUE;
664                 size += 16;
665                 code = buf = (guint8 *)mono_domain_code_reserve_align (domain, size, 1);
666         }
667 #elif defined(__native_client_codegen__)
668         size = 5 + 1 + 4;
669         /* Aligning the call site below could */
670         /* add up to kNaClAlignment-1 bytes   */
671         size += (kNaClAlignment-1);
672         size = NACL_BUNDLE_ALIGN_UP (size);
673         buf = mono_domain_code_reserve_align (domain, size, kNaClAlignment);
674         code = buf;
675 #endif
676
677         if (far_addr) {
678                 amd64_mov_reg_imm (code, AMD64_R11, tramp);
679                 amd64_call_reg (code, AMD64_R11);
680         } else {
681                 amd64_call_code (code, tramp);
682         }
683         /* The trampoline code will obtain the argument from the instruction stream */
684 #if defined(__default_codegen__)
685         if ((((guint64)arg1) >> 32) == 0) {
686                 *code = 0x4;
687                 *(guint32*)(code + 1) = (gint64)arg1;
688                 code += 5;
689         } else {
690                 *code = 0x8;
691                 *(guint64*)(code + 1) = (gint64)arg1;
692                 code += 9;
693         }
694 #elif defined(__native_client_codegen__)
695         /* For NaCl, all tramp args are 32-bit because they're pointers */
696         *code = 0x68; /* push imm32 */
697         *(guint32*)(code + 1) = (gint32)arg1;
698         code += 5;
699 #endif
700
701         g_assert ((code - buf) <= size);
702
703         if (code_len)
704                 *code_len = size;
705
706         nacl_domain_code_validate(domain, &buf, size, &code);
707
708         mono_arch_flush_icache (buf, size);
709         mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type));
710
711         return buf;
712 }       
713
714 gpointer
715 mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
716 {
717         guint8 *tramp;
718         guint8 *code, *buf;
719         guint8 **rgctx_null_jumps;
720         int tramp_size;
721         int depth, index;
722         int i;
723         gboolean mrgctx;
724         MonoJumpInfo *ji = NULL;
725         GSList *unwind_ops;
726
727         mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
728         index = MONO_RGCTX_SLOT_INDEX (slot);
729         if (mrgctx)
730                 index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
731         for (depth = 0; ; ++depth) {
732                 int size = mono_class_rgctx_get_array_size (depth, mrgctx);
733
734                 if (index < size - 1)
735                         break;
736                 index -= size - 1;
737         }
738
739         tramp_size = NACL_SIZE (64 + 8 * depth, 128 + 8 * depth);
740
741         code = buf = (guint8 *)mono_global_codeman_reserve (tramp_size);
742
743         unwind_ops = mono_arch_get_cie_program ();
744
745         rgctx_null_jumps = (guint8 **)g_malloc (sizeof (guint8*) * (depth + 2));
746
747         if (mrgctx) {
748                 /* get mrgctx ptr */
749                 amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
750         } else {
751                 /* load rgctx ptr from vtable */
752                 amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context), sizeof(gpointer));
753                 /* is the rgctx ptr null? */
754                 amd64_test_reg_reg (code, AMD64_RAX, AMD64_RAX);
755                 /* if yes, jump to actual trampoline */
756                 rgctx_null_jumps [0] = code;
757                 amd64_branch8 (code, X86_CC_Z, -1, 1);
758         }
759
760         for (i = 0; i < depth; ++i) {
761                 /* load ptr to next array */
762                 if (mrgctx && i == 0)
763                         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, sizeof(gpointer));
764                 else
765                         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, 0, sizeof(gpointer));
766                 /* is the ptr null? */
767                 amd64_test_reg_reg (code, AMD64_RAX, AMD64_RAX);
768                 /* if yes, jump to actual trampoline */
769                 rgctx_null_jumps [i + 1] = code;
770                 amd64_branch8 (code, X86_CC_Z, -1, 1);
771         }
772
773         /* fetch slot */
774         amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, sizeof (gpointer) * (index + 1), sizeof(gpointer));
775         /* is the slot null? */
776         amd64_test_reg_reg (code, AMD64_RAX, AMD64_RAX);
777         /* if yes, jump to actual trampoline */
778         rgctx_null_jumps [depth + 1] = code;
779         amd64_branch8 (code, X86_CC_Z, -1, 1);
780         /* otherwise return */
781         amd64_ret (code);
782
783         for (i = mrgctx ? 1 : 0; i <= depth + 1; ++i)
784                 mono_amd64_patch (rgctx_null_jumps [i], code);
785
786         g_free (rgctx_null_jumps);
787
788         /* move the rgctx pointer to the VTABLE register */
789         amd64_mov_reg_reg (code, MONO_ARCH_VTABLE_REG, AMD64_ARG_REG1, sizeof(gpointer));
790
791         if (aot) {
792                 code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, g_strdup_printf ("specific_trampoline_lazy_fetch_%u", slot));
793                 amd64_jump_reg (code, AMD64_R11);
794         } else {
795                 tramp = (guint8 *)mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);
796
797                 /* jump to the actual trampoline */
798                 amd64_jump_code (code, tramp);
799         }
800
801         nacl_global_codeman_validate (&buf, tramp_size, &code);
802         mono_arch_flush_icache (buf, code - buf);
803         mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
804
805         g_assert (code - buf <= tramp_size);
806
807         char *name = mono_get_rgctx_fetch_trampoline_name (slot);
808         *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops);
809         g_free (name);
810
811         return buf;
812 }
813
814 void
815 mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
816 {
817         /* FIXME: This is not thread safe */
818         guint8 *code = (guint8 *)ji->code_start;
819
820         amd64_mov_reg_imm (code, AMD64_ARG_REG1, func_arg);
821         amd64_mov_reg_imm (code, AMD64_R11, func);
822
823         x86_push_imm (code, (guint64)func_arg);
824         amd64_call_reg (code, AMD64_R11);
825 }
826
827
828 static void
829 handler_block_trampoline_helper (gpointer *ptr)
830 {
831         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
832         *ptr = jit_tls->handler_block_return_address;
833 }
834
835 gpointer
836 mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
837 {
838         guint8 *tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD);
839         guint8 *code, *buf;
840         int tramp_size = 64;
841         MonoJumpInfo *ji = NULL;
842         GSList *unwind_ops;
843
844         g_assert (!aot);
845
846         code = buf = (guint8 *)mono_global_codeman_reserve (tramp_size);
847
848         unwind_ops = mono_arch_get_cie_program ();
849
850         /*
851         This trampoline restore the call chain of the handler block then jumps into the code that deals with it.
852         */
853         if (mono_get_jit_tls_offset () != -1) {
854                 code = mono_amd64_emit_tls_get (code, MONO_AMD64_ARG_REG1, mono_get_jit_tls_offset ());
855                 amd64_mov_reg_membase (code, MONO_AMD64_ARG_REG1, MONO_AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 8);
856                 /* Simulate a call */
857                 amd64_push_reg (code, AMD64_RAX);
858                 mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 16);
859                 amd64_jump_code (code, tramp);
860         } else {
861                 /*Slow path uses a c helper*/
862                 amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RSP, 8);
863                 amd64_mov_reg_imm (code, AMD64_RAX, tramp);
864                 amd64_push_reg (code, AMD64_RAX);
865                 mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 16);
866                 amd64_push_reg (code, AMD64_RAX);
867                 mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 24);
868                 amd64_jump_code (code, handler_block_trampoline_helper);
869         }
870
871         mono_arch_flush_icache (buf, code - buf);
872         mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
873         g_assert (code - buf <= tramp_size);
874
875         *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
876
877         return buf;
878 }
879
880 /*
881  * mono_arch_get_call_target:
882  *
883  *   Return the address called by the code before CODE if exists.
884  */
885 guint8*
886 mono_arch_get_call_target (guint8 *code)
887 {
888         if (code [-5] == 0xe8) {
889                 gint32 disp = *(gint32*)(code - 4);
890                 guint8 *target = code + disp;
891
892                 return target;
893         } else {
894                 return NULL;
895         }
896 }
897
898 /*
899  * mono_arch_get_plt_info_offset:
900  *
901  *   Return the PLT info offset belonging to the plt entry PLT_ENTRY.
902  */
903 guint32
904 mono_arch_get_plt_info_offset (guint8 *plt_entry, mgreg_t *regs, guint8 *code)
905 {
906 #if defined(__native_client__) || defined(__native_client_codegen__)
907         /* 18 = 3 (mov opcode) + 4 (disp) + 10 (nacljmp) + 1 (push opcode) */
908         /* See aot-compiler.c arch_emit_plt_entry for details.             */
909         return *(guint32*)(plt_entry + 18);
910 #else
911         return *(guint32*)(plt_entry + 6);
912 #endif
913 }
914
915 /*
916  * mono_arch_create_sdb_trampoline:
917  *
918  *   Return a trampoline which captures the current context, passes it to
919  * debugger_agent_single_step_from_context ()/debugger_agent_breakpoint_from_context (),
920  * then restores the (potentially changed) context.
921  */
922 guint8*
923 mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gboolean aot)
924 {
925         int tramp_size = 256;
926         int i, framesize, ctx_offset, cfa_offset, gregs_offset;
927         guint8 *code, *buf;
928         GSList *unwind_ops = NULL;
929         MonoJumpInfo *ji = NULL;
930
931         code = buf = (guint8 *)mono_global_codeman_reserve (tramp_size);
932
933         framesize = 0;
934 #ifdef TARGET_WIN32
935         /* Reserve space where the callee can save the argument registers */
936         framesize += 4 * sizeof (mgreg_t);
937 #endif
938
939         ctx_offset = framesize;
940         framesize += sizeof (MonoContext);
941
942         framesize = ALIGN_TO (framesize, MONO_ARCH_FRAME_ALIGNMENT);
943
944         // CFA = sp + 8
945         cfa_offset = 8;
946         mono_add_unwind_op_def_cfa (unwind_ops, code, buf, AMD64_RSP, 8);
947         // IP saved at CFA - 8
948         mono_add_unwind_op_offset (unwind_ops, code, buf, AMD64_RIP, -cfa_offset);
949
950         amd64_push_reg (code, AMD64_RBP);
951         cfa_offset += sizeof(mgreg_t);
952         mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
953         mono_add_unwind_op_offset (unwind_ops, code, buf, AMD64_RBP, - cfa_offset);
954
955         amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof(mgreg_t));
956         mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, AMD64_RBP);
957         amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize);
958
959         gregs_offset = ctx_offset + MONO_STRUCT_OFFSET (MonoContext, gregs);
960
961         /* Initialize a MonoContext structure on the stack */
962         for (i = 0; i < AMD64_NREG; ++i) {
963                 if (i != AMD64_RIP && i != AMD64_RSP && i != AMD64_RBP)
964                         amd64_mov_membase_reg (code, AMD64_RSP, gregs_offset + (i * sizeof (mgreg_t)), i, sizeof (mgreg_t));
965         }
966         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, 0, sizeof (mgreg_t));
967         amd64_mov_membase_reg (code, AMD64_RSP, gregs_offset + (AMD64_RBP * sizeof (mgreg_t)), AMD64_R11, sizeof (mgreg_t));
968         amd64_lea_membase (code, AMD64_R11, AMD64_RBP, 2 * sizeof (mgreg_t));
969         amd64_mov_membase_reg (code, AMD64_RSP, gregs_offset + (AMD64_RSP * sizeof (mgreg_t)), AMD64_R11, sizeof (mgreg_t));
970         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, sizeof (mgreg_t), sizeof (mgreg_t));
971         amd64_mov_membase_reg (code, AMD64_RSP, gregs_offset + (AMD64_RIP * sizeof (mgreg_t)), AMD64_R11, sizeof (mgreg_t));
972
973         /* Call the single step/breakpoint function in sdb */
974         amd64_lea_membase (code, AMD64_ARG_REG1, AMD64_RSP, ctx_offset);
975
976         if (aot) {
977                 if (single_step)
978                         code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_single_step_from_context");
979                 else
980                         code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_breakpoint_from_context");
981         } else {
982                 if (single_step)
983                         amd64_mov_reg_imm (code, AMD64_R11, debugger_agent_single_step_from_context);
984                 else
985                         amd64_mov_reg_imm (code, AMD64_R11, debugger_agent_breakpoint_from_context);
986         }       
987         amd64_call_reg (code, AMD64_R11);
988
989         /* Restore registers from ctx */
990         for (i = 0; i < AMD64_NREG; ++i) {
991                 if (i != AMD64_RIP && i != AMD64_RSP && i != AMD64_RBP)
992                         amd64_mov_reg_membase (code, i, AMD64_RSP, gregs_offset + (i * sizeof (mgreg_t)), sizeof (mgreg_t));
993         }
994         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RSP, gregs_offset + (AMD64_RBP * sizeof (mgreg_t)), sizeof (mgreg_t));
995         amd64_mov_membase_reg (code, AMD64_RBP, 0, AMD64_R11, sizeof (mgreg_t));
996         amd64_mov_reg_membase (code, AMD64_R11, AMD64_RSP, gregs_offset + (AMD64_RIP * sizeof (mgreg_t)), sizeof (mgreg_t));
997         amd64_mov_membase_reg (code, AMD64_RBP, sizeof (mgreg_t), AMD64_R11, sizeof (mgreg_t));
998
999         amd64_leave (code);
1000         cfa_offset -= sizeof (mgreg_t);
1001         mono_add_unwind_op_def_cfa (unwind_ops, code, buf, AMD64_RSP, cfa_offset);
1002         amd64_ret (code);
1003
1004         mono_arch_flush_icache (code, code - buf);
1005         mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
1006         g_assert (code - buf <= tramp_size);
1007
1008         const char *tramp_name = single_step ? "sdb_single_step_trampoline" : "sdb_breakpoint_trampoline";
1009         *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
1010
1011         return buf;
1012 }