char * captoinfo(char *cap) { char *info, *ip, *token, *val, *p, tok[3]; const char *name; size_t len, lp, nl, vl, rl; int defs[__arraycount(def_infos)], fv; _DIAGASSERT(cap != NULL); len = strlen(cap) * 2; len += __arraycount(def_infos) * (5 + 4 + 3); /* reserve for defs */ info = ip = malloc(len); if (info == NULL) return NULL; memset(defs, 0, sizeof(defs)); lp = 0; tok[2] = '\0'; for (token = _ti_get_token(&cap, ':'); token != NULL; token = _ti_get_token(&cap, ':')) { if (token[0] == '\0') continue; name = token; val = p = NULL; fv = nl = 0; if (token[1] != '\0') { tok[0] = token[0]; tok[1] = token[1]; nl = 1; if (token[2] == '\0') { name = flagname(tok); val = NULL; } else if (token[2] == '#') { name = numname(tok); val = token + 2; } else if (token[2] == '=') { name = strname(tok); val = strval(token + 2); fv = 1; } else nl = 0; } /* If not matched we may need to convert padding still. */ if (nl == 0) { p = strchr(name, '='); if (p != NULL) { val = strval(p); *p = '\0'; fv = 1; } } /* See if this sets a default. */ for (nl = 0; nl < __arraycount(def_infos); nl++) { if (strcmp(name, def_infos[nl].name) == 0) { defs[nl] = 1; break; } } nl = strlen(name); if (val == NULL) vl = 0; else vl = strlen(val); rl = nl + vl + 3; /* , \0 */ if (lp + rl > len) { if (rl < 256) len += 256; else len += rl; p = realloc(info, len); if (p == NULL) { if (fv == 1) free(val); return NULL; } info = p; } if (ip != info) { *ip++ = ','; *ip++ = ' '; } strcpy(ip, name); ip += nl; if (val != NULL) { strcpy(ip, val); ip += vl; if (fv == 1) free(val); } } /* Add any defaults not set above. */ for (nl = 0; nl < __arraycount(def_infos); nl++) { if (defs[nl] == 0) { *ip++ = ','; *ip++ = ' '; strcpy(ip, def_infos[nl].name); ip += strlen(def_infos[nl].name); *ip++ = '='; strcpy(ip, def_infos[nl].cap); ip += strlen(def_infos[nl].cap); } } *ip = '\0'; return info; }
int main() { // Work out all possible masks for(int i=0;i<512;i++) masks[i]=i+1; qsort(masks,512,sizeof(int),compare_bitcounts); // Okay, we now have a set of rules that we can apply. // Generate VHDL file printf("Generating addressing_modes.vhdl\n"); FILE *f=fopen("addressing_modes.vhdl","w"); fprintf(f, "-- DO NOT MODIFY: Auto-generated by addressingmodeequations.c\n" "\n\n" "library ieee;\n" "use Std.TextIO.all;\n" "use ieee.STD_LOGIC_1164.all;\n" "use ieee.numeric_std.all;\n" "\n" "package addressing_modes is\n" "\n" " type addressing_mode is record\n"); for(int flag=1;flag<=MAX_FLAG;flag*=2) { fprintf(f," %s : boolean;\n",flagname(flag)); } fprintf(f, " end record;\n" "\n" " function addressing_modes(opcode : std_logic_vector(8 downto 0)) return addressing_mode;\n" "\n" "end package;\n" "\n" "package body addressing_modes is\n" " function addressing_modes(opcode : std_logic_vector(8 downto 0)) return addressing_mode is\n" " variable mode : addressing_mode := (others => false);\n" " begin\n" " -- XXX Zero out contents of modes?\n" ); for(int flag=1;flag<=MAX_FLAG;flag*=2) { // Try all masks with all possible values, to see what the largest mask is // that we can use to cover the most unclassified remaining opcodes for this mode action. rule_count=0; int remaining=512; for(int i=0;i<512;i++) { covered[i]=0; if (!(modes[i]&flag)) { covered[i]=1; remaining--; } } printf("Finding equations for %d opcodes with mode.%s\n", remaining,flagname(flag)); while(remaining>0) { int best_matches=-1; int best_m=-1, best_v=-1; for(int m=0;m<512;m++) { int last_mv=-1; for(int v=0;v<512;v++) { int mv=m&v; if (mv!=last_mv) { int matches=0; for(int i=0;i<512;i++) { if ((i&m)==v) { if (!(modes[i]&flag)) { matches=-1; break; } if (!covered[i]) matches++; } } if (matches>best_matches) { best_m=m; best_v=v; best_matches=matches; } last_mv=mv; } } } printf("mode.%s, Rule #%d: OPCODE & $%03x = $%03x -> flag is %s (covers %d/%d remaining instructions).\n", flagname(flag),rule_count,best_m,best_v,flagname(flag),best_matches,remaining); rules[rule_count].m=best_m; rules[rule_count].v=best_v; rule_count++; for(int i=0;i<512;i++) if ((i&best_m)==best_v) { if (!covered[i]) remaining--; covered[i]=1; } } // Now verify rules printf("Verifying that %d rules correctly classify lengths of all instructions.\n", rule_count); for(int i=0;i<512;i++) { int actual_value=(modes[i]&flag)?1:0; int predicted_value=0; for(int r=0;r<rule_count;r++) { if ((i&rules[r].m)==rules[r].v) { predicted_value=1; } } if (predicted_value==-1) predicted_value=0; if (predicted_value!=actual_value) { printf("Rules produced wrong value for $%03x: expected %d, but saw %d\n", i,actual_value,predicted_value); exit(-1); } } fprintf(f," -- Equations for mode.%s\n",flagname(flag)); for(int r=0;r<rule_count;r++) { fprintf(f," if (opcode and \"%c%c%c%c%c%c%c%c%c\") = \"%c%c%c%c%c%c%c%c%c\" then mode.%s := true; end if;\n", rules[r].m&256?'1':'0', rules[r].m&128?'1':'0', rules[r].m&64?'1':'0', rules[r].m&32?'1':'0', rules[r].m&16?'1':'0', rules[r].m&8?'1':'0', rules[r].m&4?'1':'0', rules[r].m&2?'1':'0', rules[r].m&1?'1':'0', rules[r].v&256?'1':'0', rules[r].v&128?'1':'0', rules[r].v&64?'1':'0', rules[r].v&32?'1':'0', rules[r].v&16?'1':'0', rules[r].v&8?'1':'0', rules[r].v&4?'1':'0', rules[r].v&2?'1':'0', rules[r].v&1?'1':'0', flagname(flag) ); } } fprintf(f, " return mode;\n" " end function;\n" "end package body;\n"); fclose(f); return 0; }
static void print_label(struct sun_disklabel *sl, const char *disk, FILE *out) { int i, j; int havevtoc; uintmax_t secpercyl; /* Long enough to hex-encode each character. */ char volname[4 * SUN_VOLNAME_LEN + 1]; havevtoc = sl->sl_vtoc_sane == SUN_VTOC_SANE; secpercyl = sl->sl_nsectors * sl->sl_ntracks; fprintf(out, "# /dev/%s:\n" "text: %s\n" "bytes/sector: %d\n" "sectors/cylinder: %ju\n", disk, sl->sl_text, sectorsize, secpercyl); if (eflag) fprintf(out, "# max sectors/unit (including alt cylinders): %ju\n", (uintmax_t)mediasize / sectorsize); fprintf(out, "sectors/unit: %ju\n", secpercyl * sl->sl_ncylinders); if (havevtoc && sl->sl_vtoc_volname[0] != '\0') { for (i = j = 0; i < SUN_VOLNAME_LEN; i++) { if (sl->sl_vtoc_volname[i] == '\0') break; if (isprint(sl->sl_vtoc_volname[i])) volname[j++] = sl->sl_vtoc_volname[i]; else j += sprintf(volname + j, "\\x%02X", sl->sl_vtoc_volname[i]); } volname[j] = '\0'; fprintf(out, "volume name: %s\n", volname); } fprintf(out, "\n" "%d partitions:\n" "#\n", SUN_NPART); if (!hflag) { fprintf(out, "# Size is in %s.", cflag? "cylinders": "sectors"); if (eflag) fprintf(out, " Use %%d%c, %%dK, %%dM or %%dG to specify in %s,\n" "# kilobytes, megabytes or gigabytes respectively, or '*' to specify rest of\n" "# disk.\n", cflag? 's': 'c', cflag? "sectors": "cylinders"); else putc('\n', out); fprintf(out, "# Offset is in cylinders."); if (eflag) fprintf(out, " Use '*' to calculate offsets automatically.\n" "#\n"); else putc('\n', out); } if (havevtoc) fprintf(out, "# size offset tag flag\n" "# ---------- ---------- ---------- ----\n" ); else fprintf(out, "# size offset\n" "# ---------- ----------\n" ); for (i = 0; i < SUN_NPART; i++) { if (sl->sl_part[i].sdkp_nsectors == 0) continue; if (hflag) { fprintf(out, " %c: %10s", 'a' + i, make_h_number((uintmax_t) sl->sl_part[i].sdkp_nsectors * 512)); fprintf(out, " %10s", make_h_number((uintmax_t) sl->sl_part[i].sdkp_cyloffset * 512 * secpercyl)); } else { fprintf(out, " %c: %10ju %10u", 'a' + i, sl->sl_part[i].sdkp_nsectors / (cflag? secpercyl: 1), sl->sl_part[i].sdkp_cyloffset); } if (havevtoc) fprintf(out, " %11s %5s", tagname(sl->sl_vtoc_map[i].svtoc_tag), flagname(sl->sl_vtoc_map[i].svtoc_flag)); putc('\n', out); } }