From 99d55796569d84e6b9be9579bdf54bddaa23e3ac Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 8 Feb 2021 00:13:52 -0800 Subject: [PATCH] arch-mips: Fix a bug in the MIPS yield instruction. The yieldThread function implements MIPS's yield instruction, and had a if condition in it, (src_reg && !yield_mask != 0), which upset clang. When originally committed, this check read (src_reg & !yield_mask != 0), but apparently as part of a cleanup sweep a long time ago, it was assumed that the & was being used as a logical operator and was turned into &&. Reading the actual description of what the yield instruction is supposed to do, if src_reg is positive (it is at this point in the function), then it's supposed to be treated as a bitvector. The YQMask register, what gets passed in as yield_mask, can have bits set in it which mask bits that might be set in src_reg, and if any are still set, the an interrupt should happen, as implemented by the body of the if. From this description, it's apparent that what the original code was *trying* to do was to use yield_mask to mask any set bits in src_reg, and then if any bits were left go into the body. The original author used ! as a bitwise negating operator since what they *wanted* to do was to block any bits in src_reg where yield_mask *is* set, and let through any where yield_mask *is not* set. The & would do that, but only with a bitwise negated yield_mask. Hence: if ((src_reg & ~yield_mask) != 0) { ... } Change-Id: I30d0a47992750adf78c8aa0c28217da187e0cbda Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40957 Maintainer: Gabe Black Tested-by: kokoro Reviewed-by: Boris Shingarov --- src/arch/mips/mt.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/mips/mt.hh b/src/arch/mips/mt.hh index 9ab3290b7a..da4c51ac93 100644 --- a/src/arch/mips/mt.hh +++ b/src/arch/mips/mt.hh @@ -273,7 +273,7 @@ yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) curTick(), tc->threadId()); } } else if (src_reg > 0) { - if (src_reg && !yield_mask != 0) { + if ((src_reg & ~yield_mask) != 0) { VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL); vpeControl.excpt = 2; tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl);