mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 21:53:12 +08:00
[SPARC] Implement L and H inline asm argument modifiers (#87259)
This adds support for using the L and H argument modifiers for twinword
operands in inline asm code, such as in:
```
%1 = tail call i64 asm sideeffect "rd %pc, ${0:L} ; srlx ${0:L}, 32, ${0:H}", "={o4}"()
```
This is needed by the Linux kernel.
This commit is contained in:
@@ -5557,6 +5557,8 @@ RISC-V:
|
||||
|
||||
Sparc:
|
||||
|
||||
- ``L``: Print the low-order register of a two-register operand.
|
||||
- ``H``: Print the high-order register of a two-register operand.
|
||||
- ``r``: No effect.
|
||||
|
||||
SystemZ:
|
||||
|
||||
@@ -434,6 +434,50 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
default:
|
||||
// See if this is a generic print operand
|
||||
return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
|
||||
case 'L': // Low order register of a twin word register operand
|
||||
case 'H': // High order register of a twin word register operand
|
||||
{
|
||||
const SparcSubtarget &Subtarget = MF->getSubtarget<SparcSubtarget>();
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
|
||||
Register MOReg = MO.getReg();
|
||||
|
||||
Register HiReg, LoReg;
|
||||
if (!SP::IntPairRegClass.contains(MOReg)) {
|
||||
// If we aren't given a register pair already, find out which pair it
|
||||
// belongs to. Note that here, the specified register operand, which
|
||||
// refers to the high part of the twinword, needs to be an even-numbered
|
||||
// register.
|
||||
MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
|
||||
&SP::IntPairRegClass);
|
||||
if (!MOReg) {
|
||||
SMLoc Loc;
|
||||
OutContext.reportError(
|
||||
Loc, "Hi part of pair should point to an even-numbered register");
|
||||
OutContext.reportError(
|
||||
Loc, "(note that in some cases it might be necessary to manually "
|
||||
"bind the input/output registers instead of relying on "
|
||||
"automatic allocation)");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
|
||||
LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
|
||||
|
||||
Register Reg;
|
||||
switch (ExtraCode[0]) {
|
||||
case 'L':
|
||||
Reg = LoReg;
|
||||
break;
|
||||
case 'H':
|
||||
Reg = HiReg;
|
||||
break;
|
||||
}
|
||||
|
||||
O << '%' << SparcInstPrinter::getRegisterName(Reg);
|
||||
return false;
|
||||
}
|
||||
case 'f':
|
||||
case 'r':
|
||||
break;
|
||||
|
||||
@@ -11,3 +11,12 @@ entry:
|
||||
tail call void asm sideeffect "faddq $0,$1,$2", "{f38},{f0},{f0}"(fp128 0xL0, fp128 0xL0, fp128 0xL0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-label:test_twinword_error
|
||||
; CHECK: error: Hi part of pair should point to an even-numbered register
|
||||
; CHECK: error: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)
|
||||
|
||||
define i64 @test_twinword_error(){
|
||||
%1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i1}"()
|
||||
ret i64 %1
|
||||
}
|
||||
|
||||
@@ -143,3 +143,12 @@ entry:
|
||||
%1 = call double asm sideeffect "faddd $1, $2, $0", "=f,f,e"(i64 0, i64 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-label:test_twinword
|
||||
; CHECK: rd %asr5, %i1
|
||||
; CHECK: srlx %i1, 32, %i0
|
||||
|
||||
define i64 @test_twinword(){
|
||||
%1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i0}"()
|
||||
ret i64 %1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user