-
Is it better to have it in Espruino, where it will take up space even if you don't use compiledC, or is it better to have in each compiledC block that uses doubles?
Well, the conversion code already takes that space in Espruino due to Float32Array. I just tried to implement float type support for native calls in espruino and with this small patch (also attached) it works
diff --git a/src/jsnative.c b/src/jsnative.c index fb1f20a22..201a158a7 100644 --- a/src/jsnative.c +++ b/src/jsnative.c @@ -145,6 +145,12 @@ JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar case JSWAT_INT32: // 32 bit int argData[argCount++] = (uint32_t)jsvGetInteger(param); break; + case JSWAT_FLOAT32: { // 32 bit float + union {uint32_t i; float f;} v; // with softfp convention float values are passed in integer registers + v.f = (float) jsvGetFloat(param); // truncate from double + argData[argCount++] = v.i; + break; + } [#ifndef](https://forum.espruino.com/search/?q=%23ifndef) ESPR_EMBED case JSWAT_PIN: // 16 bit int argData[argCount++] = (uint32_t)jshGetPinFromVar(param); @@ -265,6 +271,11 @@ JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar return jsvNewFromInteger((JsVarInt)result); case JSWAT_JSVARFLOAT: // 64 bit float return jsvNewFromFloat(*(JsVarFloat*)&result); + case JSWAT_FLOAT32: {// 32 bit float + union {uint32_t i; float f;} v; // with softfp convention float values are passed in integer registers + v.i = (uint32_t)result; + return jsvNewFromFloat((JsVarFloat)v.f); + } default: assert(0); return 0; diff --git a/src/jswrap_espruino.c b/src/jswrap_espruino.c index 1d6ef5cba..80ccf61f7 100644 --- a/src/jswrap_espruino.c +++ b/src/jswrap_espruino.c @@ -196,6 +211,7 @@ int nativeCallGetCType() { if (strcmp(name,"bool")==0) t=JSWAT_BOOL; if (strcmp(name,"Pin")==0) t=JSWAT_PIN; if (strcmp(name,"JsVar")==0) t=JSWAT_JSVAR; + if (strcmp(name,"float")==0) t=JSWAT_FLOAT32; jslMatch(LEX_ID); return t; } diff --git a/src/jswrapper.h b/src/jswrapper.h index 99866f0dd..c60a55069 100644 --- a/src/jswrapper.h +++ b/src/jswrapper.h @@ -43,6 +43,7 @@ typedef enum { JSWAT_BOOL, ///< boolean JSWAT_INT32, ///< 32 bit int JSWAT_PIN, ///< A pin + JSWAT_FLOAT32, ///< 32 bit float JSWAT_JSVARFLOAT, ///< 64 bit float JSWAT__LAST = JSWAT_JSVARFLOAT, JSWAT_MASK = NEXT_POWER_2(JSWAT__LAST)-1,
Tested with
var c = E.compiledC(` // float fadd(float,float) // float fmul(float,float) float fadd(float f1,float f2){ return f1+f2; } float fmul(float f1,float f2){ return f1*f2; }`); print(c.fmul(1.5,-1.5)); print(c.fadd(1.5,-0.25));
and I get
>-2.25 >1.25
EDIT: after comparing output of
echo 'int main(){return 0;}' | arm-none-eabi-gcc -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -xc - -dM -E | sort
for different calling conventions it looks like the code in jsnative.c and jswrap_espruino.c could be #ifdef-ed by__ARM_PCS
so that it is there only for ARM soft/softfp builds.
I don't know what the implication is to support float directly, but it does sound like a good alternative to doing the conversion in C. The conversion needs to happen somewhere. Is it better to have it in Espruino, where it will take up space even if you don't use compiledC, or is it better to have in each compiledC block that uses doubles?
Personally, I don't really need to pass floats/doubles to/from C. Just being able to work with floats is enough for me. I merely replied with a working version of the code that was asked for.