#include <stdio.h>
#include <ctype.h>
#include <stdint.h>

char *make_string(uint32_t val)
{
  static char string[5] = "xxxx";
  int i, ch;

  for ( i = 0 ; i < 4 ; i++ ) {
    ch = val & 0xff;
    string[i] = isprint(ch) ? ch : '.';
    val >>= 8;
  }

  return string;
}

void dump_cpuid_level(uint32_t level)
{
  uint32_t eax, ebx, ecx, edx;

  asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
      : "a" (level));

  printf("%08X:  %08X %s  ", level, eax, make_string(eax));
  printf("%08X %s  ", ebx, make_string(ebx));
  printf("%08X %s  ", ecx, make_string(ecx));
  printf("%08X %s\n", edx, make_string(edx));
}

void dump_levels(uint32_t region)
{
  uint32_t max, n;

  asm("cpuid" : "=a" (max) : "a" (region) : "ebx","ecx","edx");
  if ( (max & 0xffff0000) == region ) {
    for ( n = region ; n <= max ; n++ ) {
      dump_cpuid_level(n);
    }
  }
}

int main(int argc, char *argv[])
{
  uint32_t n;

  printf("Level      EAX            EBX            ECX            EDX            \n");

  for ( n = 0 ; n <= 0xffff ; n++ ) {
    dump_levels(n << 16);
  }

  return 0;
}
