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))]>; <--- --- ---
}
}
}
}
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.