Hello.
I am playing with LLVM and trying to make Z80 (Zilog Z80) backend.
The source code is attached.
I have succesfully made some simple test. But now I have problem with ADD
instruction.
The source C code is:
typedef struct
{
unsigned char id1;
unsigned char id2;
unsigned char id3;
} testS;
void simple()
{
testS test;
test.id1 = 0x40;
test.id2 = 0x80;
test.id3 = 0xc0;
}
It produces this LLVM IR:
%struct.testS = type { i8, i8, i8 }
define void @simple() nounwind {
entry:
%test = alloca %struct.testS, align 1
%id1 = getelementptr inbounds %struct.testS* %test, i32 0, i32 0
store i8 64, i8* %id1, align 1
%id2 = getelementptr inbounds %struct.testS* %test, i32 0, i32 1
store i8 -128, i8* %id2, align 1
%id3 = getelementptr inbounds %struct.testS* %test, i32 0, i32 2
store i8 -64, i8* %id3, align 1
ret void
}
And with llc -filetype=asm -march=z80 a get this .s file:
.file "simple4.bc"
.text
.globl simple
.type simple, at function
simple: # @simple
# BB#0: # %entry
ld HL, 8
add HL,SP <--- problem line
ld DE, 1
ld BC, 2
ld (SP+6), BC
ld B, H
ld C, L
or BC, DE
ld (SP+4), BC
ld (HL),64
ld D, H
ld E, L
ld BC, (SP+6)
or DE, BC
ld BC, (SP+4)
ld H, B
ld L, C
ld (HL),-128
ld H, D
ld L, E
ld (HL),-64
$tmp0:
.size simple, ($tmp0)-simple
The problem is that llc replaces ADD instruction with OR.
Without defining OR16 function, the .S is not generated and claims that it
cannot select OR instruction.
So I added OR16 (that's the or BC,DE piece of code).
But problem is that I am using the first two lines:
ld HL, 8
add HL,SP
For FrameIndex and the HL register will contain SP which is only two 2bytes
aligned.
So "OR with 1" will work, but for second assigned :OR with 2"
will not work.
I suspect that llc is assuming that HL will contain 8 (that's the start) and
or-ing 8 with 1 or with 2 is ok.
But my HL has also added SP to it.
This is how my ISD::FrameIndex instruction look like:
def addHLdisp : Z80Instr<(outs HL16:$dst), (ins i16imm:$disp, GPR16:$src),
"ld $dst, $disp\n\tadd $dst,$src",
[(set HL16:$dst, (add GPR16:$src, (i16 imm:$disp)))]>;
So it say that HL16:$dst wich is only HL register, will be changed.
I also tried to change it to
<(outs HL16:$dst), (ins i16imm:$disp, SP16:$src),
But the output is the same.
Can someone tell me what I am doing wrong?
Peter.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: llvm_to_send.tgz
Type: application/x-compressed
Size: 20867 bytes
Desc: not available
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20120425/837febdd/attachment.bin>
Hi Peter,
I think the problem is that you did not explicitly define stack alignment
in Z80TargetMachine.cpp
DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-n8")
Try to add S16 to the string if your stack is 2-byte aligned. Refer to
http://llvm.org/docs/LangRef.html#datalayout .
If it does not work, try to specify the layout in the input module using
target layout directive.
David
On Wed, Apr 25, 2012 at 4:57 PM, Peter Hanzel <hanzelpeter at gmail.com>
wrote:
> Hello.
>
> I am playing with LLVM and trying to make Z80 (Zilog Z80) backend.
> The source code is attached.
>
> I have succesfully made some simple test. But now I have problem with ADD
> instruction.
> The source C code is:
>
> typedef struct
> {
> unsigned char id1;
> unsigned char id2;
> unsigned char id3;
>
> } testS;
>
> void simple()
> {
> testS test;
> test.id1 = 0x40;
> test.id2 = 0x80;
> test.id3 = 0xc0;
> }
>
> It produces this LLVM IR:
>
> %struct.testS = type { i8, i8, i8 }
>
> define void @simple() nounwind {
> entry:
> %test = alloca %struct.testS, align 1
> %id1 = getelementptr inbounds %struct.testS* %test, i32 0, i32 0
> store i8 64, i8* %id1, align 1
> %id2 = getelementptr inbounds %struct.testS* %test, i32 0, i32 1
> store i8 -128, i8* %id2, align 1
> %id3 = getelementptr inbounds %struct.testS* %test, i32 0, i32 2
> store i8 -64, i8* %id3, align 1
> ret void
> }
>
> And with llc -filetype=asm -march=z80 a get this .s file:
>
> .file "simple4.bc"
> .text
> .globl simple
> .type simple, at function
> simple: # @simple
> # BB#0: # %entry
> ld HL, 8
> add HL,SP <--- problem line
> ld DE, 1
> ld BC, 2
> ld (SP+6), BC
> ld B, H
> ld C, L
> or BC, DE
> ld (SP+4), BC
> ld (HL),64
> ld D, H
> ld E, L
> ld BC, (SP+6)
> or DE, BC
> ld BC, (SP+4)
> ld H, B
> ld L, C
> ld (HL),-128
> ld H, D
> ld L, E
> ld (HL),-64
> $tmp0:
> .size simple, ($tmp0)-simple
>
>
> The problem is that llc replaces ADD instruction with OR.
>
> Without defining OR16 function, the .S is not generated and claims that it
> cannot select OR instruction.
> So I added OR16 (that's the or BC,DE piece of code).
>
> But problem is that I am using the first two lines:
>
> ld HL, 8
> add HL,SP
>
> For FrameIndex and the HL register will contain SP which is only two
> 2bytes aligned.
> So "OR with 1" will work, but for second assigned :OR with
2" will not
> work.
>
> I suspect that llc is assuming that HL will contain 8 (that's the
start)
> and or-ing 8 with 1 or with 2 is ok.
> But my HL has also added SP to it.
> This is how my ISD::FrameIndex instruction look like:
>
> def addHLdisp : Z80Instr<(outs HL16:$dst), (ins i16imm:$disp,
GPR16:$src),
> "ld $dst, $disp\n\tadd $dst,$src",
> [(set HL16:$dst, (add GPR16:$src, (i16 imm:$disp)))]>;
>
> So it say that HL16:$dst wich is only HL register, will be changed.
> I also tried to change it to
> <(outs HL16:$dst), (ins i16imm:$disp, SP16:$src),
>
> But the output is the same.
>
> Can someone tell me what I am doing wrong?
>
> Peter.
>
>
>
>
>
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20120425/b0046bc0/attachment.html>
Hello. I have played with DataLayout and found a solution with is uknown to me. I added S16 and also s0:16:16, but it had not worked. Then I found that in Z80FrameLowering.h I am calling TargetFrameLowering with stack aligment set to 8. So I changed it to 2 bytes. But this also didn't help. Then I changed llc to show TargetDataLayout and found that a option is set to a0:0:64. So I changed my Z80DataLayout to a0:0:16. And voila, it started to work and ADD was not longer replaced by OR. Only for add+1 to or, which is correct. So now I don't understand that a option in datalyout. According doc it is alignment for aggregate type. But anyhow thanks for help and pointing me in right direction. Peter. On Wed, Apr 25, 2012 at 4:31 PM, Fan Dawei <fandawei.s at gmail.com> wrote:> Hi Peter, > > I think the problem is that you did not explicitly define stack alignment > in Z80TargetMachine.cpp > > DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-n8") > > Try to add S16 to the string if your stack is 2-byte aligned. Refer to > http://llvm.org/docs/LangRef.html#datalayout . > > If it does not work, try to specify the layout in the input module using > target layout directive. > > David > > On Wed, Apr 25, 2012 at 4:57 PM, Peter Hanzel <hanzelpeter at gmail.com>wrote: > >> Hello. >> >> I am playing with LLVM and trying to make Z80 (Zilog Z80) backend. >> The source code is attached. >> >> I have succesfully made some simple test. But now I have problem with ADD >> instruction. >> The source C code is: >> >> typedef struct >> { >> unsigned char id1; >> unsigned char id2; >> unsigned char id3; >> >> } testS; >> >> void simple() >> { >> testS test; >> test.id1 = 0x40; >> test.id2 = 0x80; >> test.id3 = 0xc0; >> } >> >> It produces this LLVM IR: >> >> %struct.testS = type { i8, i8, i8 } >> >> define void @simple() nounwind { >> entry: >> %test = alloca %struct.testS, align 1 >> %id1 = getelementptr inbounds %struct.testS* %test, i32 0, i32 0 >> store i8 64, i8* %id1, align 1 >> %id2 = getelementptr inbounds %struct.testS* %test, i32 0, i32 1 >> store i8 -128, i8* %id2, align 1 >> %id3 = getelementptr inbounds %struct.testS* %test, i32 0, i32 2 >> store i8 -64, i8* %id3, align 1 >> ret void >> } >> >> And with llc -filetype=asm -march=z80 a get this .s file: >> >> .file "simple4.bc" >> .text >> .globl simple >> .type simple, at function >> simple: # @simple >> # BB#0: # %entry >> ld HL, 8 >> add HL,SP <--- problem line >> ld DE, 1 >> ld BC, 2 >> ld (SP+6), BC >> ld B, H >> ld C, L >> or BC, DE >> ld (SP+4), BC >> ld (HL),64 >> ld D, H >> ld E, L >> ld BC, (SP+6) >> or DE, BC >> ld BC, (SP+4) >> ld H, B >> ld L, C >> ld (HL),-128 >> ld H, D >> ld L, E >> ld (HL),-64 >> $tmp0: >> .size simple, ($tmp0)-simple >> >> >> The problem is that llc replaces ADD instruction with OR. >> >> Without defining OR16 function, the .S is not generated and claims that >> it cannot select OR instruction. >> So I added OR16 (that's the or BC,DE piece of code). >> >> But problem is that I am using the first two lines: >> >> ld HL, 8 >> add HL,SP >> >> For FrameIndex and the HL register will contain SP which is only two >> 2bytes aligned. >> So "OR with 1" will work, but for second assigned :OR with 2" will not >> work. >> >> I suspect that llc is assuming that HL will contain 8 (that's the start) >> and or-ing 8 with 1 or with 2 is ok. >> But my HL has also added SP to it. >> This is how my ISD::FrameIndex instruction look like: >> >> def addHLdisp : Z80Instr<(outs HL16:$dst), (ins i16imm:$disp, GPR16:$src), >> "ld $dst, $disp\n\tadd $dst,$src", >> [(set HL16:$dst, (add GPR16:$src, (i16 imm:$disp)))]>; >> >> So it say that HL16:$dst wich is only HL register, will be changed. >> I also tried to change it to >> <(outs HL16:$dst), (ins i16imm:$disp, SP16:$src), >> >> But the output is the same. >> >> Can someone tell me what I am doing wrong? >> >> Peter. >> >> >> >> >> >> >> >> >> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120425/df8bb5a1/attachment.html>