New x86 instruction with opcode 0x0F 0x7A

Hi all,

I’m trying to simulate an extended x86 architecture on gem5 with several new instructions. My hardware setup is done and now I’d like llvm to accept the existence of the new instruction passed in inline assembly and output the correct opcode and registers. I chose the two-byte opcode 0x0F 0x7A and I would like the instruction to have the same operands and return values as CVTPS2PI instruction.

I have found this link (https://llvm.org/docs/ExtendingLLVM.html) which claims “Before you invest a significant amount of effort into a non-trivial extension, ask on the list” so that’s what I’m doing. I would like to know which of the solutions would work in my case and what’s the easiest way to achieve my goal.

Thank you very much!

Adding these to X86InstrInfo.td or any other X86Instr*.td should pretty much do it.

def MYINSTRrr : I<0x7A, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), “myinstrmnemonic\t{$src, $dst|$dst, $src}”, []> PS;

def MYINSTRrm : I<0x7A, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), “myinstrmnemonic\t{$src, $dst|$dst, $src}”, []> PS;

Replace MYINSTR and myinstrmnemonic with the name of your instruction.

Since CVTPS2PI has a form that reads memory and a form that reads a register you need to do define two instructions for LLVM. The MRMSrcReg and MRMSrcMem distinguish the difference for the assembler and disassembler to know how to map the operands to the ModRM byte. There are also MRMDestReg and MRMDestMem for instructions that have store behavior instead of load.

The 0x7A is from your chosen opcode of 0x0F 0x7A. The 0x0F is specificed implicitly as part of the PS at the end of the line. PS means its on the "two byte opcode map"where the first byte is 0x0F. The PS further implies that there is no 0xF2/0xF3/0x66 prefix emitted with this instruction. But if you had one of those prefixes in front of 0x0F 0x7A it should not decode to this instruction. This is probably used by most SSE instruction that has a packed single precision floating point type. And most MMX instructions.

The “ins” and “outs” list specify the inputs and outputs of the instructions and their types. VR64 means 64-bit Vector Register (aka. MM0-MM7), VR128 is a 128-bit Vector Register (XMM0-XMM15). f64mem means it reads a 64-bit floating point location. There are also f128mem, i128mem, f256mem, i256mem, etc.

The string with “myisntrmnemonic” is the string for the assembler to match. The names prefixed with dollar sign correspond to the names in ins and outs. So that they can me matched correctly and allow arbitrary orders. The curly braces indicate alternatives for at&t and intel syntax. at&t put destination on the right of the operand list. Intel syntax puts destination first. The | character in the middle separates the two orders.

The empty square brackets normally define an instruction selection pattern, but since you only mentioned inline assembly you can leave it empty.

let me know if you have any questions.

Hi Craig,

I’m assuming much or all of this information isn’t written up in documentation anywhere, or you would have provided a link.

Would you be willing to write some kind of how-to-write-instruction-definitions overview? Or even if it’s specific to X86, I suspect that would still be helpful to people writing private targets (seems to happen a lot).

Just a thought… thanks,

–paulr