Previous 199869 Revisions Next

r19367 Thursday 6th December, 2012 at 19:08:40 UTC by O. Galibert
m6502,tms57002: Snakes in an emulator [Robert Muth, O. Galibert]
[src/emu/cpu]cpu.mak
[src/emu/cpu/m6502]m6502make.c m6502make.py
[src/emu/cpu/tms57002]tmsmake.c tmsmake.py

trunk/src/emu/cpu/m6502/m6502make.c
r19366r19367
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
12using namespace std;
13
14enum { STATES = 0x101 };
15
16const char *snames[STATES-0x100] = {
17   "STATE_RESET"
18};
19
20struct opcode {
21   string name;
22   vector<string> instructions;
23};
24
25vector<opcode> opcodes;
26
27struct table_t {
28   string opcodes[STATES];
29};
30
31table_t table;
32
33string device_name;
34
35static 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
67static 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
101enum { NONE, EAT_ALL, MEMORY };
102
103static 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
115static 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
174static 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
224static 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
242int 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
r19366r19367
1#!/usr/bin/python
2
3USAGE = """
4Usage:
5%s device_name {opc.lst|-} disp.lst device.inc
6"""
7import sys
8import logging
9
10MAX_STATES = 0x101
11
12def 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
35def 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
51def emit(f, text):
52    """write string to file"""
53    print >>f, text,
54
55FULL_PROLOG="""\
56void %(device)s::%(opcode)s_full()
57{
58"""
59
60FULL_EPILOG="""\
61}
62"""
63
64FULL_EAT_ALL="""\
65\ticount=0; inst_substate = %(substate)s; return;
66"""
67
68FULL_MEMORY="""\
69\tif(icount == 0) { inst_substate = %(substate)s; return; }
70%(ins)s
71\ticount--;
72"""
73
74FULL_NONE="""\
75%(ins)s
76"""
77
78PARTIAL_PROLOG="""\
79void %(device)s::%(opcode)s_partial()
80{
81switch(inst_substate) {
82case 0:
83"""
84
85PARTIAL_EPILOG="""\
86}
87\tinst_substate = 0;
88}
89
90"""
91
92PARTIAL_EAT_ALL="""\
93\ticount=0; inst_substate = %(substate)s; return;
94case %(substate)s:;
95"""
96
97PARTIAL_MEMORY="""\
98\tif(icount == 0) { inst_substate = %(substate)s; return; }
99case %(substate)s:
100%(ins)s
101\ticount--;
102"""
103
104PARTIAL_NONE="""\
105%(ins)s
106"""
107def 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
115def 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
154DO_EXEC_FULL_PROLOG="""\
155void %(device)s::do_exec_full()
156{
157\tswitch(inst_state) {
158"""
159
160DO_EXEC_FULL_EPILOG="""\
161\t}
162}
163"""
164
165DO_EXEC_PARTIAL_PROLOG="""\
166void %(device)s::do_exec_partial()
167{
168\tswitch(inst_state) {
169"""
170
171DO_EXEC_PARTIAL_EPILOG="""\
172\t}
173}
174"""
175
176DISASM_PROLOG="""\
177const %(device)s::disasm_entry %(device)s::disasm_entries[0x100] = {
178"""
179
180DISASM_EPILOG="""\
181};
182"""
183
184def 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
223def 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
236def 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# ======================================================================
271if __name__ == "__main__":
272    sys.exit(main(sys.argv))
273
trunk/src/emu/cpu/cpu.mak
r19366r19367
10181018           $(CPUOBJ)/m6502/n2a03.o \
10191019           $(CPUOBJ)/m6502/r65c02.o
10201020DASMOBJS +=
1021M6502MAKE += $(BUILDOUT)/m6502make$(BUILD_EXE)
10221021endif
10231022
10241023$(CPUOBJ)/m6502/deco16.o:   $(CPUSRC)/m6502/deco16.c \
r19366r19367
10941093                     $(CPUSRC)/m6502/m6502.h
10951094
10961095# rule to generate the C files
1097$(CPUOBJ)/m6502/deco16.inc: $(M6502MAKE) $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst
1096$(CPUOBJ)/m6502/deco16.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst
10981097   @echo Generating DECO16 source file...
1099   $(M6502MAKE) deco16_device $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst $@
1098   $(CPUSRC)/m6502/m6502make.py deco16_device $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst $@
11001099
1101$(CPUOBJ)/m6502/m4510.inc: $(M6502MAKE) $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst
1100$(CPUOBJ)/m6502/m4510.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst
11021101   @echo Generating M4510 source file...
1103   $(M6502MAKE) m4510_device $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst $@
1102   $(CPUSRC)/m6502/m6502make.py m4510_device $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst $@
11041103
1105$(CPUOBJ)/m6502/m6502.inc: $(M6502MAKE) $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst
1104$(CPUOBJ)/m6502/m6502.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst
11061105   @echo Generating M6502 source file...
1107   $(M6502MAKE) m6502_device $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst $@
1106   $(CPUSRC)/m6502/m6502make.py m6502_device $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst $@
11081107
1109$(CPUOBJ)/m6502/m65c02.inc: $(M6502MAKE) $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst
1108$(CPUOBJ)/m6502/m65c02.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst
11101109   @echo Generating M65C02 source file...
1111   $(M6502MAKE) m65c02_device $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst $@
1110   $(CPUSRC)/m6502/m6502make.py m65c02_device $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst $@
11121111
1113$(CPUOBJ)/m6502/m65ce02.inc: $(M6502MAKE) $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst
1112$(CPUOBJ)/m6502/m65ce02.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst
11141113   @echo Generating M65CE02 source file...
1115   $(M6502MAKE) m65ce02_device $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst $@
1114   $(CPUSRC)/m6502/m6502make.py m65ce02_device $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst $@
11161115
1117$(CPUOBJ)/m6502/m6509.inc: $(M6502MAKE) $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst
1116$(CPUOBJ)/m6502/m6509.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst
11181117   @echo Generating M6509 source file...
1119   $(M6502MAKE) m6509_device $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst $@
1118   $(CPUSRC)/m6502/m6502make.py m6509_device $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst $@
11201119
1121$(CPUOBJ)/m6502/m6510.inc: $(M6502MAKE) $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst
1120$(CPUOBJ)/m6502/m6510.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst
11221121   @echo Generating M6510 source file...
1123   $(M6502MAKE) m6510_device $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst $@
1122   $(CPUSRC)/m6502/m6502make.py m6510_device $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst $@
11241123
1125$(CPUOBJ)/m6502/n2a03.inc: $(M6502MAKE) $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst
1124$(CPUOBJ)/m6502/n2a03.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst
11261125   @echo Generating N2A03 source file...
1127   $(M6502MAKE) n2a03_device $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst $@
1126   $(CPUSRC)/m6502/m6502make.py n2a03_device $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst $@
11281127
1129$(CPUOBJ)/m6502/r65c02.inc: $(M6502MAKE) $(CPUSRC)/m6502/dr65c02.lst
1128$(CPUOBJ)/m6502/r65c02.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/dr65c02.lst
11301129   @echo Generating R65C02 source file...
1131   $(M6502MAKE) r65c02_device - $(CPUSRC)/m6502/dr65c02.lst $@
1130   $(CPUSRC)/m6502/m6502make.py r65c02_device - $(CPUSRC)/m6502/dr65c02.lst $@
11321131
11331132
1134# rule to build the generator
1135ifneq ($(CROSS_BUILD),1)
1136
1137BUILD += $(M6502MAKE)
1138
1139$(M6502MAKE): $(CPUOBJ)/m6502/m6502make.o $(LIBOCORE)
1140   @echo Linking $@...
1141   $(LD) $(LDFLAGS) $(OSDBGLDFLAGS) $^ $(LIBS) -o $@
1142
1143endif
1144
1145
11461133#-------------------------------------------------
11471134# Motorola 680x
11481135#-------------------------------------------------
r19366r19367
18431830OBJDIRS += $(CPUOBJ)/tms57002
18441831CPUOBJS += $(CPUOBJ)/tms57002/tms57002.o $(CPUOBJ)/tms57002/tms57kdec.o
18451832DASMOBJS += $(CPUOBJ)/tms57002/57002dsm.o
1846ifndef TMSMAKE
1847TMSMAKE += $(BUILDOUT)/tmsmake$(BUILD_EXE)
18481833endif
1849endif
18501834
18511835$(CPUOBJ)/tms57002/tms57002.o:   $(CPUSRC)/tms57002/tms57002.c \
18521836                        $(CPUSRC)/tms57002/tms57002.h \
r19366r19367
18601844                        $(CPUOBJ)/tms57002/tms57002.inc
18611845
18621846# rule to generate the C file
1863$(CPUOBJ)/tms57002/tms57002.inc: $(TMSMAKE) $(CPUSRC)/tms57002/tmsinstr.lst
1847$(CPUOBJ)/tms57002/tms57002.inc: $(CPUSRC)/tms57002/tmsmake.py $(CPUSRC)/tms57002/tmsinstr.lst
18641848   @echo Generating TMS57002 source file...
1865   $(TMSMAKE) $(CPUSRC)/tms57002/tmsinstr.lst $@
1849   $(CPUSRC)/tms57002/tmsmake.py $(CPUSRC)/tms57002/tmsinstr.lst $@
18661850
1867# rule to build the generator
1868ifneq ($(CROSS_BUILD),1)
18691851
1870BUILD += $(TMSMAKE)
1871
1872$(TMSMAKE): $(CPUOBJ)/tms57002/tmsmake.o $(LIBOCORE)
1873   @echo Linking $@...
1874   $(LD) $(LDFLAGS) $(OSDBGLDFLAGS) $^ $(LIBS) -o $@
1875
1876endif
1877
1878
18791852#-------------------------------------------------
18801853# Toshiba TLCS-90 Series
18811854#-------------------------------------------------
trunk/src/emu/cpu/tms57002/tmsmake.c
r19366r19367
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
9enum {
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
24enum {
25  T_STD,
26  T_BRANCH,
27  T_CBRANCH,
28  T_IDLE,
29  T_FLAGS
30};
31
32enum { PA, PC, PD, PD24, PI, PML, PMO, PMV, PB, PWA, PWC, PWD, SFAI };
33
34struct instr {
35  char *name;
36  char *dasm;
37  char *run;
38  int line, cycles, type, baseval, variants;
39  unsigned int flags;
40};
41
42struct pdesc {
43  const char *opt;
44  int pcount, id;
45};
46
47struct pinf {
48  const char *start;
49  int size;
50  int id;
51  int pcount;
52  int ppos[4];
53};
54
55static 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
72static instr cat1[0x40], cat2[0x80], cat3[0x80];
73
74static pinf parse_res[4096];
75static int parse_count;
76
77struct vinfo {
78  unsigned int mask;
79  int variants;
80  const char *name;
81  const char *getter;
82};
83
84enum { IxCMODE, IxDMODE, IxSFAI, IxCRM, IxDBP, IxSFAO, IxSFMO, IxRND, IxMOVM, IxSFMA, IxCOUNT };
85
86static 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
100static 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
111static 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
123static 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
133static 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
263static 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
272static 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
354static void parse(const char *str, const pdesc *inf)
355{
356  parse_count = 0;
357  parse_1(str, inf, &str, 0);
358}
359
360static 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
399static 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
405static void scs(char **str, const char *s)
406{
407  int len = strlen(s);
408  memcpy(*str, s, len);
409  (*str) += len;
410}
411
412static 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
475static 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
565static 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
586static 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
628static 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
827static 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
864static 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
872static 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
879void 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
887static 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
895static 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
904static 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
926static 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
936static void clear(void)
937{
938  clear_cat(cat1, 0x40);
939  clear_cat(cat2, 0x80);
940  clear_cat(cat3, 0x80);
941}
942
943int 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
r19366r19367
1#!/usr/bin/python
2
3import sys
4import re
5
6
7DASM_ARGS = {
8    "c": ("%s", "get_memadr(opcode, 'c')"),
9    "d": ("%s", "get_memadr(opcode, 'd')"),
10    "i": ("%02x", "opcode & 0xff"),
11}
12
13TYPES = {
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
22def 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
27def 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
32def 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
37EXPAND_ML = ["macc", "(macc << 2)", "(macc << 4)", "(macc >> 16)" ]
38
39def expand_mv(v):
40    c = ["", "s"][v["movm"]]
41    return "check_macc_overflow_%d%s()" % (v["sfmo"], c)
42
43EXPAND_WC = ["cmem[i->param] =", "cmem[ca] =", "cmem[ca++] ="]
44
45
46ROUNDING = [ 0, 1 << (48-32-1), 1 << (48-24-1), 1 << (48-30-1),
47             1 << (48-16-1), 0, 0, 0]
48
49A = (1 << 64) - 1
50RMASK= [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
60def 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
66def 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
71WA2 = (
72"  if(r < -0x80000000 || r > 0x7fffffff)\n"
73"    st1 |= ST1_AOV;\n"
74"  aacc = r;")
75
76
77PDESC_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
97PDESC = {
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
113VARIANTS = {
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
129VARIANT_CANONICAL_ORDER = [
130    "cmode",
131    "dmode",
132    "sfai",
133    "crm",
134    "dbp",
135    "sfao",
136    "sfmo",
137    "rnd",
138    "movm",
139    "sfma",
140]
141
142def EmitWithPrefix(f, out, prefix):
143    for o in out:
144        print >>f, prefix + o
145
146class 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
321def 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
328def 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
348def 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
365def 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
409def 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
419ins_list = LoadLst(sys.argv[1])
420try:
421    f = open(sys.argv[2], "w")
422except Exception, err:
423    logging.error("cannot write file %s [%s]", fname, err)
424    sys.exit(1)
425
426EmitDasm(f, ins_list)
427EmitCdec(f, ins_list)
428EmitCintrp(f, ins_list)

Previous 199869 Revisions Next


© 1997-2024 The MAME Team