When writing a unit test on replacing standard epilogue sequences with BR __mspabi_func_epilog_<N>, by manually asm-clobbering rN - r10 for N = 4..10, everything worked well except for seeming inability to clobber r4.
The problem was that MSP430 code generator of LLVM used an obsolete name FP for that register. Things were worse because when llc read an unknown register name, it silently ignored it.
Example: take the following source:
void f(void) { asm volatile ("" : : : "r0"); asm volatile ("" : : : "r1"); asm volatile ("" : : : "r2"); asm volatile ("" : : : "r3"); asm volatile ("" : : : "r4"); asm volatile ("" : : : "r5"); } void g(void) { asm volatile ("" : : : "pc"); asm volatile ("" : : : "sp"); asm volatile ("" : : : "sr"); asm volatile ("" : : : "cg"); asm volatile ("" : : : "fp"); asm volatile ("" : : : "r5"); }
and execute:
$ $sysroot/bin/msp430-elf-gcc --version msp430-elf-gcc (Mitto Systems Limited - msp430-gcc 8.3.1.25) 8.3.1 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ $sysroot/bin/msp430-elf-gcc -c test-regs.c test-regs.c: In function 'g': test-regs.c:14:3: error: unknown register name 'pc' in 'asm' asm volatile ("" : : : "pc"); ^~~ test-regs.c:15:3: error: unknown register name 'sp' in 'asm' asm volatile ("" : : : "sp"); ^~~ test-regs.c:16:3: error: unknown register name 'sr' in 'asm' asm volatile ("" : : : "sr"); ^~~ test-regs.c:17:3: error: unknown register name 'cg' in 'asm' asm volatile ("" : : : "cg"); ^~~ test-regs.c:18:3: error: unknown register name 'fp' in 'asm' asm volatile ("" : : : "fp"); ^~~ $ clang --version clang version 10.0.0-4ubuntu1 Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin $ clang -target msp430 -c test-regs.c test-regs.c:14:26: error: unknown register name 'pc' in asm asm volatile ("" : : : "pc"); ^ test-regs.c:15:26: error: unknown register name 'sp' in asm asm volatile ("" : : : "sp"); ^ test-regs.c:16:26: error: unknown register name 'sr' in asm asm volatile ("" : : : "sr"); ^ test-regs.c:17:26: error: unknown register name 'cg' in asm asm volatile ("" : : : "cg"); ^ test-regs.c:18:26: error: unknown register name 'fp' in asm asm volatile ("" : : : "fp"); ^ 5 errors generated.
No differences at all. Now, let's drop g() function, to make it valid source.
$ clang -target msp430 test-regs.c -S -emit-llvm -o- ... ; Function Attrs: noinline nounwind optnone define dso_local void @f() #0 { call void asm sideeffect "", "~{r0}"() #1, !srcloc !2 call void asm sideeffect "", "~{r1}"() #1, !srcloc !3 call void asm sideeffect "", "~{r2}"() #1, !srcloc !4 call void asm sideeffect "", "~{r3}"() #1, !srcloc !5 call void asm sideeffect "", "~{r4}"() #1, !srcloc !6 call void asm sideeffect "", "~{r5}"() #1, !srcloc !7 ret void } ...
Everything looks good, again.
$ clang -target msp430 test-regs.c -S -mllvm -stop-after=finalize-isel -o- ... body: | bb.0 (%ir-block.0): INLINEASM &"", 1, !2 INLINEASM &"", 1, !3 INLINEASM &"", 1, !4 INLINEASM &"", 1, !5 INLINEASM &"", 1, !6 INLINEASM &"", 1, 12, implicit-def early-clobber $r5, !7 RET
That is, I cannot use fp register name from the C code because Clang does not accept it (exactly like GCC). But the accepted name r4 is not recognised by llc (it can be used in listings passed to llvm-mc and even fp is replace to r4 by llvm-mc). So I can specify any of fp or r4 for the string literal of asm(...) but nothing in the clobber list.
This patch replaces MSP430::FP with MSP430::R4 in the backend code (even MSP430 EABI doesn't mention FP as a register name). The R0 - R3 registers, on the other hand, are left as is in the backend code (after all, they have some special meaning on the ISA level). It is just ensured clang is renaming them as expected by the downstream tools. There is probably not much sense in marking them clobbered but rename them just in case for use at potentially different contexts.