MC PowerPC 32 bit vs. 64 bit

Hi,
over the past days I have been proofing a concept involving LLVM MC on
the PowerPC target. The 32 bit part went quite ok, but i am puzzled with
the results I get using the 64 bit target.
When disassembling in 64bit some instructions refer to GPRs in PPC::R0
to PPC::R31, some refer to PPC::X0 to PPC::X31.
I understand that the registers are modeled with Rx referring to the
32bit parts and Xx referring to the 64bit parts, but the way it looks to
me right now is that you only get the 64bit registers if the opcode is
available exclusively in 64bit mode.
I have seen that many instructions have been duplicated to support 32
bit registers and 64 bit register, e.g. oris vs. oris8, but the
disassembler does not pick the 64 bit variant.
PPCGenDisassemblerTables.inc does not have anything about oris8, only oris.
As a user of the Disassembler I would expect it to return me the 64bit
instruction referencing the 64bit registers if I ask it to disassemble a
ppc64 target.

Is this intended behavior or am I just missing some bit somewhere?
Thank you very much in advance for clarifying this.

Cheers,

Keve

Hi Keve,

As you've noticed, this is not modeled currently: We should, at least in theory, be selecting the 64-bit instructions with their associated registers when in 64-bit mode. Because the assembly is ambiguous in this regard, this does not matter for the purpose of printing the resulting assembly code (it will look the same regardless) nor will it matter for the purpose of reassembling the instructions. This will likely be confusing it you're trying to do analysis on the disassembled instructions, and I'd be happy to review a patch that improves our handling here.

-Hal

This issue has also started to be discussed in the context of
Krzysztof's variable-sized register class proposal:
http://lists.llvm.org/pipermail/llvm-dev/2016-October/105753.html
http://lists.llvm.org/pipermail/llvm-dev/2016-October/105763.html

Best,

Alex

Dear Hal and Alex,

thank you for the fast answer and confirming my thoughts. I am afraid my
understanding of LLVM internals is not yet sufficient to propose
patches, but I will certainly dig deeper into this.

I need to first understand why introducing the additional complexity
(doubling the GPRs and doubling the opcodes using them) had to be
introduced in the first place. Intuitively I would have modeled the CPU
"by the book" with 64bit GPRs and use a flag "32bit mode" to indicate
that upper half of the register is undefined/zero.

32bit mode would be either hw enforced (embedded CPUs) or software
chosen. This would allow LLVM to understand the 64bit CPUs in 32bit as
well (SF bit of MSR).

"32bit mode" is a fairly common thing with 64 bit CPUs, i.e. a LLVM
should have target agnostic fabric for this, but I have not stumbled
upon it yet.

Cheers,

Keve

I need to first understand why introducing the additional complexity
(doubling the GPRs and doubling the opcodes using them) had to be
introduced in the first place. Intuitively I would have modeled the CPU
"by the book" with 64bit GPRs and use a flag "32bit mode" to indicate
that upper half of the register is undefined/zero.

The mode switch effectively means that only one set of opcodes is
available at any given moment. Some architectures allow you to access
the 32bit parts of the GPRs independently (like x86), so it is natural
to model them as subregister in that case. If there is no way to access
them in parts, modelling them as independent sets makes things easier
for the register allocator.

32bit mode would be either hw enforced (embedded CPUs) or software
chosen. This would allow LLVM to understand the 64bit CPUs in 32bit as
well (SF bit of MSR).

You are assuming that it is the only difference between 32bit and 64bit
mode. In most cases, the size of pointers and registers is the smallest
part. They are typically using somewhat different ABIs, in the case of
PowerPC very different ABIs. For X86, you have instructions that only
exist in one mode or the other. The filtering works reliably on the
assembling side of things. The problem is that it seems that noone
taught the disassembler how to disambiguate things.

Joerg

Hi Keve,

Dear Hal and Alex,

thank you for the fast answer and confirming my thoughts. I am afraid my
understanding of LLVM internals is not yet sufficient to propose
patches, but I will certainly dig deeper into this.

I need to first understand why introducing the additional complexity
(doubling the GPRs and doubling the opcodes using them) had to be
introduced in the first place. Intuitively I would have modeled the CPU
"by the book" with 64bit GPRs and use a flag "32bit mode" to indicate
that upper half of the register is undefined/zero.

MIPS64 introduces a complexity here, in that our arithmetic instructions have
64 bit and 32 bit versions. For the 32bit versions, the result is sign extended to
64 bits. 32 bit word loads are also sign extended. Our logical, comparison and
branch instructions operate on the full length of the register.

To date we've handled this by duplicating portions of our instruction definitions
for codegen purposes, but we have the same issue you've highlighted with
disassembly.

As Hal pointed out, it's a known issue but speaking for MIPS it's been a very
low priority issue.

Thanks,
Simon