Addr pc, const Loader::SymbolTable *symtab) const
{
stringstream ss;
+ bool printSecondSrc = true;
+ bool printShift = true;
+ bool printMaskBeg = true;
+ bool printMaskEnd = true;
- ccprintf(ss, "%-10s ", mnemonic);
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("rlwinm")) {
+ if (maskBeg == 0 && maskEnd == 31) {
+ myMnemonic = "rotlwi";
+ printMaskBeg = false;
+ printMaskEnd = false;
+ } else if (shift == 0 && maskEnd == 31) {
+ myMnemonic = "clrlwi";
+ printShift = false;
+ printMaskEnd = false;
+ }
+ printSecondSrc = false;
+ } else if (!myMnemonic.compare("rlwnm")) {
+ if (maskBeg == 0 && maskEnd == 31) {
+ myMnemonic = "rotlw";
+ printMaskBeg = false;
+ printMaskEnd = false;
+ }
+ printShift = false;
+ } else if (!myMnemonic.compare("rlwimi")) {
+ printSecondSrc = false;
+ }
+
+ // Additional characters depending on isa bits being set
+ if (rcSet) myMnemonic = myMnemonic + ".";
+ ccprintf(ss, "%-10s ", myMnemonic);
// Print the first destination only
if (_numDestRegs > 0) {
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
+
+ // Print the second source register
+ if (printSecondSrc) {
+
+ // If the instruction updates the CR, the destination register
+ // Ra is read and thus, it becomes the second source register
+ // due to its higher precedence over Rb. In this case, it must
+ // be skipped.
+ if (rcSet) {
+ if (_numSrcRegs > 2) {
+ ss << ", ";
+ printReg(ss, _srcRegIdx[2]);
+ }
+ } else {
+ if (_numSrcRegs > 1) {
+ ss << ", ";
+ printReg(ss, _srcRegIdx[1]);
+ }
+ }
+ }
+ }
+
+ // Print the shift value
+ if (printShift) {
+ ss << ", " << shift;
}
- // Print the shift, mask begin and mask end
- ss << ", " << sh << ", " << mb << ", " << me;
+ // Print the mask bounds
+ if (printMaskBeg) {
+ ss << ", " << maskBeg;
+ }
+ if (printMaskEnd) {
+ ss << ", " << maskEnd;
+ }
return ss.str();
}
/**
- * Class for integer rotate operations.
+ * Class for integer rotate operations with a shift amount obtained
+ * from a register or an immediate and the first and last bits of a
+ * mask obtained from immediates.
*/
class IntRotateOp : public IntShiftOp
{
protected:
- uint32_t mb;
- uint32_t me;
- uint32_t fullMask;
+ uint32_t maskBeg;
+ uint32_t maskEnd;
/// Constructor
IntRotateOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: IntShiftOp(mnem, _machInst, __opClass),
- mb(machInst.mb),
- me(machInst.me)
+ maskBeg(machInst.mb),
+ maskEnd(machInst.me)
{
- if (me >= mb) {
- fullMask = mask(31 - mb, 31 - me);
- } else {
- fullMask = ~mask(31 - (me + 1), 31 - (mb - 1));
- }
}
- uint32_t
- rotateValue(uint32_t rs, uint32_t shift) const
+ inline uint64_t
+ rotate(uint32_t rs, uint32_t sh) const
{
- uint32_t n = shift & 31;
- return (rs << n) | (rs >> (32 - n));
+ uint64_t res;
+ sh = sh & 0x1f;
+ res = rs;
+ res = (res << 32) | res;
+ res = (res << sh) | (res >> (32 - sh));
+ return res;
+ }
+
+ inline uint64_t
+ bitmask(uint32_t mb, uint32_t me) const
+ {
+ mb = mb & 0x1f;
+ me = me & 0x1f;
+ if (mb <= me) {
+ return mask(31 - mb, 31 - me);
+ } else {
+ return ~mask(31 - (me + 1), 31 - (mb - 1));
+ }
}
std::string generateDisassembly(
}
format IntRotateOp {
- 21: rlwinm({{ Ra = rotateValue(Rs, sh) & fullMask; }});
- 23: rlwnm({{ Ra = rotateValue(Rs, Rb) & fullMask; }});
- 20: rlwimi({{ Ra = (rotateValue(Rs, sh) & fullMask) |
- (Ra & ~fullMask); }});
+ 21: rlwinm({{
+ uint64_t res;
+ res = rotate(Rs, shift);
+ res = res & bitmask(maskBeg, maskEnd);
+ Ra = res;
+ }});
+
+ 23: rlwnm({{
+ uint64_t res;
+ res = rotate(Rs, Rb);
+ res = res & bitmask(maskBeg, maskEnd);
+ Ra = res;
+ }});
+
+ 20: rlwimi({{
+ uint64_t res, mask;
+ mask = bitmask(maskBeg, maskEnd);
+ res = rotate(Rs, shift);
+ res = (res & mask) | (Ra & ~mask);
+ Ra = res;
+ }});
}
// There are a large number of instructions that have the same primary
}};
-// A special format for rotate instructions which use certain fields
-// from the instruction's binary encoding. We need two versions for each
-// instruction to deal with the Rc bit.
+// Integer instructions with or without immediate that perform rotate
+// operations. All instructions write to Ra and use Rs as a source
+// register. If immediate is not used, Rb is also used as a source
+// register. We need two versions for each instruction to deal with
+// the Rc bit.
def format IntRotateOp(code, inst_flags = []) {{
# The result is always in Ra
dict = {'result':'Ra'}
- # Setup the code for when Rc is set
+ # Code when Rc is set
code_rc1 = readXERCode + code + computeCR0Code % dict
# Generate the first class