/* * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * author: Jerome Glisse */ #include #include #include #include #include "rdb.h" #define WINDOW 64 struct reg { struct reg *next; unsigned offset; unsigned value; unsigned after; unsigned before; unsigned tmp_count; unsigned pos; }; struct cmp { struct reg *reg; unsigned nreg; }; void cmp_set_reg(struct cmp *cmp, unsigned offset, unsigned value, unsigned pos) { struct reg *reg = cmp->reg; while (reg) { if (reg->offset == offset) { reg->value = value; reg->tmp_count++; reg->pos = pos; return; } reg = reg->next; } reg = malloc(sizeof(*reg)); reg->offset = offset; reg->value = value; reg->next = cmp->reg; reg->after = 0; reg->before = 0; reg->pos = pos; reg->tmp_count = 1; cmp->reg = reg; cmp->nreg++; } void cmp_commit_before(struct cmp *cmp, unsigned pos) { struct reg *reg = cmp->reg; while (reg) { if (reg->pos < pos && (pos - reg->pos) < WINDOW) { reg->before += reg->tmp_count; } reg->tmp_count = 0; reg = reg->next; } } void cmp_commit_after(struct cmp *cmp, unsigned pos) { struct reg *reg = cmp->reg; while (reg) { if (reg->pos > pos && (reg->pos - pos) < WINDOW) { reg->after += reg->tmp_count; } reg->tmp_count = 0; reg = reg->next; } } void cmp_print(struct cmp *cmp) { struct reg *reg = cmp->reg; while (reg) { printf("%8d %8d 0x%08x\n", reg->before, reg->after, reg->offset); reg = reg->next; } } static void cmp_short_before(struct cmp *cmp) { unsigned not_shorted = 1; unsigned npass = 0; //cmp_print(cmp); while (not_shorted) { struct reg *reg = cmp->reg; struct reg **preg = &cmp->reg; not_shorted = 0; while (reg) { if (reg->next && reg->next->before > reg->before) { struct reg *nreg = reg->next; *preg = nreg; reg->next = nreg->next; nreg->next = reg; not_shorted = 1; } preg = ®->next; reg = reg->next; } //printf("pass %d ---------------------------------------\n", npass); //cmp_print(cmp); npass++; } } static void cmp_short_after(struct cmp *cmp) { unsigned not_shorted = 1; while (not_shorted) { struct reg *reg = cmp->reg; struct reg **preg = &cmp->reg; not_shorted = 0; while (reg) { if (reg->next && reg->next->after > reg->after) { struct reg *nreg = reg->next; *preg = nreg; reg->next = nreg->next; nreg->next = reg; not_shorted = 1; } preg = ®->next; reg = reg->next; } } } char *line_skip(char *line, unsigned nspace) { do { if (*line == ' ') { nspace--; } line++; } while (nspace); return line; } void annotate(struct cmp *cmp, unsigned mreg, FILE *file) { char line[128], *tmp; unsigned offset, value, ndw = 0, pkt = 0, it; unsigned pos = 0, rpos = 0; while (!feof(file)) { if (fgets(line, sizeof(line), file) == NULL) { continue; } pos++; if (rpos && pos > rpos && (pos - rpos) >= WINDOW) { cmp_commit_after(cmp, rpos); rpos = 0; } line[strlen(line) - 1] = 0; tmp = strstr(line, "] ["); if (tmp == NULL) { // printf("%s\n", line); continue; } tmp = strchr(tmp + 4, ']'); if (tmp == NULL) { // printf("%s\n", line); continue; } value = strtoul(tmp + 2, &tmp, 0); if (tmp == NULL) { // printf("%s\n", line); continue; } if (ndw) { switch (pkt) { case 3: switch (it) { case 0x68: if (!offset) { offset = (value << 2) + 0x8000; } else { cmp_set_reg(cmp, offset, value, pos); if (offset == mreg) { rpos = pos; cmp_commit_before(cmp, rpos); } offset += 4; } break; case 0x69: if (!offset) { offset = (value << 2) + 0x28000; } else { cmp_set_reg(cmp, offset, value, pos); if (offset == mreg) { rpos = pos; cmp_commit_before(cmp, rpos); } offset += 4; } break; default: // printf("%s\n", line); break; } break; case 0: default: cmp_set_reg(cmp, offset, value, pos); if (offset == mreg) { rpos = pos; cmp_commit_before(cmp, rpos); } offset += 4; break; } ndw--; } else { pkt = (value >> 30) & 3; switch (pkt) { case 0: offset = (value & 0xffff) << 2; if (offset == mreg) { rpos = pos; cmp_commit_before(cmp, rpos); } ndw = ((value >> 16) & 0x3fff) + 1; break; case 3: offset = 0; ndw = ((value >> 16) & 0x3fff) + 1; it = ((value >> 8) & 0xff); switch (it) { case 0x29: case 0x2b: case 0x2d: case 0x2e: case 0x35: /* DRAW */ break; default: break; } break; case 1: case 2: default: break; } } } } int main(int argc, char *argv[]) { struct cmp cmp; FILE *file; unsigned reg, i; cmp.reg = NULL; cmp.nreg = 0; if (argc < 3) { printf("usage %s rdb reg ibfile*\n", argv[0]); return -1; } reg = strtoul(argv[1], NULL, 0); for (i = 2; i < argc; i++) { file = fopen(argv[i], "r"); if (file == NULL) { fprintf(stderr, "failed reading %s\n", argv[i]); return -1; } while (!feof(file)) { annotate(&cmp, reg, file); } fclose(file); } printf("BEFORE REG %d -------------------------------------------------------\n", cmp.nreg); cmp_short_before(&cmp); cmp_print(&cmp); #if 1 printf("AFTER REG %d -------------------------------------------------------\n", cmp.nreg); cmp_short_after(&cmp); cmp_print(&cmp); #endif }