diff dyncall/dyncall_callvm_ppc64.c @ 83:54930a037e8a

- PPC64 single-precision float fixes for more than 13 float args (thanks Masanori!) - changelog and todo update
author cslag
date Mon, 28 Mar 2016 23:46:59 +0200
parents 7ca57dbefed4
children 67961454902b
line wrap: on
line diff
--- a/dyncall/dyncall_callvm_ppc64.c	Thu Mar 24 23:53:03 2016 +0100
+++ b/dyncall/dyncall_callvm_ppc64.c	Mon Mar 28 23:46:59 2016 +0200
@@ -74,7 +74,7 @@
 {
   DCCallVM_ppc64* self = (DCCallVM_ppc64*)in_self;
 
-  if (self->mFloatRegs < 13) { 
+  if (self->mFloatRegs < 13) {
     self->mRegData.mFloatData[self->mFloatRegs++] = d;
     if (self->mIntRegs < 8) {
       self->mRegData.mIntData[self->mIntRegs++] = *( (DClonglong*) &d );
@@ -82,7 +82,7 @@
       return;
 #endif
     }
-  } 
+  }
 
 #if DC__ABI_PPC64_ELF_V == 2
   if (dcVecSize(&self->mVecHead) == 0) {
@@ -99,10 +99,10 @@
 {
   DCCallVM_ppc64* self = (DCCallVM_ppc64*)in_self;
 
-  if (dcVecSize(&self->mVecHead) == 0) 
+  if (dcVecSize(&self->mVecHead) == 0)
     dcVecSkip(&self->mVecHead,(sizeof(DClonglong))*(self->mIntRegs));
 
-  if (self->mFloatRegs < 13) { 
+  if (self->mFloatRegs < 13) {
     self->mRegData.mFloatData[self->mFloatRegs++] = d;
     if (self->mIntRegs < 8) {
       self->mRegData.mIntData[self->mIntRegs++] = *( (DClonglong*) &d );
@@ -116,19 +116,55 @@
 
 
 /* Floating-point */
-  
+
 static void dc_callvm_argFloat_ppc64(DCCallVM* in_self, DCfloat f)
 {
+  DCCallVM_ppc64* self = (DCCallVM_ppc64*)in_self;
+
+  DCdouble d;
+#if defined(DC__Endian_BIG)
+  struct { DCfloat f_pad; DCfloat f; } sf;
+#else /* Endian_LITTLE */
+  struct { DCfloat f; DCfloat f_pad; } sf;
+#endif
+
+  if (self->mFloatRegs < 13) {
+    d = (DCdouble)f;
+    self->mRegData.mFloatData[self->mFloatRegs++] = d;
+    if (self->mIntRegs < 8) {
+      self->mRegData.mIntData[self->mIntRegs++] = *( (DClonglong*) &d );
+#if DC__ABI_PPC64_ELF_V == 2
+      return;
+#endif
+    }
+  }
+
+#if DC__ABI_PPC64_ELF_V == 2
+  if (dcVecSize(&self->mVecHead) == 0) {
+    dcVecSkip(&self->mVecHead,sizeof(DClonglong)*8);
+  }
+#endif
+
+  /* push on stack */
+  sf.f = f;
+  dcVecAppend(&self->mVecHead,(DCpointer) &sf,sizeof(DCdouble));
+}
+
+#if DC__ABI_PPC64_ELF_V == 2
+static void dc_callvm_argFloat_ppc64_ellipsis(DCCallVM* in_self, DCfloat f)
+{
   /* promote to double */
   dcArgDouble(in_self, (DCdouble) f );
 }
+#endif
+
 
 /* long long integer */
 
 static void dc_callvm_argLongLong_ppc64(DCCallVM* in_self, DClonglong L)
 {
   DCCallVM_ppc64* self = (DCCallVM_ppc64*)in_self;
-  
+
   /* fillup integer register file */
   if (self->mIntRegs < 8) {
     self->mRegData.mIntData[self->mIntRegs++] = L;
@@ -259,7 +295,7 @@
 , &dc_callvm_argInt_ppc64
 , &dc_callvm_argLong_ppc64
 , &dc_callvm_argLongLong_ppc64_ellipsis
-, &dc_callvm_argFloat_ppc64
+, &dc_callvm_argFloat_ppc64_ellipsis
 , &dc_callvm_argDouble_ppc64_ellipsis
 , &dc_callvm_argPointer_ppc64
 , NULL /* argStruct */