summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2006-04-21 16:48:56 (GMT)
committerThomas Heller <theller@ctypes.org>2006-04-21 16:48:56 (GMT)
commit4b75a7c1cfb0aebd939fc17fccbcfc66ade4dea0 (patch)
treef8f739399c76d1257573143133284d6f8730d863 /Modules
parentf9cc5940960568ef8824f234369359060a8cf8bf (diff)
downloadcpython-4b75a7c1cfb0aebd939fc17fccbcfc66ade4dea0.zip
cpython-4b75a7c1cfb0aebd939fc17fccbcfc66ade4dea0.tar.gz
cpython-4b75a7c1cfb0aebd939fc17fccbcfc66ade4dea0.tar.bz2
Merge in changes from ctypes 0.9.9.6 upstream version.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/_ctypes.c17
-rw-r--r--Modules/_ctypes/libffi/fficonfig.py.in1
-rw-r--r--Modules/_ctypes/libffi_msvc/ffi.c85
-rw-r--r--Modules/_ctypes/libffi_msvc/ffi.h4
-rw-r--r--Modules/_ctypes/libffi_msvc/ffi_common.h19
-rw-r--r--Modules/_ctypes/libffi_msvc/ffitarget.h20
-rw-r--r--Modules/_ctypes/libffi_msvc/mingwin32.S228
-rw-r--r--Modules/_ctypes/libffi_msvc/prep_cif.c2
-rw-r--r--Modules/_ctypes/libffi_msvc/win32.S20
9 files changed, 297 insertions, 99 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 0108a7c..6a27833 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -1223,6 +1223,19 @@ c_void_p_from_param(PyObject *type, PyObject *value)
return value;
}
}
+/* function pointer */
+ if (CFuncPtrObject_Check(value)) {
+ PyCArgObject *parg;
+ CFuncPtrObject *func;
+ func = (CFuncPtrObject *)value;
+ parg = new_CArgObject();
+ parg->pffi_type = &ffi_type_pointer;
+ parg->tag = 'P';
+ Py_INCREF(value);
+ parg->value.p = *(void **)func->b_ptr;
+ parg->obj = value;
+ return (PyObject *)parg;
+ }
/* c_char_p, c_wchar_p */
stgd = PyObject_stgdict(value);
if (stgd && CDataObject_Check(value) && stgd->proto && PyString_Check(stgd->proto)) {
@@ -4407,6 +4420,8 @@ cast_check_pointertype(PyObject *arg)
if (PointerTypeObject_Check(arg))
return 1;
+ if (CFuncPtrTypeObject_Check(arg))
+ return 1;
dict = PyType_stgdict(arg);
if (dict) {
if (PyString_Check(dict->proto)
@@ -4566,7 +4581,7 @@ init_ctypes(void)
#endif
PyModule_AddObject(m, "FUNCFLAG_CDECL", PyInt_FromLong(FUNCFLAG_CDECL));
PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyInt_FromLong(FUNCFLAG_PYTHONAPI));
- PyModule_AddStringConstant(m, "__version__", "0.9.9.4");
+ PyModule_AddStringConstant(m, "__version__", "0.9.9.6");
PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove));
PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset));
diff --git a/Modules/_ctypes/libffi/fficonfig.py.in b/Modules/_ctypes/libffi/fficonfig.py.in
index 2ed2347..5e53c6d 100644
--- a/Modules/_ctypes/libffi/fficonfig.py.in
+++ b/Modules/_ctypes/libffi/fficonfig.py.in
@@ -31,5 +31,6 @@ ffi_sources += ffi_platforms['@TARGET@']
ffi_sources = [os.path.join('@srcdir@', f) for f in ffi_sources]
ffi_cflags = '@CFLAGS@'
+# I think this may no longer be needed:
if sys.platform == "openbsd3":
ffi_cflags += " -fno-stack-protector"
diff --git a/Modules/_ctypes/libffi_msvc/ffi.c b/Modules/_ctypes/libffi_msvc/ffi.c
index 5c49b39..e5600b2 100644
--- a/Modules/_ctypes/libffi_msvc/ffi.c
+++ b/Modules/_ctypes/libffi_msvc/ffi.c
@@ -26,8 +26,6 @@
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
-#ifndef __x86_64__
-
#include <ffi.h>
#include <ffi_common.h>
@@ -143,11 +141,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
/*@-declundef@*/
/*@-exportheader@*/
-#ifdef _MSC_VER
extern int
-#else
-extern void
-#endif
ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
@@ -156,14 +150,9 @@ ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@=declundef@*/
/*@=exportheader@*/
-#if defined(X86_WIN32) || defined(_MSC_VER)
/*@-declundef@*/
/*@-exportheader@*/
-#ifdef _MSC_VER
extern int
-#else
-extern void
-#endif
ffi_call_STDCALL(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
@@ -171,13 +160,8 @@ ffi_call_STDCALL(void (*)(char *, extended_cif *),
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
-#endif /* X86_WIN32 || _MSC_VER*/
-#ifdef _MSC_VER
int
-#else
-void
-#endif
ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
@@ -206,24 +190,18 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
{
case FFI_SYSV:
/*@-usedef@*/
-#ifdef _MSC_VER
- return
-#endif
- ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
+ return ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
-#if defined(X86_WIN32) || defined(_MSC_VER)
+
case FFI_STDCALL:
/*@-usedef@*/
-#ifdef _MSC_VER
- return
-#endif
- ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
+ return ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
-#endif /* X86_WIN32 */
+
default:
FFI_ASSERT(0);
break;
@@ -236,23 +214,10 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
void** args, ffi_cif* cif);
-#ifndef _MSC_VER
-static void ffi_closure_SYSV (ffi_closure *)
- __attribute__ ((regparm(1)));
-static void ffi_closure_raw_SYSV (ffi_raw_closure *)
- __attribute__ ((regparm(1)));
-#endif
-
/* This function is jumped to by the trampoline */
-#ifdef _MSC_VER
static void __fastcall
ffi_closure_SYSV (ffi_closure *closure, int *argp)
-#else
-static void
-ffi_closure_SYSV (closure)
- ffi_closure *closure;
-#endif
{
// this is our return value storage
long double res;
@@ -262,11 +227,11 @@ ffi_closure_SYSV (closure)
void **arg_area;
unsigned short rtype;
void *resp = (void*)&res;
-#ifdef _MSC_VER
+//#ifdef _MSC_VER
void *args = &argp[1];
-#else
- void *args = __builtin_dwarf_cfa ();
-#endif
+//#else
+// void *args = __builtin_dwarf_cfa ();
+//#endif
cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
@@ -390,7 +355,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
/* MOV EDX, ESP is 0x8b 0xd4 */
-#ifdef _MSC_VER
+//#ifdef _MSC_VER
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,BYTES) \
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
@@ -407,18 +372,18 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
*(unsigned short*) &__tramp[13] = BYTES; \
}
-#else
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,BYTES) \
-({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
- unsigned int __fun = (unsigned int)(FUN); \
- unsigned int __ctx = (unsigned int)(CTX); \
- unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
- *(unsigned char*) &__tramp[0] = 0xb8; \
- *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
- *(unsigned char *) &__tramp[5] = 0xe9; \
- *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
- })
-#endif
+//#else
+//#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,BYTES) \
+//({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+// unsigned int __fun = (unsigned int)(FUN); \
+// unsigned int __ctx = (unsigned int)(CTX); \
+// unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
+// *(unsigned char*) &__tramp[0] = 0xb8; \
+// *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
+// *(unsigned char *) &__tramp[5] = 0xe9; \
+// *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
+// })
+//#endif
/* the cif must already be prep'ed */
@@ -433,10 +398,8 @@ ffi_prep_closure (ffi_closure* closure,
if (cif->abi == FFI_SYSV)
bytes = 0;
-#ifdef _MSC_VER
else if (cif->abi == FFI_STDCALL)
bytes = cif->bytes;
-#endif
else
return FFI_BAD_ABI;
@@ -450,5 +413,3 @@ ffi_prep_closure (ffi_closure* closure,
return FFI_OK;
}
-
-#endif /* __x86_64__ */
diff --git a/Modules/_ctypes/libffi_msvc/ffi.h b/Modules/_ctypes/libffi_msvc/ffi.h
index b9d31fd..203142d 100644
--- a/Modules/_ctypes/libffi_msvc/ffi.h
+++ b/Modules/_ctypes/libffi_msvc/ffi.h
@@ -272,11 +272,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
/*@dependent@*/ ffi_type **atypes);
-#ifdef _MSC_VER
int
-#else
-void
-#endif
ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
diff --git a/Modules/_ctypes/libffi_msvc/ffi_common.h b/Modules/_ctypes/libffi_msvc/ffi_common.h
index 1b948d5..43fb83b 100644
--- a/Modules/_ctypes/libffi_msvc/ffi_common.h
+++ b/Modules/_ctypes/libffi_msvc/ffi_common.h
@@ -13,24 +13,7 @@ extern "C" {
#endif
#include <fficonfig.h>
-
-/* Do not move this. Some versions of AIX are very picky about where
- this is positioned. */
-#ifdef __GNUC__
-# define alloca __builtin_alloca
-#else
-# if HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
- #pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-# endif
-# endif
-# endif
-#endif
+#include <malloc.h>
/* Check for the existence of memcpy. */
#if STDC_HEADERS
diff --git a/Modules/_ctypes/libffi_msvc/ffitarget.h b/Modules/_ctypes/libffi_msvc/ffitarget.h
index c9d95bc..57d275b 100644
--- a/Modules/_ctypes/libffi_msvc/ffitarget.h
+++ b/Modules/_ctypes/libffi_msvc/ffitarget.h
@@ -43,23 +43,21 @@ typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
/* ---- Intel x86 Win32 ---------- */
-#if defined(X86_WIN32) || defined(_MSC_VER)
FFI_SYSV,
FFI_STDCALL,
/* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV,
-#endif
/* ---- Intel x86 and AMD x86-64 - */
-#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
- FFI_SYSV,
- FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
-#ifdef __i386__
- FFI_DEFAULT_ABI = FFI_SYSV,
-#else
- FFI_DEFAULT_ABI = FFI_UNIX64,
-#endif
-#endif
+/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */
+/* FFI_SYSV, */
+/* FFI_UNIX64,*/ /* Unix variants all use the same ABI for x86-64 */
+/* #ifdef __i386__ */
+/* FFI_DEFAULT_ABI = FFI_SYSV, */
+/* #else */
+/* FFI_DEFAULT_ABI = FFI_UNIX64, */
+/* #endif */
+/* #endif */
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
diff --git a/Modules/_ctypes/libffi_msvc/mingwin32.S b/Modules/_ctypes/libffi_msvc/mingwin32.S
new file mode 100644
index 0000000..e71f2b2
--- /dev/null
+++ b/Modules/_ctypes/libffi_msvc/mingwin32.S
@@ -0,0 +1,228 @@
+/* -----------------------------------------------------------------------
+ win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
+ Copyright (c) 2001 John Beniton
+ Copyright (c) 2002 Ranjit Mathew
+
+
+ X86 Foreign Function Interface
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+.globl ffi_prep_args
+
+ # This assumes we are using gas.
+ .balign 16
+.globl _ffi_call_SYSV
+
+_ffi_call_SYSV:
+ pushl %ebp
+ movl %esp,%ebp
+
+ # Make room for all of the new args.
+ movl 16(%ebp),%ecx
+ subl %ecx,%esp
+
+ movl %esp,%eax
+
+ # Place all of the ffi_prep_args in position
+ pushl 12(%ebp)
+ pushl %eax
+ call *8(%ebp)
+
+ # Return stack to previous state and call the function
+ addl $8,%esp
+
+ # FIXME: Align the stack to a 128-bit boundary to avoid
+ # potential performance hits.
+
+ call *28(%ebp)
+
+ # Remove the space we pushed for the args
+ movl 16(%ebp),%ecx
+ addl %ecx,%esp
+
+ # Load %ecx with the return type code
+ movl 20(%ebp),%ecx
+
+ # If the return value pointer is NULL, assume no return value.
+ cmpl $0,24(%ebp)
+ jne retint
+
+ # Even if there is no space for the return value, we are
+ # obliged to handle floating-point values.
+ cmpl $2,%ecx # Float_type
+ jne noretval
+ fstp %st(0)
+
+ jmp epilogue
+
+retint:
+ cmpl $1,%ecx # Int_type
+ jne retfloat
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ movl %eax,0(%ecx)
+ jmp epilogue
+
+retfloat:
+ cmpl $2,%ecx # Float_type
+ jne retdouble
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ fstps (%ecx)
+ jmp epilogue
+
+retdouble:
+ cmpl $3,%ecx # Double_type
+ jne retlongdouble
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ fstpl (%ecx)
+ jmp epilogue
+
+retlongdouble:
+ cmpl $4,%ecx # Longdouble_type
+ jne retint64
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ fstpt (%ecx)
+ jmp epilogue
+
+retint64:
+ cmpl $12,%ecx # SINT64_type
+ jne retstruct
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ movl %eax,0(%ecx)
+ movl %edx,4(%ecx)
+
+retstruct:
+ # Nothing to do!
+
+noretval:
+epilogue:
+ movl %ebp,%esp
+ popl %ebp
+ ret
+
+.ffi_call_SYSV_end:
+
+ # This assumes we are using gas.
+ .balign 16
+.globl _ffi_call_STDCALL
+
+_ffi_call_STDCALL:
+ pushl %ebp
+ movl %esp,%ebp
+
+ # Make room for all of the new args.
+ movl 16(%ebp),%ecx
+ subl %ecx,%esp
+
+ movl %esp,%eax
+
+ # Place all of the ffi_prep_args in position
+ pushl 12(%ebp)
+ pushl %eax
+ call *8(%ebp)
+
+ # Return stack to previous state and call the function
+ addl $8,%esp
+
+ # FIXME: Align the stack to a 128-bit boundary to avoid
+ # potential performance hits.
+
+ call *28(%ebp)
+
+ # stdcall functions pop arguments off the stack themselves
+
+ # Load %ecx with the return type code
+ movl 20(%ebp),%ecx
+
+ # If the return value pointer is NULL, assume no return value.
+ cmpl $0,24(%ebp)
+ jne sc_retint
+
+ # Even if there is no space for the return value, we are
+ # obliged to handle floating-point values.
+ cmpl $2,%ecx # Float_type
+ jne sc_noretval
+ fstp %st(0)
+
+ jmp sc_epilogue
+
+sc_retint:
+ cmpl $1,%ecx # Int_type
+ jne sc_retfloat
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ movl %eax,0(%ecx)
+ jmp sc_epilogue
+
+sc_retfloat:
+ cmpl $2,%ecx # Float_type
+ jne sc_retdouble
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ fstps (%ecx)
+ jmp sc_epilogue
+
+sc_retdouble:
+ cmpl $2,%ecx # Double_type
+ jne sc_retlongdouble
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ fstpl (%ecx)
+ jmp sc_epilogue
+
+sc_retlongdouble:
+ cmpl $4,%ecx # Longdouble_type
+ jne sc_retint64
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ fstpt (%ecx)
+ jmp sc_epilogue
+
+sc_retint64:
+ cmpl $12,%ecx # SINT64_Type
+ jne sc_retstruct
+ # Load %ecx with the pointer to storage for the return value
+ movl 24(%ebp),%ecx
+ movl %eax,0(%ecx)
+ movl %edx,4(%ecx)
+
+sc_retstruct:
+ # Nothing to do!
+
+sc_noretval:
+sc_epilogue:
+ movl %ebp,%esp
+ popl %ebp
+ ret
+
+.ffi_call_STDCALL_end:
+
diff --git a/Modules/_ctypes/libffi_msvc/prep_cif.c b/Modules/_ctypes/libffi_msvc/prep_cif.c
index 9edce2f..2650fa0 100644
--- a/Modules/_ctypes/libffi_msvc/prep_cif.c
+++ b/Modules/_ctypes/libffi_msvc/prep_cif.c
@@ -147,7 +147,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
else
#endif
{
-#ifndef _MSC_VER
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
/* Don't know if this is a libffi bug or not. At least on
Windows with MSVC, function call parameters are *not*
aligned in the same way as structure fields are, they are
diff --git a/Modules/_ctypes/libffi_msvc/win32.S b/Modules/_ctypes/libffi_msvc/win32.S
index 40743af..cc82ab9 100644
--- a/Modules/_ctypes/libffi_msvc/win32.S
+++ b/Modules/_ctypes/libffi_msvc/win32.S
@@ -41,7 +41,11 @@
_ffi_call_SYSV:
pushl %ebp
movl %esp,%ebp
-
+
+ #THe: save previous %esi, and store the current stack pointer in %esi
+ pushl %esi
+ movl %esp,%esi
+
# Make room for all of the new args.
movl 16(%ebp),%ecx
subl %ecx,%esp
@@ -64,7 +68,9 @@ _ffi_call_SYSV:
# Remove the space we pushed for the args
movl 16(%ebp),%ecx
addl %ecx,%esp
-
+
+ sub %esp,%esi # calculate stack pointer difference
+
# Load %ecx with the return type code
movl 20(%ebp),%ecx
@@ -125,6 +131,8 @@ retstruct:
noretval:
epilogue:
+ movl %esi,%eax # return the stack pointer detlta in %eax
+ popl %esi # restore previous %esi
movl %ebp,%esp
popl %ebp
ret
@@ -139,6 +147,10 @@ _ffi_call_STDCALL:
pushl %ebp
movl %esp,%ebp
+ #THe: save previous %esi, and store the current stack pointer in %esi
+ pushl %esi
+ movl %esp,%esi
+
# Make room for all of the new args.
movl 16(%ebp),%ecx
subl %ecx,%esp
@@ -158,6 +170,8 @@ _ffi_call_STDCALL:
call *28(%ebp)
+ sub %esp,%esi # difference in stack
+
# stdcall functions pop arguments off the stack themselves
# Load %ecx with the return type code
@@ -220,6 +234,8 @@ sc_retstruct:
sc_noretval:
sc_epilogue:
+ movl %esi,%eax # return the stack difference
+ popl %esi # restore previous %esi value
movl %ebp,%esp
popl %ebp
ret