1

To test the performance feature of an assembly language feature, I would like to use it inside a C program with inline assembly to replace existing functionality.

My GNU GAS assembler already recognizes the instruction with an appropriate -march.

How to make GCC generate code that accepts such inline assembly instructions that is cannot yet emit and does not recognize?

For example, the ARM SVE extensions were more or less recently added to the ARM architecture.

So in a minimal useless inline SVE assembly example I try:

main.c

int main(void) {
    __asm__ __volatile__ ("ld1d z1.d, p0/z, [x0, x4, lsl 3]");
}

and I try to compile with:

aarch64-linux-gnu-gcc -c -o main.o --save-temps -v main.c

but assembly fails with:

main.s: Assembler messages:
main.s:10: Error: selected processor does not support `ld1d z1.d,p0/z,[x0,x4,lsl 3]'

The verbose output contains:

/usr/lib/gcc-cross/aarch64-linux-gnu/7/../../../../aarch64-linux-gnu/bin/as -v -EL -mabi=lp64 -o main.o main.s

and main.s contains:

    .arch armv8-a
    .file   "main.c"
    .text
    .align  2
    .global main
    .type   main, %function
main:
#APP
// 2 "main.c" 1
    ld1d z1.d, p0/z, [x0, x4, lsl 3]
// 0 "" 2
#NO_APP
    mov w0, 0
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1) 7.4.0"
    .section    .note.GNU-stack,"",@progbits

However, my assembler is new enough to assemble that, since I managed to get it to assemble by either:

  • replacing .arch armv8-a in the generated main.s file manually with .arch armv8-a+sve
  • removing .arch armv8-a in main.s and adding -march=all or -march=armv8-a+sve on the GAS CLI (TODO .arch all does not exist unfortunately, I wonder why?)

However, if I try to add -march=armv8-a+sve or -march=all to the GCC CLI, it complains respectively with:

cc1: error: invalid feature modifier in ‘-march=armv8-a+sve’
cc1: error: unknown value ‘all’ for -march

I also tried to add -Xassembler -march=all to the GCC CLI:

aarch64-linux-gnu-gcc -Xassembler -march=all -c -o main.o --save-temps -v main.c

and the option does get forwarded to the assembler according to -v, but it still fails, because the .arch armv8-a that GCC puts into the assembly file takes precedence.

Out of desperation, I finally tried to modify my C example to:

int main(void) {
    __asm__ __volatile__ (".arch armv8-a+sve\nld1d z1.d, p0/z, [x0, x4, lsl 3]");
}

and that did work, but I think it is too insane to be usable. Notably, the .arch armv8-a+sve stays in effect even after my inline assembly statement, and I don't know how to revert to the previous default GCC .arch.

I also looked for GCC -masm options which might be useful like this one but could not find anything interesting.

Tested in Ubuntu 18.04, aarch64-linux-gnu-gcc 7.4.0, aarch64-linux-gnu-as 2.30.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • I don't think it is totally insane, as GCC use to force something similar to switch GAS into .code16gcc generation until they added the `-m16` option. I'm not sure there is an alternative (GCC command line option) at present to do what you are suggesting - although clearly it would be nice. – Michael Petch Jun 26 '19 at 16:05
  • @MichaelPetch thanks for the comment! Yes, the worst part is that me adding it explicitly is that it could affect the code that follows, if there was a way to restore the original arch afterwards, a macro solution would be workable. – Ciro Santilli OurBigBook.com Jun 26 '19 at 18:21
  • 1
    If you placed all arch specific code in separate objects that wouldn't be much of a problem. Splitting up arch specific functionality is probably not a bad idea for maintaining the code base. – Michael Petch Jun 26 '19 at 18:31
  • Does the latest version of GCC for the target platform support these instructions yet? If it did I'm wondering if upgrading GCC is an option? – Michael Petch Jun 26 '19 at 18:38
  • 1
    @MichaelPetch - Using godbolt, 7.3 fails, but 8.2 compiles with `-march=armv8-a+sve`. In fact, the [docs](https://gcc.gnu.org/onlinedocs/gcc-7.4.0/gcc/AArch64-Options.html#g_t-march-and--mcpu-Feature-Modifiers) for 7.4 don't mention this extension, while the current docs do. – David Wohlferd Jun 26 '19 at 18:40
  • @DavidWohlferd: oh cool, I hadn't noticed that Godbolt added binary mode for non-x86 compilers. https://godbolt.org/z/M2LuWE. Until recently all you could test was that your C compiled to asm, without being able to test if the asm would assemble (and link). – Peter Cordes Jun 26 '19 at 20:28
  • @MichaelPetch yes, upgrading can sometimes be an option. But not always, especially for the people work on the ISA bringup itself ;-) – Ciro Santilli OurBigBook.com Jun 26 '19 at 20:40
  • If you were able to get one of those command line options to work, it would replace the `.arch` at the top of the gcc output. Such being the case, what's so bad about adding a `asm(".arch armv8-a+sve");` at the very top of the source file? It (appears to) override gcc's .arch, and it seems unlikely gcc would have any reason to issue another one within the same file, so your declaration would 'win.' Ok, still ugly, but you could wrap it with an #ifdef, since you only need it until you move to 8.2. – David Wohlferd Jun 27 '19 at 18:56
  • @DavidWohlferd yes, this might be the best one can do now, and possibly good enough. The `#ifdef` on GCC version is desirable otherwise when GCC moves e.g. to say `armv8.2-a` by default the emitted code that follows could break. Also the `-march` from the CLI would be ignored, which is a small annoyance. – Ciro Santilli OurBigBook.com Jun 27 '19 at 20:08
  • Best I've got for you. To be clear: I'm suggestion putting it at the top of the *file*, not the top of the *function* (like you do in your last code sample above). Basic asm (ie no params) can be used outside of functions. – David Wohlferd Jun 27 '19 at 23:19

0 Answers0