Skip to content

Commit 6e9110a

Browse files
author
Hal Finkel
committed
[PowerPC] Add asm parser support for bitmask forms of rotate-and-mask instructions
The asm syntax for the 32-bit rotate-and-mask instructions can take a 32-bit bitmask instead of an (mb, me) pair. This syntax is not specified in the Power ISA manual, but is accepted by GNU as, and is documented in IBM's Assembler Language Reference. The GNU Multiple Precision Arithmetic Library (gmp) contains assembly that uses this syntax. To implement this, I moved the isRunOfOnes utility function from PPCISelDAGToDAG.cpp to PPCMCTargetDesc.h. llvm-svn: 233483
1 parent 7fdcc30 commit 6e9110a

File tree

5 files changed

+122
-31
lines changed

5 files changed

+122
-31
lines changed

llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,58 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst,
10711071
Inst = TmpInst;
10721072
break;
10731073
}
1074+
case PPC::RLWINMbm:
1075+
case PPC::RLWINMobm: {
1076+
unsigned MB, ME;
1077+
int64_t BM = Inst.getOperand(3).getImm();
1078+
if (!isRunOfOnes(BM, MB, ME))
1079+
break;
1080+
1081+
MCInst TmpInst;
1082+
TmpInst.setOpcode(Opcode == PPC::RLWINMbm ? PPC::RLWINM : PPC::RLWINMo);
1083+
TmpInst.addOperand(Inst.getOperand(0));
1084+
TmpInst.addOperand(Inst.getOperand(1));
1085+
TmpInst.addOperand(Inst.getOperand(2));
1086+
TmpInst.addOperand(MCOperand::CreateImm(MB));
1087+
TmpInst.addOperand(MCOperand::CreateImm(ME));
1088+
Inst = TmpInst;
1089+
break;
1090+
}
1091+
case PPC::RLWIMIbm:
1092+
case PPC::RLWIMIobm: {
1093+
unsigned MB, ME;
1094+
int64_t BM = Inst.getOperand(3).getImm();
1095+
if (!isRunOfOnes(BM, MB, ME))
1096+
break;
1097+
1098+
MCInst TmpInst;
1099+
TmpInst.setOpcode(Opcode == PPC::RLWIMIbm ? PPC::RLWIMI : PPC::RLWIMIo);
1100+
TmpInst.addOperand(Inst.getOperand(0));
1101+
TmpInst.addOperand(Inst.getOperand(0)); // The tied operand.
1102+
TmpInst.addOperand(Inst.getOperand(1));
1103+
TmpInst.addOperand(Inst.getOperand(2));
1104+
TmpInst.addOperand(MCOperand::CreateImm(MB));
1105+
TmpInst.addOperand(MCOperand::CreateImm(ME));
1106+
Inst = TmpInst;
1107+
break;
1108+
}
1109+
case PPC::RLWNMbm:
1110+
case PPC::RLWNMobm: {
1111+
unsigned MB, ME;
1112+
int64_t BM = Inst.getOperand(3).getImm();
1113+
if (!isRunOfOnes(BM, MB, ME))
1114+
break;
1115+
1116+
MCInst TmpInst;
1117+
TmpInst.setOpcode(Opcode == PPC::RLWNMbm ? PPC::RLWNM : PPC::RLWNMo);
1118+
TmpInst.addOperand(Inst.getOperand(0));
1119+
TmpInst.addOperand(Inst.getOperand(1));
1120+
TmpInst.addOperand(Inst.getOperand(2));
1121+
TmpInst.addOperand(MCOperand::CreateImm(MB));
1122+
TmpInst.addOperand(MCOperand::CreateImm(ME));
1123+
Inst = TmpInst;
1124+
break;
1125+
}
10741126
}
10751127
}
10761128

llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#undef PPC
1919

2020
#include "llvm/Support/DataTypes.h"
21+
#include "llvm/Support/MathExtras.h"
2122

2223
namespace llvm {
2324
class MCAsmBackend;
@@ -51,6 +52,35 @@ MCObjectWriter *createPPCELFObjectWriter(raw_ostream &OS,
5152
MCObjectWriter *createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit,
5253
uint32_t CPUType,
5354
uint32_t CPUSubtype);
55+
56+
/// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with
57+
/// any number of 0s on either side. The 1s are allowed to wrap from LSB to
58+
/// MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is
59+
/// not, since all 1s are not contiguous.
60+
static inline bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
61+
if (!Val)
62+
return false;
63+
64+
if (isShiftedMask_32(Val)) {
65+
// look for the first non-zero bit
66+
MB = countLeadingZeros(Val);
67+
// look for the first zero bit after the run of ones
68+
ME = countLeadingZeros((Val - 1) ^ Val);
69+
return true;
70+
} else {
71+
Val = ~Val; // invert mask
72+
if (isShiftedMask_32(Val)) {
73+
// effectively look for the first zero bit
74+
ME = countLeadingZeros(Val) - 1;
75+
// effectively look for the first one bit after the run of zeros
76+
MB = countLeadingZeros((Val - 1) ^ Val) + 1;
77+
return true;
78+
}
79+
}
80+
// no run present
81+
return false;
82+
}
83+
5484
} // End llvm namespace
5585

5686
// Generated files will use "namespace PPC". To avoid symbol clash,

llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,6 @@ namespace {
105105
return CurDAG->getTargetConstant(Imm, PPCLowering->getPointerTy());
106106
}
107107

108-
/// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s
109-
/// with any number of 0s on either side. The 1s are allowed to wrap from
110-
/// LSB to MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs.
111-
/// 0x0F0F0000 is not, since all 1s are not contiguous.
112-
static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME);
113-
114-
115108
/// isRotateAndMask - Returns true if Mask and Shift can be folded into a
116109
/// rotate and mask opcode and mask operation.
117110
static bool isRotateAndMask(SDNode *N, unsigned Mask, bool isShiftMask,
@@ -418,30 +411,6 @@ SDNode *PPCDAGToDAGISel::getFrameIndex(SDNode *SN, SDNode *N, unsigned Offset) {
418411
getSmallIPtrImm(Offset));
419412
}
420413

421-
bool PPCDAGToDAGISel::isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
422-
if (!Val)
423-
return false;
424-
425-
if (isShiftedMask_32(Val)) {
426-
// look for the first non-zero bit
427-
MB = countLeadingZeros(Val);
428-
// look for the first zero bit after the run of ones
429-
ME = countLeadingZeros((Val - 1) ^ Val);
430-
return true;
431-
} else {
432-
Val = ~Val; // invert mask
433-
if (isShiftedMask_32(Val)) {
434-
// effectively look for the first zero bit
435-
ME = countLeadingZeros(Val) - 1;
436-
// effectively look for the first one bit after the run of zeros
437-
MB = countLeadingZeros((Val - 1) ^ Val) + 1;
438-
return true;
439-
}
440-
}
441-
// no run present
442-
return false;
443-
}
444-
445414
bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask,
446415
bool isShiftMask, unsigned &SH,
447416
unsigned &MB, unsigned &ME) {

llvm/lib/Target/PowerPC/PPCInstrInfo.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3726,6 +3726,19 @@ def : InstAlias<"rotld. $rA, $rS, $rB", (RLDCLo g8rc:$rA, g8rc:$rS, gprc:$rB, 0)
37263726
def : InstAlias<"clrldi $rA, $rS, $n", (RLDICL g8rc:$rA, g8rc:$rS, 0, u6imm:$n)>;
37273727
def : InstAlias<"clrldi. $rA, $rS, $n", (RLDICLo g8rc:$rA, g8rc:$rS, 0, u6imm:$n)>;
37283728

3729+
def RLWINMbm : PPCAsmPseudo<"rlwinm $rA, $rS, $n, $b",
3730+
(ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>;
3731+
def RLWINMobm : PPCAsmPseudo<"rlwinm. $rA, $rS, $n, $b",
3732+
(ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>;
3733+
def RLWIMIbm : PPCAsmPseudo<"rlwimi $rA, $rS, $n, $b",
3734+
(ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>;
3735+
def RLWIMIobm : PPCAsmPseudo<"rlwimi. $rA, $rS, $n, $b",
3736+
(ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>;
3737+
def RLWNMbm : PPCAsmPseudo<"rlwnm $rA, $rS, $n, $b",
3738+
(ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>;
3739+
def RLWNMobm : PPCAsmPseudo<"rlwnm. $rA, $rS, $n, $b",
3740+
(ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>;
3741+
37293742
// These generic branch instruction forms are used for the assembler parser only.
37303743
// Defs and Uses are conservative, since we don't know the BO value.
37313744
let PPC970_Unit = 7 in {

llvm/test/MC/PowerPC/ppc64-encoding.s

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,33 @@
703703
# CHECK-LE: rldimi. 2, 3, 4, 5 # encoding: [0x4d,0x21,0x62,0x78]
704704
rldimi. 2, 3, 4, 5
705705

706+
# Aliases that take bit masks...
707+
708+
# CHECK-BE: rlwinm 0, 0, 30, 31, 31 # encoding: [0x54,0x00,0xf7,0xfe]
709+
rlwinm 0, 0, 30, 1
710+
# CHECK-BE: rlwinm. 0, 0, 30, 31, 31 # encoding: [0x54,0x00,0xf7,0xff]
711+
rlwinm. 0, 0, 30, 1
712+
# CHECK-BE: rlwinm 0, 0, 30, 31, 0 # encoding: [0x54,0x00,0xf7,0xc0]
713+
rlwinm 0, 0, 30, 2147483649
714+
# CHECK-BE: rlwinm. 0, 0, 30, 31, 0 # encoding: [0x54,0x00,0xf7,0xc1]
715+
rlwinm. 0, 0, 30, 2147483649
716+
# CHECK-BE: rlwimi 0, 0, 30, 31, 31 # encoding: [0x50,0x00,0xf7,0xfe]
717+
rlwimi 0, 0, 30, 1
718+
# CHECK-BE: rlwimi. 0, 0, 30, 31, 31 # encoding: [0x50,0x00,0xf7,0xff]
719+
rlwimi. 0, 0, 30, 1
720+
# CHECK-BE: rlwimi 0, 0, 30, 31, 0 # encoding: [0x50,0x00,0xf7,0xc0]
721+
rlwimi 0, 0, 30, 2147483649
722+
# CHECK-BE: rlwimi. 0, 0, 30, 31, 0 # encoding: [0x50,0x00,0xf7,0xc1]
723+
rlwimi. 0, 0, 30, 2147483649
724+
# CHECK-BE: rlwnm 0, 0, 30, 31, 31 # encoding: [0x5c,0x00,0xf7,0xfe]
725+
rlwnm 0, 0, 30, 1
726+
# CHECK-BE: rlwnm. 0, 0, 30, 31, 31 # encoding: [0x5c,0x00,0xf7,0xff]
727+
rlwnm. 0, 0, 30, 1
728+
# CHECK-BE: rlwnm 0, 0, 30, 31, 0 # encoding: [0x5c,0x00,0xf7,0xc0]
729+
rlwnm 0, 0, 30, 2147483649
730+
# CHECK-BE: rlwnm. 0, 0, 30, 31, 0 # encoding: [0x5c,0x00,0xf7,0xc1]
731+
rlwnm. 0, 0, 30, 2147483649
732+
706733
# CHECK-BE: slw 2, 3, 4 # encoding: [0x7c,0x62,0x20,0x30]
707734
# CHECK-LE: slw 2, 3, 4 # encoding: [0x30,0x20,0x62,0x7c]
708735
slw 2, 3, 4

0 commit comments

Comments
 (0)