Browse Source

Add first set of codegeneration macros and closure support for x86_64.

cache-refactoring
Klaus Treichel 17 years ago
parent
commit
003ad8d0c8
  1. 11
      ChangeLog
  2. 2
      jit/Makefile.am
  3. 224
      jit/jit-apply-x86-64.c
  4. 15
      jit/jit-apply-x86-64.h
  5. 2515
      jit/jit-gen-x86-64.h

11
ChangeLog

@ -1,3 +1,14 @@
2008-01-29 Klaus Treichel <ktreichel@web.de
* jit/jit-apply-x86-64.h: Fix the macros jit_builtin_return_int
and jit_builtin_return_float.
* jit/jit-apply-x86-64.c: Add closure support for x86_64.
* jit/jit-gen-x86-64.h: Add first codegeneration macros for x86_64.
* jit/Makefile.am: Add the two new files to the libjit sources.
2008-01-26 Aleksey Demakov <ademakov@gmail.com>
* auto_gen.sh: remove, use "autoreconf -i -f" instead (thanks

2
jit/Makefile.am

@ -12,6 +12,7 @@ libjit_la_SOURCES = \
jit-apply-x86.h \
jit-apply-x86.c \
jit-apply-x86-64.h \
jit-apply-x86-64.c \
jit-bitset.h \
jit-bitset.c \
jit-block.c \
@ -33,6 +34,7 @@ libjit_la_SOURCES = \
jit-gen-arm.h \
jit-gen-arm.c \
jit-gen-x86.h \
jit-gen-x86_64.h \
jit-insn.c \
jit-init.c \
jit-internal.h \

224
jit/jit-apply-x86-64.c

@ -0,0 +1,224 @@
/*
* jit-apply-x86-64.c - Apply support routines for x86_64.
*
* Copyright (C) 2008 Southern Storm Software, Pty Ltd.
*
* This file is part of the libjit library.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* The libjit library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the libjit library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "jit-internal.h"
#include "jit-apply-rules.h"
#include "jit-apply-func.h"
#if defined(__amd64) || defined(__amd64__) || defined(_x86_64) || defined(_x86_64__)
#include "jit-gen-x86-64.h"
void _jit_create_closure(unsigned char *buf, void *func,
void *closure, void *_type)
{
jit_nint offset;
jit_type_t signature = (jit_type_t)_type;
/* Set up the local stack frame */
x86_64_push_reg_size(buf, X86_64_RBP, 8);
x86_64_mov_reg_reg_size(buf, X86_64_RBP, X86_64_RSP, 8);
/* Create the apply argument block on the stack */
x86_64_sub_reg_imm_size(buf, X86_64_RSP, 192, 8);
/* fill the apply buffer */
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x08, X86_64_RDI, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x10, X86_64_RSI, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x18, X86_64_RDX, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x20, X86_64_RCX, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x28, X86_64_R8, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x30, X86_64_R9, 8);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x40, X86_64_XMM0);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x50, X86_64_XMM1);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x60, X86_64_XMM2);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x70, X86_64_XMM3);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x80, X86_64_XMM4);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x90, X86_64_XMM5);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0xA0, X86_64_XMM6);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0xB0, X86_64_XMM7);
/* Now fill the arguments for the closure function */
/* the closure function is #1 */
x86_64_mov_reg_imm_size(buf, X86_64_RDI, (jit_nint)closure, 8);
/* the apply buff is #2 */
x86_64_mov_reg_reg_size(buf, X86_64_RSI, X86_64_RSP, 8);
/* Call the closure handling function */
offset = (jit_nint)func - ((jit_nint)buf + 5);
if((offset < jit_min_int) || (offset > jit_max_int))
{
/* offset is outside the 32 bit offset range */
/* so we have to do an indirect call */
/* We use R11 here because it's the only temporary caller saved */
/* register not used for argument passing. */
x86_64_mov_reg_imm_size(buf, X86_64_R11, (jit_nint)func, 8);
x86_64_call_reg(buf, X86_64_R11);
}
else
{
x86_64_call_imm(buf, (jit_int)offset);
}
/* Pop the current stack frame */
x86_64_mov_reg_reg_size(buf, X86_64_RSP, X86_64_RBP, 8);
x86_64_pop_reg_size(buf, X86_64_RBP, 8);
/* Return from the closure */
x86_64_ret(buf);
}
void *_jit_create_redirector(unsigned char *buf, void *func,
void *user_data, int abi)
{
jit_nint offset;
void *start = (void *)buf;
/* Save all registers used for argument passing */
/* At this point RSP is not aligned on a 16 byte boundary because */
/* the return address is pushed on the stack. */
/* We need (7 * 8) + (8 * 8) bytes for the registers */
x86_64_sub_reg_imm_size(buf, X86_64_RSP, 0xB8, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0xB0, X86_64_RAX, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0xA8, X86_64_RDI, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0xA0, X86_64_RSI, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x98, X86_64_RDX, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x90, X86_64_RCX, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x88, X86_64_R8, 8);
x86_64_mov_membase_reg_size(buf, X86_64_RSP, 0x80, X86_64_R9, 8);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x70, X86_64_XMM0);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x60, X86_64_XMM1);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x50, X86_64_XMM2);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x40, X86_64_XMM3);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x30, X86_64_XMM4);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x20, X86_64_XMM5);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x10, X86_64_XMM6);
x86_64_movaps_membase_reg(buf, X86_64_RSP, 0x00, X86_64_XMM7);
/* Fill the pointer to the stack args */
x86_64_lea_membase_size(buf, X86_64_RDI, X86_64_RSP, 0xD0, 8);
x86_64_mov_regp_reg_size(buf, X86_64_RSP, X86_64_RDI, 8);
/* Load the user data argument */
x86_64_mov_reg_imm_size(buf, X86_64_RDI, (jit_nint)user_data, 8);
/* Call "func" (the pointer result will be in RAX) */
offset = (jit_nint)func - ((jit_nint)buf + 5);
if((offset < jit_min_int) || (offset > jit_max_int))
{
/* offset is outside the 32 bit offset range */
/* so we have to do an indirect call */
/* We use R11 here because it's the only temporary caller saved */
/* register not used for argument passing. */
x86_64_mov_reg_imm_size(buf, X86_64_R11, (jit_nint)func, 8);
x86_64_call_reg(buf, X86_64_R11);
}
else
{
x86_64_call_imm(buf, (jit_int)offset);
}
/* store the returned address in R11 */
x86_64_mov_reg_reg_size(buf, X86_64_R11, X86_64_RAX, 8);
/* Restore the argument registers */
x86_64_mov_reg_membase_size(buf, X86_64_RAX, X86_64_RSP, 0xB0, 8);
x86_64_mov_reg_membase_size(buf, X86_64_RDI, X86_64_RSP, 0xA8, 8);
x86_64_mov_reg_membase_size(buf, X86_64_RSI, X86_64_RSP, 0xA0, 8);
x86_64_mov_reg_membase_size(buf, X86_64_RDX, X86_64_RSP, 0x98, 8);
x86_64_mov_reg_membase_size(buf, X86_64_RCX, X86_64_RSP, 0x90, 8);
x86_64_mov_reg_membase_size(buf, X86_64_R8, X86_64_RSP, 0x88, 8);
x86_64_mov_reg_membase_size(buf, X86_64_R9, X86_64_RSP, 0x80, 8);
x86_64_movaps_reg_membase(buf, X86_64_XMM0, X86_64_RSP, 0x70);
x86_64_movaps_reg_membase(buf, X86_64_XMM1, X86_64_RSP, 0x60);
x86_64_movaps_reg_membase(buf, X86_64_XMM2, X86_64_RSP, 0x50);
x86_64_movaps_reg_membase(buf, X86_64_XMM3, X86_64_RSP, 0x40);
x86_64_movaps_reg_membase(buf, X86_64_XMM4, X86_64_RSP, 0x30);
x86_64_movaps_reg_membase(buf, X86_64_XMM5, X86_64_RSP, 0x20);
x86_64_movaps_reg_membase(buf, X86_64_XMM6, X86_64_RSP, 0x10);
x86_64_movaps_reg_membase(buf, X86_64_XMM7, X86_64_RSP, 0x00);
/* Restore the stack pointer */
x86_64_add_reg_imm_size(buf, X86_64_RSP, 0xB8, 8);
/* Jump to the function that the redirector indicated */
x86_64_jmp_reg(buf, X86_64_R11);
/* Return the start of the buffer as the redirector entry point */
return start;
}
void *_jit_create_indirector(unsigned char *buf, void **entry)
{
jit_nint offset;
void *start = (void *)buf;
/* Jump to the entry point. */
offset = (jit_nint)entry - ((jit_nint)buf + 5);
if((offset < jit_min_int) || (offset > jit_max_int))
{
/* offset is outside the 32 bit offset range */
/* so we have to do an indirect jump via register. */
x86_64_mov_reg_imm_size(buf, X86_64_R11, (jit_nint)entry, 8);
x86_64_jmp_reg(buf, X86_64_R11);
}
else
{
x86_64_jmp_mem(buf, offset);
}
return start;
}
void _jit_pad_buffer(unsigned char *buf, int len)
{
while(len >= 6)
{
/* "leal 0(%esi), %esi" with 32-bit displacement */
*buf++ = (unsigned char)0x8D;
x86_address_byte(buf, 2, X86_ESI, X86_ESI);
x86_imm_emit32(buf, 0);
len -= 6;
}
if(len >= 3)
{
/* "leal 0(%esi), %esi" with 8-bit displacement */
*buf++ = (unsigned char)0x8D;
x86_address_byte(buf, 1, X86_ESI, X86_ESI);
x86_imm_emit8(buf, 0);
len -= 3;
}
if(len == 1)
{
/* Traditional x86 NOP */
x86_nop(buf);
}
else if(len == 2)
{
/* movl %esi, %esi */
x86_mov_reg_reg(buf, X86_ESI, X86_ESI, 4);
}
}
#endif /* x86-64 */

15
jit/jit-apply-x86-64.h

@ -143,11 +143,11 @@
#define jit_builtin_return_int(return_buf) \
do { \
__asm__ ( \
"movq %0, %%rcx\n\t" \
"lea %0, %%rcx\n\t" \
"movq (%%rcx), %%rax\n\t" \
"movq 0x08(%%rcx), %%rdx\n\t" \
"movaps 0x10(%%rcx), %%xmm0\n\t" \
: : "m"((return_buf)) \
: : "m"(*(return_buf)) \
: "rax", "rcx", "rdx", "xmm0" \
); \
return; \
@ -156,10 +156,10 @@
#define jit_builtin_return_float(return_buf) \
do { \
__asm__ ( \
"movq %0, %%rcx\n\t" \
"lea %0, %%rcx\n\t" \
"movaps 0x10(%%rcx), %%xmm0\n\t" \
"fldt 0x20(%%rcx)\n\t" \
: : "m"((return_buf)) \
: : "m"(*(return_buf)) \
: "rcx", "xmm0", "st" \
); \
return; \
@ -167,4 +167,11 @@
#endif /* GNUC */
/*
* The maximum number of bytes that are needed to represent a closure,
* and the alignment to use for the closure.
*/
#define jit_closure_size 0x90
#define jit_closure_align 0x20
#endif /* _JIT_APPLY_X86_64_H */

2515
jit/jit-gen-x86-64.h

File diff suppressed because it is too large
Loading…
Cancel
Save