diff options
author | Rodrigo Kumpera <kumpera@gmail.com> | 2014-09-09 17:14:37 +0400 |
---|---|---|
committer | Rodrigo Kumpera <kumpera@gmail.com> | 2014-09-09 17:14:37 +0400 |
commit | 8602eed8f7f134deff6ed89fb38f8ec4119b3004 (patch) | |
tree | 1178872f42438e5ed8fa49c39e9206e92dc53679 | |
parent | 6bee6a7b18978aa6ce977b8b0f9ce19cf962f36b (diff) |
[cleanup] Remove more old files.
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | mono/arch/amd64/Makefile.am | 7 | ||||
-rw-r--r-- | mono/arch/amd64/tramp.c | 1054 | ||||
-rw-r--r-- | mono/arch/ppc/Makefile.am | 8 | ||||
-rw-r--r-- | mono/arch/ppc/test.c | 35 | ||||
-rw-r--r-- | mono/arch/ppc/tramp.c | 895 | ||||
-rw-r--r-- | mono/arch/x86/Makefile.am | 6 | ||||
-rw-r--r-- | mono/arch/x86/test.c | 225 | ||||
-rw-r--r-- | mono/arch/x86/tramp.c | 545 |
9 files changed, 3 insertions, 2776 deletions
diff --git a/README.md b/README.md index 609b9fa4660..b061956eee2 100644 --- a/README.md +++ b/README.md @@ -494,16 +494,12 @@ Directory Roadmap * `dis/` - CIL executable Disassembler - * `cli/` - Common code for the JIT and the interpreter. - * `io-layer/` - The I/O layer and system abstraction for emulating the .NET IO model. * `cil/` - Common Intermediate Representation, XML definition of the CIL bytecodes. - * `interp/` - Interpreter for CLI executables (obsolete). - * `arch/` - Architecture specific portions. * `man/` - Manual pages for the various Mono commands and programs. diff --git a/mono/arch/amd64/Makefile.am b/mono/arch/amd64/Makefile.am index 3c728263190..47daaaff699 100644 --- a/mono/arch/amd64/Makefile.am +++ b/mono/arch/amd64/Makefile.am @@ -1,7 +1,2 @@ - -AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) - -noinst_LTLIBRARIES = libmonoarch-amd64.la - -libmonoarch_amd64_la_SOURCES = tramp.c amd64-codegen.h +EXTRA_DIST = amd64-codegen.h diff --git a/mono/arch/amd64/tramp.c b/mono/arch/amd64/tramp.c deleted file mode 100644 index 6dbec93e859..00000000000 --- a/mono/arch/amd64/tramp.c +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * Create trampolines to invoke arbitrary functions. - * - * Copyright (C) Ximian Inc. - * - * Author: - * Zalman Stern - * Based on code by: - * Paolo Molaro (lupus@ximian.com) - * Dietmar Maurer (dietmar@ximian.com) - * - * To understand this code, one will want to the calling convention section of the ABI sepc at: - * http://x86-64.org/abi.pdf - * and the AMD64 architecture docs found at amd.com . - */ - -#include "config.h" -#include <stdlib.h> -#include <string.h> -#include "amd64-codegen.h" -#include "mono/metadata/class.h" -#include "mono/metadata/tabledefs.h" -#include "mono/interpreter/interp.h" -#include "mono/metadata/appdomain.h" -#include "mono/metadata/marshal.h" - -/* - * The resulting function takes the form: - * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments); - */ -#define FUNC_ADDR_POS 8 -#define RETVAL_POS 12 -#define THIS_POS 16 -#define ARGP_POS 20 -#define LOC_POS -4 - -#define ARG_SIZE sizeof (stackval) - -#define MAX_INT_ARG_REGS 6 -#define MAX_FLOAT_ARG_REGS 8 - -// TODO get these right. They are upper bounds anyway, so it doesn't much matter. -#define PUSH_INT_STACK_ARG_SIZE 16 -#define MOVE_INT_REG_ARG_SIZE 16 -#define PUSH_FLOAT_STACK_ARG_SIZE 16 -#define MOVE_FLOAT_REG_ARG_SIZE 16 -#define COPY_STRUCT_STACK_ARG_SIZE 16 - -/* Maps an argument number (starting at 0) to the register it is passed in (if it fits). - * E.g. int foo(int bar, int quux) has the foo arg in RDI and the quux arg in RSI - * There is no such map for floating point args as they go in XMM0-XMM7 in order and thus the - * index is the register number. - */ -static int int_arg_regs[] = { AMD64_RDI, AMD64_RSI, AMD64_RDX, AMD64_RCX, AMD64_R8, AMD64_R9 }; - -/* This next block of code resolves the ABI rules for passing structures in the argument registers. - * These basically amount to "Use up to two registers if they are all integer or all floating point. - * If the structure is bigger than two registers or would be in one integer register and one floating point, - * it is passed in memory instead. - * - * It is possible this code needs to be recursive to be correct in the case when one of the structure members - * is itself a structure. - * - * The 80-bit floating point stuff is ignored. - */ -typedef enum { - ARG_IN_MEMORY, - ARG_IN_INT_REGS, - ARG_IN_FLOAT_REGS -} struct_arg_type; - -static struct_arg_type compute_arg_type(MonoType *type) -{ - guint32 simpletype = type->type; - - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_I8: - return ARG_IN_INT_REGS; - break; - case MONO_TYPE_VALUETYPE: { - if (type->data.klass->enumtype) - return ARG_IN_INT_REGS; - return ARG_IN_MEMORY; - break; - } - case MONO_TYPE_R4: - case MONO_TYPE_R8: - return ARG_IN_FLOAT_REGS; - break; - default: - g_error ("Can't trampoline 0x%x", type->type); - } - - return ARG_IN_MEMORY; -} - -static struct_arg_type value_type_info(MonoClass *klass, int *native_size, int *regs_used, int *offset1, int *size1, int *offset2, int *size2) -{ - MonoMarshalType *info = mono_marshal_load_type_info (klass); - - *native_size = info->native_size; - - if (info->native_size > 8 || info->num_fields > 2) - { - *regs_used = 0; - *offset1 = -1; - *offset2 = -1; - return ARG_IN_MEMORY; - } - - if (info->num_fields == 1) - { - struct_arg_type result = compute_arg_type(info->fields[0].field->type); - if (result != ARG_IN_MEMORY) - { - *regs_used = 1; - *offset1 = info->fields[0].offset; - *size1 = mono_marshal_type_size (info->fields[0].field->type, info->fields[0].mspec, NULL, 1, 1); - } - else - { - *regs_used = 0; - *offset1 = -1; - } - - *offset2 = -1; - return result; - } - - struct_arg_type result1 = compute_arg_type(info->fields[0].field->type); - struct_arg_type result2 = compute_arg_type(info->fields[0].field->type); - - if (result1 == result2 && result1 != ARG_IN_MEMORY) - { - *regs_used = 2; - *offset1 = info->fields[0].offset; - *size1 = mono_marshal_type_size (info->fields[0].field->type, info->fields[0].mspec, NULL, 1, 1); - *offset2 = info->fields[1].offset; - *size2 = mono_marshal_type_size (info->fields[1].field->type, info->fields[1].mspec, NULL, 1, 1); - return result1; - } - - return ARG_IN_MEMORY; -} - -MonoPIFunc -mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) -{ - unsigned char *p, *code_buffer; - guint32 stack_size = 0, code_size = 50; - guint32 arg_pos, simpletype; - int i; - static GHashTable *cache = NULL; - MonoPIFunc res; - - guint32 int_arg_regs_used = 0; - guint32 float_arg_regs_used = 0; - guint32 next_int_arg_reg = 0; - guint32 next_float_arg_reg = 0; - /* Indicates that the return value is filled in inside the called function. */ - int retval_implicit = 0; - char *arg_in_reg_bitvector; /* A set index by argument number saying if it is in a register - (integer or floating point according to type) */ - - if (!cache) - cache = g_hash_table_new ((GHashFunc)mono_signature_hash, - (GCompareFunc)mono_metadata_signature_equal); - - if ((res = (MonoPIFunc)g_hash_table_lookup (cache, sig))) - return res; - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) { - int_arg_regs_used++; - code_size += MOVE_INT_REG_ARG_SIZE; - } - - if (sig->hasthis) { - int_arg_regs_used++; - code_size += MOVE_INT_REG_ARG_SIZE; - } - - /* Run through stuff to calculate code size and argument bytes that will be pushed on stack (stack_size). */ - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i]->type; -enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_I8: - if (int_arg_regs_used++ > MAX_INT_ARG_REGS) { - stack_size += 8; - code_size += PUSH_INT_STACK_ARG_SIZE; - } - else - code_size += MOVE_INT_REG_ARG_SIZE; - break; - case MONO_TYPE_VALUETYPE: { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - if (arg_type == ARG_IN_INT_REGS && - (int_arg_regs_used + regs_used) <= MAX_INT_ARG_REGS) - { - code_size += MOVE_INT_REG_ARG_SIZE; - int_arg_regs_used += regs_used; - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS && - (float_arg_regs_used + regs_used) <= MAX_FLOAT_ARG_REGS) - { - code_size += MOVE_FLOAT_REG_ARG_SIZE; - float_arg_regs_used += regs_used; - break; - } - - /* Else item is in memory. */ - - stack_size += size + 7; - stack_size &= ~7; - code_size += COPY_STRUCT_STACK_ARG_SIZE; - - break; - } - case MONO_TYPE_R4: - case MONO_TYPE_R8: - if (float_arg_regs_used++ > MAX_FLOAT_ARG_REGS) { - stack_size += 8; - code_size += PUSH_FLOAT_STACK_ARG_SIZE; - } - else - code_size += MOVE_FLOAT_REG_ARG_SIZE; - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - /* - * FIXME: take into account large return values. - * (Comment carried over from IA32 code. Not sure what it means :-) - */ - - code_buffer = p = alloca (code_size); - - /* - * Standard function prolog. - */ - amd64_push_reg (p, AMD64_RBP); - amd64_mov_reg_reg (p, AMD64_RBP, AMD64_RSP, 8); - /* - * and align to 16 byte boundary... - */ - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - retval_implicit = 1; - } - } - - if (sig->ret->byref || string_ctor || !(retval_implicit || sig->ret->type == MONO_TYPE_VOID)) { - /* Push the retval register so it is saved across the call. It will be addressed via RBP later. */ - amd64_push_reg (p, AMD64_RSI); - stack_size += 8; - } - - /* Ensure stack is 16 byte aligned when entering called function as required by calling convention. - * Getting this wrong results in a general protection fault on an SSE load or store somewhere in the - * code called under the trampoline. - */ - if ((stack_size & 15) != 0) - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, 16 - (stack_size & 15)); - - /* - * On entry to generated function: - * RDI has target function address - * RSI has return value location address - * RDX has this pointer address - * RCX has the pointer to the args array. - * - * Inside the stub function: - * R10 holds the pointer to the args - * R11 holds the target function address. - * The return value address is pushed on the stack. - * The this pointer is moved into the first arg register at the start. - * - * Optimization note: we could keep the args pointer in RCX and then - * load over itself at the end. Ditto the callee addres could be left in RDI in some cases. - */ - - /* Move args pointer to temp register. */ - amd64_mov_reg_reg (p, AMD64_R10, AMD64_RCX, 8); - amd64_mov_reg_reg (p, AMD64_R11, AMD64_RDI, 8); - - /* First args register gets return value pointer, if need be. - * Note that "byref" equal true means the called function returns a pointer. - */ - if (retval_implicit) { - amd64_mov_reg_reg (p, int_arg_regs[next_int_arg_reg], AMD64_RSI, 8); - next_int_arg_reg++; - } - - /* this pointer goes in next args register. */ - if (sig->hasthis) { - amd64_mov_reg_reg (p, int_arg_regs[next_int_arg_reg], AMD64_RDX, 8); - next_int_arg_reg++; - } - - /* - * Generate code to handle arguments in registers. Stack arguments will happen in a loop after this. - */ - arg_in_reg_bitvector = (char *)alloca((sig->param_count + 7) / 8); - memset(arg_in_reg_bitvector, 0, (sig->param_count + 7) / 8); - - /* First, load all the arguments that are passed in registers into the appropriate registers. - * Below there is another loop to handle arguments passed on the stack. - */ - for (i = 0; i < sig->param_count; i++) { - arg_pos = ARG_SIZE * i; - - if (sig->params [i]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i]->type; -enum_marshal: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_I8: - case MONO_TYPE_U8: - case MONO_TYPE_CLASS: - if (next_int_arg_reg < MAX_INT_ARG_REGS) { - amd64_mov_reg_membase (p, int_arg_regs[next_int_arg_reg], AMD64_R10, arg_pos, 8); - next_int_arg_reg++; - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - } - break; - case MONO_TYPE_R4: - if (next_float_arg_reg < MAX_FLOAT_ARG_REGS) { - amd64_movss_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos); - next_float_arg_reg++; - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - } - break; - case MONO_TYPE_R8: - if (next_float_arg_reg < MAX_FLOAT_ARG_REGS) { - amd64_movsd_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos); - next_float_arg_reg++; - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - } - break; - case MONO_TYPE_VALUETYPE: { - if (!sig->params [i]->data.klass->enumtype) { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS && - (next_int_arg_reg + regs_used) <= MAX_INT_ARG_REGS) - { - amd64_mov_reg_membase (p, int_arg_regs[next_int_arg_reg], AMD64_R10, arg_pos + offset1, size1); - next_int_arg_reg++; - if (regs_used > 1) - { - amd64_mov_reg_membase (p, int_arg_regs[next_int_arg_reg], AMD64_R10, arg_pos + offset2, size2); - next_int_arg_reg++; - } - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS && - (next_float_arg_reg + regs_used) <= MAX_FLOAT_ARG_REGS) - { - if (size1 == 4) - amd64_movss_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset1); - else - amd64_movsd_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset1); - next_float_arg_reg++; - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset2); - else - amd64_movsd_reg_membase (p, next_float_arg_reg, AMD64_R10, arg_pos + offset2); - next_float_arg_reg++; - } - arg_in_reg_bitvector[i >> 3] |= (1 << (i & 7)); - break; - } - - /* Structs in memory are handled in the next loop. */ - } else { - /* it's an enum value */ - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_marshal; - } - break; - } - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - /* Handle stack arguments, pushing the rightmost argument first. */ - for (i = sig->param_count; i > 0; --i) { - arg_pos = ARG_SIZE * (i - 1); - if (sig->params [i - 1]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i - 1]->type; -enum_marshal2: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_I8: - case MONO_TYPE_U8: - case MONO_TYPE_CLASS: - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) { - amd64_push_membase (p, AMD64_R10, arg_pos); - } - break; - case MONO_TYPE_R4: - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) { - amd64_push_membase (p, AMD64_R10, arg_pos); - } - break; - case MONO_TYPE_R8: - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) { - amd64_push_membase (p, AMD64_R10, arg_pos); - } - break; - case MONO_TYPE_VALUETYPE: - if (!sig->params [i - 1]->data.klass->enumtype) { - if ((arg_in_reg_bitvector[(i - 1) >> 3] & (1 << ((i - 1) & 7))) == 0) - { - int ss = mono_class_native_size (sig->params [i - 1]->data.klass, NULL); - ss += 7; - ss &= ~7; - - amd64_alu_reg_imm(p, X86_SUB, AMD64_RSP, ss); - /* Count register */ - amd64_mov_reg_imm(p, AMD64_RCX, ss); - /* Source register */ - amd64_lea_membase(p, AMD64_RSI, AMD64_R10, arg_pos); - /* Dest register */ - amd64_mov_reg_reg(p, AMD64_RDI, AMD64_RSP, 8); - - /* AMD64 calling convention guarantees direction flag is clear at call boundary. */ - x86_prefix(p, AMD64_REX(AMD64_REX_W)); - x86_prefix(p, X86_REP_PREFIX); - x86_movsb(p); - } - } else { - /* it's an enum value */ - simpletype = sig->params [i - 1]->data.klass->enum_basetype->type; - goto enum_marshal2; - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i - 1]->type); - } - } - - /* TODO: Set RAL to number of XMM registers used in case this is a varags function? */ - - /* - * Insert call to function - */ - amd64_call_reg (p, AMD64_R11); - - if (sig->ret->byref || string_ctor || !(retval_implicit || sig->ret->type == MONO_TYPE_VOID)) { - amd64_mov_reg_membase(p, AMD64_RSI, AMD64_RBP, -8, SIZEOF_VOID_P); - } - /* - * Handle retval. - * Small integer and pointer values are in EAX. - * Long integers are in EAX:EDX. - * FP values are on the FP stack. - */ - - if (sig->ret->byref || string_ctor) { - simpletype = MONO_TYPE_PTR; - } else { - simpletype = sig->ret->type; - } - enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_STRING: - case MONO_TYPE_PTR: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 8); - break; - case MONO_TYPE_R4: - amd64_movss_regp_reg (p, AMD64_RSI, AMD64_XMM0); - break; - case MONO_TYPE_R8: - amd64_movsd_regp_reg (p, AMD64_RSI, AMD64_XMM0); - break; - case MONO_TYPE_I8: - amd64_mov_regp_reg (p, AMD64_RSI, X86_EAX, 8); - break; - case MONO_TYPE_VALUETYPE: { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS) - { - amd64_mov_membase_reg (p, AMD64_RSI, offset1, AMD64_RAX, size1); - if (regs_used > 1) - amd64_mov_membase_reg (p, AMD64_RSI, offset2, AMD64_RDX, size2); - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS) - { - if (size1 == 4) - amd64_movss_membase_reg (p, AMD64_RSI, offset1, AMD64_XMM0); - else - amd64_movsd_membase_reg (p, AMD64_RSI, offset1, AMD64_XMM0); - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_membase_reg (p, AMD64_RSI, offset2, AMD64_XMM1); - else - amd64_movsd_membase_reg (p, AMD64_RSI, offset2, AMD64_XMM1); - } - break; - } - - /* Else result should have been stored in place already. */ - break; - } - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - - /* - * Standard epilog. - */ - amd64_leave (p); - amd64_ret (p); - - g_assert (p - code_buffer < code_size); - res = (MonoPIFunc)g_memdup (code_buffer, p - code_buffer); - - g_hash_table_insert (cache, sig, res); - - return res; -} - -/* - * Returns a pointer to a native function that can be used to - * call the specified method. - * The function created will receive the arguments according - * to the call convention specified in the method. - * This function works by creating a MonoInvocation structure, - * filling the fields in and calling ves_exec_method on it. - * Still need to figure out how to handle the exception stuff - * across the managed/unmanaged boundary. - */ -void * -mono_arch_create_method_pointer (MonoMethod *method) -{ - MonoMethodSignature *sig; - MonoJitInfo *ji; - unsigned char *p, *code_buffer; - guint32 simpletype; - gint32 local_size; - gint32 stackval_pos; - gint32 mono_invocation_pos; - int i, cpos; - int *vtbuf; - int *rbpoffsets; - int int_arg_regs_used = 0; - int float_arg_regs_used = 0; - int stacked_args_size = 0; /* bytes of register passed arguments pushed on stack for safe keeping. Used to get alignment right. */ - int next_stack_arg_rbp_offset = 16; - int retval_ptr_rbp_offset = 0; - int this_reg = -1; /* Remember register this ptr is in. */ - - /* - * If it is a static P/Invoke method, we can just return the pointer - * to the method implementation. - */ - if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && ((MonoMethodPInvoke*) method)->addr) { - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = 1; - ji->code_start = ((MonoMethodPInvoke*) method)->addr; - - mono_jit_info_table_add (mono_get_root_domain (), ji); - return ((MonoMethodPInvoke*) method)->addr; - } - - sig = method->signature; - - code_buffer = p = alloca (512); /* FIXME: check for overflows... */ - vtbuf = alloca (sizeof(int)*sig->param_count); - rbpoffsets = alloca (sizeof(int)*sig->param_count); - - - /* - * Standard function prolog. - */ - amd64_push_reg (p, AMD64_RBP); - amd64_mov_reg_reg (p, AMD64_RBP, AMD64_RSP, 8); - - /* If there is an implicit return value pointer in the first args reg, save it now so - * the result can be stored through the pointer at the end. - */ - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) - { - amd64_push_reg (p, int_arg_regs[int_arg_regs_used]); - int_arg_regs_used++; - stacked_args_size += 8; - retval_ptr_rbp_offset = -stacked_args_size; - } - - /* - * If there is a this pointer, remember the number of the register it is in. - */ - if (sig->hasthis) { - this_reg = int_arg_regs[int_arg_regs_used++]; - } - - /* Put all arguments passed in registers on the stack. - * Record offsets from RBP to each argument. - */ - cpos = 0; - - for (i = 0; i < sig->param_count; i++) { - if (sig->params [i]->byref) - simpletype = MONO_TYPE_PTR; - else - simpletype = sig->params [i]->type; -enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_I8: - if (int_arg_regs_used < MAX_INT_ARG_REGS) { - amd64_push_reg (p, int_arg_regs[int_arg_regs_used]); - int_arg_regs_used++; - stacked_args_size += 8; - rbpoffsets[i] = -stacked_args_size; - } - else - { - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += 8; - } - break; - case MONO_TYPE_VALUETYPE: { - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - else - { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS && - (int_arg_regs_used + regs_used) <= MAX_INT_ARG_REGS) - { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, size); - stacked_args_size += size; - rbpoffsets[i] = stacked_args_size; - - amd64_mov_reg_membase (p, int_arg_regs[int_arg_regs_used], AMD64_RSP, offset1, size1); - int_arg_regs_used++; - if (regs_used > 1) - { - amd64_mov_reg_membase (p, int_arg_regs[int_arg_regs_used], AMD64_RSP, offset2, size2); - int_arg_regs_used++; - } - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS && - (float_arg_regs_used + regs_used) <= MAX_FLOAT_ARG_REGS) - { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, size); - stacked_args_size += size; - rbpoffsets[i] = stacked_args_size; - - if (size1 == 4) - amd64_movss_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset1); - else - amd64_movsd_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset1); - float_arg_regs_used++; - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset2); - else - amd64_movsd_reg_membase (p, float_arg_regs_used, AMD64_RSP, offset2); - float_arg_regs_used++; - } - break; - } - - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += size; - } - break; - } - case MONO_TYPE_R4: - if (float_arg_regs_used < MAX_FLOAT_ARG_REGS) { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, 8); - amd64_movss_regp_reg (p, AMD64_RSP, float_arg_regs_used); - float_arg_regs_used++; - stacked_args_size += 8; - rbpoffsets[i] = -stacked_args_size; - } - else - { - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += 8; - } - break; - case MONO_TYPE_R8: - stacked_args_size += 8; - if (float_arg_regs_used < MAX_FLOAT_ARG_REGS) { - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, 8); - amd64_movsd_regp_reg (p, AMD64_RSP, float_arg_regs_used); - float_arg_regs_used++; - stacked_args_size += 8; - rbpoffsets[i] = -stacked_args_size; - } - else - { - rbpoffsets[i] = next_stack_arg_rbp_offset; - next_stack_arg_rbp_offset += 8; - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - local_size = sizeof (MonoInvocation) + sizeof (stackval) * (sig->param_count + 1) + stacked_args_size; - - local_size += 15; - local_size &= ~15; - - stackval_pos = -local_size; - mono_invocation_pos = stackval_pos + sizeof (stackval) * (sig->param_count + 1); - - /* stacked_args_size has already been pushed onto the stack. Make room for the rest of it. */ - amd64_alu_reg_imm (p, X86_SUB, AMD64_RSP, local_size - stacked_args_size); - - /* Be careful not to trash any arg regs before saving this_reg to MonoInvocation structure below. */ - - /* - * Initialize MonoInvocation fields, first the ones known now. - */ - amd64_alu_reg_reg (p, X86_XOR, AMD64_RAX, AMD64_RAX); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, ex)), AMD64_RAX, SIZEOF_VOID_P); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), AMD64_RAX, SIZEOF_VOID_P); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, parent)), AMD64_RAX, SIZEOF_VOID_P); - /* - * Set the method pointer. - */ - amd64_mov_membase_imm (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, method)), (long)method, SIZEOF_VOID_P); - - /* - * Handle this. - */ - if (sig->hasthis) - amd64_mov_membase_reg(p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, obj)), this_reg, SIZEOF_VOID_P); - - /* - * Handle the arguments. stackval_pos is the offset from RBP of the stackval in the MonoInvocation args array . - * arg_pos is the offset from RBP to the incoming arg on the stack. - * We just call stackval_from_data to handle all the (nasty) issues.... - */ - amd64_lea_membase (p, AMD64_RAX, AMD64_RBP, stackval_pos); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, stack_args)), AMD64_RAX, SIZEOF_VOID_P); - for (i = 0; i < sig->param_count; ++i) { -/* Need to call stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvoke); */ - amd64_mov_reg_imm (p, AMD64_R11, stackval_from_data); - amd64_mov_reg_imm (p, int_arg_regs[0], sig->params[i]); - amd64_lea_membase (p, int_arg_regs[1], AMD64_RBP, stackval_pos); - amd64_lea_membase (p, int_arg_regs[2], AMD64_RBP, rbpoffsets[i]); - amd64_mov_reg_imm (p, int_arg_regs[3], sig->pinvoke); - amd64_call_reg (p, AMD64_R11); - stackval_pos += sizeof (stackval); -#if 0 - /* fixme: alignment */ - if (sig->pinvoke) - arg_pos += mono_type_native_stack_size (sig->params [i], &align); - else - arg_pos += mono_type_stack_size (sig->params [i], &align); -#endif - } - - /* - * Handle the return value storage area. - */ - amd64_lea_membase (p, AMD64_RAX, AMD64_RBP, stackval_pos); - amd64_mov_membase_reg (p, AMD64_RBP, (mono_invocation_pos + G_STRUCT_OFFSET (MonoInvocation, retval)), AMD64_RAX, SIZEOF_VOID_P); - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - amd64_mov_reg_membase (p, AMD64_RCX, AMD64_RBP, retval_ptr_rbp_offset, SIZEOF_VOID_P); - amd64_mov_membase_reg (p, AMD64_RBP, stackval_pos, AMD64_RCX, SIZEOF_VOID_P); - } - } - - /* - * Call the method. - */ - amd64_lea_membase (p, int_arg_regs[0], AMD64_RBP, mono_invocation_pos); - amd64_mov_reg_imm (p, AMD64_R11, ves_exec_method); - amd64_call_reg (p, AMD64_R11); - - /* - * Move the return value to the proper place. - */ - amd64_lea_membase (p, AMD64_RAX, AMD64_RBP, stackval_pos); - if (sig->ret->byref) { - amd64_mov_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, SIZEOF_VOID_P); - } else { - int simpletype = sig->ret->type; - enum_retvalue: - switch (sig->ret->type) { - case MONO_TYPE_VOID: - break; - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 4); - break; - case MONO_TYPE_I8: - amd64_movzx_reg_membase (p, AMD64_RAX, AMD64_RAX, 0, 8); - break; - case MONO_TYPE_R4: - amd64_movss_regp_reg (p, AMD64_RAX, AMD64_XMM0); - break; - case MONO_TYPE_R8: - amd64_movsd_regp_reg (p, AMD64_RAX, AMD64_XMM0); - break; - case MONO_TYPE_VALUETYPE: { - int size; - int arg_type; - int regs_used; - int offset1; - int size1; - int offset2; - int size2; - - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - - arg_type = value_type_info(sig->params [i]->data.klass, &size, ®s_used, &offset1, &size1, &offset2, &size2); - - if (arg_type == ARG_IN_INT_REGS) - { - if (regs_used > 1) - amd64_mov_membase_reg (p, AMD64_RAX, offset2, AMD64_RDX, size2); - amd64_mov_membase_reg (p, AMD64_RAX, offset1, AMD64_RAX, size1); - break; - } - - if (arg_type == ARG_IN_FLOAT_REGS) - { - if (size1 == 4) - amd64_movss_membase_reg (p, AMD64_RAX, offset1, AMD64_XMM0); - else - amd64_movsd_membase_reg (p, AMD64_RAX, offset1, AMD64_XMM0); - - if (regs_used > 1) - { - if (size2 == 4) - amd64_movss_membase_reg (p, AMD64_RAX, offset2, AMD64_XMM1); - else - amd64_movsd_membase_reg (p, AMD64_RAX, offset2, AMD64_XMM1); - } - break; - } - - /* Else result should have been stored in place already. IA32 code has a stackval_to_data call here, which - * looks wrong to me as the pointer in the stack val being converted is setup to point to the output area anyway. - * It all looks a bit suspect anyway. - */ - break; - } - default: - g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); - break; - } - } - - /* - * Standard epilog. - */ - amd64_leave (p); - amd64_ret (p); - - g_assert (p - code_buffer < 512); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = p - code_buffer; - ji->code_start = g_memdup (code_buffer, p - code_buffer); - - mono_jit_info_table_add (mono_get_root_domain (), ji); - - return ji->code_start; -} diff --git a/mono/arch/ppc/Makefile.am b/mono/arch/ppc/Makefile.am index 667ad258d73..9b209ef9400 100644 --- a/mono/arch/ppc/Makefile.am +++ b/mono/arch/ppc/Makefile.am @@ -1,7 +1 @@ -AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) - -noinst_LTLIBRARIES = libmonoarch-ppc.la - -libmonoarch_ppc_la_SOURCES = tramp.c ppc-codegen.h - -noinst_PROGRAMS = test +EXTRA_DIST = ppc-codegen.h
\ No newline at end of file diff --git a/mono/arch/ppc/test.c b/mono/arch/ppc/test.c deleted file mode 100644 index c19358dcab0..00000000000 --- a/mono/arch/ppc/test.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "ppc-codegen.h" -#include <stdio.h> - -/* don't run the resulting program, it will destroy your computer, - * just objdump -d it to inspect we generated the correct assembler. - * On Mac OS X use otool[64] -v -t - */ - -int main() { - guint8 code [16000]; - guint8 *p = code; - guint8 *cp; - - printf (".text\n.align 4\n.globl main\n"); -#ifndef __APPLE__ - printf (".type main,@function\n"); -#endif - printf ("main:\n"); - - ppc_stwu (p, ppc_r1, -32, ppc_r1); - ppc_mflr (p, ppc_r0); - ppc_stw (p, ppc_r31, 28, ppc_r1); - ppc_or (p, ppc_r1, ppc_r2, ppc_r3); - ppc_mr (p, ppc_r31, ppc_r1); - ppc_lwz (p, ppc_r11, 0, ppc_r1); - ppc_mtlr (p, ppc_r0); - ppc_blr (p); - ppc_addi (p, ppc_r6, ppc_r6, 16); - - for (cp = code; cp < p; cp++) { - printf (".byte 0x%x\n", *cp); - } - - return 0; -} diff --git a/mono/arch/ppc/tramp.c b/mono/arch/ppc/tramp.c deleted file mode 100644 index 6bb1896255f..00000000000 --- a/mono/arch/ppc/tramp.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Create trampolines to invoke arbitrary functions. - * - * Copyright (C) Radek Doulik - * - */ - -#include "config.h" -#include <stdlib.h> -#include <string.h> -#include "ppc-codegen.h" -#include "mono/metadata/class.h" -#include "mono/metadata/tabledefs.h" -#include "mono/interpreter/interp.h" -#include "mono/metadata/appdomain.h" - -#ifdef NEED_MPROTECT -#include <sys/mman.h> -#include <limits.h> /* for PAGESIZE */ -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif -#endif - -#define DEBUG(x) - -/* gpointer -fake_func (gpointer (*callme)(gpointer), stackval *retval, void *this_obj, stackval *arguments) -{ - guint32 i = 0xc002becd; - - callme = (gpointer) 0x100fabcd; - - *(gpointer*)retval = (gpointer)(*callme) (arguments [0].data.p, arguments [1].data.p, arguments [2].data.p); - *(gdouble*) retval = (gdouble)(*callme) (arguments [0].data.f); - - return (gpointer) (*callme) (((MonoType *)arguments [0]. data.p)->data.klass); -} */ - -#define MIN_CACHE_LINE 8 - -static void inline -flush_icache (guint8 *code, guint size) -{ - guint i; - guint8 *p; - - p = code; - for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) { - asm ("dcbst 0,%0;" : : "r"(p) : "memory"); - } - asm ("sync"); - p = code; - for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) { - asm ("icbi 0,%0; sync;" : : "r"(p) : "memory"); - } - asm ("sync"); - asm ("isync"); -} - -static void -disassemble (guint8 *code, int size) -{ - int i; - FILE *ofd; - const char *tmp = g_getenv("TMP"); - char *as_file; - char *o_file; - char *cmd; - - if (tmp == NULL) - tmp = "/tmp"; - as_file = g_strdup_printf ("%s/test.s", tmp); - - if (!(ofd = fopen (as_file, "w"))) - g_assert_not_reached (); - - fprintf (ofd, "tmp:\n"); - - for (i = 0; i < size; ++i) - fprintf (ofd, ".byte %d\n", (unsigned int) code [i]); - - fclose (ofd); -#ifdef __APPLE__ -#define DIS_CMD "otool -V -v -t" -#else -#define DIS_CMD "objdump -d" -#endif - o_file = g_strdup_printf ("%s/test.o", tmp); - cmd = g_strdup_printf ("as %s -o %s", as_file, o_file); - system (cmd); - g_free (cmd); - cmd = g_strdup_printf (DIS_CMD " %s", o_file); - system (cmd); - g_free (cmd); - g_free (o_file); - g_free (as_file); -} - - -#define NOT_IMPLEMENTED(x) \ - g_error ("FIXME: %s is not yet implemented. (trampoline)", x); - -#define PROLOG_INS 8 -#define CALL_INS 2 -#define EPILOG_INS 6 -#define FLOAT_REGS 8 -#define GENERAL_REGS 8 -#ifdef __APPLE__ -#define MINIMAL_STACK_SIZE 10 -#define ALWAYS_ON_STACK(s) s -#define FP_ALSO_IN_REG(s) s -#define RET_ADDR_OFFSET 8 -#define STACK_PARAM_OFFSET 24 -#else -#define MINIMAL_STACK_SIZE 5 -#define ALWAYS_ON_STACK(s) -#define FP_ALSO_IN_REG(s) s -#define ALIGN_DOUBLES -#define RET_ADDR_OFFSET 4 -#define STACK_PARAM_OFFSET 8 -#endif - -static void inline -add_general (guint *gr, guint *stack_size, guint *code_size, gboolean simple) -{ - if (simple) { - if (*gr >= GENERAL_REGS) { - *stack_size += 4; - *code_size += 8; /* load from stack, save on stack */ - } else { - ALWAYS_ON_STACK (*stack_size += 4); - *code_size += 4; /* load from stack */ - } - } else { - if (*gr >= GENERAL_REGS - 1) { - *stack_size += 8; -#ifdef ALIGN_DOUBLES - *stack_size += (*stack_size % 8); -#endif - *code_size += 16; /* 2x load from stack, 2x save to stack */ - } else { - ALWAYS_ON_STACK (*stack_size += 8); - *code_size += 8; /* 2x load from stack */ - } -#ifdef ALIGN_DOUBLES - if ((*gr) & 1) - (*gr) ++; -#endif - (*gr) ++; - } - (*gr) ++; -} - -static void inline -calculate_sizes (MonoMethodSignature *sig, guint *stack_size, guint *code_size, gboolean string_ctor, gboolean *use_memcpy) -{ - guint i, fr, gr; - guint32 simpletype; - - fr = gr = 0; - *stack_size = MINIMAL_STACK_SIZE*4; - *code_size = (PROLOG_INS + CALL_INS + EPILOG_INS)*4; - - if (sig->hasthis) { - add_general (&gr, stack_size, code_size, TRUE); - } - DEBUG(printf("params: %d\n", sig->param_count)); - for (i = 0; i < sig->param_count; ++i) { - DEBUG(printf("param %d: ", i)); - if (sig->params [i]->byref) { - DEBUG(printf("byref\n")); - add_general (&gr, stack_size, code_size, TRUE); - continue; - } - simpletype = sig->params [i]->type; - enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - add_general (&gr, stack_size, code_size, TRUE); - break; - case MONO_TYPE_SZARRAY: - add_general (&gr, stack_size, code_size, TRUE); - *code_size += 4; - break; - case MONO_TYPE_VALUETYPE: { - gint size; - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - size = mono_class_value_size (sig->params [i]->data.klass, NULL); - if (size != 4) { - DEBUG(printf ("copy %d bytes struct on stack\n", - mono_class_value_size (sig->params [i]->data.klass, NULL))); - *use_memcpy = TRUE; - *code_size += 8*4; - *stack_size += (size + 3) & (~3); - if (gr > GENERAL_REGS) { - *code_size += 4; - *stack_size += 4; - } - } else { - DEBUG(printf ("load %d bytes struct\n", - mono_class_value_size (sig->params [i]->data.klass, NULL))); - add_general (&gr, stack_size, code_size, TRUE); - *code_size += 4; - } - break; - } - case MONO_TYPE_I8: - add_general (&gr, stack_size, code_size, FALSE); - break; - case MONO_TYPE_R4: - if (fr < 7) { - *code_size += 4; - fr ++; - FP_ALSO_IN_REG (gr ++); - ALWAYS_ON_STACK (*stack_size += 4); - } else { - NOT_IMPLEMENTED ("R4 arg"); - } - break; - case MONO_TYPE_R8: - if (fr < 7) { - *code_size += 4; - fr ++; - FP_ALSO_IN_REG (gr += 2); - ALWAYS_ON_STACK (*stack_size += 8); - } else { - NOT_IMPLEMENTED ("R8 arg"); - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - if (sig->ret->byref || string_ctor) { - *code_size += 8; - } else { - simpletype = sig->ret->type; -enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_R4: - case MONO_TYPE_R8: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_STRING: - *code_size += 8; - break; - case MONO_TYPE_I8: - *code_size += 12; - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - *code_size += 2*4; - break; - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - } - - if (*use_memcpy) { - *stack_size += 2*4; /* for r14, r15 */ - *code_size += 6*4; - if (sig->hasthis) { - *stack_size += 4; /* for r16 */ - *code_size += 4; - } - } - - /* align stack size to 16 */ - DEBUG (printf (" stack size: %d (%d)\n code size: %d\n", (*stack_size + 15) & ~15, *stack_size, *code_size)); - *stack_size = (*stack_size + 15) & ~15; -} - -static inline guint8 * -emit_prolog (guint8 *p, MonoMethodSignature *sig, guint stack_size) -{ - /* function prolog */ - ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */ - ppc_mflr (p, ppc_r0); /* r0 <--- LR */ - ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */ - ppc_stw (p, ppc_r0, stack_size + RET_ADDR_OFFSET, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */ - ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */ - - return p; -} - -#define ARG_BASE ppc_r12 -#define ARG_SIZE sizeof (stackval) -#define SAVE_4_IN_GENERIC_REGISTER \ - if (gr < GENERAL_REGS) { \ - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); \ - gr ++; \ - ALWAYS_ON_STACK (stack_par_pos += 4); \ - } else { \ - ppc_lwz (p, ppc_r11, i*ARG_SIZE, ARG_BASE); \ - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \ - stack_par_pos += 4; \ - } -#define SAVE_4_VAL_IN_GENERIC_REGISTER \ - if (gr < GENERAL_REGS) { \ - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); \ - ppc_lwz (p, ppc_r3 + gr, 0, ppc_r3 + gr); \ - gr ++; \ - ALWAYS_ON_STACK (stack_par_pos += 4); \ - } else { \ - ppc_lwz (p, ppc_r11, i*ARG_SIZE, ARG_BASE); \ - ppc_lwz (p, ppc_r11, 0, ppc_r11); \ - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \ - stack_par_pos += 4; \ - } - -inline static guint8* -emit_save_parameters (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean use_memcpy) -{ - guint i, fr, gr, stack_par_pos, struct_pos, cur_struct_pos; - guint32 simpletype; - - fr = gr = 0; - stack_par_pos = STACK_PARAM_OFFSET; - - ppc_stw (p, ppc_r4, stack_size - 12, ppc_r31); /* preserve "retval", sp[+8] */ - - if (use_memcpy) { - ppc_stw (p, ppc_r14, stack_size - 16, ppc_r31); /* save r14 */ - ppc_stw (p, ppc_r15, stack_size - 20, ppc_r31); /* save r15 */ - ppc_mr (p, ppc_r14, ppc_r3); /* keep "callme" in register */ - ppc_mr (p, ppc_r15, ppc_r6); /* keep "arguments" in register */ - } else { - ppc_mr (p, ppc_r12, ppc_r6); /* keep "arguments" in register */ - ppc_mr (p, ppc_r0, ppc_r3); /* keep "callme" in register */ - } - - if (sig->hasthis) { - if (use_memcpy) { - ppc_stw (p, ppc_r16, stack_size - 24, ppc_r31); /* save r16 */ - ppc_mr (p, ppc_r16, ppc_r5); - } else - ppc_mr (p, ppc_r3, ppc_r5); - gr ++; - ALWAYS_ON_STACK (stack_par_pos += 4); - } - - if (use_memcpy) { - cur_struct_pos = struct_pos = stack_par_pos; - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) - continue; - if (sig->params [i]->type == MONO_TYPE_VALUETYPE && !sig->params [i]->data.klass->enumtype) { - gint size; - - size = mono_class_value_size (sig->params [i]->data.klass, NULL); - if (size != 4) { - /* call memcpy */ - ppc_addi (p, ppc_r3, ppc_r1, stack_par_pos); - ppc_lwz (p, ppc_r4, i*16, ppc_r15); - /* FIXME check if size > 0xffff */ - ppc_li (p, ppc_r5, size & 0xffff); - ppc_lis (p, ppc_r0, (guint32) memcpy >> 16); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) memcpy & 0xffff); - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - stack_par_pos += (size + 3) & (~3); - } - } - } - - if (sig->hasthis) { - ppc_mr (p, ppc_r3, ppc_r16); - ppc_lwz (p, ppc_r16, stack_size - 24, ppc_r31); /* restore r16 */ - } - ppc_mr (p, ppc_r0, ppc_r14); - ppc_mr (p, ppc_r12, ppc_r15); - ppc_lwz (p, ppc_r14, stack_size - 16, ppc_r31); /* restore r14 */ - ppc_lwz (p, ppc_r15, stack_size - 20, ppc_r31); /* restore r15 */ - } - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - gint size = mono_class_native_size (klass, NULL); - - DEBUG(printf ("retval value type size: %d\n", size)); - if (size > 8) { - ppc_lwz (p, ppc_r3, stack_size - 12, ppc_r31); - ppc_lwz (p, ppc_r3, 0, ppc_r3); - gr ++; - ALWAYS_ON_STACK (stack_par_pos += 4); - } else { - NOT_IMPLEMENTED ("retval valuetype <= 8 bytes"); - } - } - } - - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) { - SAVE_4_IN_GENERIC_REGISTER; - continue; - } - simpletype = sig->params [i]->type; - enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_SZARRAY: - SAVE_4_IN_GENERIC_REGISTER; - break; - case MONO_TYPE_VALUETYPE: { - gint size; - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - size = mono_class_value_size (sig->params [i]->data.klass, NULL); - if (size == 4) { - SAVE_4_VAL_IN_GENERIC_REGISTER; - } else { - if (gr < GENERAL_REGS) { - ppc_addi (p, ppc_r3 + gr, ppc_r1, cur_struct_pos); - gr ++; - } else { - ppc_lwz (p, ppc_r11, cur_struct_pos, ppc_r1); - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); - stack_par_pos += 4; - } - cur_struct_pos += (size + 3) & (~3); - } - break; - } - case MONO_TYPE_I8: -DEBUG(printf("Mono_Type_i8. gr = %d, arg_base = %d\n", gr, ARG_BASE)); -#ifdef ALIGN_DOUBLES - if (gr & 1) - gr++; -#endif - if (gr < 7) { - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); - ppc_lwz (p, ppc_r3 + gr + 1, i*ARG_SIZE + 4, ARG_BASE); - ALWAYS_ON_STACK (stack_par_pos += 8); - } else if (gr == 7) { - ppc_lwz (p, ppc_r3 + gr, i*ARG_SIZE, ARG_BASE); - ppc_lwz (p, ppc_r11, i*ARG_SIZE + 4, ARG_BASE); - ppc_stw (p, ppc_r11, stack_par_pos + 4, ppc_r1); - stack_par_pos += 8; - } else { - ppc_lwz (p, ppc_r11, i*ARG_SIZE, ARG_BASE); - ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); - ppc_lwz (p, ppc_r11, i*ARG_SIZE + 4, ARG_BASE); - ppc_stw (p, ppc_r11, stack_par_pos + 4, ppc_r1); - stack_par_pos += 8; - } - gr += 2; - break; - case MONO_TYPE_R4: - if (fr < 7) { - ppc_lfs (p, ppc_f1 + fr, i*ARG_SIZE, ARG_BASE); - fr ++; - FP_ALSO_IN_REG (gr ++); - ALWAYS_ON_STACK (stack_par_pos += 4); - } else { - NOT_IMPLEMENTED ("r4 on stack"); - } - break; - case MONO_TYPE_R8: - if (fr < 7) { - ppc_lfd (p, ppc_f1 + fr, i*ARG_SIZE, ARG_BASE); - fr ++; - FP_ALSO_IN_REG (gr += 2); - ALWAYS_ON_STACK (stack_par_pos += 8); - } else { - NOT_IMPLEMENTED ("r8 on stack"); - } - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - - return p; -} - -static inline guint8 * -alloc_code_memory (guint code_size) -{ - guint8 *p; - -#ifdef NEED_MPROTECT - p = g_malloc (code_size + PAGESIZE - 1); - - /* Align to a multiple of PAGESIZE, assumed to be a power of two */ - p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1)); -#else - p = g_malloc (code_size); -#endif - DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4)); - - return p; -} - -/* static MonoString* -mono_string_new_wrapper (const char *text) -{ - return text ? mono_string_new (mono_domain_get (), text) : NULL; -} */ - -static inline guint8 * -emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean string_ctor) -{ - guint32 simpletype; - - /* call "callme" */ - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - - /* get return value */ - if (sig->ret->byref || string_ctor) { - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - } else { - simpletype = sig->ret->type; -enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stb (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_sth (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_STRING: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_R4: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stfs (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */ - break; - case MONO_TYPE_R8: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stfd (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */ - break; - case MONO_TYPE_I8: - ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */ - ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */ - ppc_stw (p, ppc_r4, 4, ppc_r9); /* save return value (r3) to "retval" */ - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - break; - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - } - - return p; -} - -static inline guint8 * -emit_epilog (guint8 *p, MonoMethodSignature *sig, guint stack_size) -{ - /* function epilog */ - ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */ - ppc_lwz (p, ppc_r0, RET_ADDR_OFFSET, ppc_r11); /* r0 <--- r11[4] load return address */ - ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */ - ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */ - ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */ - ppc_blr (p); /* return */ - - return p; -} - -MonoPIFunc -mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) -{ - guint8 *p, *code_buffer; - guint stack_size, code_size; - gboolean use_memcpy = FALSE; - - DEBUG (printf ("\nPInvoke [start emiting]\n")); - calculate_sizes (sig, &stack_size, &code_size, string_ctor, &use_memcpy); - - p = code_buffer = alloc_code_memory (code_size); - p = emit_prolog (p, sig, stack_size); - p = emit_save_parameters (p, sig, stack_size, use_memcpy); - p = emit_call_and_store_retval (p, sig, stack_size, string_ctor); - p = emit_epilog (p, sig, stack_size); - - /* { - guchar *cp; - printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n"); - for (cp = code_buffer; cp < p; cp++) { - printf (".byte 0x%x\n", *cp); - } - } */ - -#ifdef NEED_MPROTECT - if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) { - g_error ("Cannot mprotect trampoline\n"); - } -#endif - - DEBUG (printf ("emited code size: %d\n", p - code_buffer)); - flush_icache (code_buffer, p - code_buffer); - - DEBUG (printf ("PInvoke [end emiting]\n")); - - return (MonoPIFunc) code_buffer; - /* return fake_func; */ -} - - -#ifdef __APPLE__ -#define MINV_POS 40 /* MonoInvocation structure offset on stack - STACK_PARAM_OFFSET + 4 pointer args for stackval_from_data */ -#else -#define MINV_POS 8 /* MonoInvocation structure offset on stack */ -#endif -#define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count) -#define OBJ_POS 8 -#define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type)) - -/* - * Returns a pointer to a native function that can be used to - * call the specified method. - * The function created will receive the arguments according - * to the call convention specified in the method. - * This function works by creating a MonoInvocation structure, - * filling the fields in and calling ves_exec_method on it. - * Still need to figure out how to handle the exception stuff - * across the managed/unmanaged boundary. - */ -void * -mono_arch_create_method_pointer (MonoMethod *method) -{ - MonoMethodSignature *sig; - MonoJitInfo *ji; - guint8 *p, *code_buffer; - guint i, align = 0, code_size, stack_size, stackval_arg_pos, local_pos, local_start, reg_param = 0, stack_param, - cpos, vt_cur; - gint *vtbuf; - guint32 simpletype; - - code_size = 1024; - stack_size = 1024; - stack_param = 0; - - sig = mono_method_signature (method); - - p = code_buffer = g_malloc (code_size); - - DEBUG (printf ("\nDelegate [start emiting] %s\n", mono_method_get_name (method))); - - /* prolog */ - ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */ - ppc_mflr (p, ppc_r0); /* r0 <--- LR */ - ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */ - ppc_stw (p, ppc_r0, stack_size + RET_ADDR_OFFSET, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */ - ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */ - - /* let's fill MonoInvocation */ - /* first zero some fields */ - ppc_li (p, ppc_r0, 0); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)), ppc_r31); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), ppc_r31); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)), ppc_r31); - - /* set method pointer */ - ppc_lis (p, ppc_r0, (guint32) method >> 16); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) method & 0xffff); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)), ppc_r31); - - local_start = local_pos = MINV_POS + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval); - - if (sig->hasthis) { - ppc_stw (p, ppc_r3, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)), ppc_r31); - reg_param = 1; - } - - if (sig->param_count) { - gint save_count = MIN (8, sig->param_count + sig->hasthis); - for (i = reg_param; i < save_count; i ++) { - ppc_stw (p, ppc_r3 + i, local_pos, ppc_r31); - local_pos += 4; - DEBUG (printf ("save r%d\n", 4 + i)); - } - } - - /* prepare space for valuetypes */ - vt_cur = local_pos; - vtbuf = alloca (sizeof(int)*sig->param_count); - cpos = 0; - for (i = 0; i < sig->param_count; i++) { - MonoType *type = sig->params [i]; - vtbuf [i] = -1; - if (type->type == MONO_TYPE_VALUETYPE) { - MonoClass *klass = type->data.klass; - gint size; - - if (klass->enumtype) - continue; - size = mono_class_native_size (klass, &align); - cpos += align - 1; - cpos &= ~(align - 1); - vtbuf [i] = cpos; - cpos += size; - } - } - cpos += 3; - cpos &= ~3; - - local_pos += cpos; - - /* set MonoInvocation::stack_args */ - stackval_arg_pos = MINV_POS + sizeof (MonoInvocation); - ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos); - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)), ppc_r31); - - /* add stackval arguments */ - for (i = 0; i < sig->param_count; ++i) { - if (reg_param < 8) { - ppc_addi (p, ppc_r5, ppc_r31, local_start + i*4); - reg_param ++; - } else { - ppc_addi (p, ppc_r5, stack_size + 8 + stack_param, ppc_r31); - stack_param ++; - } - ppc_lis (p, ppc_r3, (guint32) sig->params [i] >> 16); - - if (vtbuf [i] >= 0) { - ppc_addi (p, ppc_r4, ppc_r31, vt_cur); - ppc_stw (p, ppc_r4, stackval_arg_pos, ppc_r31); - ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos); - ppc_lwz (p, ppc_r5, 0, ppc_r5); - vt_cur += vtbuf [i]; - } else { - ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos); - } - ppc_ori (p, ppc_r3, ppc_r3, (guint32) sig->params [i] & 0xffff); - ppc_lis (p, ppc_r0, (guint32) stackval_from_data >> 16); - ppc_li (p, ppc_r6, sig->pinvoke); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) stackval_from_data & 0xffff); - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - - stackval_arg_pos += sizeof (stackval); - } - - /* return value storage */ - if (sig->param_count) { - ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos); - } - ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)), ppc_r31); - - /* call ves_exec_method */ - ppc_lis (p, ppc_r0, (guint32) ves_exec_method >> 16); - ppc_addi (p, ppc_r3, ppc_r31, MINV_POS); - ppc_ori (p, ppc_r0, ppc_r0, (guint32) ves_exec_method & 0xffff); - ppc_mtlr (p, ppc_r0); - ppc_blrl (p); - - /* move retval from stackval to proper place (r3/r4/...) */ - if (sig->ret->byref) { - DEBUG (printf ("ret by ref\n")); - ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31); - } else { - enum_retvalue: - switch (sig->ret->type) { - case MONO_TYPE_VOID: - break; - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - ppc_lbz (p, ppc_r3, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - ppc_lhz (p, ppc_r3, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_I8: - ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31); - ppc_lwz (p, ppc_r4, stackval_arg_pos + 4, ppc_r31); - break; - case MONO_TYPE_R4: - ppc_lfs (p, ppc_f1, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_R8: - ppc_lfd (p, ppc_f1, stackval_arg_pos, ppc_r31); - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - NOT_IMPLEMENTED ("value type as ret val from delegate"); - break; - default: - g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); - break; - } - } - - /* epilog */ - ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */ - ppc_lwz (p, ppc_r0, RET_ADDR_OFFSET, ppc_r11); /* r0 <--- r11[4] load return address */ - ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */ - ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */ - ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */ - ppc_blr (p); /* return */ - - DEBUG (printf ("emited code size: %d\n", p - code_buffer)); - DEBUG (disassemble (code_buffer, p - code_buffer)); - flush_icache (code_buffer, p - code_buffer); - - DEBUG (printf ("Delegate [end emiting]\n")); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = p - code_buffer; - ji->code_start = code_buffer; - - mono_jit_info_table_add (mono_get_root_domain (), ji); - - return ji->code_start; -} diff --git a/mono/arch/x86/Makefile.am b/mono/arch/x86/Makefile.am index e88506e4cd8..bab0f9e54d6 100644 --- a/mono/arch/x86/Makefile.am +++ b/mono/arch/x86/Makefile.am @@ -1,5 +1 @@ -AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) - -noinst_LTLIBRARIES = libmonoarch-x86.la - -libmonoarch_x86_la_SOURCES = tramp.c x86-codegen.h +EXTRA_DIST = x86-codegen.h
\ No newline at end of file diff --git a/mono/arch/x86/test.c b/mono/arch/x86/test.c deleted file mode 100644 index 3511e8fdaf0..00000000000 --- a/mono/arch/x86/test.c +++ /dev/null @@ -1,225 +0,0 @@ -#include "x86-codegen.h" -#include <stdio.h> - -/* don't run the resulting program, it will destroy your computer, - * just objdump -d it to inspect we generated the correct assembler. - */ - -int main() { - unsigned char code [16000]; - unsigned char *p = code; - unsigned char *target, *start, *end; - unsigned long mem_addr = 0xdeadbeef; - int size, i; - - printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n"); - - x86_prolog (p, 16, X86_CALLER_REGS); - - x86_cmpxchg_reg_reg (p, X86_EAX, X86_EBP); - x86_cmpxchg_membase_reg (p, X86_EAX, 12, X86_EBP); - - x86_xchg_reg_reg (p, X86_EAX, X86_EBP, 4); - x86_xchg_reg_reg (p, X86_EAX, X86_EBP, 1); // FIXME? - x86_xchg_membase_reg (p, X86_EAX, 12, X86_EBP, 4); - x86_xchg_membase_reg (p, X86_EAX, 12, X86_EBP, 2); - x86_xchg_membase_reg (p, X86_EAX, 12, X86_EBX, 1); // FIXME? - - x86_inc_reg (p, X86_EAX); - x86_inc_mem (p, mem_addr); - x86_inc_membase (p, X86_ESP, 4); - - x86_nop (p); - x86_nop (p); - - x86_dec_reg (p, X86_EAX); - x86_dec_reg (p, X86_ECX); - x86_dec_mem (p, mem_addr); - x86_dec_membase (p, X86_ESP, 4); - - x86_not_reg (p, X86_EDX); - x86_not_reg (p, X86_ECX); - x86_not_mem (p, mem_addr); - x86_not_membase (p, X86_ESP, 4); - x86_not_membase (p, X86_ESP, 0x4444444); - x86_not_membase (p, X86_EBP, 0x4444444); - x86_not_membase (p, X86_ECX, 0x4444444); - x86_not_membase (p, X86_EDX, 0); - x86_not_membase (p, X86_EBP, 0); - - x86_neg_reg (p, X86_EAX); - x86_neg_reg (p, X86_ECX); - x86_neg_mem (p, mem_addr); - x86_neg_membase (p, X86_ESP, 8); - - x86_alu_reg_imm (p, X86_ADD, X86_EAX, 5); - x86_alu_reg_imm (p, X86_ADD, X86_EBX, -10); - x86_alu_reg_imm (p, X86_SUB, X86_EDX, 7); - x86_alu_reg_imm (p, X86_OR, X86_ESP, 0xffffedaf); - x86_alu_reg_imm (p, X86_CMP, X86_ECX, 1); - x86_alu_mem_imm (p, X86_ADC, mem_addr, 2); - x86_alu_membase_imm (p, X86_ADC, X86_ESP, -4, 4); - x86_alu_membase_imm (p, X86_ADC, X86_ESP, -12, 0xffffedaf); - - x86_alu_mem_reg (p, X86_SUB, mem_addr, X86_EDX); - x86_alu_reg_reg (p, X86_ADD, X86_EAX, X86_EBX); - x86_alu_reg_mem (p, X86_ADD, X86_EAX, mem_addr); - x86_alu_reg_imm (p, X86_ADD, X86_EAX, 0xdeadbeef); - x86_alu_reg_membase (p, X86_XOR, X86_EDX, X86_ESP, 4); - x86_alu_membase_reg (p, X86_XOR, X86_EBP, 8, X86_ESI); - - x86_test_reg_imm (p, X86_EAX, 16); - x86_test_reg_imm (p, X86_EDX, -16); - x86_test_mem_imm (p, mem_addr, 1); - x86_test_membase_imm (p, X86_EBP, 8, 1); - - x86_test_reg_reg (p, X86_EAX, X86_EDX); - x86_test_mem_reg (p, mem_addr, X86_EDX); - x86_test_membase_reg (p, X86_ESI, 4, X86_EDX); - - x86_shift_reg_imm (p, X86_SHL, X86_EAX, 1); - x86_shift_reg_imm (p, X86_SHL, X86_EDX, 2); - - x86_shift_mem_imm (p, X86_SHL, mem_addr, 2); - x86_shift_membase_imm (p, X86_SHLR, X86_EBP, 8, 4); - - /* - * Shift by CL - */ - x86_shift_reg (p, X86_SHL, X86_EAX); - x86_shift_mem (p, X86_SHL, mem_addr); - - x86_mul_reg (p, X86_EAX, 0); - x86_mul_reg (p, X86_EAX, 1); - x86_mul_membase (p, X86_EBP, 8, 1); - - x86_imul_reg_reg (p, X86_EBX, X86_EDX); - x86_imul_reg_membase (p, X86_EBX, X86_EBP, 12); - - x86_imul_reg_reg_imm (p, X86_EBX, X86_EDX, 10); - x86_imul_reg_mem_imm (p, X86_EBX, mem_addr, 20); - x86_imul_reg_membase_imm (p, X86_EBX, X86_EBP, 16, 300); - - x86_div_reg (p, X86_EDX, 0); - x86_div_reg (p, X86_EDX, 1); - x86_div_mem (p, mem_addr, 1); - x86_div_membase (p, X86_ESI, 4, 1); - - x86_mov_mem_reg (p, mem_addr, X86_EAX, 4); - x86_mov_mem_reg (p, mem_addr, X86_EAX, 2); - x86_mov_mem_reg (p, mem_addr, X86_EAX, 1); - x86_mov_membase_reg (p, X86_EBP, 4, X86_EAX, 1); - - x86_mov_regp_reg (p, X86_EAX, X86_EAX, 4); - x86_mov_membase_reg (p, X86_EAX, 0, X86_EAX, 4); - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - x86_mov_reg_memindex (p, X86_ECX, X86_EAX, 34, X86_EDX, 2, 4); - x86_mov_reg_memindex (p, X86_ECX, X86_NOBASEREG, 34, X86_EDX, 2, 4); - x86_mov_memindex_reg (p, X86_EAX, X86_EAX, 0, X86_EDX, 2, 4); - x86_mov_reg_reg (p, X86_EAX, X86_EAX, 1); - x86_mov_reg_reg (p, X86_EAX, X86_EAX, 4); - x86_mov_reg_mem (p, X86_EAX, mem_addr, 4); - - x86_mov_reg_imm (p, X86_EAX, 10); - x86_mov_mem_imm (p, mem_addr, 54, 4); - x86_mov_mem_imm (p, mem_addr, 54, 1); - - x86_lea_mem (p, X86_EDX, mem_addr); - /* test widen */ - x86_widen_memindex (p, X86_EDX, X86_ECX, 0, X86_EBX, 2, 1, 0); - - x86_cdq (p); - x86_wait (p); - - x86_fp_op_mem (p, X86_FADD, mem_addr, 1); - x86_fp_op_mem (p, X86_FSUB, mem_addr, 0); - x86_fp_op (p, X86_FSUB, 2); - x86_fp_op_reg (p, X86_FMUL, 1, 0); - x86_fstp (p, 2); - x86_fcompp (p); - x86_fnstsw (p); - x86_fnstcw (p, mem_addr); - x86_fnstcw_membase (p, X86_ESP, -8); - - x86_fldcw_membase (p, X86_ESP, -8); - x86_fchs (p); - x86_frem (p); - x86_fxch (p, 3); - x86_fcomip (p, 3); - x86_fld_membase (p, X86_ESP, -8, 1); - x86_fld_membase (p, X86_ESP, -8, 0); - x86_fld80_membase (p, X86_ESP, -8); - x86_fild_membase (p, X86_ESP, -8, 1); - x86_fild_membase (p, X86_ESP, -8, 0); - x86_fld_reg (p, 4); - x86_fldz (p); - x86_fld1 (p); - - x86_fst (p, mem_addr, 1, 0); - x86_fst (p, mem_addr, 1, 1); - x86_fst (p, mem_addr, 0, 1); - - x86_fist_pop_membase (p, X86_EDX, 4, 1); - x86_fist_pop_membase (p, X86_EDX, 4, 0); - - x86_push_reg (p, X86_EBX); - x86_push_membase (p, X86_EBP, 8); - x86_push_imm (p, -1); - x86_pop_reg (p, X86_EBX); - - x86_pushad (p); - x86_pushfd (p); - x86_popfd (p); - x86_popad (p); - - target = p; - - start = p; - x86_jump32 (p, mem_addr); - x86_patch (start, target); - start = p; - x86_jump8 (p, 12); - x86_patch (start, target); - x86_jump_reg (p, X86_EAX); - x86_jump_membase (p, X86_EDX, 16); - - x86_jump_code (p, target); - - x86_branch8 (p, X86_CC_EQ, 54, 1); - x86_branch32 (p, X86_CC_LT, 54, 0); - x86_branch (p, X86_CC_GT, target, 0); - x86_branch_disp (p, X86_CC_NE, -4, 0); - - x86_set_reg (p, X86_CC_EQ, X86_EAX, 0); - x86_set_membase (p, X86_CC_LE, X86_EBP, -8, 0); - - x86_call_code (p, printf); - x86_call_reg (p, X86_ECX); - - x86_sahf (p); - - x86_fsin (p); - x86_fcos (p); - x86_fabs (p); - x86_fpatan (p); - x86_fprem (p); - x86_fprem1 (p); - x86_frndint (p); - x86_fsqrt (p); - x86_fptan (p); - - x86_leave (p); - x86_ret (p); - x86_ret_imm (p, 24); - - x86_cmov_reg (p, X86_CC_GT, 1, X86_EAX, X86_EDX); - x86_cmov_membase (p, X86_CC_GT, 0, X86_EAX, X86_EDX, -4); - - x86_nop (p); - x86_epilog (p, X86_CALLER_REGS); - - size = p-code; - for (i = 0; i < size; ++i) - printf (".byte %d\n", (unsigned int) code [i]); - return 0; -} diff --git a/mono/arch/x86/tramp.c b/mono/arch/x86/tramp.c deleted file mode 100644 index fab5a55325f..00000000000 --- a/mono/arch/x86/tramp.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Create trampolines to invoke arbitrary functions. - * - * Copyright (C) Ximian Inc. - * - * Authors: - * Paolo Molaro (lupus@ximian.com) - * Dietmar Maurer (dietmar@ximian.com) - * - */ - -#include "config.h" -#include <stdlib.h> -#include <string.h> -#include "x86-codegen.h" -#include "mono/metadata/class.h" -#include "mono/metadata/tabledefs.h" -#include "mono/interpreter/interp.h" -#include "mono/metadata/appdomain.h" -#include "mono/metadata/marshal.h" - -/* - * The resulting function takes the form: - * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments); - */ -#define FUNC_ADDR_POS 8 -#define RETVAL_POS 12 -#define THIS_POS 16 -#define ARGP_POS 20 -#define LOC_POS -4 - -#define ARG_SIZE sizeof (stackval) - -MonoPIFunc -mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor) -{ - unsigned char *p, *code_buffer; - guint32 stack_size = 0, code_size = 50; - guint32 arg_pos, simpletype; - int i, stringp; - static GHashTable *cache = NULL; - MonoPIFunc res; - - if (!cache) - cache = g_hash_table_new ((GHashFunc)mono_signature_hash, - (GCompareFunc)mono_metadata_signature_equal); - - if ((res = (MonoPIFunc)g_hash_table_lookup (cache, sig))) - return res; - - if (sig->hasthis) { - stack_size += sizeof (gpointer); - code_size += 10; - } - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) { - stack_size += sizeof (gpointer); - code_size += 5; - } - - for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) { - stack_size += sizeof (gpointer); - code_size += 20; - continue; - } - simpletype = sig->params [i]->type; -enum_calc_size: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - stack_size += 4; - code_size += i < 10 ? 5 : 8; - break; - case MONO_TYPE_VALUETYPE: { - int size; - if (sig->params [i]->data.klass->enumtype) { - simpletype = sig->params [i]->data.klass->enum_basetype->type; - goto enum_calc_size; - } - if ((size = mono_class_native_size (sig->params [i]->data.klass, NULL)) != 4) { - stack_size += size + 3; - stack_size &= ~3; - code_size += 32; - } else { - stack_size += 4; - code_size += i < 10 ? 5 : 8; - } - break; - } - case MONO_TYPE_I8: - stack_size += 8; - code_size += i < 10 ? 5 : 8; - break; - case MONO_TYPE_R4: - stack_size += 4; - code_size += i < 10 ? 10 : 13; - break; - case MONO_TYPE_R8: - stack_size += 8; - code_size += i < 10 ? 7 : 10; - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i]->type); - } - } - /* - * FIXME: take into account large return values. - */ - - code_buffer = p = alloca (code_size); - - /* - * Standard function prolog. - */ - x86_push_reg (p, X86_EBP); - x86_mov_reg_reg (p, X86_EBP, X86_ESP, 4); - /* - * and align to 16 byte boundary... - */ - stack_size += 15; - stack_size &= ~15; - - if (stack_size) - x86_alu_reg_imm (p, X86_SUB, X86_ESP, stack_size); - - /* - * EDX has the pointer to the args. - */ - x86_mov_reg_membase (p, X86_EDX, X86_EBP, ARGP_POS, 4); - - /* - * Push arguments in reverse order. - */ - stringp = 0; - for (i = sig->param_count; i; --i) { - arg_pos = ARG_SIZE * (i - 1); - if (sig->params [i - 1]->byref) { - x86_push_membase (p, X86_EDX, arg_pos); - continue; - } - simpletype = sig->params [i - 1]->type; -enum_marshal: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - x86_push_membase (p, X86_EDX, arg_pos); - break; - case MONO_TYPE_R4: - x86_alu_reg_imm (p, X86_SUB, X86_ESP, 4); - x86_fld_membase (p, X86_EDX, arg_pos, TRUE); - x86_fst_membase (p, X86_ESP, 0, FALSE, TRUE); - break; - case MONO_TYPE_CLASS: - x86_push_membase (p, X86_EDX, arg_pos); - break; - case MONO_TYPE_SZARRAY: - x86_push_membase (p, X86_EDX, arg_pos); - break; - case MONO_TYPE_VALUETYPE: - if (!sig->params [i - 1]->data.klass->enumtype) { - int size = mono_class_native_size (sig->params [i - 1]->data.klass, NULL); - if (size == 4) { - /* it's a structure that fits in 4 bytes, need to push the value pointed to */ - x86_mov_reg_membase (p, X86_EAX, X86_EDX, arg_pos, 4); - x86_push_regp (p, X86_EAX); - } else { - int ss = size; - ss += 3; - ss &= ~3; - - x86_alu_reg_imm (p, X86_SUB, X86_ESP, ss); - x86_push_imm (p, size); - x86_push_membase (p, X86_EDX, arg_pos); - x86_lea_membase (p, X86_EAX, X86_ESP, 2*4); - x86_push_reg (p, X86_EAX); - x86_mov_reg_imm (p, X86_EAX, memcpy); - x86_call_reg (p, X86_EAX); - x86_alu_reg_imm (p, X86_ADD, X86_ESP, 12); - /* memcpy might clobber EDX so restore it */ - x86_mov_reg_membase (p, X86_EDX, X86_EBP, ARGP_POS, 4); - } - } else { - /* it's an enum value */ - simpletype = sig->params [i - 1]->data.klass->enum_basetype->type; - goto enum_marshal; - } - break; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - case MONO_TYPE_R8: - x86_push_membase (p, X86_EDX, arg_pos + 4); - x86_push_membase (p, X86_EDX, arg_pos); - break; - default: - g_error ("Can't trampoline 0x%x", sig->params [i - 1]->type); - } - } - - if (sig->hasthis) { - if (sig->call_convention != MONO_CALL_THISCALL) { - x86_mov_reg_membase (p, X86_EDX, X86_EBP, THIS_POS, 4); - x86_push_reg (p, X86_EDX); - } else { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, THIS_POS, 4); - } - } - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_push_membase (p, X86_ECX, 0); - } - } - - /* - * Insert call to function - */ - x86_mov_reg_membase (p, X86_EDX, X86_EBP, FUNC_ADDR_POS, 4); - x86_call_reg (p, X86_EDX); - - /* - * Handle retval. - * Small integer and pointer values are in EAX. - * Long integers are in EAX:EDX. - * FP values are on the FP stack. - */ - - if (sig->ret->byref || string_ctor) { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - } else { - simpletype = sig->ret->type; - enum_retvalue: - switch (simpletype) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - break; - case MONO_TYPE_STRING: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - break; - case MONO_TYPE_R4: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_fst_membase (p, X86_ECX, 0, FALSE, TRUE); - break; - case MONO_TYPE_R8: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_fst_membase (p, X86_ECX, 0, TRUE, TRUE); - break; - case MONO_TYPE_I8: - x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4); - x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4); - x86_mov_membase_reg (p, X86_ECX, 4, X86_EDX, 4); - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", sig->ret->type); - } - } - - /* - * Standard epilog. - */ - x86_leave (p); - x86_ret (p); - - g_assert (p - code_buffer < code_size); - res = (MonoPIFunc)g_memdup (code_buffer, p - code_buffer); - - g_hash_table_insert (cache, sig, res); - - return res; -} - -#define MINV_POS (- sizeof (MonoInvocation)) -#define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count) -#define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type)) - -/* - * Returns a pointer to a native function that can be used to - * call the specified method. - * The function created will receive the arguments according - * to the call convention specified in the method. - * This function works by creating a MonoInvocation structure, - * filling the fields in and calling ves_exec_method on it. - * Still need to figure out how to handle the exception stuff - * across the managed/unmanaged boundary. - */ -void * -mono_arch_create_method_pointer (MonoMethod *method) -{ - MonoMethodSignature *sig; - MonoJitInfo *ji; - unsigned char *p, *code_buffer; - gint32 local_size; - gint32 stackval_pos, arg_pos = 8; - int i, size, align, cpos; - int *vtbuf; - - sig = method->signature; - - code_buffer = p = alloca (512); /* FIXME: check for overflows... */ - vtbuf = alloca (sizeof(int)*sig->param_count); - - local_size = sizeof (MonoInvocation) + sizeof (stackval) * (sig->param_count + 1); - - local_size += 7; - local_size &= ~7; - - stackval_pos = -local_size; - - cpos = 0; - for (i = 0; i < sig->param_count; i++) { - MonoType *type = sig->params [i]; - vtbuf [i] = -1; - if (type->type == MONO_TYPE_VALUETYPE) { - MonoClass *klass = type->data.klass; - if (klass->enumtype) - continue; - size = mono_class_native_size (klass, &align); - cpos += align - 1; - cpos &= ~(align - 1); - vtbuf [i] = cpos; - cpos += size; - } - } - - cpos += 7; - cpos &= ~7; - - local_size += cpos; - - /* - * Standard function prolog. - */ - x86_push_reg (p, X86_EBP); - x86_mov_reg_reg (p, X86_EBP, X86_ESP, 4); - x86_alu_reg_imm (p, X86_SUB, X86_ESP, local_size); - - /* - * Initialize MonoInvocation fields, first the ones known now. - */ - x86_mov_reg_imm (p, X86_EAX, 0); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)), X86_EAX, 4); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), X86_EAX, 4); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)), X86_EAX, 4); - /* - * Set the method pointer. - */ - x86_mov_membase_imm (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)), (int)method, 4); - - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) - arg_pos += 4; - - /* - * Handle this. - */ - if (sig->hasthis) { - if (sig->call_convention != MONO_CALL_THISCALL) { - /* - * Grab it from the stack, otherwise it's already in ECX. - */ - x86_mov_reg_membase (p, X86_ECX, X86_EBP, arg_pos, 4); - arg_pos += 4; - } - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)), X86_ECX, 4); - } - /* - * Handle the arguments. stackval_pos is the posset of the stackval array from EBP. - * arg_pos is the offset from EBP to the incoming arg on the stack. - * We just call stackval_from_data to handle all the (nasty) issues.... - */ - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)), X86_EAX, 4); - for (i = 0; i < sig->param_count; ++i) { - if (vtbuf [i] >= 0) { - x86_lea_membase (p, X86_EAX, X86_EBP, - local_size + vtbuf [i]); - x86_mov_membase_reg (p, X86_EBP, stackval_pos, X86_EAX, 4); - } - x86_mov_reg_imm (p, X86_ECX, stackval_from_data); - x86_lea_membase (p, X86_EDX, X86_EBP, arg_pos); - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - x86_push_imm (p, sig->pinvoke); - x86_push_reg (p, X86_EDX); - x86_push_reg (p, X86_EAX); - x86_push_imm (p, sig->params [i]); - x86_call_reg (p, X86_ECX); - x86_alu_reg_imm (p, X86_SUB, X86_ESP, 16); - stackval_pos += sizeof (stackval); - /* fixme: alignment */ - if (sig->pinvoke) - arg_pos += mono_type_native_stack_size (sig->params [i], &align); - else - arg_pos += mono_type_stack_size (sig->params [i], &align); - } - - /* - * Handle the return value storage area. - */ - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)), X86_EAX, 4); - if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - x86_mov_reg_membase (p, X86_ECX, X86_EBP, 8, 4); - x86_mov_membase_reg (p, X86_EBP, stackval_pos, X86_ECX, 4); - } - } - - /* - * Call the method. - */ - x86_lea_membase (p, X86_EAX, X86_EBP, MINV_POS); - x86_push_reg (p, X86_EAX); - x86_mov_reg_imm (p, X86_EDX, ves_exec_method); - x86_call_reg (p, X86_EDX); - - /* - * Move the return value to the proper place. - */ - x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos); - if (sig->ret->byref) { - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - } else { - int simpletype = sig->ret->type; - enum_retvalue: - switch (sig->ret->type) { - case MONO_TYPE_VOID: - break; - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 1); - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 2); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - break; - case MONO_TYPE_I8: - x86_mov_reg_membase (p, X86_EDX, X86_EAX, 4, 4); - x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 4); - break; - case MONO_TYPE_R8: - x86_fld_membase (p, X86_EAX, 0, TRUE); - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - - x86_push_imm (p, sig->pinvoke); - x86_push_membase (p, X86_EBP, stackval_pos); - x86_push_reg (p, X86_EAX); - x86_push_imm (p, sig->ret); - x86_mov_reg_imm (p, X86_ECX, stackval_to_data); - x86_call_reg (p, X86_ECX); - x86_alu_reg_imm (p, X86_SUB, X86_ESP, 16); - - break; - default: - g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); - break; - } - } - - /* - * Standard epilog. - */ - x86_leave (p); - x86_ret (p); - - g_assert (p - code_buffer < 512); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = p - code_buffer; - ji->code_start = g_memdup (code_buffer, p - code_buffer); - - mono_jit_info_table_add (mono_get_root_domain (), ji); - - return ji->code_start; -} |