Addr pc, const Loader::SymbolTable *symtab) const
{
stringstream ss;
+ bool printSecondSrc = true;
+ bool printShift = false;
- ccprintf(ss, "%-10s ", mnemonic);
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("srawi")) {
+ printSecondSrc = false;
+ printShift = true;
+ }
+
+ // 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
- ss << ", " << sh;
+ // Print the shift value
+ if (printShift) {
+ ss << ", " << shift;
+ }
return ss.str();
}
/**
- * Class for integer operations with a shift.
+ * Class for integer operations with a shift value obtained from
+ * a register or an instruction field.
*/
class IntShiftOp : public IntOp
{
protected:
- uint32_t sh;
+ uint32_t shift;
/// Constructor
IntShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: IntOp(mnem, _machInst, __opClass),
- sh(machInst.sh)
+ shift(machInst.sh)
{
}
}
Ra = res;
}});
+ }
+ // Integer instructions with a shift value.
+ format IntShiftOp {
24: slw({{
- if (Rb & 0x20) {
- Ra = 0;
- } else {
- Ra = Rs << (Rb & 0x1f);
+ int32_t shift = Rb_sw;
+ uint32_t res = Rs_uw & ~((shift << 26) >> 31);
+ if (shift != 0) {
+ shift = shift & 0x1f;
+ res = res << shift;
}
+ Ra = res;
}});
536: srw({{
- if (Rb & 0x20) {
- Ra = 0;
- } else {
- Ra = Rs >> (Rb & 0x1f);
+ int32_t shift = Rb_sw;
+ uint32_t res = Rs_uw & ~((shift << 26) >> 31);
+ if (shift != 0) {
+ shift = shift & 0x1f;
+ res = res >> shift;
}
+ Ra = res;
}});
792: sraw({{
- bool shiftSetCA = false;
- int32_t s = Rs;
- if (Rb == 0) {
- Ra = Rs;
- shiftSetCA = true;
- } else if (Rb & 0x20) {
- if (s < 0) {
- Ra = (uint32_t)-1;
- if (s & 0x7fffffff) {
- shiftSetCA = true;
- } else {
- shiftSetCA = false;
- }
- } else {
- Ra = 0;
- shiftSetCA = false;
+ int32_t src = Rs_sw;
+ uint32_t shift = Rb_uw;
+ int64_t res;
+ if ((shift & 0x20) != 0) {
+ res = src >> 31;
+ if (res != 0) {
+ setCA = true;
}
} else {
- Ra = s >> (Rb & 0x1f);
- if (s < 0 && (s << (32 - (Rb & 0x1f))) != 0) {
- shiftSetCA = true;
+ if (shift != 0) {
+ shift = shift & 0x1f;
+ res = src >> shift;
+ if (src < 0 && (src & mask(shift)) != 0) {
+ setCA = true;
+ }
} else {
- shiftSetCA = false;
+ res = src;
}
}
- Xer xer1 = XER;
- if (shiftSetCA) {
- xer1.ca = 1;
- } else {
- xer1.ca = 0;
- }
- XER = xer1;
- }});
- }
+ Ra = res;
+ }},
+ true);
- // Integer logic instructions with a shift value.
- format IntShiftOp {
824: srawi({{
- bool shiftSetCA = false;
- if (sh == 0) {
- Ra = Rs;
- shiftSetCA = false;
- } else {
- int32_t s = Rs;
- Ra = s >> sh;
- if (s < 0 && (s << (32 - sh)) != 0) {
- shiftSetCA = true;
- } else {
- shiftSetCA = false;
+ int32_t src = Rs_sw;
+ int64_t res;
+ if (shift != 0) {
+ res = src >> shift;
+ if (src < 0 && (src & mask(shift)) != 0) {
+ setCA = true;
}
- }
- Xer xer1 = XER;
- if (shiftSetCA) {
- xer1.ca = 1;
} else {
- xer1.ca = 0;
+ res = src;
}
- XER = xer1;
- }});
+ Ra = res;
+ }},
+ true);
}
// Generic integer format instructions.
}};
-// Integer instructions with a shift amount. As above, except inheriting
-// from the IntShiftOp class.
-def format IntShiftOp(code, inst_flags = []) {{
+// Integer instructions that perform shift operations. All of these
+// instructions write to Ra and use Rs as a source register. The shift
+// value is obtained from an register or an instruction field. If it
+// from a register, Rb is also used as a source register. In certain
+// situations, the carry bits have to be set and this is dealt with
+// using the 'setCA' boolean in decoder.isa. We need two versions for
+// each instruction to deal with the Rc bit.
+def format IntShiftOp(code, computeCA = 0, inst_flags = []) {{
dict = {'result':'Ra'}
+ # Add code to setup variables and access XER if necessary
+ code = 'bool setCA M5_VAR_USED = false;\n' + code
+
# Code when Rc is set
- code_rc1 = code + readXERCode + computeCR0Code % dict
+ code_rc1 = readXERCode + code + computeCR0Code % dict
+
+ # Add code for calculating the carry, if needed
+ if computeCA:
+ code = readXERCode + code + setCACode + setXERCode
+ code_rc1 += setCACode + setXERCode
# Generate the first class
(header_output, decoder_output, decode_block, exec_output) = \