I’m attempting to implement codegen support for the AVR ST/LD 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).