Stream: project-inline-asm

Topic: zero registers


Jake Goulding (Jan 12 2020 at 03:30, on Zulip):

Some registers are explicitly not supported for use with inline assembly:
x86 k0 This is a constant zero register which can't be modified.

Why can't the zero registers be read from?

Amanieu (Jan 12 2020 at 08:38, on Zulip):

It doesn't make sense to use a zero register as an input or output.

Amanieu (Jan 12 2020 at 08:38, on Zulip):

You are of course free to use the zero register inside your asm code.

Jake Goulding (Jan 12 2020 at 18:49, on Zulip):

So should that RFC text be clarified to state something more precise than "Some registers are explicitly not supported for use with inline assembly"?

Jake Goulding (Jan 12 2020 at 18:49, on Zulip):

As you say that we are "free to use the zero register".

Amanieu (Jan 12 2020 at 19:24, on Zulip):

OK I will clarify the text.

gnzlbg (Jan 12 2020 at 19:39, on Zulip):

@Jake Goulding they can be used in inline assembly

gnzlbg (Jan 12 2020 at 19:39, on Zulip):

but the content of those registers is always zero

gnzlbg (Jan 12 2020 at 19:40, on Zulip):

so setting such registers as inputs in an asm!("...", in k0(foo)) expression is pointless, since foo won't be written to the k0 register

gnzlbg (Jan 12 2020 at 19:41, on Zulip):

the same applies to using them as outputs, such the content of the register after an inline assembly expression gets written to a Rust variable, since that just means that the variable will always be zeroed

Jake Goulding (Jan 12 2020 at 19:45, on Zulip):

Yes, that’s why I’m pointing this out. The text of the RFC says that those registers may not be used and now multiple people are trying to correct me and say they can be used. I think @Amanieu understands the issue and is already going to clarify the mistake in the RFC.

Jake Goulding (Jan 12 2020 at 19:46, on Zulip):

The text does not say that they may not be used as input or output arguments, just that they may not be used at all.

gnzlbg (Jan 12 2020 at 19:55, on Zulip):

Ah gotcha, yes, the text should be specific about using them in input and output arguments

Jake Goulding (Jan 12 2020 at 19:57, on Zulip):

This is why I started this topic with the direct quote.

gnzlbg (Jan 12 2020 at 19:58, on Zulip):

@Jake Goulding I was confused by your proposed wording:

"Some registers are explicitly not supported for use with inline assembly"?

gnzlbg (Jan 12 2020 at 19:58, on Zulip):

But your last suggestion makes sense (e.g. "Some registers are explicitly not supported for use as input or output arguments" or something like that)

gnzlbg (Jan 12 2020 at 20:00, on Zulip):

Like, in RISC-V, if you want to implement a register to register copy (like an x86 mov) the simplest way would be something like and add of the source register with r0 (which is always zero) to the destination. So it is critically important that these "always zero" registers can be used within inline assembly.

Jake Goulding (Jan 12 2020 at 20:03, on Zulip):

I have not proposed any alternate wording. The part you cite as confusing is from the RFC

Jake Goulding (Jan 12 2020 at 20:04, on Zulip):

Again, quoted at the beginning of the topic and then later with more bolding.

gnzlbg (Jan 12 2020 at 20:05, on Zulip):

I misread your second quote

gnzlbg (Jan 12 2020 at 20:05, on Zulip):

I thought the bolding was a proposed change

Jake Goulding (Jan 12 2020 at 20:11, on Zulip):

The good thing here is that it seems we all agree the original phrasing was suboptimal.

nagisa (Jan 12 2020 at 21:53, on Zulip):

so setting such registers as inputs in an asm!("...", in k0(foo)) expression is pointless, since foo won't be written to the k0 register

I feel like I remember a few idioms in riscv that write to the 0 register and that make sense. Or maybe it was some other arch

nagisa (Jan 12 2020 at 21:54, on Zulip):

IIRC it was instructions that may write to multiple outputs and when you specify one of the outputs to be 0, you get some simplified instruction (same encoding)

Jake Goulding (Jan 13 2020 at 18:55, on Zulip):

It seems like in that case, you still wouldn't use it as an input register. As best I can tell from your description, that would mean that you've already done the operation with multiple outputs outside the asm! block, then are trying to move one of the outputs into the zero register and call some more assembly.

As mentioned above, you should be able to use the zero registers inside the asm! block, so you could write multioutput_op input1, input2, output1, $zero_reg;

nagisa (Jan 14 2020 at 15:05, on Zulip):

yeah, just using x0 directly in assembly makes more sense.

nagisa (Jan 14 2020 at 15:06, on Zulip):

I remember also that ld IMM is really encoded as add x0, IMM IIRC. But again, just use x0 directly

nagisa (Jan 14 2020 at 15:07, on Zulip):

LLVM could pass in x0 regardless for your "reg" constraint for in variable if it knows variable is 0 too, but that’s transparent… or could it… nah, because you can modify the registers…

Amanieu (Jan 14 2020 at 15:22, on Zulip):

GCC uses a separate constraint code for the zero register, which allows you to specify "zr" as the constraint code. This means: select the zero register if you can (the input value is 0) otherwise use a normal register.

Amanieu (Jan 14 2020 at 15:23, on Zulip):

However LLVM doesn't support multiple constraints (it will always pick the most generic) so it will always select a normal register even if the input value is 0.

gnzlbg (Jan 15 2020 at 13:33, on Zulip):

@nagisa I think you might be referring to RISC-V's jal instruction with x0 as the output register to discard the return address ?
cc @rkruppe - they might now

gnzlbg (Jan 15 2020 at 13:36, on Zulip):

Disallowing zero registers in inputs/outputs seems to me to at least be the conservative choice. We can always allow that later if someone finds a good use for it, but I can't think of any reason why using input/outputs with them would be better than just writing them in the text literal for the assembly

gnzlbg (Jan 15 2020 at 13:37, on Zulip):

For RISC-V it would be interesting to maybe specify whether the assembly literal supports pseudo-instructions like j or not - I don't see any reasons why not, all backends should support them anyways.

Last update: Apr 05 2020 at 00:30UTC