Compile with both arm and thumb mode


I would like to use clang to cross compile the ARM binary. I hope the target binary contains both arm and thumb instruction sets.

I use the flag -mhwdiv=arm,thumb. I compiled several binaries. However, I found that the thumb mode instructions are few. Even for very big program like gcc. The number of thumb mode instruction is less than 100. I get the ground truth from the mapping table.

Maybe the flag I use is not right? I think there should be many thumb mode instructions. How do clang select thumb or arm mode when compiling? Many Thanks


Hello Muhui,

clang with a target like armv7a-linux-gnueabihf will default to
compiling all the functions in the file in Arm state. If the option
-mthumb or a target like thumbv7a-linux-gnueabi is used then all of
the functions will be compiled in Thumb state. Depending on how the
flags vary across the program will determine the mix of Arm and Thumb
in the binary.

Off the top of my head I think that you can use the target attribute
to change the state of individual function


Hi Peter

Thanks for your reply. It seems that the mix of arm and thumb is determined by the target attribute inside the source code. Is it right?

May I understand like this, I think the ‘-mthumb’ is a compiling flag. If no target information is provided. Then instruction mode will be determined by the compiling flag. If I set -mthumb, all the instructions will be in thumb mode. If I set nothing, all the instructions will be compiled into arm mode by default. What if I set -mthumb, but there is a target information specifying arm mode?

Besides, I looked at the link you provided, I don’t know the valid value of target if I need the function to be compiled to thumb mode. Maybe something like attribute((target(“thumbv7a-linux-gnueabi”)))? Thank you very much.


Peter Smith <> 于2018年11月9日周五 上午12:17写道:

Hello Muhui,

Yes the -mthumb (and the corresponding -marm) flag work at compile
time, and assembly time if you are using the GNU assembler. In clang
the -mthumb and -marm flag are currently implemented by changing the
target triple. For example --target=armv7a-linux-gnueabihf -mthumb
changes the the target to thumbv7a-linux-gnueabihf.

If you use a target starting with arm like armv7a-linux-gnueabihf then
by default you will get Arm instructions. If you use a target
thumbv7a-linux-gnueabihf then by default you will get Thumb

For an example of using attributes see
clang/test/CodeGen/arm-target-attr.c . The available attributes are:
__attribute__((target("arm"))) void test_target_arm() {

__attribute__((target("thumb"))) void test_target_thumb() {
The effect of these attributes is to add -thumb-mode or +thumb-mode to
the target-features attribute.