5

Assume I have a very big source code and intend to make the rdx register totally unused during the execution, i.e., while generating the assembly code, all I want is to inform my compiler (GCC) that it should not use rdx at all.

NOTE: register rdx is just an example. I am OK with any available Intel x86 register.

I am even happy to update the source code of the compiler and use my custom GCC. But which changes to the source code are needed?

janw
  • 8,758
  • 11
  • 40
  • 62
Sandhya Kumar
  • 293
  • 3
  • 11

4 Answers4

7

You tell GCC not to allocate a register via the -ffixed-reg option (gcc docs).

  • -ffixed-reg

    Treat the register named reg as a fixed register; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some other fixed role). reg must be the name of a register. The register names accepted are machine-specific and are defined in the REGISTER_NAMES macro in the machine description macro file.

For example, gcc -ffixed-r13 will make gcc leave it alone entirely. Using registers that are part of the calling convention, or required for certain instructions, may be problematic.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
chill
  • 16,470
  • 2
  • 40
  • 44
  • It "does not work" for registers with ABI prescribed meaning, like `RDX` is used to pass function arguments. For registers, generally available to the register allocator, it works (by making them not available). – chill Oct 01 '15 at 13:40
  • Can you give an example register for which it works? I will perhaps use that – Sandhya Kumar Oct 01 '15 at 14:19
5

You can put some global variable to this register. For ARM CPU you can do it this way:

register volatile type *global_ptr asm ("r8")

This instruction uses general purpose register "r8" to hold the value of global_ptr pointer.

See the source in U-Boot for real-life example:

http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/include/asm/global_data.h;h=4e3ea55e290a19c766017b59241615f7723531d5;hb=HEAD#l83

File arch/arm/include/asm/global_data.h (line ~83).

#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")

KostaZ
  • 710
  • 1
  • 7
  • 17
  • 1
    I like the idea, it's a good hack. I wonder though whether the compiler might have the idea to save the register to the stack, e.g when calling a function, and restore it later. Is there a gurantee that a register used this way stays untouched? What about code in libraries which cannot know this? – Peter - Reinstate Monica Oct 01 '15 at 11:38
  • It gives a warning, but the assembly code does contain those registers. warning: call-clobbered register used for global register variable [enabled by default] – Sandhya Kumar Oct 01 '15 at 13:30
  • +KostaZ ..I am okay with your idea of engaging a register in global value. But this does not work for me in x86_64. I use gcc 4.8.4 which probably is not respecting the register keyword – Sandhya Kumar Oct 01 '15 at 14:38
  • Please show-case your issue on the publicly accessible machine. For example, on Digital Ocean or alike. So, that me (or anyone else) can login and see the source code and hack around. – KostaZ Oct 01 '15 at 15:24
  • @SandhyaKumar, GCC x86_64 does have [global register variables](https://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html). I know because I have used it. See the end of this answer http://stackoverflow.com/a/26827308/2542702. KostaZ's answer is what I would suggest. Note that I don't think there is any guranetee the compiler will do what you want. You have to look at the aseembly. But in the case I looked at GCC I reserved `xmm15` as a global register variable and the assembly showed that the compiler did this. – Z boson Oct 02 '15 at 08:10
  • @KostaZ - Can you point me to some other way to achieve this? Perhaps, point me where to change in i386 machine descriptor files of GCC ? – Sandhya Kumar Oct 12 '15 at 07:27
1

I don't know whether there is a simple mechanism to tell that to gcc at run time. I would assume that you must recompile. From what I read I understand that there are description files for the different CPUs, e.g. this file, but what exactly needs to be changed in order to prevent gcc from using the register, and what potential side effects such a change could have, is beyond me.

I would ask on the gcc mailing list for assistence. Chances are that the modification is not so difficult per se, except that building gcc isn't trivial in my experience. In your case, if I analyze the situation correctly, a caveat applies. You are essentially cross-compiling, i.e building for a different architecture. In particular I understand that you have to build your system and other libraries which your program uses because their code would normally use that register. If you intend to link dynamically you probably would also have to build your own ld.so (the dynamic loader) because starting a dynamically linked executable actually starts that loader which would use that register. (Therefore maybe linking statically is better.)

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • Is this feasible in any other compiler (say LLVM)? Please note that I am OK with any fixed regsiter, not just rdx – Sandhya Kumar Oct 02 '15 at 03:19
  • I was just oulining general considerations which were barely more than comments. (For example I was unaware of what Brett said.) I would really ask on your compiler of choice's mailing list. – Peter - Reinstate Monica Oct 02 '15 at 05:33
1

Consider the divq instruction - the dividend is represented by [rdx][rax], and, assuming the divisor (D) satisfies rdx < D, the quotient is stored in %rax and remainder in %rdx. There are no alternative registers that can be used here.

The same applies with the mul/mulq instructions, where the product is stored in [rdx][rax] - even the recent mulx instruction, while more flexible, still uses %rdx as a source register. (If memory serves)

More importantly, %rdx is used to pass parameters in the x86-64 ELF ABI. You could never call C library functions (or any other ELF library for that matter) - even kernel syscalls use %rdx to pass parameters - though the register use is not the same.

I'm not clear on your motivation - but the fact is, you won't be able to do anything practical on any x86[-64] platform (let alone an ELF/Linux platform) - at least in user-space.

Brett Hale
  • 21,653
  • 2
  • 61
  • 90