Sometimes the constraints imposed on an instruction’s encoding are too complex to be described in tablegen alone. In such cases a custom decoder method is implemented. This makes sense when the decoding itself is very complex, but it is wasteful to do it only when checking additional constraints. This is because:
- a custom decoder method has to decode operands, set opcodes, etc. - many times the tablegen generated decoder is perfectly capable of doing this job so there is no reason in doing it by hand
- when custom decoder methods are implemented for similar-looking instructions there is high chance of code duplication (i.e. reading the fields out of the encoding, setting opcodes using the same logic but with different enums, etc.).
Here is a practical example: ARM NEON vector instructions may work in either double word mode (taking d registers) or in quad word mode (taking q registers). The mode is selected by bit 6 (Q bit). When Q == 1, then quad word mode is used.
There is an additional constraint: whenever Q == 1, the registers encoded in the instruction need to be even. Otherwise the encoding is undefined.
This constraint is currently unimplemented and triggers incorrect behaviour in the MC disassembler. In order to correct this I would have to create custom decoder methods for a dozen-some instructions which is wasteful. I would much prefer to be able to define a constraint function like:
static DecodeStatus CheckNEONConstraint(const MCInst &Inst, unsigned Insn)
Vd = fieldFromInstruction(Insn, 12, 4);
Vm = fieldFromInstruction(Insn, 0, 4);
Vn = fieldFromInstruction(Insn, 16, 4);
Q = fieldFromInstruction(Insn, 6, 1);
if (Q == 1 && ((Vd & 1) || (Vm & 1) || (Vn & 1)))
Then I’d like to use this in the td file with something along the lines of
ConstraintCheckMethod = “CheckNEONConstraint”
in the superclass of NEON instructions.
I envision this as the very last step in deciding whether an encoding is valid or not. In my example the tablegen generated decoder would “decode” the invalid encoding and create a MCInst but, because this final test returns failure, the encoding is rejected.
What do you guys think about this? I feel it’ll generally simplify things and could be an opportunity to get rid of some of the custom decoder methods.