* (C) 2001-2003 Ximian, Inc.
* Copyright 2003-2011 Novell Inc
* Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
-#ifdef USE_JUMP_TABLES
-
-static guint16
-decode_imm16 (guint32 insn)
-{
- return (((insn >> 16) & 0xf) << 12) | (insn & 0xfff);
-}
-
-#define INSN_MASK 0xff00000
-#define MOVW_MASK ((3 << 24) | (0 << 20))
-#define MOVT_MASK ((3 << 24) | (4 << 20))
-
-gpointer*
-mono_arch_jumptable_entry_from_code (guint8 *code)
-{
- guint32 insn1 = ((guint32*)code) [0];
- guint32 insn2 = ((guint32*)code) [1];
-
- if (((insn1 & INSN_MASK) == MOVW_MASK) &&
- ((insn2 & INSN_MASK) == MOVT_MASK) ) {
- guint32 imm_lo = decode_imm16 (insn1);
- guint32 imm_hi = decode_imm16 (insn2);
- return (gpointer*) GUINT_TO_POINTER (imm_lo | (imm_hi << 16));
- } else {
- g_assert_not_reached ();
- return NULL;
- }
-}
-
-#undef INSN_MASK
-#undef MOVW_MASK
-#undef MOVT_MASK
-
-void
-mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr)
-{
- gpointer *jte;
- /*
- * code_ptr is 4 instructions after MOVW/MOVT used to address
- * jumptable entry.
- */
- jte = mono_jumptable_get_entry (code_ptr - 16);
- g_assert ( jte != NULL);
- *jte = addr;
-}
-#else
void
mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr)
{
g_assert_not_reached ();
}
-#endif
void
mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
#define arm_is_imm12(v) ((int)(v) > -4096 && (int)(v) < 4096)
-#ifndef USE_JUMP_TABLES
/*
* Return the instruction to jump from code to target, 0 if not
* reachable with a single instruction
}
return 0;
}
-#endif
static inline guint8*
emit_bx (guint8* code, int reg)
{
char *tramp_name;
guint8 *buf, *code = NULL;
-#ifdef USE_JUMP_TABLES
- gpointer *load_get_lmf_addr = NULL, *load_trampoline = NULL;
-#else
guint8 *load_get_lmf_addr = NULL, *load_trampoline = NULL;
gpointer *constants;
-#endif
int i, cfa_offset, regsave_size, lr_offset;
GSList *unwind_ops = NULL;
MonoJumpInfo *ji = NULL;
int buf_len;
-#ifdef USE_JUMP_TABLES
- g_assert (!aot);
-#endif
-
/* Now we'll create in 'buf' the ARM trampoline code. This
is the trampoline code common to all methods */
code += 4;
ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R0);
} else {
-#ifdef USE_JUMP_TABLES
- load_get_lmf_addr = mono_jumptable_add_entry ();
- code = mono_arm_load_jumptable_entry (code, load_get_lmf_addr, ARMREG_R0);
-#else
load_get_lmf_addr = code;
code += 4;
-#endif
}
ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
code = emit_bx (code, ARMREG_R0);
code += 4;
ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
} else {
-#ifdef USE_JUMP_TABLES
- load_trampoline = mono_jumptable_add_entry ();
- code = mono_arm_load_jumptable_entry (code, load_trampoline, ARMREG_IP);
-#else
load_trampoline = code;
code += 4;
-#endif
}
ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
code += 4;
ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
} else {
-#ifdef USE_JUMP_TABLES
- gpointer *jte = mono_jumptable_add_entry ();
- code = mono_arm_load_jumptable_entry (code, jte, ARMREG_IP);
- jte [0] = mono_interruption_checkpoint_from_trampoline;
-#else
ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
ARM_B (code, 0);
*(gpointer*)code = mono_interruption_checkpoint_from_trampoline;
code += 4;
-#endif
}
ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
code = emit_bx (code, ARMREG_IP);
else
code = emit_bx (code, ARMREG_IP);
-#ifdef USE_JUMP_TABLES
- load_get_lmf_addr [0] = mono_get_lmf_addr;
- load_trampoline [0] = (gpointer)mono_get_trampoline_func (tramp_type);
-#else
constants = (gpointer*)code;
constants [0] = mono_get_lmf_addr;
constants [1] = (gpointer)mono_get_trampoline_func (tramp_type);
}
code += 8;
-#endif
/* Flush instruction cache, since we've generated code */
mono_arch_flush_icache (buf, code - buf);
{
guint8 *code, *buf, *tramp;
gpointer *constants;
-#ifndef USE_JUMP_TABLES
guint32 short_branch = FALSE;
-#endif
guint32 size = SPEC_TRAMP_SIZE;
tramp = mono_get_trampoline_code (tramp_type);
if (domain) {
mono_domain_lock (domain);
-#ifdef USE_JUMP_TABLES
- code = buf = mono_domain_code_reserve_align (domain, size, 4);
-#else
code = buf = mono_domain_code_reserve_align (domain, size, 4);
if ((short_branch = branch_for_target_reachable (code + 4, tramp))) {
size = 12;
mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size);
- }
-#endif
+ }
mono_domain_unlock (domain);
} else {
code = buf = mono_global_codeman_reserve (size);
short_branch = FALSE;
}
-#ifdef USE_JUMP_TABLES
- /* For jumptables case we always generate the same code for trampolines,
- * namely
- * push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
- * movw lr, lo(jte)
- * movt lr, hi(jte)
- * ldr r1, [lr + 4]
- * bx r1
- */
- ARM_PUSH (code, 0x5fff);
- constants = mono_jumptable_add_entries (2);
- code = mono_arm_load_jumptable_entry_addr (code, constants, ARMREG_LR);
- ARM_LDR_IMM (code, ARMREG_R1, ARMREG_LR, 4);
- code = emit_bx (code, ARMREG_R1);
- constants [0] = arg1;
- constants [1] = tramp;
-#else
/* we could reduce this to 12 bytes if tramp is within reach:
* ARM_PUSH ()
* ARM_BL ()
constants [1] = tramp;
code += 8;
}
-#endif
/* Flush instruction cache, since we've generated code */
mono_arch_flush_icache (buf, code - buf);
guint8 *code, *start;
MonoDomain *domain = mono_domain_get ();
GSList *unwind_ops;
-#ifdef USE_JUMP_TABLES
- gpointer *jte;
- guint32 size = 20;
-#else
- guint32 size = 16;
-#endif
+ guint32 size = 16;
start = code = mono_domain_code_reserve (domain, size);
unwind_ops = mono_arch_get_cie_program ();
-#ifdef USE_JUMP_TABLES
- jte = mono_jumptable_add_entry ();
- code = mono_arm_load_jumptable_entry (code, jte, ARMREG_IP);
- ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject));
- code = emit_bx (code, ARMREG_IP);
- jte [0] = addr;
-#else
ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 4);
ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject));
code = emit_bx (code, ARMREG_IP);
*(guint32*)code = (guint32)addr;
code += 4;
-#endif
mono_arch_flush_icache (start, code - start);
mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
g_assert ((code - start) <= size);
{
guint8 *code, *start;
GSList *unwind_ops;
-#ifdef USE_JUMP_TABLES
- int buf_len = 20;
- gpointer *jte;
-#else
int buf_len = 16;
-#endif
MonoDomain *domain = mono_domain_get ();
start = code = mono_domain_code_reserve (domain, buf_len);
unwind_ops = mono_arch_get_cie_program ();
-#ifdef USE_JUMP_TABLES
- jte = mono_jumptable_add_entries (2);
- code = mono_arm_load_jumptable_entry_addr (code, jte, ARMREG_IP);
- ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_IP, 0);
- ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 4);
- ARM_BX (code, ARMREG_IP);
- jte [0] = mrgctx;
- jte [1] = addr;
-#else
ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_PC, 0);
ARM_LDR_IMM (code, ARMREG_PC, ARMREG_PC, 0);
*(guint32*)code = (guint32)mrgctx;
code += 4;
*(guint32*)code = (guint32)addr;
code += 4;
-#endif
g_assert ((code - start) <= buf_len);
gboolean mrgctx;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
-#ifdef USE_JUMP_TABLES
- gpointer *jte;
-#endif
mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
index = MONO_RGCTX_SLOT_INDEX (slot);
tramp = mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), &code_len);
/* Jump to the actual trampoline */
-#ifdef USE_JUMP_TABLES
- jte = mono_jumptable_add_entry ();
- jte [0] = tramp;
- code = mono_arm_load_jumptable_entry (code, jte, ARMREG_R1);
- code = emit_bx (code, ARMREG_R1);
-#else
ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); /* temp reg */
code = emit_bx (code, ARMREG_R1);
*(gpointer*)code = tramp;
code += 4;
-#endif
}
mono_arch_flush_icache (buf, code - buf);
ARM_MOV_REG_REG (code, ARMREG_R0, ARMREG_FP);
/* call */
- // FIXME: AOT
-#ifdef USE_JUMP_TABLES
- {
- gpointer *jte = mono_jumptable_add_entry ();
- code = mono_arm_load_jumptable_entry (code, jte, ARMREG_IP);
- jte [0] = function;
+ if (aot) {
+ if (single_step)
+ ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_single_step_from_context");
+ else
+ ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_breakpoint_from_context");
+ ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
+ ARM_B (code, 0);
+ *(gpointer*)code = NULL;
+ code += 4;
+ ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
+ ARM_BLX_REG (code, ARMREG_IP);
+ } else {
+ ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
+ ARM_B (code, 0);
+ if (single_step)
+ *(gpointer*)code = debugger_agent_single_step_from_context;
+ else
+ *(gpointer*)code = debugger_agent_breakpoint_from_context;
+ code += 4;
+ ARM_BLX_REG (code, ARMREG_IP);
}
-#else
- ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
- ARM_B (code, 0);
- if (single_step)
- *(gpointer*)code = debugger_agent_single_step_from_context;
- else
- *(gpointer*)code = debugger_agent_breakpoint_from_context;
- code += 4;
-#endif
- ARM_BLX_REG (code, ARMREG_IP);
/* we're back; save ctx.eip and ctx.esp into the corresponding regs slots. */
ARM_LDR_IMM (code, ARMREG_R0, ARMREG_FP, MONO_STRUCT_OFFSET (MonoContext, pc));
{
guint32 ins = ((guint32*)(gpointer)code) [-1];
-#if MONOTOUCH
/* Should be a 'bl' or a 'b' */
if (((ins >> 25) & 0x7) == 0x5) {
-#else
- /* Should be a 'bl' */
- if ((((ins >> 25) & 0x7) == 0x5) && (((ins >> 24) & 0x1) == 0x1)) {
-#endif
gint32 disp = ((((gint32)ins) & 0xffffff) << 8) >> 8;
guint8 *target = code - 4 + 8 + (disp * 4);
g_assert ((code - buf) <= buf_len);
- nacl_domain_code_validate (domain, &buf, buf_len, &code);
mono_arch_flush_icache (buf, code - buf);
mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
}
#endif
-
-#if defined(ENABLE_GSHAREDVT)
-
-#include "../../../mono-extensions/mono/mini/tramp-arm-gsharedvt.c"
-
-#else
-
-gpointer
-mono_arm_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg)
-{
- g_assert_not_reached ();
- return NULL;
-}
-
-gpointer
-mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
-{
- *info = NULL;
- return NULL;
-}
-
-#endif /* !MONOTOUCH */