+#ifdef __native_client_codegen__
+
+/* Keep track of instruction "depth", that is, the level of sub-instruction */
+/* for any given instruction. For instance, amd64_call_reg resolves to */
+/* amd64_call_reg_internal, which uses amd64_alu_* macros, etc. */
+/* We only want to force bundle alignment for the top level instruction, */
+/* so NaCl pseudo-instructions can be implemented with sub instructions. */
+static guint32 nacl_instruction_depth;
+
+static guint32 nacl_rex_tag;
+static guint32 nacl_legacy_prefix_tag;
+
+void
+amd64_nacl_clear_legacy_prefix_tag ()
+{
+ TlsSetValue (nacl_legacy_prefix_tag, NULL);
+}
+
+void
+amd64_nacl_tag_legacy_prefix (guint8* code)
+{
+ if (TlsGetValue (nacl_legacy_prefix_tag) == NULL)
+ TlsSetValue (nacl_legacy_prefix_tag, code);
+}
+
+void
+amd64_nacl_tag_rex (guint8* code)
+{
+ TlsSetValue (nacl_rex_tag, code);
+}
+
+guint8*
+amd64_nacl_get_legacy_prefix_tag ()
+{
+ return (guint8*)TlsGetValue (nacl_legacy_prefix_tag);
+}
+
+guint8*
+amd64_nacl_get_rex_tag ()
+{
+ return (guint8*)TlsGetValue (nacl_rex_tag);
+}
+
+/* Increment the instruction "depth" described above */
+void
+amd64_nacl_instruction_pre ()
+{
+ intptr_t depth = (intptr_t) TlsGetValue (nacl_instruction_depth);
+ depth++;
+ TlsSetValue (nacl_instruction_depth, (gpointer)depth);
+}
+
+/* amd64_nacl_instruction_post: Decrement instruction "depth", force bundle */
+/* alignment if depth == 0 (top level instruction) */
+/* IN: start, end pointers to instruction beginning and end */
+/* OUT: start, end pointers to beginning and end after possible alignment */
+/* GLOBALS: nacl_instruction_depth defined above */
+void
+amd64_nacl_instruction_post (guint8 **start, guint8 **end)
+{
+ intptr_t depth = (intptr_t) TlsGetValue(nacl_instruction_depth);
+ depth--;
+ TlsSetValue (nacl_instruction_depth, (void*)depth);
+
+ g_assert ( depth >= 0 );
+ if (depth == 0) {
+ uintptr_t space_in_block;
+ uintptr_t instlen;
+ guint8 *prefix = amd64_nacl_get_legacy_prefix_tag ();
+ /* if legacy prefix is present, and if it was emitted before */
+ /* the start of the instruction sequence, adjust the start */
+ if (prefix != NULL && prefix < *start) {
+ g_assert (*start - prefix <= 3);/* only 3 are allowed */
+ *start = prefix;
+ }
+ space_in_block = kNaClAlignment - ((uintptr_t)(*start) & kNaClAlignmentMask);
+ instlen = (uintptr_t)(*end - *start);
+ /* Only check for instructions which are less than */
+ /* kNaClAlignment. The only instructions that should ever */
+ /* be that long are call sequences, which are already */
+ /* padded out to align the return to the next bundle. */
+ if (instlen > space_in_block && instlen < kNaClAlignment) {
+ const size_t MAX_NACL_INST_LENGTH = kNaClAlignment;
+ guint8 copy_of_instruction[MAX_NACL_INST_LENGTH];
+ const size_t length = (size_t)((*end)-(*start));
+ g_assert (length < MAX_NACL_INST_LENGTH);
+
+ memcpy (copy_of_instruction, *start, length);
+ *start = mono_arch_nacl_pad (*start, space_in_block);
+ memcpy (*start, copy_of_instruction, length);
+ *end = *start + length;
+ }
+ amd64_nacl_clear_legacy_prefix_tag ();
+ amd64_nacl_tag_rex (NULL);
+ }
+}
+
+/* amd64_nacl_membase_handler: ensure all access to memory of the form */
+/* OFFSET(%rXX) is sandboxed. For allowable base registers %rip, %rbp, */
+/* %rsp, and %r15, emit the membase as usual. For all other registers, */
+/* make sure the upper 32-bits are cleared, and use that register in the */
+/* index field of a new address of this form: OFFSET(%r15,%eXX,1) */
+/* IN: code */
+/* pointer to current instruction stream (in the */
+/* middle of an instruction, after opcode is emitted) */
+/* basereg/offset/dreg */
+/* operands of normal membase address */
+/* OUT: code */
+/* pointer to the end of the membase/memindex emit */
+/* GLOBALS: nacl_rex_tag */
+/* position in instruction stream that rex prefix was emitted */
+/* nacl_legacy_prefix_tag */
+/* (possibly NULL) position in instruction of legacy x86 prefix */
+void
+amd64_nacl_membase_handler (guint8** code, gint8 basereg, gint32 offset, gint8 dreg)
+{
+ gint8 true_basereg = basereg;
+
+ /* Cache these values, they might change */
+ /* as new instructions are emitted below. */
+ guint8* rex_tag = amd64_nacl_get_rex_tag ();
+ guint8* legacy_prefix_tag = amd64_nacl_get_legacy_prefix_tag ();
+
+ /* 'basereg' is given masked to 0x7 at this point, so check */
+ /* the rex prefix to see if this is an extended register. */
+ if ((rex_tag != NULL) && IS_REX(*rex_tag) && (*rex_tag & AMD64_REX_B)) {
+ true_basereg |= 0x8;
+ }
+
+#define X86_LEA_OPCODE (0x8D)
+
+ if (!amd64_is_valid_nacl_base (true_basereg) && (*(*code-1) != X86_LEA_OPCODE)) {
+ guint8* old_instruction_start;
+
+ /* This will hold the 'mov %eXX, %eXX' that clears the upper */
+ /* 32-bits of the old base register (new index register) */
+ guint8 buf[32];
+ guint8* buf_ptr = buf;
+ size_t insert_len;
+
+ g_assert (rex_tag != NULL);
+
+ if (IS_REX(*rex_tag)) {
+ /* The old rex.B should be the new rex.X */
+ if (*rex_tag & AMD64_REX_B) {
+ *rex_tag |= AMD64_REX_X;
+ }
+ /* Since our new base is %r15 set rex.B */
+ *rex_tag |= AMD64_REX_B;
+ } else {
+ /* Shift the instruction by one byte */
+ /* so we can insert a rex prefix */
+ memmove (rex_tag + 1, rex_tag, (size_t)(*code - rex_tag));
+ *code += 1;
+ /* New rex prefix only needs rex.B for %r15 base */
+ *rex_tag = AMD64_REX(AMD64_REX_B);
+ }
+
+ if (legacy_prefix_tag) {
+ old_instruction_start = legacy_prefix_tag;
+ } else {
+ old_instruction_start = rex_tag;
+ }
+
+ /* Clears the upper 32-bits of the previous base register */
+ amd64_mov_reg_reg_size (buf_ptr, true_basereg, true_basereg, 4);
+ insert_len = buf_ptr - buf;
+
+ /* Move the old instruction forward to make */
+ /* room for 'mov' stored in 'buf_ptr' */
+ memmove (old_instruction_start + insert_len, old_instruction_start, (size_t)(*code - old_instruction_start));
+ *code += insert_len;
+ memcpy (old_instruction_start, buf, insert_len);
+
+ /* Sandboxed replacement for the normal membase_emit */
+ x86_memindex_emit (*code, dreg, AMD64_R15, offset, basereg, 0);
+
+ } else {
+ /* Normal default behavior, emit membase memory location */
+ x86_membase_emit_body (*code, dreg, basereg, offset);
+ }
+}
+
+
+static inline unsigned char*
+amd64_skip_nops (unsigned char* code)
+{
+ guint8 in_nop;
+ do {
+ in_nop = 0;
+ if ( code[0] == 0x90) {
+ in_nop = 1;
+ code += 1;
+ }
+ if ( code[0] == 0x66 && code[1] == 0x90) {
+ in_nop = 1;
+ code += 2;
+ }
+ if (code[0] == 0x0f && code[1] == 0x1f
+ && code[2] == 0x00) {
+ in_nop = 1;
+ code += 3;
+ }
+ if (code[0] == 0x0f && code[1] == 0x1f
+ && code[2] == 0x40 && code[3] == 0x00) {
+ in_nop = 1;
+ code += 4;
+ }
+ if (code[0] == 0x0f && code[1] == 0x1f
+ && code[2] == 0x44 && code[3] == 0x00
+ && code[4] == 0x00) {
+ in_nop = 1;
+ code += 5;
+ }
+ if (code[0] == 0x66 && code[1] == 0x0f
+ && code[2] == 0x1f && code[3] == 0x44
+ && code[4] == 0x00 && code[5] == 0x00) {
+ in_nop = 1;
+ code += 6;
+ }
+ if (code[0] == 0x0f && code[1] == 0x1f
+ && code[2] == 0x80 && code[3] == 0x00
+ && code[4] == 0x00 && code[5] == 0x00
+ && code[6] == 0x00) {
+ in_nop = 1;
+ code += 7;
+ }
+ if (code[0] == 0x0f && code[1] == 0x1f
+ && code[2] == 0x84 && code[3] == 0x00
+ && code[4] == 0x00 && code[5] == 0x00
+ && code[6] == 0x00 && code[7] == 0x00) {
+ in_nop = 1;
+ code += 8;
+ }
+ } while ( in_nop );
+ return code;
+}
+
+guint8*
+mono_arch_nacl_skip_nops (guint8* code)
+{
+ return amd64_skip_nops(code);
+}
+
+#endif /*__native_client_codegen__*/
+