Extending SDK

From llvm-mos

After Porting LLVM-MOS to a platform, please consider submitting your port for inclusion in the LLVM-MOS SDK. We'd like the SDK to be a nice out-of-the-box way to write code for any 6502 platform, and contributions along those lines are greatly appreciated.

This guide follows the Porting Guide above; make sure you've at least skimmed it before continuing, otherwise this guide likely won't make as much sense.

Review[edit | edit source]

Completing the porting guide produced the following artifacts:

A linker script, link.ld:

MEMORY {
  ram : ORIGIN = 0x0000, LENGTH = 0x10000
  user_ram (rw) : ORIGIN = 0x0200, LENGTH = 0xfe00
}
SECTIONS { INCLUDE c.ld }

__rc0 = 0x00;
INCLUDE imag-regs.ld
ASSERT(__rc0 == 0x00, "Inconsistent zero page map.")
ASSERT(__rc31 == 0x1f, "Inconsistent zero page map.")

/* Top of stack would be 0x10000, but wrap around. */
__stack = 0

OUTPUT_FORMAT { FULL(ram) SHORT(_start) }

A command line to build a binary:

mos-common-clang -o main -Os main.c -lexit-loop -linit-stack

This is enough to set up a freestanding platform in the SDK.

CMake[edit | edit source]

As mentioned previously, our SDK uses CMake to build. If you haven't done so already, check out and build the SDK sources using CMake.

Let's call our platform xyzzy, for old times' sake. Make a xyzzy subdirectory under the mos-platform directory for the platform to live in. Tell CMake that the new directory exists by adding add_subdirectory(xyzzy) to mos-platform/CMakeLists.txt. This will cause CMake to look for a CMakeLists.txt file in the xyzzy subdirectory, which will tell it how to build the xyzzy platform.

Platform Definition[edit | edit source]

A minimal platform CMakeLists.txt for xyzzy is just platform(xyzzy). Building and installing the SDK afterwards will then produce a mos-xyzzy-clang symlink that tells Clang to use the platform.

This produces an incomplete target with nothing in it. Our target should be complete though; it should be possible to produce binaries from it. So we can tell CMake that by using platform(xyzzy COMPLETE).

This will cause CMake to link for a link.ld file in the xyzzy subdirectory. Placing the link.ld file there allows the build and install to succeed and causes mos-xyzzy-clang to automatically use that linker script.

This still doesn't allow producing binaries though; the command line used for this was mos-common-clang, not mos-clang. Since the xyzzy platform is based off of the common platform, we need to change the platform definition to platform(xyzzy COMPLETE PARENT common). With this, mos-xyzzy-clang can produce executables.

Platform Libraries[edit | edit source]

There's one remaining part of the command line to deal with: -lexit-loop and -linit-stack. These libraries need to be included in the platform libraries for xyzzy.

For each platform, the Clang driver expects the following files to be available to the linker:

File Description
link.ld Linker Script
crt0.o Mandatory entry/exit functionality
libcrt0.a Optional entry/exit functionality
libcrt.a C runtime
libc.a C standard library

link.ld has already been discussed. crt0.o and libcrt0.a contain routines used at the beginning and end of a program. libcrt0.a contains functionality that may or may not be included, depending on what symbols are referenced in the program, while crt0.o contains the essential scaffolding to start and end a program. libcrt.a contains routines used to implement compiler functionality like multiplication and division, while libc.a contains the C standard library and support for some C++ language features.

We can't just include -lexit-loop and -linit-stack on the command line; the above files are structured so that compiler flags like -nostartfiles do what they logically should. So, we need to include libexit-loop.a and libinit-stack.a into the appropriate platform library, libcrt0.a.

To do so, we add to the xyzzy CMakeLists.txt :

platform(xyzzy COMPLETE PARENT common)

if(NOT CMAKE_CROSSCOMPILING)
  return()
endif()

add_platform_library(xyzzy-crt0)
merge_libraries(xyzzy-crt0
  common-crt0
  common-init-stack
  common-exit-loop
)

The early return just makes sure the following libraries aren't compiled for the host; they're 6502 code, so they need to be compiled with llvm-mos.

The remainder of the code creates a libcrt0.a for xyzzy that bundles in the libcrt0.a, libinit-stack.a , and libexit-loop.a libraries from the common platform. The other libraries bleed through from the common platform, while the libcrt0.a for xyzzy will be used in preference to the one from libcommon

With this, mos-xyzzy-clang will behave like to the original command line, and the platform is now fully incorporated into the SDK.