||<>|| When you see some assembler in a source package, there are some things which you need to consider when porting for Thumb-2 compatibility. This page aims to highlight the main issues and help would-be porters to get started. == How to Port Packages == [WRITE ME] [find the affected bits of code] [work out the implications and fix, depending on the issue types] == Documentation Links == IRC discussion highlighting some of these issues: * http://irclogs.ubuntu.com/2010/02/11/%23ubuntu-arm.html The specification for atomic primitives implemented by GCC can be found here: * [[http://refspecs.freestandards.org/elf/IA64-SysV-psABI.pdf]] General ARM documents are available at [[http://infocenter.arm.com/]]. For the instruction set "quick reference cards", browse to: * Browse to ARM Architecture -> Instruction Set Quick Reference Cards * For ARM procedure call standard, browse to !RealView software development tools -> Application Binary Interface See also http://blogs.arm.com/software-enablement/ for postings of interest to software developers. == ARM Assembler Overview == I could spend a long time writing one, but there's plenty of resources on the web. Most are a bit out of date, but this one isn't too bad: [[http://www.coranac.com/tonc/text/asm.htm]] ''Warning:'' the above page is a good introduction, but some things are no longer true for newer ARM architecture versions (such as ARMv7). The information on this wiki page takes precedence. == Key Thumb-2 compatibility Issues == Here's a quick breakdown of the key issues which may need attention === Identifying the Target Architecture === Because you're trying to port ARM assembler, it is assumed here that the affected source files or build system have already detected that you are building for an ARM processor of some sort. How to tell which ARM architecture variant is being targeted takes a bit more work. Generally, GCC defines ''one'' macro depending on the targeted variant: ||<(|3> '''Macro''' ||<(|3> '''Variant''' ||<(|3> '''BX supported''' ||<(|3> '''Thumb Variant supported''' ||<-5> '''Distro Support''' ||<(|3> '''Notes''' || ||<-2> '''Debian''' ||<-3> '''Ubuntu'''|| || '''arm''' || '''armel''' (lenny) || '''jaunty''' || '''karmic''' || '''lucid''' || || {{{__ARM_ARCH_2__}}} || ARMv2 or ARMv2a || no || none || || || || || || ''obsolete'' || || {{{__ARM_ARCH_3__}}} || ARMv3 || no || none || yes? || || || || || ''obsolete'' || || {{{__ARM_ARCH_3M__}}} || ARMv3M || no || none || yes? || || || || || ''obsolete'' || || {{{__ARM_ARCH_4__}}} || ARMv4 || (including StrongARM) || none || yes? || yes || || || || Debian runtime baseline for the {{{armel}}} arch || || {{{__ARM_ARCH_4T__}}} || ARMv4T (including ARM7TDMI) ) || '''yes''' || Thumb 1 || ? || yes || || || || Debian build baseline for the {{{armel}}} arch (Thumb not used) || || {{{__ARM_ARCH_5__}}} ||<(|2>ARMv5 non-Thumb variants ||<(|2> '''yes''' ||<(|2> none ||<(|2> ? ||<(|2> yes ||<(|2> yes ||<|2>||<|2>||<|2>|| || {{{__ARM_ARCH_5E__}}} || || {{{__ARM_ARCH_5T__}}} ||<(|3>ARMv5 Thumb variants (including Xscale) ||<(|3> '''yes''' ||<(|3> Thumb 1 ||<(|3> ? ||<(|3> yes ||<(|3> yes ||<|3>||<|3>||<(|3> Ubuntu jaunty build baseline is ARMv5TE || || {{{__ARM_ARCH_5TE__}}} || || {{{__ARM_ARCH_5TEJ__}}} || || {{{__ARM_ARCH_6__}}} ||<(|4> ARMv6 and variants ||<(|4> '''yes''' ||<(|4> Thumb 1 ||<(|4> ? ||<(|4> yes ||<(|4> yes ||<(|4> yes ||<|4>||<(|4> Ubuntu karmic build baseline is ARMv6 + VFPv2 || || {{{__ARM_ARCH_6J__}}} || || {{{__ARM_ARCH_6K__}}} || || {{{__ARM_ARCH_6Z__}}} || || {{{__ARM_ARCH_6ZK__}}} || || {{{__ARM_ARCH_6T2__}}} || ARMv6T2 || '''yes''' || '''Thumb 2''' || ? || ? || not officially || not officially || || rare || || {{{__ARM_ARCH_7__}}} || ARMv7 variants common subset || '''yes''' || '''Thumb 2''' || no || no || no || no || no || not applicable; ARM instruction set not guaranteed to be supported || || {{{__ARM_ARCH_7A__}}} || ARMv7-A (Applications profile, including Cortex-A8, Cortex-A9) || '''yes''' || '''Thumb 2''' || ? || yes || yes || yes || yes || Ubuntu lucid build baseline is ARMv7-A + VFPv3-D16 + Thumb-2 || || {{{__ARM_ARCH_7R__}}} || ARMv7-R (Real-Time profile) || '''yes''' || '''Thumb 2''' || ? || ? || not officially || not officially || not officially || embedded only; not applicable || || {{{__ARM_ARCH_7M__}}} || ARMv7-M (Microcontroller profile) || '''yes''' || '''Thumb 2''' || no || no || no || no || no || not applicable; ARM instruction set not supported || In addition, the following macros are used to indicate the architecture family and target instruction set: || '''Macro''' || '''Description''' || || {{{__arm__}}} || Always defined when building for the ARM architecture (regardless of target instruction set) || || {{{__thumb__}}} || Defined only when targeting any Thumb instruction set variant (Thumb-1 or Thumb-2) || || {{{__thumb2__}}} || Defined only when targeting Thumb-2 || The changes required for Thumb-2 compatibility would provoke build failures when building for older architectures. Unfortunately, the {{{__ARM_ARCH_}}}* macros are mutually exclusive, which makes it difficult to test whether the architectural features required by a particular code snippet are supported, especially in a forwards-compatible manner. However, when modifying the Ubuntu archive and upstream, we only really need to worry about build-time compatibility with Ubuntu releases and Debian (since Debian uses the oldest build baselines among all active distros for ARM, AFAIK). This suggests the following most general {{{#ifdef}}} test to use when making Thumb-2 porting changes: {{{ #if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) /* traditional ARM-compatible code */ #else /* Thumb-2 compatible code, which should only use features compatible with both Thumb-2 and ARMv5 */ #endif }}} If the above causes problems for the Debian community, it may be preferable to use this more comprehensive test: {{{ #if defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) /* traditional ARM-compatible code */ #else /* Thumb-2 compatible code, which should only use features compatible with both Thumb-2 and ARMv5 */ #endif }}} ...however, this starts to become fragile and cumbersome, and may be overkill; it depends on the level of activity of the old Debian {{{arm}}} port. === Procedure calls and returns === When using Thumb-2, the system will generally contain a mixture of ARM and Thumb-2 functions (depending on how libraries and binaries, and their component objects and functions, were assembled). The processor does not automatically know which instruction set is used for the code being executed after a branch, procedure call or procedure return --- instead, it must be told which instruction set to use at the time of the branch or return. Getting this right is known as "interworking". For C code, it's magic and will "just work", but for assembler, when you need to jump around, you need to do it the right way and not the wrong way... otherwise the processor will try to interpret the code using the wrong instruction set and sooner or later crash the running process (it certainly won't be doing what the programmer intended... much as if you branched into some arbitrary data). ==== Quick Reference ==== The target instruction set state is determined is different ways depending on the type of branch. Here's a very quick summary of kinds of branch, classified by context. This is not a list of all possibilities, just the most common/popular ones. || '''Context''' || '''Traditional ARM instruction''' || '''Preferred instruction for ARMv7''' || '''Notes''' || || function call (to label / named function) || {{{BL