Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodrigo Kumpera <kumpera@gmail.com>2014-09-09 17:14:37 +0400
committerRodrigo Kumpera <kumpera@gmail.com>2014-09-09 17:14:37 +0400
commit8602eed8f7f134deff6ed89fb38f8ec4119b3004 (patch)
tree1178872f42438e5ed8fa49c39e9206e92dc53679
parent6bee6a7b18978aa6ce977b8b0f9ce19cf962f36b (diff)
[cleanup] Remove more old files.
-rw-r--r--README.md4
-rw-r--r--mono/arch/amd64/Makefile.am7
-rw-r--r--mono/arch/amd64/tramp.c1054
-rw-r--r--mono/arch/ppc/Makefile.am8
-rw-r--r--mono/arch/ppc/test.c35
-rw-r--r--mono/arch/ppc/tramp.c895
-rw-r--r--mono/arch/x86/Makefile.am6
-rw-r--r--mono/arch/x86/test.c225
-rw-r--r--mono/arch/x86/tramp.c545
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, &regs_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, &regs_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, &regs_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, &regs_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, &regs_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;
-}