static void insertMaskField(uint32_t *instruction, TR::InstOpCode::Mnemonic op, int64_t lmask) { int32_t encoding; // A mask is is a string of 1 bits surrounded by a string of 0 bits. // For word instructions it is specified through its start and stop bit // numbers. Note - the mask is considered circular so the start bit // number may be greater than the stop bit number. // Examples: input start stop // 00FFFF00 8 23 // 00000001 31 31 // 80000001 31 0 // FFFFFFFF 0 31 (somewhat arbitrary) // 00000000 ? ? (illegal) // // For doubleword instructions only one of the start bit or stop bit is // specified and the other is implicit in the instruction. The bit // number is strangely encoded in that the low order bit 5 comes first // and the high order bits after. The field is in bit positions 21-26. // For these instructions the immediate is not a mask but a 1-bit immediate operand if (op == TR::InstOpCode::cmprb) { // populate 1-bit L field encoding = (((uint32_t)lmask) & 0x1) << 21; *instruction |= encoding; return; } // For these instructions the immediate is not a mask but a 2-bit immediate operand if (op == TR::InstOpCode::xxpermdi || op == TR::InstOpCode::xxsldwi) { encoding = (((uint32_t)lmask) & 0x3) << 8; *instruction |= encoding; return; } if (op == TR::InstOpCode::addex || op == TR::InstOpCode::addex_r) { encoding = (((uint32_t)lmask) & 0x3) << 9; *instruction |= encoding; return; } // For these instructions the immediate is not a mask but a 4-bit immediate operand if (op == TR::InstOpCode::vsldoi) { encoding = (((uint32_t)lmask) & 0xf)<< 6; *instruction |= encoding; return; } TR::InstOpCode opCode(op); if (opCode.isCRLogical()) { encoding = (((uint32_t) lmask) & 0xffffffff); *instruction |= encoding; return; } TR_ASSERT(lmask, "A mask of 0 cannot be encoded"); if (opCode.isDoubleWord()) { int bitnum; if (opCode.useMaskEnd()) { TR_ASSERT(contiguousBits(lmask) && ((lmask & CONSTANT64(0x8000000000000000)) != 0) && ((lmask == -1) || ((lmask & 0x1) == 0)), "Bad doubleword mask for ME encoding"); bitnum = leadingOnes(lmask) - 1; } else { bitnum = leadingZeroes(lmask); // assert on cases like 0xffffff00000000ff TR_ASSERT((bitnum != 0) || (lmask == -1) || ((lmask & 0x1) == 0) || (op!=TR::InstOpCode::rldic && op!=TR::InstOpCode::rldimi && op!=TR::InstOpCode::rldic_r && op!=TR::InstOpCode::rldimi_r), "Cannot handle wrap-around, check mask for correctness"); } encoding = ((bitnum&0x1f)<<6) | ((bitnum&0x20)); } else // single word { // special case the 3-bit rounding mode fields if (op == TR::InstOpCode::drrnd || op == TR::InstOpCode::dqua) { encoding = (lmask << 9) & 0x600; } else { int32_t mask = lmask&0xffffffff; int32_t maskBegin; int32_t maskEnd; maskBegin = leadingZeroes(~mask & (2*mask)); maskBegin = (maskBegin + (maskBegin != 32)) & 0x1f; maskEnd = leadingZeroes(mask & ~(2*mask)); encoding = 32*maskBegin + maskEnd << 1; // shift encrypted mask into position } } *instruction |= encoding; }
const char *TR::DebugCounter::debugCounterBucketName(TR::Compilation *comp, int32_t value, const char *format, ...) { if (!comp->getOptions()->enableDebugCounters()) { return NULL; } TR::StackMemoryRegion stackMemoryRegion(*comp->trMemory()); char *bucketFormat = (char*)comp->trMemory()->allocateStackMemory(strlen(format) + 40); // appending "=%d..%d" where each %d could be 11 characters int32_t low = value; int32_t high = value; if (value != 0 && comp->getOptions()->getDebugCounterBucketGranularity() >= 1) { const int32_t magnitude = abs(value); low = high = magnitude; const int32_t granularity = comp->getOptions()->getDebugCounterBucketGranularity(); const double bucketRatio = pow(2.0, 1.0 / granularity); // TODO: calculate once const int32_t logLow = (int)(log((double)magnitude)/log(bucketRatio)); // Figure out which bucket sizing algorithm to use // const int32_t log2magnitude = 31-leadingZeroes(magnitude); // floor const int32_t doublingInterval = 1 << log2magnitude; if (doublingInterval <= granularity) { // Tiny buckets degenerate to one value per bucket high = low; } else { // We do this with some buckets of size smallBucketSize, plus // some that are 1 larger. // We'd like to make sure make sure the smaller ones come // before bigger ones (eg. we want to see 8-9, 10-12, 13-15 // rather than 8-10, 11-12, 13-15) // low = 1 << log2magnitude; // power-of-two starting point int32_t smallBucketSize = doublingInterval / granularity; int32_t numBigBuckets = doublingInterval - smallBucketSize * granularity; int32_t numSmallBuckets = granularity - numBigBuckets; int32_t totalSmallBucketSize = numSmallBuckets * smallBucketSize; int32_t offset = magnitude-low; if (offset < totalSmallBucketSize) { low += offset - offset % smallBucketSize; high = low + smallBucketSize - 1; } else { offset -= totalSmallBucketSize; low += totalSmallBucketSize + offset - offset % (smallBucketSize+1); high = low + smallBucketSize; } } TR_ASSERT(low <= magnitude && magnitude <= high, "Range (%d..%d) must contain %d\n", low, high, magnitude); if (value < 0) { low = -low; high = -high; } } if (low == high) sprintf(bucketFormat, "%s=%d", format, low); else sprintf(bucketFormat, "%s=%d..%d", format, low, high); va_list args; va_start(args, format); const char *result = comp->getPersistentInfo()->getStaticCounters()->counterName(comp, bucketFormat, args); va_end(args); return result; }