arch-power: Fix rotate instructions

Now that 64-bit registers are being used, the rotation
operation changes for words. Instead of just rotating
the lower word of the operand, the lower word is first
duplicated in the upper word and then rotated. This
fixes the following instructions.
  * Rotate Left Word Immediate then And with Mask (rlwinm[.])
  * Rotate Left Word then And with Mask (rlwnm[.])
  * Rotate Left Word Immediate then Mask Insert (rlwimi[.])

Change-Id: Ic743bceb8bafff461276984ecc999dedc1f94e9f
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40930
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:
Sandipan Das
2021-02-06 17:22:00 +05:30
parent 4ccd755b8c
commit f6ff1b19f7
2 changed files with 40 additions and 12 deletions

View File

@@ -631,7 +631,6 @@ class IntRotateOp : public IntShiftOp
{
protected:
uint32_t fullMask;
uint8_t mb;
uint8_t me;
@@ -641,18 +640,29 @@ class IntRotateOp : public IntShiftOp
mb(machInst.mb),
me(machInst.me)
{
if (me >= mb) {
fullMask = mask(31 - mb, 31 - me);
} else {
fullMask = ~mask(31 - (me + 1), 31 - (mb - 1));
}
}
inline uint32_t
inline uint64_t
rotate(uint32_t value, uint32_t shift) const
{
shift &= 31;
return (value << shift) | (value >> (32 - shift));
uint64_t res;
shift = shift & 0x1f;
res = value;
res = (res << 32) | res;
res = (res << shift) | (res >> (32 - shift));
return res;
}
inline uint64_t
bitmask(uint32_t begin, uint32_t end) const
{
begin = begin & 0x1f;
end = end & 0x1f;
if (begin <= end) {
return mask(31 - begin, 31 - end);
} else {
return ~mask(31 - (end + 1), 31 - (begin - 1));
}
}
std::string generateDisassembly(

View File

@@ -195,9 +195,27 @@ decode PO default Unknown::unknown() {
}
format IntRotateOp {
20: rlwimi({{ Ra = (rotate(Rs, sh) & fullMask) | (Ra & ~fullMask); }});
21: rlwinm({{ Ra = rotate(Rs, sh) & fullMask; }});
23: rlwnm({{ Ra = rotate(Rs, Rb) & fullMask; }});
21: rlwinm({{
uint64_t res;
res = rotate(Rs, sh);
res = res & bitmask(mb, me);
Ra = res;
}});
23: rlwnm({{
uint64_t res;
res = rotate(Rs, Rb);
res = res & bitmask(mb, me);
Ra = res;
}});
20: rlwimi({{
uint64_t res, mask;
mask = bitmask(mb, me);
res = rotate(Rs, sh);
res = (res & mask) | (Ra & ~mask);
Ra = res;
}});
}
format IntImmLogicOp {