You are reading a single comment by @Gordon and its replies. Click here to read the full conversation.
  • I was hoping I could add the following to E.compiledC, but even after accounting for the double-escaping, I'm not having success :

    float __attribute__((naked)) __aeabi_d2f(double d) {__asm__ volatile(
        "lsrs r0, #30\n\t"
        "lsls r2, r1, #12\n\t"
        "lsrs r2, #9\n\t"
        "asrs r1, #22\n\t"
        "lsls r1, #22\n\t"
        "orrs r0, r1\n\t"
        "orrs r0, r2\n\t"
        "bx lr"
    );}
    
    double __attribute__((naked)) __aeabi_f2d(float f) {__asm__ volatile(
        "asrs r1, r0, #3\n\t"
        "movs r2, [#0xf](https://forum.espruino.com/search­/?q=%230xf)\n\t"
        "lsls r2, #27\n\t"
        "orrs r1, r2\n\t"
        "lsls r0, #25\n\t"
        "bx lr"
    );}
    

    If you have any luck, please let me know!

  • Currently you can pass single precision floats (and converted doubles) into inline C code and back via Float32Array or with shared buffer with Int32Array for conversions of single values when passing parameters (more info https://gist.github.com/fanoush/9227640a­869d78d69a799276dff0fb71#file-espruino-f­pu-softfp-inlinec-js-L24), maybe it would be nice to support float type directly when passing parameters to native code (with automatic conversion to/from javascript double)? then d2f and f2d would not be needed?

  • The Pico code is for a Cortex M0+ and what you have in your snippet is incomplete.
    The correct code for a Cortex M4 is this (from assembled+disassembled libgcc, corrected to return the result in S0 instead of R0, since the compiler ignores the softfp ABI for functions in the same compilation unit, apparently):

    let c = E.compiledC(`
    // int boop(double)
    
    extern "C" float __attribute__((naked)) d2f(double) {__asm__ volatile(R"(
     	mov.w	r2, r1, lsl 1
     	subs.w	r3, r2, 0x70000000
     	itt	cs
     	subscs.w ip, r3, 0x200000
     	rsbscs	ip, ip, 0x1fc00000
     	bls.n	2f
    1:
     	and.w	ip, r1, 0x80000000
     	mov.w	r2, r0, lsl 3
     	orr.w	r0, ip, r0, lsr 29
     	cmp.w	r2, 0x80000000
     	adc.w	r0, r0, r3, lsl 2
     	it	eq
     	biceq.w	r0, r0, 1
     	b 6f
    2:
     	tst.w	r1, 0x40000000
     	bne.n	3f
     	adds.w	r2, r3, 0x2e00000
     	itt	lt
     	andlt.w	r0, r1, 0x80000000
     	blt	6f
     	orr.w	r1, r1, 0x100000
     	mov.w	r2, r2, lsr 21
     	rsb	r2, r2, 24
     	rsb	ip, r2, 32
     	lsls.w	r3, r0, ip
     	lsr.w	r0, r0, r2
     	it	ne
     	orrne.w	r0, r0, 1
     	mov.w	r3, r1, lsl 11
     	mov.w	r3, r3, lsr 11
     	lsl.w	ip, r3, ip
     	orr.w	r0, r0, ip
     	lsr.w	r3, r3, r2
     	mov.w	r3, r3, lsl 1
     	b.n	1b
    3:
     	mvns.w	r3, r2, asr 21
     	bne.n	5f
     	orrs.w	r3, r0, r1, lsl 12
     	ittt	ne
     	movne.w	r0, 0x7f000000
     	orrne.w	r0, r0, 0xc00000
     	bne	6f
    5:
     	and.w	r0, r1, 0x80000000
     	orr.w	r0, r0, 0x7f000000
     	orr.w	r0, r0, 0x800000
    6:
      vmov s0, r0
     	bx	lr
     	nop
    )");}
    
    
    int boop(double d) {
      return d2f(d) * 3;
    }
    `);
    
    print('boop:', c.boop(3.5)); // 3.5 * 3 = 10.5 cast to int = 10
    
    

    Note that you have to call the function explicitly, I couldn't use a float cast and get it to link as __aeabi_d2f. It might work if we compile the assembly into a library and then link to that. If one were to go that far, might as well link to libgcc and let the linker throw away all the stuff that isn't used.

About

Avatar for Gordon @Gordon started