Describe instruction set of a VLIW architecture with TableGen

I have read the following documents about TableGen:

I also have Alex Bradbury’s RISC-V commit history handy, and have understood how to describe a straightforward RISC ISA with llvm-tblgen and include the generated code in the MC layer C++ source files. But I am not sure if llvm-tblgen is versatile enough to describe my own ISA with the following features:

I am working on implementing the MC layer for a VLIW architecture (not CodeGen yet). The instructions are grouped into bundles (or packets). Each bundle is 64-bit wide, and contains three 21-bit wide individual ops. The last one X-bit in the bundle specifies whether the individual ops in the bundle are executed in parallel. Its encoding can be depicted as below:

  63 62           42 41           21 20            0
+---+---------------+---------------+---------------+
| X |      op1      |      op2      |      op3      |
+---+---------------+---------------+---------------+

Some instructions are 42-bit wide, and they take up 2 consecutive slots within a bundle.

When writing assembly, the parallel ops (X-bit = 0) are delimited by ||, and the serial ops (X-bit = 1) are delimited by &&.

op1 || op2 || op3;   # ops in bundle executed in parallel
op1 && op2 && op3;   # ops executed sequentially from left to right

I even spent the time learning the Hexagon ISA. But their VLIW is different from mine. To simply put, Hexagon glues individual 32-bit instructions together to form long bundles. While in my case, I shove instructions into a bundle of fixed width.

Can experts tell me whether the current llvm-tblgen is able to handle this kind of ISA? If so, how? I can express the 21-bit or 42-bit individual ops in those .td files, but that X-bit really got me :frowning:

Just looked into HexagonMCCodeEmitter::encodeInstruction(), which emits the encoding of the whole bundle. This function traverses each single instruction in a bundle using HexagonMCCodeEmitter::EncodeSingleInstruction(), which ultimately calles getBinaryCodeForInstr() generated by TableGen.

It’s good to find out that the bundling is coped outside of the getBinaryCodeForInstr() function, and I don’t have to think my a** off trying to figure out how to shove that information into TableGen.