How to map own register operands in llvm-tablegen to instruction's opcode?

522 views Asked by At

I'm trying to implement "address register with offset"-type operands. They consist of base registers and offset registers: [K1 + K3]. However in instruction's opcode I need to keep code for those register separately. I found no way of 1) Getting code of operand (is that a thing?) 2) Mapping Reg:$Rm, Reg:$Rn of operand to Rm and Rn fields of instruction directly. I'm getting Rm placed in slot for Rn and Rn merely ignored.

So how to get this thing done?

When i try to add them via BuildMI and print code they seem to be written correctly, so I guess those operands are parsed properly.

Operands description

def MemRRAsmOperand : AsmOperandClass {
  let Name = "MemRR";
  let ParserMethod = "parseMEMOperand";
}

class MemRR<RegisterOperand Reg> : Operand<i32>
{
  let MIOperandInfo = (ops Reg:$Rm, Reg:$Rn); <--- --- ---
  let ParserMatchClass = MemRRAsmOperand;
}

let PrintMethod = "printMemOperand" in
{
  def memJJ : MemRR<RegisterOperand<JSS>>;
  def memKK : MemRR<RegisterOperand<KSS>>;
}

Instruction description

class IALULoadStoreInstBase<dag outs, dag ins, string mnemonic, string operands, list<dag> pattern> :
  MyInst<outs, ins, mnemonic, operands, pattern>
{

    ...

  bits<5> Ureg; 
  bits<5> Rn; 
  bits<5> Rm; 

    ...
//IType is opcode
  let IType{25-21} = Group;  
  let IType{20-16} = Ureg;

  let IType{15} = MOD;
  let IType{14} = LQ;
  let IType{13} = ImmFlag;

  let IType{12-8} = Rm; <--- --- ---
  let IType{7-6} = 0b00;
  let IType{5-1} = Rn; <--- --- ---
  let IType{0} = Q;
   ...

}

Multiclass where I fill flags and pass out's and ins'es

multiclass IALULoadInstDst<RegisterOperand Dst, string mnemonic, string prefix, ValueType Type>
{
  let WR = 0 in
  {
    let JK = 0 in
    {
      let MOD = 0 in
      {
        defm fromJrr : IALULoadStoreRRInstEx<(outs Dst:$Ureg), (ins memJJ:$src), <--- --- ---
                                             !strconcat(mnemonic, "fromjrr"), !strconcat("$Ureg, ", prefix, "[$src]"), <--- --- ---
                                             [(set Type:$Ureg, (load addr:$src))]>; <--- --- ---
      }
    }
    let JK = 1 in
    {
      let MOD = 0 in
      {
        defm fromKrr : IALULoadStoreRRInstEx<(outs Dst:$Ureg), (ins memKK:$src), <--- --- ---
                                             !strconcat(mnemonic, "fromkrr"), !strconcat("$Ureg, ", prefix, "[$src]"), <--- --- ---
                                             [(set Type:$Ureg, (load addr:$src))]>; <--- --- ---
      }
    }
  }
}
1

There are 1 answers

0
Anton Korobeynikov On BEST ANSWER

You need to write your own selection code for such operands. Such patterns are called "Complex" and you need to write custom instruction selection code for them. See e.g. X86DAGToDAGISel::SelectAddr() or SystemZDAGToDGAISel::selectBDAddr() and around.