* x86/x86-codegen.h: added x86_rdtsc() and fixes.
* x86/tramp.c: create trampolines to call pinvoke methods.
* x86/Makefile.am: create a libmonoarch convenience library.
Thu Sep 6 15:41:24 CEST 2001 Paolo Molaro <lupus@ximian.com>
* Makefile.am: link to libmonoarch.
* interp.h, interp.c: use mono_create_trampoline ().
Pass the command line arguments to Main (String[]) methods.
svn path=/trunk/mono/; revision=728
mono/metadata/Makefile
mono/dis/Makefile
mono/cil/Makefile
+mono/arch/Makefile
+mono/arch/x86/Makefile
mono/interpreter/Makefile
mono/tests/Makefile
mono/wrapper/Makefile
-SUBDIRS = monoburg metadata cil dis interpreter wrapper
+SUBDIRS = monoburg metadata cil dis arch interpreter wrapper
+Thu Sep 6 15:38:00 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+ * x86/x86-codegen.h: added x86_rdtsc() and fixes.
+ * x86/tramp.c: create trampolines to call pinvoke methods.
+ * x86/Makefile.am: create a libmonoarch convenience library.
+
Mon Aug 27 09:29:00 CEST 2001 Paolo Molaro <lupus@ximian.com>
* x86/x86-codegen.h: fix x86_call_code (). x86_mov_regp_reg () added.
--- /dev/null
+# conditional compilation support here
+
+SUBDIRS = x86
--- /dev/null
+INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
+
+lib_LIBRARIES = libmonoarch.a
+
+libmonoarch_a_SOURCES = tramp.c x86-codegen.h
+
--- /dev/null
+/*
+ * Create trampolines to invoke arbitrary functions.
+ *
+ * Copyright (C) Ximian Inc.
+ *
+ * Author: Paolo Molaro (lupus@ximian.com)
+ *
+ */
+
+#include "x86-codegen.h"
+#include "mono/metadata/class.h"
+#include "mono/interpreter/interp.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)
+
+static char *
+mono_get_ansi_string (MonoObject *o)
+{
+ MonoStringObject *s = (MonoStringObject *)o;
+ char *as, *vector;
+ int i;
+
+ g_assert (o != NULL);
+
+ if (!s->length)
+ return g_strdup ("");
+
+ vector = s->c_str->vector;
+
+ g_assert (vector != NULL);
+
+ as = g_malloc (s->length + 1);
+
+ /* fixme: replace with a real unicode/ansi conversion */
+ for (i = 0; i < s->length; i++) {
+ as [i] = vector [i*2];
+ }
+
+ as [i] = '\0';
+
+ return as;
+}
+
+MonoPIFunc
+mono_create_trampoline (MonoMethod *method)
+{
+ MonoMethodSignature *sig;
+ unsigned char *p, *code_buffer;
+ guint32 local_size = 0, stack_size = 0, code_size = 30;
+ guint32 arg_pos;
+ int i, stringp;
+
+ sig = method->signature;
+
+ if (sig->hasthis) {
+ 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 += i < 10 ? 5 : 8;
+ continue;
+ }
+ switch (sig->params [i]->type) {
+ 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_R4:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ stack_size += 4;
+ code_size += i < 10 ? 5 : 8;
+ break;
+ case MONO_TYPE_STRING:
+ stack_size += 4;
+ code_size += 20;
+ local_size++;
+ break;
+ case MONO_TYPE_I8:
+ stack_size += 8;
+ code_size += i < 10 ? 5 : 8;
+ 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);
+ /*
+ * We store some local vars here to handle string pointers.
+ */
+ if (local_size)
+ x86_alu_reg_imm (p, X86_SUB, X86_ESP, local_size * 4);
+
+ /*
+ * We'll need to align to at least 8 bytes boudary... (16 may be better)
+ * 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;
+ }
+ switch (sig->params [i - 1]->type) {
+ 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_R4:
+ x86_push_membase (p, X86_EDX, arg_pos);
+ break;
+ case MONO_TYPE_R8:
+ x86_alu_reg_imm (p, X86_SUB, X86_ESP, 8);
+ x86_fld_membase (p, X86_EDX, arg_pos, TRUE);
+ x86_fst_membase (p, X86_ESP, 0, TRUE, TRUE);
+ break;
+ case MONO_TYPE_STRING:
+ /*if (frame->method->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI*/
+ x86_push_membase (p, X86_EDX, arg_pos);
+ x86_mov_reg_imm (p, X86_EDX, mono_get_ansi_string);
+ x86_call_reg (p, X86_EDX);
+ x86_alu_reg_imm (p, X86_SUB, X86_ESP, 4);
+ x86_push_reg (p, X86_EAX);
+ /*
+ * Store the pointer in a local we'll free later.
+ */
+ stringp++;
+ x86_mov_membase_reg (p, X86_EBP, LOC_POS * stringp, X86_EAX, 4);
+ /*
+ * we didn't save the reg: restore it here.
+ */
+ x86_mov_reg_membase (p, X86_EDX, X86_EBP, ARGP_POS, 4);
+ break;
+ case MONO_TYPE_I8:
+ x86_push_membase (p, X86_EDX, arg_pos + 4);
+ x86_push_membase (p, X86_EDX, arg_pos);
+ break;
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ 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);
+ }
+ }
+
+ /*
+ * 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) {
+ x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+ x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4);
+ } else {
+ switch (sig->ret->type) {
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_OBJECT:
+ 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_VOID:
+ break;
+ default:
+ g_error ("Can't handle as return value 0x%x", sig->ret->type);
+ }
+ }
+
+ /*
+ * free the allocated strings.
+ */
+ if (local_size)
+ x86_mov_reg_imm (p, X86_EDX, g_free);
+ for (i = 1; i <= local_size; ++i) {
+ x86_push_membase (p, X86_EBP, LOC_POS * i);
+ x86_call_reg (p, X86_EDX);
+ }
+ /*
+ * Standard epilog.
+ */
+ x86_leave (p);
+ x86_ret (p);
+
+ return g_memdup (code_buffer, p - code_buffer);
+}
+
/* Copyright (C) 2000 Intel Corporation. All rights reserved.
Copyright (C) 2001 Ximian, Inc.
//
-// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.5 2001/08/27 03:43:09 lupus Exp $
+// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.6 2001/09/06 09:46:03 lupus Exp $
*/
#ifndef X86_H
#define x86_prefix(inst,p) do { *(inst)++ =(unsigned char) (p); } while (0)
+#define x86_rdtsc(inst) \
+ do { \
+ *(inst)++ = 0x0f; \
+ *(inst)++ = 0x31; \
+ } while (0)
+
#define x86_cmpxchg_reg_reg(inst,dreg,reg) \
do { \
*(inst)++ = (unsigned char)0x0f; \
*(inst)++ = (unsigned char)0xc6; \
x86_mem_emit ((inst), 0, (mem)); \
x86_imm_emit8 ((inst), (imm)); \
- } else if ((size) == 4) { \
+ } else if ((size) == 2) { \
*(inst)++ = (unsigned char)0x66; \
*(inst)++ = (unsigned char)0xc7; \
x86_mem_emit ((inst), 0, (mem)); \
+
+Thu Sep 6 15:41:24 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+ * Makefile.am: link to libmonoarch.
+ * interp.h, interp.c: use mono_create_trampoline ().
+ Pass the command line arguments to Main (String[]) methods.
+
2001-08-30 Dietmar Maurer <dietmar@ximian.com>
* interp.c (ves_pinvoke_method): removed the libffi dependency
interp.c
mint_LDADD = \
+ ../arch/x86/libmonoarch.a \
../metadata/libmetadata.a \
$(GLIB_LIBS) \
$(GMODULE_LIBS) \
return;
}
switch (type->type) {
+ case MONO_TYPE_VOID:
+ return;
case MONO_TYPE_I1:
result->type = VAL_I32;
result->data.i = *(gint8*)data;
stackval_from_data (mt, frame->retval, ea);
}
-static char *
-mono_get_ansi_string (MonoObject *o)
-{
- MonoStringObject *s = (MonoStringObject *)o;
- char *as, *vector;
- int i;
-
- g_assert (o != NULL);
-
- if (!s->length)
- return g_strdup ("");
-
- vector = s->c_str->vector;
-
- g_assert (vector != NULL);
-
- as = g_malloc (s->length + 1);
-
- /* fixme: replace with a real unicode/ansi conversion */
- for (i = 0; i < s->length; i++) {
- as [i] = vector [i*2];
- }
-
- as [i] = '\0';
-
- return as;
-}
-
static void
ves_pinvoke_method (MonoInvocation *frame)
{
- MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)frame->method;
- MonoMethodSignature *sig = frame->method->signature;
- stackval *sp = frame->stack_args;
- int hasthis = sig->hasthis;
- char *tmp_string;
- int i, acount;
- GSList *t, *l = NULL;
- guint8 *p;
-
- acount = sig->param_count;
-
- (gpointer)piinfo->code = p = alloca ((acount+hasthis)*32);
-
- x86_enter (p, 0);
-
- /* fixme: only works on little endian machines */
-
- for (i = acount - 1; i >= 0; i--) {
-
- switch (sig->params [i]->type) {
-
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I: /* FIXME: not 64 bit clean */
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- x86_push_imm (p, sp [i].data.i);
- break;
- case MONO_TYPE_R4:
- x86_fld (p, &sp [i].data.f, FALSE);
- x86_alu_reg_imm (p, X86_SUB, X86_ESP, 4);
- x86_fst_membase (p, X86_ESP, 0, FALSE, TRUE);
- break;
- case MONO_TYPE_R8:
- x86_fld (p, &sp [i].data.f, TRUE);
- x86_alu_reg_imm (p, X86_SUB, X86_ESP, 8);
- x86_fst_membase (p, X86_ESP, 0, TRUE, TRUE);
- break;
- case MONO_TYPE_I8:
- x86_push_imm (p, sp [i].data.i);
- x86_push_imm (p, *(&sp [i].data.i+1));
- break;
- case MONO_TYPE_STRING:
- g_assert (sp [i].type == VAL_OBJ);
-
- if (frame->method->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI && sp [i].data.p) {
- tmp_string = mono_get_ansi_string (sp [i].data.p);
- l = g_slist_prepend (l, tmp_string);
- x86_push_imm (p, tmp_string);
- } else {
- x86_push_imm (p, sp [i].data.p);
- }
-
- break;
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_SZARRAY:
- x86_push_imm (p, sp [i].data.p);
- break;
- default:
- g_warning ("not implemented %02x", sig->params [i]->type);
- g_assert_not_reached ();
- }
-
- }
-
- if (hasthis)
- x86_push_imm (p, frame->obj);
-
- x86_call_code (p, (unsigned char*)frame->method->addr);
-
- switch (sig->ret->type) {
-
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I: /* FIXME: not 64 bit clean */
- case MONO_TYPE_U:
- frame->retval->type = VAL_I32;
- x86_mov_reg_imm (p, X86_EDX, &frame->retval->data.p);
- x86_mov_regp_reg (p, X86_EDX, X86_EAX, 4);
- break;
- case MONO_TYPE_I8:
- frame->retval->type = VAL_I64;
- x86_mov_mem_reg (p, &frame->retval->data.i, X86_EAX, 4);
- x86_mov_mem_reg (p, &frame->retval->data.i + 1, X86_EDX, 4);
- break;
- case MONO_TYPE_R4:
- frame->retval->type = VAL_DOUBLE;
- x86_mov_reg_imm (p, X86_EDX, &frame->retval->data.p);
- x86_fst_membase (p, X86_EDX, 0, FALSE, TRUE);
- break;
- case MONO_TYPE_R8:
- frame->retval->type = VAL_DOUBLE;
- x86_mov_reg_imm (p, X86_EDX, &frame->retval->data.p);
- x86_fst_membase (p, X86_EDX, 0, TRUE, TRUE);
- break;
- case MONO_TYPE_PTR:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_SZARRAY:
- frame->retval->type = VAL_OBJ;
- x86_mov_reg_imm (p, X86_EDX, &frame->retval->data.p);
- x86_mov_regp_reg (p, X86_EDX, X86_EAX, 4);
- break;
- case MONO_TYPE_VOID:
- break;
- default:
- g_warning ("not implemented %02x", sig->ret->type);
- g_assert_not_reached ();
- }
-
- x86_leave (p);
- x86_ret (p);
-
- piinfo->code ();
-
- t = l;
- while (t) {
- g_free (t->data);
- t = t->next;
- }
-
- g_slist_free (l);
+ MonoPIFunc func = mono_create_trampoline (frame->method);
+ func (frame->method->addr, &frame->retval->data.p, frame->obj, frame->stack_args);
+ stackval_from_data (frame->method->signature->ret, frame->retval, (const char*)&frame->retval->data.p);
+ g_free (func);
}
static void
method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
if (method->signature->param_count) {
- g_warning ("Main () with arguments not yet supported");
- exit (1);
- /*
int i;
stackval argv_array;
- MonoObject *arr = mono_new_szarray (mono_defaults.corlib, mono_defaults.string_token, argc);
+ MonoArrayObject *arr = (MonoArrayObject*)mono_new_szarray (mono_defaults.string_class, argc);
argv_array.type = VAL_OBJ;
argv_array.data.p = arr;
+ argv_array.data.vt.klass = NULL;
for (i=0; i < argc; ++i) {
+ ((gpointer *)arr->vector)[i] = mono_new_string (argv [i]);
}
- INIT_FRAME (&call, NULL, NULL, NULL, &result, method);
- */
+ INIT_FRAME (&call, NULL, NULL, &argv_array, &result, method);
} else {
INIT_FRAME (&call, NULL, NULL, NULL, &result, method);
}
#ifdef RUN_TEST
test_load_class (assembly->image);
#else
- retval = ves_exec (assembly, argc, argv);
+ /*
+ * skip the program name from the args.
+ */
+ ++i;
+ retval = ves_exec (assembly, argc - i, argv + i);
#endif
mono_assembly_close (assembly);
void mono_init_icall (void);
+typedef void (*MonoFunc) ();
+typedef void (*MonoPIFunc) (MonoFunc callme, void *retval, void *obj_this, stackval *arguments);
+
+/*
+ * defined in an arch specific file.
+ */
+MonoPIFunc mono_create_trampoline (MonoMethod *method);