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));

3 Likes

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)

2 Likes

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.

1 Like