visualize: provide a visual map of the memory layout - on Z80 at least
authorAlan Cox <alan@linux.intel.com>
Mon, 25 Jun 2018 21:08:38 +0000 (22:08 +0100)
committerAlan Cox <alan@linux.intel.com>
Mon, 25 Jun 2018 21:08:38 +0000 (22:08 +0100)
A 64 x 4 display showing 64K split into 256 byte chunks in 64 x 1K vertical
stripes showing free and used spaces.

Doesn't produce sensible output for banked binaries.

Kernel/tools/visualize.c [new file with mode: 0644]

diff --git a/Kernel/tools/visualize.c b/Kernel/tools/visualize.c
new file mode 100644 (file)
index 0000000..ad07096
--- /dev/null
@@ -0,0 +1,156 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static uint8_t use[256];
+
+struct section {
+       struct section *next;
+       char name[64];
+       char code;
+       unsigned int start;
+       unsigned int len;
+       int flags;
+#define KNOW_START     1
+#define KNOW_SIZE      2
+};
+
+static struct section *head;
+
+static struct section *find_create(const char *name)
+{
+       struct section *s = head;
+       while (s) {
+               if (strcmp(s->name, name) == 0)
+                       return s;
+               s = s->next;
+       }
+       s = malloc(sizeof(struct section));
+       if (s == NULL) {
+               fputs("Out of memory.\n", stderr);
+               exit(1);
+       }
+       s->flags = 0;
+       strncpy(s->name, name, 64);
+       s->name[63] = 0;
+       s->next = head;
+       head = s;
+       return s;
+}
+
+static char code_for(const char *name)
+{
+       if (strcmp(name, "CODE") == 0)
+               return '1';
+       if (strcmp(name, "CODE1") == 0)
+               return '1';
+       if (strcmp(name, "CODE2") == 0)
+               return '2';
+       if (strcmp(name, "CODE3") == 0)
+               return '3';
+       if (strcmp(name, "CODE4") == 0)
+               return '4';
+       if (strcmp(name, "CODE5") == 0)
+               return '5';
+       if (strcmp(name, "CODE6") == 0)
+               return '6';
+       if (strcmp(name, "VIDEO") == 0)
+               return 'V';
+       if (strcmp(name, "FONT") == 0)
+               return 'F';
+       if (strcmp(name, "INITIALIZED") == 0)
+               return 'I';
+       if (strcmp(name, "HOME") == 0)
+               return 'H';
+       if (strcmp(name, "DISCARD") == 0)
+               return 'X';
+       if (strcmp(name, "DATA") == 0)
+               return 'D';
+       if (strcmp(name, "BUFFERS") == 0)
+               return 'B';
+       if (strcmp(name, "COMMONMEM") == 0)
+               return 'S';
+       if (strcmp(name, "COMMONDATA") == 0)
+               return 's';
+       if (strcmp(name, "CONST") == 0)
+               return 'C';
+       if (strcmp(name, "INITIALIZER") == 0)
+               return 'i';
+       return '?';
+}
+
+static void learn_size(const char *size, const char *name)
+{
+       struct section *s = find_create(name);
+       if (sscanf(size, "%8X", &s->len) != 1) {
+               fprintf(stderr, "Invalid size '%s'.\n", size);
+               exit(1);
+       }
+       s->flags |= KNOW_SIZE;
+}
+
+static void learn_start(const char *addr, const char *name)
+{
+       struct section *s = find_create(name);
+       if (sscanf(addr, "%8X", &s->start) != 1) {
+               fprintf(stderr, "Invalid start '%s'.\n", addr);
+               exit(1);
+       }
+       s->flags |= KNOW_START;
+}
+
+static void mark_map(void)
+{
+       unsigned int base, end;
+       struct section *s = head;
+       while (s) {
+               if (s->flags != (KNOW_SIZE | KNOW_START)) {
+                       fprintf(stderr, "Incomplete section '%s'.\n",
+                               s->name);
+                       exit(1);
+               }
+               if (s->len) {
+                       s->code = code_for(s->name);
+                       base = (s->start + 127) >> 8;
+                       end = (s->start + s->len + 127) >> 8;
+                       while (base <= end) {
+                               use[base++] = s->code;
+                       }
+               }
+               s = s->next;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       char buf[512];
+       int i;
+       int r;
+
+       memset(use, '#', 256);
+
+       while (fgets(buf, 511, stdin)) {
+               char *p1 = strtok(buf, " \t\n");
+               char *p2 = NULL;
+
+               if (p1)
+                       p2 = strtok(NULL, " \t\n");
+
+               if (p1 == NULL || p2 == NULL)
+                       continue;
+
+               if (strncmp(p2, "l__", 3) == 0)
+                       learn_size(p1, p2 + 3);
+               if (strncmp(p2, "s__", 3) == 0)
+                       learn_start(p1, p2 + 3);
+       }
+       mark_map();
+       for (r = 0; r < 4; r++) {
+               for (i = 0; i < 256; i += 4)
+                       putchar(use[i + r]);
+               putchar('\n');
+       }
+       exit(0);
+}