#ifdef __native_client_codegen__
-const guint kNaClAlignment = kNaClAlignmentX86;
-const guint kNaClAlignmentMask = kNaClAlignmentMaskX86;
/* Default alignment for Native Client is 32-byte. */
gint8 nacl_align_byte = -32; /* signed version of 0xe0 */
return res;
}
+#if !defined(__native_client__)
static const guchar cpuid_impl [] = {
0x55, /* push %ebp */
0x89, 0xe5, /* mov %esp,%ebp */
0xc9, /* leave */
0xc3, /* ret */
};
+#else
+static const guchar cpuid_impl [] = {
+ 0x55, /* push %ebp */
+ 0x89, 0xe5, /* mov %esp,%ebp */
+ 0x53, /* push %ebx */
+ 0x8b, 0x45, 0x08, /* mov 0x8(%ebp),%eax */
+ 0x0f, 0xa2, /* cpuid */
+ 0x50, /* push %eax */
+ 0x8b, 0x45, 0x10, /* mov 0x10(%ebp),%eax */
+ 0x89, 0x18, /* mov %ebx,(%eax) */
+ 0x8b, 0x45, 0x14, /* mov 0x14(%ebp),%eax */
+ 0x89, 0x08, /* mov %ecx,(%eax) */
+ 0x8b, 0x45, 0x18, /* mov 0x18(%ebp),%eax */
+ 0x89, 0x10, /* mov %edx,(%eax) */
+ 0x58, /* pop %eax */
+ 0x8b, 0x55, 0x0c, /* mov 0xc(%ebp),%edx */
+ 0x89, 0x02, /* mov %eax,(%edx) */
+ 0x5b, /* pop %ebx */
+ 0xc9, /* leave */
+ 0x59, 0x83, 0xe1, 0xe0, 0xff, 0xe1, /* naclret */
+ 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, /* padding, to provide bundle aligned version */
+ 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4
+};
+#endif
typedef void (*CpuidFunc) (int id, int* p_eax, int* p_ebx, int* p_ecx, int* p_edx);
cpuid (int id, int* p_eax, int* p_ebx, int* p_ecx, int* p_edx)
{
#if defined(__native_client__)
- /* Taken from below, the bug listed in the comment is */
- /* only valid for non-static cases. */
- __asm__ __volatile__ ("cpuid"
- : "=a" (*p_eax), "=b" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
- : "a" (id));
- return 1;
+ static CpuidFunc func = NULL;
+ void *ptr, *end_ptr;
+ if (!func) {
+ ptr = mono_global_codeman_reserve (sizeof (cpuid_impl));
+ memcpy(ptr, cpuid_impl, sizeof(cpuid_impl));
+ end_ptr = ptr + sizeof(cpuid_impl);
+ nacl_global_codeman_validate (&ptr, sizeof(cpuid_impl), &end_ptr);
+ func = (CpuidFunc)ptr;
+ }
+ func (id, p_eax, p_ebx, p_ecx, p_edx);
#else
int have_cpuid = 0;
#ifndef _MSC_VER
#define bb_is_loop_start(bb) ((bb)->loop_body_start && (bb)->nesting)
#ifndef DISABLE_JIT
-
-#if defined(__native_client__) || defined(__native_client_codegen__)
-void
-mono_nacl_gc()
-{
-#ifdef __native_client_gc__
- __nacl_suspend_thread_if_needed();
-#endif
-}
-#endif
-
void
mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
{
break;
case OP_IDIV:
case OP_IREM:
+#if defined( __native_client_codegen__ )
+ x86_alu_reg_imm (code, X86_CMP, ins->sreg2, 0);
+ EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "DivideByZeroException");
+#endif
/*
* The code is the same for div/rem, the allocator will allocate dreg
* to RAX/RDX as appropriate.
break;
case OP_IDIV_UN:
case OP_IREM_UN:
+#if defined( __native_client_codegen__ )
+ x86_alu_reg_imm (code, X86_CMP, ins->sreg2, 0);
+ EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "DivideByZeroException");
+#endif
if (ins->sreg2 == X86_EDX) {
x86_push_reg (code, ins->sreg2);
x86_alu_reg_reg (code, X86_XOR, X86_EDX, X86_EDX);
}
break;
case OP_DIV_IMM:
+#if defined( __native_client_codegen__ )
+ if (ins->inst_imm == 0) {
+ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC, "DivideByZeroException");
+ x86_jump32 (code, 0);
+ break;
+ }
+#endif
x86_mov_reg_imm (code, ins->sreg2, ins->inst_imm);
x86_cdq (code);
x86_div_reg (code, ins->sreg2, TRUE);
x86_fprem (code);
x86_fnstsw (code);
x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_C2);
- l2 = code + 2;
- x86_branch8 (code, X86_CC_NE, l1 - l2, FALSE);
+ l2 = code;
+ x86_branch8 (code, X86_CC_NE, 0, FALSE);
+ x86_patch (l2, l1);
/* pop result */
x86_fstp (code, 1);
break;
}
case OP_NACL_GC_SAFE_POINT: {
-#if defined(__native_client_codegen__)
- code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc);
+#if defined(__native_client_codegen__) && defined(__native_client_gc__)
+ if (cfg->compile_aot)
+ code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc);
+ else {
+ guint8 *br [1];
+
+ x86_test_mem_imm8 (code, (gpointer)&__nacl_thread_suspension_needed, 0xFFFFFFFF);
+ br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
+ code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc);
+ x86_patch (br[0], code);
+ }
#endif
break;
}
code = cfg->native_code = g_malloc (cfg->code_size);
#elif defined(__native_client_codegen__)
/* native_code_alloc is not 32-byte aligned, native_code is. */
+ cfg->code_size = NACL_BUNDLE_ALIGN_UP (cfg->code_size);
cfg->native_code_alloc = g_malloc (cfg->code_size + kNaClAlignment);
/* Align native_code to next nearest kNaclAlignment byte. */
max_offset += LOOP_ALIGNMENT;
#ifdef __native_client_codegen__
/* max alignment for native client */
- max_offset += kNaClAlignment;
+ if (bb->flags & BB_INDIRECT_JUMP_TARGET || bb->flags & BB_EXCEPTION_HANDLER)
+ max_offset += kNaClAlignment;
#endif
MONO_BB_FOR_EACH_INS (bb, ins) {
if (ins->opcode == OP_LABEL)
ins->inst_c1 = max_offset;
#ifdef __native_client_codegen__
+ switch (ins->opcode)
{
- int space_in_block = kNaClAlignment -
- ((max_offset + cfg->code_len) & kNaClAlignmentMask);
- int max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
- if (space_in_block < max_len && max_len < kNaClAlignment) {
- max_offset += space_in_block;
- }
+ case OP_FCALL:
+ case OP_LCALL:
+ case OP_VCALL:
+ case OP_VCALL2:
+ case OP_VOIDCALL:
+ case OP_CALL:
+ case OP_FCALL_REG:
+ case OP_LCALL_REG:
+ case OP_VCALL_REG:
+ case OP_VCALL2_REG:
+ case OP_VOIDCALL_REG:
+ case OP_CALL_REG:
+ case OP_FCALL_MEMBASE:
+ case OP_LCALL_MEMBASE:
+ case OP_VCALL_MEMBASE:
+ case OP_VCALL2_MEMBASE:
+ case OP_VOIDCALL_MEMBASE:
+ case OP_CALL_MEMBASE:
+ max_offset += kNaClAlignment;
+ break;
+ default:
+ max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN] - 1;
+ break;
}
#endif /* __native_client_codegen__ */
max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
#if defined(__native_client__) && defined(__native_client_codegen__)
/* In Native Client, we don't re-use thunks, allocate from the */
/* normal code manager paths. */
+ size = NACL_BUNDLE_ALIGN_UP (size);
code = mono_domain_code_reserve (domain, size);
#else
if (fail_tramp)