Rebased from gcc
[libffi.git] / patches / sparc-v8-aggregate-returns
1 Index: libffi/ChangeLog
2 ===================================================================
3 --- libffi.orig/ChangeLog
4 +++ libffi/ChangeLog
5 @@ -111,6 +111,12 @@
6  
7         * configure: Regenerate.
8  
9 +2011-02-08  Ginn Chen  <ginn.chen@oracle.com>
10 +
11 +       * src/sparc/ffi.c (ffi_call): Make compatible with Solaris Studio
12 +       aggregate return ABI.  Flush cache.
13 +       (ffi_prep_closure_loc): Flush cache.
14 +
15  2011-02-11  Anthony Green  <green@moxielogic.com>
16  
17         From Tom Honermann <tom.honermann@oracle.com>:
18 Index: libffi/src/sparc/ffi.c
19 ===================================================================
20 --- libffi.orig/src/sparc/ffi.c
21 +++ libffi/src/sparc/ffi.c
22 @@ -1,5 +1,6 @@
23  /* -----------------------------------------------------------------------
24     ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc.
25 +           Copyright (c) 2011 Anthony Green
26     
27     SPARC Foreign Function Interface 
28  
29 @@ -406,8 +407,50 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
30        /* We don't yet support calling 32bit code from 64bit */
31        FFI_ASSERT(0);
32  #else
33 -      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, 
34 -                 cif->flags, rvalue, fn);
35 +      if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
36 +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
37 +         || cif->flags == FFI_TYPE_LONGDOUBLE
38 +#endif
39 +         ))
40 +       {
41 +         /* For v8, we need an "unimp" with size of returning struct */
42 +         /* behind "call", so we alloc some executable space for it. */
43 +         /* l7 is used, we need to make sure v8.S doesn't use %l7.   */
44 +         unsigned int *call_struct = NULL;
45 +         ffi_closure_alloc(32, &call_struct);
46 +         if (call_struct)
47 +           {
48 +             unsigned long f = (unsigned long)fn;
49 +             call_struct[0] = 0xae10001f;               /* mov   %i7, %l7       */
50 +             call_struct[1] = 0xbe10000f;               /* mov   %o7, %i7       */
51 +             call_struct[2] = 0x03000000 | f >> 10;     /* sethi %hi(fn), %g1   */
52 +             call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
53 +             call_struct[4] = 0x01000000;               /* nop                  */
54 +             if (cif->rtype->size < 0x7f)
55 +               call_struct[5] = cif->rtype->size;       /* unimp                */
56 +             else
57 +               call_struct[5] = 0x01000000;             /* nop                  */
58 +             call_struct[6] = 0x81c7e008;               /* ret                  */
59 +             call_struct[7] = 0xbe100017;               /* mov   %l7, %i7       */
60 +             asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
61 +                           "r" (call_struct) : "memory");
62 +             /* SPARC v8 requires 5 instructions for flush to be visible */
63 +             asm volatile ("nop; nop; nop; nop; nop");
64 +             ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
65 +                         cif->flags, rvalue, call_struct);
66 +             ffi_closure_free(call_struct);
67 +           }
68 +         else
69 +           {
70 +             ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
71 +                         cif->flags, rvalue, fn);
72 +           }
73 +       }
74 +      else
75 +       {
76 +         ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
77 +                     cif->flags, rvalue, fn);
78 +       }
79  #endif
80        break;
81      case FFI_V9:
82 @@ -425,7 +468,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
83        FFI_ASSERT(0);
84        break;
85      }
86 -
87  }
88  
89  
90 @@ -468,13 +510,13 @@ ffi_prep_closure_loc (ffi_closure* closu
91    closure->fun = fun;
92    closure->user_data = user_data;
93  
94 -  /* Flush the Icache.  FIXME: alignment isn't certain, assume 8 bytes */
95 +  /* Flush the Icache.  closure is 8 bytes aligned.  */
96  #ifdef SPARC64
97 -  asm volatile ("flush %0" : : "r" (closure) : "memory");
98 -  asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
99 +  asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory");
100  #else
101 -  asm volatile ("iflush        %0" : : "r" (closure) : "memory");
102 -  asm volatile ("iflush        %0" : : "r" (((char *) closure) + 8) : "memory");
103 +  asm volatile ("iflush        %0; iflush %0+8" : : "r" (closure) : "memory");
104 +  /* SPARC v8 requires 5 instructions for flush to be visible */
105 +  asm volatile ("nop; nop; nop; nop; nop");
106  #endif
107  
108    return FFI_OK;