Adding ASM .s file to a project

Say I have the following file.

src/fast_sqrt.s

        .syntax unified
        .set ALIGNMENT, 4

.text
        .align ALIGNMENT
        .global fast_sqrt
fast_sqrt:
        vsqrt.f32  s0, s0
        bx         lr

How do I assemble and link it into a project? The Makefile has a place for "user asm files", but it does not appear to be pulling the file in.

EDIT: The header follows so the routine can be called from C. Note that the above ASM routine has not been tested in another environment so it may be broken.

src/fast_sqrt.h

#ifndef FAST_SQRT_H
#define FAST_SQRT_H

extern float fast_sqrt(float);

#endif  // FAST_SQRT_H

EDIT 2: The tested X86_64 version follows. I never figured out how to conditionally include ASM files based on the target platform, so any insight on that front is appreciated.

        .intel_syntax
        .set ALIGNMENT, 16

.text
        .global _fast_sqrt
_fast_sqrt:
        sqrtss xmm0, xmm0
        ret

EDIT 3: 64-bit ARM ASM version, tested in the simulator running on Apple Silicon.

        .set ALIGNMENT, 8

.text
        .align ALIGNMENT
        .global _fast_sqrt
_fast_sqrt:
        fsqrt   s0, s0
        ret

EDIT 4: Note that the Cortex M7 only supports Thumb2 instructions.

The following changes to PlaydateSDK/C_API/buildsupport/common.mk kind of work, but different x86_64 and arm .s files need to be supplied to make pdc and make device, respectively.

$ diff PlaydateSDK/C_API/buildsupport/common.mk  CustomPlaydateSDK/C_API/buildsupport/common.mk
59c59
< __OBJS	= $(SRC:.c=.o)
---
> __OBJS	= $(SRC:.c=.o) $(ASRC:.s=.o)
144c144
< 	clang $(DYLIB_FLAGS) -lm $(CLANGFLAGS) -DTARGET_SIMULATOR=1 -DTARGET_EXTENSION=1 $(INCDIR) -o $(OBJDIR)/pdex.${DYLIB_EXT} $(SRC)
---
> 	clang $(DYLIB_FLAGS) -lm $(CLANGFLAGS) -DTARGET_SIMULATOR=1 -DTARGET_EXTENSION=1 $(INCDIR) -o $(OBJDIR)/pdex.${DYLIB_EXT} $(SRC) $(ASRC)
152a153,154

Part of the makefile follows. Basically, switching is being done manually and there is no hardware to test on at this point.

ASMTest/Makefile

# List C source files here
SRC = src/main.c
#SRC = src/main.c src/dummy_sqrt.c

# List ASM source files here
#ASRC = src/fast_sqrt_x86_64.s
ASRC = src/fast_sqrt_arm.s

Having said that, the x86_64 ASM appears to be working properly in the simulator.

// modified Hello World example message
pd->system->formatString(&message, "d=%.3f", fast_sqrt(x*x+y*y));

The following changes to PlaydateSDK/C_API/buildsupport/common.mk allow make to be run without manually modifying the ASM .s file to be used for different targets. Note that the assumption is that the simulator runs X86_64 ASM, and hardware runs ARM7 ASM. There may be a better way of doing this.

$ (cd $PLAYDATE_SDK_PATH/..; diff PlaydateSDK/C_API/buildsupport/common.mk CustomPlaydateSDK/C_API/buildsupport/common.mk)
59c59
< __OBJS	= $(SRC:.c=.o)
---
> __OBJS	= $(SRC:.c=.o) $(ASRC_DEVICE:.s=.o)
144c144
< 	clang $(DYLIB_FLAGS) -lm $(CLANGFLAGS) -DTARGET_SIMULATOR=1 -DTARGET_EXTENSION=1 $(INCDIR) -o $(OBJDIR)/pdex.${DYLIB_EXT} $(SRC)
---
> 	clang $(DYLIB_FLAGS) -lm $(CLANGFLAGS) -DTARGET_SIMULATOR=1 -DTARGET_EXTENSION=1 $(INCDIR) -o $(OBJDIR)/pdex.${DYLIB_EXT} $(SRC) $(ASRC_SIMULATOR)

The relevant portion of the Makefile folows.

ASMTest/Makefile

# List C source files here
SRC = src/main.c

# List ASM source files here
ASRC_DEVICE = src/fast_sqrt_arm7.s
ASRC_SIMULATOR = src/fast_sqrt_x86_64.s

EDIT: Note that it is possible to move a modified version of common.mk into the project directory and include that instead of PlaydateSDK/C_API/buildsupport/common.mk.

ASMTest/Makefile

# last line of Makefile
include common.mk

ASMTest demo source code attached. The d-pad, buttons, and crank can be used to control the distance in different ways. As listed above, the square root is calculated using an assembly routine.

pd->system->formatString(&message, "d=%.3f", fast_sqrt(x*x + y*y));

EDIT: New upload that actually builds and runs on hardware! Files modified to use Simulator ASM that runs on Apple Silicon, but the X86_64 .s file is still in the project.

ASMTest.zip (38.0 KB)

You could probably use arch or uname and provide an environment variable to select the proper assembly file. This would likely be easier done from a cmake file.

arch and uname provide information about the host system. I need to be able cross compile and select the file based on the compilation target.

I recently summarized ASM Playdate Development in a blog post. It may be easier to follow for anyone who is looking for something in a tutorial format.