<div dir="ltr"><div>On Tue, Jul 17, 2018 at 9:28 PM, Michael Stellmann via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br></div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I'm working on a Z80 backend and am trying to efficiently lower SEXT, specifically 8 to 16 bit, in LowerOperation() according to the following rules:<br>
<br>
The Z80 has 8 bit registers and 16 bit registers, which are aliased versions of two 8 bit registers.<br>
<br>
8 bit registers are named A, H, L, D, E and some more.<br>
16 bit registers are HL (composed of H + L), DE (D + E) - and some more - with L and E being the low bits (LSB).<br>
<br>
For SEXT from 8 to 16 bit, here are the rules to do it efficiently:<br>
<br>
8 bit reg  ->  16 bit reg<br>
Fast extension:<br>
L              HL, by making MSB (H) = 0/255<br>
E              DE, by making MSB (D) = 0/255<br>
<br>
Slow (costly) extension:<br>
H              HL or DE, by making LSB (D or L) = H and MSB (H) = 0/255<br>
D              same as above<br>
<br>
Reg "A" doesn't have a 16 bit register pair, so SEXT must always done as a "slow" operation.</blockquote><div><br></div><div><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">I'm not sure it's a useful thing to insist on putting the high and low bytes into a 16 bit register pair. Maybe that's the path of least resistance with LLVM.</span></div><div><br><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial">I don't think there's any particularly fast or slow places to start with the value. In the place where you want the low half to end up is ideal of course, but if not then it changes little. I don't think you can do better than this?</div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial"><br></div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial">LO -> HI || LO:</div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial"><br></div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial">ld a, LO<br></div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial">rla</div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial">sbc a, a</div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial">ld HI, a</div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial"><br></div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial">If the value starts in a, reverse the first instruction. If the value starts somewhere else (even in HI) then move it to both LO and a. One more instruction. Nothing else changes.</div><br class="gmail-Apple-interchange-newline"> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
For the fast extension, how could an efficient lowering be done so L prefers being extended into HL and E into DE (and saving any previous content of H or D somewhere else)?<br></blockquote><div><br></div><div>Again, you don't need to do that. If LLVM allocates the result into a 16 bit register, it will make sure<span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span> </span>by itself that</span> nothing else useful is already there.</div><div><br></div></div></div></div>