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>