Commit 697701ad by Kaz Kojima

ffi.c (ffi_prep_cif_machdep): Handle float arguments passed with FP registers correctly.

	* src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments
	passed with FP registers correctly.
	(ffi_closure_helper_SYSV): Likewise.
	* src/sh64/sysv.S: Likewise.

From-SVN: r112083
parent 8b96512f
2006-03-15 Kaz Kojima <kkojima@gcc.gnu.org>
* src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments
passed with FP registers correctly.
(ffi_closure_helper_SYSV): Likewise.
* src/sh64/sysv.S: Likewise.
2006-03-01 Andreas Tobler <a.tobler@schweiz.ch> 2006-03-01 Andreas Tobler <a.tobler@schweiz.ch>
* testsuite/libffi.special/unwindtest.cc (closure_test_fn): Mark cif, * testsuite/libffi.special/unwindtest.cc (closure_test_fn): Mark cif,
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2003, 2004 Kaz Kojima ffi.c - Copyright (c) 2003, 2004, 2006 Kaz Kojima
SuperH SHmedia Foreign Function Interface SuperH SHmedia Foreign Function Interface
...@@ -160,6 +160,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -160,6 +160,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
int n, m; int n, m;
int greg; int greg;
int freg; int freg;
int fpair = -1;
greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0); greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
freg = 0; freg = 0;
...@@ -175,7 +176,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -175,7 +176,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->bytes += sizeof (UINT64) - sizeof (float); cif->bytes += sizeof (UINT64) - sizeof (float);
if (freg >= NFREGARG - 1) if (freg >= NFREGARG - 1)
continue; continue;
freg++; if (fpair < 0)
{
fpair = freg;
freg += 2;
}
else
fpair = -1;
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
break; break;
...@@ -184,7 +191,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -184,7 +191,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
continue; continue;
if ((freg + 1) < NFREGARG) if ((freg + 1) < NFREGARG)
{ {
freg = (freg + 1) & ~1;
freg += 2; freg += 2;
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
} }
...@@ -350,6 +356,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, ...@@ -350,6 +356,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
int i, avn; int i, avn;
int greg, freg; int greg, freg;
ffi_cif *cif; ffi_cif *cif;
int fpair = -1;
cif = closure->cif; cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *)); avalue = alloca (cif->nargs * sizeof (void *));
...@@ -358,7 +365,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, ...@@ -358,7 +365,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
returns the data directly to the caller. */ returns the data directly to the caller. */
if (return_type (cif->rtype) == FFI_TYPE_STRUCT) if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
{ {
rvalue = *pgr; rvalue = (UINT64 *) *pgr;
greg = 1; greg = 1;
} }
else else
...@@ -402,11 +409,24 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, ...@@ -402,11 +409,24 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
if ((*p_arg)->type == FFI_TYPE_FLOAT) if ((*p_arg)->type == FFI_TYPE_FLOAT)
{ {
if (freg < NFREGARG - 1) if (freg < NFREGARG - 1)
{
if (fpair >= 0)
{
avalue[i] = (UINT32 *) pfr + fpair;
fpair = -1;
}
else
{
#ifdef __LITTLE_ENDIAN__ #ifdef __LITTLE_ENDIAN__
avalue[i] = (UINT32 *) pfr + (1 ^ freg++); fpair = freg;
avalue[i] = (UINT32 *) pfr + (1 ^ freg);
#else #else
avalue[i] = (UINT32 *) pfr + freg++; fpair = 1 ^ freg;
avalue[i] = (UINT32 *) pfr + freg;
#endif #endif
freg += 2;
}
}
else else
#ifdef __LITTLE_ENDIAN__ #ifdef __LITTLE_ENDIAN__
avalue[i] = pgr + greg; avalue[i] = pgr + greg;
...@@ -428,7 +448,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, ...@@ -428,7 +448,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
avalue[i] = pgr + greg; avalue[i] = pgr + greg;
else else
{ {
freg = (freg + 1) & ~1;
avalue[i] = pfr + (freg >> 1); avalue[i] = pfr + (freg >> 1);
freg += 2; freg += 2;
} }
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2003, 2004 Kaz Kojima sysv.S - Copyright (c) 2003, 2004, 2006 Kaz Kojima
SuperH SHmedia Foreign Function Interface SuperH SHmedia Foreign Function Interface
...@@ -84,6 +84,7 @@ ENTRY(ffi_call_SYSV) ...@@ -84,6 +84,7 @@ ENTRY(ffi_call_SYSV)
addi r15, 64, r22 addi r15, 64, r22
movi 0, r0 movi 0, r0
movi 0, r1 movi 0, r1
movi -1, r23
pt/l 1f, tr1 pt/l 1f, tr1
bnei/l r29, FFI_TYPE_STRUCT, tr1 bnei/l r29, FFI_TYPE_STRUCT, tr1
...@@ -106,9 +107,6 @@ ENTRY(ffi_call_SYSV) ...@@ -106,9 +107,6 @@ ENTRY(ffi_call_SYSV)
.L_pass_d: .L_pass_d:
addi r0, 1, r0 addi r0, 1, r0
addi r1, 1, r1
andi r1, ~1, r1
pt/l 3f, tr0 pt/l 3f, tr0
movi 12, r20 movi 12, r20
bge/l r1, r20, tr0 bge/l r1, r20, tr0
...@@ -158,13 +156,23 @@ ENTRY(ffi_call_SYSV) ...@@ -158,13 +156,23 @@ ENTRY(ffi_call_SYSV)
addi.l r15, 8, r15 addi.l r15, 8, r15
3: 3:
pt/l .L_pass, tr0 pt/l .L_pass, tr0
addi r1, 1, r1
blink tr0, r63 blink tr0, r63
.L_pop_f: .L_pop_f:
pt/l .L_pop_f_tbl, tr1 pt/l .L_pop_f_tbl, tr1
pt/l 5f, tr2
gettr tr1, r20 gettr tr1, r20
bge/l r23, r63, tr2
add r1, r63, r23
shlli r1, 3, r21 shlli r1, 3, r21
addi r1, 2, r1
add r20, r21, r20
ptabs/l r20, tr1
blink tr1, r63
5:
addi r23, 1, r21
movi -1, r23
shlli r21, 3, r21
add r20, r21, r20 add r20, r21, r20
ptabs/l r20, tr1 ptabs/l r20, tr1
blink tr1, r63 blink tr1, r63
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment