With Arm Compiler 6, Arm has moved to an advanced, modern compiler based on LLVM and Clang technology. There are many reasons to migrate your C code to this compiler (see my colleague Paul's excellent discussion 'Link Time Optimization in Arm Compiler 6'). But what of the assembler? We have provided a stand-alone assembler, armasm, as part of our tool suites (RVDS, MDK, and DS-5) for many years. Arm Compiler 6, or armclang, as the executable is named, contains a built-in integrated assembler that can be used to build your low level source files. In this blog I will discuss how to make use of this feature, and how to migrate legacy source to this tool.
Perhaps surprisingly, I will start by saying that you may not need to migrate source files to this tool! The existing Arm assembler (armasm) has been maintained to support the latest Armv8 architecture and conforming processors (up to Armv8.3). Even if you have migrated the C source to the new compiler, you can still build the assembler source with armasm as before. The linker will happily consume objects built with either assembler (or either compiler). That being said, we do encourage you to start the migration process.
If you use the Eclipse IDE within DS-5 to manage your project, you will know that there is a default project template for Arm Compiler 6. This selects armclang as the default assembler, as visible in the Properties → C/C++ Build → Settings view.
You can change this, by navigating to the Tool Chain Editor pane in the same view, and click on Select Tools...
Within this view, you can replace Arm Assembler for Arm Assembler 5 (i.e. armasm):
Click OK to save, then, when you go back to Settings, you will see armasm listed instead.
Of course, as assembly level source code is typically written for initialization of device specific features, it is usually re-written for new platforms, perhaps based on existing code, and so when you are at this point, it is a good time to start to consider migration to armclang. Armasm consumes source code written in a proprietary format, whereas armclang consumes source in GNU assembler (gas) format. Unfortunately these are quite different formats, even for the most basic of examples, as illustrated below:
; Example armasm syntax source file
; This is a comment
AREA ARMex, CODE ; Name this block of code ARMex
ENTRY ; Image (potential) entry point
CODE32 ; A32 code from here
EXPORT foo ; Make symbol foo global
IMPORT bar ; Reference external global symbol
foo ; symbol declaration
LDR r0, [pc]
DCD 0x12345678 ; This is data
END ; End of file. Ignore everything after
// Example GNU syntax source file
// This is a comment
.section ARMex, "x“ // Name this block of code ARMex
// specify entry point by linker
.code 32 // A32 code from here
.global foo // Make symbol foo global
// undef symbols assumed global
foo: // symbol declaration
LDR r0, [pc]
.word 0x12345678 // This is data
.end // End of file. Ignore everything after
Command-line options are also significantly different, a table is provided in documentation to compare equivalent options.
It is possible to insert assembler code within C source to implement functionality for which there is no direct equivalent C construct, by using the __asm keyword.
As above, the legacy Arm Compiler, armcc, used armasm syntax, whereas armclang uses GNU inline assembly syntax, and so these sources would need to be rewritten to be re-compiled with armclang. However our recommendation for such cases is to reconsider if assembler notation is truly appropriate any more. Better to make use of the intrinsic functions as defined within arm_acle.h (and arm_compat.h) which are portable implementations of such operations, defned within the Arm C Language Extensions specification.
I hope this was a useful introduction on this topic. For more information on migrating both C and assembly code to Arm Compiler 6, click the button below:
Arm Compiler Migration and Compatibility Guide