<html><head></head><body><div style="font-family: Verdana;font-size: 12.0px;"><div>
<div>Thanks Craig for your quick reply and pointing me to a direction!</div>

<div> </div>

<div>So even when finding a syntax that tablegen would accept, it would not lead to the desired result.</div>

<div> </div>

<div>Will look at the X86 code you mentioned below and try to understand how it's done.</div>

<div> </div>

<div>Although the X86 seems to be the "closest" to the Z80 regarding the instruction set (and, as far as I can see, the only officially supported CISC CPU), it seems also to be the most complex backend to get started with. But I'm commited ;-)</div>

<div> </div>

<div>Michael</div>

<div> 
<div name="quote" style="margin:10px 5px 5px 10px; padding: 10px 0 10px 10px; border-left:2px solid #C3D9E5; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">
<div style="margin:0 0 10px 0;"><b>Gesendet:</b> Dienstag, 10. Juli 2018 um 08:21 Uhr<br/>
<b>Von:</b> "Craig Topper" <craig.topper@gmail.com><br/>
<b>An:</b> Michael.Stellmann@gmx.net<br/>
<b>Cc:</b> llvm-dev <llvm-dev@lists.llvm.org><br/>
<b>Betreff:</b> Re: [llvm-dev] Stuck with instruction in tablegen</div>

<div name="quoted-content">
<div>To the best of my knowledge, having 2 explicit physical registers(in your case A and F) in the output of an instruction isn't supported correctly by tablegen and never has been. Maybe it previously appeared to work well enough to pass build?
<div> </div>

<div>This is why X86 has the pattern commented out here and implements custom handling in X86ISelDAGToDAG.cpp.
<div> </div>

<div>
<div>// EAX,EDX = EAX*GR32</div>

<div>let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], hasSideEffects = 0 in</div>

<div>def MUL32r : I<0xF7, MRM4r, (outs),  (ins GR32:$src),</div>

<div>               "mul{l}\t$src",</div>

<div>               [/*(set EAX, EDX, EFLAGS, (X86umul_flag EAX, GR32:$src))*/]>,</div>

<div>               OpSize32, Sched<[WriteIMul]>;</div>

<div>// RAX,RDX = RAX*GR64</div>

<div>let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], hasSideEffects = 0 indef MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src),</div>

<div>                "mul{q}\t$src",</div>

<div>                [/*(set RAX, RDX, EFLAGS, (X86umul_flag RAX, GR64:$src))*/]>,</div>

<div>                Sched<[WriteIMul64]>;</div>
</div>

<div> </div>

<div> </div>

<div>I vaguely recall trying to fix tablegen probably at least 5 years ago, but didn't succeed. Looking back at the code now I can tell you the two places in DAGISelMatcherGen.cpp that call HasOneImplicitDefWithKnownVT are definitely unable to handle multiple implicit def destinations in a pattern.</div>

<div> </div>

<div>
<div>
<div class="gmail_signature">~Craig</div>
</div>
</div>
</div>
</div>
 

<div class="gmail_quote">
<div>On Mon, Jul 9, 2018 at 9:30 PM Michael Stellmann via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" onclick="parent.window.location.href='llvm-dev@lists.llvm.org'; return false;" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:</div>

<blockquote class="gmail_quote" style="margin: 0 0 0 0.8ex;border-left: 1.0px rgb(204,204,204) solid;padding-left: 1.0ex;">Hi,<br/>
<br/>
I'm trying to revive jacobly0's Z80 back-end (from<br/>
<a href="https://github.com/jacobly0/llvm-z80" target="_blank">https://github.com/jacobly0/llvm-z80</a>) and build it with a current<br/>
version of LLVM.<br/>
<br/>
Apart from some interface changes, I'm stuck at building the tables.<br/>
Specifically, the generation of the DAG instruction selector causes an<br/>
assertion in the table generator:<br/>
<br/>
     Assertion failed: Ops.size() >= NumSrcResults && "Didn't provide<br/>
enough results"<br/>
<br/>
I tried to fix the problem by searched in the documentation and in other<br/>
table sources, but to no avail. Even stepping through that code in the<br/>
debugger (MatcherGen::EmitResultCode()) didn't help me to find the cause<br/>
of the problem. The instruction tables description are quite unique in<br/>
all the officially supported CPU models, I couldn't find any similar<br/>
code that could help me figuring out what is going wrong.<br/>
<br/>
So I isolated the table sources to a minimum of two simple<br/>
base-instructions and attached these for reproduction of the problem<br/>
(not sure if the attachment gets through).<br/>
<br/>
The table generation is done with:<br/>
<br/>
     llvm-tblgen -gen-dag-isel -I=<path-to-llvm-include> -o=out.inc Z80.td<br/>
<br/>
The first instruction in Z80InstrInfo.td is a unary instruction, that<br/>
does a rotate left of a byte in memory, resulting in the leftmost bit<br/>
being placed in the Carry flag - and changing the memory contents at the<br/>
pointer's address (in Z80: "RLC (HL)", I expect).<br/>
The table generation completes without errors with just this instruction<br/>
(by commenting the last line in Z80InstrInfo.td).<br/>
<br/>
The second one is a binary instruction, adding the contents of a pointer<br/>
and a register, with results in register A and F (Z80: "ADD A,(HL)").<br/>
<br/>
A is an 8-bit register. The Z80 ALU can only do 8 bit arithmetic with<br/>
that register and another param. The two instructions don't seem to<br/>
require a specific register for the address in the table class, so the<br/>
RegisterInfo table is not defined so far in the minimized version<br/>
<br/>
The problem is in Z80InstrInfo.td, in the following section of<br/>
"BinOp8RF", which is used by the "defm" line that generates the "add"<br/>
instruction pattern:<br/>
<br/>
     multiclass BinOp8RF<Prefix prefix, bits<3> opcode, string mnemonic,<br/>
                         bit compare = 0> {<br/>
       let isCompare = compare, Defs = [A, F], Uses = [A] in {<br/>
         def 8ap : I8 <prefix, {0b10, opcode, 0b110}, mnemonic, "\ta,<br/>
$src", "",<br/>
                       (outs), (ins   ptr:$src),<br/>
                       [(set A, F,<br/>
                            (Z80add_flag<br/>
                                 A, (i8 (load   iPTR:$src))))]>;<br/>
       }<br/>
     }<br/>
<br/>
and the parameters:<br/>
<br/>
     def SDTBinOpRF  : SDTypeProfile<2, 2, [SDTCisInt<0>,<br/>
                                            SDTCisFlag<1>,<br/>
                                            SDTCisSameAs<2, 0>,<br/>
                                            SDTCisSameAs<3, 0>]>;<br/>
<br/>
     def Z80add_flag      : SDNode<"Z80ISD::ADD",     SDTBinOpRF,<br/>
[SDNPCommutative]>;<br/>
<br/>
<br/>
The unary instruction builds fine, which can be checked by commenting<br/>
out the generation of the binary instruction in the last line of the<br/>
attached Z80InstrInfo.td.<br/>
<br/>
The log in Github indicates that this section was present for over a<br/>
year, so I assume that it did work at some time in the past.<br/>
<br/>
My attempts to fixing the instruction failed with other errors, pointing<br/>
specifically to the specific problems I introduced with the change, e.g.<br/>
parameter number mismatch or wrong type, so above (and attached) is the<br/>
unmodified version.<br/>
<br/>
Any help is appreciated!<br/>
<br/>
Michael<br/>
<br/>
<br/>
_______________________________________________<br/>
LLVM Developers mailing list<br/>
<a href="mailto:llvm-dev@lists.llvm.org" onclick="parent.window.location.href='llvm-dev@lists.llvm.org'; return false;" target="_blank">llvm-dev@lists.llvm.org</a><br/>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a></blockquote>
</div>
</div>
</div>
</div>
</div></div></body></html>