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:
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user