Add some missing compat lib functions and fix a bug.

Change-Id: I2950e1b4f785bcc1f0b6154ce822fe17832b3f4f
diff --git a/cpu_ref/rsCpuRuntimeMath.cpp b/cpu_ref/rsCpuRuntimeMath.cpp
index 6c02303..ee82328 100644
--- a/cpu_ref/rsCpuRuntimeMath.cpp
+++ b/cpu_ref/rsCpuRuntimeMath.cpp
@@ -27,15 +27,29 @@
 #include "rsCpuCore.h"
 #include "rsCpuScript.h"
 
-
 using namespace android;
 using namespace android::renderscript;
 
+#define EXPORT_F32_FN_F32(func)                                 \
+    float __attribute__((overloadable)) SC_##func(float v) {    \
+        return func(v);                                         \
+    }
+
+#define EXPORT_F32_FN_F32_F32(func)                                     \
+    float __attribute__((overloadable)) SC_##func(float t, float v) {   \
+        return func(t, v);                                              \
+    }
 
 //////////////////////////////////////////////////////////////////////////////
 // Float util
 //////////////////////////////////////////////////////////////////////////////
 
+// Handle missing Gingerbread functions like tgammaf.
+float SC_tgammaf(float x) {
+    return tgamma(x);
+}
+
+uint32_t SC_abs_i32(int32_t v) {return abs(v);}
 
 static void SC_MatrixLoadRotate(Matrix4x4 *m, float rot, float x, float y, float z) {
     m->loadRotate(rot, x, y, z);
@@ -94,6 +108,54 @@
     return fmin(v - i, 0x1.fffffep-1f);
 }
 
+#ifdef RS_COMPATIBILITY_LIB
+EXPORT_F32_FN_F32(acosf)
+EXPORT_F32_FN_F32(acoshf)
+EXPORT_F32_FN_F32(asinf)
+EXPORT_F32_FN_F32(asinhf)
+EXPORT_F32_FN_F32(atanf)
+EXPORT_F32_FN_F32_F32(atan2f)
+EXPORT_F32_FN_F32(atanhf)
+EXPORT_F32_FN_F32(cbrtf)
+EXPORT_F32_FN_F32(ceilf)
+EXPORT_F32_FN_F32_F32(copysignf)
+EXPORT_F32_FN_F32(cosf)
+EXPORT_F32_FN_F32(coshf)
+EXPORT_F32_FN_F32(erfcf)
+EXPORT_F32_FN_F32(erff)
+EXPORT_F32_FN_F32(expf)
+EXPORT_F32_FN_F32(exp2f)
+EXPORT_F32_FN_F32(expm1f)
+EXPORT_F32_FN_F32_F32(fdimf)
+EXPORT_F32_FN_F32(floorf)
+float SC_fmaf(float u, float t, float v) {return fmaf(u, t, v);}
+EXPORT_F32_FN_F32_F32(fmaxf)
+EXPORT_F32_FN_F32_F32(fminf)
+EXPORT_F32_FN_F32_F32(fmodf)
+float SC_frexpf(float v, int* ptr) {return frexpf(v, ptr);}
+EXPORT_F32_FN_F32_F32(hypotf)
+EXPORT_F32_FN_F32(ilogbf)
+float SC_ldexpf(float v, int i) {return ldexpf(v, i);}
+EXPORT_F32_FN_F32(lgammaf)
+float SC_lgammaf_r(float v, int* ptr) {return lgammaf_r(v, ptr);}
+EXPORT_F32_FN_F32(logf)
+EXPORT_F32_FN_F32(log10f)
+EXPORT_F32_FN_F32(log1pf)
+EXPORT_F32_FN_F32(logbf)
+float SC_modff(float v, float* ptr) {return modff(v, ptr);}
+EXPORT_F32_FN_F32_F32(nextafterf)
+EXPORT_F32_FN_F32_F32(powf)
+EXPORT_F32_FN_F32_F32(remainderf)
+float SC_remquof(float t, float v, int* ptr) {return remquof(t, v, ptr);}
+EXPORT_F32_FN_F32(rintf)
+EXPORT_F32_FN_F32(roundf)
+EXPORT_F32_FN_F32(sinf)
+EXPORT_F32_FN_F32(sinhf)
+EXPORT_F32_FN_F32(sqrtf)
+EXPORT_F32_FN_F32(tanf)
+EXPORT_F32_FN_F32(tanhf)
+EXPORT_F32_FN_F32(truncf)
+#endif
 
 //////////////////////////////////////////////////////////////////////////////
 // Class implementation
diff --git a/cpu_ref/rsCpuRuntimeMathFuncs.cpp b/cpu_ref/rsCpuRuntimeMathFuncs.cpp
new file mode 100644
index 0000000..a1d7aff
--- /dev/null
+++ b/cpu_ref/rsCpuRuntimeMathFuncs.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// exports unavailable mathlib functions to compat lib
+
+#ifdef RS_COMPATIBILITY_LIB
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+extern uint32_t SC_abs_i32(int32_t v);
+uint32_t __attribute__((overloadable)) abs(int32_t v) {return SC_abs_i32(v);}
+
+#define IMPORT_F32_FN_F32(func)                                         \
+    extern float SC_##func##f(float v);                                 \
+    float __attribute__((overloadable)) func(float v) {return SC_##func##f(v);}
+
+#define IMPORT_F32_FN_F32_F32(func)                                     \
+    extern float SC_##func##f(float t, float v);                        \
+    float __attribute__((overloadable)) func(float t, float v) {return SC_##func##f(t, v);}
+
+IMPORT_F32_FN_F32(acos)
+IMPORT_F32_FN_F32(acosh)
+IMPORT_F32_FN_F32(asin)
+IMPORT_F32_FN_F32(asinh)
+IMPORT_F32_FN_F32(atan)
+IMPORT_F32_FN_F32_F32(atan2)
+IMPORT_F32_FN_F32(atanh)
+IMPORT_F32_FN_F32(cbrt)
+IMPORT_F32_FN_F32(ceil)
+IMPORT_F32_FN_F32_F32(copysign)
+IMPORT_F32_FN_F32(cos)
+IMPORT_F32_FN_F32(cosh)
+IMPORT_F32_FN_F32(erfc)
+IMPORT_F32_FN_F32(erf)
+IMPORT_F32_FN_F32(exp)
+IMPORT_F32_FN_F32(exp2)
+IMPORT_F32_FN_F32(expm1)
+IMPORT_F32_FN_F32_F32(fdim)
+IMPORT_F32_FN_F32(floor)
+extern float SC_fmaf(float u, float t, float v);
+float __attribute__((overloadable)) fma(float u, float t, float v) {return SC_fmaf(u, t, v);}
+IMPORT_F32_FN_F32_F32(fmax)
+IMPORT_F32_FN_F32_F32(fmin)
+IMPORT_F32_FN_F32_F32(fmod)
+extern float SC_frexpf(float v, int* ptr);
+float __attribute__((overloadable)) frexp(float v, int* ptr) {return SC_frexpf(v, ptr);}
+IMPORT_F32_FN_F32_F32(hypot)
+IMPORT_F32_FN_F32(ilogb)
+extern float SC_ldexpf(float v, int i);
+float __attribute__((overloadable)) ldexp(float v, int i) {return SC_ldexpf(v, i);}
+IMPORT_F32_FN_F32(lgamma)
+extern float SC_lgammaf_r(float v, int* ptr);
+float __attribute__((overloadable)) lgamma(float v, int* ptr) {return SC_lgammaf_r(v, ptr);}
+IMPORT_F32_FN_F32(log)
+IMPORT_F32_FN_F32(log10)
+IMPORT_F32_FN_F32(log1p)
+IMPORT_F32_FN_F32(logb)
+extern float SC_modff(float v, float* ptr);
+float modf(float v, float* ptr) {return SC_modff(v, ptr);}
+IMPORT_F32_FN_F32_F32(nextafter)
+IMPORT_F32_FN_F32_F32(pow)
+IMPORT_F32_FN_F32_F32(remainder)
+extern float SC_remquof(float t, float v, int* ptr);
+float remquo(float t, float v, int* ptr) {return SC_remquof(t, v, ptr);}
+IMPORT_F32_FN_F32(rint)
+IMPORT_F32_FN_F32(round)
+IMPORT_F32_FN_F32(sin)
+IMPORT_F32_FN_F32(sinh)
+IMPORT_F32_FN_F32(sqrt)
+IMPORT_F32_FN_F32(tan)
+IMPORT_F32_FN_F32(tanh)
+IMPORT_F32_FN_F32(tgamma)
+IMPORT_F32_FN_F32(trunc)
+
+// !!! DANGER !!!
+// These functions are potentially missing on older Android versions.
+// Work around the issue by supplying our own variants.
+// !!! DANGER !!!
+
+// The logbl() implementation is taken from the latest bionic/, since
+// double == long double on Android.
+extern "C" long double logbl(long double x) { return logb(x); }
+
+// __aeabi_idiv0 is a missing function in libcompiler_rt.so, so we just
+// pick the simplest implementation based on the ARM EABI doc.
+extern "C" int __aeabi_idiv0(int v) { return v; }
+
+#endif // compatibility lib
diff --git a/driver/rsdRuntimeStubs.cpp b/driver/rsdRuntimeStubs.cpp
index 8e7d9ee..76c3654 100644
--- a/driver/rsdRuntimeStubs.cpp
+++ b/driver/rsdRuntimeStubs.cpp
@@ -72,6 +72,31 @@
 typedef uint64_t ulong;
 #endif
 
+#ifdef RS_COMPATIBILITY_LIB
+#define OPAQUETYPE(t) \
+    typedef struct { const int* const p; } __attribute__((packed, aligned(4))) t;
+
+OPAQUETYPE(rs_element)
+OPAQUETYPE(rs_type)
+OPAQUETYPE(rs_allocation)
+OPAQUETYPE(rs_sampler)
+OPAQUETYPE(rs_script)
+OPAQUETYPE(rs_script_call)
+#undef OPAQUETYPE
+
+typedef struct {
+    int tm_sec;     ///< seconds
+    int tm_min;     ///< minutes
+    int tm_hour;    ///< hours
+    int tm_mday;    ///< day of the month
+    int tm_mon;     ///< month
+    int tm_year;    ///< year
+    int tm_wday;    ///< day of the week
+    int tm_yday;    ///< day of the year
+    int tm_isdst;   ///< daylight savings time
+} rs_tm;
+#endif
+
 //////////////////////////////////////////////////////////////////////////////
 // Allocation
 //////////////////////////////////////////////////////////////////////////////
@@ -480,10 +505,17 @@
     return rsrGetDt(rsc, sc);
 }
 
+#ifndef RS_COMPATIBILITY_LIB
 time_t SC_Time(time_t *timer) {
     Context *rsc = RsdCpuReference::getTlsContext();
     return rsrTime(rsc, timer);
 }
+#else
+static int SC_Time(int *timer) {
+    Context *rsc = RsdCpuReference::getTlsContext();
+    return rsrTime(rsc, (long*)timer);
+}
+#endif
 
 tm* SC_LocalTime(tm *local, time_t *timer) {
     Context *rsc = RsdCpuReference::getTlsContext();
@@ -1140,6 +1172,68 @@
 
 #ifdef RS_COMPATIBILITY_LIB
 
+//////////////////////////////////////////////////////////////////////////////
+// Compatibility Library entry points
+//////////////////////////////////////////////////////////////////////////////
+
+bool rsIsObject(rs_element src) {
+    return SC_IsObject((ObjectBase*)src.p);
+}
+
+#define CLEAR_SET_OBJ(t) \
+    void __attribute__((overloadable)) rsClearObject(t *dst) { \
+    return SC_ClearObject((ObjectBase**) dst); \
+    } \
+    void __attribute__((overloadable)) rsSetObject(t *dst, t src) { \
+    return SC_SetObject((ObjectBase**) dst, (ObjectBase*) src.p); \
+    }
+
+CLEAR_SET_OBJ(rs_element)
+CLEAR_SET_OBJ(rs_type)
+CLEAR_SET_OBJ(rs_allocation)
+CLEAR_SET_OBJ(rs_sampler)
+CLEAR_SET_OBJ(rs_script)
+#undef CLEAR_SET_OBJ
+
+const Allocation * rsGetAllocation(const void *ptr) {
+    return SC_GetAllocation(ptr);
+}
+
+void __attribute__((overloadable)) rsForEach(rs_script script,
+                                             rs_allocation in,
+                                             rs_allocation out,
+                                             const void *usr,
+                                             const rs_script_call *call) {
+    return SC_ForEach_SAAUS((Script *)script.p, (Allocation*)in.p, (Allocation*)out.p, usr, (RsScriptCall*)call);
+}
+
+void __attribute__((overloadable)) rsForEach(rs_script script,
+                                             rs_allocation in,
+                                             rs_allocation out,
+                                             const void *usr,
+                                             uint32_t usrLen,
+                                             const rs_script_call *call) {
+    return SC_ForEach_SAAULS((Script *)script.p, (Allocation*)in.p, (Allocation*)out.p, usr, usrLen, (RsScriptCall*)call);
+}
+
+int rsTime(int *timer) {
+    return SC_Time(timer);
+}
+
+rs_tm* rsLocaltime(rs_tm* local, const int *timer) {
+    return (rs_tm*)(SC_LocalTime((tm*)local, (long*)timer));
+}
+
+int64_t rsUptimeMillis() {
+    Context *rsc = RsdCpuReference::getTlsContext();
+    return rsrUptimeMillis(rsc);
+}
+
+uint32_t rsSendToClientBlocking2(int cmdID, void *data, int len) {
+    Context *rsc = RsdCpuReference::getTlsContext();
+    return rsrToClientBlocking(rsc, cmdID, data, len);
+}
+
 uint32_t rsSendToClientBlocking(int cmdID) {
     Context *rsc = RsdCpuReference::getTlsContext();
     return rsrToClientBlocking(rsc, cmdID, NULL, 0);
@@ -1323,11 +1417,11 @@
 }
 
 void rsDebug(const char *s, rs_matrix3x3 *m) {
-    SC_debugFM4v4(s, (float *) m);
+    SC_debugFM3v3(s, (float *) m);
 }
 
 void rsDebug(const char *s, rs_matrix2x2 *m) {
-    SC_debugFM4v4(s, (float *) m);
+    SC_debugFM2v2(s, (float *) m);
 }
 
 void rsDebug(const char *s, char c) {