trunk/src/emu/cpu/m6502/m6502make.c
| r19366 | r19367 | |
| 1 | | #include <stdio.h> |
| 2 | | #include <stdlib.h> |
| 3 | | #include <string.h> |
| 4 | | #include <assert.h> |
| 5 | | #include <stdarg.h> |
| 6 | | #include <ctype.h> |
| 7 | | #include "osdcomm.h" |
| 8 | | |
| 9 | | #include <string> |
| 10 | | #include <vector> |
| 11 | | |
| 12 | | using namespace std; |
| 13 | | |
| 14 | | enum { STATES = 0x101 }; |
| 15 | | |
| 16 | | const char *snames[STATES-0x100] = { |
| 17 | | "STATE_RESET" |
| 18 | | }; |
| 19 | | |
| 20 | | struct opcode { |
| 21 | | string name; |
| 22 | | vector<string> instructions; |
| 23 | | }; |
| 24 | | |
| 25 | | vector<opcode> opcodes; |
| 26 | | |
| 27 | | struct table_t { |
| 28 | | string opcodes[STATES]; |
| 29 | | }; |
| 30 | | |
| 31 | | table_t table; |
| 32 | | |
| 33 | | string device_name; |
| 34 | | |
| 35 | | static void load_opcodes(const char *fname) |
| 36 | | { |
| 37 | | char buf[4096]; |
| 38 | | FILE *f; |
| 39 | | |
| 40 | | sprintf(buf, "Error opening %s for reading\n", fname); |
| 41 | | f = fopen(fname, "r"); |
| 42 | | if(!f) { |
| 43 | | perror(buf); |
| 44 | | exit(1); |
| 45 | | } |
| 46 | | |
| 47 | | while(fgets(buf, sizeof(buf), f)) { |
| 48 | | char *p = buf; |
| 49 | | if(p[0] == '#' || p[0] == '\r' || p[0] == '\n' || p[0] == 0) |
| 50 | | continue; |
| 51 | | |
| 52 | | for(char *q = p; *q; q++) |
| 53 | | if(*q == '\r' || *q == '\n') { |
| 54 | | *q = 0; |
| 55 | | break; |
| 56 | | } |
| 57 | | |
| 58 | | if(p[0] != ' ' && p[0] != '\t') { |
| 59 | | opcodes.resize(opcodes.size()+1); |
| 60 | | opcodes.back().name = p; |
| 61 | | } else |
| 62 | | opcodes.back().instructions.push_back(p); |
| 63 | | } |
| 64 | | fclose(f); |
| 65 | | } |
| 66 | | |
| 67 | | static void load_disp(const char *fname) |
| 68 | | { |
| 69 | | char buf[4096]; |
| 70 | | FILE *f; |
| 71 | | |
| 72 | | sprintf(buf, "Error opening %s for reading\n", fname); |
| 73 | | f = fopen(fname, "r"); |
| 74 | | if(!f) { |
| 75 | | perror(buf); |
| 76 | | exit(1); |
| 77 | | } |
| 78 | | |
| 79 | | int state = 0; |
| 80 | | |
| 81 | | while(fgets(buf, sizeof(buf), f)) { |
| 82 | | char *p = buf; |
| 83 | | if(p[0] == '#' || p[0] == '\r' || p[0] == '\n' || p[0] == 0) |
| 84 | | continue; |
| 85 | | |
| 86 | | while(state < STATES) { |
| 87 | | while(*p && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t')) |
| 88 | | p++; |
| 89 | | if(!*p) |
| 90 | | break; |
| 91 | | |
| 92 | | char *q = p; |
| 93 | | while(*p != '\n' && *p != '\r' && *p != ' ' && *p != '\t') |
| 94 | | p++; |
| 95 | | table.opcodes[state++] = string(q, p); |
| 96 | | } |
| 97 | | } |
| 98 | | fclose(f); |
| 99 | | } |
| 100 | | |
| 101 | | enum { NONE, EAT_ALL, MEMORY }; |
| 102 | | |
| 103 | | static int identify_line_type(string inst) |
| 104 | | { |
| 105 | | if(inst.find("eat-all-cycles") != string::npos) |
| 106 | | return EAT_ALL; |
| 107 | | if(inst.find("read") != string::npos || |
| 108 | | inst.find("write") != string::npos || |
| 109 | | inst.find("prefetch(") != string::npos || |
| 110 | | inst.find("prefetch_noirq(") != string::npos) |
| 111 | | return MEMORY; |
| 112 | | return NONE; |
| 113 | | } |
| 114 | | |
| 115 | | static void save_opcodes(FILE *f) |
| 116 | | { |
| 117 | | for(unsigned int i=0; i != opcodes.size(); i++) { |
| 118 | | int substate; |
| 119 | | opcode &o = opcodes[i]; |
| 120 | | |
| 121 | | fprintf(f, "void %s::%s_full()\n", device_name.c_str(), o.name.c_str()); |
| 122 | | fprintf(f, "{\n"); |
| 123 | | substate = 1; |
| 124 | | for(unsigned int j=0; j != o.instructions.size(); j++) { |
| 125 | | string inst = o.instructions[j]; |
| 126 | | int type = identify_line_type(inst); |
| 127 | | if(type == EAT_ALL) { |
| 128 | | fprintf(f, "\ticount=0; inst_substate = %d; return;", substate); |
| 129 | | substate++; |
| 130 | | } else { |
| 131 | | if(type == MEMORY) |
| 132 | | fprintf(f, "\tif(icount == 0) { inst_substate = %d; return; }\n", substate); |
| 133 | | fprintf(f, "%s\n", inst.c_str()); |
| 134 | | if(type == MEMORY) { |
| 135 | | fprintf(f, "\ticount--;\n"); |
| 136 | | substate++; |
| 137 | | } |
| 138 | | } |
| 139 | | } |
| 140 | | fprintf(f, "}\n"); |
| 141 | | |
| 142 | | fprintf(f, "void %s::%s_partial()\n", device_name.c_str(), o.name.c_str()); |
| 143 | | fprintf(f, "{\n"); |
| 144 | | fprintf(f, "switch(inst_substate) {\n"); |
| 145 | | fprintf(f, "case 0:\n"); |
| 146 | | substate = 1; |
| 147 | | for(unsigned int j=0; j != o.instructions.size(); j++) { |
| 148 | | string inst = o.instructions[j]; |
| 149 | | int type = identify_line_type(inst); |
| 150 | | if(type == EAT_ALL) { |
| 151 | | fprintf(f, "\ticount=0; inst_substate = %d; return;", substate); |
| 152 | | fprintf(f, "case %d:;\n", substate); |
| 153 | | substate++; |
| 154 | | } else { |
| 155 | | if(type == MEMORY) { |
| 156 | | fprintf(f, "\tif(icount == 0) { inst_substate = %d; return; }\n", substate); |
| 157 | | fprintf(f, "case %d:\n", substate); |
| 158 | | } |
| 159 | | fprintf(f, "%s\n", inst.c_str()); |
| 160 | | if(type == MEMORY) { |
| 161 | | fprintf(f, "\ticount--;\n"); |
| 162 | | substate++; |
| 163 | | } |
| 164 | | } |
| 165 | | } |
| 166 | | fprintf(f, "}\n"); |
| 167 | | fprintf(f, "\tinst_substate = 0;\n"); |
| 168 | | fprintf(f, "}\n"); |
| 169 | | fprintf(f, "\n"); |
| 170 | | } |
| 171 | | fprintf(f, "\n"); |
| 172 | | } |
| 173 | | |
| 174 | | static void save_tables(FILE *f) |
| 175 | | { |
| 176 | | fprintf(f, "void %s::do_exec_full()\n", device_name.c_str()); |
| 177 | | fprintf(f, "{\n"); |
| 178 | | fprintf(f, "\tswitch(inst_state) {\n"); |
| 179 | | for(int j=0; j<STATES; j++) { |
| 180 | | if(table.opcodes[j] != ".") { |
| 181 | | if(j < 0x100) |
| 182 | | fprintf(f, "\tcase 0x%02x: %s_full(); break;\n", j, table.opcodes[j].c_str()); |
| 183 | | else |
| 184 | | fprintf(f, "\tcase %s: %s_full(); break;\n", snames[j-0x100], table.opcodes[j].c_str()); |
| 185 | | } |
| 186 | | } |
| 187 | | fprintf(f, "\t}\n"); |
| 188 | | fprintf(f, "}\n"); |
| 189 | | fprintf(f, "void %s::do_exec_partial()\n", device_name.c_str()); |
| 190 | | fprintf(f, "{\n"); |
| 191 | | fprintf(f, "\tswitch(inst_state) {\n"); |
| 192 | | for(int j=0; j<STATES; j++) { |
| 193 | | if(table.opcodes[j] != ".") { |
| 194 | | if(j < 0x100) |
| 195 | | fprintf(f, "\tcase 0x%02x: %s_partial(); break;\n", j, table.opcodes[j].c_str()); |
| 196 | | else |
| 197 | | fprintf(f, "\tcase %s: %s_partial(); break;\n", snames[j-0x100], table.opcodes[j].c_str()); |
| 198 | | } |
| 199 | | } |
| 200 | | fprintf(f, "\t}\n"); |
| 201 | | fprintf(f, "}\n"); |
| 202 | | fprintf(f, "const %s::disasm_entry %s::disasm_entries[0x100] = {\n", device_name.c_str(), device_name.c_str()); |
| 203 | | for(int j=0; j<0x100; j++) |
| 204 | | if(table.opcodes[j] != ".") { |
| 205 | | string opcode = table.opcodes[j]; |
| 206 | | string opc, fullopc, mode; |
| 207 | | string::iterator k, ke; |
| 208 | | for(k = opcode.begin(); k != opcode.end() && *k != '_'; k++); |
| 209 | | for(ke = opcode.end(); ke != opcode.begin() && ke[-1] != '_'; ke--); |
| 210 | | assert(k != opcode.end()); |
| 211 | | opc = string(opcode.begin(), k); |
| 212 | | fullopc = string(opcode.begin(), ke-1); |
| 213 | | mode = string(ke, opcode.end()); |
| 214 | | |
| 215 | | bool step_over = opc == "jsr" || opc == "bsr"; |
| 216 | | bool step_out = opc == "rts" || opc == "rti" || opc == "rtn"; |
| 217 | | fprintf(f, "\t{ \"%s\", DASM_%s, %s },\n", |
| 218 | | opc.c_str(), mode.c_str(), step_over ? "DASMFLAG_STEP_OVER" : step_out ? "DASMFLAG_STEP_OUT" : "0"); |
| 219 | | } else |
| 220 | | fprintf(f, "\t{ \"???\", DASM_imp, 0, false },\n"); |
| 221 | | fprintf(f, "};\n"); |
| 222 | | } |
| 223 | | |
| 224 | | static void save(const char *fname) |
| 225 | | { |
| 226 | | char buf[4096]; |
| 227 | | FILE *f; |
| 228 | | |
| 229 | | sprintf(buf, "Error opening %s for writing\n", fname); |
| 230 | | f = fopen(fname, "w"); |
| 231 | | if(!f) { |
| 232 | | perror(buf); |
| 233 | | exit(1); |
| 234 | | } |
| 235 | | |
| 236 | | save_opcodes(f); |
| 237 | | save_tables(f); |
| 238 | | |
| 239 | | fclose(f); |
| 240 | | } |
| 241 | | |
| 242 | | int main(int argc, char *argv[]) |
| 243 | | { |
| 244 | | if(argc != 5) { |
| 245 | | fprintf(stderr, "Usage:\n%s device_name {opc.lst|-} disp.lst device.inc\n", argv[0]); |
| 246 | | exit(1); |
| 247 | | } |
| 248 | | |
| 249 | | device_name = argv[1]; |
| 250 | | if(strcmp(argv[2], "-")) |
| 251 | | load_opcodes(argv[2]); |
| 252 | | load_disp(argv[3]); |
| 253 | | save(argv[4]); |
| 254 | | |
| 255 | | |
| 256 | | return 0; |
| 257 | | } |
trunk/src/emu/cpu/m6502/m6502make.py
| r19366 | r19367 | |
| 1 | #!/usr/bin/python |
| 2 | |
| 3 | USAGE = """ |
| 4 | Usage: |
| 5 | %s device_name {opc.lst|-} disp.lst device.inc |
| 6 | """ |
| 7 | import sys |
| 8 | import logging |
| 9 | |
| 10 | MAX_STATES = 0x101 |
| 11 | |
| 12 | def load_opcodes(fname): |
| 13 | """Load opcodes from .lst file""" |
| 14 | opcodes = [] |
| 15 | logging.info("load_opcodes: %s", fname) |
| 16 | try: |
| 17 | f = open(fname, "r") |
| 18 | except Exception, err: |
| 19 | logging.error("cannot read opcodes file %s [%s]", fname, err) |
| 20 | sys.exit(1) |
| 21 | |
| 22 | for line in f: |
| 23 | if line.startswith("#"): continue |
| 24 | line = line.rstrip() |
| 25 | if not line: continue |
| 26 | if line.startswith(" ") or line.startswith("\t"): |
| 27 | # append instruction to last opcode |
| 28 | opcodes[-1][1].append(line) |
| 29 | else: |
| 30 | # add new opcode |
| 31 | opcodes.append((line, [])) |
| 32 | return opcodes |
| 33 | |
| 34 | |
| 35 | def load_disp(fname): |
| 36 | logging.info("load_disp: %s", fname) |
| 37 | states = [] |
| 38 | try: |
| 39 | f = open(fname, "r") |
| 40 | except Exception, err: |
| 41 | logging.error("cannot read display file %s [%s]", fname, err) |
| 42 | sys.exit(1) |
| 43 | for line in f: |
| 44 | if line.startswith("#"): continue |
| 45 | line = line.strip() |
| 46 | if not line: continue |
| 47 | tokens = line.split() |
| 48 | states += tokens |
| 49 | return states |
| 50 | |
| 51 | def emit(f, text): |
| 52 | """write string to file""" |
| 53 | print >>f, text, |
| 54 | |
| 55 | FULL_PROLOG="""\ |
| 56 | void %(device)s::%(opcode)s_full() |
| 57 | { |
| 58 | """ |
| 59 | |
| 60 | FULL_EPILOG="""\ |
| 61 | } |
| 62 | """ |
| 63 | |
| 64 | FULL_EAT_ALL="""\ |
| 65 | \ticount=0; inst_substate = %(substate)s; return; |
| 66 | """ |
| 67 | |
| 68 | FULL_MEMORY="""\ |
| 69 | \tif(icount == 0) { inst_substate = %(substate)s; return; } |
| 70 | %(ins)s |
| 71 | \ticount--; |
| 72 | """ |
| 73 | |
| 74 | FULL_NONE="""\ |
| 75 | %(ins)s |
| 76 | """ |
| 77 | |
| 78 | PARTIAL_PROLOG="""\ |
| 79 | void %(device)s::%(opcode)s_partial() |
| 80 | { |
| 81 | switch(inst_substate) { |
| 82 | case 0: |
| 83 | """ |
| 84 | |
| 85 | PARTIAL_EPILOG="""\ |
| 86 | } |
| 87 | \tinst_substate = 0; |
| 88 | } |
| 89 | |
| 90 | """ |
| 91 | |
| 92 | PARTIAL_EAT_ALL="""\ |
| 93 | \ticount=0; inst_substate = %(substate)s; return; |
| 94 | case %(substate)s:; |
| 95 | """ |
| 96 | |
| 97 | PARTIAL_MEMORY="""\ |
| 98 | \tif(icount == 0) { inst_substate = %(substate)s; return; } |
| 99 | case %(substate)s: |
| 100 | %(ins)s |
| 101 | \ticount--; |
| 102 | """ |
| 103 | |
| 104 | PARTIAL_NONE="""\ |
| 105 | %(ins)s |
| 106 | """ |
| 107 | def identify_line_type(ins): |
| 108 | if "eat-all-cycles" in ins: return "EAT" |
| 109 | for s in ["read", "write", "prefetch(", "prefetch_noirq("]: |
| 110 | if s in ins: |
| 111 | return "MEMORY" |
| 112 | return "NONE" |
| 113 | |
| 114 | |
| 115 | def save_opcodes(f, device, opcodes): |
| 116 | for name, instructions in opcodes: |
| 117 | d = { "device": device, |
| 118 | "opcode": name, |
| 119 | } |
| 120 | |
| 121 | emit(f, FULL_PROLOG % d) |
| 122 | substate = 1 |
| 123 | for ins in instructions: |
| 124 | d["substate"] = str(substate) |
| 125 | d["ins"] = ins |
| 126 | line_type = identify_line_type(ins) |
| 127 | if line_type == "EAT": |
| 128 | emit(f, FULL_EAT_ALL % d) |
| 129 | substate += 1 |
| 130 | elif line_type == "MEMORY": |
| 131 | emit(f, FULL_MEMORY % d) |
| 132 | substate += 1 |
| 133 | else: |
| 134 | emit(f, FULL_NONE %d) |
| 135 | emit(f, FULL_EPILOG % d) |
| 136 | |
| 137 | emit(f, PARTIAL_PROLOG % d) |
| 138 | substate = 1 |
| 139 | for ins in instructions: |
| 140 | d["substate"] = str(substate) |
| 141 | d["ins"] = ins |
| 142 | line_type = identify_line_type(ins) |
| 143 | if line_type == "EAT": |
| 144 | emit(f, PARTIAL_EAT_ALL % d) |
| 145 | substate += 1 |
| 146 | elif line_type == "MEMORY": |
| 147 | emit(f, PARTIAL_MEMORY % d) |
| 148 | substate += 1 |
| 149 | else: |
| 150 | emit(f, PARTIAL_NONE %d) |
| 151 | emit(f, PARTIAL_EPILOG % d) |
| 152 | |
| 153 | |
| 154 | DO_EXEC_FULL_PROLOG="""\ |
| 155 | void %(device)s::do_exec_full() |
| 156 | { |
| 157 | \tswitch(inst_state) { |
| 158 | """ |
| 159 | |
| 160 | DO_EXEC_FULL_EPILOG="""\ |
| 161 | \t} |
| 162 | } |
| 163 | """ |
| 164 | |
| 165 | DO_EXEC_PARTIAL_PROLOG="""\ |
| 166 | void %(device)s::do_exec_partial() |
| 167 | { |
| 168 | \tswitch(inst_state) { |
| 169 | """ |
| 170 | |
| 171 | DO_EXEC_PARTIAL_EPILOG="""\ |
| 172 | \t} |
| 173 | } |
| 174 | """ |
| 175 | |
| 176 | DISASM_PROLOG="""\ |
| 177 | const %(device)s::disasm_entry %(device)s::disasm_entries[0x100] = { |
| 178 | """ |
| 179 | |
| 180 | DISASM_EPILOG="""\ |
| 181 | }; |
| 182 | """ |
| 183 | |
| 184 | def save_tables(f, device, states): |
| 185 | d = { "device": device, |
| 186 | } |
| 187 | |
| 188 | assert len(states) == MAX_STATES |
| 189 | |
| 190 | emit(f, DO_EXEC_FULL_PROLOG % d) |
| 191 | for n, state in enumerate(states): |
| 192 | if state == ".": continue |
| 193 | if n < MAX_STATES - 1: |
| 194 | emit(f, "\tcase 0x%02x: %s_full(); break;\n" % (n, state)) |
| 195 | else: |
| 196 | emit(f, "\tcase %s: %s_full(); break;\n" % ("STATE_RESET", state)) |
| 197 | emit(f, DO_EXEC_FULL_EPILOG % d) |
| 198 | |
| 199 | emit(f, DO_EXEC_PARTIAL_PROLOG % d) |
| 200 | for n, state in enumerate(states): |
| 201 | if state == ".": continue |
| 202 | if n < MAX_STATES - 1: |
| 203 | emit(f, "\tcase 0x%02x: %s_partial(); break;\n" % (n, state)) |
| 204 | else: |
| 205 | emit(f, "\tcase %s: %s_partial(); break;\n" % ("STATE_RESET", state)) |
| 206 | emit(f, DO_EXEC_PARTIAL_EPILOG % d) |
| 207 | |
| 208 | emit(f, DISASM_PROLOG % d) |
| 209 | for n, state in enumerate(states): |
| 210 | if state == ".": continue |
| 211 | if n == MAX_STATES - 1: break |
| 212 | tokens = state.split("_") |
| 213 | opc = tokens[0] |
| 214 | mode = tokens[-1] |
| 215 | extra = "0" |
| 216 | if opc in ["jsr", "bsr"]: |
| 217 | extra = "DASMFLAG_STEP_OVER" |
| 218 | elif opc in ["rts", "rti", "rtn"]: |
| 219 | extra = "DASMFLAG_STEP_OUT" |
| 220 | emit(f, '\t{ "%s", DASM_%s, %s },\n' % (opc, mode, extra)) |
| 221 | emit(f, DISASM_EPILOG % d) |
| 222 | |
| 223 | def save(fname, device, opcodes, states): |
| 224 | logging.info("saving: %s", fname) |
| 225 | try: |
| 226 | f = open(fname, "w") |
| 227 | except Exception, err: |
| 228 | logging.error("cannot write file %s [%s]", fname, err) |
| 229 | sys.exit(1) |
| 230 | save_opcodes(f,device, opcodes) |
| 231 | emit(f, "\n") |
| 232 | save_tables(f, device, states) |
| 233 | f.close() |
| 234 | |
| 235 | |
| 236 | def main(argv): |
| 237 | debug = True |
| 238 | logformat=("%(levelname)s:" |
| 239 | "%(module)s:" |
| 240 | "%(lineno)d:" |
| 241 | "%(threadName)s:" |
| 242 | "%(message)s") |
| 243 | if debug: |
| 244 | logging.basicConfig(level=logging.INFO, format=logformat) |
| 245 | else: |
| 246 | logging.basicConfig(level=logging.WARNING, format=logformat) |
| 247 | |
| 248 | |
| 249 | if len(argv) != 5: |
| 250 | print USAGE % argv[0] |
| 251 | return 1 |
| 252 | |
| 253 | device_name = argv[1] |
| 254 | |
| 255 | opcodes = [] |
| 256 | if argv[2] != "-": |
| 257 | opcodes = load_opcodes(argv[2]) |
| 258 | logging.info("found %d opcodes", len(opcodes)) |
| 259 | else: |
| 260 | logging.info("skipping opcode reading") |
| 261 | |
| 262 | |
| 263 | states = load_disp(argv[3]) |
| 264 | logging.info("loaded %s states", len(states)) |
| 265 | assert len(states) == MAX_STATES |
| 266 | |
| 267 | save(argv[4], device_name, opcodes, states) |
| 268 | |
| 269 | |
| 270 | # ====================================================================== |
| 271 | if __name__ == "__main__": |
| 272 | sys.exit(main(sys.argv)) |
| 273 | |
trunk/src/emu/cpu/tms57002/tmsmake.c
| r19366 | r19367 | |
| 1 | | #include <stdio.h> |
| 2 | | #include <stdlib.h> |
| 3 | | #include <string.h> |
| 4 | | #include <assert.h> |
| 5 | | #include <stdarg.h> |
| 6 | | #include <ctype.h> |
| 7 | | #include "osdcomm.h" |
| 8 | | |
| 9 | | enum { |
| 10 | | I_POST = 0x00000001, |
| 11 | | I_REP = 0x00000002, |
| 12 | | I_CMODE = 0x00000004, |
| 13 | | I_DMODE = 0x00000008, |
| 14 | | I_SFAI = 0x00000010, |
| 15 | | I_CRM = 0x00000020, |
| 16 | | I_DBP = 0x00000040, |
| 17 | | I_SFAO = 0x00000080, |
| 18 | | I_SFMO = 0x00000100, |
| 19 | | I_RND = 0x00000200, |
| 20 | | I_MOVM = 0x00000400, |
| 21 | | I_SFMA = 0x00000800 |
| 22 | | }; |
| 23 | | |
| 24 | | enum { |
| 25 | | T_STD, |
| 26 | | T_BRANCH, |
| 27 | | T_CBRANCH, |
| 28 | | T_IDLE, |
| 29 | | T_FLAGS |
| 30 | | }; |
| 31 | | |
| 32 | | enum { PA, PC, PD, PD24, PI, PML, PMO, PMV, PB, PWA, PWC, PWD, SFAI }; |
| 33 | | |
| 34 | | struct instr { |
| 35 | | char *name; |
| 36 | | char *dasm; |
| 37 | | char *run; |
| 38 | | int line, cycles, type, baseval, variants; |
| 39 | | unsigned int flags; |
| 40 | | }; |
| 41 | | |
| 42 | | struct pdesc { |
| 43 | | const char *opt; |
| 44 | | int pcount, id; |
| 45 | | }; |
| 46 | | |
| 47 | | struct pinf { |
| 48 | | const char *start; |
| 49 | | int size; |
| 50 | | int id; |
| 51 | | int pcount; |
| 52 | | int ppos[4]; |
| 53 | | }; |
| 54 | | |
| 55 | | static const pdesc pp_r[] = { |
| 56 | | { "a", 0, PA }, |
| 57 | | { "c", 0, PC }, |
| 58 | | { "d", 0, PD }, |
| 59 | | { "d24", 0, PD24 }, |
| 60 | | { "i", 0, PI }, |
| 61 | | { "ml", 0, PML }, |
| 62 | | { "mo", 0, PMO }, |
| 63 | | { "mv", 0, PMV }, |
| 64 | | { "wa", 1, PWA }, |
| 65 | | { "wc", 1, PWC }, |
| 66 | | { "wd", 1, PWD }, |
| 67 | | { "b", 1, PB }, |
| 68 | | { "sfai", 2, SFAI }, |
| 69 | | { 0 } |
| 70 | | }; |
| 71 | | |
| 72 | | static instr cat1[0x40], cat2[0x80], cat3[0x80]; |
| 73 | | |
| 74 | | static pinf parse_res[4096]; |
| 75 | | static int parse_count; |
| 76 | | |
| 77 | | struct vinfo { |
| 78 | | unsigned int mask; |
| 79 | | int variants; |
| 80 | | const char *name; |
| 81 | | const char *getter; |
| 82 | | }; |
| 83 | | |
| 84 | | enum { IxCMODE, IxDMODE, IxSFAI, IxCRM, IxDBP, IxSFAO, IxSFMO, IxRND, IxMOVM, IxSFMA, IxCOUNT }; |
| 85 | | |
| 86 | | static const vinfo vinf[] = { |
| 87 | | { I_CMODE, 3, "cmode", "xmode(opcode, 'c')" }, |
| 88 | | { I_DMODE, 3, "dmode", "xmode(opcode, 'd')" }, |
| 89 | | { I_SFAI, 2, "sfai", "sfai(st1)" }, |
| 90 | | { I_CRM, 4, "crm", "crm(st1)" }, |
| 91 | | { I_DBP, 2, "dbp", "dbp(st1)" }, |
| 92 | | { I_SFAO, 2, "sfao", "sfao(st1)" }, |
| 93 | | { I_SFMO, 4, "sfmo", "sfmo(st1)" }, |
| 94 | | { I_RND, 8, "rnd", "rnd(st1)" }, |
| 95 | | { I_MOVM, 2, "movm", "movm(st1)" }, |
| 96 | | { I_SFMA, 4, "sfma", "sfma(st1)" }, |
| 97 | | { 0 } |
| 98 | | }; |
| 99 | | |
| 100 | | static char *xstrdup(const char *str) |
| 101 | | { |
| 102 | | char *cpy = NULL; |
| 103 | | if (str != NULL) { |
| 104 | | cpy = (char *)malloc(strlen(str) + 1); |
| 105 | | if (cpy != NULL) |
| 106 | | strcpy(cpy, str); |
| 107 | | } |
| 108 | | return cpy; |
| 109 | | } |
| 110 | | |
| 111 | | static char *sconcat(char *dest, const char *src) |
| 112 | | { |
| 113 | | char *r; |
| 114 | | int len = strlen(src); |
| 115 | | int pos = dest ? strlen(dest) : 0; |
| 116 | | r = (char *)realloc(dest, pos+len+2); |
| 117 | | memcpy(r + pos, src, len); |
| 118 | | r[pos+len] = '\n'; |
| 119 | | r[pos+len+1] = 0; |
| 120 | | return r; |
| 121 | | } |
| 122 | | |
| 123 | | static void next(char **q) |
| 124 | | { |
| 125 | | char *p = *q; |
| 126 | | while(*p && *p != ' ') |
| 127 | | p++; |
| 128 | | while(*p == ' ') |
| 129 | | *p++ = 0; |
| 130 | | *q = p; |
| 131 | | } |
| 132 | | |
| 133 | | static void load(const char *fname) |
| 134 | | { |
| 135 | | char buf[4096]; |
| 136 | | FILE *f; |
| 137 | | instr *i = 0; |
| 138 | | int line = 0; |
| 139 | | |
| 140 | | sprintf(buf, "Error opening %s for reading\n", fname); |
| 141 | | f = fopen(fname, "r"); |
| 142 | | if(!f) { |
| 143 | | perror(buf); |
| 144 | | exit(1); |
| 145 | | } |
| 146 | | |
| 147 | | while(fgets(buf, sizeof(buf), f)) { |
| 148 | | char *p = buf; |
| 149 | | |
| 150 | | while(*p && *p != '\r' && *p != '\n') |
| 151 | | p++; |
| 152 | | *p = 0; |
| 153 | | |
| 154 | | line++; |
| 155 | | |
| 156 | | if(!buf[0]) { |
| 157 | | i = 0; |
| 158 | | continue; |
| 159 | | } |
| 160 | | if(buf[0] == ' ' || buf[0] == '\t') { |
| 161 | | if(!i) { |
| 162 | | fprintf(stderr, "%s:%d: Text line without an instruction.\n", fname, line); |
| 163 | | exit(1); |
| 164 | | } |
| 165 | | if(i->dasm) |
| 166 | | i->run = sconcat(i->run, buf); |
| 167 | | else { |
| 168 | | p = buf; |
| 169 | | while(*p == ' ' || *p == '\t') |
| 170 | | p++; |
| 171 | | i->dasm = xstrdup(p); |
| 172 | | } |
| 173 | | } else { |
| 174 | | char *name=0, *cat=0, *id=0, *cyc=0, *rep=0, *type=0; |
| 175 | | p = buf; |
| 176 | | int pid, limit; |
| 177 | | instr *bi; |
| 178 | | unsigned int flags; |
| 179 | | |
| 180 | | name = p; |
| 181 | | next(&p); |
| 182 | | cat = p; |
| 183 | | next(&p); |
| 184 | | id = p; |
| 185 | | next(&p); |
| 186 | | cyc = p; |
| 187 | | next(&p); |
| 188 | | rep = p; |
| 189 | | next(&p); |
| 190 | | type = p; |
| 191 | | next(&p); |
| 192 | | if(*p) { |
| 193 | | fprintf(stderr, "%s:%d: Extra text at end of instruction description.\n", fname, line); |
| 194 | | exit(1); |
| 195 | | } |
| 196 | | if(!rep[0]) { |
| 197 | | fprintf(stderr, "%s:%d: Missing columns in instruction description.\n", fname, line); |
| 198 | | exit(1); |
| 199 | | } |
| 200 | | |
| 201 | | flags = 0; |
| 202 | | pid = strtol(id, 0, 16); |
| 203 | | if(!strcmp(cat, "1")) { |
| 204 | | bi = cat1; |
| 205 | | limit = 0x40; |
| 206 | | } else if(!strcmp(cat, "2a")) { |
| 207 | | bi = cat2; |
| 208 | | limit = 0x80; |
| 209 | | } else if(!strcmp(cat, "2b")) { |
| 210 | | bi = cat2; |
| 211 | | limit = 0x80; |
| 212 | | flags = I_POST; |
| 213 | | } else if(!strcmp(cat, "3")) { |
| 214 | | bi = cat3; |
| 215 | | limit = 0x80; |
| 216 | | } else { |
| 217 | | fprintf(stderr, "%s:%d: Unknown category '%s'.\n", fname, line, cat); |
| 218 | | exit(1); |
| 219 | | } |
| 220 | | |
| 221 | | if(pid<0 || pid >= limit) { |
| 222 | | fprintf(stderr, "%s:%d: Index %s out of range for category %s.\n", fname, line, id, cat); |
| 223 | | exit(1); |
| 224 | | } |
| 225 | | |
| 226 | | i = bi + pid; |
| 227 | | if(i->name) { |
| 228 | | fprintf(stderr, "%s:%d: Conflict with %s instruction line %d.\n", fname, line, i->name, i->line); |
| 229 | | exit(1); |
| 230 | | } |
| 231 | | |
| 232 | | if(!strcmp(rep, "y")) |
| 233 | | flags |= I_REP; |
| 234 | | else if(strcmp(rep, "n")) { |
| 235 | | fprintf(stderr, "%s:%d: Unknown repetition mode '%s'.\n", fname, line, rep); |
| 236 | | exit(1); |
| 237 | | } |
| 238 | | |
| 239 | | i->name = xstrdup(name); |
| 240 | | i->line = line; |
| 241 | | i->cycles = strtol(cyc, 0, 10); |
| 242 | | i->flags = flags; |
| 243 | | |
| 244 | | if(type[0] == 0) |
| 245 | | i->type = T_STD; |
| 246 | | else if(!strcmp(type, "b")) |
| 247 | | i->type = T_BRANCH; |
| 248 | | else if(!strcmp(type, "cb")) |
| 249 | | i->type = T_CBRANCH; |
| 250 | | else if(!strcmp(type, "i")) |
| 251 | | i->type = T_IDLE; |
| 252 | | else if(!strcmp(type, "f")) |
| 253 | | i->type = T_FLAGS; |
| 254 | | else { |
| 255 | | fprintf(stderr, "%s:%d: Unknown type '%s'.\n", fname, line, type); |
| 256 | | exit(1); |
| 257 | | } |
| 258 | | } |
| 259 | | } |
| 260 | | fclose(f); |
| 261 | | } |
| 262 | | |
| 263 | | static void pstr(const char *s, const char *e) |
| 264 | | { |
| 265 | | parse_res[parse_count].start = s; |
| 266 | | parse_res[parse_count].size = e-s; |
| 267 | | parse_res[parse_count].id = -1; |
| 268 | | parse_res[parse_count].pcount = 0; |
| 269 | | parse_count++; |
| 270 | | } |
| 271 | | |
| 272 | | static void parse_1(const char *start, const pdesc *inf, const char **str, int emode) |
| 273 | | { |
| 274 | | const char *p = *str; |
| 275 | | const char *s = p; |
| 276 | | int depth = 0; |
| 277 | | while(*p) { |
| 278 | | char c = *p++; |
| 279 | | if(!depth && ((c == ',' && emode == ',') || (c == ')' && emode == ')'))) { |
| 280 | | if(s != p-1) |
| 281 | | pstr(s, p-1); |
| 282 | | *str = p; |
| 283 | | return; |
| 284 | | } |
| 285 | | if(c == '(') |
| 286 | | depth++; |
| 287 | | else if(c == ')') { |
| 288 | | depth--; |
| 289 | | if(depth < 0) { |
| 290 | | if(emode == ',') |
| 291 | | fprintf(stderr, "Parse error, missing parameter in '%s'.\n", start); |
| 292 | | else |
| 293 | | fprintf(stderr, "Parse error, unbalanced parenthesis in '%s'.\n", start); |
| 294 | | exit(1); |
| 295 | | } |
| 296 | | } else if(c == '%' && ((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9'))) { |
| 297 | | char buf[4096]; |
| 298 | | char *pp = buf; |
| 299 | | int i, j; |
| 300 | | int pos; |
| 301 | | |
| 302 | | if(s != p-1) |
| 303 | | pstr(s, p-1); |
| 304 | | |
| 305 | | while((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9')) |
| 306 | | *pp++ = *p++; |
| 307 | | *pp = 0; |
| 308 | | for(i=0; inf[i].opt && strcmp(buf, inf[i].opt); i++); |
| 309 | | if(!inf[i].opt) { |
| 310 | | fprintf(stderr, "Parse error, unhandled parameter %%%s\n", buf); |
| 311 | | exit(1); |
| 312 | | } |
| 313 | | |
| 314 | | pos = parse_count++; |
| 315 | | parse_res[pos].start = 0; |
| 316 | | parse_res[pos].size = 0; |
| 317 | | parse_res[pos].id = inf[i].id; |
| 318 | | parse_res[pos].pcount = inf[i].pcount; |
| 319 | | |
| 320 | | if(inf[i].pcount) { |
| 321 | | if(*p != '(') { |
| 322 | | fprintf(stderr, "Parse error, missing opening parenthesis on %%%s\n", buf); |
| 323 | | exit(1); |
| 324 | | } else |
| 325 | | p++; |
| 326 | | } |
| 327 | | |
| 328 | | *str = p; |
| 329 | | |
| 330 | | for(j=0; j != inf[i].pcount; j++) { |
| 331 | | parse_res[pos].ppos[j] = parse_count; |
| 332 | | parse_1(start, inf, str, j == inf[i].pcount-1 ? ')' : ','); |
| 333 | | } |
| 334 | | p = *str; |
| 335 | | parse_res[pos].ppos[j] = parse_count; |
| 336 | | s = p; |
| 337 | | } |
| 338 | | } |
| 339 | | if(s != p) |
| 340 | | pstr(s, p); |
| 341 | | *str = p; |
| 342 | | switch(emode) { |
| 343 | | case 0: |
| 344 | | return; |
| 345 | | case ',': |
| 346 | | fprintf(stderr, "Parse error, missing parameter at end of string in '%s'.\n", start); |
| 347 | | exit(1); |
| 348 | | case ')': |
| 349 | | fprintf(stderr, "Parse error, missing closing parenthesis at end of string in '%s'.\n", start); |
| 350 | | exit(1); |
| 351 | | } |
| 352 | | } |
| 353 | | |
| 354 | | static void parse(const char *str, const pdesc *inf) |
| 355 | | { |
| 356 | | parse_count = 0; |
| 357 | | parse_1(str, inf, &str, 0); |
| 358 | | } |
| 359 | | |
| 360 | | static void compute_cache_ids_cat(instr *il, int count, int *baseval) |
| 361 | | { |
| 362 | | int i, j; |
| 363 | | for(i=0; i != count; i++) |
| 364 | | if(il[i].run) { |
| 365 | | unsigned int flags = il[i].flags; |
| 366 | | int variants = 1; |
| 367 | | parse(il[i].run, pp_r); |
| 368 | | for(j=0; j != parse_count; j++) { |
| 369 | | switch(parse_res[j].id) { |
| 370 | | case -1: break; |
| 371 | | case PA: flags |= I_SFAO; break; |
| 372 | | case PC: flags |= I_CMODE|I_CRM; break; |
| 373 | | case PD: flags |= I_DMODE|I_DBP; break; |
| 374 | | case PI: break; |
| 375 | | case PD24: flags |= I_DMODE|I_DBP; break; |
| 376 | | case PML: flags |= I_SFMA; break; |
| 377 | | case PMO: flags |= I_SFMO|I_RND|I_MOVM; break; |
| 378 | | case PMV: flags |= I_SFMO|I_MOVM; break; |
| 379 | | case PB: break; |
| 380 | | case PWA: break; |
| 381 | | case PWC: flags |= I_CMODE; break; |
| 382 | | case PWD: flags |= I_DMODE|I_DBP; break; |
| 383 | | case SFAI: flags |= I_SFAI; break; |
| 384 | | } |
| 385 | | } |
| 386 | | il[i].flags = flags; |
| 387 | | il[i].baseval = *baseval; |
| 388 | | |
| 389 | | for(j=0; vinf[j].mask; j++) |
| 390 | | if(flags & vinf[j].mask) |
| 391 | | variants *= vinf[j].variants; |
| 392 | | il[i].variants = variants; |
| 393 | | |
| 394 | | *baseval += variants; |
| 395 | | } |
| 396 | | } |
| 397 | | |
| 398 | | |
| 399 | | static void scp(char **str, int idx) |
| 400 | | { |
| 401 | | memcpy(*str, parse_res[idx].start, parse_res[idx].size); |
| 402 | | (*str) += parse_res[idx].size; |
| 403 | | } |
| 404 | | |
| 405 | | static void scs(char **str, const char *s) |
| 406 | | { |
| 407 | | int len = strlen(s); |
| 408 | | memcpy(*str, s, len); |
| 409 | | (*str) += len; |
| 410 | | } |
| 411 | | |
| 412 | | static void save_dasm_cat(FILE *f, const char *def, instr *il, int count) |
| 413 | | { |
| 414 | | static const pdesc pp[] = { |
| 415 | | { "c", 0, PC }, |
| 416 | | { "d", 0, PD }, |
| 417 | | { "i", 0, PI }, |
| 418 | | { 0 } |
| 419 | | }; |
| 420 | | |
| 421 | | int i; |
| 422 | | fprintf(f, "#ifdef %s\n", def); |
| 423 | | for(i=0; i != count; i++) |
| 424 | | if(il[i].name) { |
| 425 | | int par[3]; |
| 426 | | int pc = 0; |
| 427 | | int j; |
| 428 | | char buf[4096], *p = buf; |
| 429 | | parse(il[i].dasm, pp); |
| 430 | | for(j=0; j<parse_count;j++) { |
| 431 | | switch(parse_res[j].id) { |
| 432 | | case -1: |
| 433 | | scp(&p, j); |
| 434 | | break; |
| 435 | | case PC: |
| 436 | | scs(&p, "%s"); |
| 437 | | par[pc++] = PC; |
| 438 | | break; |
| 439 | | case PD: |
| 440 | | scs(&p, "%s"); |
| 441 | | par[pc++] = PD; |
| 442 | | break; |
| 443 | | case PI: |
| 444 | | scs(&p, "%02x"); |
| 445 | | par[pc++] = PI; |
| 446 | | break; |
| 447 | | } |
| 448 | | } |
| 449 | | *p = 0; |
| 450 | | |
| 451 | | fprintf(f, " case 0x%02x:\n", i); |
| 452 | | fprintf(f, " sprintf(buf, \"%s\"", buf); |
| 453 | | for(j=0; j != pc; j++) |
| 454 | | switch(par[j]) { |
| 455 | | case PC: |
| 456 | | fprintf(f, ", get_memadr(opcode, 'c')"); |
| 457 | | break; |
| 458 | | case PD: |
| 459 | | fprintf(f, ", get_memadr(opcode, 'd')"); |
| 460 | | break; |
| 461 | | case PI: |
| 462 | | fprintf(f, ", opcode & 0xff"); |
| 463 | | break; |
| 464 | | } |
| 465 | | |
| 466 | | |
| 467 | | fprintf(f, ");\n"); |
| 468 | | fprintf(f, " break;\n"); |
| 469 | | fprintf(f, "\n"); |
| 470 | | } |
| 471 | | |
| 472 | | fprintf(f, "#endif\n\n"); |
| 473 | | } |
| 474 | | |
| 475 | | static void intrp_expand(char **p, int s, int e) |
| 476 | | { |
| 477 | | int i; |
| 478 | | for(i=s; i<e;) { |
| 479 | | switch(parse_res[i].id) { |
| 480 | | case -1: |
| 481 | | scp(p, i); |
| 482 | | break; |
| 483 | | |
| 484 | | case PA: |
| 485 | | scs(p, "aacc_to_output()"); |
| 486 | | break; |
| 487 | | |
| 488 | | case PC: |
| 489 | | scs(p, "opc_read_c(opcode)"); |
| 490 | | break; |
| 491 | | |
| 492 | | case PD: |
| 493 | | scs(p, "(opc_read_d(opcode) << 8)"); |
| 494 | | break; |
| 495 | | |
| 496 | | case PI: |
| 497 | | scs(p, "(opcode & 0xff)"); |
| 498 | | break; |
| 499 | | |
| 500 | | case PD24: |
| 501 | | scs(p, "opc_read_d(opcode)"); |
| 502 | | break; |
| 503 | | |
| 504 | | case PML: |
| 505 | | scs(p, "macc_to_loop()"); |
| 506 | | break; |
| 507 | | |
| 508 | | case PMO: |
| 509 | | scs(p, "macc_to_output()"); |
| 510 | | break; |
| 511 | | |
| 512 | | case PMV: |
| 513 | | scs(p, "check_macc_overflow()"); |
| 514 | | break; |
| 515 | | |
| 516 | | case PB: |
| 517 | | scs(p, "pc = "); |
| 518 | | intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]); |
| 519 | | scs(p, ";\n"); |
| 520 | | scs(p, " sti |= S_BRANCH"); |
| 521 | | break; |
| 522 | | |
| 523 | | case PWA: |
| 524 | | scs(p, "r = "); |
| 525 | | intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]); |
| 526 | | scs(p, ";\n"); |
| 527 | | scs(p, " if(r < -0x80000000 || r > 0x7fffffff)\n"); |
| 528 | | scs(p, " st1 |= ST1_AOV;\n"); |
| 529 | | scs(p, " aacc = r"); |
| 530 | | break; |
| 531 | | |
| 532 | | case PWC: |
| 533 | | scs(p, "opc_write_c(opcode, "); |
| 534 | | intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]); |
| 535 | | scs(p, ")"); |
| 536 | | break; |
| 537 | | |
| 538 | | case PWD: |
| 539 | | scs(p, "opc_write_d(opcode, "); |
| 540 | | intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]); |
| 541 | | scs(p, ")"); |
| 542 | | break; |
| 543 | | |
| 544 | | case SFAI: |
| 545 | | intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]); |
| 546 | | scs(p, " = "); |
| 547 | | intrp_expand(p, parse_res[i].ppos[1], parse_res[i].ppos[2]); |
| 548 | | scs(p, ";\n"); |
| 549 | | scs(p, " if(st1 & ST1_SFAI)\n"); |
| 550 | | scs(p, " "); |
| 551 | | intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]); |
| 552 | | scs(p, " = ((INT32)"); |
| 553 | | intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]); |
| 554 | | scs(p, ") >> 1"); |
| 555 | | break; |
| 556 | | } |
| 557 | | |
| 558 | | if(parse_res[i].id == -1) |
| 559 | | i++; |
| 560 | | else |
| 561 | | i = parse_res[i].ppos[parse_res[i].pcount]; |
| 562 | | } |
| 563 | | } |
| 564 | | |
| 565 | | static void save_intrp_cat(FILE *f, const char *def, instr *il, int count, unsigned int fmask, unsigned int fval) |
| 566 | | { |
| 567 | | int i; |
| 568 | | fprintf(f, "#ifdef %s\n", def); |
| 569 | | for(i=0; i != count; i++) |
| 570 | | if(il[i].run) { |
| 571 | | fprintf(f, "case 0x%02x: // %s\n", i, il[i].name); |
| 572 | | if((il[i].flags & fmask) == fval) { |
| 573 | | char buf[4096], *p = buf; |
| 574 | | parse(il[i].run, pp_r); |
| 575 | | intrp_expand(&p, 0, parse_count); |
| 576 | | *p = 0; |
| 577 | | |
| 578 | | fprintf(f, "%s", buf); |
| 579 | | } |
| 580 | | fprintf(f, " break;\n\n"); |
| 581 | | } |
| 582 | | |
| 583 | | fprintf(f, "#endif\n\n"); |
| 584 | | } |
| 585 | | |
| 586 | | static void save_cdec_cat(FILE *f, const char *def, instr *il, int count, unsigned int fmask, unsigned int fval) |
| 587 | | { |
| 588 | | int i; |
| 589 | | fprintf(f, "#ifdef %s\n", def); |
| 590 | | for(i=0; i != count; i++) |
| 591 | | if(il[i].run) { |
| 592 | | int m=1, j; |
| 593 | | unsigned int flags = il[i].flags; |
| 594 | | fprintf(f, "case 0x%02x: // %s\n", i, il[i].name); |
| 595 | | if((il[i].flags & fmask) == fval) { |
| 596 | | fprintf(f, " *op = %d", il[i].baseval); |
| 597 | | for(j=0; vinf[j].mask; j++) |
| 598 | | if(flags & vinf[j].mask) { |
| 599 | | if(m != 1) |
| 600 | | fprintf(f, " + %d*%s", m, vinf[j].getter); |
| 601 | | else |
| 602 | | fprintf(f, " + %s", vinf[j].getter); |
| 603 | | m *= vinf[j].variants; |
| 604 | | } |
| 605 | | fprintf(f, ";\n"); |
| 606 | | switch(il[i].type) { |
| 607 | | case T_FLAGS: |
| 608 | | fprintf(f, "%s", il[i].run); |
| 609 | | break; |
| 610 | | case T_BRANCH: |
| 611 | | fprintf(f, " cs->branch = BR_UB;\n"); |
| 612 | | break; |
| 613 | | case T_CBRANCH: |
| 614 | | fprintf(f, " cs->branch = BR_CB;\n"); |
| 615 | | break; |
| 616 | | case T_IDLE: |
| 617 | | fprintf(f, " cs->branch = BR_IDLE;\n"); |
| 618 | | break; |
| 619 | | } |
| 620 | | } |
| 621 | | fprintf(f, " break;\n\n"); |
| 622 | | } |
| 623 | | |
| 624 | | fprintf(f, "#endif\n\n"); |
| 625 | | } |
| 626 | | |
| 627 | | |
| 628 | | static void cintrp_expand(char **p, int s, int e, const int *cv) |
| 629 | | { |
| 630 | | int i; |
| 631 | | for(i=s; i<e;) { |
| 632 | | switch(parse_res[i].id) { |
| 633 | | case -1: |
| 634 | | scp(p, i); |
| 635 | | break; |
| 636 | | |
| 637 | | case PA: |
| 638 | | if(cv[IxSFAO]) |
| 639 | | scs(p, "(aacc << 7)"); |
| 640 | | else |
| 641 | | scs(p, "aacc"); |
| 642 | | break; |
| 643 | | |
| 644 | | case PC: { |
| 645 | | const char *r = NULL; |
| 646 | | if(cv[IxCMODE] == 0) |
| 647 | | r = "cmem[i->param]"; |
| 648 | | else if(cv[IxCMODE] == 1) |
| 649 | | r = "cmem[ca]"; |
| 650 | | else if(cv[IxCMODE] == 2) |
| 651 | | r = "cmem[ca++]"; |
| 652 | | else |
| 653 | | abort(); |
| 654 | | |
| 655 | | if(cv[IxCRM] == 0 || cv[IxCRM] == 3) |
| 656 | | scs(p, r); |
| 657 | | else if(cv[IxCRM] == 1) { |
| 658 | | scs(p, "("); |
| 659 | | scs(p, r); |
| 660 | | scs(p, " & 0xffff0000)"); |
| 661 | | } else if(cv[IxCRM] == 2) { |
| 662 | | scs(p, "("); |
| 663 | | scs(p, r); |
| 664 | | scs(p, " << 16)"); |
| 665 | | } else |
| 666 | | abort(); |
| 667 | | break; |
| 668 | | } |
| 669 | | |
| 670 | | case PD: |
| 671 | | if(cv[IxDMODE] == 0) |
| 672 | | if(cv[IxDBP]) |
| 673 | | scs(p, "(dmem1[(i->param + ba1) & 0x1f] << 8)"); |
| 674 | | else |
| 675 | | scs(p, "(dmem0[(i->param + ba0) & 0xff] << 8)"); |
| 676 | | else if(cv[IxDMODE] == 1) |
| 677 | | if(cv[IxDBP]) |
| 678 | | scs(p, "(dmem1[(id + ba1) & 0x1f] << 8)"); |
| 679 | | else |
| 680 | | scs(p, "(dmem0[(id + ba0) & 0xff] << 8)"); |
| 681 | | else if(cv[IxDMODE] == 2) |
| 682 | | if(cv[IxDBP]) |
| 683 | | scs(p, "(dmem1[((id++) + ba1) & 0x1f] << 8)"); |
| 684 | | else |
| 685 | | scs(p, "(dmem0[((id++) + ba0) & 0xff] << 8)"); |
| 686 | | else |
| 687 | | abort(); |
| 688 | | break; |
| 689 | | |
| 690 | | case PI: |
| 691 | | scs(p, "i->param"); |
| 692 | | break; |
| 693 | | |
| 694 | | case PD24: |
| 695 | | if(cv[IxDMODE] == 0) |
| 696 | | if(cv[IxDBP]) |
| 697 | | scs(p, "dmem1[(i->param + ba1) & 0x1f]"); |
| 698 | | else |
| 699 | | scs(p, "dmem0[(i->param + ba0) & 0xff]"); |
| 700 | | else if(cv[IxDMODE] == 1) |
| 701 | | if(cv[IxDBP]) |
| 702 | | scs(p, "dmem1[(id + ba1) & 0x1f]"); |
| 703 | | else |
| 704 | | scs(p, "dmem0[(id + ba0) & 0xff]"); |
| 705 | | else if(cv[IxDMODE] == 2) |
| 706 | | if(cv[IxDBP]) |
| 707 | | scs(p, "dmem1[((id++) + ba1) & 0x1f]"); |
| 708 | | else |
| 709 | | scs(p, "dmem0[((id++) + ba0) & 0xff]"); |
| 710 | | else |
| 711 | | abort(); |
| 712 | | break; |
| 713 | | |
| 714 | | case PML: |
| 715 | | if(cv[IxSFMA] == 0) |
| 716 | | scs(p, "macc"); |
| 717 | | else if(cv[IxSFMA] == 1) |
| 718 | | scs(p, "(macc << 2)"); |
| 719 | | else if(cv[IxSFMA] == 2) |
| 720 | | scs(p, "(macc << 4)"); |
| 721 | | else if(cv[IxSFMA] == 3) |
| 722 | | scs(p, "(macc >> 16)"); |
| 723 | | else |
| 724 | | abort(); |
| 725 | | break; |
| 726 | | |
| 727 | | case PMO: { |
| 728 | | static const long long rounding[8] = { |
| 729 | | 0, |
| 730 | | 1LL << (48-32-1), |
| 731 | | 1LL << (48-24-1), |
| 732 | | 1LL << (48-30-1), |
| 733 | | 1LL << (48-16-1), |
| 734 | | 0, 0, 0 |
| 735 | | }; |
| 736 | | static const unsigned long long rmask[8] = { |
| 737 | | ~0ULL, |
| 738 | | (~0ULL) << (48-32), |
| 739 | | (~0ULL) << (48-24), |
| 740 | | (~0ULL) << (48-30), |
| 741 | | (~0ULL) << (48-16), |
| 742 | | ~0ULL, ~0ULL, ~0ULL |
| 743 | | }; |
| 744 | | |
| 745 | | char r[256]; |
| 746 | | sprintf(r, "macc_to_output_%d%s(0x%016" I64FMT "xULL, 0x%016" I64FMT "xULL)", cv[IxSFMO], cv[IxMOVM] ? "s" : "", rounding[cv[IxRND]], rmask[cv[IxRND]]); |
| 747 | | scs(p, r); |
| 748 | | break; |
| 749 | | } |
| 750 | | |
| 751 | | case PMV: { |
| 752 | | char r[256]; |
| 753 | | sprintf(r, "check_macc_overflow_%d%s()", cv[IxSFMO], cv[IxMOVM] ? "s" : ""); |
| 754 | | scs(p, r); |
| 755 | | break; |
| 756 | | } |
| 757 | | |
| 758 | | case PB: |
| 759 | | scs(p, "pc = "); |
| 760 | | cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv); |
| 761 | | scs(p, ";\n"); |
| 762 | | scs(p, " sti |= S_BRANCH"); |
| 763 | | break; |
| 764 | | |
| 765 | | case PWA: |
| 766 | | scs(p, "r = "); |
| 767 | | cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv); |
| 768 | | scs(p, ";\n"); |
| 769 | | scs(p, " if(r < -0x80000000 || r > 0x7fffffff)\n"); |
| 770 | | scs(p, " st1 |= ST1_AOV;\n"); |
| 771 | | scs(p, " aacc = r"); |
| 772 | | break; |
| 773 | | |
| 774 | | case PWC: |
| 775 | | if(cv[IxCMODE] == 0) |
| 776 | | scs(p, "cmem[i->param] = "); |
| 777 | | else if(cv[IxCMODE] == 1) |
| 778 | | scs(p, "cmem[ca] = "); |
| 779 | | else if(cv[IxCMODE] == 2) |
| 780 | | scs(p, "cmem[ca++] = "); |
| 781 | | else |
| 782 | | abort(); |
| 783 | | |
| 784 | | cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv); |
| 785 | | break; |
| 786 | | |
| 787 | | case PWD: |
| 788 | | if(cv[IxDMODE] == 0) |
| 789 | | if(cv[IxDBP]) |
| 790 | | scs(p, "dmem1[(i->param + ba1) & 0x1f] = "); |
| 791 | | else |
| 792 | | scs(p, "dmem0[(i->param + ba0) & 0xff] = "); |
| 793 | | else if(cv[IxDMODE] == 1) |
| 794 | | if(cv[IxDBP]) |
| 795 | | scs(p, "dmem1[(id + ba1) & 0x1f] = "); |
| 796 | | else |
| 797 | | scs(p, "dmem0[(id + ba0) & 0xff] = "); |
| 798 | | else if(cv[IxDMODE] == 2) |
| 799 | | if(cv[IxDBP]) |
| 800 | | scs(p, "dmem1[((id++) + ba1) & 0x1f] = "); |
| 801 | | else |
| 802 | | scs(p, "dmem0[((id++) + ba0) & 0xff] = "); |
| 803 | | else |
| 804 | | abort(); |
| 805 | | |
| 806 | | cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv); |
| 807 | | break; |
| 808 | | |
| 809 | | case SFAI: |
| 810 | | cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv); |
| 811 | | scs(p, " = "); |
| 812 | | if(cv[IxSFAI]) |
| 813 | | scs(p, "((INT32)("); |
| 814 | | cintrp_expand(p, parse_res[i].ppos[1], parse_res[i].ppos[2], cv); |
| 815 | | if(cv[IxSFAI]) |
| 816 | | scs(p, ")) >> 1"); |
| 817 | | break; |
| 818 | | } |
| 819 | | |
| 820 | | if(parse_res[i].id == -1) |
| 821 | | i++; |
| 822 | | else |
| 823 | | i = parse_res[i].ppos[parse_res[i].pcount]; |
| 824 | | } |
| 825 | | } |
| 826 | | |
| 827 | | static void save_cintrp_cat(FILE *f, instr *il, int count) |
| 828 | | { |
| 829 | | int i; |
| 830 | | for(i=0; i != count; i++) |
| 831 | | if(il[i].run) { |
| 832 | | int cv[IxCOUNT]; |
| 833 | | int j, k = 0; |
| 834 | | unsigned int flags = il[i].flags; |
| 835 | | char buf[16384]; |
| 836 | | |
| 837 | | memset(cv, 0, sizeof(cv)); |
| 838 | | parse(il[i].run, pp_r); |
| 839 | | |
| 840 | | for(j=0; j != il[i].variants; j++) { |
| 841 | | char *p = buf; |
| 842 | | fprintf(f, "case %d: // %s", il[i].baseval + j, il[i].name); |
| 843 | | for(k=0; k != IxCOUNT; k++) |
| 844 | | if(flags & vinf[k].mask) |
| 845 | | fprintf(f, " %s=%d", vinf[k].name, cv[k]); |
| 846 | | fprintf(f, "\n"); |
| 847 | | cintrp_expand(&p, 0, parse_count, cv); |
| 848 | | *p = 0; |
| 849 | | fprintf(f, "%s", buf); |
| 850 | | fprintf(f, " break;\n\n"); |
| 851 | | |
| 852 | | for(k=0; k != IxCOUNT; k++) |
| 853 | | if(flags & vinf[k].mask) { |
| 854 | | cv[k]++; |
| 855 | | if(cv[k] != vinf[k].variants) |
| 856 | | break; |
| 857 | | cv[k] = 0; |
| 858 | | } |
| 859 | | } |
| 860 | | assert(k == IxCOUNT); |
| 861 | | } |
| 862 | | } |
| 863 | | |
| 864 | | static void compute_cache_ids(void) |
| 865 | | { |
| 866 | | int baseval = 1; |
| 867 | | compute_cache_ids_cat(cat1, 0x40, &baseval); |
| 868 | | compute_cache_ids_cat(cat2, 0x80, &baseval); |
| 869 | | compute_cache_ids_cat(cat3, 0x80, &baseval); |
| 870 | | } |
| 871 | | |
| 872 | | static void save_dasm(FILE *f) |
| 873 | | { |
| 874 | | save_dasm_cat(f, "DASM1", cat1, 0x40); |
| 875 | | save_dasm_cat(f, "DASM2", cat2, 0x80); |
| 876 | | save_dasm_cat(f, "DASM3", cat3, 0x80); |
| 877 | | } |
| 878 | | |
| 879 | | void save_intrp(FILE *f) |
| 880 | | { |
| 881 | | save_intrp_cat(f, "INTRP1", cat1, 0x40, 0, 0); |
| 882 | | save_intrp_cat(f, "INTRP2A", cat2, 0x80, I_POST, 0); |
| 883 | | save_intrp_cat(f, "INTRP2B", cat2, 0x80, I_POST, I_POST); |
| 884 | | save_intrp_cat(f, "INTRP3", cat3, 0x80, 0, 0); |
| 885 | | } |
| 886 | | |
| 887 | | static void save_cdec(FILE *f) |
| 888 | | { |
| 889 | | save_cdec_cat(f, "CDEC1", cat1, 0x40, 0, 0); |
| 890 | | save_cdec_cat(f, "CDEC2A", cat2, 0x80, I_POST, 0); |
| 891 | | save_cdec_cat(f, "CDEC2B", cat2, 0x80, I_POST, I_POST); |
| 892 | | save_cdec_cat(f, "CDEC3", cat3, 0x80, 0, 0); |
| 893 | | } |
| 894 | | |
| 895 | | static void save_cintrp(FILE *f) |
| 896 | | { |
| 897 | | fprintf(f, "#ifdef CINTRP\n"); |
| 898 | | save_cintrp_cat(f, cat1, 0x40); |
| 899 | | save_cintrp_cat(f, cat2, 0x80); |
| 900 | | save_cintrp_cat(f, cat3, 0x80); |
| 901 | | fprintf(f, "#endif\n"); |
| 902 | | } |
| 903 | | |
| 904 | | static void save(const char *fname) |
| 905 | | { |
| 906 | | char buf[4096]; |
| 907 | | FILE *f; |
| 908 | | |
| 909 | | sprintf(buf, "Error opening %s for writing\n", fname); |
| 910 | | f = fopen(fname, "w"); |
| 911 | | if(!f) { |
| 912 | | perror(buf); |
| 913 | | exit(1); |
| 914 | | } |
| 915 | | |
| 916 | | compute_cache_ids(); |
| 917 | | |
| 918 | | save_dasm(f); |
| 919 | | // save_intrp(f); |
| 920 | | save_cdec(f); |
| 921 | | save_cintrp(f); |
| 922 | | |
| 923 | | fclose(f); |
| 924 | | } |
| 925 | | |
| 926 | | static void clear_cat(instr *il, int count) |
| 927 | | { |
| 928 | | int i; |
| 929 | | for(i=0; i != count; i++) { |
| 930 | | free(il[i].name); |
| 931 | | free(il[i].dasm); |
| 932 | | free(il[i].run); |
| 933 | | } |
| 934 | | } |
| 935 | | |
| 936 | | static void clear(void) |
| 937 | | { |
| 938 | | clear_cat(cat1, 0x40); |
| 939 | | clear_cat(cat2, 0x80); |
| 940 | | clear_cat(cat3, 0x80); |
| 941 | | } |
| 942 | | |
| 943 | | int main(int argc, char *argv[]) |
| 944 | | { |
| 945 | | if(argc != 3) { |
| 946 | | fprintf(stderr, "Usage:\n%s tmsinstr.lst tms57002.inc\n", argv[0]); |
| 947 | | exit(1); |
| 948 | | } |
| 949 | | |
| 950 | | memset(cat1, 0, sizeof(cat1)); |
| 951 | | memset(cat2, 0, sizeof(cat2)); |
| 952 | | memset(cat3, 0, sizeof(cat3)); |
| 953 | | |
| 954 | | load(argv[1]); |
| 955 | | save(argv[2]); |
| 956 | | clear(); |
| 957 | | |
| 958 | | return 0; |
| 959 | | } |
trunk/src/emu/cpu/tms57002/tmsmake.py
| r19366 | r19367 | |
| 1 | #!/usr/bin/python |
| 2 | |
| 3 | import sys |
| 4 | import re |
| 5 | |
| 6 | |
| 7 | DASM_ARGS = { |
| 8 | "c": ("%s", "get_memadr(opcode, 'c')"), |
| 9 | "d": ("%s", "get_memadr(opcode, 'd')"), |
| 10 | "i": ("%02x", "opcode & 0xff"), |
| 11 | } |
| 12 | |
| 13 | TYPES = { |
| 14 | "": None, |
| 15 | "d": None, |
| 16 | "b": " cs->branch = BR_UB;", |
| 17 | "cb": " cs->branch = BR_CB;", |
| 18 | "i": " cs->branch = BR_IDLE;", |
| 19 | "f": None, |
| 20 | } |
| 21 | |
| 22 | def expand_c(v): |
| 23 | fmt = ["%s", "(%s & 0xffff0000)", "(%s << 16)", "%s"][v["crm"]] |
| 24 | param = ["cmem[i->param]", "cmem[ca]", "cmem[ca++]"][v["cmode"]] |
| 25 | return fmt % param |
| 26 | |
| 27 | def expand_d(v): |
| 28 | index = ["(i->param + ", "(id + ", "((id++) + "][v["dmode"]] |
| 29 | mask = ["ba0) & 0xff] << 8)", "ba1) & 0x1f] << 8)"][v["dbp"]] |
| 30 | return "(dmem%d[" % v["dbp"] + index + mask |
| 31 | |
| 32 | def expand_d24(v): |
| 33 | index = ["(i->param + ", "(id + ", "((id++) + "][v["dmode"]] |
| 34 | mask = ["ba0) & 0xff]", "ba1) & 0x1f]"][v["dbp"]] |
| 35 | return "dmem%d[" % v["dbp"] + index + mask |
| 36 | |
| 37 | EXPAND_ML = ["macc", "(macc << 2)", "(macc << 4)", "(macc >> 16)" ] |
| 38 | |
| 39 | def expand_mv(v): |
| 40 | c = ["", "s"][v["movm"]] |
| 41 | return "check_macc_overflow_%d%s()" % (v["sfmo"], c) |
| 42 | |
| 43 | EXPAND_WC = ["cmem[i->param] =", "cmem[ca] =", "cmem[ca++] ="] |
| 44 | |
| 45 | |
| 46 | ROUNDING = [ 0, 1 << (48-32-1), 1 << (48-24-1), 1 << (48-30-1), |
| 47 | 1 << (48-16-1), 0, 0, 0] |
| 48 | |
| 49 | A = (1 << 64) - 1 |
| 50 | RMASK= [A, |
| 51 | A - (1 << (48-32)) + 1, |
| 52 | A - (1 << (48-24)) + 1, |
| 53 | A - (1 << (48-30)) + 1, |
| 54 | A - (1 << (48-16)) + 1, |
| 55 | A, |
| 56 | A, |
| 57 | A, |
| 58 | ] |
| 59 | |
| 60 | def expand_mo(v): |
| 61 | c = ["", "s"][v["movm"]] |
| 62 | return "macc_to_output_%d%s(0x%016xULL, 0x%016xULL)" % ( |
| 63 | v["sfmo"], c, ROUNDING[v["rnd"]], RMASK[v["rnd"]]) |
| 64 | |
| 65 | |
| 66 | def expand_wd1(v): |
| 67 | index = ["(i->param + ", "(id + ", "((id++) + "][v["dmode"]] |
| 68 | mask = ["ba0) & 0xff] =", "ba1) & 0x1f] ="][v["dbp"]] |
| 69 | return "dmem%d[" % v["dbp"] + index + mask |
| 70 | |
| 71 | WA2 = ( |
| 72 | " if(r < -0x80000000 || r > 0x7fffffff)\n" |
| 73 | " st1 |= ST1_AOV;\n" |
| 74 | " aacc = r;") |
| 75 | |
| 76 | |
| 77 | PDESC_EXPAND = { |
| 78 | "a": lambda v: ["aacc", "(aacc << 7)"][v["sfao"]], |
| 79 | "c": expand_c, |
| 80 | "d": expand_d, |
| 81 | "d24": expand_d24, |
| 82 | "i": lambda v: "i->param", |
| 83 | |
| 84 | "ml": lambda v: EXPAND_ML[v["sfma"]], |
| 85 | "mo": expand_mo, |
| 86 | "mv": expand_mv, |
| 87 | "wa1": lambda v: "r =", |
| 88 | "wa2": lambda v: WA2, |
| 89 | "wc1": lambda v: EXPAND_WC[v["cmode"]], |
| 90 | "wd1": expand_wd1, |
| 91 | "b1": lambda v: "pc = ", |
| 92 | "b2": lambda v: " sti |= S_BRANCH;", |
| 93 | "sfai1": lambda v: ["", "((INT32)("][v["sfai"]], |
| 94 | "sfai2": lambda v: ["", ")) >> 1"][v["sfai"]], |
| 95 | } |
| 96 | |
| 97 | PDESC = { |
| 98 | "a": (0, ["sfao"]), |
| 99 | "c": (0, ["cmode", "crm"]), |
| 100 | "d": (0, ["dmode", "dbp"]), |
| 101 | "d24": (0, ["dmode", "dbp"]), |
| 102 | "i": (0, []), |
| 103 | "ml": (0, ["sfma"]), |
| 104 | "mo": (0, ["sfmo", "rnd", "movm"]), |
| 105 | "mv": (0, ["sfmo", "movm"]), |
| 106 | "wa": (1, []), |
| 107 | "wc": (1, ["cmode"]), |
| 108 | "wd": (1, ["dmode", "dbp"]), |
| 109 | "b": (1, []), |
| 110 | "sfai": (2, ["sfai"]), |
| 111 | } |
| 112 | |
| 113 | VARIANTS = { |
| 114 | "cmode": (3, "xmode(opcode, 'c')" ), |
| 115 | "dmode": (3, "xmode(opcode, 'd')" ), |
| 116 | "sfai": (2, "sfai(st1)"), |
| 117 | "crm": (4, "crm(st1)"), |
| 118 | "dbp": (2, "dbp(st1)"), |
| 119 | "sfao": (2, "sfao(st1)"), |
| 120 | "sfmo": (4, "sfmo(st1)"), |
| 121 | "rnd": (8, "rnd(st1)"), |
| 122 | "movm": (2, "movm(st1)"), |
| 123 | "sfma": (4, "sfma(st1)"), |
| 124 | # dummy |
| 125 | "post": (1, None), |
| 126 | |
| 127 | } |
| 128 | |
| 129 | VARIANT_CANONICAL_ORDER = [ |
| 130 | "cmode", |
| 131 | "dmode", |
| 132 | "sfai", |
| 133 | "crm", |
| 134 | "dbp", |
| 135 | "sfao", |
| 136 | "sfmo", |
| 137 | "rnd", |
| 138 | "movm", |
| 139 | "sfma", |
| 140 | ] |
| 141 | |
| 142 | def EmitWithPrefix(f, out, prefix): |
| 143 | for o in out: |
| 144 | print >>f, prefix + o |
| 145 | |
| 146 | class Instruction: |
| 147 | |
| 148 | def __init__(self, line): |
| 149 | token = line.split() |
| 150 | if len(token) == 5: |
| 151 | token.append("") |
| 152 | assert len(token) == 6 |
| 153 | |
| 154 | self._name = token[0] |
| 155 | self._cat = token[1] |
| 156 | self._id = int(token[2], 16) |
| 157 | self._cyc = int(token[3]) |
| 158 | self._rep = token[4] |
| 159 | self._type = token[5] |
| 160 | self._flags = set() |
| 161 | if self._cat == "2b": |
| 162 | self._flags.add("post") |
| 163 | self._dasm = None |
| 164 | self._run = [] |
| 165 | self._variants = 1 |
| 166 | # sanity checks |
| 167 | assert 0 <= self._id |
| 168 | if self._cat == "1": |
| 169 | assert self._id < 0x40 |
| 170 | else: |
| 171 | assert self._id < 0x80 |
| 172 | assert self._type in TYPES |
| 173 | |
| 174 | def __str__(self): |
| 175 | return repr([self._name, self._cat, self._id, self._variants, self._flags]) |
| 176 | |
| 177 | |
| 178 | def GetDasmInfo(self): |
| 179 | lst = [] |
| 180 | def extract(match): |
| 181 | s = match.group()[1:] |
| 182 | assert s in DASM_ARGS |
| 183 | fmt, val = DASM_ARGS[s] |
| 184 | lst.append(val) |
| 185 | return fmt |
| 186 | s = re.sub("%.", extract, self._dasm) |
| 187 | return s, lst |
| 188 | |
| 189 | |
| 190 | def GetCdecSum(self): |
| 191 | lst = [] |
| 192 | n = 1 |
| 193 | for f in VARIANT_CANONICAL_ORDER: |
| 194 | if f in self._flags: |
| 195 | c, s = VARIANTS[f] |
| 196 | lst.append(" + ") |
| 197 | if n != 1: |
| 198 | lst.append("%d*" % n) |
| 199 | lst.append(s) |
| 200 | n *=c |
| 201 | return "".join(lst) |
| 202 | |
| 203 | |
| 204 | def EmitDasm(self, f, prefix): |
| 205 | opcode, args = self.GetDasmInfo() |
| 206 | args = [", " + a for a in args] |
| 207 | print >>f, "%scase 0x%02x:" % (prefix, self._id) |
| 208 | print >>f, "%s sprintf(buf, \"%s\"%s);" % (prefix, opcode, "".join(args)) |
| 209 | print >>f, "%s break;" % prefix |
| 210 | |
| 211 | |
| 212 | def EmitCdec(self, f, prefix, no, empty): |
| 213 | print >>f, "%scase 0x%02x: // %s" % (prefix, self._id, self._name) |
| 214 | if not empty: |
| 215 | print >>f, "%s *op = %s%s;" % (prefix, no, self.GetCdecSum()) |
| 216 | if self._type == "f": |
| 217 | for l in self._run: |
| 218 | print >>f, prefix + l |
| 219 | else: |
| 220 | l = TYPES[self._type] |
| 221 | if l: |
| 222 | print >>f, prefix + l |
| 223 | print >>f, "%s break;" % prefix |
| 224 | |
| 225 | |
| 226 | def ExpandCintrp(self, line, values): |
| 227 | def extract(match): |
| 228 | s = match.group()[1:] |
| 229 | assert s in PDESC_EXPAND |
| 230 | # call the right expand_XXX function |
| 231 | return PDESC_EXPAND[s](values) |
| 232 | |
| 233 | |
| 234 | return re.sub("%[a-z0-9]+", extract, line) |
| 235 | |
| 236 | |
| 237 | def PreprocessRunString(self): |
| 238 | out = [] |
| 239 | for r in self._run: |
| 240 | if "%wa(" in r: |
| 241 | assert r.endswith(");") |
| 242 | r = r[0:-2].replace("%wa(", "%wa1 ") + ";" |
| 243 | out.append(r) |
| 244 | out.append("%wa2") |
| 245 | elif "%wd(" in r: |
| 246 | assert r.endswith(");") |
| 247 | r = r[0:-2].replace("%wd(", "%wd1 ") + ";" |
| 248 | out.append(r) |
| 249 | elif "%wc(" in r: |
| 250 | assert r.endswith(");") |
| 251 | r = r[0:-2].replace("%wc(", "%wc1 ") + ";" |
| 252 | out.append(r) |
| 253 | elif "%b(" in r: |
| 254 | assert r.endswith(");") |
| 255 | r = r[0:-2].replace("%b(", "%b1") + ";" |
| 256 | out.append(r) |
| 257 | out.append("%b2") |
| 258 | elif "%sfai(" in r: |
| 259 | assert r.endswith(");") |
| 260 | r = r[0:-2].replace("%sfai(", "") |
| 261 | r = r.replace(",", " = %sfai1", 1) |
| 262 | out.append(r + "%sfai2;") |
| 263 | else: |
| 264 | out.append(r) |
| 265 | return out |
| 266 | |
| 267 | |
| 268 | def EmitCintrpRecurse(self, f, prefix, no, flags_fixed, flags_unfixed): |
| 269 | if not flags_unfixed: |
| 270 | vals = [] |
| 271 | for v in VARIANT_CANONICAL_ORDER: |
| 272 | if v in flags_fixed: |
| 273 | #print "@@@@", f |
| 274 | vals.append("%s=%d" % (v, flags_fixed[v])) |
| 275 | out = [] |
| 276 | out.append("case %d: // %s %s" % (no, self._name, " ".join(vals))) |
| 277 | for line in self.PreprocessRunString(): |
| 278 | out.append(self.ExpandCintrp(line, flags_fixed)) |
| 279 | out.append(" break;") |
| 280 | out.append("") |
| 281 | EmitWithPrefix(f, out, prefix) |
| 282 | return no + 1 |
| 283 | x = flags_unfixed.pop(-1) |
| 284 | n = VARIANTS[x][0] |
| 285 | for i in range(n): |
| 286 | flags_fixed[x] = i |
| 287 | no = self.EmitCintrpRecurse(f, prefix, no, flags_fixed, flags_unfixed) |
| 288 | flags_unfixed.append(x) |
| 289 | return no |
| 290 | |
| 291 | |
| 292 | def EmitCintrp(self, f, prefix, no): |
| 293 | if not self._run: |
| 294 | return no |
| 295 | flags = [fn for fn in VARIANT_CANONICAL_ORDER |
| 296 | if fn in self._flags] |
| 297 | return self.EmitCintrpRecurse(f, prefix, no, {}, flags) |
| 298 | |
| 299 | |
| 300 | def Finalize(self): |
| 301 | def extract(match): |
| 302 | s = match.group()[1:] |
| 303 | assert s in PDESC |
| 304 | self._flags.update(PDESC[s][1]) |
| 305 | # result does not matter |
| 306 | return "X" |
| 307 | for line in self._run: |
| 308 | # ignore result of substitution |
| 309 | re.sub("%[a-z0-9]+", extract, line) |
| 310 | for f in self._flags: |
| 311 | self._variants *= VARIANTS[f][0] |
| 312 | |
| 313 | |
| 314 | def AddInfo(self, line): |
| 315 | if self._dasm is None: |
| 316 | self._dasm = line.lstrip() |
| 317 | else: |
| 318 | self._run.append(line) |
| 319 | |
| 320 | |
| 321 | def ins_cmp_dasm(a, b): |
| 322 | if a._cat[0] != b._cat[0]: |
| 323 | return cmp(a._cat[0], b._cat[0]) |
| 324 | else: |
| 325 | return cmp(a._id, b._id) |
| 326 | |
| 327 | |
| 328 | def LoadLst(filename): |
| 329 | instructions = [] |
| 330 | ins = None |
| 331 | for n, line in enumerate(open(filename)): |
| 332 | line = line.rstrip() |
| 333 | if not line and ins: |
| 334 | # new lines separate intructions |
| 335 | ins.Finalize() |
| 336 | ins = None |
| 337 | elif line[0] in [" ", "\t"]: |
| 338 | assert ins |
| 339 | ins.AddInfo(line) |
| 340 | else: |
| 341 | ins = Instruction(line) |
| 342 | instructions.append(ins) |
| 343 | if ins: |
| 344 | ins.Finalize() |
| 345 | return instructions |
| 346 | |
| 347 | |
| 348 | def EmitDasm(f, ins_list): |
| 349 | ins_list.sort(cmp=ins_cmp_dasm) |
| 350 | last_cat = "" |
| 351 | for i in ins_list: |
| 352 | cat = i._cat[0] |
| 353 | if cat != last_cat: |
| 354 | if last_cat: |
| 355 | print >>f, "#endif" |
| 356 | print >>f |
| 357 | print >>f, "#ifdef DASM" + cat |
| 358 | last_cat = cat |
| 359 | i.EmitDasm(f, " ") |
| 360 | print >>f |
| 361 | print >>f, "#endif" |
| 362 | print >>f |
| 363 | |
| 364 | |
| 365 | def EmitCdec(f, ins_list): |
| 366 | ins_list.sort(cmp=ins_cmp_dasm) |
| 367 | no = 1 |
| 368 | last_cat = "" |
| 369 | for i in ins_list: |
| 370 | if not i._run: continue |
| 371 | cat = i._cat.upper() |
| 372 | if cat == "2B": cat = "2A" |
| 373 | if cat == "3": continue |
| 374 | |
| 375 | if cat != last_cat: |
| 376 | if last_cat: |
| 377 | print >>f, "#endif" |
| 378 | print >>f |
| 379 | print >>f, "#ifdef CDEC" + cat |
| 380 | last_cat = cat |
| 381 | |
| 382 | i.EmitCdec(f, "", no, i._cat == "2b") |
| 383 | no += i._variants |
| 384 | print >>f |
| 385 | |
| 386 | no = 1 |
| 387 | for i in ins_list: |
| 388 | if not i._run: continue |
| 389 | cat = i._cat.upper() |
| 390 | if cat == "2A": cat = "2B" |
| 391 | |
| 392 | if cat == "1": |
| 393 | no += i._variants |
| 394 | continue |
| 395 | |
| 396 | if cat != last_cat: |
| 397 | if last_cat: |
| 398 | print >>f, "#endif" |
| 399 | print >>f |
| 400 | print >>f, "#ifdef CDEC" + cat |
| 401 | last_cat = cat |
| 402 | |
| 403 | i.EmitCdec(f, "", no, i._cat == "2a") |
| 404 | no += i._variants |
| 405 | print >>f |
| 406 | print >>f, "#endif" |
| 407 | print >>f |
| 408 | |
| 409 | def EmitCintrp(f, ins_list): |
| 410 | ins_list.sort(cmp=ins_cmp_dasm) |
| 411 | print >>f, "#ifdef CINTRP" |
| 412 | no = 1 |
| 413 | for i in ins_list: |
| 414 | no = i.EmitCintrp(f, "", no) |
| 415 | print >>f, "#endif" |
| 416 | |
| 417 | |
| 418 | |
| 419 | ins_list = LoadLst(sys.argv[1]) |
| 420 | try: |
| 421 | f = open(sys.argv[2], "w") |
| 422 | except Exception, err: |
| 423 | logging.error("cannot write file %s [%s]", fname, err) |
| 424 | sys.exit(1) |
| 425 | |
| 426 | EmitDasm(f, ins_list) |
| 427 | EmitCdec(f, ins_list) |
| 428 | EmitCintrp(f, ins_list) |