Dylan McKay
2015-Jan-31 08:40 UTC
[LLVMdev] Encoding instructions with inconsistent formats
I'm attempting to implement codegen support for the AVR ST/LD <http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_ST.html> family of instructions. The binary encoding is not particularly consistent -- take a look at this table of variants of LD, along with their machine code representation: # load 8 bits from pointer register X into general purpose Rd ld Rd, X `1001 000d dddd 1100` ld Rd, X+ `1001 000d dddd 1101` (load with postincrement) ld Rd, -X `1001 000d dddd 1110` (load with predecrement) ld Rd, Y `1000 000d dddd 1000` ld Rd, Y+ `1001 000d dddd 1001` ld Rd, -Y `1001 000d dddd 1010` ld Rd, Z `1000 000d dddd 0000` ld Rd, Z+ `1001 000d dddd 0001` ld Rd, -Z `1001 000d dddd 0010` ^ | Note this one inconsistent bit One way to solve this solution would be to to describe them in InstrInfo.td as seperate instructions. Note that R27R26 is a pointer register defined in AVRRegisterInfo.td, and 'X' is an alias for this. let Uses = [R27R26], canFoldAsLoad = 1, isReMaterializable = 1 in def LDRdX : FSTLDPtrReg<0b0, (outs GPR8:$reg), (ins), "ld\t$reg, X", [(set GPR8:$reg, (load R27R26))]>; def LDRdY : FSTLDPtrReg<0b0, // ... When I do this, however, I get errors that the pointer register is an invalid operand type. Another solution might be to have a generic 'LD' pseudo instruction, which is later lowered into one of the 9 variants, which each have the correct encoding. This is a messy, hacky solution, which also bloats the code a fair bit more. One last solution is to 'make up a pattern' for the inconsistent bit that fits. It is: Inconsistent bit = (postinc OR predec) OR IsPtrXReg Where 'postinc' and 'predec' is 1 if the respective mode is used, and 0 otherwise, and IsPtrXReg is 1 if the pointer register is X. I have tried to assign this bit using this expression with macros in AVRInstrInfo.td, but I couldn't get it to compile (!or is not defined, and I don't think macros will solve this situation regardless). -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150131/96296f69/attachment.html>
Tim Northover
2015-Jan-31 18:10 UTC
[LLVMdev] Encoding instructions with inconsistent formats
Hi Dylan, One way to view those instructions is that the extra bit is actually part of how the register is encoded. You could probably create a new Operand subclass with a custom EncoderMethod that gets assigned to both the dddd and the odd field. Something like: def BasicMemXYZ : Operand<i16> { let MIOperandInfo = (ops XYZReg); // Sorry, don't know what you've called it let CustomEncoder = "encodeXYZForBasicMem"; } Associate that operand with 5 bits in the instruction instead of 4 and let the C++ set the final bit as appropriate. Cheers. Tim.
Dylan McKay
2015-Jan-31 22:52 UTC
[LLVMdev] Encoding instructions with inconsistent formats
I can't get it to work with pattern matching. My operand is defined like so: def LDSTPtrReg : Operand<i16> { let MIOperandInfo = (ops PTRREGS); let EncoderMethod = "encodeLDSTPtrReg"; } I am able to use it in the place of PTRREGS in the definition of the LD instruction, but if I use it in an instruction matching pattern, compilation fails with the error "Unknown leaf kind: LDSTPtrReg:i16:$ptrreg". On Sun, Feb 1, 2015 at 10:26 AM, Dylan McKay <dylanmckay34 at gmail.com> wrote:> You could probably create a new >> Operand subclass with a custom EncoderMethod that gets assigned to >> both the dddd and the odd field > > Ah, I hadn't realised that the encoder method had access to the containing > instruction. > > I believe your method will work well, thanks! > > On Sun, Feb 1, 2015 at 7:10 AM, Tim Northover <t.p.northover at gmail.com> > wrote: > >> Hi Dylan, >> >> One way to view those instructions is that the extra bit is actually >> part of how the register is encoded. You could probably create a new >> Operand subclass with a custom EncoderMethod that gets assigned to >> both the dddd and the odd field. >> >> Something like: >> >> def BasicMemXYZ : Operand<i16> { >> let MIOperandInfo = (ops XYZReg); // Sorry, don't know what you've >> called it >> let CustomEncoder = "encodeXYZForBasicMem"; >> } >> >> Associate that operand with 5 bits in the instruction instead of 4 and >> let the C++ set the final bit as appropriate. >> >> Cheers. >> >> Tim. >> > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150201/84150920/attachment.html>
Tim Northover
2015-Jan-31 23:00 UTC
[LLVMdev] Encoding instructions with inconsistent formats
Hi Dylan,> I am able to use it in the place of PTRREGS in the definition of the LD > instruction, but if I use it in an instruction matching pattern, compilation > fails with the error "Unknown leaf kind: LDSTPtrReg:i16:$ptrreg".I think it should work if you just use "i16:$ptrreg" in the pattern rather than specifying the new operand type: "(set GPR8:$reg, (load i16:$ptrreg))". Cheers. Tim.