rem: while ((db = (reg & 0xff))) insert(slot, indexOf[db], i++), reg >>= 8;
add: for (; reg; reg >>= 8) if ((db = (reg & 0xff))) insert(slot, indexOf[db], i++);
context: Intel_TLB_cache(cpuid_info *info){	// displays technical info for the CPU's various instruction and data pipeline caches	// and the TLBs (Translation Lookaside Buffers).	//	// The method for extracting and displaying this info might be less than obvious,	// so here's an explanation:	//	// The TLB/Cache info is stored in a global table. Each entry is uniquely identified	// by a descriptor byte. Additionally, each entry is catagorized according to the	// cache type. A textual string contains the information to display.	//	// To retrieve the CPUs capabilities, the pass loop repeatedly (maybe) calls	// get_cpuid() which fills the registers. Each register is a 4-byte datum,	// capable of holding up to 4 descriptor bytes. The descriptor bytes are extracted	// (thru shifting and masking) and then inserted into a slot array. The slot array	// stores indexes into the table. Since descriptor bytes are not indexes themselves,	// an index array is created and used to convert them. The slot array is filled so	// as to keep the indexes in sorted order -- this guarantees than all entries for	// a particular cache type will display together.	//	// After the pass loop is finished, the slot array contains the indexes of all the	// table entries that apply to the host processor. Displaying the info merely a matter	// of spinning thru the slot array and printing the text. The output is organized by	// the cache types -- this technique *only* works because the TLB/Cache table has been	// carefully arranged in that order.		#define BIT_31_MASK (1 << 31)		int    pass, matches;       // counters	uint32 reg;                 // value of an individual register (eax, ebx, ecx, edx)	uint8  db;                  // descriptor byte	int    indexOf[256] = {0};  // converts descriptor bytes to table indexes	int    slot[256] = {0};     // indexes into the TLB/Cache table (for entries found)		tlbc_info *tab = Intel_TLB_Cache_Table;	int   tabsize  = sizeof Intel_TLB_Cache_Table / sizeof(Intel_TLB_Cache_Table[0]);	// fill the index conversion array	int i = 0;	int n = 0;	while (n < tabsize)		indexOf[tab[n++].descriptor] = i++;		// pass loop: insert relevant table indexes into the slots array	i = 0;	for (pass = 0; ; ++pass) {		get_cpuid(info, 2, 0);				// low byte of eax register holds maximum iterations		reg = info->regs.eax;		if (pass >= (reg & 0xff))			break;				reg >>= 8; // skip low byte		while ((db = (reg & 0xff)))			insert(slot, indexOf[db], i++),			reg >>= 8;				reg = info->regs.ebx;  // ebx		if ((reg & BIT_31_MASK) == 0)			while ((db = (reg & 0xff)))				insert(slot, indexOf[db], i++),				reg >>= 8;		reg = info->regs.ecx;  // ecx		if ((reg & BIT_31_MASK) == 0)			while ((db = (reg & 0xff)))				insert(slot, indexOf[db], i++),				reg >>= 8;		reg = info->regs.edx;  // edx		if ((reg & BIT_31_MASK) == 0)			while ((db = (reg & 0xff)))				insert(slot, indexOf[db], i++),				reg >>= 8;	}	// reset slot index for output loop	i = 0;		// eeiuw! an icky macro (but it really does prevent much repetitive code)		#define display_matching_entries(type_name,type_code) \		printf(type_name ":\n"); \		matches = 0; \		while (tab[n = slot[i]].cache_type == type_code) { \			printf("   %s\n", tab[n].text); \			++matches; \			++i; \		} \		if (matches == 0) \			printf("   None\n")		// at long last... output the data	display_matching_entries("Instruction TLB", Inst_TLB);	display_matching_entries("Data TLB", Data_TLB);	display_matching_entries("L1 Instruction Cache", L1_Inst_Cache);	display_matching_entries("L1 Data Cache", L1_Data_Cache);	display_matching_entries("L2 Cache", L2_Cache);		if (tab[slot[i]].cache_type == No_L2_Or_L3)		// no need to print the text on this one, just skip it		++i;		display_matching_entries("L3 Cache", L3_Cache);	display_matching_entries("Trace Cache", Trace_Cache);}