arch-power: Add doubleword shift instructions
This introduces a new class and a new format for XS form instructions where the shift amount is specified by two fields that must be concatenated and adds the following instructions. * Shift Left Doubleword (sld[.]) * Shift Right Doubleword (srd[.]) * Shift Right Algebraic Doubleword (srad[.]) * Shift Right Algebraic Doubleword Immediate (sradi[.]) * Extend-Sign Word and Shift Left Immediate (extswsli[.]) Change-Id: If51c676009ddafb40f855b66c00eeeffa5d8874c Signed-off-by: Sandipan Das <sandipan@linux.ibm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40928 Reviewed-by: Boris Shingarov <shingarov@labware.com> Maintainer: Boris Shingarov <shingarov@labware.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -594,6 +594,68 @@ IntShiftOp::generateDisassembly(
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
IntConcatShiftOp::generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
bool printSecondSrc = true;
|
||||
bool printShift = false;
|
||||
|
||||
// Generate the correct mnemonic
|
||||
std::string myMnemonic(mnemonic);
|
||||
|
||||
// Special cases
|
||||
if (myMnemonic == "sradi" ||
|
||||
myMnemonic == "extswsli") {
|
||||
printSecondSrc = false;
|
||||
printShift = true;
|
||||
}
|
||||
|
||||
// Additional characters depending on isa bits being set
|
||||
if (rc)
|
||||
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 (rc) {
|
||||
if (_numSrcRegs > 2) {
|
||||
ss << ", ";
|
||||
printReg(ss, srcRegIdx(2));
|
||||
}
|
||||
} else {
|
||||
if (_numSrcRegs > 1) {
|
||||
ss << ", ";
|
||||
printReg(ss, srcRegIdx(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print the shift value
|
||||
if (printShift)
|
||||
ss << ", " << (int) sh;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
IntRotateOp::generateDisassembly(
|
||||
Addr pc, const loader::SymbolTable *symtab) const
|
||||
|
||||
@@ -600,6 +600,28 @@ class IntShiftOp : public IntOp
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class for integer shift operations with a shift value obtained from
|
||||
* a register or by concatenating immediates.
|
||||
*/
|
||||
class IntConcatShiftOp : public IntOp
|
||||
{
|
||||
protected:
|
||||
|
||||
uint8_t sh;
|
||||
|
||||
/// Constructor
|
||||
IntConcatShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: IntOp(mnem, _machInst, __opClass),
|
||||
sh((machInst.shn << 5) | machInst.sh)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class for integer rotate operations.
|
||||
*/
|
||||
|
||||
@@ -250,10 +250,19 @@ decode PO default Unknown::unknown() {
|
||||
Ra = res;
|
||||
}});
|
||||
|
||||
format IntLogicOp {
|
||||
26: cntlzw({{ Ra = findLeadingZeros(Rs_uw); }}, true);
|
||||
28: and({{ Ra = Rs & Rb; }}, true);
|
||||
}
|
||||
26: IntLogicOp::cntlzw({{ Ra = findLeadingZeros(Rs_uw); }}, true);
|
||||
|
||||
27: IntConcatShiftOp::sld({{
|
||||
int64_t shift = Rb_sd;
|
||||
uint64_t res = Rs & ~((shift << 57) >> 63);
|
||||
if (shift != 0) {
|
||||
shift = bits(shift, 5, 0);
|
||||
res = res << shift;
|
||||
}
|
||||
Ra = res;
|
||||
}});
|
||||
|
||||
28: IntLogicOp::and({{ Ra = Rs & Rb; }}, true);
|
||||
|
||||
32: IntCompOp::cmpl({{
|
||||
if (l)
|
||||
@@ -512,6 +521,17 @@ decode PO default Unknown::unknown() {
|
||||
}});
|
||||
|
||||
538: IntLogicOp::cnttzw({{ Ra = findTrailingZeros(Rs_uw); }}, true);
|
||||
|
||||
539: IntConcatShiftOp::srd({{
|
||||
int64_t shift = Rb_sd;
|
||||
uint64_t res = Rs & ~((shift << 57) >> 63);
|
||||
if (shift != 0) {
|
||||
shift = bits(shift, 5, 0);
|
||||
res = res >> shift;
|
||||
}
|
||||
Ra = res;
|
||||
}});
|
||||
|
||||
567: LoadIndexUpdateOp::lfsux({{ Ft_sf = Mem_sf; }});
|
||||
570: IntLogicOp::cnttzd({{ Ra = findTrailingZeros(Rs); }}, true);
|
||||
598: MiscOp::sync({{ }}, [ IsReadBarrier, IsWriteBarrier ]);
|
||||
@@ -590,40 +610,57 @@ decode PO default Unknown::unknown() {
|
||||
|
||||
790: LoadIndexOp::lhbrx({{ Rt = swap_byte(Mem_uh); }});
|
||||
|
||||
format IntShiftOp {
|
||||
792: sraw({{
|
||||
int32_t src = Rs_sw;
|
||||
uint32_t shift = Rb_uw;
|
||||
int64_t res;
|
||||
if (bits(shift, 5)) {
|
||||
res = src >> 31;
|
||||
if (res != 0) {
|
||||
setCA = true;
|
||||
}
|
||||
} else {
|
||||
if (shift != 0) {
|
||||
shift = bits(shift, 4, 0);
|
||||
res = src >> shift;
|
||||
setCA = src < 0 && (src & mask(shift)) != 0;
|
||||
} else {
|
||||
res = src;
|
||||
}
|
||||
792: IntShiftOp::sraw({{
|
||||
int32_t src = Rs_sw;
|
||||
uint32_t shift = Rb_uw;
|
||||
int64_t res;
|
||||
if (bits(shift, 5)) {
|
||||
res = src >> 31;
|
||||
if (res != 0) {
|
||||
setCA = true;
|
||||
}
|
||||
Ra = res;
|
||||
}}, true);
|
||||
|
||||
824: srawi({{
|
||||
int32_t src = Rs_sw;
|
||||
int64_t res;
|
||||
if (sh) {
|
||||
res = src >> sh;
|
||||
setCA = src < 0 && (src & mask(sh)) != 0;
|
||||
} else {
|
||||
if (shift != 0) {
|
||||
shift = bits(shift, 4, 0);
|
||||
res = src >> shift;
|
||||
setCA = src < 0 && (src & mask(shift)) != 0;
|
||||
} else {
|
||||
res = src;
|
||||
}
|
||||
Ra = res;
|
||||
}}, true);
|
||||
}
|
||||
}
|
||||
Ra = res;
|
||||
}}, true);
|
||||
|
||||
794: IntConcatShiftOp::srad({{
|
||||
int64_t src = Rs_sd;
|
||||
uint64_t shift = Rb;
|
||||
int64_t res;
|
||||
if (bits(shift, 6)) {
|
||||
res = src >> 63;
|
||||
setCA = res != 0;
|
||||
} else {
|
||||
if (shift != 0) {
|
||||
shift = shift & 0x3f;
|
||||
res = src >> shift;
|
||||
setCA = src < 0 && (src & mask(shift)) != 0;
|
||||
} else {
|
||||
res = src;
|
||||
}
|
||||
}
|
||||
Ra = res;
|
||||
}}, true);
|
||||
|
||||
824: IntShiftOp::srawi({{
|
||||
int32_t src = Rs_sw;
|
||||
int64_t res;
|
||||
if (sh) {
|
||||
res = src >> sh;
|
||||
setCA = src < 0 && (src & mask(sh)) != 0;
|
||||
} else {
|
||||
res = src;
|
||||
}
|
||||
Ra = res;
|
||||
}}, true);
|
||||
|
||||
854: MiscOp::eieio({{ }}, [ IsReadBarrier, IsWriteBarrier ]);
|
||||
855: LoadIndexOp::lfiwax({{ Ft_uw = Mem; }});
|
||||
@@ -810,38 +847,64 @@ decode PO default Unknown::unknown() {
|
||||
}}, true);
|
||||
}
|
||||
|
||||
default: decode XFX_XO {
|
||||
format IntOp {
|
||||
19: mfcr({{ Rt = CR; }});
|
||||
|
||||
144: mtcrf({{
|
||||
uint32_t mask = 0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (((FXM >> i) & 0x1) == 0x1) {
|
||||
mask |= 0xf << (4 * i);
|
||||
// These instructions are of XS form and use bits 21 - 29 as XO.
|
||||
default: decode XS_XO {
|
||||
format IntConcatShiftOp {
|
||||
413: sradi({{
|
||||
int64_t src = Rs_sd;
|
||||
if (sh != 0) {
|
||||
Ra = src >> sh;
|
||||
if (src < 0 && (src & mask(sh))) {
|
||||
setCA = true;
|
||||
}
|
||||
} else {
|
||||
Ra = src;
|
||||
}
|
||||
}}, true);
|
||||
|
||||
445: extswsli({{
|
||||
int64_t src = Rs_sw;
|
||||
if (sh != 0) {
|
||||
Ra = src << sh;
|
||||
} else {
|
||||
Ra = src;
|
||||
}
|
||||
CR = (Rs & mask) | (CR & ~mask);
|
||||
}});
|
||||
}
|
||||
|
||||
339: decode SPR {
|
||||
0x20: mfxer({{ Rt = XER; }});
|
||||
0x100: mflr({{ Rt = LR; }});
|
||||
0x120: mfctr({{ Rt = CTR; }});
|
||||
0x1f9: mftar({{ Rt = TAR; }});
|
||||
default: decode XFX_XO {
|
||||
format IntOp {
|
||||
19: mfcr({{ Rt = CR; }});
|
||||
|
||||
144: mtcrf({{
|
||||
uint32_t mask = 0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (((FXM >> i) & 0x1) == 0x1) {
|
||||
mask |= 0xf << (4 * i);
|
||||
}
|
||||
}
|
||||
CR = (Rs & mask) | (CR & ~mask);
|
||||
}});
|
||||
|
||||
339: decode SPR {
|
||||
0x20: mfxer({{ Rt = XER; }});
|
||||
0x100: mflr({{ Rt = LR; }});
|
||||
0x120: mfctr({{ Rt = CTR; }});
|
||||
0x1f9: mftar({{ Rt = TAR; }});
|
||||
}
|
||||
|
||||
467: decode SPR {
|
||||
0x20: mtxer({{ XER = Rs; }});
|
||||
0x100: mtlr({{ LR = Rs; }});
|
||||
0x120: mtctr({{ CTR = Rs; }});
|
||||
0x1f9: mttar({{ TAR = Rs; }});
|
||||
}
|
||||
|
||||
512: mcrxr({{
|
||||
CR = insertCRField(CR, BF, XER<31:28>);
|
||||
XER = XER<27:0>;
|
||||
}});
|
||||
}
|
||||
|
||||
467: decode SPR {
|
||||
0x20: mtxer({{ XER = Rs; }});
|
||||
0x100: mtlr({{ LR = Rs; }});
|
||||
0x120: mtctr({{ CTR = Rs; }});
|
||||
0x1f9: mttar({{ TAR = Rs; }});
|
||||
}
|
||||
|
||||
512: mcrxr({{
|
||||
CR = insertCRField(CR, BF, XER<31:28>);
|
||||
XER = XER<27:0>;
|
||||
}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,6 +453,41 @@ def format IntArithCheckRcOp(code, computeOV = 0, inst_flags = []) {{
|
||||
}};
|
||||
|
||||
|
||||
// Integer instructions that also perform shift operations. Everything
|
||||
// is same as above except if the shift value is not obtained from a
|
||||
// register, two immediates need to be concatenated to get the final
|
||||
// shift value.
|
||||
def format IntConcatShiftOp(code, computeCA = 0, inst_flags = []) {{
|
||||
dict = {'result':'Ra'}
|
||||
|
||||
# Add code to setup variables and access XER if necessary
|
||||
code = 'GEM5_VAR_USED bool setCA = false;\n' + code
|
||||
|
||||
# Code when Rc is set
|
||||
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) = \
|
||||
GenAluOp(name, Name, 'IntConcatShiftOp', code, inst_flags,
|
||||
CheckRcDecode, BasicConstructor)
|
||||
|
||||
# Generate the second class
|
||||
(header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
|
||||
GenAluOp(name, Name + 'RcSet', 'IntConcatShiftOp', code_rc1,
|
||||
inst_flags, CheckRcDecode, BasicConstructor)
|
||||
|
||||
# Finally, add to the other outputs
|
||||
header_output += header_output_rc1
|
||||
decoder_output += decoder_output_rc1
|
||||
exec_output += exec_output_rc1
|
||||
}};
|
||||
|
||||
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user