}
+string
+IntLogicOp::generateDisassembly(
+ Addr pc, const Loader::SymbolTable *symtab) const
+{
+ stringstream ss;
+ bool printSecondSrc = true;
+
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("or") && _srcRegIdx[0] == _srcRegIdx[1]) {
+ myMnemonic = "mr";
+ printSecondSrc = false;
+ } else if (!myMnemonic.compare("extsb") ||
+ !myMnemonic.compare("extsh") ||
+ !myMnemonic.compare("cntlzw")) {
+ 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) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ // Print the first source register
+ if (_numSrcRegs > 0) {
+ 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]);
+ }
+ }
+ }
+ }
+
+ return ss.str();
+}
+
+
+string
+IntImmLogicOp::generateDisassembly(
+ Addr pc, const Loader::SymbolTable *symtab) const
+{
+ stringstream ss;
+ bool printRegs = true;
+
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("ori") &&
+ _destRegIdx[0].index() == 0 && _srcRegIdx[0].index() == 0) {
+ myMnemonic = "nop";
+ printRegs = false;
+ } else if (!myMnemonic.compare("xori") &&
+ _destRegIdx[0].index() == 0 && _srcRegIdx[0].index() == 0) {
+ myMnemonic = "xnop";
+ printRegs = false;
+ } else if (!myMnemonic.compare("andi_")) {
+ myMnemonic = "andi.";
+ } else if (!myMnemonic.compare("andis_")) {
+ myMnemonic = "andis.";
+ }
+
+ ccprintf(ss, "%-10s ", myMnemonic);
+
+ if (printRegs) {
+
+ // Print the first destination only
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ // Print the source register
+ if (_numSrcRegs > 0) {
+ if (_numDestRegs > 0) {
+ ss << ", ";
+ }
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ // Print the immediate value
+ ss << ", " << uimm;
+ }
+
+ return ss.str();
+}
+
+
string
IntCompOp::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
};
+/**
+ * Class for integer logical operations.
+ */
+class IntLogicOp : public IntOp
+{
+ protected:
+
+ /// Constructor
+ IntLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : IntOp(mnem, _machInst, __opClass)
+ {
+ }
+
+ inline int
+ findLeadingZeros(uint32_t rs) const
+ {
+ if (rs) {
+ #if defined(__GNUC__) || (defined(__clang__) && \
+ __has_builtin(__builtin_clz))
+ return __builtin_clz(rs);
+ #else
+ return 31 - findMsbSet(rs);
+ #endif
+ } else {
+ return 32;
+ }
+ }
+
+ std::string generateDisassembly(
+ Addr pc, const SymbolTable *symtab) const override;
+};
+
+
+/**
+ * Class for integer immediate logical operations.
+ */
+class IntImmLogicOp : public IntLogicOp
+{
+ protected:
+
+ uint32_t uimm;
+
+ /// Constructor
+ IntImmLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : IntLogicOp(mnem, _machInst, __opClass),
+ uimm(machInst.si)
+ {
+ }
+
+ std::string generateDisassembly(
+ Addr pc, const SymbolTable *symtab) const override;
+};
+
+
/**
* Class for integer operations with a shift.
*/
// Integer logic instructions use source registers Rs and Rb,
// with destination register Ra.
format IntLogicOp {
- 28: and({{ Ra = Rs & Rb; }});
- 316: xor({{ Ra = Rs ^ Rb; }});
- 476: nand({{ Ra = ~(Rs & Rb); }});
- 444: or({{ Ra = Rs | Rb; }});
- 124: nor({{ Ra = ~(Rs | Rb); }});
- 60: andc({{ Ra = Rs & ~Rb; }});
- 954: extsb({{ Ra = sext<8>(Rs); }});
- 284: eqv({{ Ra = ~(Rs ^ Rb); }});
- 412: orc({{ Ra = Rs | ~Rb; }});
- 922: extsh({{ Ra = sext<16>(Rs); }});
- 26: cntlzw({{ Ra = Rs == 0 ? 32 : 31 - findMsbSet(Rs); }});
+ 28: and({{ Ra = Rs & Rb; }}, true);
+ 316: xor({{ Ra = Rs ^ Rb; }}, true);
+ 476: nand({{ Ra = ~(Rs & Rb); }}, true);
+ 444: or({{ Ra = Rs | Rb; }}, true);
+ 124: nor({{ Ra = ~(Rs | Rb); }}, true);
+ 60: andc({{ Ra = Rs & ~Rb; }}, true);
+ 284: eqv({{ Ra = ~(Rs ^ Rb); }}, true);
+ 412: orc({{ Ra = Rs | ~Rb; }}, true);
+ 954: extsb({{ Ra = Rs_sb; }}, true);
+ 922: extsh({{ Ra = Rs_sh; }}, true);
+ 26: cntlzw({{ Ra = findLeadingZeros(Rs_uw); }}, true);
+
508: cmpb({{
- uint32_t val = 0;
- for (int n = 0; n < 32; n += 8) {
- if(bits(Rs, n+7, n) == bits(Rb, n+7, n)) {
- val = insertBits(val, n+7, n, 0xff);
+ uint64_t mask = 0xff;
+ uint64_t res = 0;
+ for (int i = 0; i < 8; ++i) {
+ if ((Rs & mask) == (Rb & mask)) {
+ res |= mask;
}
+ mask <<= 8;
}
- Ra = val;
+ Ra = res;
}});
24: slw({{
# Set up the dictionary and deal with computing CR0
dict = {'result':'Ra'}
+
+ # Code when Rc is set
if computeCR0:
code += readXERCode + computeCR0Code % dict
# Generate the class
(header_output, decoder_output, decode_block, exec_output) = \
- GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode,
+ GenAluOp(name, Name, 'IntImmLogicOp', code, inst_flags, BasicDecode,
BasicConstructor)
}};
// Integer instructions that perform logic operations. The result is
-// always written into Ra. All instructions have 2 versions depending on
+// always written into Ra. Some instructions have 2 versions depending on
// whether the Rc bit is set to compute the CR0 code. This is determined
// at decode as before.
-def format IntLogicOp(code, inst_flags = []) {{
+def format IntLogicOp(code, computeCR0 = 0, inst_flags = []) {{
dict = {'result':'Ra'}
- # Code when Rc is set
- code_rc1 = code + readXERCode + computeCR0Code % dict
+ # Deal with computing CR0
+ if computeCR0:
+ # Setup the 2 code versions and add code to access XER if necessary
+ code_rc1 = code + readXERCode + computeCR0Code % dict
- # Generate the first class
- (header_output, decoder_output, decode_block, exec_output) = \
- GenAluOp(name, Name, 'IntOp', code, inst_flags,
- CheckRcDecode, BasicConstructor)
+ # Generate the first class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntLogicOp', code, inst_flags,
+ CheckRcDecode, BasicConstructor)
- # Generate the second class
- (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
- GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags,
- CheckRcDecode, IntRcConstructor)
+ # Generate the second class
+ (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
+ GenAluOp(name, Name + 'RcSet', 'IntLogicOp', code_rc1, inst_flags,
+ CheckRcDecode, IntRcConstructor)
- # Finally, add to the other outputs
- header_output += header_output_rc1
- decoder_output += decoder_output_rc1
- exec_output += exec_output_rc1
+ # Finally, add to the other outputs
+ header_output += header_output_rc1
+ decoder_output += decoder_output_rc1
+ exec_output += exec_output_rc1
+
+ else:
+ # Generate the class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntLogicOp', code, inst_flags,
+ BasicDecode, BasicConstructor)
}};